gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac
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/README.md +1 -1
- package/dist/cli.js +49 -35
- package/dist/headless-ui.d.ts +17 -0
- package/dist/headless-ui.js +97 -3
- package/dist/headless.js +67 -6
- package/dist/help-text.js +1 -0
- package/dist/onboarding.js +44 -0
- package/dist/resource-loader.js +16 -1
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/ask-user-questions.js +16 -3
- package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
- package/dist/resources/extensions/context7/extension-manifest.json +1 -1
- package/dist/resources/extensions/get-secrets-from-user.js +8 -5
- package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
- package/dist/resources/extensions/google-search/index.js +2 -1
- package/dist/resources/extensions/gsd/auto/phases.js +25 -21
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
- package/dist/resources/extensions/gsd/auto-start.js +35 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
- package/dist/resources/extensions/gsd/auto.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
- package/dist/resources/extensions/gsd/captures.js +56 -4
- package/dist/resources/extensions/gsd/db-writer.js +116 -8
- package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
- package/dist/resources/extensions/gsd/doctor.js +3 -1
- package/dist/resources/extensions/gsd/error-classifier.js +13 -10
- package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
- package/dist/resources/extensions/gsd/forensics.js +123 -20
- package/dist/resources/extensions/gsd/git-service.js +23 -1
- package/dist/resources/extensions/gsd/gitignore.js +33 -0
- package/dist/resources/extensions/gsd/gsd-db.js +36 -9
- package/dist/resources/extensions/gsd/guided-flow.js +106 -44
- package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
- package/dist/resources/extensions/gsd/health-widget.js +17 -0
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
- package/dist/resources/extensions/gsd/migrate-external.js +8 -1
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
- package/dist/resources/extensions/gsd/model-router.js +35 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
- package/dist/resources/extensions/gsd/notifications.js +16 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
- package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
- package/dist/resources/extensions/gsd/paths.js +43 -0
- package/dist/resources/extensions/gsd/preferences-models.js +14 -1
- package/dist/resources/extensions/gsd/preferences-types.js +2 -1
- package/dist/resources/extensions/gsd/preferences.js +13 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/dist/resources/extensions/gsd/repo-identity.js +205 -11
- package/dist/resources/extensions/gsd/rethink.js +5 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
- package/dist/resources/extensions/gsd/state.js +85 -27
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
- package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
- package/dist/resources/extensions/gsd/undo.js +2 -2
- package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
- package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
- package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
- package/dist/resources/extensions/gsd/workspace-index.js +24 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
- package/dist/resources/extensions/mcp-client/index.js +11 -7
- package/dist/resources/extensions/ollama/index.js +112 -0
- package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
- package/dist/resources/extensions/ollama/ollama-client.js +168 -0
- package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
- package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
- package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
- package/dist/resources/extensions/ollama/types.js +2 -0
- package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/dist/resources/extensions/shared/interview-ui.js +11 -1
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/startup-model-validation.d.ts +39 -0
- package/dist/startup-model-validation.js +50 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
- package/dist/web-mode.js +2 -1
- package/package.json +2 -2
- package/packages/daemon/src/cli.ts +49 -0
- package/packages/daemon/src/daemon.test.ts +104 -1
- package/packages/daemon/src/daemon.ts +24 -1
- package/packages/daemon/src/discord-bot.ts +73 -3
- package/packages/daemon/src/event-bridge.ts +15 -9
- package/packages/daemon/src/event-formatter.ts +30 -2
- package/packages/daemon/src/index.ts +9 -0
- package/packages/daemon/src/launchd.test.ts +356 -0
- package/packages/daemon/src/launchd.ts +242 -0
- package/packages/daemon/src/message-batcher.test.ts +2 -2
- package/packages/daemon/src/message-batcher.ts +9 -3
- package/packages/daemon/src/orchestrator.test.ts +1 -0
- package/packages/daemon/src/orchestrator.ts +106 -2
- package/packages/native/dist/ast/index.js +9 -5
- package/packages/native/dist/ast/types.js +2 -1
- package/packages/native/dist/clipboard/index.js +12 -7
- package/packages/native/dist/clipboard/types.js +2 -1
- package/packages/native/dist/diff/index.js +12 -7
- package/packages/native/dist/diff/types.js +2 -1
- package/packages/native/dist/fd/index.js +6 -3
- package/packages/native/dist/fd/types.js +2 -1
- package/packages/native/dist/glob/index.js +9 -5
- package/packages/native/dist/glob/types.js +2 -1
- package/packages/native/dist/grep/index.js +9 -5
- package/packages/native/dist/grep/types.js +2 -1
- package/packages/native/dist/gsd-parser/index.js +18 -11
- package/packages/native/dist/gsd-parser/types.js +2 -1
- package/packages/native/dist/highlight/index.js +12 -7
- package/packages/native/dist/highlight/types.js +2 -1
- package/packages/native/dist/html/index.js +6 -3
- package/packages/native/dist/html/types.js +2 -1
- package/packages/native/dist/image/index.js +10 -5
- package/packages/native/dist/image/types.js +7 -4
- package/packages/native/dist/index.js +70 -17
- package/packages/native/dist/json-parse/index.js +13 -8
- package/packages/native/dist/native.js +47 -10
- package/packages/native/dist/ps/index.js +15 -9
- package/packages/native/dist/ps/types.js +2 -1
- package/packages/native/dist/stream-process/index.js +12 -7
- package/packages/native/dist/text/index.js +24 -14
- package/packages/native/dist/text/types.js +5 -2
- package/packages/native/dist/truncate/index.js +12 -7
- package/packages/native/dist/ttsr/index.js +12 -7
- package/packages/native/dist/ttsr/types.js +2 -1
- package/packages/native/dist/xxhash/index.js +9 -5
- package/packages/native/package.json +19 -19
- package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
- package/packages/native/src/native.ts +9 -8
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/proxy.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
- package/packages/pi-agent-core/src/agent-loop.ts +3 -2
- package/packages/pi-agent-core/src/proxy.ts +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +1 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +3 -3
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/json-parse.d.ts +3 -0
- package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/json-parse.js +24 -1
- package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/index.ts +1 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
- package/packages/pi-ai/src/types.ts +3 -2
- package/packages/pi-ai/src/utils/json-parse.ts +28 -1
- package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/exec.js +3 -1
- package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +31 -2
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +2 -2
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
- package/packages/pi-coding-agent/src/core/exec.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
- package/packages/pi-coding-agent/src/core/index.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
- package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
- package/packages/pi-coding-agent/src/core/messages.ts +29 -2
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
- package/packages/pi-coding-agent/src/index.ts +6 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +9 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/terminal.ts +14 -0
- package/packages/pi-tui/src/tui.ts +8 -0
- package/pkg/package.json +1 -1
- package/scripts/ensure-workspace-builds.cjs +45 -14
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/ask-user-questions.ts +21 -3
- package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
- package/src/resources/extensions/context7/extension-manifest.json +1 -1
- package/src/resources/extensions/get-secrets-from-user.ts +8 -5
- package/src/resources/extensions/google-search/extension-manifest.json +1 -1
- package/src/resources/extensions/google-search/index.ts +2 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +43 -34
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
- package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-start.ts +35 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
- package/src/resources/extensions/gsd/auto.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
- package/src/resources/extensions/gsd/captures.ts +63 -3
- package/src/resources/extensions/gsd/db-writer.ts +140 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +14 -11
- package/src/resources/extensions/gsd/extension-manifest.json +16 -1
- package/src/resources/extensions/gsd/forensics.ts +144 -20
- package/src/resources/extensions/gsd/git-service.ts +26 -3
- package/src/resources/extensions/gsd/gitignore.ts +33 -0
- package/src/resources/extensions/gsd/gsd-db.ts +43 -7
- package/src/resources/extensions/gsd/guided-flow.ts +114 -45
- package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
- package/src/resources/extensions/gsd/health-widget.ts +17 -0
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
- package/src/resources/extensions/gsd/migrate-external.ts +9 -1
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
- package/src/resources/extensions/gsd/model-router.ts +35 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
- package/src/resources/extensions/gsd/notifications.ts +16 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
- package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
- package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
- package/src/resources/extensions/gsd/paths.ts +42 -0
- package/src/resources/extensions/gsd/preferences-models.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +13 -15
- package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/src/resources/extensions/gsd/repo-identity.ts +186 -11
- package/src/resources/extensions/gsd/rethink.ts +6 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
- package/src/resources/extensions/gsd/state.ts +84 -32
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
- package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
- package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
- package/src/resources/extensions/gsd/types.ts +4 -2
- package/src/resources/extensions/gsd/undo.ts +2 -2
- package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
- package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
- package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
- package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
- package/src/resources/extensions/gsd/workspace-index.ts +30 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
- package/src/resources/extensions/mcp-client/index.ts +13 -7
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
- package/src/resources/extensions/ollama/index.ts +130 -0
- package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
- package/src/resources/extensions/ollama/ollama-client.ts +196 -0
- package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
- package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
- package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
- package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
- package/src/resources/extensions/ollama/types.ts +130 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/src/resources/extensions/shared/interview-ui.ts +12 -1
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
- package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
|
@@ -484,3 +484,120 @@ test("runProviderChecks uses object provider field for anthropic-vertex models",
|
|
|
484
484
|
rmSync(repo, { recursive: true, force: true });
|
|
485
485
|
rmSync(tmpHome, { recursive: true, force: true });
|
|
486
486
|
});
|
|
487
|
+
|
|
488
|
+
// ─── Cross-provider routing: Codex & Gemini CLI (#2922) ────────────────────
|
|
489
|
+
|
|
490
|
+
test("runProviderChecks reports ok for Google via google-gemini-cli auth.json (#2922)", () => {
|
|
491
|
+
const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-gemini-cli-repo-")));
|
|
492
|
+
mkdirSync(join(repo, ".gsd"), { recursive: true });
|
|
493
|
+
writeFileSync(
|
|
494
|
+
join(repo, ".gsd", "PREFERENCES.md"),
|
|
495
|
+
[
|
|
496
|
+
"---",
|
|
497
|
+
"models:",
|
|
498
|
+
" execution: gemini-2.5-pro",
|
|
499
|
+
"---",
|
|
500
|
+
"",
|
|
501
|
+
].join("\n"),
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-gemini-cli-home-")));
|
|
505
|
+
const agentDir = join(tmpHome, ".gsd", "agent");
|
|
506
|
+
mkdirSync(agentDir, { recursive: true });
|
|
507
|
+
|
|
508
|
+
// google-gemini-cli OAuth in auth.json (no google API key)
|
|
509
|
+
const authData = {
|
|
510
|
+
"google-gemini-cli": { type: "oauth", apiKey: "ya29.gemini-cli-token", expires: Date.now() + 3_600_000 },
|
|
511
|
+
};
|
|
512
|
+
writeFileSync(join(agentDir, "auth.json"), JSON.stringify(authData));
|
|
513
|
+
|
|
514
|
+
withEnv({
|
|
515
|
+
HOME: tmpHome,
|
|
516
|
+
GEMINI_API_KEY: undefined,
|
|
517
|
+
GOOGLE_API_KEY: undefined,
|
|
518
|
+
}, () => {
|
|
519
|
+
withCwd(repo, () => {
|
|
520
|
+
const results = runProviderChecks();
|
|
521
|
+
const google = results.find(r => r.name === "google");
|
|
522
|
+
assert.ok(google, "google result should exist");
|
|
523
|
+
assert.equal(google!.status, "ok", "should be ok when google-gemini-cli auth is available (#2922)");
|
|
524
|
+
assert.ok(google!.message.includes("Google Gemini CLI"), "should mention Gemini CLI as the source (#2922)");
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
rmSync(repo, { recursive: true, force: true });
|
|
529
|
+
rmSync(tmpHome, { recursive: true, force: true });
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
test("runProviderChecks reports ok for OpenAI via openai-codex auth.json (#2922)", () => {
|
|
533
|
+
const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-codex-repo-")));
|
|
534
|
+
mkdirSync(join(repo, ".gsd"), { recursive: true });
|
|
535
|
+
writeFileSync(
|
|
536
|
+
join(repo, ".gsd", "PREFERENCES.md"),
|
|
537
|
+
[
|
|
538
|
+
"---",
|
|
539
|
+
"models:",
|
|
540
|
+
" execution: gpt-4o",
|
|
541
|
+
"---",
|
|
542
|
+
"",
|
|
543
|
+
].join("\n"),
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-codex-home-")));
|
|
547
|
+
const agentDir = join(tmpHome, ".gsd", "agent");
|
|
548
|
+
mkdirSync(agentDir, { recursive: true });
|
|
549
|
+
|
|
550
|
+
// openai-codex OAuth in auth.json (no openai API key)
|
|
551
|
+
const authData = {
|
|
552
|
+
"openai-codex": { type: "oauth", apiKey: "codex-token", expires: Date.now() + 3_600_000 },
|
|
553
|
+
};
|
|
554
|
+
writeFileSync(join(agentDir, "auth.json"), JSON.stringify(authData));
|
|
555
|
+
|
|
556
|
+
withEnv({
|
|
557
|
+
HOME: tmpHome,
|
|
558
|
+
OPENAI_API_KEY: undefined,
|
|
559
|
+
// Clear Copilot env vars so it doesn't route through Copilot
|
|
560
|
+
COPILOT_GITHUB_TOKEN: undefined,
|
|
561
|
+
GH_TOKEN: undefined,
|
|
562
|
+
GITHUB_TOKEN: undefined,
|
|
563
|
+
}, () => {
|
|
564
|
+
withCwd(repo, () => {
|
|
565
|
+
const results = runProviderChecks();
|
|
566
|
+
const openai = results.find(r => r.name === "openai");
|
|
567
|
+
assert.ok(openai, "openai result should exist");
|
|
568
|
+
assert.equal(openai!.status, "ok", "should be ok when openai-codex auth is available (#2922)");
|
|
569
|
+
assert.ok(openai!.message.includes("Codex"), "should mention Codex as the source (#2922)");
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
rmSync(repo, { recursive: true, force: true });
|
|
574
|
+
rmSync(tmpHome, { recursive: true, force: true });
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
test("PROVIDER_ROUTES includes google-gemini-cli as route for google (#2922)", async () => {
|
|
578
|
+
const { readFileSync: readFS } = await import("node:fs");
|
|
579
|
+
const { dirname: dirn, join: joinPath } = await import("node:path");
|
|
580
|
+
const { fileURLToPath: fileUrl } = await import("node:url");
|
|
581
|
+
const __dir = dirn(fileUrl(import.meta.url));
|
|
582
|
+
const src = readFS(joinPath(__dir, "..", "doctor-providers.ts"), "utf-8");
|
|
583
|
+
|
|
584
|
+
// PROVIDER_ROUTES must map google -> [..., "google-gemini-cli"]
|
|
585
|
+
assert.ok(
|
|
586
|
+
src.includes('"google-gemini-cli"'),
|
|
587
|
+
'PROVIDER_ROUTES must include "google-gemini-cli" as a route (#2922)',
|
|
588
|
+
);
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
test("PROVIDER_ROUTES includes openai-codex as route for openai (#2922)", async () => {
|
|
592
|
+
const { readFileSync: readFS } = await import("node:fs");
|
|
593
|
+
const { dirname: dirn, join: joinPath } = await import("node:path");
|
|
594
|
+
const { fileURLToPath: fileUrl } = await import("node:url");
|
|
595
|
+
const __dir = dirn(fileUrl(import.meta.url));
|
|
596
|
+
const src = readFS(joinPath(__dir, "..", "doctor-providers.ts"), "utf-8");
|
|
597
|
+
|
|
598
|
+
// PROVIDER_ROUTES must map openai -> [..., "openai-codex"]
|
|
599
|
+
assert.ok(
|
|
600
|
+
src.includes('"openai-codex"'),
|
|
601
|
+
'PROVIDER_ROUTES must include "openai-codex" as a route (#2922)',
|
|
602
|
+
);
|
|
603
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic routing default — verifies routing is enabled by default.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { defaultRoutingConfig } from "../model-router.js";
|
|
8
|
+
|
|
9
|
+
test("defaultRoutingConfig returns enabled: true", () => {
|
|
10
|
+
const config = defaultRoutingConfig();
|
|
11
|
+
assert.equal(config.enabled, true, "dynamic routing should be enabled by default");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("defaultRoutingConfig enables all routing features", () => {
|
|
15
|
+
const config = defaultRoutingConfig();
|
|
16
|
+
assert.equal(config.escalate_on_failure, true);
|
|
17
|
+
assert.equal(config.budget_pressure, true);
|
|
18
|
+
assert.equal(config.cross_provider, true);
|
|
19
|
+
assert.equal(config.hooks, true);
|
|
20
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* empty-content-abort-loop.test.ts — Regression test for #2695.
|
|
3
|
+
*
|
|
4
|
+
* When the LLM sends an assistant message with empty `content: []` and
|
|
5
|
+
* `stopReason: "aborted"`, this is NOT a fatal abort — it is a non-fatal
|
|
6
|
+
* end-of-turn. The abort handler in agent-end-recovery.ts must distinguish
|
|
7
|
+
* this case and NOT pause auto-mode, allowing the loop to continue via
|
|
8
|
+
* resolveAgentEnd instead of entering a stuck re-dispatch loop.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import test from "node:test";
|
|
12
|
+
import assert from "node:assert/strict";
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
14
|
+
import { join, dirname } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const RECOVERY_PATH = join(__dirname, "..", "bootstrap", "agent-end-recovery.ts");
|
|
19
|
+
|
|
20
|
+
function getRecoverySource(): string {
|
|
21
|
+
return readFileSync(RECOVERY_PATH, "utf-8");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
test("agent-end-recovery.ts does not pause on aborted messages with empty content (#2695)", () => {
|
|
25
|
+
const source = getRecoverySource();
|
|
26
|
+
|
|
27
|
+
// The abort handler at `stopReason === "aborted"` must check for empty content
|
|
28
|
+
// before deciding to pause. An empty content array is a non-fatal agent stop.
|
|
29
|
+
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
30
|
+
assert.ok(abortIdx > -1, "abort handler must exist in agent-end-recovery.ts");
|
|
31
|
+
|
|
32
|
+
// Extract the region around the abort handler (enough to see the guard logic)
|
|
33
|
+
const abortRegion = source.slice(Math.max(0, abortIdx - 200), abortIdx + 600);
|
|
34
|
+
|
|
35
|
+
// Must check for empty content before pausing
|
|
36
|
+
assert.ok(
|
|
37
|
+
abortRegion.includes("content") && (abortRegion.includes("length") || abortRegion.includes("?.length")),
|
|
38
|
+
"abort handler must inspect content array length to distinguish empty-content aborts from fatal aborts (#2695)",
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("agent-end-recovery.ts routes empty-content aborted messages to resolveAgentEnd (#2695)", () => {
|
|
43
|
+
const source = getRecoverySource();
|
|
44
|
+
|
|
45
|
+
// The abort block must have a path that calls resolveAgentEnd for empty-content messages
|
|
46
|
+
// instead of unconditionally calling pauseAuto
|
|
47
|
+
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
48
|
+
assert.ok(abortIdx > -1, "abort handler must exist");
|
|
49
|
+
|
|
50
|
+
// Get the full abort handling block (from the if to the next stopReason check or success path)
|
|
51
|
+
const afterAbort = source.slice(abortIdx, abortIdx + 800);
|
|
52
|
+
|
|
53
|
+
// The abort block must have a code path that calls resolveAgentEnd (for empty-content case)
|
|
54
|
+
assert.ok(
|
|
55
|
+
afterAbort.includes("resolveAgentEnd"),
|
|
56
|
+
"abort handler must route empty-content aborted messages to resolveAgentEnd instead of always pausing (#2695)",
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("agent-end-recovery.ts checks for errorMessage presence in abort handler (#2695)", () => {
|
|
61
|
+
const source = getRecoverySource();
|
|
62
|
+
|
|
63
|
+
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
64
|
+
assert.ok(abortIdx > -1, "abort handler must exist");
|
|
65
|
+
|
|
66
|
+
const abortRegion = source.slice(abortIdx, abortIdx + 600);
|
|
67
|
+
|
|
68
|
+
// Fatal aborts should have error context (errorMessage field).
|
|
69
|
+
// The handler should check for this to distinguish fatal from non-fatal aborts.
|
|
70
|
+
assert.ok(
|
|
71
|
+
abortRegion.includes("errorMessage"),
|
|
72
|
+
"abort handler must check for errorMessage to distinguish fatal aborts from empty-content non-fatal stops (#2695)",
|
|
73
|
+
);
|
|
74
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// GSD State Machine Regression Tests — Event Replay & Reconciliation (#3161)
|
|
2
|
+
|
|
3
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import {
|
|
6
|
+
openDatabase,
|
|
7
|
+
closeDatabase,
|
|
8
|
+
insertMilestone,
|
|
9
|
+
insertSlice,
|
|
10
|
+
insertTask,
|
|
11
|
+
getTask,
|
|
12
|
+
updateTaskStatus,
|
|
13
|
+
insertVerificationEvidence,
|
|
14
|
+
upsertDecision,
|
|
15
|
+
} from "../gsd-db.ts";
|
|
16
|
+
import { extractEntityKey } from "../workflow-reconcile.ts";
|
|
17
|
+
|
|
18
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
const MID = "M001";
|
|
21
|
+
const SID = "S01";
|
|
22
|
+
const TID = "T01";
|
|
23
|
+
const TS = new Date().toISOString();
|
|
24
|
+
|
|
25
|
+
function setupDb(): void {
|
|
26
|
+
openDatabase(":memory:");
|
|
27
|
+
insertMilestone({ id: MID, title: "Test Milestone" });
|
|
28
|
+
insertSlice({ id: SID, milestoneId: MID, title: "Test Slice" });
|
|
29
|
+
insertTask({ id: TID, sliceId: SID, milestoneId: MID, title: "Test Task" });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
describe("event-replay-idempotency", () => {
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
setupDb();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
closeDatabase();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("updateTaskStatus is idempotent for complete_task replay", () => {
|
|
44
|
+
// Simulates replaying a complete_task event twice (e.g. crash recovery)
|
|
45
|
+
updateTaskStatus(MID, SID, TID, "done", TS);
|
|
46
|
+
updateTaskStatus(MID, SID, TID, "done", TS);
|
|
47
|
+
|
|
48
|
+
const task = getTask(MID, SID, TID);
|
|
49
|
+
assert.ok(task !== null, "task should exist after status update");
|
|
50
|
+
assert.equal(task!.status, "done", "status should be 'done' after double replay");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("updateTaskStatus is idempotent for start_task replay", () => {
|
|
54
|
+
// Simulates replaying a start_task event twice
|
|
55
|
+
updateTaskStatus(MID, SID, TID, "in-progress");
|
|
56
|
+
updateTaskStatus(MID, SID, TID, "in-progress");
|
|
57
|
+
|
|
58
|
+
const task = getTask(MID, SID, TID);
|
|
59
|
+
assert.ok(task !== null, "task should exist after status update");
|
|
60
|
+
assert.equal(task!.status, "in-progress", "status should be 'in-progress' after double replay");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("updateTaskStatus for report_blocker does not set blocker_discovered flag (M4)", () => {
|
|
64
|
+
// M4 finding: report_blocker replay only calls updateTaskStatus("blocked").
|
|
65
|
+
// The blocker_discovered column is NOT set during replay — this is a known
|
|
66
|
+
// lossy replay: status is recovered but the blocker flag is not.
|
|
67
|
+
updateTaskStatus(MID, SID, TID, "blocked");
|
|
68
|
+
|
|
69
|
+
const task = getTask(MID, SID, TID);
|
|
70
|
+
assert.ok(task !== null, "task should exist after blocked status update");
|
|
71
|
+
assert.equal(task!.status, "blocked", "status should be 'blocked'");
|
|
72
|
+
assert.equal(
|
|
73
|
+
task!.blocker_discovered,
|
|
74
|
+
false,
|
|
75
|
+
"blocker_discovered should remain false — report_blocker replay is lossy (M4 finding)",
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("insertVerificationEvidence is NOT idempotent — duplicates accumulate (M5)", () => {
|
|
80
|
+
// M5 finding: insertVerificationEvidence uses a plain INSERT (no ON CONFLICT),
|
|
81
|
+
// so replaying the same record_verification event twice produces two rows.
|
|
82
|
+
// Both calls must succeed without throwing — the duplication is the risk.
|
|
83
|
+
const evidence = {
|
|
84
|
+
taskId: TID,
|
|
85
|
+
sliceId: SID,
|
|
86
|
+
milestoneId: MID,
|
|
87
|
+
command: "npm test",
|
|
88
|
+
exitCode: 0,
|
|
89
|
+
verdict: "pass",
|
|
90
|
+
durationMs: 1200,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
assert.doesNotThrow(
|
|
94
|
+
() => insertVerificationEvidence(evidence),
|
|
95
|
+
"first insertVerificationEvidence call should not throw",
|
|
96
|
+
);
|
|
97
|
+
assert.doesNotThrow(
|
|
98
|
+
() => insertVerificationEvidence(evidence),
|
|
99
|
+
"second insertVerificationEvidence call should not throw — duplicates accumulate silently (M5 finding)",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("upsertDecision is idempotent via INSERT OR REPLACE", () => {
|
|
104
|
+
// save_decision replay uses upsertDecision which is INSERT OR REPLACE,
|
|
105
|
+
// so replaying the same decision id twice overwrites without error.
|
|
106
|
+
const base = {
|
|
107
|
+
id: "arch:logging",
|
|
108
|
+
when_context: "during planning",
|
|
109
|
+
scope: "arch",
|
|
110
|
+
decision: "logging",
|
|
111
|
+
rationale: "structured logs",
|
|
112
|
+
revisable: "yes" as const,
|
|
113
|
+
made_by: "agent" as const,
|
|
114
|
+
superseded_by: null,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
upsertDecision({ ...base, choice: "structured" });
|
|
118
|
+
upsertDecision({ ...base, choice: "unstructured" });
|
|
119
|
+
|
|
120
|
+
// No error means the second call replaced the first — idempotent at the id level.
|
|
121
|
+
// The final choice is "unstructured" per INSERT OR REPLACE semantics.
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("unknown event commands in replayEvents are silently skipped — extractEntityKey returns null for unknown commands", () => {
|
|
125
|
+
// replayEvents uses a switch/default that silently skips unrecognised commands.
|
|
126
|
+
// We verify this via extractEntityKey which follows the same command set.
|
|
127
|
+
// A future_command not in the switch must return null (not throw).
|
|
128
|
+
const event = {
|
|
129
|
+
cmd: "future_command",
|
|
130
|
+
params: { foo: "bar" },
|
|
131
|
+
ts: new Date().toISOString(),
|
|
132
|
+
hash: "0000000000000000",
|
|
133
|
+
actor: "agent" as const,
|
|
134
|
+
session_id: "test-session",
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const key = extractEntityKey(event);
|
|
138
|
+
assert.equal(key, null, "extractEntityKey should return null for unknown commands");
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const gsdDir = join(__dirname, "..");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Test suite for #2941: Forensics report context lost on follow-up turns.
|
|
12
|
+
*
|
|
13
|
+
* The forensics flow sends a one-shot message via sendMessage() with
|
|
14
|
+
* triggerTurn: true. On follow-up turns, the context is gone because
|
|
15
|
+
* there's no re-injection mechanism like buildGuidedExecuteContextInjection
|
|
16
|
+
* provides for task execution.
|
|
17
|
+
*
|
|
18
|
+
* Fix: write an active-forensics.json marker when forensics starts, and
|
|
19
|
+
* have buildBeforeAgentStartResult() re-inject the forensics prompt on
|
|
20
|
+
* subsequent turns.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
describe("forensics context persistence (#2941)", () => {
|
|
24
|
+
// ─── Source-level invariant tests ──────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
it("forensics.ts writes active-forensics marker after saving report", () => {
|
|
27
|
+
const src = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
28
|
+
assert.ok(
|
|
29
|
+
src.includes("active-forensics.json"),
|
|
30
|
+
"forensics.ts must reference active-forensics.json marker file",
|
|
31
|
+
);
|
|
32
|
+
assert.ok(
|
|
33
|
+
src.includes("writeForensicsMarker"),
|
|
34
|
+
"forensics.ts must call writeForensicsMarker to persist session state",
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("system-context.ts checks for active forensics marker in buildBeforeAgentStartResult", () => {
|
|
39
|
+
const src = readFileSync(join(gsdDir, "bootstrap", "system-context.ts"), "utf-8");
|
|
40
|
+
assert.ok(
|
|
41
|
+
src.includes("active-forensics.json"),
|
|
42
|
+
"system-context.ts must check for active-forensics.json marker",
|
|
43
|
+
);
|
|
44
|
+
assert.ok(
|
|
45
|
+
src.includes("gsd-forensics"),
|
|
46
|
+
"system-context.ts must inject gsd-forensics customType message",
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("system-context.ts exports clearForensicsMarker for cleanup", () => {
|
|
51
|
+
const src = readFileSync(join(gsdDir, "bootstrap", "system-context.ts"), "utf-8");
|
|
52
|
+
assert.ok(
|
|
53
|
+
src.includes("clearForensicsMarker"),
|
|
54
|
+
"system-context.ts must export clearForensicsMarker function",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ─── Functional tests using temp directories ──────────────────────────────
|
|
59
|
+
|
|
60
|
+
const tmpBase = join(__dirname, "__tmp_forensics_persist__");
|
|
61
|
+
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
64
|
+
mkdirSync(join(tmpBase, ".gsd", "runtime"), { recursive: true });
|
|
65
|
+
mkdirSync(join(tmpBase, ".gsd", "forensics"), { recursive: true });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("writeForensicsMarker creates marker with reportPath and promptContent", async () => {
|
|
73
|
+
const { writeForensicsMarker } = await import("../forensics.ts");
|
|
74
|
+
|
|
75
|
+
const reportPath = join(tmpBase, ".gsd", "forensics", "report-2026-01-01.md");
|
|
76
|
+
writeFileSync(reportPath, "# Test Report", "utf-8");
|
|
77
|
+
|
|
78
|
+
writeForensicsMarker(tmpBase, reportPath, "Test forensics prompt content");
|
|
79
|
+
|
|
80
|
+
const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
|
|
81
|
+
assert.ok(existsSync(markerPath), "marker file must be created");
|
|
82
|
+
|
|
83
|
+
const marker = JSON.parse(readFileSync(markerPath, "utf-8"));
|
|
84
|
+
assert.equal(marker.reportPath, reportPath);
|
|
85
|
+
assert.equal(marker.promptContent, "Test forensics prompt content");
|
|
86
|
+
assert.ok(marker.createdAt, "marker must have createdAt timestamp");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("readForensicsMarker returns null when no marker exists", async () => {
|
|
90
|
+
const { readForensicsMarker } = await import("../forensics.ts");
|
|
91
|
+
|
|
92
|
+
const result = readForensicsMarker(join(tmpBase, "nonexistent"));
|
|
93
|
+
assert.equal(result, null);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("readForensicsMarker returns marker data when file exists", async () => {
|
|
97
|
+
const { readForensicsMarker } = await import("../forensics.ts");
|
|
98
|
+
|
|
99
|
+
const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
|
|
100
|
+
const markerData = {
|
|
101
|
+
reportPath: "/some/report.md",
|
|
102
|
+
promptContent: "forensics prompt",
|
|
103
|
+
createdAt: new Date().toISOString(),
|
|
104
|
+
};
|
|
105
|
+
writeFileSync(markerPath, JSON.stringify(markerData), "utf-8");
|
|
106
|
+
|
|
107
|
+
const result = readForensicsMarker(tmpBase);
|
|
108
|
+
assert.ok(result);
|
|
109
|
+
assert.equal(result.reportPath, "/some/report.md");
|
|
110
|
+
assert.equal(result.promptContent, "forensics prompt");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("clearForensicsMarker removes the marker file", async () => {
|
|
114
|
+
const { clearForensicsMarker } = await import("../bootstrap/system-context.ts");
|
|
115
|
+
|
|
116
|
+
const markerPath = join(tmpBase, ".gsd", "runtime", "active-forensics.json");
|
|
117
|
+
writeFileSync(markerPath, JSON.stringify({ reportPath: "/x", promptContent: "y", createdAt: new Date().toISOString() }), "utf-8");
|
|
118
|
+
assert.ok(existsSync(markerPath), "precondition: marker must exist");
|
|
119
|
+
|
|
120
|
+
clearForensicsMarker(tmpBase);
|
|
121
|
+
assert.ok(!existsSync(markerPath), "marker must be removed after clear");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("clearForensicsMarker is a no-op when no marker exists", async () => {
|
|
125
|
+
const { clearForensicsMarker } = await import("../bootstrap/system-context.ts");
|
|
126
|
+
// Should not throw
|
|
127
|
+
clearForensicsMarker(join(tmpBase, "nonexistent"));
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const gsdDir = join(__dirname, "..");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Tests for #3129: forensics reads DB for completion status instead of legacy file.
|
|
12
|
+
*
|
|
13
|
+
* The old loadCompletedKeys() reads completed-units.json which is never populated
|
|
14
|
+
* during normal auto-mode completion. The DB (milestones/slices/tasks tables) is
|
|
15
|
+
* the authoritative source for completion status.
|
|
16
|
+
*/
|
|
17
|
+
describe("forensics DB completion status (#3129)", () => {
|
|
18
|
+
const forensicsSrc = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
19
|
+
const stateSrc = readFileSync(join(gsdDir, "state.ts"), "utf-8");
|
|
20
|
+
|
|
21
|
+
// ── Primary fix: forensics queries DB for completion counts ──────────
|
|
22
|
+
|
|
23
|
+
it("ForensicReport has dbCompletionCounts field for DB-sourced completion data", () => {
|
|
24
|
+
assert.ok(
|
|
25
|
+
forensicsSrc.includes("dbCompletionCounts"),
|
|
26
|
+
"ForensicReport must include dbCompletionCounts field for DB-sourced completion data",
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("buildForensicReport queries DB for completed milestones, slices, and tasks", () => {
|
|
31
|
+
assert.ok(
|
|
32
|
+
forensicsSrc.includes("getDbCompletionCounts"),
|
|
33
|
+
"buildForensicReport must call getDbCompletionCounts to query DB completion status",
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("getDbCompletionCounts checks isDbAvailable before querying", () => {
|
|
38
|
+
assert.ok(
|
|
39
|
+
forensicsSrc.includes("isDbAvailable"),
|
|
40
|
+
"getDbCompletionCounts must check isDbAvailable() before querying the DB",
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("getDbCompletionCounts queries getAllMilestones for milestone completion", () => {
|
|
45
|
+
assert.ok(
|
|
46
|
+
forensicsSrc.includes("getAllMilestones"),
|
|
47
|
+
"getDbCompletionCounts must use getAllMilestones() to count completed milestones",
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("completion counting uses isClosedStatus for consistent status checks", () => {
|
|
52
|
+
assert.ok(
|
|
53
|
+
forensicsSrc.includes("isClosedStatus"),
|
|
54
|
+
"forensics must use isClosedStatus() for consistent status checks",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("report rendering shows DB completion counts instead of just legacy key count", () => {
|
|
59
|
+
assert.ok(
|
|
60
|
+
forensicsSrc.includes("milestones complete"),
|
|
61
|
+
"report must show '__ milestones complete' from DB data",
|
|
62
|
+
);
|
|
63
|
+
assert.ok(
|
|
64
|
+
forensicsSrc.includes("slices complete"),
|
|
65
|
+
"report must show '__ slices complete' from DB data",
|
|
66
|
+
);
|
|
67
|
+
assert.ok(
|
|
68
|
+
forensicsSrc.includes("tasks complete"),
|
|
69
|
+
"report must show '__ tasks complete' from DB data",
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("falls back to completed-units.json only when DB is unavailable", () => {
|
|
74
|
+
// loadCompletedKeys should still exist as fallback
|
|
75
|
+
assert.ok(
|
|
76
|
+
forensicsSrc.includes("loadCompletedKeys"),
|
|
77
|
+
"loadCompletedKeys must still exist as fallback for non-DB projects",
|
|
78
|
+
);
|
|
79
|
+
// But the report should prefer DB counts
|
|
80
|
+
assert.ok(
|
|
81
|
+
forensicsSrc.includes("dbCompletionCounts"),
|
|
82
|
+
"report must prefer dbCompletionCounts over legacy completedKeys",
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// ── Secondary fix: STATE.md label when all milestones complete ───────
|
|
87
|
+
|
|
88
|
+
it("state.ts returns null activeMilestone when all milestones are complete", () => {
|
|
89
|
+
// When phase is "complete", activeMilestone should be null, not the last milestone
|
|
90
|
+
// The last completed milestone should be in a separate field
|
|
91
|
+
assert.ok(
|
|
92
|
+
stateSrc.includes("lastCompletedMilestone"),
|
|
93
|
+
"GSDState must have lastCompletedMilestone field for the final milestone when phase=complete",
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -46,3 +46,34 @@ describe("forensics dedup (#2096)", () => {
|
|
|
46
46
|
"opt-in notice must mention duplicate detection");
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
|
+
|
|
50
|
+
describe("forensics dedup ordering (#2704)", () => {
|
|
51
|
+
it("{{dedupSection}} appears before Investigation Protocol in the prompt template", () => {
|
|
52
|
+
const prompt = readFileSync(join(gsdDir, "prompts", "forensics.md"), "utf-8");
|
|
53
|
+
const dedupIndex = prompt.indexOf("{{dedupSection}}");
|
|
54
|
+
const investigationIndex = prompt.indexOf("## Investigation Protocol");
|
|
55
|
+
assert.ok(dedupIndex !== -1, "prompt must contain {{dedupSection}}");
|
|
56
|
+
assert.ok(investigationIndex !== -1, "prompt must contain ## Investigation Protocol");
|
|
57
|
+
assert.ok(
|
|
58
|
+
dedupIndex < investigationIndex,
|
|
59
|
+
`{{dedupSection}} (index ${dedupIndex}) must appear before Investigation Protocol (index ${investigationIndex}) — dedup should run before expensive investigation to avoid wasting tokens on already-fixed bugs`,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("DEDUP_PROMPT_SECTION contains a decision gate to skip investigation", () => {
|
|
64
|
+
const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
65
|
+
// The dedup section must instruct the agent to skip investigation when a match is found
|
|
66
|
+
assert.ok(
|
|
67
|
+
source.includes("Skip full investigation") || source.includes("skip full investigation") || source.includes("Skip investigation"),
|
|
68
|
+
"DEDUP_PROMPT_SECTION must contain a decision gate telling the agent to skip full investigation when a duplicate is found",
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("DEDUP_PROMPT_SECTION heading reflects pre-investigation role", () => {
|
|
73
|
+
const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
74
|
+
assert.ok(
|
|
75
|
+
source.includes("Pre-Investigation") || source.includes("pre-investigation"),
|
|
76
|
+
"DEDUP_PROMPT_SECTION heading must indicate it runs before investigation, not just before issue creation",
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
});
|