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
|
*/
|
|
@@ -37,8 +37,7 @@ import { debugLog } from "./debug-logger.js";
|
|
|
37
37
|
import { runSafely } from "./auto-utils.js";
|
|
38
38
|
import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
|
|
39
39
|
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
40
|
-
|
|
41
|
-
// import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
40
|
+
import { crossReferenceEvidence } from "./safety/evidence-cross-ref.js";
|
|
42
41
|
import { validateContent } from "./safety/content-validator.js";
|
|
43
42
|
import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
|
|
44
43
|
import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto-artifact-paths.js";
|
|
@@ -171,6 +170,9 @@ export function _shouldDispatchQuickTaskForTest(state) {
|
|
|
171
170
|
!!state.currentUnit &&
|
|
172
171
|
state.currentUnit.type !== "quick-task";
|
|
173
172
|
}
|
|
173
|
+
export function shouldDeferCloseoutGitAction(unitType) {
|
|
174
|
+
return unitType === "execute-task";
|
|
175
|
+
}
|
|
174
176
|
/** Unit types that only touch `.gsd/` internal state files (no code changes).
|
|
175
177
|
* Auto-commit is skipped for these — their state files are picked up by the
|
|
176
178
|
* next actual task commit via `smartStage()`. */
|
|
@@ -360,6 +362,124 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
|
360
362
|
return null;
|
|
361
363
|
}
|
|
362
364
|
}
|
|
365
|
+
async function runCloseoutGitAction(pctx, unit) {
|
|
366
|
+
const { s, ctx, pi, pauseAuto } = pctx;
|
|
367
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
368
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
369
|
+
const turnAction = uokFlags.gitops ? uokFlags.gitopsTurnAction : "commit";
|
|
370
|
+
const traceId = s.currentTraceId ?? `turn:${unit.startedAt}`;
|
|
371
|
+
const turnId = s.currentTurnId ?? `${unit.type}/${unit.id}/${unit.startedAt}`;
|
|
372
|
+
s.lastGitActionFailure = null;
|
|
373
|
+
s.lastGitActionStatus = null;
|
|
374
|
+
try {
|
|
375
|
+
let taskContext;
|
|
376
|
+
if (turnAction === "commit" && unit.type === "execute-task") {
|
|
377
|
+
taskContext = await buildTaskCommitContextForUnit(s.basePath, unit.id);
|
|
378
|
+
}
|
|
379
|
+
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
380
|
+
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
381
|
+
// `false` result causes autoCommit to skip staging entirely.
|
|
382
|
+
_resetHasChangesCache();
|
|
383
|
+
const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(unit.type);
|
|
384
|
+
if (skipLifecycleCommit) {
|
|
385
|
+
debugLog("postUnit", {
|
|
386
|
+
phase: "git-action-skipped",
|
|
387
|
+
reason: "lifecycle-only-unit",
|
|
388
|
+
unitType: unit.type,
|
|
389
|
+
unitId: unit.id,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
const gitResult = runTurnGitAction({
|
|
394
|
+
basePath: s.basePath,
|
|
395
|
+
action: turnAction,
|
|
396
|
+
unitType: unit.type,
|
|
397
|
+
unitId: unit.id,
|
|
398
|
+
taskContext,
|
|
399
|
+
});
|
|
400
|
+
if (uokFlags.gitops) {
|
|
401
|
+
writeTurnGitTransaction({
|
|
402
|
+
basePath: s.basePath,
|
|
403
|
+
traceId,
|
|
404
|
+
turnId,
|
|
405
|
+
unitType: unit.type,
|
|
406
|
+
unitId: unit.id,
|
|
407
|
+
stage: "publish",
|
|
408
|
+
action: turnAction,
|
|
409
|
+
push: uokFlags.gitopsTurnPush,
|
|
410
|
+
status: gitResult.status,
|
|
411
|
+
error: gitResult.error,
|
|
412
|
+
metadata: {
|
|
413
|
+
dirty: gitResult.dirty,
|
|
414
|
+
commitMessage: gitResult.commitMessage,
|
|
415
|
+
snapshotLabel: gitResult.snapshotLabel,
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
if (gitResult.status === "failed") {
|
|
420
|
+
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
421
|
+
s.lastGitActionStatus = "failed";
|
|
422
|
+
if (uokFlags.gitops && uokFlags.gates) {
|
|
423
|
+
const parsed = parseUnitId(unit.id);
|
|
424
|
+
const gateRunner = new UokGateRunner();
|
|
425
|
+
gateRunner.register({
|
|
426
|
+
id: "closeout-git-action",
|
|
427
|
+
type: "closeout",
|
|
428
|
+
execute: async () => ({
|
|
429
|
+
outcome: "fail",
|
|
430
|
+
failureClass: "git",
|
|
431
|
+
rationale: `turn git action "${turnAction}" failed`,
|
|
432
|
+
findings: gitResult.error ?? "unknown git failure",
|
|
433
|
+
}),
|
|
434
|
+
});
|
|
435
|
+
await gateRunner.run("closeout-git-action", {
|
|
436
|
+
basePath: s.basePath,
|
|
437
|
+
traceId,
|
|
438
|
+
turnId,
|
|
439
|
+
milestoneId: parsed.milestone ?? undefined,
|
|
440
|
+
sliceId: parsed.slice ?? undefined,
|
|
441
|
+
taskId: parsed.task ?? undefined,
|
|
442
|
+
unitType: unit.type,
|
|
443
|
+
unitId: unit.id,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
447
|
+
ctx.ui.notify(failureMsg, "error");
|
|
448
|
+
debugLog("postUnit", {
|
|
449
|
+
phase: "git-action-failed-blocking",
|
|
450
|
+
action: turnAction,
|
|
451
|
+
error: gitResult.error ?? "unknown error",
|
|
452
|
+
});
|
|
453
|
+
await pauseAuto(ctx, pi);
|
|
454
|
+
return "dispatched";
|
|
455
|
+
}
|
|
456
|
+
s.lastGitActionStatus = "ok";
|
|
457
|
+
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
458
|
+
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
459
|
+
}
|
|
460
|
+
else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
461
|
+
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
catch (e) {
|
|
466
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
467
|
+
s.lastGitActionFailure = message;
|
|
468
|
+
s.lastGitActionStatus = "failed";
|
|
469
|
+
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
470
|
+
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
|
|
471
|
+
if (uokFlags.gitops) {
|
|
472
|
+
await pauseAuto(ctx, pi);
|
|
473
|
+
return "dispatched";
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
// GitHub sync (non-blocking, opt-in)
|
|
477
|
+
await runSafely("postUnit", "github-sync", async () => {
|
|
478
|
+
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
479
|
+
await runGitHubSync(s.basePath, unit.type, unit.id);
|
|
480
|
+
});
|
|
481
|
+
return "continue";
|
|
482
|
+
}
|
|
363
483
|
/**
|
|
364
484
|
* Pre-verification processing: parallel worker signal check, cache invalidation,
|
|
365
485
|
* auto-commit, doctor run, state rebuild, worktree sync, artifact verification.
|
|
@@ -370,7 +490,7 @@ export async function autoCommitUnit(basePath, unitType, unitId, ctx) {
|
|
|
370
490
|
* - "retry" — artifact verification failed, s.pendingVerificationRetry set for loop re-iteration
|
|
371
491
|
*/
|
|
372
492
|
export async function postUnitPreVerification(pctx, opts) {
|
|
373
|
-
const { s, ctx, pi,
|
|
493
|
+
const { s, ctx, pi, stopAuto, pauseAuto } = pctx;
|
|
374
494
|
// ── Parallel worker signal check ──
|
|
375
495
|
const milestoneLock = process.env.GSD_MILESTONE_LOCK;
|
|
376
496
|
if (milestoneLock) {
|
|
@@ -392,125 +512,22 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
392
512
|
if (!opts?.skipSettleDelay) {
|
|
393
513
|
await new Promise(r => setTimeout(r, 100));
|
|
394
514
|
}
|
|
395
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
396
|
-
const uokFlags = resolveUokFlags(prefs);
|
|
397
515
|
// Turn-level git action (commit | snapshot | status-only)
|
|
398
516
|
if (s.currentUnit) {
|
|
399
517
|
const unit = s.currentUnit;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
let taskContext;
|
|
407
|
-
if (turnAction === "commit" && s.currentUnit.type === "execute-task") {
|
|
408
|
-
taskContext = await buildTaskCommitContextForUnit(s.basePath, s.currentUnit.id);
|
|
409
|
-
}
|
|
410
|
-
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
411
|
-
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
412
|
-
// `false` result causes autoCommit to skip staging entirely, leaving
|
|
413
|
-
// code files only in the working tree where they are destroyed by
|
|
414
|
-
// `git worktree remove --force` during teardown.
|
|
415
|
-
_resetHasChangesCache();
|
|
416
|
-
const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type);
|
|
417
|
-
if (skipLifecycleCommit) {
|
|
418
|
-
debugLog("postUnit", {
|
|
419
|
-
phase: "git-action-skipped",
|
|
420
|
-
reason: "lifecycle-only-unit",
|
|
421
|
-
unitType: s.currentUnit.type,
|
|
422
|
-
unitId: s.currentUnit.id,
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
const gitResult = runTurnGitAction({
|
|
427
|
-
basePath: s.basePath,
|
|
428
|
-
action: turnAction,
|
|
429
|
-
unitType: s.currentUnit.type,
|
|
430
|
-
unitId: s.currentUnit.id,
|
|
431
|
-
taskContext,
|
|
432
|
-
});
|
|
433
|
-
if (uokFlags.gitops) {
|
|
434
|
-
writeTurnGitTransaction({
|
|
435
|
-
basePath: s.basePath,
|
|
436
|
-
traceId,
|
|
437
|
-
turnId,
|
|
438
|
-
unitType: unit.type,
|
|
439
|
-
unitId: unit.id,
|
|
440
|
-
stage: "publish",
|
|
441
|
-
action: turnAction,
|
|
442
|
-
push: uokFlags.gitopsTurnPush,
|
|
443
|
-
status: gitResult.status,
|
|
444
|
-
error: gitResult.error,
|
|
445
|
-
metadata: {
|
|
446
|
-
dirty: gitResult.dirty,
|
|
447
|
-
commitMessage: gitResult.commitMessage,
|
|
448
|
-
snapshotLabel: gitResult.snapshotLabel,
|
|
449
|
-
},
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
if (gitResult.status === "failed") {
|
|
453
|
-
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
454
|
-
s.lastGitActionStatus = "failed";
|
|
455
|
-
if (uokFlags.gitops && uokFlags.gates) {
|
|
456
|
-
const parsed = parseUnitId(unit.id);
|
|
457
|
-
const gateRunner = new UokGateRunner();
|
|
458
|
-
gateRunner.register({
|
|
459
|
-
id: "closeout-git-action",
|
|
460
|
-
type: "closeout",
|
|
461
|
-
execute: async () => ({
|
|
462
|
-
outcome: "fail",
|
|
463
|
-
failureClass: "git",
|
|
464
|
-
rationale: `turn git action "${turnAction}" failed`,
|
|
465
|
-
findings: gitResult.error ?? "unknown git failure",
|
|
466
|
-
}),
|
|
467
|
-
});
|
|
468
|
-
await gateRunner.run("closeout-git-action", {
|
|
469
|
-
basePath: s.basePath,
|
|
470
|
-
traceId,
|
|
471
|
-
turnId,
|
|
472
|
-
milestoneId: parsed.milestone ?? undefined,
|
|
473
|
-
sliceId: parsed.slice ?? undefined,
|
|
474
|
-
taskId: parsed.task ?? undefined,
|
|
475
|
-
unitType: unit.type,
|
|
476
|
-
unitId: unit.id,
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
480
|
-
ctx.ui.notify(failureMsg, "error");
|
|
481
|
-
debugLog("postUnit", {
|
|
482
|
-
phase: "git-action-failed-blocking",
|
|
483
|
-
action: turnAction,
|
|
484
|
-
error: gitResult.error ?? "unknown error",
|
|
485
|
-
});
|
|
486
|
-
await pauseAuto(ctx, pi);
|
|
487
|
-
return "dispatched";
|
|
488
|
-
}
|
|
489
|
-
s.lastGitActionStatus = "ok";
|
|
490
|
-
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
491
|
-
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
492
|
-
}
|
|
493
|
-
else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
494
|
-
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
495
|
-
}
|
|
496
|
-
}
|
|
518
|
+
if (shouldDeferCloseoutGitAction(unit.type)) {
|
|
519
|
+
debugLog("postUnit", {
|
|
520
|
+
phase: "git-action-deferred-until-verification",
|
|
521
|
+
unitType: unit.type,
|
|
522
|
+
unitId: unit.id,
|
|
523
|
+
});
|
|
497
524
|
}
|
|
498
|
-
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
s.lastGitActionStatus = "failed";
|
|
502
|
-
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
503
|
-
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
|
|
504
|
-
if (uokFlags.gitops) {
|
|
505
|
-
await pauseAuto(ctx, pi);
|
|
525
|
+
else {
|
|
526
|
+
const gitActionResult = await runCloseoutGitAction(pctx, unit);
|
|
527
|
+
if (gitActionResult === "dispatched") {
|
|
506
528
|
return "dispatched";
|
|
507
529
|
}
|
|
508
530
|
}
|
|
509
|
-
// GitHub sync (non-blocking, opt-in)
|
|
510
|
-
await runSafely("postUnit", "github-sync", async () => {
|
|
511
|
-
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
512
|
-
await runGitHubSync(s.basePath, unit.type, unit.id);
|
|
513
|
-
});
|
|
514
531
|
// Prune dead bg-shell processes
|
|
515
532
|
await runSafely("postUnit", "prune-bg-shell", async () => {
|
|
516
533
|
const { pruneDeadProcesses } = await import("../bg-shell/process-manager.js");
|
|
@@ -723,7 +740,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
723
740
|
const safetyConfig = resolveSafetyHarnessConfig(prefs?.safety_harness);
|
|
724
741
|
if (safetyConfig.enabled) {
|
|
725
742
|
const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
|
|
726
|
-
// File change validation (execute-task only, after
|
|
743
|
+
// File change validation (execute-task only, after unit execution)
|
|
727
744
|
if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid && isDbAvailable()) {
|
|
728
745
|
try {
|
|
729
746
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
@@ -756,12 +773,34 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
756
773
|
const bashCalls = actual.filter(e => e.kind === "bash");
|
|
757
774
|
if (sMid && sSid && sTid && isDbAvailable()) {
|
|
758
775
|
const taskRow = getTask(sMid, sSid, sTid);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
776
|
+
if (taskRow?.status === "complete") {
|
|
777
|
+
const claimedEvidence = getVerificationEvidence(sMid, sSid, sTid)
|
|
778
|
+
.map((row) => ({
|
|
779
|
+
command: row.command,
|
|
780
|
+
exitCode: row.exit_code,
|
|
781
|
+
verdict: row.verdict,
|
|
782
|
+
}))
|
|
783
|
+
.filter((row) => typeof row.command === "string" && row.command.trim().length > 0);
|
|
784
|
+
const mismatches = crossReferenceEvidence(claimedEvidence, actual);
|
|
785
|
+
for (const mismatch of mismatches) {
|
|
786
|
+
const logMessage = `evidence-xref: ${mismatch.reason}`;
|
|
787
|
+
if (mismatch.severity === "error") {
|
|
788
|
+
logError("safety", logMessage);
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
logWarning("safety", logMessage);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
if (claimedEvidence.length > 0 && bashCalls.length === 0) {
|
|
795
|
+
logWarning("safety", "task claimed verification command evidence but no execution tool calls were recorded");
|
|
796
|
+
ctx.ui.notify(`Safety: task ${sTid} claimed command evidence but no execution tool calls were recorded`, "warning");
|
|
797
|
+
}
|
|
798
|
+
const blockingMismatch = mismatches.find((mismatch) => mismatch.severity === "error");
|
|
799
|
+
if (blockingMismatch) {
|
|
800
|
+
ctx.ui.notify(`Safety: task ${sTid} claimed passing verification that failed in recorded execution`, "error");
|
|
801
|
+
await pauseAuto(ctx, pi);
|
|
802
|
+
return "dispatched";
|
|
803
|
+
}
|
|
765
804
|
}
|
|
766
805
|
}
|
|
767
806
|
}
|
|
@@ -992,6 +1031,12 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
992
1031
|
export async function postUnitPostVerification(pctx) {
|
|
993
1032
|
const { s, ctx, pi, buildSnapshotOpts, lockBase, stopAuto, pauseAuto, updateProgressWidget } = pctx;
|
|
994
1033
|
if (s.currentUnit) {
|
|
1034
|
+
if (shouldDeferCloseoutGitAction(s.currentUnit.type)) {
|
|
1035
|
+
const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit);
|
|
1036
|
+
if (gitActionResult === "dispatched") {
|
|
1037
|
+
return "stopped";
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
995
1040
|
try {
|
|
996
1041
|
const codebasePrefs = loadEffectiveGSDPreferences()?.preferences?.codebase;
|
|
997
1042
|
const refresh = ensureCodebaseMapFresh(s.basePath, codebasePrefs
|
|
@@ -728,12 +728,20 @@ export async function inlineDecisionsFromDb(base, milestoneId, scope, level) {
|
|
|
728
728
|
try {
|
|
729
729
|
const { isDbAvailable } = await import("./gsd-db.js");
|
|
730
730
|
if (isDbAvailable()) {
|
|
731
|
-
|
|
731
|
+
// ADR-013 Phase 6 cutover (Stage 1): read decisions from the `memories`
|
|
732
|
+
// table. Both `queryDecisions` (legacy) and `queryDecisionsFromMemories`
|
|
733
|
+
// return identical Decision[] for active rows once Phase 5 dual-write is
|
|
734
|
+
// caught up. Switching the read here lets the destructive Phase 6 step
|
|
735
|
+
// (#5755) retire the legacy `decisions` table without changing prompt
|
|
736
|
+
// contents. Projection regen (`DECISIONS.md`) still sources from the
|
|
737
|
+
// legacy table — that switch lands separately to handle superseded
|
|
738
|
+
// history cleanly.
|
|
739
|
+
const { queryDecisionsFromMemories, formatDecisionsForPrompt } = await import("./context-store.js");
|
|
732
740
|
// First query: try with both milestoneId and scope (if scope provided)
|
|
733
|
-
let decisions =
|
|
741
|
+
let decisions = queryDecisionsFromMemories({ milestoneId, scope });
|
|
734
742
|
// Cascade: if empty AND scope was provided, retry without scope
|
|
735
743
|
if (decisions.length === 0 && scope) {
|
|
736
|
-
decisions =
|
|
744
|
+
decisions = queryDecisionsFromMemories({ milestoneId });
|
|
737
745
|
}
|
|
738
746
|
if (decisions.length > 0) {
|
|
739
747
|
// Use compact format for non-full levels to save ~35% tokens
|
|
@@ -2769,7 +2777,7 @@ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, b
|
|
|
2769
2777
|
subagentSections.push([
|
|
2770
2778
|
`### ${slice.id}: ${slice.title}`,
|
|
2771
2779
|
"",
|
|
2772
|
-
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`
|
|
2780
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`scout\`):`,
|
|
2773
2781
|
"",
|
|
2774
2782
|
"```",
|
|
2775
2783
|
slicePrompt,
|
|
@@ -2838,7 +2846,7 @@ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base,
|
|
|
2838
2846
|
subagentSections.push([
|
|
2839
2847
|
`### ${def.id}: ${def.question}`,
|
|
2840
2848
|
"",
|
|
2841
|
-
`Use this as the prompt for a \`subagent\` call${modelSuffix}:`,
|
|
2849
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`tester\`):`,
|
|
2842
2850
|
"",
|
|
2843
2851
|
"```",
|
|
2844
2852
|
subPrompt,
|
|
@@ -18,9 +18,7 @@ import { join } from "node:path";
|
|
|
18
18
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
19
19
|
import { UokGateRunner } from "./uok/gate-runner.js";
|
|
20
20
|
import { verificationRetryKey } from "./auto/verification-retry-policy.js";
|
|
21
|
-
|
|
22
|
-
return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(stderr);
|
|
23
|
-
}
|
|
21
|
+
import { decideVerificationVerdict } from "./verification-verdict.js";
|
|
24
22
|
/**
|
|
25
23
|
* Post-unit guard for `validate-milestone` units (#4094).
|
|
26
24
|
*
|
|
@@ -128,7 +126,7 @@ async function countIncompleteSlices(basePath, milestoneId) {
|
|
|
128
126
|
/**
|
|
129
127
|
* Run the verification gate for the current execute-task unit.
|
|
130
128
|
* Returns:
|
|
131
|
-
* - "continue" —
|
|
129
|
+
* - "continue" — host-owned verification passed, proceed normally
|
|
132
130
|
* - "retry" — gate failed with retries remaining, s.pendingVerificationRetry set for loop re-iteration
|
|
133
131
|
* - "pause" — gate failed with retries exhausted, pauseAuto already called
|
|
134
132
|
*/
|
|
@@ -178,6 +176,10 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
178
176
|
process.stderr.write(` [${w.severity}] ${w.name}: ${w.title}\n`);
|
|
179
177
|
}
|
|
180
178
|
}
|
|
179
|
+
const verdict = decideVerificationVerdict(s.currentUnit.type, result);
|
|
180
|
+
if (!verdict.passed) {
|
|
181
|
+
result.passed = false;
|
|
182
|
+
}
|
|
181
183
|
if (uokFlags.gates) {
|
|
182
184
|
const gateRunner = new UokGateRunner();
|
|
183
185
|
gateRunner.register({
|
|
@@ -190,10 +192,12 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
190
192
|
: "verification",
|
|
191
193
|
rationale: result.passed
|
|
192
194
|
? "verification checks passed"
|
|
193
|
-
:
|
|
195
|
+
: verdict.reason === "no-host-checks"
|
|
196
|
+
? "no runnable host-owned verification checks discovered"
|
|
197
|
+
: "verification checks failed",
|
|
194
198
|
findings: result.passed
|
|
195
199
|
? ""
|
|
196
|
-
: formatFailureContext(result),
|
|
200
|
+
: verdict.failureContext || formatFailureContext(result),
|
|
197
201
|
}),
|
|
198
202
|
});
|
|
199
203
|
await gateRunner.run("verification-gate", {
|
|
@@ -251,7 +255,11 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
251
255
|
}
|
|
252
256
|
else {
|
|
253
257
|
const nextAttempt = attempt + 1;
|
|
254
|
-
|
|
258
|
+
const includeRetryMetadata = !result.passed &&
|
|
259
|
+
verdict.retryable &&
|
|
260
|
+
autoFixEnabled &&
|
|
261
|
+
nextAttempt <= maxRetries;
|
|
262
|
+
writeVerificationJSON(result, tasksDir, tid, s.currentUnit.id, includeRetryMetadata ? nextAttempt : undefined, includeRetryMetadata ? maxRetries : undefined);
|
|
255
263
|
}
|
|
256
264
|
}
|
|
257
265
|
}
|
|
@@ -259,18 +267,6 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
259
267
|
logWarning("engine", `verification-evidence write error: ${evidenceErr.message}`);
|
|
260
268
|
}
|
|
261
269
|
}
|
|
262
|
-
const advisoryFailure = !result.passed &&
|
|
263
|
-
(result.discoverySource === "package-json" ||
|
|
264
|
-
result.checks.some((check) => isInfraVerificationFailure(check.stderr)));
|
|
265
|
-
if (advisoryFailure) {
|
|
266
|
-
s.verificationRetryCount.delete(retryKey);
|
|
267
|
-
s.verificationRetryFailureHashes.delete(retryKey);
|
|
268
|
-
s.pendingVerificationRetry = null;
|
|
269
|
-
ctx.ui.notify(result.discoverySource === "package-json"
|
|
270
|
-
? "Verification failed in auto-discovered package.json checks — treating as advisory."
|
|
271
|
-
: "Verification failed due to infrastructure/runtime environment issues — treating as advisory.", "warning");
|
|
272
|
-
return "continue";
|
|
273
|
-
}
|
|
274
270
|
// ── Post-execution checks (run after main verification passes for execute-task units) ──
|
|
275
271
|
let postExecChecks;
|
|
276
272
|
let postExecBlockingFailure = false;
|
|
@@ -430,6 +426,15 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
430
426
|
s.pendingVerificationRetry = null;
|
|
431
427
|
return "continue";
|
|
432
428
|
}
|
|
429
|
+
else if (verdict.reason === "no-host-checks") {
|
|
430
|
+
s.verificationRetryCount.delete(retryKey);
|
|
431
|
+
s.verificationRetryFailureHashes.delete(retryKey);
|
|
432
|
+
s.pendingVerificationRetry = null;
|
|
433
|
+
ctx.ui.notify("Verification gate FAILED — no runnable host-owned verification checks were discovered. Pausing for human review.", "error");
|
|
434
|
+
process.stderr.write(`verification-gate: ${verdict.failureContext}\n`);
|
|
435
|
+
await pauseAuto(ctx, pi);
|
|
436
|
+
return "pause";
|
|
437
|
+
}
|
|
433
438
|
else if (postExecBlockingFailure) {
|
|
434
439
|
// Post-execution failures are cross-task consistency issues — retrying the same task won't fix them.
|
|
435
440
|
// Skip retry and pause immediately for human review.
|
|
@@ -445,7 +450,7 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
445
450
|
s.verificationRetryCount.set(retryKey, nextAttempt);
|
|
446
451
|
s.pendingVerificationRetry = {
|
|
447
452
|
unitId: s.currentUnit.id,
|
|
448
|
-
failureContext: formatFailureContext(result),
|
|
453
|
+
failureContext: verdict.failureContext || formatFailureContext(result),
|
|
449
454
|
attempt: nextAttempt,
|
|
450
455
|
};
|
|
451
456
|
const failedCmds = result.checks
|
|
@@ -475,9 +480,10 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
475
480
|
}
|
|
476
481
|
}
|
|
477
482
|
catch (err) {
|
|
478
|
-
// Gate errors are non-fatal
|
|
479
483
|
logWarning("engine", `verification-gate error: ${err.message}`);
|
|
480
|
-
|
|
484
|
+
ctx.ui.notify(`Verification gate errored before producing an authoritative verdict: ${err.message}`, "error");
|
|
485
|
+
await pauseAuto(ctx, pi);
|
|
486
|
+
return "pause";
|
|
481
487
|
}
|
|
482
488
|
}
|
|
483
489
|
/**
|