feat(run): resume-aware per-check runs, verify hooks, run-state hardening

/pygienium-<check> is now resume-aware (terminal checks skipped unless
--fresh) and shares run-state with all/resume; every check gets a verify
hook that fails loudly when a sub-agent returns ok with no artifact;
run-state clears stale errors on retry success and reconciles a run as
failed only when every check failed. Drops the superseded
hygiene-state.ts model.
This commit is contained in:
2026-08-09 16:45:30 -04:00
parent 5f8a5cbe5f
commit c605a709fb
15 changed files with 804 additions and 643 deletions

View File

@@ -89,6 +89,33 @@ function defensiveGuardsGate(cwd: string): string | undefined {
return undefined;
}
/**
* Verify hook: confirms the check actually produced its artifacts (mirrors
* {@link commentsVerify} / {@link todosVerify}). After scan `findings.md` must
* exist; after `--fix` `changes.md` must exist too. Catches a sub-agent that
* returns ok with no output — which would otherwise be a false `complete`.
*/
async function defensiveGuardsVerify(
scope: CheckScope,
): Promise<string | undefined> {
const { stat } = await import("node:fs/promises");
const f = findingsPath(scope.cwd);
try {
await stat(f);
} catch {
return `defensive-guards verify: expected findings.md at ${f} after scan, none found.`;
}
if (scope.fix) {
const c = changesPath(scope.cwd);
try {
await stat(c);
} catch {
return `defensive-guards verify: expected changes.md at ${c} after --fix, none found.`;
}
}
return undefined;
}
/**
* Build the scan task. The defensive-guards scanner agent inspects the target,
* classifies each guard as redundant or a legitimate boundary guard against the
@@ -185,6 +212,7 @@ const defensiveGuardsCheck: CheckDefinition = {
buildScanTask: buildDefensiveGuardsScanTask,
buildFixTask: buildDefensiveGuardsFixTask,
gate: defensiveGuardsGate,
verify: defensiveGuardsVerify,
};
registerCheck(defensiveGuardsCheck);