feat(web): authorize corrective smooth reader
This commit is contained in:
@@ -38,6 +38,18 @@ function currentTask() {
|
||||
return { task, parentManifest };
|
||||
}
|
||||
|
||||
function terminalTask(task) {
|
||||
try {
|
||||
const index = JSON.parse(read("tests/golden/WBV2/task-index.json"));
|
||||
const manifestPath = `tests/golden/${task}/manifest.json`;
|
||||
const manifest = fs.existsSync(abs(manifestPath)) ? JSON.parse(read(manifestPath)) : null;
|
||||
return index.activeTask === null && manifest?.task === task && manifest.status === "done" && manifest.nextTask === null;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function taskCommand(task) {
|
||||
const card = read(`docs/tasks/${task}.md`);
|
||||
const match = card.match(/- Implementation entrypoint: `([^`]+)`/u);
|
||||
@@ -55,16 +67,25 @@ const summary = [];
|
||||
while (maxIterations === 0 || iterations < maxIterations) {
|
||||
const before = currentTask();
|
||||
assertContext();
|
||||
// A completed V2 plan intentionally leaves the final task as an auditable
|
||||
// pointer. Do not replay its implementation command on later unattended
|
||||
// passes; close the runner cleanly at the terminal boundary.
|
||||
if (terminalTask(before.task)) {
|
||||
summary.push({ task: before.task, command: null, nextTask: null, terminal: true, log: null });
|
||||
process.stdout.write(`continuous-terminal task=${before.task}\n`);
|
||||
break;
|
||||
}
|
||||
const focused = taskCommand(before.task);
|
||||
const logPath = `tests/golden/${before.task}/continuous-runner.log`;
|
||||
const focusedResult = command(focused, logPath);
|
||||
if (focusedResult.code !== 0) throw new Error(`${before.task} focused command failed (exit ${focusedResult.code}); log=${logPath}`);
|
||||
const after = currentTask();
|
||||
if (after.task === before.task) throw new Error(`${before.task} focused command exited 0 without advancing queue; log=${logPath}`);
|
||||
const terminal = after.task === before.task && terminalTask(before.task);
|
||||
if (after.task === before.task && !terminal) throw new Error(`${before.task} focused command exited 0 without advancing queue; log=${logPath}`);
|
||||
const gates = command("node tools/web/check-context-governance.mjs && node tools/web/check-execution-control-plane.mjs --allow-unrunnable && node tools/web/check-v2-task-index.mjs && node tools/web/check-v2-handoff.mjs && npm --prefix web run typecheck && npm --prefix web run lint && git diff --check", `tests/golden/${before.task}/continuous-gates.log`);
|
||||
if (gates.code !== 0) throw new Error(`${before.task} post-handoff gate failed (exit ${gates.code}); log=tests/golden/${before.task}/continuous-gates.log`);
|
||||
iterations += 1;
|
||||
summary.push({ task: before.task, command: focused, nextTask: after.task, log: logPath });
|
||||
summary.push({ task: before.task, command: focused, nextTask: terminal ? null : after.task, terminal, log: logPath });
|
||||
process.stdout.write(`continuous-iteration=${iterations} task=${before.task} next=${after.task}\n`);
|
||||
if (commitEnabled) {
|
||||
const manifestPath = `tests/golden/${before.task}/manifest.json`;
|
||||
@@ -75,15 +96,19 @@ while (maxIterations === 0 || iterations < maxIterations) {
|
||||
"docs/EXECUTION_QUEUE.md",
|
||||
"nextTask.md",
|
||||
`docs/tasks/${before.task}.md`,
|
||||
`docs/tasks/${after.task}.md`,
|
||||
...(terminal ? [] : [`docs/tasks/${after.task}.md`]),
|
||||
`docs/status/${before.task}.md`,
|
||||
`docs/status/${after.task}.md`,
|
||||
...(terminal ? [] : [`docs/status/${after.task}.md`]),
|
||||
manifestPath,
|
||||
...artifactPaths,
|
||||
"tests/golden/WBV2/task-index.json",
|
||||
"tests/golden/WBV2/task-catalog.jsonl",
|
||||
].filter((file, index, all) => file && all.indexOf(file) === index && fs.existsSync(abs(file)));
|
||||
const commit = command(`git add ${handoffPaths.map(shellQuote).join(" ")}`, `tests/golden/${before.task}/continuous-commit.log`);
|
||||
// Every path named by the manifest is part of the auditable handoff. Some
|
||||
// task logs are intentionally ignored by the repository defaults, so use
|
||||
// force-add for this exact, manifest-derived list instead of failing after
|
||||
// the task has already produced a valid receipt.
|
||||
const commit = command(`git add -f ${handoffPaths.map(shellQuote).join(" ")}`, `tests/golden/${before.task}/continuous-commit.log`);
|
||||
if (commit.code !== 0) throw new Error(`${before.task} staging failed; log=tests/golden/${before.task}/continuous-commit.log`);
|
||||
const commitResult = command(`git diff --cached --quiet || git commit -m "chore(web): continuous handoff ${before.task}"`, `tests/golden/${before.task}/continuous-commit-result.log`);
|
||||
if (commitResult.code !== 0) throw new Error(`${before.task} commit failed; log=tests/golden/${before.task}/continuous-commit-result.log`);
|
||||
@@ -107,5 +132,6 @@ while (maxIterations === 0 || iterations < maxIterations) {
|
||||
if (!pushed) throw new Error(`${before.task} remote push verification failed after ${pushRetries + 1} attempts; log=tests/golden/${before.task}/continuous-push-verify.log`);
|
||||
}
|
||||
}
|
||||
if (terminal) break;
|
||||
}
|
||||
process.stdout.write(`continuous-run-complete iterations=${iterations} current=${currentTask().task} committed=${commitEnabled} pushed=${pushEnabled}\n`);
|
||||
|
||||
Reference in New Issue
Block a user