feat(auto): auto-triage TODO.md on each autonomous cycle
- Add autoTriageTodo() helper that checks root TODO.md for raw dump notes beyond the empty template before each autonomous cycle - Lazy-imports buildTodoTriageLLMCall + triageTodoDump from commands-todo.js to avoid startup overhead - Triage results written to DB backlog with clear=true + backlog=true - Best-effort: never blocks autonomous loop on triage failure - Fast-path skips when TODO.md is empty template or doesn't exist Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ca7ff554c3
commit
72c3811a7b
1 changed files with 66 additions and 0 deletions
|
|
@ -275,6 +275,63 @@ async function drainSleeptimeQueue(basePath) {
|
|||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Auto-triage root TODO.md if it contains raw dump notes.
|
||||
*
|
||||
* Purpose: check for untriaged human dump notes at the start of each autonomous
|
||||
* cycle and promote them into reviewable artifacts (eval candidates, harness
|
||||
* gaps, memory requirements, docs/tests, implementation tasks) before the agent
|
||||
* picks the next unit. This prevents raw TODO.md notes from being treated as
|
||||
* durable instructions.
|
||||
*
|
||||
* Consumer: autoLoop between-unit boundary.
|
||||
*
|
||||
* @param {string} basePath
|
||||
* @param {number} iteration
|
||||
* @param {object} deps
|
||||
* @param {object} ctx
|
||||
*/
|
||||
async function autoTriageTodo(basePath, iteration, deps, ctx) {
|
||||
const todoPath = join(basePath, "TODO.md");
|
||||
if (!existsSync(todoPath)) return;
|
||||
const raw = readFileSync(todoPath, "utf-8");
|
||||
// Fast-path: skip if TODO.md matches the empty template
|
||||
const _EMPTY_TODO = "# TODO\n\nDump anything here.\n";
|
||||
if (raw.trim() === _EMPTY_TODO.trim()) return;
|
||||
// Skip if there's no real dump content (just header + empty prompt)
|
||||
const body = raw
|
||||
.replace(/\r\n/g, "\n")
|
||||
.split("\n")
|
||||
.filter((line, idx) => {
|
||||
if (idx === 0 && line.trim().toLowerCase() === "# todo") return false;
|
||||
if (line.trim() === "Dump anything here.") return false;
|
||||
return true;
|
||||
})
|
||||
.join("\n")
|
||||
.trim();
|
||||
if (!body) return;
|
||||
// Lazy-import triage function to avoid loading the full commands-todo module
|
||||
// at startup. It pulls in sf-db, crypto, etc.
|
||||
const { buildTodoTriageLLMCall, triageTodoDump } = await import(
|
||||
"../commands-todo.js"
|
||||
);
|
||||
const llmCall = buildTodoTriageLLMCall(ctx);
|
||||
if (!llmCall) return;
|
||||
const result = await triageTodoDump(basePath, llmCall, {
|
||||
clear: true,
|
||||
backlog: true,
|
||||
});
|
||||
if (result.skipped) return;
|
||||
ctx.ui.notify(
|
||||
`TODO.md auto-triage: ${result.backlogItemsAdded} backlog items, ${result.result.eval_candidates.length} eval candidates`,
|
||||
"info",
|
||||
{
|
||||
noticeKind: NOTICE_KIND.SYSTEM_NOTICE,
|
||||
dedupe_key: `auto-triage-${iteration}`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a phase function with a timeout. Rejects with an Error whose message
|
||||
* starts with "phase-timeout:" so the blanket catch can handle it specially.
|
||||
|
|
@ -573,6 +630,15 @@ export async function autoLoop(ctx, pi, s, deps) {
|
|||
} catch {
|
||||
/* best-effort — never block autonomous loop on consolidation */
|
||||
}
|
||||
// ── Auto-triage TODO.md dump inbox ──
|
||||
// If root TODO.md contains raw dump notes beyond the empty template,
|
||||
// triage them into reviewable artifacts before picking the next unit.
|
||||
// This runs cheaply (one hash check + one LLM call only when content exists).
|
||||
try {
|
||||
await autoTriageTodo(s.basePath, iteration, deps, ctx);
|
||||
} catch {
|
||||
/* best-effort — never block autonomous loop on triage */
|
||||
}
|
||||
try {
|
||||
// ── Blanket try/catch: one bad iteration must not kill the session
|
||||
const prefs = deps.loadEffectiveSFPreferences()?.preferences;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue