gsd-pi 2.73.1-dev.d987996 → 2.74.0-dev.0306a2e
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/cli-web-branch.d.ts +4 -3
- package/dist/cli-web-branch.js +10 -7
- package/dist/cli.js +184 -206
- package/dist/headless-query.js +4 -1
- package/dist/help-text.js +23 -0
- package/dist/logo.d.ts +1 -1
- package/dist/logo.js +1 -1
- package/dist/onboarding.js +59 -53
- package/dist/resource-loader.js +2 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +68 -4
- package/dist/resources/extensions/gsd/activity-log.js +16 -0
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +11 -4
- package/dist/resources/extensions/gsd/auto/loop.js +147 -10
- package/dist/resources/extensions/gsd/auto/phases.js +173 -13
- package/dist/resources/extensions/gsd/auto/session.js +10 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +22 -4
- package/dist/resources/extensions/gsd/auto-model-selection.js +105 -16
- package/dist/resources/extensions/gsd/auto-post-unit.js +254 -15
- package/dist/resources/extensions/gsd/auto-prompts.js +12 -0
- package/dist/resources/extensions/gsd/auto-start.js +23 -6
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +13 -0
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +18 -0
- package/dist/resources/extensions/gsd/auto-verification.js +186 -3
- package/dist/resources/extensions/gsd/auto.js +65 -12
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +30 -8
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +41 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +26 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +25 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +68 -9
- package/dist/resources/extensions/gsd/commands-add-tests.js +111 -0
- package/dist/resources/extensions/gsd/commands-backlog.js +140 -0
- package/dist/resources/extensions/gsd/commands-do.js +79 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +225 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +8 -2
- package/dist/resources/extensions/gsd/commands-maintenance.js +6 -6
- package/dist/resources/extensions/gsd/commands-pr-branch.js +180 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands-session-report.js +82 -0
- package/dist/resources/extensions/gsd/commands-ship.js +187 -0
- package/dist/resources/extensions/gsd/db-writer.js +3 -5
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +15 -2
- 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 +157 -0
- package/dist/resources/extensions/gsd/gsd-db.js +581 -2
- package/dist/resources/extensions/gsd/guided-flow.js +23 -0
- package/dist/resources/extensions/gsd/index.js +15 -2
- package/dist/resources/extensions/gsd/init-wizard.js +1 -0
- package/dist/resources/extensions/gsd/journal.js +27 -0
- package/dist/resources/extensions/gsd/md-importer.js +3 -4
- package/dist/resources/extensions/gsd/memory-store.js +19 -51
- package/dist/resources/extensions/gsd/metrics.js +19 -0
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +13 -12
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -4
- package/dist/resources/extensions/gsd/notification-widget.js +2 -2
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +33 -1
- package/dist/resources/extensions/gsd/preferences-models.js +63 -3
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +130 -2
- package/dist/resources/extensions/gsd/preferences.js +26 -0
- package/dist/resources/extensions/gsd/prompts/add-tests.md +35 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +12 -2
- package/dist/resources/extensions/gsd/state.js +66 -15
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +39 -4
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +3 -14
- package/dist/resources/extensions/gsd/triage-resolution.js +2 -5
- 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/gsd/workflow-manifest.js +8 -69
- package/dist/resources/extensions/gsd/workflow-migration.js +21 -22
- package/dist/resources/extensions/gsd/workflow-projections.js +4 -1
- package/dist/resources/extensions/gsd/workflow-reconcile.js +14 -11
- package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -0
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +13 -5
- package/dist/update-cmd.js +4 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- 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 +13 -13
- 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 +3 -3
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/index.d.ts +3 -0
- package/packages/mcp-server/dist/index.d.ts.map +1 -1
- package/packages/mcp-server/dist/index.js +3 -0
- package/packages/mcp-server/dist/index.js.map +1 -1
- package/packages/mcp-server/dist/readers/graph.d.ts +87 -0
- package/packages/mcp-server/dist/readers/graph.d.ts.map +1 -0
- package/packages/mcp-server/dist/readers/graph.js +655 -0
- package/packages/mcp-server/dist/readers/graph.js.map +1 -0
- package/packages/mcp-server/dist/readers/index.d.ts +2 -0
- package/packages/mcp-server/dist/readers/index.d.ts.map +1 -1
- package/packages/mcp-server/dist/readers/index.js +1 -0
- package/packages/mcp-server/dist/readers/index.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +65 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/index.ts +15 -0
- package/packages/mcp-server/src/readers/graph.test.ts +604 -0
- package/packages/mcp-server/src/readers/graph.ts +855 -0
- package/packages/mcp-server/src/readers/index.ts +12 -0
- package/packages/mcp-server/src/server.ts +83 -0
- package/packages/mcp-server/tsconfig.json +1 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -0
- package/packages/native/package.json +2 -2
- package/packages/native/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.json +1 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-ai/dist/index.d.ts +2 -9
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -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/dist/utils/overflow.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/overflow.js +12 -0
- package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.js +50 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.js.map +1 -0
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +74 -40
- package/packages/pi-ai/src/index.ts +5 -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/src/utils/overflow.ts +14 -1
- package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
- package/packages/pi-ai/tsconfig.json +1 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +721 -8
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js +5 -5
- package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +45 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -0
- 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/assistant-message.d.ts +12 -2
- 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 +65 -28
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +9 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +52 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -0
- 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 +305 -20
- 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 +13 -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 +59 -6
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +884 -8
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +5 -5
- package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +50 -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/assistant-message.ts +78 -32
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +73 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +9 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +381 -39
- 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 +79 -6
- package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
- package/packages/pi-coding-agent/tsconfig.json +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +60 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +8 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +32 -3
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/tui.test.ts +76 -1
- package/packages/pi-tui/src/tui.ts +31 -3
- package/packages/pi-tui/tsconfig.json +1 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/tsconfig.json +1 -0
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +107 -5
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +111 -2
- package/src/resources/extensions/gsd/activity-log.ts +21 -0
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +12 -4
- package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -0
- package/src/resources/extensions/gsd/auto/loop.ts +159 -10
- package/src/resources/extensions/gsd/auto/phases.ts +213 -13
- package/src/resources/extensions/gsd/auto/session.ts +10 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +26 -10
- package/src/resources/extensions/gsd/auto-model-selection.ts +151 -16
- package/src/resources/extensions/gsd/auto-post-unit.ts +278 -16
- package/src/resources/extensions/gsd/auto-prompts.ts +13 -0
- package/src/resources/extensions/gsd/auto-start.ts +30 -6
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +17 -0
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +25 -1
- package/src/resources/extensions/gsd/auto-verification.ts +225 -3
- package/src/resources/extensions/gsd/auto.ts +72 -16
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +38 -8
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +52 -2
- package/src/resources/extensions/gsd/commands/catalog.ts +26 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +25 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +74 -9
- package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
- package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
- package/src/resources/extensions/gsd/commands-do.ts +109 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +304 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +8 -2
- package/src/resources/extensions/gsd/commands-maintenance.ts +6 -6
- package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
- package/src/resources/extensions/gsd/commands-ship.ts +219 -0
- package/src/resources/extensions/gsd/db-writer.ts +3 -5
- package/src/resources/extensions/gsd/docs/preferences-reference.md +15 -2
- 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 +212 -0
- package/src/resources/extensions/gsd/gsd-db.ts +788 -3
- package/src/resources/extensions/gsd/guided-flow.ts +32 -0
- package/src/resources/extensions/gsd/index.ts +18 -2
- package/src/resources/extensions/gsd/init-wizard.ts +3 -2
- package/src/resources/extensions/gsd/journal.ts +30 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -5
- package/src/resources/extensions/gsd/memory-store.ts +31 -62
- package/src/resources/extensions/gsd/metrics.ts +26 -0
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +13 -14
- package/src/resources/extensions/gsd/native-git-bridge.ts +11 -12
- package/src/resources/extensions/gsd/notification-widget.ts +2 -2
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +40 -1
- package/src/resources/extensions/gsd/preferences-models.ts +61 -3
- package/src/resources/extensions/gsd/preferences-types.ts +44 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +130 -2
- package/src/resources/extensions/gsd/preferences.ts +28 -0
- package/src/resources/extensions/gsd/prompts/add-tests.md +35 -0
- 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/state.ts +80 -17
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +18 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +9 -5
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +51 -2
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +6 -2
- package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/commands-do.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +340 -0
- package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +142 -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/completed-at-reconcile.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +68 -8
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +10 -7
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +137 -1
- package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
- 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/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +68 -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/model-isolation.test.ts +91 -2
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +140 -0
- 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/preferences.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +9 -6
- 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-stuck-guard.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +223 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +48 -3
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +3 -11
- package/src/resources/extensions/gsd/triage-resolution.ts +2 -7
- 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/gsd/workflow-manifest.ts +9 -104
- package/src/resources/extensions/gsd/workflow-migration.ts +21 -29
- package/src/resources/extensions/gsd/workflow-projections.ts +8 -1
- package/src/resources/extensions/gsd/workflow-reconcile.ts +15 -15
- 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/{cGmbVq2su4f9tMpgIkG8u → tqdo0yKKYz6fJXQnIgbdx}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cGmbVq2su4f9tMpgIkG8u → tqdo0yKKYz6fJXQnIgbdx}/_ssgManifest.js +0 -0
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// gsd-pi — Regression tests for the validate-milestone stuck-loop guard (#4094)
|
|
2
|
+
|
|
3
|
+
import { describe, test, mock, beforeEach, afterEach } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
import { runPostUnitVerification, type VerificationContext } from "../auto-verification.ts";
|
|
10
|
+
import { AutoSession } from "../auto/session.ts";
|
|
11
|
+
import {
|
|
12
|
+
openDatabase,
|
|
13
|
+
closeDatabase,
|
|
14
|
+
insertMilestone,
|
|
15
|
+
insertSlice,
|
|
16
|
+
} from "../gsd-db.ts";
|
|
17
|
+
import { invalidateAllCaches } from "../cache.ts";
|
|
18
|
+
import { _clearGsdRootCache } from "../paths.ts";
|
|
19
|
+
|
|
20
|
+
let tempDir: string;
|
|
21
|
+
let dbPath: string;
|
|
22
|
+
let originalCwd: string;
|
|
23
|
+
|
|
24
|
+
function makeMockCtx() {
|
|
25
|
+
return {
|
|
26
|
+
ui: {
|
|
27
|
+
notify: mock.fn(),
|
|
28
|
+
setStatus: () => {},
|
|
29
|
+
setWidget: () => {},
|
|
30
|
+
setFooter: () => {},
|
|
31
|
+
},
|
|
32
|
+
model: { id: "test-model" },
|
|
33
|
+
} as any;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function makeMockPi() {
|
|
37
|
+
return {
|
|
38
|
+
sendMessage: mock.fn(),
|
|
39
|
+
setModel: mock.fn(async () => true),
|
|
40
|
+
} as any;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function makeMockSession(basePath: string, unitType: string, unitId: string): AutoSession {
|
|
44
|
+
const s = new AutoSession();
|
|
45
|
+
s.basePath = basePath;
|
|
46
|
+
s.active = true;
|
|
47
|
+
s.pendingVerificationRetry = null;
|
|
48
|
+
s.currentUnit = { type: unitType, id: unitId, startedAt: Date.now() };
|
|
49
|
+
return s;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setupTestEnvironment(): void {
|
|
53
|
+
originalCwd = process.cwd();
|
|
54
|
+
tempDir = join(tmpdir(), `validate-milestone-guard-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
55
|
+
mkdirSync(tempDir, { recursive: true });
|
|
56
|
+
|
|
57
|
+
const milestoneDir = join(tempDir, ".gsd", "milestones", "M001");
|
|
58
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
59
|
+
|
|
60
|
+
process.chdir(tempDir);
|
|
61
|
+
_clearGsdRootCache();
|
|
62
|
+
|
|
63
|
+
dbPath = join(tempDir, ".gsd", "gsd.db");
|
|
64
|
+
openDatabase(dbPath);
|
|
65
|
+
invalidateAllCaches();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function cleanupTestEnvironment(): void {
|
|
69
|
+
try { process.chdir(originalCwd); } catch { /* ignore */ }
|
|
70
|
+
try { closeDatabase(); } catch { /* ignore */ }
|
|
71
|
+
try { rmSync(tempDir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function writeValidationFile(verdict: string): void {
|
|
75
|
+
const path = join(tempDir, ".gsd", "milestones", "M001", "M001-VALIDATION.md");
|
|
76
|
+
const content = `---
|
|
77
|
+
verdict: ${verdict}
|
|
78
|
+
remediation_round: 1
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
# Milestone Validation: M001
|
|
82
|
+
|
|
83
|
+
## Verdict Rationale
|
|
84
|
+
Test fixture
|
|
85
|
+
`;
|
|
86
|
+
writeFileSync(path, content, "utf-8");
|
|
87
|
+
invalidateAllCaches();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
describe("validate-milestone stuck-loop guard (#4094)", () => {
|
|
91
|
+
beforeEach(() => setupTestEnvironment());
|
|
92
|
+
afterEach(() => cleanupTestEnvironment());
|
|
93
|
+
|
|
94
|
+
test("pauses when verdict=needs-remediation and all slices are closed", async () => {
|
|
95
|
+
insertMilestone({ id: "M001" });
|
|
96
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|
|
97
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Slice 2", status: "done" });
|
|
98
|
+
writeValidationFile("needs-remediation");
|
|
99
|
+
|
|
100
|
+
const ctx = makeMockCtx();
|
|
101
|
+
const pi = makeMockPi();
|
|
102
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
103
|
+
const s = makeMockSession(tempDir, "validate-milestone", "M001");
|
|
104
|
+
|
|
105
|
+
const result = await runPostUnitVerification({ s, ctx, pi } as VerificationContext, pauseAutoMock);
|
|
106
|
+
|
|
107
|
+
assert.equal(result, "pause");
|
|
108
|
+
assert.equal(pauseAutoMock.mock.callCount(), 1);
|
|
109
|
+
assert.equal(ctx.ui.notify.mock.callCount(), 1);
|
|
110
|
+
const notifyArgs = ctx.ui.notify.mock.calls[0].arguments;
|
|
111
|
+
assert.match(notifyArgs[0], /needs-remediation/);
|
|
112
|
+
assert.equal(notifyArgs[1], "error");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("treats skipped slices as closed", async () => {
|
|
116
|
+
insertMilestone({ id: "M001" });
|
|
117
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|
|
118
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Slice 2", status: "skipped" });
|
|
119
|
+
writeValidationFile("needs-remediation");
|
|
120
|
+
|
|
121
|
+
const ctx = makeMockCtx();
|
|
122
|
+
const pi = makeMockPi();
|
|
123
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
124
|
+
const s = makeMockSession(tempDir, "validate-milestone", "M001");
|
|
125
|
+
|
|
126
|
+
const result = await runPostUnitVerification({ s, ctx, pi } as VerificationContext, pauseAutoMock);
|
|
127
|
+
|
|
128
|
+
assert.equal(result, "pause");
|
|
129
|
+
assert.equal(pauseAutoMock.mock.callCount(), 1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("continues when verdict=needs-remediation but a queued remediation slice exists", async () => {
|
|
133
|
+
insertMilestone({ id: "M001" });
|
|
134
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|
|
135
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Remediation", status: "queued" });
|
|
136
|
+
writeValidationFile("needs-remediation");
|
|
137
|
+
|
|
138
|
+
const ctx = makeMockCtx();
|
|
139
|
+
const pi = makeMockPi();
|
|
140
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
141
|
+
const s = makeMockSession(tempDir, "validate-milestone", "M001");
|
|
142
|
+
|
|
143
|
+
const result = await runPostUnitVerification({ s, ctx, pi } as VerificationContext, pauseAutoMock);
|
|
144
|
+
|
|
145
|
+
assert.equal(result, "continue");
|
|
146
|
+
assert.equal(pauseAutoMock.mock.callCount(), 0);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("continues when verdict is pass", async () => {
|
|
150
|
+
insertMilestone({ id: "M001" });
|
|
151
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|
|
152
|
+
writeValidationFile("pass");
|
|
153
|
+
|
|
154
|
+
const ctx = makeMockCtx();
|
|
155
|
+
const pi = makeMockPi();
|
|
156
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
157
|
+
const s = makeMockSession(tempDir, "validate-milestone", "M001");
|
|
158
|
+
|
|
159
|
+
const result = await runPostUnitVerification({ s, ctx, pi } as VerificationContext, pauseAutoMock);
|
|
160
|
+
|
|
161
|
+
assert.equal(result, "continue");
|
|
162
|
+
assert.equal(pauseAutoMock.mock.callCount(), 0);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("continues when no VALIDATION file exists yet", async () => {
|
|
166
|
+
insertMilestone({ id: "M001" });
|
|
167
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|
|
168
|
+
|
|
169
|
+
const ctx = makeMockCtx();
|
|
170
|
+
const pi = makeMockPi();
|
|
171
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
172
|
+
const s = makeMockSession(tempDir, "validate-milestone", "M001");
|
|
173
|
+
|
|
174
|
+
const result = await runPostUnitVerification({ s, ctx, pi } as VerificationContext, pauseAutoMock);
|
|
175
|
+
|
|
176
|
+
assert.equal(result, "continue");
|
|
177
|
+
assert.equal(pauseAutoMock.mock.callCount(), 0);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
@@ -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
|
});
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// GSD Extension — workflow-logger wiring regression tests
|
|
2
|
+
//
|
|
3
|
+
// Verifies the plumbing between workflow-logger and the rest of the state
|
|
4
|
+
// system (auto-loop phases, detect-stuck, notification store). Without this
|
|
5
|
+
// wiring, warnings/errors logged during a unit leak across units, never
|
|
6
|
+
// reach the user as a consolidated post-unit alert, and don't enrich
|
|
7
|
+
// stuck-detection reasons.
|
|
8
|
+
|
|
9
|
+
import test from "node:test";
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
logWarning,
|
|
16
|
+
logError,
|
|
17
|
+
peekLogs,
|
|
18
|
+
_resetLogs,
|
|
19
|
+
setStderrLoggingEnabled,
|
|
20
|
+
} from "../workflow-logger.ts";
|
|
21
|
+
import { detectStuck } from "../auto/detect-stuck.ts";
|
|
22
|
+
|
|
23
|
+
const phasesSrc = readFileSync(
|
|
24
|
+
join(import.meta.dirname, "..", "auto", "phases.ts"),
|
|
25
|
+
"utf-8",
|
|
26
|
+
);
|
|
27
|
+
const autoSrc = readFileSync(
|
|
28
|
+
join(import.meta.dirname, "..", "auto.ts"),
|
|
29
|
+
"utf-8",
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// ─── Source-scan: phases.ts calls the logger lifecycle API ─────────────────
|
|
33
|
+
|
|
34
|
+
test("auto/phases.ts imports _resetLogs, drainAndSummarize, formatForNotification, hasAnyIssues", () => {
|
|
35
|
+
assert.match(
|
|
36
|
+
phasesSrc,
|
|
37
|
+
/from\s+"\.\.\/workflow-logger\.js"/,
|
|
38
|
+
"phases.ts imports from workflow-logger",
|
|
39
|
+
);
|
|
40
|
+
for (const name of [
|
|
41
|
+
"_resetLogs",
|
|
42
|
+
"drainLogs",
|
|
43
|
+
"drainAndSummarize",
|
|
44
|
+
"formatForNotification",
|
|
45
|
+
"hasAnyIssues",
|
|
46
|
+
]) {
|
|
47
|
+
assert.ok(
|
|
48
|
+
phasesSrc.includes(name),
|
|
49
|
+
`phases.ts should reference ${name}`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("runUnitPhase calls _resetLogs() before assigning s.currentUnit", () => {
|
|
55
|
+
// Find the "s.currentUnit = { type: unitType" assignment line and check
|
|
56
|
+
// the preceding ~500 chars contain a _resetLogs() call.
|
|
57
|
+
const idx = phasesSrc.indexOf("s.currentUnit = { type: unitType");
|
|
58
|
+
assert.ok(idx > 0, "runUnitPhase should assign s.currentUnit");
|
|
59
|
+
const before = phasesSrc.slice(Math.max(0, idx - 500), idx);
|
|
60
|
+
assert.match(
|
|
61
|
+
before,
|
|
62
|
+
/_resetLogs\(\)/,
|
|
63
|
+
"_resetLogs() must be called immediately before s.currentUnit assignment",
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("runFinalize drains and surfaces logger buffer via ctx.ui.notify", () => {
|
|
68
|
+
// Locate the runFinalize success path and verify it calls drainAndSummarize
|
|
69
|
+
// and routes the result through ctx.ui.notify.
|
|
70
|
+
const runFinalizeIdx = phasesSrc.indexOf("export async function runFinalize");
|
|
71
|
+
assert.ok(runFinalizeIdx > 0, "runFinalize export should exist");
|
|
72
|
+
const finalizeBody = phasesSrc.slice(runFinalizeIdx);
|
|
73
|
+
assert.match(
|
|
74
|
+
finalizeBody,
|
|
75
|
+
/hasAnyIssues\(\)/,
|
|
76
|
+
"runFinalize should gate drain on hasAnyIssues",
|
|
77
|
+
);
|
|
78
|
+
assert.match(
|
|
79
|
+
finalizeBody,
|
|
80
|
+
/drainAndSummarize\(\)/,
|
|
81
|
+
"runFinalize should call drainAndSummarize on success",
|
|
82
|
+
);
|
|
83
|
+
assert.match(
|
|
84
|
+
finalizeBody,
|
|
85
|
+
/formatForNotification\(logs\)/,
|
|
86
|
+
"runFinalize should format drained logs for the notification",
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("runFinalize timeout branches drain the buffer to prevent bleed", () => {
|
|
91
|
+
// Both timeout branches null out s.currentUnit — they should also drain
|
|
92
|
+
// so accumulated logs for the timed-out unit don't leak into the next.
|
|
93
|
+
const runFinalizeIdx = phasesSrc.indexOf("export async function runFinalize");
|
|
94
|
+
const finalizeBody = phasesSrc.slice(runFinalizeIdx);
|
|
95
|
+
const drainCallCount =
|
|
96
|
+
(finalizeBody.match(/drainLogs\(\)/g) ?? []).length;
|
|
97
|
+
assert.ok(
|
|
98
|
+
drainCallCount >= 2,
|
|
99
|
+
`runFinalize timeout branches should each call drainLogs() (found ${drainCallCount}, expected >= 2)`,
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// ─── Source-scan: auto.ts calls setLogBasePath in startAuto ────────────────
|
|
104
|
+
|
|
105
|
+
test("startAuto calls setLogBasePath(base) so audit log is pinned on resume", () => {
|
|
106
|
+
const startAutoIdx = autoSrc.indexOf("export async function startAuto");
|
|
107
|
+
assert.ok(startAutoIdx > 0, "startAuto export should exist");
|
|
108
|
+
const body = autoSrc.slice(startAutoIdx);
|
|
109
|
+
assert.match(
|
|
110
|
+
body,
|
|
111
|
+
/setLogBasePath\(base\)/,
|
|
112
|
+
"startAuto must call setLogBasePath(base) to pin the audit log",
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// ─── Runtime: detect-stuck enriches reason with summarizeLogs() ────────────
|
|
117
|
+
|
|
118
|
+
test("detectStuck reason includes workflow-logger summary when logs present", () => {
|
|
119
|
+
setStderrLoggingEnabled(false);
|
|
120
|
+
try {
|
|
121
|
+
_resetLogs();
|
|
122
|
+
logWarning("projection", "STATE.md render failed");
|
|
123
|
+
logError("db", "WAL checkpoint failed");
|
|
124
|
+
|
|
125
|
+
const result = detectStuck([
|
|
126
|
+
{ key: "execute-task/slice-A/task-1", error: "ENOENT: no such file" },
|
|
127
|
+
{ key: "execute-task/slice-A/task-1", error: "ENOENT: no such file" },
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
assert.notEqual(result, null);
|
|
131
|
+
assert.equal(result!.stuck, true);
|
|
132
|
+
assert.match(
|
|
133
|
+
result!.reason,
|
|
134
|
+
/Same error repeated:/,
|
|
135
|
+
"reason should still start with the rule string",
|
|
136
|
+
);
|
|
137
|
+
assert.match(
|
|
138
|
+
result!.reason,
|
|
139
|
+
/STATE\.md render failed/,
|
|
140
|
+
"reason should include the accumulated logger warning",
|
|
141
|
+
);
|
|
142
|
+
assert.match(
|
|
143
|
+
result!.reason,
|
|
144
|
+
/WAL checkpoint failed/,
|
|
145
|
+
"reason should include the accumulated logger error",
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Critical: summarizeLogs must not drain — the auto-loop's finalize
|
|
149
|
+
// step owns the buffer lifecycle, detect-stuck is read-only.
|
|
150
|
+
assert.equal(
|
|
151
|
+
peekLogs().length,
|
|
152
|
+
2,
|
|
153
|
+
"detect-stuck must not drain the buffer",
|
|
154
|
+
);
|
|
155
|
+
} finally {
|
|
156
|
+
_resetLogs();
|
|
157
|
+
setStderrLoggingEnabled(true);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("detectStuck reason unchanged when logger buffer is empty", () => {
|
|
162
|
+
setStderrLoggingEnabled(false);
|
|
163
|
+
try {
|
|
164
|
+
_resetLogs();
|
|
165
|
+
const result = detectStuck([
|
|
166
|
+
{ key: "A", error: "boom" },
|
|
167
|
+
{ key: "A", error: "boom" },
|
|
168
|
+
]);
|
|
169
|
+
assert.notEqual(result, null);
|
|
170
|
+
// No trailing " — " suffix when there are no logs to summarize.
|
|
171
|
+
assert.doesNotMatch(
|
|
172
|
+
result!.reason,
|
|
173
|
+
/ — \d+ (error|warning)/,
|
|
174
|
+
"reason should have no logger suffix when buffer is empty",
|
|
175
|
+
);
|
|
176
|
+
} finally {
|
|
177
|
+
setStderrLoggingEnabled(true);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// ─── Runtime: readTransaction rollback failure surfaces via logError ────────
|
|
182
|
+
//
|
|
183
|
+
// snapshotState now delegates its transaction to readTransaction() in
|
|
184
|
+
// gsd-db.ts (single-writer refactor in #4198), so the split-brain
|
|
185
|
+
// ROLLBACK-failure log lives there, not in workflow-manifest.ts.
|
|
186
|
+
|
|
187
|
+
test("readTransaction logs ROLLBACK failures as split-brain signal", () => {
|
|
188
|
+
const dbSrc = readFileSync(
|
|
189
|
+
join(import.meta.dirname, "..", "gsd-db.ts"),
|
|
190
|
+
"utf-8",
|
|
191
|
+
);
|
|
192
|
+
assert.match(
|
|
193
|
+
dbSrc,
|
|
194
|
+
/logError\("db",\s*"snapshotState ROLLBACK failed"/,
|
|
195
|
+
"readTransaction ROLLBACK catch should call logError",
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// ─── Runtime: state.ts and workflow-projections.ts log silent bailouts ─────
|
|
200
|
+
|
|
201
|
+
test("state.ts logs roadmap read failures instead of silently continuing", () => {
|
|
202
|
+
const stateSrc = readFileSync(
|
|
203
|
+
join(import.meta.dirname, "..", "state.ts"),
|
|
204
|
+
"utf-8",
|
|
205
|
+
);
|
|
206
|
+
assert.match(
|
|
207
|
+
stateSrc,
|
|
208
|
+
/logWarning\("state",\s*"reconcileDiskToDb: roadmap read failed/,
|
|
209
|
+
"state.ts reconcileDiskToDb should log roadmap read failures",
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("workflow-projections.ts logs DB probe failures instead of silent return", () => {
|
|
214
|
+
const projectionsSrc = readFileSync(
|
|
215
|
+
join(import.meta.dirname, "..", "workflow-projections.ts"),
|
|
216
|
+
"utf-8",
|
|
217
|
+
);
|
|
218
|
+
assert.match(
|
|
219
|
+
projectionsSrc,
|
|
220
|
+
/logWarning\("projection",\s*"renderStateProjection: DB handle probe failed/,
|
|
221
|
+
"renderStateProjection DB probe should log on failure",
|
|
222
|
+
);
|
|
223
|
+
});
|
|
@@ -424,6 +424,32 @@ export async function handleCompleteSlice(
|
|
|
424
424
|
logError("tool", `complete-slice event log FAILED — completion invisible to reconciliation`, { error: (eventErr as Error).message });
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
+
// Fire-and-forget graph rebuild — must NOT await, must NOT crash slice completion.
|
|
428
|
+
// Dynamic import of the package name (not a relative path) so it resolves
|
|
429
|
+
// correctly via package.json#exports in both development and production.
|
|
430
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
431
|
+
(async () => {
|
|
432
|
+
try {
|
|
433
|
+
const graphMod = await import("@gsd-build/mcp-server") as unknown as Partial<{
|
|
434
|
+
buildGraph: (dir: string) => Promise<{ nodes: unknown[]; edges: unknown[]; builtAt: string }>;
|
|
435
|
+
writeGraph: (gsdRoot: string, graph: unknown) => Promise<void>;
|
|
436
|
+
resolveGsdRoot: (basePath: string) => string;
|
|
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
|
+
}
|
|
445
|
+
const g = await graphMod.buildGraph(basePath);
|
|
446
|
+
await graphMod.writeGraph(graphMod.resolveGsdRoot(basePath), g);
|
|
447
|
+
} catch (graphErr) {
|
|
448
|
+
// Graph rebuild is best-effort — log at warning level but never propagate
|
|
449
|
+
logWarning("tool", `complete-slice graph rebuild failed (non-fatal): ${(graphErr as Error).message ?? String(graphErr)}`);
|
|
450
|
+
}
|
|
451
|
+
})();
|
|
452
|
+
|
|
427
453
|
return {
|
|
428
454
|
sliceId: params.sliceId,
|
|
429
455
|
milestoneId: params.milestoneId,
|