This commit is contained in:
thePR0M3TH3AN committed 2026-02-25 15:17:24 -05:00
1 parent 464fa0c56e
commit 94bb42d3df
2699 files changed
+263882 -125

No files matched your search

+28 -4
View File
@@ -41,6 +41,7 @@
// Source of truth: numbered MUST steps 2 and 4-16 in src/prompts/scheduler-flow.md are
// implemented by this script; step 3 (policy-file read) is best-effort and non-fatal.
import fs from 'node:fs/promises';
import fsSync from 'node:fs';
import path from 'node:path';
import { randomUUID } from 'node:crypto';
@@ -72,6 +73,7 @@ import {
} from './scheduler-lock.mjs';
import { detectPlatform } from '../../src/utils.mjs';
import { getTorchConfigPath } from '../../src/torch-config.mjs';
const VALID_CADENCES = new Set(['daily', 'weekly']);
const ALL_EXCLUDED_REASON = 'All roster tasks currently claimed by other agents';
@@ -328,9 +330,31 @@ function selectNextAgent({ roster, excludedSet, previousAgent, firstPrompt }) {
* @returns {Promise<Object>} Normalized scheduler config object.
*/
async function getSchedulerConfig(cadence, { isInteractive }) {
const cfg = await readJson(path.resolve(process.cwd(), 'torch-config.json'), {});
const configPath = getTorchConfigPath();
const cfg = await readJson(configPath, {});
const configDir = path.dirname(configPath);
const runtimeDir = process.cwd();
const resolveNodeCommand = (command) => {
if (typeof command !== 'string') return command;
const trimmed = command.trim();
if (!trimmed.startsWith('node ')) return trimmed;
const parts = trimmed.split(/\s+/);
if (parts.length < 2) return trimmed;
const scriptArg = parts[1];
if (!scriptArg || scriptArg.startsWith('-') || path.isAbsolute(scriptArg)) return trimmed;
const absoluteScriptPath = path.resolve(configDir, scriptArg);
if (!fsSync.existsSync(absoluteScriptPath)) return trimmed;
const rewrittenScriptPath = path.relative(runtimeDir, absoluteScriptPath).split(path.sep).join('/');
if (!rewrittenScriptPath || rewrittenScriptPath.startsWith('..')) return trimmed;
parts[1] = rewrittenScriptPath;
return parts.join(' ');
};
const scheduler = cfg.scheduler || {};
const handoffCommand = scheduler.handoffCommandByCadence?.[cadence] || null;
const defaultHandoffCommand = resolveNodeCommand('node scripts/agent/run-selected-prompt.mjs');
const handoffCommandRaw = scheduler.handoffCommandByCadence?.[cadence] || defaultHandoffCommand;
const handoffCommand = resolveNodeCommand(handoffCommandRaw);
const missingHandoffCommandForMode = !isInteractive && !handoffCommand;
const memoryPolicyRaw = scheduler.memoryPolicyByCadence?.[cadence] || {};
const mode = memoryPolicyRaw.mode === 'required' ? 'required' : 'optional';
@@ -390,10 +414,10 @@ async function getSchedulerConfig(cadence, { isInteractive }) {
memoryPolicy: {
mode,
retrieveCommand: typeof memoryPolicyRaw.retrieveCommand === 'string' && memoryPolicyRaw.retrieveCommand.trim()
? memoryPolicyRaw.retrieveCommand.trim()
? resolveNodeCommand(memoryPolicyRaw.retrieveCommand.trim())
: null,
storeCommand: typeof memoryPolicyRaw.storeCommand === 'string' && memoryPolicyRaw.storeCommand.trim()
? memoryPolicyRaw.storeCommand.trim()
? resolveNodeCommand(memoryPolicyRaw.storeCommand.trim())
: null,
retrieveSuccessMarkers: normalizeStringList(memoryPolicyRaw.retrieveSuccessMarkers, ['MEMORY_RETRIEVED']),
storeSuccessMarkers: normalizeStringList(memoryPolicyRaw.storeSuccessMarkers, ['MEMORY_STORED']),
+19 -28
View File
@@ -2,23 +2,16 @@ import os
import subprocess
import sys
def get_all_files(extensions=[".mjs", ".js"]):
def get_all_files(extensions=['.mjs', '.js']):
files = []
for root, dirs, filenames in os.walk("."):
if (
"node_modules" in root
or ".git" in root
or "artifacts" in root
or "dist" in root
):
for root, dirs, filenames in os.walk('.'):
if 'node_modules' in root or '.git' in root or 'artifacts' in root or 'dist' in root:
continue
for filename in filenames:
if any(filename.endswith(ext) for ext in extensions):
files.append(os.path.join(root, filename))
return files
def grep_file(filepath, all_files):
filename = os.path.basename(filepath)
name_no_ext = os.path.splitext(filename)[0]
@@ -38,16 +31,16 @@ def grep_file(filepath, all_files):
# Search for filename (e.g. "foo.mjs")
result_full = subprocess.run(
["git", "grep", "-F", filename, "--", "."], capture_output=True, text=True
['git', 'grep', '-F', filename, '--', '.'],
capture_output=True, text=True
)
# Search for name without extension (e.g. "foo") if it's not "index"
result_no_ext = None
if name_no_ext != "index":
result_no_ext = subprocess.run(
["git", "grep", "-F", name_no_ext, "--", "."],
capture_output=True,
text=True,
if name_no_ext != 'index':
result_no_ext = subprocess.run(
['git', 'grep', '-F', name_no_ext, '--', '.'],
capture_output=True, text=True
)
output = result_full.stdout
@@ -59,15 +52,14 @@ def grep_file(filepath, all_files):
# Filter out self-references
count = 0
for line in lines:
if line.startswith(filepath.lstrip("./")):
if line.startswith(filepath.lstrip('./')):
continue
count += 1
return count
except Exception as e:
print(f"Error grepping {filepath}: {e}")
return 1 # Assume used on error
return 1 # Assume used on error
def main():
files = get_all_files()
@@ -76,11 +68,11 @@ def main():
# Known entry points or special files to exclude from "dead" list immediately
# These might not be imported but are used by scripts or configuration
exclusions = [
"./bin/torch-lock.mjs",
"./src/lib.mjs", # Main entry
"./src/constants.mjs", # Likely used
"./build.mjs",
"./eslint.config.mjs",
'./bin/torch-lock.mjs',
'./src/lib.mjs', # Main entry
'./src/constants.mjs', # Likely used
'./build.mjs',
'./eslint.config.mjs',
]
print(f"Scanning {len(files)} files...")
@@ -90,7 +82,7 @@ def main():
continue
# Skip test files
if ".test." in f or "/test/" in f or "/tests/" in f:
if '.test.' in f or '/test/' in f or '/tests/' in f:
continue
count = grep_file(f, files)
@@ -102,10 +94,9 @@ def main():
print("No candidates found.")
else:
print(f"Found {len(candidates)} candidates.")
with open("artifacts/candidates.txt", "w") as f_out:
with open('artifacts/candidates.txt', 'w') as f_out:
for c in candidates:
f_out.write(c + "\n")
f_out.write(c + '\n')
if __name__ == "__main__":
main()
@@ -61,7 +61,7 @@ const invariants = [
],
flow: [
'Roster source: `src/prompts/roster.json`',
'Read `scheduler.firstPromptByCadence.<cadence>` from `torch-config.json` if present.',
'Read `scheduler.firstPromptByCadence.<cadence>` from repository-root `torch-config.json` if present.',
'All roster tasks currently claimed by other agents',
],
},
@@ -119,7 +119,7 @@ const invariants = [
meta: [
'If any validation command exits non-zero, do not call `lock:complete`',
'Publish completion before writing `_completed.md`',
'Only after step 10 succeeds, write final task log (`_completed.md`',
'Only after step 11 succeeds, write final task log (`_completed.md`',
],
flow: [
'step 12 MUST NOT be executed (`lock:complete` is forbidden until validation passes)',