gsd-pi 2.81.0-dev.72a81bdf3 → 2.82.0-dev.2841a1e44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -30
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +3 -1
- package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
- package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
- package/dist/resources/extensions/cmux/index.js +5 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +113 -6
- package/dist/resources/extensions/gsd/auto/phases.js +9 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +169 -124
- package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
- package/dist/resources/extensions/gsd/auto-verification.js +28 -22
- package/dist/resources/extensions/gsd/auto.js +128 -52
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +5 -0
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +16 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +3 -1
- package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
- package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
- package/dist/resources/extensions/gsd/context-store.js +112 -0
- package/dist/resources/extensions/gsd/db-writer.js +150 -84
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
- package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
- package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
- package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
- package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +6 -1
- package/dist/resources/extensions/gsd/md-importer.js +1 -1
- package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
- package/dist/resources/extensions/gsd/migrate/command.js +5 -0
- package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
- package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
- package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
- package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +25 -2
- package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +21 -2
- package/dist/resources/extensions/subagent/index.js +448 -78
- package/dist/resources/extensions/subagent/launch.js +77 -0
- package/dist/resources/extensions/subagent/run-store.js +148 -0
- package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
- package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/dist/resources/extensions/visual-brief/index.js +5 -0
- package/dist/resources/extensions/visual-brief/page-contract.js +122 -0
- package/dist/resources/extensions/visual-brief/prompts.js +111 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
- package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-6a95bc41e0f7ec89.js} +1 -1
- package/dist/web/standalone/.next/static/css/0262768ec1b89d34.css +1 -0
- package/package.json +5 -4
- package/packages/contracts/dist/rpc.test.js +7 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +21 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +24 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/src/rpc.test.ts +8 -0
- package/packages/contracts/src/workflow.ts +24 -0
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +14 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +80 -0
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +22 -0
- package/packages/mcp-server/src/workflow-tools.ts +168 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -2
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -1
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/index.ts +7 -2
- package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +5 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/tui.ts +6 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +3 -1
- package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
- package/src/resources/extensions/cmux/index.ts +6 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +46 -11
- package/src/resources/extensions/gsd/auto/orchestrator.ts +118 -6
- package/src/resources/extensions/gsd/auto/phases.ts +14 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +194 -137
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
- package/src/resources/extensions/gsd/auto-verification.ts +36 -34
- package/src/resources/extensions/gsd/auto.ts +136 -51
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -0
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +16 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +3 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
- package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +25 -1
- package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
- package/src/resources/extensions/gsd/context-store.ts +120 -1
- package/src/resources/extensions/gsd/db-writer.ts +167 -84
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
- package/src/resources/extensions/gsd/md-importer.ts +1 -1
- package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/migrate/command.ts +5 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
- package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +408 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +16 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +35 -2
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +20 -2
- package/src/resources/extensions/subagent/index.ts +567 -103
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +134 -0
- package/src/resources/extensions/visual-brief/prompts.ts +147 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +172 -0
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
- /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → Qgr2B_MRhPxC0z8fwv4vT}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → Qgr2B_MRhPxC0z8fwv4vT}/_ssgManifest.js +0 -0
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Split into two functions called sequentially by auto-loop with
|
|
9
9
|
* the verification gate between them:
|
|
10
|
-
* 1. postUnitPreVerification() —
|
|
11
|
-
* 2. postUnitPostVerification() — DB dual-write, hooks, triage, quick-tasks
|
|
10
|
+
* 1. postUnitPreVerification() — closeout git for non-task units, doctor, state rebuild, worktree sync, artifact verification
|
|
11
|
+
* 2. postUnitPostVerification() — post-verified task git, DB dual-write, hooks, triage, quick-tasks
|
|
12
12
|
*
|
|
13
13
|
* Extracted from the pre-loop agent_end handler in auto.ts.
|
|
14
14
|
*/
|
|
@@ -62,8 +62,7 @@ import { runSafely } from "./auto-utils.js";
|
|
|
62
62
|
import type { AutoSession, SidecarItem } from "./auto/session.js";
|
|
63
63
|
import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
|
|
64
64
|
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
65
|
-
|
|
66
|
-
// import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
65
|
+
import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
67
66
|
import { validateContent } from "./safety/content-validator.js";
|
|
68
67
|
import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
|
|
69
68
|
import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto-artifact-paths.js";
|
|
@@ -222,6 +221,10 @@ export function _shouldDispatchQuickTaskForTest(
|
|
|
222
221
|
state.currentUnit.type !== "quick-task";
|
|
223
222
|
}
|
|
224
223
|
|
|
224
|
+
export function shouldDeferCloseoutGitAction(unitType: string): boolean {
|
|
225
|
+
return unitType === "execute-task";
|
|
226
|
+
}
|
|
227
|
+
|
|
225
228
|
/** Unit types that only touch `.gsd/` internal state files (no code changes).
|
|
226
229
|
* Auto-commit is skipped for these — their state files are picked up by the
|
|
227
230
|
* next actual task commit via `smartStage()`. */
|
|
@@ -466,6 +469,139 @@ export async function autoCommitUnit(
|
|
|
466
469
|
}
|
|
467
470
|
}
|
|
468
471
|
|
|
472
|
+
async function runCloseoutGitAction(
|
|
473
|
+
pctx: PostUnitContext,
|
|
474
|
+
unit: NonNullable<AutoSession["currentUnit"]>,
|
|
475
|
+
): Promise<"continue" | "dispatched"> {
|
|
476
|
+
const { s, ctx, pi, pauseAuto } = pctx;
|
|
477
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
478
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
479
|
+
const turnAction: TurnGitActionMode = uokFlags.gitops ? uokFlags.gitopsTurnAction : "commit";
|
|
480
|
+
const traceId = s.currentTraceId ?? `turn:${unit.startedAt}`;
|
|
481
|
+
const turnId = s.currentTurnId ?? `${unit.type}/${unit.id}/${unit.startedAt}`;
|
|
482
|
+
|
|
483
|
+
s.lastGitActionFailure = null;
|
|
484
|
+
s.lastGitActionStatus = null;
|
|
485
|
+
|
|
486
|
+
try {
|
|
487
|
+
let taskContext: TaskCommitContext | undefined;
|
|
488
|
+
|
|
489
|
+
if (turnAction === "commit" && unit.type === "execute-task") {
|
|
490
|
+
taskContext = await buildTaskCommitContextForUnit(s.basePath, unit.id);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
494
|
+
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
495
|
+
// `false` result causes autoCommit to skip staging entirely.
|
|
496
|
+
_resetHasChangesCache();
|
|
497
|
+
|
|
498
|
+
const skipLifecycleCommit =
|
|
499
|
+
turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(unit.type);
|
|
500
|
+
|
|
501
|
+
if (skipLifecycleCommit) {
|
|
502
|
+
debugLog("postUnit", {
|
|
503
|
+
phase: "git-action-skipped",
|
|
504
|
+
reason: "lifecycle-only-unit",
|
|
505
|
+
unitType: unit.type,
|
|
506
|
+
unitId: unit.id,
|
|
507
|
+
});
|
|
508
|
+
} else {
|
|
509
|
+
const gitResult = runTurnGitAction({
|
|
510
|
+
basePath: s.basePath,
|
|
511
|
+
action: turnAction,
|
|
512
|
+
unitType: unit.type,
|
|
513
|
+
unitId: unit.id,
|
|
514
|
+
taskContext,
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
if (uokFlags.gitops) {
|
|
518
|
+
writeTurnGitTransaction({
|
|
519
|
+
basePath: s.basePath,
|
|
520
|
+
traceId,
|
|
521
|
+
turnId,
|
|
522
|
+
unitType: unit.type,
|
|
523
|
+
unitId: unit.id,
|
|
524
|
+
stage: "publish",
|
|
525
|
+
action: turnAction,
|
|
526
|
+
push: uokFlags.gitopsTurnPush,
|
|
527
|
+
status: gitResult.status,
|
|
528
|
+
error: gitResult.error,
|
|
529
|
+
metadata: {
|
|
530
|
+
dirty: gitResult.dirty,
|
|
531
|
+
commitMessage: gitResult.commitMessage,
|
|
532
|
+
snapshotLabel: gitResult.snapshotLabel,
|
|
533
|
+
},
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (gitResult.status === "failed") {
|
|
538
|
+
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
539
|
+
s.lastGitActionStatus = "failed";
|
|
540
|
+
if (uokFlags.gitops && uokFlags.gates) {
|
|
541
|
+
const parsed = parseUnitId(unit.id);
|
|
542
|
+
const gateRunner = new UokGateRunner();
|
|
543
|
+
gateRunner.register({
|
|
544
|
+
id: "closeout-git-action",
|
|
545
|
+
type: "closeout",
|
|
546
|
+
execute: async () => ({
|
|
547
|
+
outcome: "fail",
|
|
548
|
+
failureClass: "git",
|
|
549
|
+
rationale: `turn git action "${turnAction}" failed`,
|
|
550
|
+
findings: gitResult.error ?? "unknown git failure",
|
|
551
|
+
}),
|
|
552
|
+
});
|
|
553
|
+
await gateRunner.run("closeout-git-action", {
|
|
554
|
+
basePath: s.basePath,
|
|
555
|
+
traceId,
|
|
556
|
+
turnId,
|
|
557
|
+
milestoneId: parsed.milestone ?? undefined,
|
|
558
|
+
sliceId: parsed.slice ?? undefined,
|
|
559
|
+
taskId: parsed.task ?? undefined,
|
|
560
|
+
unitType: unit.type,
|
|
561
|
+
unitId: unit.id,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
566
|
+
ctx.ui.notify(failureMsg, "error");
|
|
567
|
+
debugLog("postUnit", {
|
|
568
|
+
phase: "git-action-failed-blocking",
|
|
569
|
+
action: turnAction,
|
|
570
|
+
error: gitResult.error ?? "unknown error",
|
|
571
|
+
});
|
|
572
|
+
await pauseAuto(ctx, pi);
|
|
573
|
+
return "dispatched";
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
s.lastGitActionStatus = "ok";
|
|
577
|
+
|
|
578
|
+
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
579
|
+
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
580
|
+
} else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
581
|
+
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
} catch (e) {
|
|
585
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
586
|
+
s.lastGitActionFailure = message;
|
|
587
|
+
s.lastGitActionStatus = "failed";
|
|
588
|
+
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
589
|
+
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
|
|
590
|
+
if (uokFlags.gitops) {
|
|
591
|
+
await pauseAuto(ctx, pi);
|
|
592
|
+
return "dispatched";
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// GitHub sync (non-blocking, opt-in)
|
|
597
|
+
await runSafely("postUnit", "github-sync", async () => {
|
|
598
|
+
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
599
|
+
await runGitHubSync(s.basePath, unit.type, unit.id);
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
return "continue";
|
|
603
|
+
}
|
|
604
|
+
|
|
469
605
|
/**
|
|
470
606
|
* Pre-verification processing: parallel worker signal check, cache invalidation,
|
|
471
607
|
* auto-commit, doctor run, state rebuild, worktree sync, artifact verification.
|
|
@@ -476,7 +612,7 @@ export async function autoCommitUnit(
|
|
|
476
612
|
* - "retry" — artifact verification failed, s.pendingVerificationRetry set for loop re-iteration
|
|
477
613
|
*/
|
|
478
614
|
export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreVerificationOpts): Promise<"dispatched" | "continue" | "retry"> {
|
|
479
|
-
const { s, ctx, pi,
|
|
615
|
+
const { s, ctx, pi, stopAuto, pauseAuto } = pctx;
|
|
480
616
|
|
|
481
617
|
// ── Parallel worker signal check ──
|
|
482
618
|
const milestoneLock = process.env.GSD_MILESTONE_LOCK;
|
|
@@ -502,135 +638,22 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
502
638
|
await new Promise(r => setTimeout(r, 100));
|
|
503
639
|
}
|
|
504
640
|
|
|
505
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
506
|
-
const uokFlags = resolveUokFlags(prefs);
|
|
507
|
-
|
|
508
641
|
// Turn-level git action (commit | snapshot | status-only)
|
|
509
642
|
if (s.currentUnit) {
|
|
510
643
|
const unit = s.currentUnit;
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (
|
|
520
|
-
taskContext = await buildTaskCommitContextForUnit(s.basePath, s.currentUnit.id);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
524
|
-
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
525
|
-
// `false` result causes autoCommit to skip staging entirely, leaving
|
|
526
|
-
// code files only in the working tree where they are destroyed by
|
|
527
|
-
// `git worktree remove --force` during teardown.
|
|
528
|
-
_resetHasChangesCache();
|
|
529
|
-
|
|
530
|
-
const skipLifecycleCommit =
|
|
531
|
-
turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type);
|
|
532
|
-
|
|
533
|
-
if (skipLifecycleCommit) {
|
|
534
|
-
debugLog("postUnit", {
|
|
535
|
-
phase: "git-action-skipped",
|
|
536
|
-
reason: "lifecycle-only-unit",
|
|
537
|
-
unitType: s.currentUnit.type,
|
|
538
|
-
unitId: s.currentUnit.id,
|
|
539
|
-
});
|
|
540
|
-
} else {
|
|
541
|
-
const gitResult = runTurnGitAction({
|
|
542
|
-
basePath: s.basePath,
|
|
543
|
-
action: turnAction,
|
|
544
|
-
unitType: s.currentUnit.type,
|
|
545
|
-
unitId: s.currentUnit.id,
|
|
546
|
-
taskContext,
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
if (uokFlags.gitops) {
|
|
550
|
-
writeTurnGitTransaction({
|
|
551
|
-
basePath: s.basePath,
|
|
552
|
-
traceId,
|
|
553
|
-
turnId,
|
|
554
|
-
unitType: unit.type,
|
|
555
|
-
unitId: unit.id,
|
|
556
|
-
stage: "publish",
|
|
557
|
-
action: turnAction,
|
|
558
|
-
push: uokFlags.gitopsTurnPush,
|
|
559
|
-
status: gitResult.status,
|
|
560
|
-
error: gitResult.error,
|
|
561
|
-
metadata: {
|
|
562
|
-
dirty: gitResult.dirty,
|
|
563
|
-
commitMessage: gitResult.commitMessage,
|
|
564
|
-
snapshotLabel: gitResult.snapshotLabel,
|
|
565
|
-
},
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
if (gitResult.status === "failed") {
|
|
570
|
-
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
571
|
-
s.lastGitActionStatus = "failed";
|
|
572
|
-
if (uokFlags.gitops && uokFlags.gates) {
|
|
573
|
-
const parsed = parseUnitId(unit.id);
|
|
574
|
-
const gateRunner = new UokGateRunner();
|
|
575
|
-
gateRunner.register({
|
|
576
|
-
id: "closeout-git-action",
|
|
577
|
-
type: "closeout",
|
|
578
|
-
execute: async () => ({
|
|
579
|
-
outcome: "fail",
|
|
580
|
-
failureClass: "git",
|
|
581
|
-
rationale: `turn git action "${turnAction}" failed`,
|
|
582
|
-
findings: gitResult.error ?? "unknown git failure",
|
|
583
|
-
}),
|
|
584
|
-
});
|
|
585
|
-
await gateRunner.run("closeout-git-action", {
|
|
586
|
-
basePath: s.basePath,
|
|
587
|
-
traceId,
|
|
588
|
-
turnId,
|
|
589
|
-
milestoneId: parsed.milestone ?? undefined,
|
|
590
|
-
sliceId: parsed.slice ?? undefined,
|
|
591
|
-
taskId: parsed.task ?? undefined,
|
|
592
|
-
unitType: unit.type,
|
|
593
|
-
unitId: unit.id,
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
598
|
-
ctx.ui.notify(failureMsg, "error");
|
|
599
|
-
debugLog("postUnit", {
|
|
600
|
-
phase: "git-action-failed-blocking",
|
|
601
|
-
action: turnAction,
|
|
602
|
-
error: gitResult.error ?? "unknown error",
|
|
603
|
-
});
|
|
604
|
-
await pauseAuto(ctx, pi);
|
|
605
|
-
return "dispatched";
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
s.lastGitActionStatus = "ok";
|
|
609
|
-
|
|
610
|
-
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
611
|
-
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
612
|
-
} else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
613
|
-
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
} catch (e) {
|
|
617
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
618
|
-
s.lastGitActionFailure = message;
|
|
619
|
-
s.lastGitActionStatus = "failed";
|
|
620
|
-
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
621
|
-
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
|
|
622
|
-
if (uokFlags.gitops) {
|
|
623
|
-
await pauseAuto(ctx, pi);
|
|
644
|
+
if (shouldDeferCloseoutGitAction(unit.type)) {
|
|
645
|
+
debugLog("postUnit", {
|
|
646
|
+
phase: "git-action-deferred-until-verification",
|
|
647
|
+
unitType: unit.type,
|
|
648
|
+
unitId: unit.id,
|
|
649
|
+
});
|
|
650
|
+
} else {
|
|
651
|
+
const gitActionResult = await runCloseoutGitAction(pctx, unit);
|
|
652
|
+
if (gitActionResult === "dispatched") {
|
|
624
653
|
return "dispatched";
|
|
625
654
|
}
|
|
626
655
|
}
|
|
627
656
|
|
|
628
|
-
// GitHub sync (non-blocking, opt-in)
|
|
629
|
-
await runSafely("postUnit", "github-sync", async () => {
|
|
630
|
-
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
631
|
-
await runGitHubSync(s.basePath, unit.type, unit.id);
|
|
632
|
-
});
|
|
633
|
-
|
|
634
657
|
// Prune dead bg-shell processes
|
|
635
658
|
await runSafely("postUnit", "prune-bg-shell", async () => {
|
|
636
659
|
const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
|
|
@@ -866,7 +889,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
866
889
|
if (safetyConfig.enabled) {
|
|
867
890
|
const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
|
|
868
891
|
|
|
869
|
-
// File change validation (execute-task only, after
|
|
892
|
+
// File change validation (execute-task only, after unit execution)
|
|
870
893
|
if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid && isDbAvailable()) {
|
|
871
894
|
try {
|
|
872
895
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
@@ -902,15 +925,42 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
902
925
|
const bashCalls = actual.filter(e => e.kind === "bash");
|
|
903
926
|
if (sMid && sSid && sTid && isDbAvailable()) {
|
|
904
927
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
"
|
|
913
|
-
);
|
|
928
|
+
if (taskRow?.status === "complete") {
|
|
929
|
+
const claimedEvidence: ClaimedEvidence[] = getVerificationEvidence(sMid, sSid, sTid)
|
|
930
|
+
.map((row) => ({
|
|
931
|
+
command: row.command,
|
|
932
|
+
exitCode: row.exit_code,
|
|
933
|
+
verdict: row.verdict,
|
|
934
|
+
}))
|
|
935
|
+
.filter((row) => typeof row.command === "string" && row.command.trim().length > 0);
|
|
936
|
+
const mismatches = crossReferenceEvidence(claimedEvidence, actual);
|
|
937
|
+
|
|
938
|
+
for (const mismatch of mismatches) {
|
|
939
|
+
const logMessage = `evidence-xref: ${mismatch.reason}`;
|
|
940
|
+
if (mismatch.severity === "error") {
|
|
941
|
+
logError("safety", logMessage);
|
|
942
|
+
} else {
|
|
943
|
+
logWarning("safety", logMessage);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
if (claimedEvidence.length > 0 && bashCalls.length === 0) {
|
|
948
|
+
logWarning("safety", "task claimed verification command evidence but no execution tool calls were recorded");
|
|
949
|
+
ctx.ui.notify(
|
|
950
|
+
`Safety: task ${sTid} claimed command evidence but no execution tool calls were recorded`,
|
|
951
|
+
"warning",
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const blockingMismatch = mismatches.find((mismatch) => mismatch.severity === "error");
|
|
956
|
+
if (blockingMismatch) {
|
|
957
|
+
ctx.ui.notify(
|
|
958
|
+
`Safety: task ${sTid} claimed passing verification that failed in recorded execution`,
|
|
959
|
+
"error",
|
|
960
|
+
);
|
|
961
|
+
await pauseAuto(ctx, pi);
|
|
962
|
+
return "dispatched";
|
|
963
|
+
}
|
|
914
964
|
}
|
|
915
965
|
}
|
|
916
966
|
} catch (e) {
|
|
@@ -1169,6 +1219,13 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
1169
1219
|
const { s, ctx, pi, buildSnapshotOpts, lockBase, stopAuto, pauseAuto, updateProgressWidget } = pctx;
|
|
1170
1220
|
|
|
1171
1221
|
if (s.currentUnit) {
|
|
1222
|
+
if (shouldDeferCloseoutGitAction(s.currentUnit.type)) {
|
|
1223
|
+
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit);
|
|
1224
|
+
if (gitActionResult === "dispatched") {
|
|
1225
|
+
return "stopped";
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1172
1229
|
try {
|
|
1173
1230
|
const codebasePrefs = loadEffectiveGSDPreferences()?.preferences?.codebase;
|
|
1174
1231
|
const refresh = ensureCodebaseMapFresh(
|
|
@@ -806,14 +806,22 @@ export async function inlineDecisionsFromDb(
|
|
|
806
806
|
try {
|
|
807
807
|
const { isDbAvailable } = await import("./gsd-db.js");
|
|
808
808
|
if (isDbAvailable()) {
|
|
809
|
-
|
|
809
|
+
// ADR-013 Phase 6 cutover (Stage 1): read decisions from the `memories`
|
|
810
|
+
// table. Both `queryDecisions` (legacy) and `queryDecisionsFromMemories`
|
|
811
|
+
// return identical Decision[] for active rows once Phase 5 dual-write is
|
|
812
|
+
// caught up. Switching the read here lets the destructive Phase 6 step
|
|
813
|
+
// (#5755) retire the legacy `decisions` table without changing prompt
|
|
814
|
+
// contents. Projection regen (`DECISIONS.md`) still sources from the
|
|
815
|
+
// legacy table — that switch lands separately to handle superseded
|
|
816
|
+
// history cleanly.
|
|
817
|
+
const { queryDecisionsFromMemories, formatDecisionsForPrompt } = await import("./context-store.js");
|
|
810
818
|
|
|
811
819
|
// First query: try with both milestoneId and scope (if scope provided)
|
|
812
|
-
let decisions =
|
|
820
|
+
let decisions = queryDecisionsFromMemories({ milestoneId, scope });
|
|
813
821
|
|
|
814
822
|
// Cascade: if empty AND scope was provided, retry without scope
|
|
815
823
|
if (decisions.length === 0 && scope) {
|
|
816
|
-
decisions =
|
|
824
|
+
decisions = queryDecisionsFromMemories({ milestoneId });
|
|
817
825
|
}
|
|
818
826
|
|
|
819
827
|
if (decisions.length > 0) {
|
|
@@ -3189,7 +3197,7 @@ export async function buildParallelResearchSlicesPrompt(
|
|
|
3189
3197
|
subagentSections.push([
|
|
3190
3198
|
`### ${slice.id}: ${slice.title}`,
|
|
3191
3199
|
"",
|
|
3192
|
-
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`
|
|
3200
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`scout\`):`,
|
|
3193
3201
|
"",
|
|
3194
3202
|
"```",
|
|
3195
3203
|
slicePrompt,
|
|
@@ -3271,7 +3279,7 @@ export async function buildGateEvaluatePrompt(
|
|
|
3271
3279
|
subagentSections.push([
|
|
3272
3280
|
`### ${def.id}: ${def.question}`,
|
|
3273
3281
|
"",
|
|
3274
|
-
`Use this as the prompt for a \`subagent\` call${modelSuffix}:`,
|
|
3282
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`tester\`):`,
|
|
3275
3283
|
"",
|
|
3276
3284
|
"```",
|
|
3277
3285
|
subPrompt,
|
|
@@ -40,6 +40,7 @@ import { join } from "node:path";
|
|
|
40
40
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
41
41
|
import { UokGateRunner } from "./uok/gate-runner.js";
|
|
42
42
|
import { verificationRetryKey } from "./auto/verification-retry-policy.js";
|
|
43
|
+
import { decideVerificationVerdict } from "./verification-verdict.js";
|
|
43
44
|
|
|
44
45
|
export interface VerificationContext {
|
|
45
46
|
s: AutoSession;
|
|
@@ -49,12 +50,6 @@ export interface VerificationContext {
|
|
|
49
50
|
|
|
50
51
|
export type VerificationResult = "continue" | "retry" | "pause";
|
|
51
52
|
|
|
52
|
-
function isInfraVerificationFailure(stderr: string): boolean {
|
|
53
|
-
return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(
|
|
54
|
-
stderr,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
53
|
/**
|
|
59
54
|
* Post-unit guard for `validate-milestone` units (#4094).
|
|
60
55
|
*
|
|
@@ -196,7 +191,7 @@ async function countIncompleteSlices(basePath: string, milestoneId: string): Pro
|
|
|
196
191
|
/**
|
|
197
192
|
* Run the verification gate for the current execute-task unit.
|
|
198
193
|
* Returns:
|
|
199
|
-
* - "continue" —
|
|
194
|
+
* - "continue" — host-owned verification passed, proceed normally
|
|
200
195
|
* - "retry" — gate failed with retries remaining, s.pendingVerificationRetry set for loop re-iteration
|
|
201
196
|
* - "pause" — gate failed with retries exhausted, pauseAuto already called
|
|
202
197
|
*/
|
|
@@ -260,6 +255,11 @@ export async function runPostUnitVerification(
|
|
|
260
255
|
}
|
|
261
256
|
}
|
|
262
257
|
|
|
258
|
+
const verdict = decideVerificationVerdict(s.currentUnit.type, result);
|
|
259
|
+
if (!verdict.passed) {
|
|
260
|
+
result.passed = false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
263
|
if (uokFlags.gates) {
|
|
264
264
|
const gateRunner = new UokGateRunner();
|
|
265
265
|
gateRunner.register({
|
|
@@ -272,10 +272,12 @@ export async function runPostUnitVerification(
|
|
|
272
272
|
: "verification",
|
|
273
273
|
rationale: result.passed
|
|
274
274
|
? "verification checks passed"
|
|
275
|
-
:
|
|
275
|
+
: verdict.reason === "no-host-checks"
|
|
276
|
+
? "no runnable host-owned verification checks discovered"
|
|
277
|
+
: "verification checks failed",
|
|
276
278
|
findings: result.passed
|
|
277
279
|
? ""
|
|
278
|
-
: formatFailureContext(result),
|
|
280
|
+
: verdict.failureContext || formatFailureContext(result),
|
|
279
281
|
}),
|
|
280
282
|
});
|
|
281
283
|
|
|
@@ -343,13 +345,18 @@ export async function runPostUnitVerification(
|
|
|
343
345
|
writeVerificationJSON(result, tasksDir, tid, s.currentUnit.id);
|
|
344
346
|
} else {
|
|
345
347
|
const nextAttempt = attempt + 1;
|
|
348
|
+
const includeRetryMetadata =
|
|
349
|
+
!result.passed &&
|
|
350
|
+
verdict.retryable &&
|
|
351
|
+
autoFixEnabled &&
|
|
352
|
+
nextAttempt <= maxRetries;
|
|
346
353
|
writeVerificationJSON(
|
|
347
354
|
result,
|
|
348
355
|
tasksDir,
|
|
349
356
|
tid,
|
|
350
357
|
s.currentUnit.id,
|
|
351
|
-
nextAttempt,
|
|
352
|
-
maxRetries,
|
|
358
|
+
includeRetryMetadata ? nextAttempt : undefined,
|
|
359
|
+
includeRetryMetadata ? maxRetries : undefined,
|
|
353
360
|
);
|
|
354
361
|
}
|
|
355
362
|
}
|
|
@@ -358,26 +365,6 @@ export async function runPostUnitVerification(
|
|
|
358
365
|
}
|
|
359
366
|
}
|
|
360
367
|
|
|
361
|
-
const advisoryFailure =
|
|
362
|
-
!result.passed &&
|
|
363
|
-
(result.discoverySource === "package-json" ||
|
|
364
|
-
result.checks.some((check) =>
|
|
365
|
-
isInfraVerificationFailure(check.stderr),
|
|
366
|
-
));
|
|
367
|
-
|
|
368
|
-
if (advisoryFailure) {
|
|
369
|
-
s.verificationRetryCount.delete(retryKey);
|
|
370
|
-
s.verificationRetryFailureHashes.delete(retryKey);
|
|
371
|
-
s.pendingVerificationRetry = null;
|
|
372
|
-
ctx.ui.notify(
|
|
373
|
-
result.discoverySource === "package-json"
|
|
374
|
-
? "Verification failed in auto-discovered package.json checks — treating as advisory."
|
|
375
|
-
: "Verification failed due to infrastructure/runtime environment issues — treating as advisory.",
|
|
376
|
-
"warning",
|
|
377
|
-
);
|
|
378
|
-
return "continue";
|
|
379
|
-
}
|
|
380
|
-
|
|
381
368
|
// ── Post-execution checks (run after main verification passes for execute-task units) ──
|
|
382
369
|
let postExecChecks: PostExecutionCheckJSON[] | undefined;
|
|
383
370
|
let postExecBlockingFailure = false;
|
|
@@ -572,6 +559,17 @@ export async function runPostUnitVerification(
|
|
|
572
559
|
s.verificationRetryFailureHashes.delete(retryKey);
|
|
573
560
|
s.pendingVerificationRetry = null;
|
|
574
561
|
return "continue";
|
|
562
|
+
} else if (verdict.reason === "no-host-checks") {
|
|
563
|
+
s.verificationRetryCount.delete(retryKey);
|
|
564
|
+
s.verificationRetryFailureHashes.delete(retryKey);
|
|
565
|
+
s.pendingVerificationRetry = null;
|
|
566
|
+
ctx.ui.notify(
|
|
567
|
+
"Verification gate FAILED — no runnable host-owned verification checks were discovered. Pausing for human review.",
|
|
568
|
+
"error",
|
|
569
|
+
);
|
|
570
|
+
process.stderr.write(`verification-gate: ${verdict.failureContext}\n`);
|
|
571
|
+
await pauseAuto(ctx, pi);
|
|
572
|
+
return "pause";
|
|
575
573
|
} else if (postExecBlockingFailure) {
|
|
576
574
|
// Post-execution failures are cross-task consistency issues — retrying the same task won't fix them.
|
|
577
575
|
// Skip retry and pause immediately for human review.
|
|
@@ -589,7 +587,7 @@ export async function runPostUnitVerification(
|
|
|
589
587
|
s.verificationRetryCount.set(retryKey, nextAttempt);
|
|
590
588
|
s.pendingVerificationRetry = {
|
|
591
589
|
unitId: s.currentUnit.id,
|
|
592
|
-
failureContext: formatFailureContext(result),
|
|
590
|
+
failureContext: verdict.failureContext || formatFailureContext(result),
|
|
593
591
|
attempt: nextAttempt,
|
|
594
592
|
};
|
|
595
593
|
const failedCmds = result.checks
|
|
@@ -623,9 +621,13 @@ export async function runPostUnitVerification(
|
|
|
623
621
|
return "pause";
|
|
624
622
|
}
|
|
625
623
|
} catch (err) {
|
|
626
|
-
// Gate errors are non-fatal
|
|
627
624
|
logWarning("engine", `verification-gate error: ${(err as Error).message}`);
|
|
628
|
-
|
|
625
|
+
ctx.ui.notify(
|
|
626
|
+
`Verification gate errored before producing an authoritative verdict: ${(err as Error).message}`,
|
|
627
|
+
"error",
|
|
628
|
+
);
|
|
629
|
+
await pauseAuto(ctx, pi);
|
|
630
|
+
return "pause";
|
|
629
631
|
}
|
|
630
632
|
}
|
|
631
633
|
|