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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { describe, test } from "node:test";
|
|
8
8
|
import assert from "node:assert/strict";
|
|
9
|
-
import { isFlatRateProvider, resolvePreferredModelConfig } from "../auto-model-selection.ts";
|
|
9
|
+
import { buildFlatRateContext, isFlatRateProvider, resolvePreferredModelConfig } from "../auto-model-selection.ts";
|
|
10
10
|
|
|
11
11
|
describe("flat-rate provider routing guard (#3453)", () => {
|
|
12
12
|
|
|
@@ -48,3 +48,139 @@ describe("flat-rate provider routing guard (#3453)", () => {
|
|
|
48
48
|
assert.equal(result, undefined, "Should not create routing config for copilot");
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
|
+
|
|
52
|
+
describe("flat-rate provider extensibility (any/all/custom)", () => {
|
|
53
|
+
test("regression: built-in providers still flat-rate with no context", () => {
|
|
54
|
+
assert.equal(isFlatRateProvider("github-copilot"), true);
|
|
55
|
+
assert.equal(isFlatRateProvider("copilot"), true);
|
|
56
|
+
assert.equal(isFlatRateProvider("claude-code"), true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("regression: non-flat-rate API providers return false with no context", () => {
|
|
60
|
+
assert.equal(isFlatRateProvider("anthropic"), false);
|
|
61
|
+
assert.equal(isFlatRateProvider("openai"), false);
|
|
62
|
+
assert.equal(isFlatRateProvider("google-vertex"), false);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("auto-detection: externalCli auth mode marks provider flat-rate", () => {
|
|
66
|
+
// Any provider registered with authMode: "externalCli" is a local
|
|
67
|
+
// CLI wrapper around the user's subscription — every request costs
|
|
68
|
+
// the same regardless of model, so dynamic routing provides no benefit.
|
|
69
|
+
assert.equal(
|
|
70
|
+
isFlatRateProvider("my-private-cli", { authMode: "externalCli" }),
|
|
71
|
+
true,
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("auto-detection: non-externalCli auth modes do not mark provider flat-rate", () => {
|
|
76
|
+
assert.equal(
|
|
77
|
+
isFlatRateProvider("my-http-proxy", { authMode: "apiKey" }),
|
|
78
|
+
false,
|
|
79
|
+
);
|
|
80
|
+
assert.equal(
|
|
81
|
+
isFlatRateProvider("my-http-proxy", { authMode: "oauth" }),
|
|
82
|
+
false,
|
|
83
|
+
);
|
|
84
|
+
assert.equal(
|
|
85
|
+
isFlatRateProvider("my-http-proxy", { authMode: "none" }),
|
|
86
|
+
false,
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("user preference: custom provider listed in userFlatRate is flat-rate", () => {
|
|
91
|
+
assert.equal(
|
|
92
|
+
isFlatRateProvider("my-ollama-proxy", { userFlatRate: ["my-ollama-proxy"] }),
|
|
93
|
+
true,
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("user preference: case-insensitive match against userFlatRate list", () => {
|
|
98
|
+
assert.equal(
|
|
99
|
+
isFlatRateProvider("My-Proxy", { userFlatRate: ["my-proxy"] }),
|
|
100
|
+
true,
|
|
101
|
+
);
|
|
102
|
+
assert.equal(
|
|
103
|
+
isFlatRateProvider("my-proxy", { userFlatRate: ["MY-PROXY"] }),
|
|
104
|
+
true,
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("user preference: provider not in userFlatRate list is not flat-rate", () => {
|
|
109
|
+
assert.equal(
|
|
110
|
+
isFlatRateProvider("other-proxy", { userFlatRate: ["my-proxy"] }),
|
|
111
|
+
false,
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("combined signals: built-in list wins even when context is empty", () => {
|
|
116
|
+
assert.equal(
|
|
117
|
+
isFlatRateProvider("claude-code", { authMode: "apiKey", userFlatRate: [] }),
|
|
118
|
+
true,
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("combined signals: externalCli auto-detection wins alongside userFlatRate miss", () => {
|
|
123
|
+
assert.equal(
|
|
124
|
+
isFlatRateProvider("my-cli", {
|
|
125
|
+
authMode: "externalCli",
|
|
126
|
+
userFlatRate: ["a-different-cli"],
|
|
127
|
+
}),
|
|
128
|
+
true,
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("buildFlatRateContext()", () => {
|
|
134
|
+
test("builds a context from ctx.modelRegistry.getProviderAuthMode + prefs", () => {
|
|
135
|
+
const ctx = {
|
|
136
|
+
modelRegistry: {
|
|
137
|
+
getProviderAuthMode: (p: string) =>
|
|
138
|
+
p === "my-cli" ? "externalCli" : "apiKey",
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
const prefs = { flat_rate_providers: ["my-proxy"] };
|
|
142
|
+
|
|
143
|
+
const ctxForCli = buildFlatRateContext("my-cli", ctx, prefs);
|
|
144
|
+
assert.equal(ctxForCli.authMode, "externalCli");
|
|
145
|
+
assert.deepEqual(ctxForCli.userFlatRate, ["my-proxy"]);
|
|
146
|
+
assert.equal(isFlatRateProvider("my-cli", ctxForCli), true);
|
|
147
|
+
|
|
148
|
+
const ctxForProxy = buildFlatRateContext("my-proxy", ctx, prefs);
|
|
149
|
+
assert.equal(ctxForProxy.authMode, "apiKey");
|
|
150
|
+
assert.equal(isFlatRateProvider("my-proxy", ctxForProxy), true);
|
|
151
|
+
|
|
152
|
+
const ctxForOther = buildFlatRateContext("anthropic", ctx, prefs);
|
|
153
|
+
assert.equal(ctxForOther.authMode, "apiKey");
|
|
154
|
+
assert.equal(isFlatRateProvider("anthropic", ctxForOther), false);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("survives missing ctx and missing prefs", () => {
|
|
158
|
+
const empty = buildFlatRateContext("anything");
|
|
159
|
+
assert.equal(empty.authMode, undefined);
|
|
160
|
+
assert.equal(empty.userFlatRate, undefined);
|
|
161
|
+
assert.equal(isFlatRateProvider("anything", empty), false);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("survives a registry lookup that throws", () => {
|
|
165
|
+
const ctx = {
|
|
166
|
+
modelRegistry: {
|
|
167
|
+
getProviderAuthMode: () => {
|
|
168
|
+
throw new Error("registry boom");
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
const result = buildFlatRateContext("anything", ctx);
|
|
173
|
+
// Error must be swallowed — authMode left undefined, function returns.
|
|
174
|
+
assert.equal(result.authMode, undefined);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("registry returning a non-canonical auth mode is ignored", () => {
|
|
178
|
+
const ctx = {
|
|
179
|
+
modelRegistry: {
|
|
180
|
+
getProviderAuthMode: () => "weird-mode",
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
const result = buildFlatRateContext("anything", ctx);
|
|
184
|
+
assert.equal(result.authMode, undefined);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph-context.test.ts — Unit tests for inlineGraphSubgraph().
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* Group 1: Null-return paths (empty term, zero nodes, missing graph.json)
|
|
6
|
+
* Group 2: Correct output formatting (nodes, edges, stale annotation)
|
|
7
|
+
* Group 3: Node formatting (description, confidence, no-description)
|
|
8
|
+
*
|
|
9
|
+
* Testing strategy:
|
|
10
|
+
* @gsd-build/mcp-server is dynamically imported inside inlineGraphSubgraph().
|
|
11
|
+
* Because node:test (v22) does not support mock.module() without the
|
|
12
|
+
* --experimental-test-module-mocks flag (not enabled in test:unit), we
|
|
13
|
+
* exercise the real graphQuery/graphStatus functions by controlling the
|
|
14
|
+
* on-disk graph.json that those functions read. This is a clean, deterministic
|
|
15
|
+
* approach that avoids all module-level mocking.
|
|
16
|
+
*
|
|
17
|
+
* Fixture layout per test:
|
|
18
|
+
* <tmpDir>/.gsd/graphs/graph.json
|
|
19
|
+
*
|
|
20
|
+
* builtAt controls staleness: old timestamp → stale, recent → fresh.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { describe, it } from "node:test";
|
|
24
|
+
import assert from "node:assert/strict";
|
|
25
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
import { tmpdir } from "node:os";
|
|
28
|
+
|
|
29
|
+
import { inlineGraphSubgraph } from "../graph-context.ts";
|
|
30
|
+
|
|
31
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
interface TestNode {
|
|
34
|
+
id: string;
|
|
35
|
+
label: string;
|
|
36
|
+
type: string;
|
|
37
|
+
confidence: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
sourceFile?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface TestEdge {
|
|
43
|
+
from: string;
|
|
44
|
+
to: string;
|
|
45
|
+
type: string;
|
|
46
|
+
confidence: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface GraphFixture {
|
|
50
|
+
nodes: TestNode[];
|
|
51
|
+
edges: TestEdge[];
|
|
52
|
+
/** ISO timestamp for graph.builtAt. Controls staleness. Default: recent (not stale). */
|
|
53
|
+
builtAt?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Returns an ISO timestamp that is stale (> 24h ago). */
|
|
57
|
+
function staleTimestamp(hoursAgo = 26): string {
|
|
58
|
+
return new Date(Date.now() - hoursAgo * 60 * 60 * 1000).toISOString();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Returns an ISO timestamp that is fresh (< 24h ago). */
|
|
62
|
+
function freshTimestamp(): string {
|
|
63
|
+
return new Date(Date.now() - 30 * 60 * 1000).toISOString(); // 30 minutes ago
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates a temp project directory with a .gsd/graphs/graph.json file.
|
|
68
|
+
* Returns the projectDir path. Caller is responsible for cleanup.
|
|
69
|
+
*/
|
|
70
|
+
function makeProjectDir(fixture: GraphFixture): string {
|
|
71
|
+
const projectDir = mkdtempSync(join(tmpdir(), "graph-ctx-test-"));
|
|
72
|
+
const gsdDir = join(projectDir, ".gsd");
|
|
73
|
+
const graphsDir = join(gsdDir, "graphs");
|
|
74
|
+
mkdirSync(graphsDir, { recursive: true });
|
|
75
|
+
|
|
76
|
+
const graph = {
|
|
77
|
+
nodes: fixture.nodes,
|
|
78
|
+
edges: fixture.edges,
|
|
79
|
+
builtAt: fixture.builtAt ?? freshTimestamp(),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
writeFileSync(join(graphsDir, "graph.json"), JSON.stringify(graph), "utf-8");
|
|
83
|
+
return projectDir;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Removes a temp directory, suppressing errors on Windows. */
|
|
87
|
+
function cleanup(dir: string): void {
|
|
88
|
+
try { rmSync(dir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Minimal node factory. */
|
|
92
|
+
function makeNode(overrides: Partial<TestNode> & { id: string; label: string }): TestNode {
|
|
93
|
+
return {
|
|
94
|
+
type: "CLASS",
|
|
95
|
+
confidence: "INFERRED",
|
|
96
|
+
...overrides,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Minimal edge factory. */
|
|
101
|
+
function makeEdge(overrides: Partial<TestEdge> & { from: string; to: string }): TestEdge {
|
|
102
|
+
return {
|
|
103
|
+
type: "CALLS",
|
|
104
|
+
confidence: "INFERRED",
|
|
105
|
+
...overrides,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ─── Group 1: Null returns ────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
describe("inlineGraphSubgraph — null returns", () => {
|
|
112
|
+
it("returns null immediately for empty string term", async () => {
|
|
113
|
+
// No graph.json needed — exits before any file I/O
|
|
114
|
+
const result = await inlineGraphSubgraph("/tmp/nonexistent", "", { budget: 3000 });
|
|
115
|
+
assert.strictEqual(result, null);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("returns null for whitespace-only term", async () => {
|
|
119
|
+
const result = await inlineGraphSubgraph("/tmp/nonexistent", " ", { budget: 3000 });
|
|
120
|
+
assert.strictEqual(result, null);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("returns null when graphQuery returns zero nodes (no matching term in graph)", async () => {
|
|
124
|
+
const projectDir = makeProjectDir({
|
|
125
|
+
nodes: [makeNode({ id: "n1", label: "AuthService" })],
|
|
126
|
+
edges: [],
|
|
127
|
+
});
|
|
128
|
+
try {
|
|
129
|
+
// "zzznomatch999" is intentionally absent from the fixture
|
|
130
|
+
const result = await inlineGraphSubgraph(projectDir, "zzznomatch999", { budget: 3000 });
|
|
131
|
+
assert.strictEqual(result, null);
|
|
132
|
+
} finally {
|
|
133
|
+
cleanup(projectDir);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("returns null (no throw) when graph.json is missing", async () => {
|
|
138
|
+
// A project dir with no .gsd directory at all — graphQuery returns zero nodes
|
|
139
|
+
const projectDir = mkdtempSync(join(tmpdir(), "graph-ctx-nofile-"));
|
|
140
|
+
try {
|
|
141
|
+
const result = await inlineGraphSubgraph(projectDir, "auth", { budget: 3000 });
|
|
142
|
+
assert.strictEqual(result, null);
|
|
143
|
+
} finally {
|
|
144
|
+
cleanup(projectDir);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// ─── Group 2: Correct output formatting ──────────────────────────────────────
|
|
150
|
+
|
|
151
|
+
describe("inlineGraphSubgraph — correct output", () => {
|
|
152
|
+
it("returns block with section header and node labels when term matches", async () => {
|
|
153
|
+
const projectDir = makeProjectDir({
|
|
154
|
+
nodes: [
|
|
155
|
+
makeNode({ id: "n1", label: "UserService" }),
|
|
156
|
+
makeNode({ id: "n2", label: "UserRepository" }),
|
|
157
|
+
],
|
|
158
|
+
edges: [],
|
|
159
|
+
});
|
|
160
|
+
try {
|
|
161
|
+
const result = await inlineGraphSubgraph(projectDir, "User", { budget: 3000 });
|
|
162
|
+
assert.ok(result !== null, "result should not be null");
|
|
163
|
+
assert.ok(result!.includes("### Knowledge Graph Context"), "should include section header");
|
|
164
|
+
assert.ok(result!.includes("UserService"), "should include first node label");
|
|
165
|
+
assert.ok(result!.includes("UserRepository"), "should include second node label");
|
|
166
|
+
assert.ok(result!.includes("Nodes (2)"), "should show node count");
|
|
167
|
+
} finally {
|
|
168
|
+
cleanup(projectDir);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("does not include Relations section when edges array is empty", async () => {
|
|
173
|
+
const projectDir = makeProjectDir({
|
|
174
|
+
nodes: [makeNode({ id: "n1", label: "AuthController" })],
|
|
175
|
+
edges: [],
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
const result = await inlineGraphSubgraph(projectDir, "Auth", { budget: 3000 });
|
|
179
|
+
assert.ok(result !== null, "result should not be null");
|
|
180
|
+
assert.ok(!result!.includes("Relations"), "should not include Relations section for zero edges");
|
|
181
|
+
assert.ok(!result!.includes("⚠"), "should not include stale warning for fresh graph");
|
|
182
|
+
} finally {
|
|
183
|
+
cleanup(projectDir);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("includes Relations section when edges are present", async () => {
|
|
188
|
+
const projectDir = makeProjectDir({
|
|
189
|
+
nodes: [
|
|
190
|
+
makeNode({ id: "n1", label: "AuthService" }),
|
|
191
|
+
makeNode({ id: "n2", label: "UserRepo" }),
|
|
192
|
+
],
|
|
193
|
+
edges: [makeEdge({ from: "n1", to: "n2", type: "CALLS" })],
|
|
194
|
+
});
|
|
195
|
+
try {
|
|
196
|
+
const result = await inlineGraphSubgraph(projectDir, "Auth", { budget: 3000 });
|
|
197
|
+
assert.ok(result !== null, "result should not be null");
|
|
198
|
+
assert.ok(result!.includes("Relations (1)"), "should show edge count");
|
|
199
|
+
assert.ok(result!.includes("→[CALLS]→"), "should include edge type in arrow notation");
|
|
200
|
+
} finally {
|
|
201
|
+
cleanup(projectDir);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("includes stale annotation when graph was built more than 24h ago", async () => {
|
|
206
|
+
const projectDir = makeProjectDir({
|
|
207
|
+
nodes: [makeNode({ id: "n1", label: "AuthService" })],
|
|
208
|
+
edges: [],
|
|
209
|
+
builtAt: staleTimestamp(26), // 26 hours ago → stale
|
|
210
|
+
});
|
|
211
|
+
try {
|
|
212
|
+
const result = await inlineGraphSubgraph(projectDir, "Auth", { budget: 3000 });
|
|
213
|
+
assert.ok(result !== null, "result should not be null");
|
|
214
|
+
assert.ok(result!.includes("⚠ Graph last built"), "should include stale annotation");
|
|
215
|
+
assert.ok(result!.includes("h ago"), "should include hours-ago text");
|
|
216
|
+
} finally {
|
|
217
|
+
cleanup(projectDir);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("does not include stale annotation for a fresh graph", async () => {
|
|
222
|
+
const projectDir = makeProjectDir({
|
|
223
|
+
nodes: [makeNode({ id: "n1", label: "AuthService" })],
|
|
224
|
+
edges: [],
|
|
225
|
+
builtAt: freshTimestamp(), // 30 minutes ago → not stale
|
|
226
|
+
});
|
|
227
|
+
try {
|
|
228
|
+
const result = await inlineGraphSubgraph(projectDir, "Auth", { budget: 3000 });
|
|
229
|
+
assert.ok(result !== null, "result should not be null");
|
|
230
|
+
assert.ok(!result!.includes("⚠"), "should not include stale annotation for fresh graph");
|
|
231
|
+
} finally {
|
|
232
|
+
cleanup(projectDir);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("returns valid block even when graph.json has corrupted builtAt (graphStatus throws internally)", async () => {
|
|
237
|
+
// Write a graph.json with an invalid builtAt — graphStatus will catch and return {exists: false}
|
|
238
|
+
// inlineGraphSubgraph should still return the node block without stale annotation
|
|
239
|
+
const projectDir = mkdtempSync(join(tmpdir(), "graph-ctx-corrupt-"));
|
|
240
|
+
const gsdDir = join(projectDir, ".gsd");
|
|
241
|
+
const graphsDir = join(gsdDir, "graphs");
|
|
242
|
+
mkdirSync(graphsDir, { recursive: true });
|
|
243
|
+
|
|
244
|
+
const graph = {
|
|
245
|
+
nodes: [{ id: "n1", label: "AuthController", type: "CLASS", confidence: "INFERRED" }],
|
|
246
|
+
edges: [],
|
|
247
|
+
builtAt: "NOT-A-DATE", // invalid ISO — will cause Date.now() - NaN to produce NaN
|
|
248
|
+
};
|
|
249
|
+
writeFileSync(join(graphsDir, "graph.json"), JSON.stringify(graph), "utf-8");
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const result = await inlineGraphSubgraph(projectDir, "Auth", { budget: 3000 });
|
|
253
|
+
// graphQuery reads the file and finds the node; graphStatus may return {exists: true, stale: false/true}
|
|
254
|
+
// Either way, function must not throw and must return a string with node content
|
|
255
|
+
assert.ok(result !== null, "result should not be null");
|
|
256
|
+
assert.ok(result!.includes("AuthController"), "should include node label");
|
|
257
|
+
} finally {
|
|
258
|
+
cleanup(projectDir);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("passes the budget option to graphQuery (enforces node count limit)", async () => {
|
|
263
|
+
// Each node uses ~20 tokens. With budget=20, only ~1 node should be returned.
|
|
264
|
+
// Build a graph with many nodes all matching the same term.
|
|
265
|
+
const nodes: TestNode[] = Array.from({ length: 10 }, (_, i) =>
|
|
266
|
+
makeNode({ id: `n${i}`, label: `AuthModule${i}` })
|
|
267
|
+
);
|
|
268
|
+
const projectDir = makeProjectDir({ nodes, edges: [] });
|
|
269
|
+
try {
|
|
270
|
+
const resultSmall = await inlineGraphSubgraph(projectDir, "Auth", { budget: 20 });
|
|
271
|
+
const resultLarge = await inlineGraphSubgraph(projectDir, "Auth", { budget: 10000 });
|
|
272
|
+
|
|
273
|
+
// Both should return something (at least 1 node matches)
|
|
274
|
+
assert.ok(resultSmall !== null, "small-budget result should not be null");
|
|
275
|
+
assert.ok(resultLarge !== null, "large-budget result should not be null");
|
|
276
|
+
|
|
277
|
+
// With a very small budget (20 tokens ≈ 1 node), fewer nodes should appear
|
|
278
|
+
const smallNodeCount = (resultSmall!.match(/- \*\*/g) || []).length;
|
|
279
|
+
const largeNodeCount = (resultLarge!.match(/- \*\*/g) || []).length;
|
|
280
|
+
assert.ok(
|
|
281
|
+
smallNodeCount <= largeNodeCount,
|
|
282
|
+
`small-budget should return <= nodes than large-budget (got ${smallNodeCount} vs ${largeNodeCount})`,
|
|
283
|
+
);
|
|
284
|
+
} finally {
|
|
285
|
+
cleanup(projectDir);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// ─── Group 3: Node formatting ─────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
describe("inlineGraphSubgraph — node formatting", () => {
|
|
293
|
+
it("includes description after em-dash when node has description", async () => {
|
|
294
|
+
const projectDir = makeProjectDir({
|
|
295
|
+
nodes: [makeNode({ id: "n1", label: "JwtValidator", description: "JWT validation" })],
|
|
296
|
+
edges: [],
|
|
297
|
+
});
|
|
298
|
+
try {
|
|
299
|
+
const result = await inlineGraphSubgraph(projectDir, "Jwt", { budget: 3000 });
|
|
300
|
+
assert.ok(result !== null, "result should not be null");
|
|
301
|
+
assert.ok(result!.includes("— JWT validation"), "should include description after em-dash");
|
|
302
|
+
} finally {
|
|
303
|
+
cleanup(projectDir);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("omits em-dash suffix when node has no description", async () => {
|
|
308
|
+
const projectDir = makeProjectDir({
|
|
309
|
+
nodes: [makeNode({ id: "n1", label: "TokenStore" })], // no description
|
|
310
|
+
edges: [],
|
|
311
|
+
});
|
|
312
|
+
try {
|
|
313
|
+
const result = await inlineGraphSubgraph(projectDir, "Token", { budget: 3000 });
|
|
314
|
+
assert.ok(result !== null, "result should not be null");
|
|
315
|
+
const lines = result!.split("\n");
|
|
316
|
+
const nodeLine = lines.find((l) => l.includes("TokenStore"));
|
|
317
|
+
assert.ok(nodeLine !== undefined, "node line should be present");
|
|
318
|
+
assert.ok(!nodeLine.includes("—"), "node line should not include em-dash when no description");
|
|
319
|
+
} finally {
|
|
320
|
+
cleanup(projectDir);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it("includes confidence tier in the node output line", async () => {
|
|
325
|
+
const projectDir = makeProjectDir({
|
|
326
|
+
nodes: [makeNode({ id: "n1", label: "AuthService", confidence: "EXTRACTED" })],
|
|
327
|
+
edges: [],
|
|
328
|
+
});
|
|
329
|
+
try {
|
|
330
|
+
const result = await inlineGraphSubgraph(projectDir, "Auth", { budget: 3000 });
|
|
331
|
+
assert.ok(result !== null, "result should not be null");
|
|
332
|
+
assert.ok(result!.includes("EXTRACTED"), "should include the confidence tier in node line");
|
|
333
|
+
} finally {
|
|
334
|
+
cleanup(projectDir);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
});
|
|
@@ -80,7 +80,7 @@ describe('gsd-db', () => {
|
|
|
80
80
|
// Check schema_version table
|
|
81
81
|
const adapter = _getAdapter()!;
|
|
82
82
|
const version = adapter.prepare('SELECT MAX(version) as version FROM schema_version').get();
|
|
83
|
-
assert.deepStrictEqual(version?.['version'],
|
|
83
|
+
assert.deepStrictEqual(version?.['version'], 15, 'schema version should be 15');
|
|
84
84
|
|
|
85
85
|
// Check tables exist by querying them
|
|
86
86
|
const dRows = adapter.prepare('SELECT count(*) as cnt FROM decisions').get();
|
|
@@ -198,7 +198,7 @@ test("session_start bootstraps the health widget alongside notifications", async
|
|
|
198
198
|
},
|
|
199
199
|
} as any;
|
|
200
200
|
|
|
201
|
-
registerHooks(pi);
|
|
201
|
+
registerHooks(pi, []);
|
|
202
202
|
const sessionStart = handlers.get("session_start");
|
|
203
203
|
assert.ok(sessionStart, "session_start handler is registered");
|
|
204
204
|
|
|
@@ -691,7 +691,7 @@ describe("transition boundary failures", () => {
|
|
|
691
691
|
);
|
|
692
692
|
});
|
|
693
693
|
|
|
694
|
-
test("blocked state: all slices have unmet deps →
|
|
694
|
+
test("blocked state: all slices have unmet deps → fallback picks slice", async () => {
|
|
695
695
|
base = makeTempDir();
|
|
696
696
|
const mDir = join(base, ".gsd", "milestones", "M001");
|
|
697
697
|
mkdirSync(join(mDir, "slices", "S01", "tasks"), { recursive: true });
|
|
@@ -736,7 +736,9 @@ describe("transition boundary failures", () => {
|
|
|
736
736
|
|
|
737
737
|
invalidateAllCaches();
|
|
738
738
|
const state = await deriveStateFromDb(base);
|
|
739
|
-
|
|
739
|
+
// With partial-dep fallback, circular deps no longer block — fallback picks first eligible slice
|
|
740
|
+
assert.equal(state.phase, "planning", "circular deps: fallback picks a slice instead of blocking");
|
|
741
|
+
assert.ok(state.activeSlice !== null, "activeSlice set via fallback");
|
|
740
742
|
});
|
|
741
743
|
});
|
|
742
744
|
|
|
@@ -92,6 +92,7 @@ function makeMockDeps(
|
|
|
92
92
|
getPriorSliceCompletionBlocker: () => null,
|
|
93
93
|
getMainBranch: () => "main",
|
|
94
94
|
closeoutUnit: async () => {},
|
|
95
|
+
autoCommitUnit: async () => null,
|
|
95
96
|
recordOutcome: () => {},
|
|
96
97
|
writeLock: () => {},
|
|
97
98
|
captureAvailableSkills: () => {},
|
|
@@ -567,7 +568,15 @@ test("unit-end event contains errorContext when unit is cancelled with structure
|
|
|
567
568
|
const { resolveAgentEndCancelled, _resetPendingResolve } = await import("../auto-loop.js");
|
|
568
569
|
_resetPendingResolve();
|
|
569
570
|
|
|
570
|
-
|
|
571
|
+
let pauseCalls = 0;
|
|
572
|
+
let commitCalls = 0;
|
|
573
|
+
const deps = makeMockDeps(capture, {
|
|
574
|
+
pauseAuto: async () => { pauseCalls++; },
|
|
575
|
+
autoCommitUnit: async () => {
|
|
576
|
+
commitCalls++;
|
|
577
|
+
return "commit";
|
|
578
|
+
},
|
|
579
|
+
});
|
|
571
580
|
const ic = makeIC(deps);
|
|
572
581
|
const iterData: IterationData = {
|
|
573
582
|
unitType: "execute-task",
|
|
@@ -593,10 +602,68 @@ test("unit-end event contains errorContext when unit is cancelled with structure
|
|
|
593
602
|
// Transient timeout cancellations pause (recoverable) instead of hard-stopping
|
|
594
603
|
assert.equal(result.action, "break");
|
|
595
604
|
assert.equal((result as any).reason, "session-timeout");
|
|
605
|
+
assert.equal(pauseCalls, 1, "timeout cancellations should pause auto-mode exactly once");
|
|
606
|
+
assert.equal(commitCalls, 1, "timeout cancellations should flush a unit auto-commit once");
|
|
596
607
|
|
|
597
608
|
// Verify error classification used structured errorContext on the window entry
|
|
598
609
|
const entry = loopState.recentUnits[loopState.recentUnits.length - 1];
|
|
599
610
|
assert.ok(entry.error, "window entry must have error set");
|
|
600
611
|
assert.ok(entry.error!.startsWith("timeout:"), "error must start with category from errorContext");
|
|
601
612
|
assert.ok(entry.error!.includes("Hard timeout error"), "error must include the errorContext message");
|
|
613
|
+
|
|
614
|
+
const endEvents = capture.events.filter(e => e.eventType === "unit-end");
|
|
615
|
+
assert.equal(endEvents.length, 1, "timeout cancellations should still emit unit-end");
|
|
616
|
+
assert.equal((endEvents[0].data as any).status, "cancelled");
|
|
617
|
+
assert.equal((endEvents[0].data as any).artifactVerified, false);
|
|
618
|
+
assert.equal((endEvents[0].data as any).errorContext.category, "timeout");
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
test("session-failed cancellations close out and emit unit-end before hard stop", async () => {
|
|
622
|
+
const capture = createEventCapture();
|
|
623
|
+
const { resolveAgentEndCancelled, _resetPendingResolve } = await import("../auto-loop.js");
|
|
624
|
+
_resetPendingResolve();
|
|
625
|
+
|
|
626
|
+
let closeoutCalls = 0;
|
|
627
|
+
let commitCalls = 0;
|
|
628
|
+
let stopCalls = 0;
|
|
629
|
+
const deps = makeMockDeps(capture, {
|
|
630
|
+
closeoutUnit: async () => { closeoutCalls++; },
|
|
631
|
+
autoCommitUnit: async () => {
|
|
632
|
+
commitCalls++;
|
|
633
|
+
return "commit";
|
|
634
|
+
},
|
|
635
|
+
stopAuto: async () => { stopCalls++; },
|
|
636
|
+
});
|
|
637
|
+
const ic = makeIC(deps);
|
|
638
|
+
const iterData: IterationData = {
|
|
639
|
+
unitType: "execute-task",
|
|
640
|
+
unitId: "M001/S01/T01",
|
|
641
|
+
prompt: "do stuff",
|
|
642
|
+
finalPrompt: "do stuff",
|
|
643
|
+
pauseAfterUatDispatch: false,
|
|
644
|
+
state: { phase: "executing", activeMilestone: { id: "M001" }, activeSlice: { id: "S01" }, registry: [], blockers: [] } as any,
|
|
645
|
+
mid: "M001",
|
|
646
|
+
midTitle: "Test",
|
|
647
|
+
isRetry: false,
|
|
648
|
+
previousTier: undefined,
|
|
649
|
+
};
|
|
650
|
+
const loopState: LoopState = { recentUnits: [{ key: "execute-task/M001/S01/T01" }], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 };
|
|
651
|
+
|
|
652
|
+
const unitPromise = runUnitPhase(ic, iterData, loopState);
|
|
653
|
+
await new Promise(r => setTimeout(r, 50));
|
|
654
|
+
|
|
655
|
+
resolveAgentEndCancelled({ message: "session bootstrap exploded", category: "session-failed", isTransient: false });
|
|
656
|
+
|
|
657
|
+
const result = await unitPromise;
|
|
658
|
+
assert.equal(result.action, "break");
|
|
659
|
+
assert.equal((result as any).reason, "session-failed");
|
|
660
|
+
assert.equal(closeoutCalls, 1, "session-failed cancellations should close out the unit before stopping");
|
|
661
|
+
assert.equal(commitCalls, 1, "session-failed cancellations should try one auto-commit flush");
|
|
662
|
+
assert.equal(stopCalls, 1, "session-failed cancellations should hard-stop auto-mode");
|
|
663
|
+
|
|
664
|
+
const endEvents = capture.events.filter(e => e.eventType === "unit-end");
|
|
665
|
+
assert.equal(endEvents.length, 1, "session-failed cancellations should emit unit-end");
|
|
666
|
+
assert.equal((endEvents[0].data as any).status, "cancelled");
|
|
667
|
+
assert.equal((endEvents[0].data as any).artifactVerified, false);
|
|
668
|
+
assert.equal((endEvents[0].data as any).errorContext.category, "session-failed");
|
|
602
669
|
});
|
|
@@ -363,7 +363,7 @@ test('md-importer: schema v1→v2 migration', () => {
|
|
|
363
363
|
openDatabase(':memory:');
|
|
364
364
|
const adapter = _getAdapter();
|
|
365
365
|
const version = adapter?.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
366
|
-
assert.deepStrictEqual(version?.v,
|
|
366
|
+
assert.deepStrictEqual(version?.v, 15, 'new DB should be at schema version 15');
|
|
367
367
|
|
|
368
368
|
// Artifacts table should exist
|
|
369
369
|
const tableCheck = adapter?.prepare("SELECT count(*) as c FROM sqlite_master WHERE type='table' AND name='artifacts'").get();
|
|
@@ -413,4 +413,3 @@ test('md-importer: round-trip fidelity', () => {
|
|
|
413
413
|
});
|
|
414
414
|
|
|
415
415
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
416
|
-
|
|
@@ -323,10 +323,9 @@ test('memory-store: schema includes memories table', () => {
|
|
|
323
323
|
const viewCount = adapter.prepare('SELECT count(*) as cnt FROM active_memories').get();
|
|
324
324
|
assert.deepStrictEqual(viewCount?.['cnt'], 0, 'active_memories view should exist');
|
|
325
325
|
|
|
326
|
-
// Verify schema version is
|
|
326
|
+
// Verify schema version is 15 (UOK gate/git/audit projection tables included)
|
|
327
327
|
const version = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
328
|
-
assert.deepStrictEqual(version?.['v'],
|
|
328
|
+
assert.deepStrictEqual(version?.['v'], 15, 'schema version should be 15');
|
|
329
329
|
|
|
330
330
|
closeDatabase();
|
|
331
331
|
});
|
|
332
|
-
|