mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Enforce scheduler memory workflow and verification
This commit is contained in:
1 parent
dbe35c7ef3
commit
d997963ea7
4 files changed
+186
-14
No files matched your search
@@ -85,6 +85,43 @@ async function readJson(filePath, fallback) {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeStringList(value, fallback = []) {
|
||||
if (!Array.isArray(value)) return fallback;
|
||||
return value.filter((item) => typeof item === 'string' && item.trim()).map((item) => item.trim());
|
||||
}
|
||||
|
||||
async function artifactExistsSince(filePath, sinceMs) {
|
||||
if (!filePath) return false;
|
||||
const resolved = path.isAbsolute(filePath)
|
||||
? filePath
|
||||
: path.resolve(process.cwd(), filePath);
|
||||
try {
|
||||
const stat = await fs.stat(resolved);
|
||||
return stat.isFile() && stat.mtimeMs >= sinceMs;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyMemoryStep({ name, markers, artifacts, outputText, sinceMs }) {
|
||||
const markerMatched = markers.some((marker) => outputText.includes(marker));
|
||||
let artifactMatched = false;
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
if (await artifactExistsSince(artifact, sinceMs)) {
|
||||
artifactMatched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
markerMatched,
|
||||
artifactMatched,
|
||||
complete: markerMatched || artifactMatched,
|
||||
};
|
||||
}
|
||||
|
||||
function parseFrontmatterAgent(markdown) {
|
||||
const lines = markdown.split(/\r?\n/);
|
||||
if (lines[0]?.trim() !== '---') return null;
|
||||
@@ -135,6 +172,9 @@ async function getSchedulerConfig(cadence, { isInteractive }) {
|
||||
const scheduler = cfg.scheduler || {};
|
||||
const handoffCommand = scheduler.handoffCommandByCadence?.[cadence] || null;
|
||||
const missingHandoffCommandForMode = !isInteractive && !handoffCommand;
|
||||
const memoryPolicyRaw = scheduler.memoryPolicyByCadence?.[cadence] || {};
|
||||
const mode = memoryPolicyRaw.mode === 'required' ? 'required' : 'optional';
|
||||
|
||||
return {
|
||||
firstPrompt: scheduler.firstPromptByCadence?.[cadence] || null,
|
||||
handoffCommand,
|
||||
@@ -142,6 +182,19 @@ async function getSchedulerConfig(cadence, { isInteractive }) {
|
||||
validationCommands: Array.isArray(scheduler.validationCommandsByCadence?.[cadence])
|
||||
? scheduler.validationCommandsByCadence[cadence].filter((cmd) => typeof cmd === 'string' && cmd.trim())
|
||||
: ['npm', 'run', 'lint'],
|
||||
memoryPolicy: {
|
||||
mode,
|
||||
retrieveCommand: typeof memoryPolicyRaw.retrieveCommand === 'string' && memoryPolicyRaw.retrieveCommand.trim()
|
||||
? memoryPolicyRaw.retrieveCommand.trim()
|
||||
: null,
|
||||
storeCommand: typeof memoryPolicyRaw.storeCommand === 'string' && memoryPolicyRaw.storeCommand.trim()
|
||||
? memoryPolicyRaw.storeCommand.trim()
|
||||
: null,
|
||||
retrieveSuccessMarkers: normalizeStringList(memoryPolicyRaw.retrieveSuccessMarkers, ['MEMORY_RETRIEVED']),
|
||||
storeSuccessMarkers: normalizeStringList(memoryPolicyRaw.storeSuccessMarkers, ['MEMORY_STORED']),
|
||||
retrieveArtifacts: normalizeStringList(memoryPolicyRaw.retrieveArtifacts),
|
||||
storeArtifacts: normalizeStringList(memoryPolicyRaw.storeArtifacts),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -257,10 +310,25 @@ async function main() {
|
||||
|
||||
const promptPath = path.resolve(process.cwd(), 'src/prompts', cadence, `${selectedAgent}.md`);
|
||||
const runArtifactSince = new Date().toISOString();
|
||||
const runStartMs = Date.parse(runArtifactSince);
|
||||
const outputChunks = [];
|
||||
|
||||
if (schedulerConfig.memoryPolicy.retrieveCommand) {
|
||||
const retrieveResult = await runCommand('bash', ['-lc', schedulerConfig.memoryPolicy.retrieveCommand], {
|
||||
env: { AGENT_PLATFORM: platform, SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
|
||||
});
|
||||
outputChunks.push(retrieveResult.stdout, retrieveResult.stderr);
|
||||
if (retrieveResult.code !== 0) {
|
||||
await writeLog({ cadence, agent: selectedAgent, status: 'failed', reason: 'Memory retrieval command failed', detail: schedulerConfig.memoryPolicy.retrieveCommand });
|
||||
process.exit(retrieveResult.code);
|
||||
}
|
||||
}
|
||||
|
||||
if (schedulerConfig.handoffCommand) {
|
||||
const handoff = await runCommand('bash', ['-lc', schedulerConfig.handoffCommand], {
|
||||
env: { AGENT_PLATFORM: platform, SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
|
||||
});
|
||||
outputChunks.push(handoff.stdout, handoff.stderr);
|
||||
if (handoff.code !== 0) {
|
||||
await writeLog({ cadence, agent: selectedAgent, status: 'failed', reason: 'Prompt/handoff execution failed', detail: 'Handoff callback failed.' });
|
||||
process.exit(handoff.code);
|
||||
@@ -273,6 +341,49 @@ async function main() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (schedulerConfig.memoryPolicy.storeCommand) {
|
||||
const storeResult = await runCommand('bash', ['-lc', schedulerConfig.memoryPolicy.storeCommand], {
|
||||
env: { AGENT_PLATFORM: platform, SCHEDULER_AGENT: selectedAgent, SCHEDULER_CADENCE: cadence, SCHEDULER_PROMPT_PATH: promptPath },
|
||||
});
|
||||
outputChunks.push(storeResult.stdout, storeResult.stderr);
|
||||
if (storeResult.code !== 0) {
|
||||
await writeLog({ cadence, agent: selectedAgent, status: 'failed', reason: 'Memory storage command failed', detail: schedulerConfig.memoryPolicy.storeCommand });
|
||||
process.exit(storeResult.code);
|
||||
}
|
||||
}
|
||||
|
||||
const memoryOutput = outputChunks.join('\n');
|
||||
const retrieveCheck = await verifyMemoryStep({
|
||||
name: 'retrieve',
|
||||
markers: schedulerConfig.memoryPolicy.retrieveSuccessMarkers,
|
||||
artifacts: schedulerConfig.memoryPolicy.retrieveArtifacts,
|
||||
outputText: memoryOutput,
|
||||
sinceMs: runStartMs,
|
||||
});
|
||||
const storeCheck = await verifyMemoryStep({
|
||||
name: 'store',
|
||||
markers: schedulerConfig.memoryPolicy.storeSuccessMarkers,
|
||||
artifacts: schedulerConfig.memoryPolicy.storeArtifacts,
|
||||
outputText: memoryOutput,
|
||||
sinceMs: runStartMs,
|
||||
});
|
||||
|
||||
const missingSteps = [retrieveCheck, storeCheck].filter((step) => !step.complete).map((step) => step.name);
|
||||
if (missingSteps.length && schedulerConfig.memoryPolicy.mode === 'required') {
|
||||
await writeLog({
|
||||
cadence,
|
||||
agent: selectedAgent,
|
||||
status: 'failed',
|
||||
reason: 'Required memory steps not verified',
|
||||
detail: `Missing evidence for: ${missingSteps.join(', ')}`,
|
||||
});
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (missingSteps.length) {
|
||||
console.warn(`[scheduler] Optional memory evidence missing for ${missingSteps.join(', ')}.`);
|
||||
}
|
||||
|
||||
const artifactCheck = await runCommand('node', [
|
||||
'scripts/agent/verify-run-artifacts.mjs',
|
||||
'--since',
|
||||
|
||||
@@ -50,15 +50,25 @@ MUST 3: Run these commands in this order:
|
||||
AGENT_PLATFORM=<platform> npm run lock:lock -- --agent <agent-name> --cadence daily
|
||||
Exit 0 = lock acquired, proceed. Exit 3 = race lost, go back to step 3.
|
||||
6) Execute selected prompt from src/prompts/daily/
|
||||
7) Run repository checks (for example: npm run lint)
|
||||
7) Run required memory workflow for this cadence:
|
||||
- Before execution, run the retrieval command if configured:
|
||||
`scheduler.memoryPolicyByCadence.daily.retrieveCommand`
|
||||
- After execution, run the storage command if configured:
|
||||
`scheduler.memoryPolicyByCadence.daily.storeCommand`
|
||||
- Emit or collect verifiable evidence for both steps using configured markers/artifacts.
|
||||
8) Validate memory evidence:
|
||||
- Confirm retrieval evidence exists (marker and/or artifact file).
|
||||
- Confirm storage evidence exists (marker and/or artifact file).
|
||||
- If `scheduler.memoryPolicyByCadence.daily.mode` is `required`, fail the run if either check is missing.
|
||||
9) Run repository checks (for example: npm run lint)
|
||||
- If any validation command exits non-zero, do not call `lock:complete`.
|
||||
- Instead, write `_failed.md` with the failing command and reason, then stop.
|
||||
8) Publish completion before writing `_completed.md` (only after step 7 passes):
|
||||
10) Publish completion before writing `_completed.md` (only after step 9 passes):
|
||||
AGENT_PLATFORM=<platform> npm run lock:complete -- --agent <agent-name> --cadence daily
|
||||
(Equivalent command allowed: torch-lock complete --agent <agent-name> --cadence daily)
|
||||
- Exit 0: continue.
|
||||
- Exit non-zero: fail the run, write `_failed.md` with a clear completion-publish failure reason and retry guidance, then stop.
|
||||
9) Only after step 8 succeeds, write final task log (`_completed.md` for success). For any failure in step 7 or step 8, write `_failed.md`, then stop.
|
||||
11) Only after step 10 succeeds, write final task log (`_completed.md` for success). For any failure in step 9 or step 10, write `_failed.md`, then stop.
|
||||
|
||||
Worked example (required order):
|
||||
- `AGENT_PLATFORM=codex npm run lock:lock -- --agent content-audit-agent --cadence daily`
|
||||
@@ -122,15 +132,25 @@ MUST 3: Run these commands in this order:
|
||||
AGENT_PLATFORM=<platform> npm run lock:lock -- --agent <agent-name> --cadence weekly
|
||||
Exit 0 = lock acquired, proceed. Exit 3 = race lost, go back to step 3.
|
||||
6) Execute selected prompt from src/prompts/weekly/
|
||||
7) Run repository checks (for example: npm run lint)
|
||||
7) Run required memory workflow for this cadence:
|
||||
- Before execution, run the retrieval command if configured:
|
||||
`scheduler.memoryPolicyByCadence.weekly.retrieveCommand`
|
||||
- After execution, run the storage command if configured:
|
||||
`scheduler.memoryPolicyByCadence.weekly.storeCommand`
|
||||
- Emit or collect verifiable evidence for both steps using configured markers/artifacts.
|
||||
8) Validate memory evidence:
|
||||
- Confirm retrieval evidence exists (marker and/or artifact file).
|
||||
- Confirm storage evidence exists (marker and/or artifact file).
|
||||
- If `scheduler.memoryPolicyByCadence.weekly.mode` is `required`, fail the run if either check is missing.
|
||||
9) Run repository checks (for example: npm run lint)
|
||||
- If any validation command exits non-zero, do not call `lock:complete`.
|
||||
- Instead, write `_failed.md` with the failing command and reason, then stop.
|
||||
8) Publish completion before writing `_completed.md` (only after step 7 passes):
|
||||
10) Publish completion before writing `_completed.md` (only after step 9 passes):
|
||||
AGENT_PLATFORM=<platform> npm run lock:complete -- --agent <agent-name> --cadence weekly
|
||||
(Equivalent command allowed: torch-lock complete --agent <agent-name> --cadence weekly)
|
||||
- Exit 0: continue.
|
||||
- Exit non-zero: fail the run, write `_failed.md` with a clear completion-publish failure reason and retry guidance, then stop.
|
||||
9) Only after step 8 succeeds, write final task log (`_completed.md` for success). For any failure in step 7 or step 8, write `_failed.md`, then stop.
|
||||
11) Only after step 10 succeeds, write final task log (`_completed.md` for success). For any failure in step 9 or step 10, write `_failed.md`, then stop.
|
||||
|
||||
Worked example (required order):
|
||||
- `AGENT_PLATFORM=codex npm run lock:lock -- --agent bug-reproducer-agent --cadence weekly`
|
||||
|
||||
@@ -30,7 +30,13 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
||||
3. **Capture reusable failures and unresolved issues**:
|
||||
- Record reusable failures in `docs/agent-handoffs/incidents/`
|
||||
- Record active unresolved reproducible items in `KNOWN_ISSUES.md`
|
||||
4. **Publish lock completion only after validation passes and before writing success logs**:
|
||||
4. **Execute memory retrieval before implementation begins**:
|
||||
- Run configured memory retrieval workflow before prompt execution (for example via `scheduler.memoryPolicyByCadence.<cadence>.retrieveCommand`)
|
||||
- Capture explicit evidence of retrieval with output markers and/or created artifact files
|
||||
5. **Store memory after implementation and before completion publish**:
|
||||
- Run configured memory storage workflow after prompt execution (for example via `scheduler.memoryPolicyByCadence.<cadence>.storeCommand`)
|
||||
- Persist summary/decision memory and emit verifiable markers/artifacts
|
||||
6. **Publish lock completion only after validation passes and before writing success logs**:
|
||||
- Run `npm run lock:complete -- --agent <agent-name> --cadence <cadence>` (or equivalent `complete`) successfully
|
||||
- If any validation command exits non-zero, do **not** call `lock:complete`; write `_failed.md` with the validation failure reason and stop
|
||||
- Only after completion publish succeeds may the agent write final `*_completed.md` log files
|
||||
@@ -125,12 +131,19 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
||||
|
||||
8. Execute `<prompt_dir>/<prompt-file>` end-to-end.
|
||||
|
||||
9. Run repository checks (for example: `npm run lint`).
|
||||
9. Confirm memory contract completion:
|
||||
|
||||
- Memory retrieval evidence must exist for this run (output marker and/or artifact file).
|
||||
- Memory storage evidence must exist for this run (output marker and/or artifact file).
|
||||
- If `scheduler.memoryPolicyByCadence.<cadence>.mode = required`, missing evidence is a hard failure.
|
||||
- If mode is `optional`, log warning context and continue.
|
||||
|
||||
10. Run repository checks (for example: `npm run lint`).
|
||||
|
||||
- If any validation command exits non-zero: **fail the run immediately**, write `_failed.md` with the failing command and reason, and stop.
|
||||
- When step 9 fails, step 10 MUST NOT be executed (`lock:complete` is forbidden until validation passes).
|
||||
- When step 10 fails, step 11 MUST NOT be executed (`lock:complete` is forbidden until validation passes).
|
||||
|
||||
10. Publish completion before writing final success log:
|
||||
11. Publish completion before writing final success log:
|
||||
|
||||
```bash
|
||||
AGENT_PLATFORM=<platform> \
|
||||
@@ -139,15 +152,15 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
||||
|
||||
(Equivalent invocation is allowed: `torch-lock complete --agent <agent-name> --cadence <cadence>`.)
|
||||
|
||||
- Exit `0`: completion published successfully; continue to step 11.
|
||||
- Exit `0`: completion published successfully; continue to step 12.
|
||||
- Exit non-zero: **fail the run**, write `_failed.md` with a clear reason that completion publish failed and retry guidance (for example: `Retry npm run lock:complete -- --agent <agent-name> --cadence <cadence> after verifying relay connectivity`), then stop.
|
||||
|
||||
11. Create final task log only after step 10 succeeds:
|
||||
12. Create final task log only after step 11 succeeds:
|
||||
|
||||
- `_completed.md` MUST be created only after completion publish succeeds.
|
||||
- `_failed.md` is required when step 9 or step 10 fails, and should include the failure reason and next retry action.
|
||||
- `_failed.md` is required when step 10 or step 11 fails, and should include the failure reason and next retry action.
|
||||
|
||||
12. Commit and push.
|
||||
13. Commit and push.
|
||||
|
||||
Worked post-task example (MUST order):
|
||||
|
||||
|
||||
@@ -17,6 +17,34 @@
|
||||
"firstPromptByCadence": {
|
||||
"daily": "scheduler-update-agent",
|
||||
"weekly": "bug-reproducer-agent"
|
||||
},
|
||||
"memoryPolicyByCadence": {
|
||||
"daily": {
|
||||
"mode": "optional",
|
||||
"retrieveCommand": null,
|
||||
"storeCommand": null,
|
||||
"retrieveSuccessMarkers": [
|
||||
"MEMORY_RETRIEVED"
|
||||
],
|
||||
"storeSuccessMarkers": [
|
||||
"MEMORY_STORED"
|
||||
],
|
||||
"retrieveArtifacts": [],
|
||||
"storeArtifacts": []
|
||||
},
|
||||
"weekly": {
|
||||
"mode": "optional",
|
||||
"retrieveCommand": null,
|
||||
"storeCommand": null,
|
||||
"retrieveSuccessMarkers": [
|
||||
"MEMORY_RETRIEVED"
|
||||
],
|
||||
"storeSuccessMarkers": [
|
||||
"MEMORY_STORED"
|
||||
],
|
||||
"retrieveArtifacts": [],
|
||||
"storeArtifacts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user