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
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
10
12
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
11
13
|
import { defaultRoutingConfig } from "./model-router.js";
|
|
12
14
|
import type { TokenProfile, InlineLevel } from "./types.js";
|
|
@@ -185,6 +187,45 @@ export function resolveDefaultSessionModel(
|
|
|
185
187
|
return undefined;
|
|
186
188
|
}
|
|
187
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Returns true if `provider` is defined as a custom provider in the user's
|
|
192
|
+
* `~/.gsd/agent/models.json` (Ollama, vLLM, LM Studio, OpenAI-compatible
|
|
193
|
+
* proxies, etc.).
|
|
194
|
+
*
|
|
195
|
+
* Used by auto-mode bootstrap to decide whether the session model
|
|
196
|
+
* (set via `/gsd model`) should override `PREFERENCES.md`. Custom providers
|
|
197
|
+
* are never reachable from `PREFERENCES.md` (which only knows built-in
|
|
198
|
+
* providers), so when the user has explicitly selected one, it must take
|
|
199
|
+
* priority — otherwise auto-mode tries to start the built-in provider from
|
|
200
|
+
* PREFERENCES.md and fails with "Not logged in · Please run /login" (#4122).
|
|
201
|
+
*
|
|
202
|
+
* Reads models.json directly with a lightweight JSON parse to avoid
|
|
203
|
+
* pulling in the full model-registry at this call site. Falls back to
|
|
204
|
+
* `~/.pi/agent/models.json` for parity with `resolveModelsJsonPath()`.
|
|
205
|
+
* Any read or parse error yields `false` (treat as not-custom) so a
|
|
206
|
+
* malformed models.json never breaks the session bootstrap.
|
|
207
|
+
*/
|
|
208
|
+
export function isCustomProvider(provider: string | undefined): boolean {
|
|
209
|
+
if (!provider) return false;
|
|
210
|
+
const candidates = [
|
|
211
|
+
join(homedir(), ".gsd", "agent", "models.json"),
|
|
212
|
+
join(homedir(), ".pi", "agent", "models.json"),
|
|
213
|
+
];
|
|
214
|
+
for (const path of candidates) {
|
|
215
|
+
if (!existsSync(path)) continue;
|
|
216
|
+
try {
|
|
217
|
+
const raw = readFileSync(path, "utf-8");
|
|
218
|
+
const parsed = JSON.parse(raw) as { providers?: Record<string, unknown> };
|
|
219
|
+
if (parsed?.providers && Object.prototype.hasOwnProperty.call(parsed.providers, provider)) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
} catch {
|
|
223
|
+
// Ignore — malformed models.json must not break bootstrap.
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
188
229
|
/**
|
|
189
230
|
* Determines the next fallback model to try when the current model fails.
|
|
190
231
|
* If the current model is not in the configured list, returns the primary model.
|
|
@@ -314,7 +355,7 @@ export function resolveAutoSupervisorConfig(): AutoSupervisorConfig {
|
|
|
314
355
|
|
|
315
356
|
// ─── Token Profile Resolution ─────────────────────────────────────────────
|
|
316
357
|
|
|
317
|
-
const VALID_TOKEN_PROFILES = new Set<TokenProfile>(["budget", "balanced", "quality"]);
|
|
358
|
+
const VALID_TOKEN_PROFILES = new Set<TokenProfile>(["budget", "balanced", "quality", "burn-max"]);
|
|
318
359
|
|
|
319
360
|
/**
|
|
320
361
|
* Resolve profile defaults for a given token profile tier.
|
|
@@ -359,6 +400,22 @@ export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPrefer
|
|
|
359
400
|
skip_reassess: true,
|
|
360
401
|
},
|
|
361
402
|
};
|
|
403
|
+
case "burn-max":
|
|
404
|
+
return {
|
|
405
|
+
// Quality-first profile: keep user-selected models, disable downgrade routing.
|
|
406
|
+
// Policy constraints still apply at dispatch time.
|
|
407
|
+
dynamic_routing: {
|
|
408
|
+
enabled: false,
|
|
409
|
+
},
|
|
410
|
+
context_selection: "full",
|
|
411
|
+
phases: {
|
|
412
|
+
skip_research: false,
|
|
413
|
+
skip_slice_research: false,
|
|
414
|
+
skip_reassess: false,
|
|
415
|
+
skip_milestone_validation: false,
|
|
416
|
+
reassess_after_slice: true,
|
|
417
|
+
},
|
|
418
|
+
};
|
|
362
419
|
}
|
|
363
420
|
}
|
|
364
421
|
|
|
@@ -375,7 +432,7 @@ export function resolveEffectiveProfile(): TokenProfile {
|
|
|
375
432
|
|
|
376
433
|
/**
|
|
377
434
|
* Resolve the inline level from the active token profile.
|
|
378
|
-
* budget -> minimal, balanced -> standard, quality -> full.
|
|
435
|
+
* budget -> minimal, balanced -> standard, quality/burn-max -> full.
|
|
379
436
|
*/
|
|
380
437
|
export function resolveInlineLevel(): InlineLevel {
|
|
381
438
|
const profile = resolveEffectiveProfile();
|
|
@@ -383,12 +440,13 @@ export function resolveInlineLevel(): InlineLevel {
|
|
|
383
440
|
case "budget": return "minimal";
|
|
384
441
|
case "balanced": return "standard";
|
|
385
442
|
case "quality": return "full";
|
|
443
|
+
case "burn-max": return "full";
|
|
386
444
|
}
|
|
387
445
|
}
|
|
388
446
|
|
|
389
447
|
/**
|
|
390
448
|
* Resolve the context selection mode from the active token profile.
|
|
391
|
-
* budget -> "smart", balanced/quality -> "full".
|
|
449
|
+
* budget -> "smart", balanced/quality/burn-max -> "full".
|
|
392
450
|
* Explicit preference always wins.
|
|
393
451
|
*/
|
|
394
452
|
export function resolveContextSelection(): import("./types.js").ContextSelectionMode {
|
|
@@ -83,6 +83,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
83
83
|
"post_unit_hooks",
|
|
84
84
|
"pre_dispatch_hooks",
|
|
85
85
|
"dynamic_routing",
|
|
86
|
+
"uok",
|
|
86
87
|
"token_profile",
|
|
87
88
|
"phases",
|
|
88
89
|
"auto_visualize",
|
|
@@ -113,6 +114,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
113
114
|
"discuss_preparation",
|
|
114
115
|
"discuss_web_research",
|
|
115
116
|
"discuss_depth",
|
|
117
|
+
"flat_rate_providers",
|
|
116
118
|
]);
|
|
117
119
|
|
|
118
120
|
/** Canonical list of all dispatch unit types. */
|
|
@@ -207,6 +209,35 @@ export interface CmuxPreferences {
|
|
|
207
209
|
browser?: boolean;
|
|
208
210
|
}
|
|
209
211
|
|
|
212
|
+
export type UokTurnActionMode = "commit" | "snapshot" | "status-only";
|
|
213
|
+
|
|
214
|
+
export interface UokPreferences {
|
|
215
|
+
enabled?: boolean;
|
|
216
|
+
legacy_fallback?: {
|
|
217
|
+
enabled?: boolean;
|
|
218
|
+
};
|
|
219
|
+
gates?: {
|
|
220
|
+
enabled?: boolean;
|
|
221
|
+
};
|
|
222
|
+
model_policy?: {
|
|
223
|
+
enabled?: boolean;
|
|
224
|
+
};
|
|
225
|
+
execution_graph?: {
|
|
226
|
+
enabled?: boolean;
|
|
227
|
+
};
|
|
228
|
+
gitops?: {
|
|
229
|
+
enabled?: boolean;
|
|
230
|
+
turn_action?: UokTurnActionMode;
|
|
231
|
+
turn_push?: boolean;
|
|
232
|
+
};
|
|
233
|
+
audit_unified?: {
|
|
234
|
+
enabled?: boolean;
|
|
235
|
+
};
|
|
236
|
+
plan_v2?: {
|
|
237
|
+
enabled?: boolean;
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
210
241
|
/**
|
|
211
242
|
* Opt-in experimental features. All features in this block are disabled by
|
|
212
243
|
* default and must be explicitly enabled. They may change or be removed without
|
|
@@ -255,6 +286,8 @@ export interface GSDPreferences {
|
|
|
255
286
|
post_unit_hooks?: PostUnitHookConfig[];
|
|
256
287
|
pre_dispatch_hooks?: PreDispatchHookConfig[];
|
|
257
288
|
dynamic_routing?: DynamicRoutingConfig;
|
|
289
|
+
/** Unified Orchestration Kernel controls (all flags default off). */
|
|
290
|
+
uok?: UokPreferences;
|
|
258
291
|
/** Per-model capability overrides. Deep-merged with built-in profiles for capability-aware routing (ADR-004). */
|
|
259
292
|
modelOverrides?: Record<string, { capabilities?: Partial<ModelCapabilities> }>;
|
|
260
293
|
context_management?: ContextManagementConfig;
|
|
@@ -359,6 +392,17 @@ export interface GSDPreferences {
|
|
|
359
392
|
* Default: "standard".
|
|
360
393
|
*/
|
|
361
394
|
discuss_depth?: "quick" | "standard" | "thorough";
|
|
395
|
+
/**
|
|
396
|
+
* Extra provider IDs to treat as flat-rate (no cost benefit from dynamic
|
|
397
|
+
* routing). Dynamic routing is suppressed for any provider listed here,
|
|
398
|
+
* in addition to the built-in list (github-copilot, copilot, claude-code)
|
|
399
|
+
* and any provider auto-detected via `authMode: "externalCli"`.
|
|
400
|
+
*
|
|
401
|
+
* Intended for private subscription-backed proxies, enterprise-gated
|
|
402
|
+
* deployments, and custom CLI wrappers where every request costs the
|
|
403
|
+
* same regardless of model. Case-insensitive.
|
|
404
|
+
*/
|
|
405
|
+
flat_rate_providers?: string[];
|
|
362
406
|
}
|
|
363
407
|
|
|
364
408
|
export interface LoadedGSDPreferences {
|
|
@@ -22,7 +22,12 @@ import {
|
|
|
22
22
|
type GSDSkillRule,
|
|
23
23
|
} from "./preferences-types.js";
|
|
24
24
|
|
|
25
|
-
const VALID_TOKEN_PROFILES = new Set<TokenProfile>(["budget", "balanced", "quality"]);
|
|
25
|
+
const VALID_TOKEN_PROFILES = new Set<TokenProfile>(["budget", "balanced", "quality", "burn-max"]);
|
|
26
|
+
const VALID_UOK_TURN_ACTIONS = new Set<"commit" | "snapshot" | "status-only">([
|
|
27
|
+
"commit",
|
|
28
|
+
"snapshot",
|
|
29
|
+
"status-only",
|
|
30
|
+
]);
|
|
26
31
|
|
|
27
32
|
export function validatePreferences(preferences: GSDPreferences): {
|
|
28
33
|
preferences: GSDPreferences;
|
|
@@ -161,12 +166,112 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
161
166
|
}
|
|
162
167
|
}
|
|
163
168
|
|
|
169
|
+
// ─── UOK Flags ──────────────────────────────────────────────────────
|
|
170
|
+
if (preferences.uok !== undefined) {
|
|
171
|
+
if (typeof preferences.uok === "object" && preferences.uok !== null) {
|
|
172
|
+
const raw = preferences.uok as Record<string, unknown>;
|
|
173
|
+
const valid: NonNullable<GSDPreferences["uok"]> = {};
|
|
174
|
+
|
|
175
|
+
if (raw.enabled !== undefined) {
|
|
176
|
+
if (typeof raw.enabled === "boolean") valid.enabled = raw.enabled;
|
|
177
|
+
else errors.push("uok.enabled must be a boolean");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const parseEnabledBlock = (
|
|
181
|
+
key: "legacy_fallback" | "gates" | "model_policy" | "execution_graph" | "audit_unified" | "plan_v2",
|
|
182
|
+
): void => {
|
|
183
|
+
const value = raw[key];
|
|
184
|
+
if (value === undefined) return;
|
|
185
|
+
if (typeof value !== "object" || value === null) {
|
|
186
|
+
errors.push(`uok.${key} must be an object`);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const block = value as Record<string, unknown>;
|
|
190
|
+
const parsed: { enabled?: boolean } = {};
|
|
191
|
+
if (block.enabled !== undefined) {
|
|
192
|
+
if (typeof block.enabled === "boolean") parsed.enabled = block.enabled;
|
|
193
|
+
else errors.push(`uok.${key}.enabled must be a boolean`);
|
|
194
|
+
}
|
|
195
|
+
const unknown = Object.keys(block).filter((k) => k !== "enabled");
|
|
196
|
+
for (const unk of unknown) {
|
|
197
|
+
warnings.push(`unknown uok.${key} key "${unk}" — ignored`);
|
|
198
|
+
}
|
|
199
|
+
if (Object.keys(parsed).length > 0) {
|
|
200
|
+
valid[key] = parsed;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
parseEnabledBlock("legacy_fallback");
|
|
205
|
+
parseEnabledBlock("gates");
|
|
206
|
+
parseEnabledBlock("model_policy");
|
|
207
|
+
parseEnabledBlock("execution_graph");
|
|
208
|
+
parseEnabledBlock("audit_unified");
|
|
209
|
+
parseEnabledBlock("plan_v2");
|
|
210
|
+
|
|
211
|
+
if (raw.gitops !== undefined) {
|
|
212
|
+
if (typeof raw.gitops !== "object" || raw.gitops === null) {
|
|
213
|
+
errors.push("uok.gitops must be an object");
|
|
214
|
+
} else {
|
|
215
|
+
const gitops = raw.gitops as Record<string, unknown>;
|
|
216
|
+
const parsed: NonNullable<NonNullable<GSDPreferences["uok"]>["gitops"]> = {};
|
|
217
|
+
if (gitops.enabled !== undefined) {
|
|
218
|
+
if (typeof gitops.enabled === "boolean") parsed.enabled = gitops.enabled;
|
|
219
|
+
else errors.push("uok.gitops.enabled must be a boolean");
|
|
220
|
+
}
|
|
221
|
+
if (gitops.turn_action !== undefined) {
|
|
222
|
+
if (
|
|
223
|
+
typeof gitops.turn_action === "string" &&
|
|
224
|
+
VALID_UOK_TURN_ACTIONS.has(gitops.turn_action as "commit" | "snapshot" | "status-only")
|
|
225
|
+
) {
|
|
226
|
+
parsed.turn_action = gitops.turn_action as "commit" | "snapshot" | "status-only";
|
|
227
|
+
} else {
|
|
228
|
+
errors.push("uok.gitops.turn_action must be one of: commit, snapshot, status-only");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (gitops.turn_push !== undefined) {
|
|
232
|
+
if (typeof gitops.turn_push === "boolean") parsed.turn_push = gitops.turn_push;
|
|
233
|
+
else errors.push("uok.gitops.turn_push must be a boolean");
|
|
234
|
+
}
|
|
235
|
+
const unknown = Object.keys(gitops).filter((k) => !["enabled", "turn_action", "turn_push"].includes(k));
|
|
236
|
+
for (const unk of unknown) {
|
|
237
|
+
warnings.push(`unknown uok.gitops key "${unk}" — ignored`);
|
|
238
|
+
}
|
|
239
|
+
if (Object.keys(parsed).length > 0) {
|
|
240
|
+
valid.gitops = parsed;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const knownUokKeys = new Set([
|
|
246
|
+
"enabled",
|
|
247
|
+
"legacy_fallback",
|
|
248
|
+
"gates",
|
|
249
|
+
"model_policy",
|
|
250
|
+
"execution_graph",
|
|
251
|
+
"gitops",
|
|
252
|
+
"audit_unified",
|
|
253
|
+
"plan_v2",
|
|
254
|
+
]);
|
|
255
|
+
for (const key of Object.keys(raw)) {
|
|
256
|
+
if (!knownUokKeys.has(key)) {
|
|
257
|
+
warnings.push(`unknown uok key "${key}" — ignored`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (Object.keys(valid).length > 0) {
|
|
262
|
+
validated.uok = valid;
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
errors.push("uok must be an object");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
164
269
|
// ─── Token Profile ─────────────────────────────────────────────────
|
|
165
270
|
if (preferences.token_profile !== undefined) {
|
|
166
271
|
if (typeof preferences.token_profile === "string" && VALID_TOKEN_PROFILES.has(preferences.token_profile as TokenProfile)) {
|
|
167
272
|
validated.token_profile = preferences.token_profile as TokenProfile;
|
|
168
273
|
} else {
|
|
169
|
-
errors.push(`token_profile must be one of: budget, balanced, quality`);
|
|
274
|
+
errors.push(`token_profile must be one of: budget, balanced, quality, burn-max`);
|
|
170
275
|
}
|
|
171
276
|
}
|
|
172
277
|
|
|
@@ -180,6 +285,29 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
180
285
|
}
|
|
181
286
|
}
|
|
182
287
|
|
|
288
|
+
// ─── Flat-rate Providers ────────────────────────────────────────────
|
|
289
|
+
// User-declared flat-rate providers for dynamic routing suppression.
|
|
290
|
+
// Built-in providers (github-copilot, copilot, claude-code) and any
|
|
291
|
+
// externalCli provider are already auto-detected; this list layers on
|
|
292
|
+
// top for private subscription proxies and custom CLI wrappers.
|
|
293
|
+
if (preferences.flat_rate_providers !== undefined) {
|
|
294
|
+
if (Array.isArray(preferences.flat_rate_providers)) {
|
|
295
|
+
const allStrings = preferences.flat_rate_providers.every(
|
|
296
|
+
(item: unknown) => typeof item === "string",
|
|
297
|
+
);
|
|
298
|
+
if (allStrings) {
|
|
299
|
+
// Strip empty/whitespace-only entries to avoid false matches.
|
|
300
|
+
validated.flat_rate_providers = preferences.flat_rate_providers
|
|
301
|
+
.map((s: string) => s.trim())
|
|
302
|
+
.filter((s: string) => s.length > 0);
|
|
303
|
+
} else {
|
|
304
|
+
errors.push("flat_rate_providers must be an array of strings");
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
errors.push("flat_rate_providers must be an array of strings");
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
183
311
|
// ─── Phase Skip Preferences ─────────────────────────────────────────
|
|
184
312
|
if (preferences.phases !== undefined) {
|
|
185
313
|
if (typeof preferences.phases === "object" && preferences.phases !== null) {
|
|
@@ -50,6 +50,8 @@ export type {
|
|
|
50
50
|
AutoSupervisorConfig,
|
|
51
51
|
RemoteQuestionsConfig,
|
|
52
52
|
CmuxPreferences,
|
|
53
|
+
UokTurnActionMode,
|
|
54
|
+
UokPreferences,
|
|
53
55
|
CodebaseMapPreferences,
|
|
54
56
|
GSDPreferences,
|
|
55
57
|
LoadedGSDPreferences,
|
|
@@ -378,6 +380,32 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
|
|
|
378
380
|
dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
|
|
379
381
|
? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) } as DynamicRoutingConfig
|
|
380
382
|
: undefined,
|
|
383
|
+
uok: (base.uok || override.uok)
|
|
384
|
+
? {
|
|
385
|
+
enabled: override.uok?.enabled ?? base.uok?.enabled,
|
|
386
|
+
legacy_fallback: (base.uok?.legacy_fallback || override.uok?.legacy_fallback)
|
|
387
|
+
? { ...(base.uok?.legacy_fallback ?? {}), ...(override.uok?.legacy_fallback ?? {}) }
|
|
388
|
+
: undefined,
|
|
389
|
+
gates: (base.uok?.gates || override.uok?.gates)
|
|
390
|
+
? { ...(base.uok?.gates ?? {}), ...(override.uok?.gates ?? {}) }
|
|
391
|
+
: undefined,
|
|
392
|
+
model_policy: (base.uok?.model_policy || override.uok?.model_policy)
|
|
393
|
+
? { ...(base.uok?.model_policy ?? {}), ...(override.uok?.model_policy ?? {}) }
|
|
394
|
+
: undefined,
|
|
395
|
+
execution_graph: (base.uok?.execution_graph || override.uok?.execution_graph)
|
|
396
|
+
? { ...(base.uok?.execution_graph ?? {}), ...(override.uok?.execution_graph ?? {}) }
|
|
397
|
+
: undefined,
|
|
398
|
+
gitops: (base.uok?.gitops || override.uok?.gitops)
|
|
399
|
+
? { ...(base.uok?.gitops ?? {}), ...(override.uok?.gitops ?? {}) }
|
|
400
|
+
: undefined,
|
|
401
|
+
audit_unified: (base.uok?.audit_unified || override.uok?.audit_unified)
|
|
402
|
+
? { ...(base.uok?.audit_unified ?? {}), ...(override.uok?.audit_unified ?? {}) }
|
|
403
|
+
: undefined,
|
|
404
|
+
plan_v2: (base.uok?.plan_v2 || override.uok?.plan_v2)
|
|
405
|
+
? { ...(base.uok?.plan_v2 ?? {}), ...(override.uok?.plan_v2 ?? {}) }
|
|
406
|
+
: undefined,
|
|
407
|
+
}
|
|
408
|
+
: undefined,
|
|
381
409
|
token_profile: override.token_profile ?? base.token_profile,
|
|
382
410
|
phases: (base.phases || override.phases)
|
|
383
411
|
? { ...(base.phases ?? {}), ...(override.phases ?? {}) }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
You are generating tests for recently completed GSD work.
|
|
2
|
+
|
|
3
|
+
## Slice: {{sliceId}} — {{sliceTitle}}
|
|
4
|
+
|
|
5
|
+
### Summary
|
|
6
|
+
|
|
7
|
+
{{sliceSummary}}
|
|
8
|
+
|
|
9
|
+
### Existing Test Patterns
|
|
10
|
+
|
|
11
|
+
{{existingTestPatterns}}
|
|
12
|
+
|
|
13
|
+
## Working Directory
|
|
14
|
+
|
|
15
|
+
`{{workingDirectory}}`
|
|
16
|
+
|
|
17
|
+
## Instructions
|
|
18
|
+
|
|
19
|
+
1. Read the slice summary above to understand what was built
|
|
20
|
+
2. Identify the source files that were created or modified for this slice
|
|
21
|
+
3. Read the implementation code to understand behavior, edge cases, and error paths
|
|
22
|
+
4. Write comprehensive tests following the project's existing test patterns and framework
|
|
23
|
+
5. Run the tests to verify they pass
|
|
24
|
+
6. Fix any failures
|
|
25
|
+
|
|
26
|
+
### Rules
|
|
27
|
+
|
|
28
|
+
- Follow the project's existing test patterns (framework, assertions, file structure)
|
|
29
|
+
- Test behavior, not implementation details
|
|
30
|
+
- Cover: happy path, edge cases, error conditions, boundary values
|
|
31
|
+
- Do NOT modify implementation files — only create or update test files
|
|
32
|
+
- Name test files consistently with the project's conventions
|
|
33
|
+
- Keep tests focused and readable
|
|
34
|
+
|
|
35
|
+
{{skillActivation}}
|
|
@@ -52,6 +52,18 @@ export interface SessionLockStatus {
|
|
|
52
52
|
recovered?: boolean;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
interface ProperLockfileApi {
|
|
56
|
+
lockSync(
|
|
57
|
+
path: string,
|
|
58
|
+
options?: {
|
|
59
|
+
realpath?: boolean;
|
|
60
|
+
stale?: number;
|
|
61
|
+
update?: number;
|
|
62
|
+
onCompromised?: () => void;
|
|
63
|
+
},
|
|
64
|
+
): () => void;
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
// ─── Module State ───────────────────────────────────────────────────────────
|
|
56
68
|
|
|
57
69
|
/** Release function from proper-lockfile — calling it releases the OS lock. */
|
|
@@ -277,9 +289,9 @@ export function acquireSessionLock(basePath: string): SessionLockResult {
|
|
|
277
289
|
unitStartedAt: new Date().toISOString(),
|
|
278
290
|
};
|
|
279
291
|
|
|
280
|
-
let lockfile:
|
|
292
|
+
let lockfile: ProperLockfileApi;
|
|
281
293
|
try {
|
|
282
|
-
lockfile = _require("proper-lockfile") as
|
|
294
|
+
lockfile = _require("proper-lockfile") as ProperLockfileApi;
|
|
283
295
|
} catch {
|
|
284
296
|
// proper-lockfile not available — fall back to PID-based check
|
|
285
297
|
return acquireFallbackLock(basePath, lp, lockData);
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
} from "./session-status-io.js";
|
|
33
33
|
import { hasFileConflict } from "./slice-parallel-conflict.js";
|
|
34
34
|
import { getErrorMessage } from "./error-utils.js";
|
|
35
|
+
import { selectConflictFreeBatch } from "./uok/execution-graph.js";
|
|
35
36
|
|
|
36
37
|
// ─── Types ─────────────────────────────────────────────────────────────────
|
|
37
38
|
|
|
@@ -61,6 +62,7 @@ export interface SliceOrchestratorState {
|
|
|
61
62
|
export interface StartSliceParallelOpts {
|
|
62
63
|
maxWorkers?: number;
|
|
63
64
|
budgetCeiling?: number;
|
|
65
|
+
useExecutionGraph?: boolean;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
// ─── Module State ──────────────────────────────────────────────────────────
|
|
@@ -118,7 +120,12 @@ export async function startSliceParallel(
|
|
|
118
120
|
const errors: Array<{ sid: string; error: string }> = [];
|
|
119
121
|
|
|
120
122
|
// Filter out conflicting slices (conservative: check all pairs)
|
|
121
|
-
const safeSlices = filterConflictingSlices(
|
|
123
|
+
const safeSlices = filterConflictingSlices(
|
|
124
|
+
basePath,
|
|
125
|
+
milestoneId,
|
|
126
|
+
eligibleSlices,
|
|
127
|
+
opts.useExecutionGraph === true,
|
|
128
|
+
);
|
|
122
129
|
|
|
123
130
|
// Limit to maxWorkers
|
|
124
131
|
const toSpawn = safeSlices.slice(0, maxWorkers);
|
|
@@ -245,7 +252,19 @@ function filterConflictingSlices(
|
|
|
245
252
|
basePath: string,
|
|
246
253
|
milestoneId: string,
|
|
247
254
|
slices: Array<{ id: string }>,
|
|
255
|
+
useExecutionGraph: boolean,
|
|
248
256
|
): Array<{ id: string }> {
|
|
257
|
+
if (useExecutionGraph) {
|
|
258
|
+
const selectedIds = selectConflictFreeBatch({
|
|
259
|
+
orderedIds: slices.map((slice) => slice.id),
|
|
260
|
+
maxParallel: slices.length,
|
|
261
|
+
hasConflict: (candidate, existing) =>
|
|
262
|
+
hasFileConflict(basePath, milestoneId, candidate, existing),
|
|
263
|
+
});
|
|
264
|
+
const selected = new Set(selectedIds);
|
|
265
|
+
return slices.filter((slice) => selected.has(slice.id));
|
|
266
|
+
}
|
|
267
|
+
|
|
249
268
|
const safe: Array<{ id: string }> = [];
|
|
250
269
|
|
|
251
270
|
for (const candidate of slices) {
|
|
@@ -345,8 +345,15 @@ function reconcileDiskToDb(basePath: string): MilestoneRow[] {
|
|
|
345
345
|
const dbSliceIds = new Set(dbSlices.map(s => s.id));
|
|
346
346
|
|
|
347
347
|
let roadmapContent: string;
|
|
348
|
-
try {
|
|
349
|
-
|
|
348
|
+
try {
|
|
349
|
+
roadmapContent = readFileSync(roadmapPath, "utf-8");
|
|
350
|
+
} catch (err) {
|
|
351
|
+
logWarning("state", "reconcileDiskToDb: roadmap read failed, skipping milestone", {
|
|
352
|
+
mid,
|
|
353
|
+
error: (err as Error).message,
|
|
354
|
+
});
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
350
357
|
|
|
351
358
|
const parsed = parseRoadmap(roadmapContent);
|
|
352
359
|
for (const s of parsed.slices) {
|
|
@@ -386,6 +393,10 @@ function buildCompletenessSet(basePath: string, milestones: MilestoneRow[]) {
|
|
|
386
393
|
const completeMilestoneIds = new Set<string>();
|
|
387
394
|
const parkedMilestoneIds = new Set<string>();
|
|
388
395
|
|
|
396
|
+
// DB-authoritative: a milestone is only "complete" when its DB row says so.
|
|
397
|
+
// SUMMARY-file presence is NOT a completion signal here — an orphan SUMMARY
|
|
398
|
+
// (crashed complete-milestone turn, partial merge, manual edit) must not
|
|
399
|
+
// flip derived state to complete and cascade into a false auto-merge (#4179).
|
|
389
400
|
for (const m of milestones) {
|
|
390
401
|
const parkedFile = resolveMilestoneFile(basePath, m.id, "PARKED");
|
|
391
402
|
if (parkedFile || m.status === 'parked') {
|
|
@@ -396,11 +407,6 @@ function buildCompletenessSet(basePath: string, milestones: MilestoneRow[]) {
|
|
|
396
407
|
completeMilestoneIds.add(m.id);
|
|
397
408
|
continue;
|
|
398
409
|
}
|
|
399
|
-
const summaryFile = resolveMilestoneFile(basePath, m.id, "SUMMARY");
|
|
400
|
-
if (summaryFile) {
|
|
401
|
-
completeMilestoneIds.add(m.id);
|
|
402
|
-
continue;
|
|
403
|
-
}
|
|
404
410
|
}
|
|
405
411
|
return { completeMilestoneIds, parkedMilestoneIds };
|
|
406
412
|
}
|
|
@@ -429,18 +435,22 @@ async function buildRegistryAndFindActive(
|
|
|
429
435
|
if (isGhostMilestone(basePath, m.id)) continue;
|
|
430
436
|
}
|
|
431
437
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
438
|
+
// DB-authoritative completeness (#4179): only trust completeMilestoneIds,
|
|
439
|
+
// which is itself derived from DB status. SUMMARY-file presence alone must
|
|
440
|
+
// not imply completion. The summary file may still be consulted below as a
|
|
441
|
+
// title source for legitimately-complete milestones whose DB row has no title.
|
|
442
|
+
if (completeMilestoneIds.has(m.id)) {
|
|
435
443
|
let title = stripMilestonePrefix(m.title) || m.id;
|
|
436
|
-
if (
|
|
437
|
-
const
|
|
438
|
-
if (
|
|
439
|
-
|
|
444
|
+
if (!m.title) {
|
|
445
|
+
const summaryFile = resolveMilestoneFile(basePath, m.id, "SUMMARY");
|
|
446
|
+
if (summaryFile) {
|
|
447
|
+
const summaryContent = await loadFile(summaryFile);
|
|
448
|
+
if (summaryContent) {
|
|
449
|
+
title = parseSummary(summaryContent).title || m.id;
|
|
450
|
+
}
|
|
440
451
|
}
|
|
441
452
|
}
|
|
442
453
|
registry.push({ id: m.id, title, status: 'complete' });
|
|
443
|
-
completeMilestoneIds.add(m.id);
|
|
444
454
|
continue;
|
|
445
455
|
}
|
|
446
456
|
|
|
@@ -481,7 +491,14 @@ async function buildRegistryAndFindActive(
|
|
|
481
491
|
const validationContent = validationFile ? await loadFile(validationFile) : null;
|
|
482
492
|
const validationTerminal = validationContent ? isValidationTerminal(validationContent) : false;
|
|
483
493
|
|
|
484
|
-
|
|
494
|
+
// DB-authoritative (#4179): completeness is already decided by
|
|
495
|
+
// completeMilestoneIds above. If we reached this branch, the DB says
|
|
496
|
+
// the milestone is NOT complete — so any SUMMARY file on disk is an
|
|
497
|
+
// orphan (crashed complete-milestone, partial merge, manual edit) and
|
|
498
|
+
// must not short-circuit this path. When validation is terminal, fall
|
|
499
|
+
// through to the default active-push below so `complete-milestone` can
|
|
500
|
+
// re-run idempotently.
|
|
501
|
+
if (!validationTerminal) {
|
|
485
502
|
activeMilestone = { id: m.id, title };
|
|
486
503
|
activeMilestoneSlices = slices;
|
|
487
504
|
activeMilestoneFound = true;
|
|
@@ -630,13 +647,39 @@ function resolveSliceDependencies(activeMilestoneSlices: SliceRow[]): { activeSl
|
|
|
630
647
|
}
|
|
631
648
|
}
|
|
632
649
|
|
|
650
|
+
// First pass: find a slice with ALL dependencies satisfied (strict)
|
|
651
|
+
let bestFallback: SliceRow | null = null;
|
|
652
|
+
let bestFallbackSatisfied = -1;
|
|
653
|
+
|
|
633
654
|
for (const s of activeMilestoneSlices) {
|
|
634
655
|
if (isStatusDone(s.status)) continue;
|
|
635
656
|
if (isDeferredStatus(s.status)) continue;
|
|
636
657
|
if (s.depends.every(dep => doneSliceIds.has(dep))) {
|
|
637
658
|
return { activeSlice: { id: s.id, title: s.title }, activeSliceRow: s };
|
|
638
659
|
}
|
|
660
|
+
// Track the slice with the most satisfied dependencies as fallback
|
|
661
|
+
const satisfied = s.depends.filter(dep => doneSliceIds.has(dep)).length;
|
|
662
|
+
if (satisfied > bestFallbackSatisfied || (satisfied === bestFallbackSatisfied && !bestFallback)) {
|
|
663
|
+
bestFallback = s;
|
|
664
|
+
bestFallbackSatisfied = satisfied;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Fallback: if no slice has all deps met but there ARE incomplete non-deferred
|
|
669
|
+
// slices, pick the one with the most deps satisfied. This prevents hard-blocking
|
|
670
|
+
// when dependency metadata is stale (e.g. after reassessment added/removed slices)
|
|
671
|
+
// or when deps reference slices from previous milestones.
|
|
672
|
+
if (bestFallback) {
|
|
673
|
+
const unmet = bestFallback.depends.filter(dep => !doneSliceIds.has(dep));
|
|
674
|
+
logWarning("state",
|
|
675
|
+
`No slice has all deps satisfied — falling back to ${bestFallback.id} ` +
|
|
676
|
+
`(${bestFallbackSatisfied}/${bestFallback.depends.length} deps met, ` +
|
|
677
|
+
`unmet: ${unmet.join(", ")})`,
|
|
678
|
+
{ mid: activeMilestoneSlices[0]?.milestone_id, sid: bestFallback.id },
|
|
679
|
+
);
|
|
680
|
+
return { activeSlice: { id: bestFallback.id, title: bestFallback.title }, activeSliceRow: bestFallback };
|
|
639
681
|
}
|
|
682
|
+
|
|
640
683
|
return { activeSlice: null, activeSliceRow: null };
|
|
641
684
|
}
|
|
642
685
|
|
|
@@ -684,7 +727,7 @@ async function reconcileSliceTasks(
|
|
|
684
727
|
const summaryPath = resolveTaskFile(basePath, milestoneId, sliceId, t.id, "SUMMARY");
|
|
685
728
|
if (summaryPath && existsSync(summaryPath)) {
|
|
686
729
|
try {
|
|
687
|
-
updateTaskStatus(milestoneId, sliceId, t.id, "complete");
|
|
730
|
+
updateTaskStatus(milestoneId, sliceId, t.id, "complete", new Date().toISOString());
|
|
688
731
|
logWarning("reconcile", `task ${milestoneId}/${sliceId}/${t.id} status reconciled from "${t.status}" to "complete" (#2514)`, { mid: milestoneId, sid: sliceId, tid: t.id });
|
|
689
732
|
reconciled = true;
|
|
690
733
|
} catch (e) {
|
|
@@ -1431,12 +1474,32 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|
|
1431
1474
|
};
|
|
1432
1475
|
}
|
|
1433
1476
|
} else {
|
|
1477
|
+
let bestFallbackLegacy: { id: string; title: string; depends: string[] } | null = null;
|
|
1478
|
+
let bestFallbackLegacySatisfied = -1;
|
|
1479
|
+
|
|
1434
1480
|
for (const s of activeRoadmap.slices) {
|
|
1435
1481
|
if (s.done) continue;
|
|
1436
1482
|
if (s.depends.every(dep => doneSliceIds.has(dep))) {
|
|
1437
1483
|
activeSlice = { id: s.id, title: s.title };
|
|
1438
1484
|
break;
|
|
1439
1485
|
}
|
|
1486
|
+
// Track best fallback
|
|
1487
|
+
const satisfied = s.depends.filter(dep => doneSliceIds.has(dep)).length;
|
|
1488
|
+
if (satisfied > bestFallbackLegacySatisfied) {
|
|
1489
|
+
bestFallbackLegacy = s;
|
|
1490
|
+
bestFallbackLegacySatisfied = satisfied;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
// Fallback: if no slice has all deps met, pick the one with the most deps satisfied
|
|
1495
|
+
if (!activeSlice && bestFallbackLegacy) {
|
|
1496
|
+
const unmet = bestFallbackLegacy.depends.filter(dep => !doneSliceIds.has(dep));
|
|
1497
|
+
logWarning("state",
|
|
1498
|
+
`No slice has all deps satisfied — falling back to ${bestFallbackLegacy.id} ` +
|
|
1499
|
+
`(${bestFallbackLegacySatisfied}/${bestFallbackLegacy.depends.length} deps met, ` +
|
|
1500
|
+
`unmet: ${unmet.join(", ")})`,
|
|
1501
|
+
);
|
|
1502
|
+
activeSlice = { id: bestFallbackLegacy.id, title: bestFallbackLegacy.title };
|
|
1440
1503
|
}
|
|
1441
1504
|
}
|
|
1442
1505
|
|