mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Print final run summary in scheduler cycle and prompts
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
a7a7679223
commit
9278dadab0
4 files changed
+216
-16
No files matched your search
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
// Source of truth: numbered MUST steps 2 and 4-14 in src/prompts/scheduler-flow.md are
|
||||
// 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 path from 'node:path';
|
||||
@@ -370,6 +370,45 @@ async function writeLog({ cadence, agent, status, reason, detail, platform, meta
|
||||
return file;
|
||||
}
|
||||
|
||||
async function printRunSummary({ status, agent, promptPath, reason, detail, memoryFile, platform }) {
|
||||
let learnings = 'No learnings recorded.';
|
||||
if (memoryFile) {
|
||||
try {
|
||||
const content = await fs.readFile(memoryFile, 'utf8');
|
||||
if (content.trim()) {
|
||||
learnings = content.trim();
|
||||
if (learnings.length > 2000) {
|
||||
learnings = learnings.slice(0, 2000) + '\n... (truncated)';
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore read errors
|
||||
}
|
||||
}
|
||||
|
||||
process.stdout.write('\n================================================================================\n');
|
||||
process.stdout.write('Scheduler Run Summary\n');
|
||||
process.stdout.write('================================================================================\n');
|
||||
process.stdout.write(`Status: ${status}\n`);
|
||||
process.stdout.write(`Agent: ${agent}\n`);
|
||||
process.stdout.write(`Prompt: ${promptPath || '(none)'}\n`);
|
||||
process.stdout.write(`Platform: ${platform}\n`);
|
||||
process.stdout.write(`Reason: ${reason}\n`);
|
||||
if (detail) {
|
||||
process.stdout.write(`Detail: ${detail}\n`);
|
||||
}
|
||||
process.stdout.write('\nLearnings / Discoveries:\n');
|
||||
process.stdout.write(`${learnings}\n`);
|
||||
process.stdout.write('================================================================================\n\n');
|
||||
}
|
||||
|
||||
async function exitWithSummary(code, summaryData) {
|
||||
if (summaryData) {
|
||||
await printRunSummary(summaryData);
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { cadence, platform, model } = parseArgs(process.argv.slice(2));
|
||||
if (!VALID_CADENCES.has(cadence)) {
|
||||
@@ -426,7 +465,13 @@ async function main() {
|
||||
relay_health_history_path: preflight.payload?.historyPath || null,
|
||||
},
|
||||
});
|
||||
process.exit(allRelaysUnhealthy ? 0 : (preflight.code || 1));
|
||||
await exitWithSummary(allRelaysUnhealthy ? 0 : (preflight.code || 1), {
|
||||
status: allRelaysUnhealthy ? 'deferred' : 'failed',
|
||||
agent: 'scheduler',
|
||||
promptPath: null,
|
||||
reason: allRelaysUnhealthy ? 'All relays unhealthy preflight' : 'Lock backend unavailable preflight',
|
||||
platform,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +513,13 @@ async function main() {
|
||||
platform,
|
||||
reason: ALL_EXCLUDED_REASON,
|
||||
});
|
||||
process.exit(1);
|
||||
await exitWithSummary(1, {
|
||||
status: 'failed',
|
||||
agent: 'scheduler',
|
||||
promptPath: null,
|
||||
reason: ALL_EXCLUDED_REASON,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
const deferralForAgent = schedulerRunState.lock_deferral?.selected_agent === selectedAgent
|
||||
@@ -533,7 +584,14 @@ async function main() {
|
||||
lock_idempotency_key: idempotencyKey,
|
||||
},
|
||||
});
|
||||
process.exit(0);
|
||||
await exitWithSummary(0, {
|
||||
status: 'deferred',
|
||||
agent: selectedAgent,
|
||||
promptPath: null,
|
||||
reason: 'Lock backend deferred',
|
||||
platform,
|
||||
detail: `Lock backend failure (${backendCategory})`,
|
||||
});
|
||||
}
|
||||
|
||||
schedulerRunState.lock_deferral = null;
|
||||
@@ -562,7 +620,14 @@ async function main() {
|
||||
lock_stdout_excerpt: stdoutExcerpt || '(empty)',
|
||||
},
|
||||
});
|
||||
process.exit(2);
|
||||
await exitWithSummary(2, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath: null,
|
||||
reason: 'Lock backend error',
|
||||
platform,
|
||||
detail: `Lock backend error (${backendCategory})`,
|
||||
});
|
||||
}
|
||||
|
||||
if (lockResult.code !== 0) {
|
||||
@@ -575,7 +640,13 @@ async function main() {
|
||||
platform,
|
||||
reason: 'Failed to acquire lock',
|
||||
});
|
||||
process.exit(lockResult.code);
|
||||
await exitWithSummary(lockResult.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath: null,
|
||||
reason: 'Failed to acquire lock',
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
const promptPath = path.resolve(process.cwd(), 'src/prompts', cadence, `${selectedAgent}.md`);
|
||||
@@ -590,7 +661,14 @@ async function main() {
|
||||
detail: promptValidation.detail,
|
||||
metadata: categorizeFailureMetadata(promptValidation.category, { prompt_path: promptPath }),
|
||||
});
|
||||
process.exit(1);
|
||||
await exitWithSummary(1, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: promptValidation.reason,
|
||||
detail: promptValidation.detail,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
schedulerRunState.lock_deferral = null;
|
||||
@@ -626,7 +704,15 @@ async function main() {
|
||||
detail: schedulerConfig.memoryPolicy.retrieveCommand,
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(retrieveResult.code);
|
||||
await exitWithSummary(retrieveResult.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Memory retrieval command failed',
|
||||
detail: schedulerConfig.memoryPolicy.retrieveCommand,
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,7 +731,15 @@ async function main() {
|
||||
detail: 'Handoff callback failed.',
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(handoff.code);
|
||||
await exitWithSummary(handoff.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Prompt/handoff execution failed',
|
||||
detail: 'Handoff callback failed',
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const detail = schedulerConfig.missingHandoffCommandForMode
|
||||
@@ -660,7 +754,15 @@ async function main() {
|
||||
detail,
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(1);
|
||||
await exitWithSummary(1, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Prompt/handoff execution failed',
|
||||
detail,
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
if (schedulerConfig.memoryPolicy.storeCommand) {
|
||||
@@ -678,7 +780,15 @@ async function main() {
|
||||
detail: schedulerConfig.memoryPolicy.storeCommand,
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(storeResult.code);
|
||||
await exitWithSummary(storeResult.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Memory storage command failed',
|
||||
detail: schedulerConfig.memoryPolicy.storeCommand,
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,7 +819,15 @@ async function main() {
|
||||
detail: `Missing evidence for: ${missingSteps.join(', ')}`,
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.PROMPT_SCHEMA, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(1);
|
||||
await exitWithSummary(1, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Required memory steps not verified',
|
||||
detail: `Missing evidence for: ${missingSteps.join(', ')}`,
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
if (missingSteps.length) {
|
||||
@@ -741,7 +859,15 @@ async function main() {
|
||||
detail,
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.PROMPT_SCHEMA, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(artifactCheck.code);
|
||||
await exitWithSummary(artifactCheck.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Missing required run artifacts',
|
||||
detail,
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
for (const validation of schedulerConfig.validationCommands) {
|
||||
@@ -758,7 +884,15 @@ async function main() {
|
||||
detail: validation,
|
||||
metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { failure_class: 'prompt_validation_error' }),
|
||||
});
|
||||
process.exit(result.code);
|
||||
await exitWithSummary(result.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Validation failed',
|
||||
detail: validation,
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,11 +910,26 @@ async function main() {
|
||||
platform,
|
||||
reason: `Completion publish failed. Retry npm run lock:complete -- --agent ${selectedAgent} --cadence ${cadence} after verifying relay connectivity`,
|
||||
});
|
||||
process.exit(completeResult.code);
|
||||
await exitWithSummary(completeResult.code, {
|
||||
status: 'failed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Completion publish failed',
|
||||
detail: 'Retry npm run lock:complete after verifying relay connectivity',
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
|
||||
await writeLog({ cadence, agent: selectedAgent, status: 'completed', platform, reason: 'Scheduler cycle completed successfully' });
|
||||
process.exit(0);
|
||||
await exitWithSummary(0, {
|
||||
status: 'completed',
|
||||
agent: selectedAgent,
|
||||
promptPath,
|
||||
reason: 'Scheduler cycle completed successfully',
|
||||
memoryFile,
|
||||
platform,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,27 @@ const invariants = [
|
||||
"status: 'completed'",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'final summary print',
|
||||
promptSnippets: {
|
||||
meta: [
|
||||
'Print a final summary message to stdout',
|
||||
'Status: [Success/Failure]',
|
||||
'Learnings: [Content of the memory update file',
|
||||
],
|
||||
flow: [
|
||||
'Print a final summary message to stdout',
|
||||
'The message MUST include:',
|
||||
'**Learnings**: [Content of the memory update file',
|
||||
],
|
||||
},
|
||||
schedulerSnippets: [
|
||||
'async function printRunSummary',
|
||||
'async function exitWithSummary',
|
||||
'await printRunSummary(summaryData)',
|
||||
'Learnings / Discoveries:',
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -71,12 +71,19 @@ MUST 3: Run these commands in this order:
|
||||
- Exit 0: continue.
|
||||
- Exit non-zero: fail the run, write `_failed.md` with a clear completion-publish failure reason and retry guidance, 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.
|
||||
12) Print a final summary message to stdout.
|
||||
- Status: [Success/Failure]
|
||||
- Agent: [Agent Name]
|
||||
- Prompt: [Prompt Path]
|
||||
- Reason: [Reason string]
|
||||
- Learnings: [Content of the memory update file or "No learnings recorded"]
|
||||
|
||||
Worked example (required order):
|
||||
- `AGENT_PLATFORM=codex npm run lock:lock -- --agent content-audit-agent --cadence daily`
|
||||
- execute selected prompt work
|
||||
- `AGENT_PLATFORM=codex npm run lock:complete -- --agent content-audit-agent --cadence daily` (complete, permanent)
|
||||
- write `task-logs/daily/<timestamp>__content-audit-agent__completed.md`
|
||||
- print final summary (Status: Success, Learnings: <content>)
|
||||
|
||||
Worked example (failed validation, no completion publish):
|
||||
- `AGENT_PLATFORM=codex npm run lock:lock -- --agent content-audit-agent --cadence daily`
|
||||
@@ -84,6 +91,7 @@ MUST 3: Run these commands in this order:
|
||||
- `npm run lint` exits non-zero (or `npm test` exits non-zero)
|
||||
- write `task-logs/daily/<timestamp>__content-audit-agent__failed.md` with failure reason
|
||||
- stop without running `AGENT_PLATFORM=codex npm run lock:complete -- --agent content-audit-agent --cadence daily`
|
||||
- print final summary (Status: Failed, Reason: <reason>)
|
||||
|
||||
MUST 4: If all daily agents are excluded, stop and write `_failed.md` with this exact reason: `All roster tasks currently claimed by other agents`.
|
||||
```
|
||||
@@ -155,12 +163,19 @@ MUST 3: Run these commands in this order:
|
||||
- Exit 0: continue.
|
||||
- Exit non-zero: fail the run, write `_failed.md` with a clear completion-publish failure reason and retry guidance, 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.
|
||||
12) Print a final summary message to stdout.
|
||||
- Status: [Success/Failure]
|
||||
- Agent: [Agent Name]
|
||||
- Prompt: [Prompt Path]
|
||||
- Reason: [Reason string]
|
||||
- Learnings: [Content of the memory update file or "No learnings recorded"]
|
||||
|
||||
Worked example (required order):
|
||||
- `AGENT_PLATFORM=codex npm run lock:lock -- --agent bug-reproducer-agent --cadence weekly`
|
||||
- execute selected prompt work
|
||||
- `AGENT_PLATFORM=codex npm run lock:complete -- --agent bug-reproducer-agent --cadence weekly` (complete, permanent)
|
||||
- write `task-logs/weekly/<timestamp>__bug-reproducer-agent__completed.md`
|
||||
- print final summary (Status: Success, Learnings: <content>)
|
||||
|
||||
Worked example (failed validation, no completion publish):
|
||||
- `AGENT_PLATFORM=codex npm run lock:lock -- --agent bug-reproducer-agent --cadence weekly`
|
||||
@@ -168,6 +183,7 @@ MUST 3: Run these commands in this order:
|
||||
- `npm run lint` exits non-zero (or `npm test` exits non-zero)
|
||||
- write `task-logs/weekly/<timestamp>__bug-reproducer-agent__failed.md` with failure reason
|
||||
- stop without running `AGENT_PLATFORM=codex npm run lock:complete -- --agent bug-reproducer-agent --cadence weekly`
|
||||
- print final summary (Status: Failed, Reason: <reason>)
|
||||
|
||||
MUST 4: If all weekly agents are excluded, stop and write `_failed.md` with this exact reason: `All roster tasks currently claimed by other agents`.
|
||||
```
|
||||
@@ -232,6 +232,18 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
||||
- `scripts/agent/run-scheduler-cycle.mjs` does **not** run `git commit` or `git push`.
|
||||
- If commit/push is required for your workflow, perform it in the configured handoff agent command or a separate orchestration step.
|
||||
|
||||
16. Print a final summary message to stdout (standard output).
|
||||
|
||||
- The message MUST include:
|
||||
- **Status**: [Success/Failure/Deferred]
|
||||
- **Agent**: [Agent Name]
|
||||
- **Prompt**: [Prompt Path]
|
||||
- **Reason**: [Reason string]
|
||||
- **Learnings**: [Content of the memory update file or "No learnings recorded"]
|
||||
|
||||
- If the run failed, include the failure reason.
|
||||
- If the run succeeded, try to include the content of the memory update file (e.g., `memory-updates/<timestamp>__<agent>.md`) as the "Learnings".
|
||||
|
||||
Worked post-task example (MUST order):
|
||||
|
||||
1. `AGENT_PLATFORM=codex npm run lock:lock -- --agent content-audit-agent --cadence daily`
|
||||
@@ -239,6 +251,7 @@ Worked post-task example (MUST order):
|
||||
3. `node scripts/agent/verify-run-artifacts.mjs --since <run-start-iso> --check-failure-notes`
|
||||
4. `AGENT_PLATFORM=codex npm run lock:complete -- --agent content-audit-agent --cadence daily` (complete, permanent)
|
||||
5. Write `task-logs/daily/2026-02-14T10-00-00Z__content-audit-agent__completed.md`
|
||||
6. Print final summary (Status: Success, Learnings: <content>)
|
||||
|
||||
Worked validation-failure example (MUST behavior):
|
||||
|
||||
@@ -248,3 +261,4 @@ Worked validation-failure example (MUST behavior):
|
||||
4. `npm run lint` exits non-zero (or `npm test` exits non-zero)
|
||||
5. Write `task-logs/daily/2026-02-14T10-00-00Z__content-audit-agent__failed.md` with the failing command and reason
|
||||
6. Stop the run **without** calling `npm run lock:complete -- --agent content-audit-agent --cadence daily`
|
||||
7. Print final summary (Status: Failed, Reason: <reason>)
|
||||
Reference in new issue
Block a user