gsd-pi 2.74.0-dev.b741afb → 2.74.0-dev.ffbcc03
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/dist/resources/extensions/gsd/activity-log.js +16 -0
- package/dist/resources/extensions/gsd/auto/loop.js +147 -10
- package/dist/resources/extensions/gsd/auto/phases.js +113 -3
- package/dist/resources/extensions/gsd/auto/session.js +10 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +51 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +215 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +24 -10
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
- package/dist/resources/extensions/gsd/auto-verification.js +100 -2
- package/dist/resources/extensions/gsd/auto.js +28 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +10 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +61 -9
- package/dist/resources/extensions/gsd/cache.js +16 -5
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +14 -1
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +144 -0
- package/dist/resources/extensions/gsd/ecosystem/loader.js +145 -0
- package/dist/resources/extensions/gsd/git-service.js +49 -1
- package/dist/resources/extensions/gsd/graph-context.js +98 -7
- package/dist/resources/extensions/gsd/gsd-db.js +260 -2
- package/dist/resources/extensions/gsd/guided-flow.js +24 -1
- package/dist/resources/extensions/gsd/init-wizard.js +1 -0
- package/dist/resources/extensions/gsd/journal.js +27 -0
- package/dist/resources/extensions/gsd/metrics.js +19 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
- package/dist/resources/extensions/gsd/preferences-models.js +20 -3
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +108 -2
- package/dist/resources/extensions/gsd/preferences.js +26 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +15 -30
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +5 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
- package/dist/resources/extensions/gsd/unit-ownership.js +1 -1
- package/dist/resources/extensions/gsd/uok/audit-toggle.js +7 -0
- package/dist/resources/extensions/gsd/uok/audit.js +40 -0
- package/dist/resources/extensions/gsd/uok/contracts.js +1 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +179 -0
- package/dist/resources/extensions/gsd/uok/flags.js +29 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +109 -0
- package/dist/resources/extensions/gsd/uok/gitops.js +53 -0
- package/dist/resources/extensions/gsd/uok/kernel.js +80 -0
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +133 -0
- package/dist/resources/extensions/gsd/uok/model-policy.js +66 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +132 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +22 -0
- package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
- 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 +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- 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/package.json +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -1
- package/packages/mcp-server/dist/readers/graph.js +107 -0
- package/packages/mcp-server/dist/readers/graph.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +88 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/readers/graph.test.ts +178 -0
- package/packages/mcp-server/src/readers/graph.ts +148 -1
- package/packages/mcp-server/src/workflow-tools.ts +95 -10
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -9
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -9
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts +19 -0
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/capability-patches.js +36 -0
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -0
- package/packages/pi-ai/dist/{models.custom.d.ts → models/custom.d.ts} +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -0
- package/packages/pi-ai/dist/{models.custom.js → models/custom.js} +4 -4
- package/packages/pi-ai/dist/models/custom.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts +1482 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.js +1484 -0
- package/packages/pi-ai/dist/models/generated/amazon-bedrock.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/anthropic.d.ts +377 -0
- package/packages/pi-ai/dist/models/generated/anthropic.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/anthropic.js +379 -0
- package/packages/pi-ai/dist/models/generated/anthropic.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts +700 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.js +702 -0
- package/packages/pi-ai/dist/models/generated/azure-openai-responses.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/cerebras.d.ts +71 -0
- package/packages/pi-ai/dist/models/generated/cerebras.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/cerebras.js +73 -0
- package/packages/pi-ai/dist/models/generated/cerebras.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.d.ts +590 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.js +444 -0
- package/packages/pi-ai/dist/models/generated/github-copilot.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts +156 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.js +158 -0
- package/packages/pi-ai/dist/models/generated/google-antigravity.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.js +107 -0
- package/packages/pi-ai/dist/models/generated/google-gemini-cli.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.d.ts +207 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.js +209 -0
- package/packages/pi-ai/dist/models/generated/google-vertex.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/google.d.ts +462 -0
- package/packages/pi-ai/dist/models/generated/google.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/google.js +464 -0
- package/packages/pi-ai/dist/models/generated/google.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/groq.d.ts +309 -0
- package/packages/pi-ai/dist/models/generated/groq.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/groq.js +311 -0
- package/packages/pi-ai/dist/models/generated/groq.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/huggingface.d.ts +383 -0
- package/packages/pi-ai/dist/models/generated/huggingface.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/huggingface.js +347 -0
- package/packages/pi-ai/dist/models/generated/huggingface.js.map +1 -0
- package/packages/pi-ai/dist/{models.generated.d.ts → models/generated/index.d.ts} +1 -1
- package/packages/pi-ai/dist/{models.generated.d.ts.map → models/generated/index.d.ts.map} +1 -1
- package/packages/pi-ai/dist/models/generated/index.js +51 -0
- package/packages/pi-ai/dist/models/generated/index.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts +37 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.js +39 -0
- package/packages/pi-ai/dist/models/generated/kimi-coding.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.js +107 -0
- package/packages/pi-ai/dist/models/generated/minimax-cn.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax.d.ts +105 -0
- package/packages/pi-ai/dist/models/generated/minimax.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/minimax.js +107 -0
- package/packages/pi-ai/dist/models/generated/minimax.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/mistral.d.ts +445 -0
- package/packages/pi-ai/dist/models/generated/mistral.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/mistral.js +447 -0
- package/packages/pi-ai/dist/models/generated/mistral.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +139 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js +141 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts +700 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openai.js +702 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.d.ts +122 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.js +124 -0
- package/packages/pi-ai/dist/models/generated/opencode-go.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode.d.ts +530 -0
- package/packages/pi-ai/dist/models/generated/opencode.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/opencode.js +532 -0
- package/packages/pi-ai/dist/models/generated/opencode.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/openrouter.d.ts +4270 -0
- package/packages/pi-ai/dist/models/generated/openrouter.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/openrouter.js +4272 -0
- package/packages/pi-ai/dist/models/generated/openrouter.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts +2604 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js +2606 -0
- package/packages/pi-ai/dist/models/generated/vercel-ai-gateway.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/xai.d.ts +411 -0
- package/packages/pi-ai/dist/models/generated/xai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/xai.js +413 -0
- package/packages/pi-ai/dist/models/generated/xai.js.map +1 -0
- package/packages/pi-ai/dist/models/generated/zai.d.ts +276 -0
- package/packages/pi-ai/dist/models/generated/zai.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/generated/zai.js +239 -0
- package/packages/pi-ai/dist/models/generated/zai.js.map +1 -0
- package/packages/pi-ai/dist/models/index.d.ts +27 -0
- package/packages/pi-ai/dist/models/index.d.ts.map +1 -0
- package/packages/pi-ai/dist/models/index.js +80 -0
- package/packages/pi-ai/dist/models/index.js.map +1 -0
- package/packages/pi-ai/dist/models.d.ts +1 -36
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +1 -2
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.js +3 -112
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +6 -5
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +74 -40
- package/packages/pi-ai/src/index.ts +1 -9
- package/packages/pi-ai/src/models/capability-patches.ts +40 -0
- package/packages/pi-ai/src/{models.custom.ts → models/custom.ts} +4 -4
- package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1486 -0
- package/packages/pi-ai/src/models/generated/anthropic.ts +381 -0
- package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
- package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
- package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
- package/packages/pi-ai/src/models/generated/google-antigravity.ts +160 -0
- package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
- package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
- package/packages/pi-ai/src/models/generated/google.ts +466 -0
- package/packages/pi-ai/src/models/generated/groq.ts +313 -0
- package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
- package/packages/pi-ai/src/models/generated/index.ts +52 -0
- package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
- package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
- package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
- package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
- package/packages/pi-ai/src/models/generated/openai-codex.ts +143 -0
- package/packages/pi-ai/src/models/generated/openai.ts +704 -0
- package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
- package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
- package/packages/pi-ai/src/models/generated/openrouter.ts +4274 -0
- package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
- package/packages/pi-ai/src/models/generated/xai.ts +415 -0
- package/packages/pi-ai/src/models/generated/zai.ts +241 -0
- package/packages/pi-ai/src/models/index.ts +106 -0
- package/packages/pi-ai/src/models.generated.test.ts +1 -2
- package/packages/pi-ai/src/models.test.ts +6 -5
- package/packages/pi-ai/src/models.ts +3 -153
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +8 -2
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +472 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js +52 -0
- package/packages/pi-coding-agent/dist/core/model-registry-env-fallback.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +23 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +47 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +8 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +68 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +22 -22
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +232 -18
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +38 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -6
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +12 -6
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +612 -0
- package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +2 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +25 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +67 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +83 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +23 -26
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +298 -41
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +44 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +92 -6
- package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
- package/packages/pi-coding-agent/tsconfig.json +2 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/activity-log.ts +21 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +4 -0
- package/src/resources/extensions/gsd/auto/loop.ts +159 -10
- package/src/resources/extensions/gsd/auto/phases.ts +123 -3
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -6
- package/src/resources/extensions/gsd/auto-model-selection.ts +66 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +226 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -9
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
- package/src/resources/extensions/gsd/auto-verification.ts +129 -2
- package/src/resources/extensions/gsd/auto.ts +34 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +72 -8
- package/src/resources/extensions/gsd/cache.ts +16 -5
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +14 -1
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +228 -0
- package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
- package/src/resources/extensions/gsd/git-service.ts +68 -0
- package/src/resources/extensions/gsd/graph-context.ts +139 -12
- package/src/resources/extensions/gsd/gsd-db.ts +321 -3
- package/src/resources/extensions/gsd/guided-flow.ts +33 -1
- package/src/resources/extensions/gsd/init-wizard.ts +3 -2
- package/src/resources/extensions/gsd/journal.ts +30 -0
- package/src/resources/extensions/gsd/metrics.ts +26 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
- package/src/resources/extensions/gsd/preferences-models.ts +20 -3
- package/src/resources/extensions/gsd/preferences-types.ts +32 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +107 -2
- package/src/resources/extensions/gsd/preferences.ts +28 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +15 -31
- package/src/resources/extensions/gsd/session-lock.ts +14 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +20 -1
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -2
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -5
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/uok-flags.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +9 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
- package/src/resources/extensions/gsd/types.ts +14 -1
- package/src/resources/extensions/gsd/unit-ownership.ts +2 -2
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
- package/src/resources/extensions/gsd/uok/audit.ts +51 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +135 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +241 -0
- package/src/resources/extensions/gsd/uok/flags.ts +45 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +146 -0
- package/src/resources/extensions/gsd/uok/gitops.ts +75 -0
- package/src/resources/extensions/gsd/uok/kernel.ts +105 -0
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +162 -0
- package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +156 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +27 -1
- package/src/resources/extensions/ttsr/ttsr-manager.ts +10 -5
- package/packages/pi-ai/dist/models.custom.d.ts.map +0 -1
- package/packages/pi-ai/dist/models.custom.js.map +0 -1
- package/packages/pi-ai/dist/models.generated.js +0 -14343
- package/packages/pi-ai/dist/models.generated.js.map +0 -1
- package/packages/pi-ai/src/models.generated.ts +0 -14345
- /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{XnHY5eXUsTCFmNodWHetD → kn6xzWKYnogsxp2b6RpDD}/_ssgManifest.js +0 -0
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* and fallback chains.
|
|
5
5
|
*/
|
|
6
6
|
import { resolveModelWithFallbacksForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
|
|
7
|
-
import { classifyUnitComplexity, tierLabel } from "./complexity-classifier.js";
|
|
7
|
+
import { classifyUnitComplexity, extractTaskMetadata, tierLabel } from "./complexity-classifier.js";
|
|
8
8
|
import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides, adjustToolSet } from "./model-router.js";
|
|
9
9
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
10
10
|
import { unitPhaseLabel } from "./auto-dashboard.js";
|
|
11
11
|
import { getSessionModelOverride } from "./session-model-override.js";
|
|
12
12
|
import { logWarning } from "./workflow-logger.js";
|
|
13
|
+
import { resolveUokFlags } from "./uok/flags.js";
|
|
14
|
+
import { applyModelPolicyFilter } from "./uok/model-policy.js";
|
|
13
15
|
export function resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode = true) {
|
|
14
16
|
const explicitConfig = resolveModelWithFallbacksForUnit(unitType);
|
|
15
17
|
if (explicitConfig)
|
|
@@ -46,6 +48,7 @@ export async function selectAndApplyModel(ctx, pi, unitType, unitId, basePath, p
|
|
|
46
48
|
isAutoMode = true,
|
|
47
49
|
/** Explicit /gsd model pin captured at bootstrap for long-running auto loops. */
|
|
48
50
|
sessionModelOverride) {
|
|
51
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
49
52
|
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
50
53
|
? getSessionModelOverride(ctx.sessionManager.getSessionId())
|
|
51
54
|
: (sessionModelOverride ?? undefined);
|
|
@@ -67,6 +70,9 @@ sessionModelOverride) {
|
|
|
67
70
|
let appliedModel = null;
|
|
68
71
|
if (modelConfig) {
|
|
69
72
|
const availableModels = ctx.modelRegistry.getAvailable();
|
|
73
|
+
const modelPolicyTraceId = `model:${ctx.sessionManager.getSessionId()}:${Date.now()}`;
|
|
74
|
+
const modelPolicyTurnId = `${unitType}:${unitId}`;
|
|
75
|
+
let policyAllowedModelKeys = null;
|
|
70
76
|
// ─── Dynamic Model Routing ─────────────────────────────────────────
|
|
71
77
|
// Dynamic routing (complexity-based downgrading) only applies in auto-mode.
|
|
72
78
|
// Interactive/guided-flow dispatches use the user's session model directly,
|
|
@@ -75,15 +81,40 @@ sessionModelOverride) {
|
|
|
75
81
|
if (!isAutoMode) {
|
|
76
82
|
routingConfig.enabled = false;
|
|
77
83
|
}
|
|
84
|
+
// burn-max defaults to quality-first dispatch (no downgrade routing).
|
|
85
|
+
if (prefs?.token_profile === "burn-max") {
|
|
86
|
+
routingConfig.enabled = false;
|
|
87
|
+
}
|
|
78
88
|
let effectiveModelConfig = modelConfig;
|
|
79
89
|
let routingTierLabel = "";
|
|
90
|
+
let routingEligibleModels = availableModels;
|
|
91
|
+
const taskMetadataForPolicy = unitType === "execute-task"
|
|
92
|
+
? extractTaskMetadata(unitId, basePath)
|
|
93
|
+
: undefined;
|
|
94
|
+
if (uokFlags.modelPolicy) {
|
|
95
|
+
const policy = applyModelPolicyFilter(availableModels, {
|
|
96
|
+
basePath,
|
|
97
|
+
traceId: modelPolicyTraceId,
|
|
98
|
+
turnId: modelPolicyTurnId,
|
|
99
|
+
unitType,
|
|
100
|
+
taskMetadata: taskMetadataForPolicy,
|
|
101
|
+
currentProvider: ctx.model?.provider,
|
|
102
|
+
allowCrossProvider: routingConfig.cross_provider !== false,
|
|
103
|
+
requiredTools: pi.getActiveTools(),
|
|
104
|
+
});
|
|
105
|
+
routingEligibleModels = policy.eligible;
|
|
106
|
+
policyAllowedModelKeys = new Set(policy.eligible.map((m) => `${m.provider.toLowerCase()}/${m.id.toLowerCase()}`));
|
|
107
|
+
if (routingEligibleModels.length === 0) {
|
|
108
|
+
throw new Error(`Model policy denied all candidate models for ${unitType}/${unitId}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
80
111
|
// Disable routing for flat-rate providers like GitHub Copilot (#3453).
|
|
81
112
|
// All models cost the same per request, so downgrading to a cheaper
|
|
82
113
|
// model provides no cost benefit — it only degrades quality.
|
|
83
114
|
// Fail-closed: if primary model can't be resolved, fall back to
|
|
84
115
|
// provider-level signals rather than allowing unwanted downgrades.
|
|
85
116
|
if (routingConfig.enabled) {
|
|
86
|
-
const primaryModel = resolveModelId(modelConfig.primary,
|
|
117
|
+
const primaryModel = resolveModelId(modelConfig.primary, routingEligibleModels, ctx.model?.provider);
|
|
87
118
|
if (primaryModel) {
|
|
88
119
|
const primaryFlatRateCtx = buildFlatRateContext(primaryModel.provider, ctx, prefs);
|
|
89
120
|
if (isFlatRateProvider(primaryModel.provider, primaryFlatRateCtx)) {
|
|
@@ -110,8 +141,8 @@ sessionModelOverride) {
|
|
|
110
141
|
const isHook = unitType.startsWith("hook/");
|
|
111
142
|
const shouldClassify = !isHook || routingConfig.hooks !== false;
|
|
112
143
|
if (shouldClassify) {
|
|
113
|
-
let classification = classifyUnitComplexity(unitType, unitId, basePath, budgetPct);
|
|
114
|
-
const availableModelIds =
|
|
144
|
+
let classification = classifyUnitComplexity(unitType, unitId, basePath, budgetPct, taskMetadataForPolicy);
|
|
145
|
+
const availableModelIds = routingEligibleModels.map(m => m.id);
|
|
115
146
|
// Escalate tier on retry when escalate_on_failure is enabled (default: true)
|
|
116
147
|
if (retryContext?.isRetry &&
|
|
117
148
|
retryContext.previousTier &&
|
|
@@ -191,13 +222,25 @@ sessionModelOverride) {
|
|
|
191
222
|
}
|
|
192
223
|
}
|
|
193
224
|
const modelsToTry = [effectiveModelConfig.primary, ...effectiveModelConfig.fallbacks];
|
|
225
|
+
let attemptedPolicyEligible = false;
|
|
194
226
|
for (const modelId of modelsToTry) {
|
|
195
|
-
const
|
|
227
|
+
const resolutionPool = uokFlags.modelPolicy ? routingEligibleModels : availableModels;
|
|
228
|
+
const model = resolveModelId(modelId, resolutionPool, ctx.model?.provider);
|
|
196
229
|
if (!model) {
|
|
197
230
|
if (verbose)
|
|
198
231
|
ctx.ui.notify(`Model ${modelId} not found, trying fallback.`, "info");
|
|
199
232
|
continue;
|
|
200
233
|
}
|
|
234
|
+
if (policyAllowedModelKeys) {
|
|
235
|
+
const key = `${model.provider.toLowerCase()}/${model.id.toLowerCase()}`;
|
|
236
|
+
if (!policyAllowedModelKeys.has(key)) {
|
|
237
|
+
if (verbose) {
|
|
238
|
+
ctx.ui.notify(`Model policy denied ${model.provider}/${model.id}; trying fallback.`, "warning");
|
|
239
|
+
}
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
attemptedPolicyEligible = true;
|
|
243
|
+
}
|
|
201
244
|
// Warn if the ID is ambiguous across providers
|
|
202
245
|
if (!modelId.includes("/")) {
|
|
203
246
|
const providers = availableModels.filter(m => m.id === modelId).map(m => m.provider);
|
|
@@ -255,6 +298,9 @@ sessionModelOverride) {
|
|
|
255
298
|
}
|
|
256
299
|
}
|
|
257
300
|
}
|
|
301
|
+
if (uokFlags.modelPolicy && policyAllowedModelKeys && !attemptedPolicyEligible) {
|
|
302
|
+
throw new Error(`Model policy denied dispatch for ${unitType}/${unitId} before prompt send`);
|
|
303
|
+
}
|
|
258
304
|
}
|
|
259
305
|
else if (autoModeStartModel) {
|
|
260
306
|
// No model preference for this unit type — re-apply the model captured
|
|
@@ -19,7 +19,7 @@ import { invalidateAllCaches } from "./cache.js";
|
|
|
19
19
|
import { rebuildState } from "./doctor.js";
|
|
20
20
|
import { parseUnitId } from "./unit-id.js";
|
|
21
21
|
import { closeoutUnit } from "./auto-unit-closeout.js";
|
|
22
|
-
import {
|
|
22
|
+
import { runTurnGitAction, } from "./git-service.js";
|
|
23
23
|
import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, } from "./auto-recovery.js";
|
|
24
24
|
import { regenerateIfMissing } from "./workflow-projections.js";
|
|
25
25
|
import { syncStateToProjectRoot } from "./auto-worktree.js";
|
|
@@ -42,6 +42,9 @@ import { getSliceTasks } from "./gsd-db.js";
|
|
|
42
42
|
import { runPreExecutionChecks } from "./pre-execution-checks.js";
|
|
43
43
|
import { writePreExecutionEvidence } from "./verification-evidence.js";
|
|
44
44
|
import { ensureCodebaseMapFresh } from "./codebase-generator.js";
|
|
45
|
+
import { resolveUokFlags } from "./uok/flags.js";
|
|
46
|
+
import { UokGateRunner } from "./uok/gate-runner.js";
|
|
47
|
+
import { writeTurnGitTransaction } from "./uok/gitops.js";
|
|
45
48
|
/** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
|
|
46
49
|
const MAX_VERIFICATION_RETRIES = 3;
|
|
47
50
|
/** Enqueue a sidecar item (hook, triage, or quick-task) for the main loop to
|
|
@@ -71,6 +74,7 @@ import { describeNextUnit, } from "./auto-dashboard.js";
|
|
|
71
74
|
import { existsSync, unlinkSync } from "node:fs";
|
|
72
75
|
import { join } from "node:path";
|
|
73
76
|
import { _resetHasChangesCache } from "./native-git-bridge.js";
|
|
77
|
+
import { autoCommitCurrentBranch } from "./worktree.js";
|
|
74
78
|
/**
|
|
75
79
|
* Detect summary files written directly to disk without the LLM calling
|
|
76
80
|
* the completion tool. A "rogue" file is one that exists on disk but has
|
|
@@ -272,10 +276,154 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
272
276
|
if (!opts?.skipSettleDelay) {
|
|
273
277
|
await new Promise(r => setTimeout(r, 100));
|
|
274
278
|
}
|
|
275
|
-
|
|
279
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
280
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
281
|
+
// Turn-level git action (commit | snapshot | status-only)
|
|
276
282
|
if (s.currentUnit) {
|
|
277
283
|
const unit = s.currentUnit;
|
|
278
|
-
|
|
284
|
+
const turnAction = uokFlags.gitops ? uokFlags.gitopsTurnAction : "commit";
|
|
285
|
+
const traceId = s.currentTraceId ?? `turn:${unit.startedAt}`;
|
|
286
|
+
const turnId = s.currentTurnId ?? `${unit.type}/${unit.id}/${unit.startedAt}`;
|
|
287
|
+
s.lastGitActionFailure = null;
|
|
288
|
+
s.lastGitActionStatus = null;
|
|
289
|
+
try {
|
|
290
|
+
let taskContext;
|
|
291
|
+
if (turnAction === "commit" && s.currentUnit.type === "execute-task") {
|
|
292
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
|
|
293
|
+
if (mid && sid && tid) {
|
|
294
|
+
const summaryPath = resolveTaskFile(s.basePath, mid, sid, tid, "SUMMARY");
|
|
295
|
+
if (summaryPath) {
|
|
296
|
+
try {
|
|
297
|
+
const summaryContent = await loadFile(summaryPath);
|
|
298
|
+
if (summaryContent) {
|
|
299
|
+
const summary = parseSummary(summaryContent);
|
|
300
|
+
// Look up GitHub issue number for commit linking
|
|
301
|
+
let ghIssueNumber;
|
|
302
|
+
try {
|
|
303
|
+
const { getTaskIssueNumberForCommit } = await import("../github-sync/sync.js");
|
|
304
|
+
ghIssueNumber = getTaskIssueNumberForCommit(s.basePath, mid, sid, tid) ?? undefined;
|
|
305
|
+
}
|
|
306
|
+
catch (err) {
|
|
307
|
+
// GitHub sync not available — skip
|
|
308
|
+
logWarning("engine", `GitHub issue lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
309
|
+
}
|
|
310
|
+
taskContext = {
|
|
311
|
+
taskId: `${sid}/${tid}`,
|
|
312
|
+
taskTitle: summary.title?.replace(/^T\d+:\s*/, "") || tid,
|
|
313
|
+
oneLiner: summary.oneLiner || undefined,
|
|
314
|
+
keyFiles: summary.frontmatter.key_files?.filter(f => !f.includes("{{")) || undefined,
|
|
315
|
+
issueNumber: ghIssueNumber,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (e) {
|
|
320
|
+
debugLog("postUnit", { phase: "task-summary-parse", error: String(e) });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Invalidate the nativeHasChanges cache before auto-commit (#1853).
|
|
326
|
+
// The cache has a 10-second TTL and is keyed by basePath. A stale
|
|
327
|
+
// `false` result causes autoCommit to skip staging entirely, leaving
|
|
328
|
+
// code files only in the working tree where they are destroyed by
|
|
329
|
+
// `git worktree remove --force` during teardown.
|
|
330
|
+
_resetHasChangesCache();
|
|
331
|
+
const skipLifecycleCommit = turnAction === "commit" && LIFECYCLE_ONLY_UNITS.has(s.currentUnit.type);
|
|
332
|
+
if (skipLifecycleCommit) {
|
|
333
|
+
debugLog("postUnit", {
|
|
334
|
+
phase: "git-action-skipped",
|
|
335
|
+
reason: "lifecycle-only-unit",
|
|
336
|
+
unitType: s.currentUnit.type,
|
|
337
|
+
unitId: s.currentUnit.id,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
const gitResult = runTurnGitAction({
|
|
342
|
+
basePath: s.basePath,
|
|
343
|
+
action: turnAction,
|
|
344
|
+
unitType: s.currentUnit.type,
|
|
345
|
+
unitId: s.currentUnit.id,
|
|
346
|
+
taskContext,
|
|
347
|
+
});
|
|
348
|
+
if (uokFlags.gitops) {
|
|
349
|
+
writeTurnGitTransaction({
|
|
350
|
+
basePath: s.basePath,
|
|
351
|
+
traceId,
|
|
352
|
+
turnId,
|
|
353
|
+
unitType: unit.type,
|
|
354
|
+
unitId: unit.id,
|
|
355
|
+
stage: "publish",
|
|
356
|
+
action: turnAction,
|
|
357
|
+
push: uokFlags.gitopsTurnPush,
|
|
358
|
+
status: gitResult.status,
|
|
359
|
+
error: gitResult.error,
|
|
360
|
+
metadata: {
|
|
361
|
+
dirty: gitResult.dirty,
|
|
362
|
+
commitMessage: gitResult.commitMessage,
|
|
363
|
+
snapshotLabel: gitResult.snapshotLabel,
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (gitResult.status === "failed") {
|
|
368
|
+
s.lastGitActionFailure = gitResult.error ?? `git ${turnAction} failed`;
|
|
369
|
+
s.lastGitActionStatus = "failed";
|
|
370
|
+
if (uokFlags.gitops && uokFlags.gates) {
|
|
371
|
+
const parsed = parseUnitId(unit.id);
|
|
372
|
+
const gateRunner = new UokGateRunner();
|
|
373
|
+
gateRunner.register({
|
|
374
|
+
id: "closeout-git-action",
|
|
375
|
+
type: "closeout",
|
|
376
|
+
execute: async () => ({
|
|
377
|
+
outcome: "fail",
|
|
378
|
+
failureClass: "git",
|
|
379
|
+
rationale: `turn git action "${turnAction}" failed`,
|
|
380
|
+
findings: gitResult.error ?? "unknown git failure",
|
|
381
|
+
}),
|
|
382
|
+
});
|
|
383
|
+
await gateRunner.run("closeout-git-action", {
|
|
384
|
+
basePath: s.basePath,
|
|
385
|
+
traceId,
|
|
386
|
+
turnId,
|
|
387
|
+
milestoneId: parsed.milestone ?? undefined,
|
|
388
|
+
sliceId: parsed.slice ?? undefined,
|
|
389
|
+
taskId: parsed.task ?? undefined,
|
|
390
|
+
unitType: unit.type,
|
|
391
|
+
unitId: unit.id,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
const failureMsg = `Git ${turnAction} failed: ${(gitResult.error ?? "unknown error").split("\n")[0]}`;
|
|
395
|
+
if (uokFlags.gitops) {
|
|
396
|
+
ctx.ui.notify(failureMsg, "error");
|
|
397
|
+
await pauseAuto(ctx, pi);
|
|
398
|
+
return "dispatched";
|
|
399
|
+
}
|
|
400
|
+
ctx.ui.notify(failureMsg, "warning");
|
|
401
|
+
debugLog("postUnit", {
|
|
402
|
+
phase: "git-action-failed-nonblocking",
|
|
403
|
+
action: turnAction,
|
|
404
|
+
error: gitResult.error ?? "unknown error",
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
s.lastGitActionStatus = "ok";
|
|
408
|
+
if (turnAction === "commit" && gitResult.commitMessage) {
|
|
409
|
+
ctx.ui.notify(`Committed: ${gitResult.commitMessage.split("\n")[0]}`, "info");
|
|
410
|
+
}
|
|
411
|
+
else if (turnAction === "snapshot" && gitResult.snapshotLabel) {
|
|
412
|
+
ctx.ui.notify(`Snapshot recorded: ${gitResult.snapshotLabel}`, "info");
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch (e) {
|
|
417
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
418
|
+
s.lastGitActionFailure = message;
|
|
419
|
+
s.lastGitActionStatus = "failed";
|
|
420
|
+
debugLog("postUnit", { phase: "git-action", error: message, action: turnAction });
|
|
421
|
+
ctx.ui.notify(`Git ${turnAction} failed: ${message.split("\n")[0]}`, uokFlags.gitops ? "error" : "warning");
|
|
422
|
+
if (uokFlags.gitops) {
|
|
423
|
+
await pauseAuto(ctx, pi);
|
|
424
|
+
return "dispatched";
|
|
425
|
+
}
|
|
426
|
+
}
|
|
279
427
|
// GitHub sync (non-blocking, opt-in)
|
|
280
428
|
await runSafely("postUnit", "github-sync", async () => {
|
|
281
429
|
const { runGitHubSync } = await import("../github-sync/sync.js");
|
|
@@ -710,11 +858,13 @@ export async function postUnitPostVerification(pctx) {
|
|
|
710
858
|
// ── Pre-execution checks (after plan-slice completes) ──
|
|
711
859
|
if (s.currentUnit &&
|
|
712
860
|
s.currentUnit.type === "plan-slice") {
|
|
861
|
+
const currentUnit = s.currentUnit;
|
|
713
862
|
let preExecPauseNeeded = false;
|
|
714
863
|
await runSafely("postUnitPostVerification", "pre-execution-checks", async () => {
|
|
864
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
865
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
715
866
|
try {
|
|
716
867
|
// Check preferences — respect enhanced_verification and enhanced_verification_pre
|
|
717
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
718
868
|
const enhancedEnabled = prefs?.enhanced_verification !== false; // default true
|
|
719
869
|
const preEnabled = prefs?.enhanced_verification_pre !== false; // default true
|
|
720
870
|
if (!enhancedEnabled || !preEnabled) {
|
|
@@ -726,7 +876,7 @@ export async function postUnitPostVerification(pctx) {
|
|
|
726
876
|
return;
|
|
727
877
|
}
|
|
728
878
|
// Parse the unit ID to get milestone/slice IDs
|
|
729
|
-
const { milestone: mid, slice: sid } = parseUnitId(
|
|
879
|
+
const { milestone: mid, slice: sid } = parseUnitId(currentUnit.id);
|
|
730
880
|
if (!mid || !sid) {
|
|
731
881
|
debugLog("postUnitPostVerification", {
|
|
732
882
|
phase: "pre-execution-checks",
|
|
@@ -745,6 +895,7 @@ export async function postUnitPostVerification(pctx) {
|
|
|
745
895
|
});
|
|
746
896
|
return;
|
|
747
897
|
}
|
|
898
|
+
const strictMode = prefs?.enhanced_verification_strict === true;
|
|
748
899
|
// Run pre-execution checks
|
|
749
900
|
const result = await runPreExecutionChecks(tasks, s.basePath);
|
|
750
901
|
// Log summary to stderr in existing verification output format
|
|
@@ -760,10 +911,43 @@ export async function postUnitPostVerification(pctx) {
|
|
|
760
911
|
if (slicePath) {
|
|
761
912
|
writePreExecutionEvidence(result, slicePath, mid, sid);
|
|
762
913
|
}
|
|
763
|
-
|
|
914
|
+
if (uokFlags.gates) {
|
|
915
|
+
const failedChecks = result.checks
|
|
916
|
+
.filter((check) => !check.passed)
|
|
917
|
+
.map((check) => `[${check.category}] ${check.target}: ${check.message}`);
|
|
918
|
+
const warnEscalated = result.status === "warn" && strictMode;
|
|
919
|
+
const blockingFailure = result.status === "fail" || warnEscalated;
|
|
920
|
+
const gateRunner = new UokGateRunner();
|
|
921
|
+
gateRunner.register({
|
|
922
|
+
id: "pre-execution-checks",
|
|
923
|
+
type: "input",
|
|
924
|
+
execute: async () => ({
|
|
925
|
+
outcome: blockingFailure ? "fail" : "pass",
|
|
926
|
+
failureClass: result.status === "fail" ? "input" : warnEscalated ? "policy" : "none",
|
|
927
|
+
rationale: blockingFailure
|
|
928
|
+
? `pre-execution checks ${result.status}${warnEscalated ? " (strict)" : ""}`
|
|
929
|
+
: "pre-execution checks passed",
|
|
930
|
+
findings: failedChecks.join("\n"),
|
|
931
|
+
}),
|
|
932
|
+
});
|
|
933
|
+
await gateRunner.run("pre-execution-checks", {
|
|
934
|
+
basePath: s.basePath,
|
|
935
|
+
traceId: `pre-execution:${currentUnit.id}`,
|
|
936
|
+
turnId: currentUnit.id,
|
|
937
|
+
milestoneId: mid,
|
|
938
|
+
sliceId: sid,
|
|
939
|
+
unitType: currentUnit.type,
|
|
940
|
+
unitId: currentUnit.id,
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
// Notify UI — surface actionable details (#4259)
|
|
764
944
|
if (result.status === "fail") {
|
|
765
|
-
const
|
|
766
|
-
|
|
945
|
+
const blockingChecks = result.checks.filter(c => !c.passed && c.blocking);
|
|
946
|
+
const blockingCount = blockingChecks.length;
|
|
947
|
+
const details = blockingChecks.slice(0, 3).map(c => ` \u2022 ${c.message}`).join("\n");
|
|
948
|
+
const suffix = blockingChecks.length > 3 ? `\n \u2022 ...and ${blockingChecks.length - 3} more` : "";
|
|
949
|
+
const evidenceNote = `\nSee ${sid}-PRE-EXEC-VERIFY.json for full details.`;
|
|
950
|
+
ctx.ui.notify(`Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found\n${details}${suffix}${evidenceNote}`, "error");
|
|
767
951
|
preExecPauseNeeded = true;
|
|
768
952
|
}
|
|
769
953
|
else if (result.status === "warn") {
|
|
@@ -790,6 +974,29 @@ export async function postUnitPostVerification(pctx) {
|
|
|
790
974
|
});
|
|
791
975
|
logError("engine", `gsd-pre-exec: Pre-execution checks threw an error: ${errorMessage}`);
|
|
792
976
|
ctx.ui.notify(`Pre-execution checks error: ${errorMessage} — pausing for human review`, "error");
|
|
977
|
+
if (uokFlags.gates && s.currentUnit) {
|
|
978
|
+
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
|
|
979
|
+
const gateRunner = new UokGateRunner();
|
|
980
|
+
gateRunner.register({
|
|
981
|
+
id: "pre-execution-checks",
|
|
982
|
+
type: "input",
|
|
983
|
+
execute: async () => ({
|
|
984
|
+
outcome: "manual-attention",
|
|
985
|
+
failureClass: "manual-attention",
|
|
986
|
+
rationale: "pre-execution checks threw before completion",
|
|
987
|
+
findings: errorMessage,
|
|
988
|
+
}),
|
|
989
|
+
});
|
|
990
|
+
await gateRunner.run("pre-execution-checks", {
|
|
991
|
+
basePath: s.basePath,
|
|
992
|
+
traceId: `pre-execution:${s.currentUnit.id}`,
|
|
993
|
+
turnId: s.currentUnit.id,
|
|
994
|
+
milestoneId: mid ?? undefined,
|
|
995
|
+
sliceId: sid ?? undefined,
|
|
996
|
+
unitType: s.currentUnit.type,
|
|
997
|
+
unitId: s.currentUnit.id,
|
|
998
|
+
});
|
|
999
|
+
}
|
|
793
1000
|
preExecPauseNeeded = true;
|
|
794
1001
|
}
|
|
795
1002
|
});
|
|
@@ -215,20 +215,28 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
215
215
|
const absPath = resolveExpectedArtifactPath(unitType, unitId, base);
|
|
216
216
|
// For unit types with no verifiable artifact (null path), the parent directory
|
|
217
217
|
// is missing on disk — treat as stale completion state so the key gets evicted (#313).
|
|
218
|
-
if (!absPath)
|
|
218
|
+
if (!absPath) {
|
|
219
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: resolveExpectedArtifactPath returned null (parent dir missing)`);
|
|
219
220
|
return false;
|
|
220
|
-
|
|
221
|
+
}
|
|
222
|
+
if (!existsSync(absPath)) {
|
|
223
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: existsSync false for ${absPath}`);
|
|
221
224
|
return false;
|
|
225
|
+
}
|
|
222
226
|
if (unitType === "validate-milestone") {
|
|
223
227
|
const validationContent = readFileSync(absPath, "utf-8");
|
|
224
|
-
if (!isValidationTerminal(validationContent))
|
|
228
|
+
if (!isValidationTerminal(validationContent)) {
|
|
229
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: validation not terminal (len=${validationContent.length}) at ${absPath}`);
|
|
225
230
|
return false;
|
|
231
|
+
}
|
|
226
232
|
}
|
|
227
233
|
if (unitType === "plan-milestone") {
|
|
228
234
|
try {
|
|
229
235
|
const roadmap = parseLegacyRoadmap(readFileSync(absPath, "utf-8"));
|
|
230
|
-
if (roadmap.slices.length === 0)
|
|
236
|
+
if (roadmap.slices.length === 0) {
|
|
237
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap has zero slices at ${absPath}`);
|
|
231
238
|
return false;
|
|
239
|
+
}
|
|
232
240
|
}
|
|
233
241
|
catch (err) {
|
|
234
242
|
logWarning("recovery", `plan-milestone roadmap verification failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -245,8 +253,10 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
245
253
|
// Accept checkbox-style (- [x] **T01: ...) or heading-style (### T01 -- / ### T01: / ### T01 —)
|
|
246
254
|
const hasCheckboxTask = /^- \[[xX ]\] \*\*T\d+:/m.test(planContent);
|
|
247
255
|
const hasHeadingTask = /^#{2,4}\s+T\d+\s*(?:--|—|:)/m.test(planContent);
|
|
248
|
-
if (!hasCheckboxTask && !hasHeadingTask)
|
|
256
|
+
if (!hasCheckboxTask && !hasHeadingTask) {
|
|
257
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: plan has no task checkbox/heading (len=${planContent.length}) at ${absPath}`);
|
|
249
258
|
return false;
|
|
259
|
+
}
|
|
250
260
|
}
|
|
251
261
|
// execute-task: DB status is authoritative. Fall back to checked-checkbox
|
|
252
262
|
// detection when the DB is unavailable (unmigrated projects).
|
|
@@ -306,11 +316,15 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
306
316
|
}
|
|
307
317
|
if (taskIds && taskIds.length > 0) {
|
|
308
318
|
const tasksDir = resolveTasksDir(base, mid, sid);
|
|
309
|
-
if (tasksDir) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
319
|
+
if (!tasksDir) {
|
|
320
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: resolveTasksDir returned null for ${mid}/${sid}`);
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
for (const tid of taskIds) {
|
|
324
|
+
const taskPlanFile = join(tasksDir, `${tid}-PLAN.md`);
|
|
325
|
+
if (!existsSync(taskPlanFile)) {
|
|
326
|
+
logWarning("recovery", `verify-fail ${unitType} ${unitId}: task plan missing ${taskPlanFile}`);
|
|
327
|
+
return false;
|
|
314
328
|
}
|
|
315
329
|
}
|
|
316
330
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { snapshotUnitMetrics } from "./metrics.js";
|
|
7
7
|
import { saveActivityLog } from "./activity-log.js";
|
|
8
8
|
import { logWarning } from "./workflow-logger.js";
|
|
9
|
+
import { writeTurnGitTransaction } from "./uok/gitops.js";
|
|
9
10
|
/**
|
|
10
11
|
* Snapshot metrics, save activity log, and fire-and-forget memory extraction
|
|
11
12
|
* for a completed unit. Returns the activity log file path (if any).
|
|
@@ -28,5 +29,22 @@ export async function closeoutUnit(ctx, basePath, unitType, unitId, startedAt, o
|
|
|
28
29
|
logWarning("engine", `operation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
29
30
|
}
|
|
30
31
|
}
|
|
32
|
+
if (opts?.traceId && opts.turnId && opts.gitAction && opts.gitStatus) {
|
|
33
|
+
writeTurnGitTransaction({
|
|
34
|
+
basePath,
|
|
35
|
+
traceId: opts.traceId,
|
|
36
|
+
turnId: opts.turnId,
|
|
37
|
+
unitType,
|
|
38
|
+
unitId,
|
|
39
|
+
stage: "record",
|
|
40
|
+
action: opts.gitAction,
|
|
41
|
+
push: opts.gitPush === true,
|
|
42
|
+
status: opts.gitStatus,
|
|
43
|
+
error: opts.gitError,
|
|
44
|
+
metadata: {
|
|
45
|
+
activityFile,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
31
49
|
return activityFile ?? undefined;
|
|
32
50
|
}
|
|
@@ -24,6 +24,8 @@ import { writeVerificationJSON } from "./verification-evidence.js";
|
|
|
24
24
|
import { logWarning } from "./workflow-logger.js";
|
|
25
25
|
import { runPostExecutionChecks } from "./post-execution-checks.js";
|
|
26
26
|
import { join } from "node:path";
|
|
27
|
+
import { resolveUokFlags } from "./uok/flags.js";
|
|
28
|
+
import { UokGateRunner } from "./uok/gate-runner.js";
|
|
27
29
|
function isInfraVerificationFailure(stderr) {
|
|
28
30
|
return /\b(ENOENT|ENOTFOUND|ETIMEDOUT|ECONNRESET|EAI_AGAIN|spawn\s+\S+\s+ENOENT|command not found)\b/i.test(stderr);
|
|
29
31
|
}
|
|
@@ -43,6 +45,31 @@ function isInfraVerificationFailure(stderr) {
|
|
|
43
45
|
*/
|
|
44
46
|
async function runValidateMilestonePostCheck(vctx, pauseAuto) {
|
|
45
47
|
const { s, ctx, pi } = vctx;
|
|
48
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
49
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
50
|
+
const persistMilestoneValidationGate = async (outcome, failureClass, rationale, findings = "", milestoneId) => {
|
|
51
|
+
if (!uokFlags.gates || !s.currentUnit)
|
|
52
|
+
return;
|
|
53
|
+
const gateRunner = new UokGateRunner();
|
|
54
|
+
gateRunner.register({
|
|
55
|
+
id: "milestone-validation-post-check",
|
|
56
|
+
type: "verification",
|
|
57
|
+
execute: async () => ({
|
|
58
|
+
outcome,
|
|
59
|
+
failureClass,
|
|
60
|
+
rationale,
|
|
61
|
+
findings,
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
await gateRunner.run("milestone-validation-post-check", {
|
|
65
|
+
basePath: s.basePath,
|
|
66
|
+
traceId: `validation-post-check:${s.currentUnit.id}`,
|
|
67
|
+
turnId: s.currentUnit.id,
|
|
68
|
+
milestoneId,
|
|
69
|
+
unitType: s.currentUnit.type,
|
|
70
|
+
unitId: s.currentUnit.id,
|
|
71
|
+
});
|
|
72
|
+
};
|
|
46
73
|
if (!s.currentUnit)
|
|
47
74
|
return "continue";
|
|
48
75
|
const { milestone: mid } = parseUnitId(s.currentUnit.id);
|
|
@@ -55,17 +82,22 @@ async function runValidateMilestonePostCheck(vctx, pauseAuto) {
|
|
|
55
82
|
if (!validationContent)
|
|
56
83
|
return "continue";
|
|
57
84
|
const verdict = extractVerdict(validationContent);
|
|
58
|
-
if (verdict !== "needs-remediation")
|
|
85
|
+
if (verdict !== "needs-remediation") {
|
|
86
|
+
await persistMilestoneValidationGate("pass", "none", `milestone validation verdict is ${verdict}; no remediation loop risk`, "", mid);
|
|
59
87
|
return "continue";
|
|
88
|
+
}
|
|
60
89
|
const incompleteSliceCount = await countIncompleteSlices(s.basePath, mid);
|
|
61
90
|
// If any non-closed slices exist, the agent successfully queued remediation
|
|
62
91
|
// work — proceed normally. The state machine will execute those slices and
|
|
63
92
|
// re-validate per the #3596/#3670 fix.
|
|
64
|
-
if (incompleteSliceCount > 0)
|
|
93
|
+
if (incompleteSliceCount > 0) {
|
|
94
|
+
await persistMilestoneValidationGate("pass", "none", `remediation slices present (${incompleteSliceCount}); validation can continue`, "", mid);
|
|
65
95
|
return "continue";
|
|
96
|
+
}
|
|
66
97
|
ctx.ui.notify(`Milestone ${mid} validation returned verdict=needs-remediation but no remediation slices were added. Pausing for human review.`, "error");
|
|
67
98
|
process.stderr.write(`validate-milestone: pausing — verdict=needs-remediation with no incomplete slices for ${mid}. ` +
|
|
68
99
|
`The agent must call gsd_reassess_roadmap to add remediation slices before re-validation.\n`);
|
|
100
|
+
await persistMilestoneValidationGate("manual-attention", "manual-attention", "needs-remediation verdict without queued remediation slices", `No incomplete slices found for ${mid} while verdict=needs-remediation`, mid);
|
|
69
101
|
await pauseAuto(ctx, pi);
|
|
70
102
|
return "pause";
|
|
71
103
|
}
|
|
@@ -122,6 +154,7 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
122
154
|
try {
|
|
123
155
|
const effectivePrefs = loadEffectiveGSDPreferences();
|
|
124
156
|
const prefs = effectivePrefs?.preferences;
|
|
157
|
+
const uokFlags = resolveUokFlags(prefs);
|
|
125
158
|
// Read task plan verify field
|
|
126
159
|
const { milestone: mid, slice: sid, task: tid } = parseUnitId(s.currentUnit.id);
|
|
127
160
|
let taskPlanVerify;
|
|
@@ -153,6 +186,35 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
153
186
|
process.stderr.write(` [${w.severity}] ${w.name}: ${w.title}\n`);
|
|
154
187
|
}
|
|
155
188
|
}
|
|
189
|
+
if (uokFlags.gates) {
|
|
190
|
+
const gateRunner = new UokGateRunner();
|
|
191
|
+
gateRunner.register({
|
|
192
|
+
id: "verification-gate",
|
|
193
|
+
type: "verification",
|
|
194
|
+
execute: async () => ({
|
|
195
|
+
outcome: result.passed ? "pass" : "fail",
|
|
196
|
+
failureClass: result.runtimeErrors?.some((e) => e.blocking)
|
|
197
|
+
? "execution"
|
|
198
|
+
: "verification",
|
|
199
|
+
rationale: result.passed
|
|
200
|
+
? "verification checks passed"
|
|
201
|
+
: "verification checks failed",
|
|
202
|
+
findings: result.passed
|
|
203
|
+
? ""
|
|
204
|
+
: formatFailureContext(result),
|
|
205
|
+
}),
|
|
206
|
+
});
|
|
207
|
+
await gateRunner.run("verification-gate", {
|
|
208
|
+
basePath: s.basePath,
|
|
209
|
+
traceId: `verification:${s.currentUnit.id}`,
|
|
210
|
+
turnId: s.currentUnit.id,
|
|
211
|
+
milestoneId: mid ?? undefined,
|
|
212
|
+
sliceId: sid ?? undefined,
|
|
213
|
+
taskId: tid ?? undefined,
|
|
214
|
+
unitType: s.currentUnit.type,
|
|
215
|
+
unitId: s.currentUnit.id,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
156
218
|
// Auto-fix retry preferences
|
|
157
219
|
const autoFixEnabled = prefs?.verification_auto_fix !== false;
|
|
158
220
|
const maxRetries = typeof prefs?.verification_max_retries === "number"
|
|
@@ -253,6 +315,42 @@ export async function runPostUnitVerification(vctx, pauseAuto) {
|
|
|
253
315
|
: "⚠";
|
|
254
316
|
process.stderr.write(`gsd-post-exec: ${checkEmoji} [${check.category}] ${check.target}: ${check.message}\n`);
|
|
255
317
|
}
|
|
318
|
+
if (uokFlags.gates) {
|
|
319
|
+
const strictMode = prefs?.enhanced_verification_strict === true;
|
|
320
|
+
const warnEscalated = postExecResult.status === "warn" && strictMode;
|
|
321
|
+
const blockingFailure = postExecResult.status === "fail" || warnEscalated;
|
|
322
|
+
const findings = postExecResult.checks
|
|
323
|
+
.filter((check) => !check.passed)
|
|
324
|
+
.map((check) => `[${check.category}] ${check.target}: ${check.message}`)
|
|
325
|
+
.join("\n");
|
|
326
|
+
const gateRunner = new UokGateRunner();
|
|
327
|
+
gateRunner.register({
|
|
328
|
+
id: "post-execution-checks",
|
|
329
|
+
type: "artifact",
|
|
330
|
+
execute: async () => ({
|
|
331
|
+
outcome: blockingFailure ? "fail" : "pass",
|
|
332
|
+
failureClass: postExecResult.status === "fail"
|
|
333
|
+
? "artifact"
|
|
334
|
+
: warnEscalated
|
|
335
|
+
? "policy"
|
|
336
|
+
: "none",
|
|
337
|
+
rationale: blockingFailure
|
|
338
|
+
? `post-execution checks ${postExecResult.status}${warnEscalated ? " (strict)" : ""}`
|
|
339
|
+
: "post-execution checks passed",
|
|
340
|
+
findings,
|
|
341
|
+
}),
|
|
342
|
+
});
|
|
343
|
+
await gateRunner.run("post-execution-checks", {
|
|
344
|
+
basePath: s.basePath,
|
|
345
|
+
traceId: `verification:${s.currentUnit.id}`,
|
|
346
|
+
turnId: s.currentUnit.id,
|
|
347
|
+
milestoneId: mid,
|
|
348
|
+
sliceId: sid,
|
|
349
|
+
taskId: tid,
|
|
350
|
+
unitType: s.currentUnit.type,
|
|
351
|
+
unitId: s.currentUnit.id,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
256
354
|
// Check for blocking failures
|
|
257
355
|
if (postExecResult.status === "fail") {
|
|
258
356
|
postExecBlockingFailure = true;
|