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
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { closeDatabase, openDatabase, _getAdapter } from "../gsd-db.ts";
|
|
5
|
+
import { UokGateRunner } from "../uok/gate-runner.ts";
|
|
6
|
+
|
|
7
|
+
test.beforeEach(() => {
|
|
8
|
+
closeDatabase();
|
|
9
|
+
const ok = openDatabase(":memory:");
|
|
10
|
+
assert.equal(ok, true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test.afterEach(() => {
|
|
14
|
+
closeDatabase();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("uok gate runner retries timeout failures using deterministic matrix", async () => {
|
|
18
|
+
const runner = new UokGateRunner();
|
|
19
|
+
|
|
20
|
+
let calls = 0;
|
|
21
|
+
runner.register({
|
|
22
|
+
id: "timeout-gate",
|
|
23
|
+
type: "verification",
|
|
24
|
+
execute: async (_ctx, attempt) => {
|
|
25
|
+
calls += 1;
|
|
26
|
+
if (attempt < 2) {
|
|
27
|
+
return {
|
|
28
|
+
outcome: "fail",
|
|
29
|
+
failureClass: "timeout",
|
|
30
|
+
rationale: "first attempt timed out",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
outcome: "pass",
|
|
35
|
+
failureClass: "none",
|
|
36
|
+
rationale: "second attempt passed",
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const result = await runner.run("timeout-gate", {
|
|
42
|
+
basePath: process.cwd(),
|
|
43
|
+
traceId: "trace-a",
|
|
44
|
+
turnId: "turn-a",
|
|
45
|
+
milestoneId: "M001",
|
|
46
|
+
sliceId: "S01",
|
|
47
|
+
taskId: "T01",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
assert.equal(result.outcome, "pass");
|
|
51
|
+
assert.equal(calls, 2);
|
|
52
|
+
|
|
53
|
+
const adapter = _getAdapter();
|
|
54
|
+
const rows = adapter?.prepare("SELECT gate_id, outcome, attempt FROM gate_runs ORDER BY id").all() ?? [];
|
|
55
|
+
assert.equal(rows.length, 2);
|
|
56
|
+
assert.equal(rows[0]?.["outcome"], "retry");
|
|
57
|
+
assert.equal(rows[1]?.["outcome"], "pass");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("uok gate runner returns manual-attention for unknown gate id", async () => {
|
|
61
|
+
const runner = new UokGateRunner();
|
|
62
|
+
const result = await runner.run("missing-gate", {
|
|
63
|
+
basePath: process.cwd(),
|
|
64
|
+
traceId: "trace-b",
|
|
65
|
+
turnId: "turn-b",
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
assert.equal(result.outcome, "manual-attention");
|
|
69
|
+
assert.equal(result.failureClass, "unknown");
|
|
70
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
import { runTurnGitAction } from "../git-service.ts";
|
|
8
|
+
|
|
9
|
+
function run(cmd: string, cwd: string): string {
|
|
10
|
+
return execSync(cmd, { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function makeRepo(): string {
|
|
14
|
+
const repo = mkdtempSync(join(tmpdir(), "gsd-uok-gitops-"));
|
|
15
|
+
run("git init", repo);
|
|
16
|
+
run('git config user.email "test@example.com"', repo);
|
|
17
|
+
run('git config user.name "Test User"', repo);
|
|
18
|
+
writeFileSync(join(repo, "README.md"), "# Test\n", "utf-8");
|
|
19
|
+
run("git add README.md", repo);
|
|
20
|
+
run('git commit -m "chore: init"', repo);
|
|
21
|
+
return repo;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
test("uok gitops turn action status-only reports working tree dirtiness", () => {
|
|
25
|
+
const repo = makeRepo();
|
|
26
|
+
try {
|
|
27
|
+
const clean = runTurnGitAction({
|
|
28
|
+
basePath: repo,
|
|
29
|
+
action: "status-only",
|
|
30
|
+
unitType: "execute-task",
|
|
31
|
+
unitId: "M001/S01/T01",
|
|
32
|
+
});
|
|
33
|
+
assert.equal(clean.status, "ok");
|
|
34
|
+
assert.equal(clean.dirty, false);
|
|
35
|
+
|
|
36
|
+
writeFileSync(join(repo, "README.md"), "# Dirty\n", "utf-8");
|
|
37
|
+
const dirty = runTurnGitAction({
|
|
38
|
+
basePath: repo,
|
|
39
|
+
action: "status-only",
|
|
40
|
+
unitType: "execute-task",
|
|
41
|
+
unitId: "M001/S01/T01",
|
|
42
|
+
});
|
|
43
|
+
assert.equal(dirty.status, "ok");
|
|
44
|
+
assert.equal(dirty.dirty, true);
|
|
45
|
+
} finally {
|
|
46
|
+
rmSync(repo, { recursive: true, force: true });
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("uok gitops turn action snapshot writes snapshot refs", () => {
|
|
51
|
+
const repo = makeRepo();
|
|
52
|
+
try {
|
|
53
|
+
const result = runTurnGitAction({
|
|
54
|
+
basePath: repo,
|
|
55
|
+
action: "snapshot",
|
|
56
|
+
unitType: "execute-task",
|
|
57
|
+
unitId: "M001/S01/T01",
|
|
58
|
+
});
|
|
59
|
+
assert.equal(result.status, "ok");
|
|
60
|
+
assert.ok(result.snapshotLabel?.includes("execute-task/M001/S01/T01"));
|
|
61
|
+
const refs = run("git for-each-ref refs/gsd/snapshots/ --format='%(refname)'", repo);
|
|
62
|
+
assert.ok(refs.includes("refs/gsd/snapshots/execute-task/M001/S01/T01/"));
|
|
63
|
+
} finally {
|
|
64
|
+
rmSync(repo, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("uok gitops turn action commit creates commit with unit trailer", () => {
|
|
69
|
+
const repo = makeRepo();
|
|
70
|
+
try {
|
|
71
|
+
writeFileSync(join(repo, "feature.ts"), "export const x = 1;\n", "utf-8");
|
|
72
|
+
const result = runTurnGitAction({
|
|
73
|
+
basePath: repo,
|
|
74
|
+
action: "commit",
|
|
75
|
+
unitType: "execute-task",
|
|
76
|
+
unitId: "M001/S01/T02",
|
|
77
|
+
});
|
|
78
|
+
assert.equal(result.status, "ok");
|
|
79
|
+
assert.ok(result.commitMessage?.includes("chore: auto-commit after execute-task"));
|
|
80
|
+
const body = run("git log -1 --pretty=%B", repo);
|
|
81
|
+
assert.ok(body.includes("GSD-Unit: M001/S01/T02"));
|
|
82
|
+
} finally {
|
|
83
|
+
rmSync(repo, { recursive: true, force: true });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const gsdDir = join(__dirname, "..");
|
|
9
|
+
|
|
10
|
+
test("post-unit pre-verification selects turn git action from UOK gitops flags", () => {
|
|
11
|
+
const source = readFileSync(join(gsdDir, "auto-post-unit.ts"), "utf-8");
|
|
12
|
+
assert.ok(
|
|
13
|
+
source.includes("const turnAction: TurnGitActionMode = uokFlags.gitops ? uokFlags.gitopsTurnAction : \"commit\""),
|
|
14
|
+
"postUnitPreVerification should derive turn action from uok.gitops.turn_action when enabled",
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("post-unit pre-verification routes git failures through closeout gate", () => {
|
|
19
|
+
const source = readFileSync(join(gsdDir, "auto-post-unit.ts"), "utf-8");
|
|
20
|
+
assert.ok(
|
|
21
|
+
source.includes('id: "closeout-git-action"') &&
|
|
22
|
+
source.includes('type: "closeout"') &&
|
|
23
|
+
source.includes('failureClass: "git"'),
|
|
24
|
+
"git failures should be persisted via a closeout gate with failureClass=git",
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("auto snapshot opts carry trace/turn IDs for turn closeout records", () => {
|
|
29
|
+
const source = readFileSync(join(gsdDir, "auto.ts"), "utf-8");
|
|
30
|
+
assert.ok(
|
|
31
|
+
source.includes("traceId: s.currentTraceId ?? undefined") &&
|
|
32
|
+
source.includes("turnId: s.currentTurnId ?? undefined"),
|
|
33
|
+
"buildSnapshotOpts should pass trace/turn IDs into closeout options",
|
|
34
|
+
);
|
|
35
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
applyModelPolicyFilter,
|
|
9
|
+
buildRequirementVector,
|
|
10
|
+
} from "../uok/model-policy.ts";
|
|
11
|
+
import {
|
|
12
|
+
registerToolCompatibility,
|
|
13
|
+
resetToolCompatibilityRegistry,
|
|
14
|
+
} from "@gsd/pi-coding-agent";
|
|
15
|
+
|
|
16
|
+
test.afterEach(() => {
|
|
17
|
+
resetToolCompatibilityRegistry();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("uok model policy builds requirement vectors from unit metadata", () => {
|
|
21
|
+
const requirements = buildRequirementVector("execute-task", {
|
|
22
|
+
tags: ["docs"],
|
|
23
|
+
fileCount: 8,
|
|
24
|
+
estimatedLines: 600,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
assert.equal(requirements.instruction, 0.9);
|
|
28
|
+
assert.equal(requirements.coding, 0.3);
|
|
29
|
+
assert.equal(requirements.speed, 0.7);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("uok model policy enforces provider/api/tool constraints and emits decision audit events", () => {
|
|
33
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-uok-model-policy-"));
|
|
34
|
+
try {
|
|
35
|
+
mkdirSync(join(basePath, ".gsd"), { recursive: true });
|
|
36
|
+
registerToolCompatibility("screenshot", { producesImages: true });
|
|
37
|
+
|
|
38
|
+
const result = applyModelPolicyFilter(
|
|
39
|
+
[
|
|
40
|
+
{ id: "openai-image", provider: "openai", api: "openai-responses" },
|
|
41
|
+
{ id: "anthropic-ok", provider: "anthropic", api: "anthropic-messages" },
|
|
42
|
+
{ id: "gemini-api-deny", provider: "google", api: "google-generative-ai" },
|
|
43
|
+
{ id: "blocked-provider", provider: "blocked", api: "anthropic-messages" },
|
|
44
|
+
],
|
|
45
|
+
{
|
|
46
|
+
basePath,
|
|
47
|
+
traceId: "trace-model-policy-1",
|
|
48
|
+
turnId: "turn-model-policy-1",
|
|
49
|
+
unitType: "execute-task",
|
|
50
|
+
taskMetadata: { tags: ["docs"] },
|
|
51
|
+
allowCrossProvider: true,
|
|
52
|
+
requiredTools: ["screenshot"],
|
|
53
|
+
allowedApis: ["anthropic-messages", "openai-responses"],
|
|
54
|
+
deniedProviders: ["blocked"],
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(
|
|
59
|
+
result.eligible.map((m) => m.id),
|
|
60
|
+
["anthropic-ok"],
|
|
61
|
+
"only the policy-compliant anthropic model should remain eligible",
|
|
62
|
+
);
|
|
63
|
+
assert.equal(result.decisions.length, 4);
|
|
64
|
+
assert.equal(result.decisions[0]?.allowed, false);
|
|
65
|
+
assert.match(result.decisions[0]?.reason ?? "", /tool policy denied/);
|
|
66
|
+
assert.equal(result.decisions[1]?.allowed, true);
|
|
67
|
+
assert.equal(result.decisions[2]?.allowed, false);
|
|
68
|
+
assert.match(result.decisions[2]?.reason ?? "", /transport\/api denied by policy/);
|
|
69
|
+
assert.equal(result.decisions[3]?.allowed, false);
|
|
70
|
+
assert.match(result.decisions[3]?.reason ?? "", /provider denied by policy/);
|
|
71
|
+
|
|
72
|
+
const auditLogPath = join(basePath, ".gsd", "audit", "events.jsonl");
|
|
73
|
+
const auditLines = readFileSync(auditLogPath, "utf-8")
|
|
74
|
+
.trim()
|
|
75
|
+
.split("\n")
|
|
76
|
+
.map((line) => JSON.parse(line) as { type: string; payload?: { reason?: string } });
|
|
77
|
+
const decisionTypes = auditLines.map((event) => event.type);
|
|
78
|
+
|
|
79
|
+
assert.equal(auditLines.length, 4);
|
|
80
|
+
assert.ok(decisionTypes.includes("model-policy-allow"));
|
|
81
|
+
assert.ok(decisionTypes.includes("model-policy-deny"));
|
|
82
|
+
assert.ok(
|
|
83
|
+
auditLines.some((event) => (event.payload?.reason ?? "").includes("tool policy denied")),
|
|
84
|
+
"audit stream should include explicit deny reasons",
|
|
85
|
+
);
|
|
86
|
+
} finally {
|
|
87
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
closeDatabase,
|
|
10
|
+
insertMilestone,
|
|
11
|
+
insertSlice,
|
|
12
|
+
insertTask,
|
|
13
|
+
openDatabase,
|
|
14
|
+
} from "../gsd-db.ts";
|
|
15
|
+
import type { GSDState, Phase } from "../types.ts";
|
|
16
|
+
import { ensurePlanV2Graph } from "../uok/plan-v2.ts";
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const gsdDir = join(__dirname, "..");
|
|
20
|
+
const MILESTONE_ID = "M001";
|
|
21
|
+
const SLICE_ID = "S01";
|
|
22
|
+
const TASK_ID = "T01";
|
|
23
|
+
const tempDirs = new Set<string>();
|
|
24
|
+
|
|
25
|
+
function createBasePath(): string {
|
|
26
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-uok-planv2-"));
|
|
27
|
+
mkdirSync(join(basePath, ".gsd", "milestones", MILESTONE_ID), { recursive: true });
|
|
28
|
+
tempDirs.add(basePath);
|
|
29
|
+
return basePath;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function writeMilestoneFile(basePath: string, suffix: string, content: string): void {
|
|
33
|
+
const milestoneDir = join(basePath, ".gsd", "milestones", MILESTONE_ID);
|
|
34
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
35
|
+
writeFileSync(join(milestoneDir, `${MILESTONE_ID}-${suffix}.md`), `${content}\n`, "utf-8");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function writeSliceFile(basePath: string, suffix: string, content: string): void {
|
|
39
|
+
const sliceDir = join(basePath, ".gsd", "milestones", MILESTONE_ID, "slices", SLICE_ID);
|
|
40
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
41
|
+
writeFileSync(join(sliceDir, `${SLICE_ID}-${suffix}.md`), `${content}\n`, "utf-8");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function seedGraphRows(): void {
|
|
45
|
+
insertMilestone({ id: MILESTONE_ID, title: "Milestone", status: "active" });
|
|
46
|
+
insertSlice({
|
|
47
|
+
id: SLICE_ID,
|
|
48
|
+
milestoneId: MILESTONE_ID,
|
|
49
|
+
title: "Slice",
|
|
50
|
+
status: "in_progress",
|
|
51
|
+
sequence: 1,
|
|
52
|
+
});
|
|
53
|
+
insertTask({
|
|
54
|
+
id: TASK_ID,
|
|
55
|
+
milestoneId: MILESTONE_ID,
|
|
56
|
+
sliceId: SLICE_ID,
|
|
57
|
+
title: "Task",
|
|
58
|
+
status: "pending",
|
|
59
|
+
keyFiles: ["src/task.ts"],
|
|
60
|
+
sequence: 1,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function buildState(phase: Phase): GSDState {
|
|
65
|
+
return {
|
|
66
|
+
phase,
|
|
67
|
+
activeMilestone: { id: MILESTONE_ID, title: "Milestone" },
|
|
68
|
+
activeSlice: null,
|
|
69
|
+
activeTask: null,
|
|
70
|
+
recentDecisions: [],
|
|
71
|
+
blockers: [],
|
|
72
|
+
nextAction: "dispatch",
|
|
73
|
+
registry: [],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
test.beforeEach(() => {
|
|
78
|
+
closeDatabase();
|
|
79
|
+
const opened = openDatabase(":memory:");
|
|
80
|
+
assert.equal(opened, true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test.afterEach(() => {
|
|
84
|
+
closeDatabase();
|
|
85
|
+
for (const path of tempDirs) {
|
|
86
|
+
rmSync(path, { recursive: true, force: true });
|
|
87
|
+
}
|
|
88
|
+
tempDirs.clear();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("guided flow enforces plan-v2 gate before execution-oriented dispatch", () => {
|
|
92
|
+
const source = readFileSync(join(gsdDir, "guided-flow.ts"), "utf-8");
|
|
93
|
+
assert.ok(
|
|
94
|
+
source.includes("needsPlanV2Gate") &&
|
|
95
|
+
source.includes("ensurePlanV2Graph") &&
|
|
96
|
+
source.includes("Plan gate failed-closed"),
|
|
97
|
+
"guided flow should fail-closed when plan-v2 graph compilation fails",
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("plan-v2 gate fails closed for execution phase when finalized context is missing", () => {
|
|
102
|
+
const basePath = createBasePath();
|
|
103
|
+
seedGraphRows();
|
|
104
|
+
|
|
105
|
+
writeMilestoneFile(basePath, "CONTEXT-DRAFT", "Draft context only.");
|
|
106
|
+
|
|
107
|
+
const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
|
|
108
|
+
assert.equal(compiled.ok, false);
|
|
109
|
+
assert.match(compiled.reason ?? "", /CONTEXT\.md/i);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("plan-v2 compiler writes pipeline metadata for clarify/research/draft stages", () => {
|
|
113
|
+
const basePath = createBasePath();
|
|
114
|
+
seedGraphRows();
|
|
115
|
+
|
|
116
|
+
writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
|
|
117
|
+
writeMilestoneFile(basePath, "CONTEXT-DRAFT", "Draft context retained.");
|
|
118
|
+
writeMilestoneFile(basePath, "RESEARCH", "Milestone research synthesis.");
|
|
119
|
+
writeSliceFile(basePath, "RESEARCH", "Slice research detail.");
|
|
120
|
+
|
|
121
|
+
const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
|
|
122
|
+
assert.equal(compiled.ok, true);
|
|
123
|
+
assert.equal(compiled.clarifyRoundLimit, 3);
|
|
124
|
+
assert.equal(compiled.researchSynthesized, true);
|
|
125
|
+
assert.equal(compiled.draftContextIncluded, true);
|
|
126
|
+
assert.equal(compiled.finalizedContextIncluded, true);
|
|
127
|
+
|
|
128
|
+
const graphPath = compiled.graphPath ?? "";
|
|
129
|
+
const graphRaw = readFileSync(graphPath, "utf-8");
|
|
130
|
+
const graph = JSON.parse(graphRaw) as {
|
|
131
|
+
pipeline?: Record<string, unknown>;
|
|
132
|
+
nodes?: unknown[];
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
assert.equal(graph.pipeline?.["clarifyRoundLimit"], 3);
|
|
136
|
+
assert.equal(graph.pipeline?.["researchSynthesized"], true);
|
|
137
|
+
assert.equal(graph.pipeline?.["draftContextIncluded"], true);
|
|
138
|
+
assert.equal(graph.pipeline?.["finalizedContextIncluded"], true);
|
|
139
|
+
assert.equal(Array.isArray(graph.nodes), true);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("plan-v2 graph may compile during planning even without finalized context", () => {
|
|
143
|
+
const basePath = createBasePath();
|
|
144
|
+
seedGraphRows();
|
|
145
|
+
|
|
146
|
+
writeMilestoneFile(basePath, "CONTEXT-DRAFT", "Planning draft context.");
|
|
147
|
+
const compiled = ensurePlanV2Graph(basePath, buildState("planning"));
|
|
148
|
+
assert.equal(compiled.ok, true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("plan-v2 ensure rejects empty executable graph", () => {
|
|
152
|
+
const basePath = createBasePath();
|
|
153
|
+
writeMilestoneFile(basePath, "CONTEXT", "Finalized context.");
|
|
154
|
+
|
|
155
|
+
insertMilestone({ id: MILESTONE_ID, title: "Milestone", status: "active" });
|
|
156
|
+
insertSlice({
|
|
157
|
+
id: SLICE_ID,
|
|
158
|
+
milestoneId: MILESTONE_ID,
|
|
159
|
+
title: "Slice",
|
|
160
|
+
status: "pending",
|
|
161
|
+
sequence: 1,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const compiled = ensurePlanV2Graph(basePath, buildState("executing"));
|
|
165
|
+
assert.equal(compiled.ok, false);
|
|
166
|
+
assert.match(compiled.reason ?? "", /compiled graph is empty/i);
|
|
167
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import { validatePreferences } from "../preferences-validation.ts";
|
|
5
|
+
|
|
6
|
+
test("uok preferences validate nested flags and turn_action", () => {
|
|
7
|
+
const input = {
|
|
8
|
+
uok: {
|
|
9
|
+
enabled: true,
|
|
10
|
+
legacy_fallback: { enabled: false },
|
|
11
|
+
gates: { enabled: true },
|
|
12
|
+
model_policy: { enabled: true },
|
|
13
|
+
execution_graph: { enabled: false },
|
|
14
|
+
gitops: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
turn_action: "status-only",
|
|
17
|
+
turn_push: false,
|
|
18
|
+
},
|
|
19
|
+
audit_unified: { enabled: true },
|
|
20
|
+
plan_v2: { enabled: true },
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const result = validatePreferences(input as never);
|
|
25
|
+
assert.equal(result.errors.length, 0);
|
|
26
|
+
assert.equal(result.preferences.uok?.enabled, true);
|
|
27
|
+
assert.equal(result.preferences.uok?.legacy_fallback?.enabled, false);
|
|
28
|
+
assert.equal(result.preferences.uok?.gitops?.turn_action, "status-only");
|
|
29
|
+
assert.equal(result.preferences.uok?.plan_v2?.enabled, true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("uok preferences reject invalid turn_action", () => {
|
|
33
|
+
const result = validatePreferences({
|
|
34
|
+
uok: {
|
|
35
|
+
gitops: {
|
|
36
|
+
turn_action: "push-everything",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
} as never);
|
|
40
|
+
|
|
41
|
+
assert.ok(result.errors.some((e) => e.includes("uok.gitops.turn_action")));
|
|
42
|
+
});
|
|
@@ -112,4 +112,43 @@ describe("handleValidateMilestone write ordering (#2725)", () => {
|
|
|
112
112
|
).get();
|
|
113
113
|
assert.equal(row, undefined, "assessment row should be deleted after disk-write rollback");
|
|
114
114
|
});
|
|
115
|
+
|
|
116
|
+
it("persists milestone validation gate_runs rows when UOK gates are enabled", async () => {
|
|
117
|
+
base = makeTmpBase();
|
|
118
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
119
|
+
openDatabase(dbPath);
|
|
120
|
+
insertMilestone({ id: "M001" });
|
|
121
|
+
insertSlice({ id: "S01", milestoneId: "M001" });
|
|
122
|
+
|
|
123
|
+
const result = await handleValidateMilestone(VALID_PARAMS, base, {
|
|
124
|
+
uokGatesEnabled: true,
|
|
125
|
+
traceId: "trace-val-1",
|
|
126
|
+
turnId: "turn-val-1",
|
|
127
|
+
});
|
|
128
|
+
assert.ok(!("error" in result), `unexpected error: ${"error" in result ? result.error : ""}`);
|
|
129
|
+
|
|
130
|
+
const adapter = _getAdapter()!;
|
|
131
|
+
const row = adapter.prepare(
|
|
132
|
+
`SELECT gate_id, outcome, failure_class, trace_id, turn_id
|
|
133
|
+
FROM gate_runs
|
|
134
|
+
WHERE gate_id = 'milestone-validation-gates'
|
|
135
|
+
ORDER BY id DESC
|
|
136
|
+
LIMIT 1`,
|
|
137
|
+
).get() as
|
|
138
|
+
| {
|
|
139
|
+
gate_id: string;
|
|
140
|
+
outcome: string;
|
|
141
|
+
failure_class: string;
|
|
142
|
+
trace_id: string;
|
|
143
|
+
turn_id: string;
|
|
144
|
+
}
|
|
145
|
+
| undefined;
|
|
146
|
+
|
|
147
|
+
assert.ok(row, "milestone validation gate row should be persisted");
|
|
148
|
+
assert.equal(row?.gate_id, "milestone-validation-gates");
|
|
149
|
+
assert.equal(row?.outcome, "pass");
|
|
150
|
+
assert.equal(row?.failure_class, "none");
|
|
151
|
+
assert.equal(row?.trace_id, "trace-val-1");
|
|
152
|
+
assert.equal(row?.turn_id, "turn-val-1");
|
|
153
|
+
});
|
|
115
154
|
});
|
|
@@ -430,11 +430,18 @@ export async function handleCompleteSlice(
|
|
|
430
430
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
431
431
|
(async () => {
|
|
432
432
|
try {
|
|
433
|
-
const graphMod = await import("@gsd-build/mcp-server") as {
|
|
433
|
+
const graphMod = await import("@gsd-build/mcp-server") as unknown as Partial<{
|
|
434
434
|
buildGraph: (dir: string) => Promise<{ nodes: unknown[]; edges: unknown[]; builtAt: string }>;
|
|
435
435
|
writeGraph: (gsdRoot: string, graph: unknown) => Promise<void>;
|
|
436
436
|
resolveGsdRoot: (basePath: string) => string;
|
|
437
|
-
}
|
|
437
|
+
}>;
|
|
438
|
+
if (
|
|
439
|
+
typeof graphMod.buildGraph !== "function"
|
|
440
|
+
|| typeof graphMod.writeGraph !== "function"
|
|
441
|
+
|| typeof graphMod.resolveGsdRoot !== "function"
|
|
442
|
+
) {
|
|
443
|
+
throw new Error("graph helpers unavailable from @gsd-build/mcp-server");
|
|
444
|
+
}
|
|
438
445
|
const g = await graphMod.buildGraph(basePath);
|
|
439
446
|
await graphMod.writeGraph(graphMod.resolveGsdRoot(basePath), g);
|
|
440
447
|
} catch (graphErr) {
|
|
@@ -23,6 +23,9 @@ import { invalidateStateCache } from "../state.js";
|
|
|
23
23
|
import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
|
|
24
24
|
import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
|
|
25
25
|
import { logWarning } from "../workflow-logger.js";
|
|
26
|
+
import { UokGateRunner } from "../uok/gate-runner.js";
|
|
27
|
+
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
28
|
+
import { resolveUokFlags } from "../uok/flags.js";
|
|
26
29
|
|
|
27
30
|
export interface ValidateMilestoneParams {
|
|
28
31
|
milestoneId: string;
|
|
@@ -43,6 +46,12 @@ export interface ValidateMilestoneResult {
|
|
|
43
46
|
validationPath: string;
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
export interface ValidateMilestoneOptions {
|
|
50
|
+
uokGatesEnabled?: boolean;
|
|
51
|
+
traceId?: string;
|
|
52
|
+
turnId?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
46
55
|
function renderValidationMarkdown(params: ValidateMilestoneParams): string {
|
|
47
56
|
let md = `---
|
|
48
57
|
verdict: ${params.verdict}
|
|
@@ -81,6 +90,7 @@ ${params.verdictRationale}
|
|
|
81
90
|
export async function handleValidateMilestone(
|
|
82
91
|
params: ValidateMilestoneParams,
|
|
83
92
|
basePath: string,
|
|
93
|
+
opts?: ValidateMilestoneOptions,
|
|
84
94
|
): Promise<ValidateMilestoneResult | { error: string }> {
|
|
85
95
|
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
86
96
|
return { error: "milestoneId is required and must be a non-empty string" };
|
|
@@ -108,6 +118,8 @@ export async function handleValidateMilestone(
|
|
|
108
118
|
// rendering can regenerate. The inverse (file exists, no DB row) is
|
|
109
119
|
// harder to detect and recover from (#2725).
|
|
110
120
|
const validatedAt = new Date().toISOString();
|
|
121
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
122
|
+
const gateSliceId = slices.length > 0 ? slices[0].id : "_milestone";
|
|
111
123
|
|
|
112
124
|
transaction(() => {
|
|
113
125
|
insertAssessment({
|
|
@@ -123,11 +135,9 @@ export async function handleValidateMilestone(
|
|
|
123
135
|
// #2945 Bug 4: persist quality_gates records alongside the assessment.
|
|
124
136
|
// Previously only the assessment was written, leaving M002+ milestones
|
|
125
137
|
// with zero quality_gate records despite passing validation.
|
|
126
|
-
const slices = getMilestoneSlices(params.milestoneId);
|
|
127
|
-
const sliceId = slices.length > 0 ? slices[0].id : "_milestone";
|
|
128
138
|
insertMilestoneValidationGates(
|
|
129
139
|
params.milestoneId,
|
|
130
|
-
|
|
140
|
+
gateSliceId,
|
|
131
141
|
params.verdict,
|
|
132
142
|
validatedAt,
|
|
133
143
|
);
|
|
@@ -147,6 +157,41 @@ export async function handleValidateMilestone(
|
|
|
147
157
|
clearPathCache();
|
|
148
158
|
clearParseCache();
|
|
149
159
|
|
|
160
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
161
|
+
const gatesEnabled = opts?.uokGatesEnabled ?? resolveUokFlags(prefs).gates;
|
|
162
|
+
if (gatesEnabled) {
|
|
163
|
+
try {
|
|
164
|
+
const gateRunner = new UokGateRunner();
|
|
165
|
+
const nonPassVerdict = params.verdict !== "pass";
|
|
166
|
+
gateRunner.register({
|
|
167
|
+
id: "milestone-validation-gates",
|
|
168
|
+
type: "verification",
|
|
169
|
+
execute: async () => ({
|
|
170
|
+
outcome: nonPassVerdict ? "manual-attention" : "pass",
|
|
171
|
+
failureClass: nonPassVerdict ? "manual-attention" : "none",
|
|
172
|
+
rationale: `milestone validation verdict: ${params.verdict}`,
|
|
173
|
+
findings: nonPassVerdict
|
|
174
|
+
? [params.verdictRationale, params.remediationPlan ?? ""].filter(Boolean).join("\n")
|
|
175
|
+
: "",
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
await gateRunner.run("milestone-validation-gates", {
|
|
179
|
+
basePath,
|
|
180
|
+
traceId: opts?.traceId ?? `validate-milestone:${params.milestoneId}`,
|
|
181
|
+
turnId: opts?.turnId ?? `${params.milestoneId}:validate`,
|
|
182
|
+
milestoneId: params.milestoneId,
|
|
183
|
+
sliceId: gateSliceId,
|
|
184
|
+
unitType: "validate-milestone",
|
|
185
|
+
unitId: params.milestoneId,
|
|
186
|
+
});
|
|
187
|
+
} catch (err) {
|
|
188
|
+
logWarning(
|
|
189
|
+
"tool",
|
|
190
|
+
`validate_milestone — failed to persist UOK gate result: ${(err as Error).message}`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
150
195
|
return {
|
|
151
196
|
milestoneId: params.milestoneId,
|
|
152
197
|
verdict: params.verdict,
|
|
@@ -253,6 +253,19 @@ export interface GSDState {
|
|
|
253
253
|
lastCompletedMilestone?: ActiveRef | null;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
// ─── GSD Ecosystem Extension API Types ────────────────────────────────────
|
|
257
|
+
// Pure data type — no runtime deps. The GSDExtensionAPI interface itself
|
|
258
|
+
// lives in ecosystem/gsd-extension-api.ts (it imports from pi).
|
|
259
|
+
|
|
260
|
+
export interface GSDActiveUnit {
|
|
261
|
+
milestoneId: string;
|
|
262
|
+
milestoneTitle: string;
|
|
263
|
+
sliceId: string;
|
|
264
|
+
sliceTitle: string;
|
|
265
|
+
taskId: string;
|
|
266
|
+
taskTitle: string;
|
|
267
|
+
}
|
|
268
|
+
|
|
256
269
|
// ─── Post-Unit Hook Types ─────────────────────────────────────────────────
|
|
257
270
|
|
|
258
271
|
export interface PostUnitHookConfig {
|
|
@@ -306,7 +319,7 @@ export interface HookDispatchResult {
|
|
|
306
319
|
|
|
307
320
|
export type BudgetEnforcementMode = "warn" | "pause" | "halt";
|
|
308
321
|
|
|
309
|
-
export type TokenProfile = "budget" | "balanced" | "quality";
|
|
322
|
+
export type TokenProfile = "budget" | "balanced" | "quality" | "burn-max";
|
|
310
323
|
|
|
311
324
|
export type InlineLevel = "full" | "standard" | "minimal";
|
|
312
325
|
|