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
|
@@ -21,8 +21,10 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
saveDecisionToDb,
|
|
23
23
|
updateRequirementInDb,
|
|
24
|
+
saveRequirementToDb,
|
|
24
25
|
saveArtifactToDb,
|
|
25
26
|
nextDecisionId,
|
|
27
|
+
nextRequirementId,
|
|
26
28
|
} from '../db-writer.ts';
|
|
27
29
|
import type { Requirement } from '../types.ts';
|
|
28
30
|
|
|
@@ -160,18 +162,11 @@ describe('gsd-tools', () => {
|
|
|
160
162
|
assert.ok(mdContent.includes('R001'), 'REQUIREMENTS.md should contain R001');
|
|
161
163
|
assert.ok(mdContent.includes('validated'), 'REQUIREMENTS.md should reflect updated status');
|
|
162
164
|
|
|
163
|
-
// Updating non-existent requirement
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
threwForMissing = true;
|
|
169
|
-
assert.ok(
|
|
170
|
-
(err as Error).message.includes('R999'),
|
|
171
|
-
'Error should mention the missing requirement ID',
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
assert.ok(threwForMissing, 'Should throw for non-existent requirement');
|
|
165
|
+
// Updating non-existent requirement upserts (creates it) — see #2919
|
|
166
|
+
await updateRequirementInDb('R999', { status: 'deferred' }, tmpDir);
|
|
167
|
+
const upserted = getRequirementById('R999');
|
|
168
|
+
assert.ok(upserted !== null, 'R999 should be created by upsert');
|
|
169
|
+
assert.deepStrictEqual(upserted!.status, 'deferred', 'Upserted requirement should have the updated status');
|
|
175
170
|
|
|
176
171
|
closeDatabase();
|
|
177
172
|
} finally {
|
|
@@ -263,6 +258,124 @@ describe('gsd-tools', () => {
|
|
|
263
258
|
assert.deepStrictEqual(fallbackId, 'D001', 'nextDecisionId should return D001 when DB unavailable');
|
|
264
259
|
});
|
|
265
260
|
|
|
261
|
+
test('gsd_requirement_save creates new requirement', async () => {
|
|
262
|
+
const tmpDir = makeTmpDir();
|
|
263
|
+
try {
|
|
264
|
+
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
265
|
+
openDatabase(dbPath);
|
|
266
|
+
|
|
267
|
+
// (a) saveRequirementToDb creates a new requirement with auto-assigned ID
|
|
268
|
+
const result = await saveRequirementToDb(
|
|
269
|
+
{
|
|
270
|
+
class: 'functional',
|
|
271
|
+
status: 'active',
|
|
272
|
+
description: 'Must support dark mode',
|
|
273
|
+
why: 'Accessibility requirement',
|
|
274
|
+
source: 'user-research',
|
|
275
|
+
},
|
|
276
|
+
tmpDir,
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
assert.deepStrictEqual(result.id, 'R001', 'First requirement should be R001');
|
|
280
|
+
|
|
281
|
+
// Verify DB row exists
|
|
282
|
+
const row = getRequirementById('R001');
|
|
283
|
+
assert.ok(row !== null, 'Requirement R001 should exist in DB');
|
|
284
|
+
assert.deepStrictEqual(row!.class, 'functional', 'Class should match');
|
|
285
|
+
assert.deepStrictEqual(row!.description, 'Must support dark mode', 'Description should match');
|
|
286
|
+
assert.deepStrictEqual(row!.status, 'active', 'Status should match');
|
|
287
|
+
|
|
288
|
+
// Verify REQUIREMENTS.md was generated
|
|
289
|
+
const mdPath = path.join(tmpDir, '.gsd', 'REQUIREMENTS.md');
|
|
290
|
+
assert.ok(fs.existsSync(mdPath), 'REQUIREMENTS.md should be created');
|
|
291
|
+
const mdContent = fs.readFileSync(mdPath, 'utf-8');
|
|
292
|
+
assert.ok(mdContent.includes('R001'), 'REQUIREMENTS.md should contain R001');
|
|
293
|
+
assert.ok(mdContent.includes('dark mode'), 'REQUIREMENTS.md should contain description');
|
|
294
|
+
|
|
295
|
+
// (b) Auto-assigns correct next ID
|
|
296
|
+
const result2 = await saveRequirementToDb(
|
|
297
|
+
{
|
|
298
|
+
class: 'non-functional',
|
|
299
|
+
status: 'active',
|
|
300
|
+
description: 'Must load in under 2 seconds',
|
|
301
|
+
why: 'Performance SLA',
|
|
302
|
+
source: 'design',
|
|
303
|
+
},
|
|
304
|
+
tmpDir,
|
|
305
|
+
);
|
|
306
|
+
assert.deepStrictEqual(result2.id, 'R002', 'Second requirement should be R002');
|
|
307
|
+
|
|
308
|
+
closeDatabase();
|
|
309
|
+
} finally {
|
|
310
|
+
cleanupDir(tmpDir);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test('nextRequirementId computes correct next ID', async () => {
|
|
315
|
+
const tmpDir = makeTmpDir();
|
|
316
|
+
try {
|
|
317
|
+
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
318
|
+
openDatabase(dbPath);
|
|
319
|
+
|
|
320
|
+
// No requirements yet
|
|
321
|
+
const id1 = await nextRequirementId();
|
|
322
|
+
assert.deepStrictEqual(id1, 'R001', 'Should return R001 when no requirements exist');
|
|
323
|
+
|
|
324
|
+
// Add one requirement
|
|
325
|
+
upsertRequirement({
|
|
326
|
+
id: 'R001',
|
|
327
|
+
class: 'functional',
|
|
328
|
+
status: 'active',
|
|
329
|
+
description: 'Test',
|
|
330
|
+
why: '',
|
|
331
|
+
source: '',
|
|
332
|
+
primary_owner: '',
|
|
333
|
+
supporting_slices: '',
|
|
334
|
+
validation: '',
|
|
335
|
+
notes: '',
|
|
336
|
+
full_content: '',
|
|
337
|
+
superseded_by: null,
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const id2 = await nextRequirementId();
|
|
341
|
+
assert.deepStrictEqual(id2, 'R002', 'Should return R002 after R001 exists');
|
|
342
|
+
|
|
343
|
+
closeDatabase();
|
|
344
|
+
} finally {
|
|
345
|
+
cleanupDir(tmpDir);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
test('gsd_requirement_update upserts when requirement not in DB', async () => {
|
|
350
|
+
const tmpDir = makeTmpDir();
|
|
351
|
+
try {
|
|
352
|
+
const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
|
|
353
|
+
openDatabase(dbPath);
|
|
354
|
+
|
|
355
|
+
// Requirement R025 does NOT exist in DB — simulates the bug scenario
|
|
356
|
+
// where requirements exist in REQUIREMENTS.md but were never imported.
|
|
357
|
+
// updateRequirementInDb should create the row instead of throwing.
|
|
358
|
+
await updateRequirementInDb(
|
|
359
|
+
'R025',
|
|
360
|
+
{ status: 'validated', validation: 'Integration tests pass' },
|
|
361
|
+
tmpDir,
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
const created = getRequirementById('R025');
|
|
365
|
+
assert.ok(created !== null, 'R025 should be created by upsert');
|
|
366
|
+
assert.deepStrictEqual(created!.status, 'validated', 'Status should be set');
|
|
367
|
+
assert.deepStrictEqual(created!.validation, 'Integration tests pass', 'Validation should be set');
|
|
368
|
+
|
|
369
|
+
// Verify REQUIREMENTS.md was generated
|
|
370
|
+
const mdPath = path.join(tmpDir, '.gsd', 'REQUIREMENTS.md');
|
|
371
|
+
assert.ok(fs.existsSync(mdPath), 'REQUIREMENTS.md should be created');
|
|
372
|
+
|
|
373
|
+
closeDatabase();
|
|
374
|
+
} finally {
|
|
375
|
+
cleanupDir(tmpDir);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
|
|
266
379
|
test('Tool result format', async () => {
|
|
267
380
|
const tmpDir = makeTmpDir();
|
|
268
381
|
try {
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gsdroot-worktree-detection.test.ts — Regression test for #2594.
|
|
3
|
+
*
|
|
4
|
+
* gsdRoot() must return the worktree's own .gsd directory when the basePath
|
|
5
|
+
* is inside a .gsd/worktrees/<name>/ structure, not walk up to the project
|
|
6
|
+
* root's .gsd via the git-root probe.
|
|
7
|
+
*
|
|
8
|
+
* The bug: when a git worktree lives at /project/.gsd/worktrees/M008/,
|
|
9
|
+
* probeGsdRoot() runs `git rev-parse --show-toplevel` which can return the
|
|
10
|
+
* main project root (not the worktree root) depending on git version and
|
|
11
|
+
* worktree setup. The walk-up then finds /project/.gsd and returns that
|
|
12
|
+
* instead of the worktree's own .gsd path.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
16
|
+
import assert from "node:assert/strict";
|
|
17
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { mkdtempSync, realpathSync } from "node:fs";
|
|
20
|
+
import { tmpdir } from "node:os";
|
|
21
|
+
import { spawnSync } from "node:child_process";
|
|
22
|
+
|
|
23
|
+
import { gsdRoot, _clearGsdRootCache } from "../paths.ts";
|
|
24
|
+
|
|
25
|
+
describe("gsdRoot() worktree detection (#2594)", () => {
|
|
26
|
+
let projectRoot: string;
|
|
27
|
+
let projectGsd: string;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
_clearGsdRootCache();
|
|
31
|
+
// Create a temporary project with a git repo to simulate real conditions.
|
|
32
|
+
// realpathSync handles macOS /tmp -> /private/tmp.
|
|
33
|
+
projectRoot = realpathSync(mkdtempSync(join(tmpdir(), "gsdroot-wt-")));
|
|
34
|
+
projectGsd = join(projectRoot, ".gsd");
|
|
35
|
+
mkdirSync(projectGsd, { recursive: true });
|
|
36
|
+
|
|
37
|
+
// Initialize a git repo in the project root so git rev-parse works
|
|
38
|
+
spawnSync("git", ["init", "--initial-branch=main"], {
|
|
39
|
+
cwd: projectRoot,
|
|
40
|
+
stdio: "ignore",
|
|
41
|
+
});
|
|
42
|
+
spawnSync("git", ["config", "user.email", "test@test.com"], {
|
|
43
|
+
cwd: projectRoot,
|
|
44
|
+
stdio: "ignore",
|
|
45
|
+
});
|
|
46
|
+
spawnSync("git", ["config", "user.name", "Test"], {
|
|
47
|
+
cwd: projectRoot,
|
|
48
|
+
stdio: "ignore",
|
|
49
|
+
});
|
|
50
|
+
// Create an initial commit so we have a HEAD
|
|
51
|
+
writeFileSync(join(projectRoot, "README.md"), "# Test");
|
|
52
|
+
spawnSync("git", ["add", "."], { cwd: projectRoot, stdio: "ignore" });
|
|
53
|
+
spawnSync("git", ["commit", "-m", "init"], {
|
|
54
|
+
cwd: projectRoot,
|
|
55
|
+
stdio: "ignore",
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
_clearGsdRootCache();
|
|
61
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("returns worktree .gsd when basePath is a worktree with its own .gsd (fast path)", () => {
|
|
65
|
+
// Simulates a worktree that already had copyPlanningArtifacts() run,
|
|
66
|
+
// so it has its own .gsd/ directory.
|
|
67
|
+
const worktreeBase = join(projectGsd, "worktrees", "M008");
|
|
68
|
+
const worktreeGsd = join(worktreeBase, ".gsd");
|
|
69
|
+
mkdirSync(worktreeGsd, { recursive: true });
|
|
70
|
+
|
|
71
|
+
const result = gsdRoot(worktreeBase);
|
|
72
|
+
assert.equal(
|
|
73
|
+
result,
|
|
74
|
+
worktreeGsd,
|
|
75
|
+
`Expected worktree .gsd (${worktreeGsd}), got ${result}. ` +
|
|
76
|
+
"gsdRoot() should use the fast path for an existing worktree .gsd.",
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("returns worktree .gsd path (not project root .gsd) when worktree .gsd does not exist yet", () => {
|
|
81
|
+
// This is the core #2594 bug: the worktree directory exists but its .gsd
|
|
82
|
+
// subdirectory hasn't been created yet. Without the fix, probeGsdRoot()
|
|
83
|
+
// walks up from the worktree path, finds /project/.gsd, and returns it.
|
|
84
|
+
// With the fix, it detects the .gsd/worktrees/<name>/ pattern and returns
|
|
85
|
+
// the worktree-local .gsd path as the creation fallback.
|
|
86
|
+
const worktreeBase = join(projectGsd, "worktrees", "M008");
|
|
87
|
+
mkdirSync(worktreeBase, { recursive: true });
|
|
88
|
+
// NOTE: no .gsd/ inside worktreeBase
|
|
89
|
+
|
|
90
|
+
const result = gsdRoot(worktreeBase);
|
|
91
|
+
const expected = join(worktreeBase, ".gsd");
|
|
92
|
+
|
|
93
|
+
// Without the fix, this returns projectGsd (/project/.gsd) because the
|
|
94
|
+
// walk-up from worktreeBase finds it. With the fix, it returns the
|
|
95
|
+
// worktree-local path.
|
|
96
|
+
assert.notEqual(
|
|
97
|
+
result,
|
|
98
|
+
projectGsd,
|
|
99
|
+
"gsdRoot() must NOT return the project root .gsd when basePath is inside .gsd/worktrees/",
|
|
100
|
+
);
|
|
101
|
+
assert.equal(
|
|
102
|
+
result,
|
|
103
|
+
expected,
|
|
104
|
+
`Expected worktree-local .gsd (${expected}), got ${result}.`,
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("returns worktree .gsd when basePath is a real git worktree inside .gsd/worktrees/", () => {
|
|
109
|
+
// Create a real git worktree at .gsd/worktrees/M010
|
|
110
|
+
const worktreeName = "M010";
|
|
111
|
+
const worktreeBase = join(projectGsd, "worktrees", worktreeName);
|
|
112
|
+
|
|
113
|
+
// Use git worktree add to create a real worktree
|
|
114
|
+
const result = spawnSync(
|
|
115
|
+
"git",
|
|
116
|
+
["worktree", "add", "-b", `milestone/${worktreeName}`, worktreeBase],
|
|
117
|
+
{ cwd: projectRoot, encoding: "utf-8" },
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (result.status !== 0) {
|
|
121
|
+
// If git worktree add fails, skip the test gracefully
|
|
122
|
+
assert.ok(true, "Skipped: git worktree add not available");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// The real git worktree exists at worktreeBase but has NO .gsd/ subdir yet
|
|
127
|
+
const gsdResult = gsdRoot(worktreeBase);
|
|
128
|
+
const expected = join(worktreeBase, ".gsd");
|
|
129
|
+
|
|
130
|
+
assert.notEqual(
|
|
131
|
+
gsdResult,
|
|
132
|
+
projectGsd,
|
|
133
|
+
"gsdRoot() must NOT escape to project root .gsd from inside a git worktree",
|
|
134
|
+
);
|
|
135
|
+
assert.equal(
|
|
136
|
+
gsdResult,
|
|
137
|
+
expected,
|
|
138
|
+
`Expected worktree-local .gsd (${expected}), got ${gsdResult}`,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// Cleanup worktree
|
|
142
|
+
spawnSync("git", ["worktree", "remove", "--force", worktreeBase], {
|
|
143
|
+
cwd: projectRoot,
|
|
144
|
+
stdio: "ignore",
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("still returns project .gsd for normal (non-worktree) basePath", () => {
|
|
149
|
+
const result = gsdRoot(projectRoot);
|
|
150
|
+
assert.equal(result, projectGsd);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("still returns project .gsd for a subdirectory of the project", () => {
|
|
154
|
+
const subdir = join(projectRoot, "src", "lib");
|
|
155
|
+
mkdirSync(subdir, { recursive: true });
|
|
156
|
+
|
|
157
|
+
const result = gsdRoot(subdir);
|
|
158
|
+
assert.equal(
|
|
159
|
+
result,
|
|
160
|
+
projectGsd,
|
|
161
|
+
"Non-worktree subdirectories should still resolve to project .gsd",
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guided-flow dynamic routing — regression test for #2958.
|
|
3
|
+
*
|
|
4
|
+
* Verifies that dispatchWorkflow() routes through the dynamic routing pipeline
|
|
5
|
+
* (selectAndApplyModel from auto-model-selection.ts) instead of bypassing it
|
|
6
|
+
* with a direct call to resolveModelWithFallbacksForUnit.
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
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 gsdDir = join(__dirname, "..");
|
|
19
|
+
|
|
20
|
+
function readSrc(file: string): string {
|
|
21
|
+
return readFileSync(join(gsdDir, file), "utf-8");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const guidedFlowSrc = readSrc("guided-flow.ts");
|
|
25
|
+
|
|
26
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
27
|
+
// #2958: dispatchWorkflow must route through dynamic routing pipeline
|
|
28
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
29
|
+
|
|
30
|
+
test("#2958: guided-flow imports selectAndApplyModel from auto-model-selection", () => {
|
|
31
|
+
assert.ok(
|
|
32
|
+
guidedFlowSrc.includes("selectAndApplyModel"),
|
|
33
|
+
"guided-flow.ts must import and use selectAndApplyModel from auto-model-selection.ts",
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("#2958: dispatchWorkflow does not call resolveModelWithFallbacksForUnit directly", () => {
|
|
38
|
+
// Extract the dispatchWorkflow function body
|
|
39
|
+
const fnStart = guidedFlowSrc.indexOf("async function dispatchWorkflow(");
|
|
40
|
+
assert.ok(fnStart !== -1, "dispatchWorkflow function not found");
|
|
41
|
+
|
|
42
|
+
// Find the function body by tracking brace depth
|
|
43
|
+
const openBrace = guidedFlowSrc.indexOf("{", fnStart);
|
|
44
|
+
let depth = 1;
|
|
45
|
+
let pos = openBrace + 1;
|
|
46
|
+
while (depth > 0 && pos < guidedFlowSrc.length) {
|
|
47
|
+
if (guidedFlowSrc[pos] === "{") depth++;
|
|
48
|
+
else if (guidedFlowSrc[pos] === "}") depth--;
|
|
49
|
+
pos++;
|
|
50
|
+
}
|
|
51
|
+
const fnBody = guidedFlowSrc.slice(openBrace, pos);
|
|
52
|
+
|
|
53
|
+
assert.ok(
|
|
54
|
+
!fnBody.includes("resolveModelWithFallbacksForUnit"),
|
|
55
|
+
"dispatchWorkflow must NOT call resolveModelWithFallbacksForUnit directly — " +
|
|
56
|
+
"it must route through selectAndApplyModel for dynamic routing support (#2958)",
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("#2958: dispatchWorkflow calls selectAndApplyModel for model selection", () => {
|
|
61
|
+
// Extract the dispatchWorkflow function body
|
|
62
|
+
const fnStart = guidedFlowSrc.indexOf("async function dispatchWorkflow(");
|
|
63
|
+
assert.ok(fnStart !== -1, "dispatchWorkflow function not found");
|
|
64
|
+
|
|
65
|
+
const openBrace = guidedFlowSrc.indexOf("{", fnStart);
|
|
66
|
+
let depth = 1;
|
|
67
|
+
let pos = openBrace + 1;
|
|
68
|
+
while (depth > 0 && pos < guidedFlowSrc.length) {
|
|
69
|
+
if (guidedFlowSrc[pos] === "{") depth++;
|
|
70
|
+
else if (guidedFlowSrc[pos] === "}") depth--;
|
|
71
|
+
pos++;
|
|
72
|
+
}
|
|
73
|
+
const fnBody = guidedFlowSrc.slice(openBrace, pos);
|
|
74
|
+
|
|
75
|
+
assert.ok(
|
|
76
|
+
fnBody.includes("selectAndApplyModel"),
|
|
77
|
+
"dispatchWorkflow must call selectAndApplyModel to route through the dynamic routing pipeline (#2958)",
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("#2958: dispatchWorkflow does not use resolveAvailableModel inline", () => {
|
|
82
|
+
const fnStart = guidedFlowSrc.indexOf("async function dispatchWorkflow(");
|
|
83
|
+
assert.ok(fnStart !== -1, "dispatchWorkflow function not found");
|
|
84
|
+
|
|
85
|
+
const openBrace = guidedFlowSrc.indexOf("{", fnStart);
|
|
86
|
+
let depth = 1;
|
|
87
|
+
let pos = openBrace + 1;
|
|
88
|
+
while (depth > 0 && pos < guidedFlowSrc.length) {
|
|
89
|
+
if (guidedFlowSrc[pos] === "{") depth++;
|
|
90
|
+
else if (guidedFlowSrc[pos] === "}") depth--;
|
|
91
|
+
pos++;
|
|
92
|
+
}
|
|
93
|
+
const fnBody = guidedFlowSrc.slice(openBrace, pos);
|
|
94
|
+
|
|
95
|
+
assert.ok(
|
|
96
|
+
!fnBody.includes("resolveAvailableModel"),
|
|
97
|
+
"dispatchWorkflow must NOT use resolveAvailableModel inline — " +
|
|
98
|
+
"model resolution is handled by selectAndApplyModel (#2958)",
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("#2958: guided-flow does not import resolveModelWithFallbacksForUnit", () => {
|
|
103
|
+
// The import should be removed since dispatchWorkflow was the only consumer
|
|
104
|
+
// Check if resolveModelWithFallbacksForUnit is still used elsewhere in the file
|
|
105
|
+
const fnStart = guidedFlowSrc.indexOf("async function dispatchWorkflow(");
|
|
106
|
+
const beforeDispatch = guidedFlowSrc.slice(0, fnStart);
|
|
107
|
+
const afterFnEnd = (() => {
|
|
108
|
+
const openBrace = guidedFlowSrc.indexOf("{", fnStart);
|
|
109
|
+
let depth = 1;
|
|
110
|
+
let p = openBrace + 1;
|
|
111
|
+
while (depth > 0 && p < guidedFlowSrc.length) {
|
|
112
|
+
if (guidedFlowSrc[p] === "{") depth++;
|
|
113
|
+
else if (guidedFlowSrc[p] === "}") depth--;
|
|
114
|
+
p++;
|
|
115
|
+
}
|
|
116
|
+
return guidedFlowSrc.slice(p);
|
|
117
|
+
})();
|
|
118
|
+
|
|
119
|
+
// If resolveModelWithFallbacksForUnit is not used outside dispatchWorkflow,
|
|
120
|
+
// the import should be removed
|
|
121
|
+
const usedOutside = beforeDispatch.includes("resolveModelWithFallbacksForUnit(")
|
|
122
|
+
|| afterFnEnd.includes("resolveModelWithFallbacksForUnit(");
|
|
123
|
+
|
|
124
|
+
if (!usedOutside) {
|
|
125
|
+
// Verify the import line was cleaned up
|
|
126
|
+
const importLines = guidedFlowSrc.split("\n").filter(l =>
|
|
127
|
+
l.includes("import") && l.includes("resolveModelWithFallbacksForUnit"),
|
|
128
|
+
);
|
|
129
|
+
assert.equal(
|
|
130
|
+
importLines.length,
|
|
131
|
+
0,
|
|
132
|
+
"resolveModelWithFallbacksForUnit import should be removed when no longer used outside dispatchWorkflow",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #2985 Bugs 3 & 4:
|
|
3
|
+
* Bug 3 — module-level pendingAutoStart singleton clobbers concurrent sessions.
|
|
4
|
+
* Bug 4 — getDiscussionMilestoneId() returns wrong project's milestone under concurrency.
|
|
5
|
+
*
|
|
6
|
+
* pendingAutoStart must be keyed by basePath so concurrent discuss sessions
|
|
7
|
+
* in different projects are independent. getDiscussionMilestoneId() must accept
|
|
8
|
+
* a basePath parameter to perform a keyed lookup.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, test, beforeEach } from "node:test";
|
|
12
|
+
import assert from "node:assert/strict";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
getDiscussionMilestoneId,
|
|
16
|
+
setPendingAutoStart,
|
|
17
|
+
clearPendingAutoStart,
|
|
18
|
+
} from "../guided-flow.ts";
|
|
19
|
+
|
|
20
|
+
// ─── Tests ─────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
describe("#2985 Bug 3 — concurrent discuss sessions must be independent", () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
clearPendingAutoStart();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("second session does not clobber first session's pending auto-start", () => {
|
|
28
|
+
// Simulate two concurrent discuss sessions for different projects
|
|
29
|
+
const projectA = "/projects/alpha";
|
|
30
|
+
const projectB = "/projects/beta";
|
|
31
|
+
|
|
32
|
+
setPendingAutoStart(projectA, {
|
|
33
|
+
basePath: projectA,
|
|
34
|
+
milestoneId: "M001-aaa111",
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
setPendingAutoStart(projectB, {
|
|
38
|
+
basePath: projectB,
|
|
39
|
+
milestoneId: "M002-bbb222",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Both sessions should be retrievable
|
|
43
|
+
const milestoneA = getDiscussionMilestoneId(projectA);
|
|
44
|
+
const milestoneB = getDiscussionMilestoneId(projectB);
|
|
45
|
+
|
|
46
|
+
assert.equal(milestoneA, "M001-aaa111", "projectA's milestone should be preserved");
|
|
47
|
+
assert.equal(milestoneB, "M002-bbb222", "projectB's milestone should be preserved");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("clearing one session does not affect the other", () => {
|
|
51
|
+
const projectA = "/projects/alpha";
|
|
52
|
+
const projectB = "/projects/beta";
|
|
53
|
+
|
|
54
|
+
setPendingAutoStart(projectA, { basePath: projectA, milestoneId: "M001-aaa111" });
|
|
55
|
+
setPendingAutoStart(projectB, { basePath: projectB, milestoneId: "M002-bbb222" });
|
|
56
|
+
|
|
57
|
+
// Clear only projectA
|
|
58
|
+
clearPendingAutoStart(projectA);
|
|
59
|
+
|
|
60
|
+
assert.equal(getDiscussionMilestoneId(projectA), null, "projectA should be cleared");
|
|
61
|
+
assert.equal(getDiscussionMilestoneId(projectB), "M002-bbb222", "projectB should survive");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("#2985 Bug 4 — getDiscussionMilestoneId must be keyed by basePath", () => {
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
clearPendingAutoStart();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("getDiscussionMilestoneId(basePath) returns correct milestone for each project", () => {
|
|
71
|
+
setPendingAutoStart("/proj/a", { basePath: "/proj/a", milestoneId: "M001" });
|
|
72
|
+
setPendingAutoStart("/proj/b", { basePath: "/proj/b", milestoneId: "M002" });
|
|
73
|
+
|
|
74
|
+
assert.equal(getDiscussionMilestoneId("/proj/a"), "M001");
|
|
75
|
+
assert.equal(getDiscussionMilestoneId("/proj/b"), "M002");
|
|
76
|
+
assert.equal(getDiscussionMilestoneId("/proj/unknown"), null);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("getDiscussionMilestoneId() without basePath returns null when multiple sessions exist", () => {
|
|
80
|
+
setPendingAutoStart("/proj/a", { basePath: "/proj/a", milestoneId: "M001" });
|
|
81
|
+
setPendingAutoStart("/proj/b", { basePath: "/proj/b", milestoneId: "M002" });
|
|
82
|
+
|
|
83
|
+
// Without a key, the function should not blindly return the first entry
|
|
84
|
+
const result = getDiscussionMilestoneId();
|
|
85
|
+
// When there's ambiguity (multiple sessions), it should return null
|
|
86
|
+
// to force callers to be explicit
|
|
87
|
+
assert.equal(result, null, "should not return arbitrary milestone when multiple sessions exist");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("getDiscussionMilestoneId() without basePath returns the milestone when only one session", () => {
|
|
91
|
+
setPendingAutoStart("/proj/a", { basePath: "/proj/a", milestoneId: "M001" });
|
|
92
|
+
|
|
93
|
+
// With only one session, backward compat — return it
|
|
94
|
+
const result = getDiscussionMilestoneId();
|
|
95
|
+
assert.equal(result, "M001", "should return the only active milestone for backward compat");
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -6,6 +6,7 @@ import { tmpdir } from "node:os";
|
|
|
6
6
|
import {
|
|
7
7
|
buildHealthLines,
|
|
8
8
|
detectHealthWidgetProjectState,
|
|
9
|
+
formatRelativeTime,
|
|
9
10
|
type HealthWidgetData,
|
|
10
11
|
} from "../health-widget-core.ts";
|
|
11
12
|
|
|
@@ -34,6 +35,8 @@ function activeData(overrides: Partial<HealthWidgetData> = {}): HealthWidgetData
|
|
|
34
35
|
providerIssue: null,
|
|
35
36
|
environmentErrorCount: 0,
|
|
36
37
|
environmentWarningCount: 0,
|
|
38
|
+
lastCommitEpoch: null,
|
|
39
|
+
lastCommitMessage: null,
|
|
37
40
|
lastRefreshed: Date.now(),
|
|
38
41
|
...overrides,
|
|
39
42
|
};
|
|
@@ -98,6 +101,70 @@ test("buildHealthLines: active state with issues reports issue summary", (t) =>
|
|
|
98
101
|
assert.match(lines[0]!, /Env: 1 error/);
|
|
99
102
|
});
|
|
100
103
|
|
|
104
|
+
// ── Last commit display ──────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
test("buildHealthLines: shows last commit with relative time and message", (t) => {
|
|
107
|
+
const epoch = Math.floor(Date.now() / 1000) - 300; // 5 minutes ago
|
|
108
|
+
const lines = buildHealthLines(activeData({
|
|
109
|
+
lastCommitEpoch: epoch,
|
|
110
|
+
lastCommitMessage: "feat(widget): add health display",
|
|
111
|
+
}));
|
|
112
|
+
assert.equal(lines.length, 1);
|
|
113
|
+
assert.match(lines[0]!, /Last commit: 5m ago/);
|
|
114
|
+
assert.match(lines[0]!, /feat\(widget\): add health display/);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("buildHealthLines: truncates long commit messages", (t) => {
|
|
118
|
+
const epoch = Math.floor(Date.now() / 1000) - 60;
|
|
119
|
+
const longMsg = "a".repeat(80);
|
|
120
|
+
const lines = buildHealthLines(activeData({
|
|
121
|
+
lastCommitEpoch: epoch,
|
|
122
|
+
lastCommitMessage: longMsg,
|
|
123
|
+
}));
|
|
124
|
+
assert.equal(lines.length, 1);
|
|
125
|
+
assert.match(lines[0]!, /a{49}…/);
|
|
126
|
+
assert.ok(!lines[0]!.includes("a".repeat(51)), "message is truncated");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("buildHealthLines: no last commit section when epoch is null", (t) => {
|
|
130
|
+
const lines = buildHealthLines(activeData({ lastCommitEpoch: null }));
|
|
131
|
+
assert.equal(lines.length, 1);
|
|
132
|
+
assert.ok(!lines[0]!.includes("Last commit"), "no last commit when null");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("buildHealthLines: last commit without message shows only time", (t) => {
|
|
136
|
+
const epoch = Math.floor(Date.now() / 1000) - 3600; // 1 hour ago
|
|
137
|
+
const lines = buildHealthLines(activeData({
|
|
138
|
+
lastCommitEpoch: epoch,
|
|
139
|
+
lastCommitMessage: null,
|
|
140
|
+
}));
|
|
141
|
+
assert.equal(lines.length, 1);
|
|
142
|
+
assert.match(lines[0]!, /Last commit: 1h ago/);
|
|
143
|
+
assert.ok(!lines[0]!.includes(" — "), "no dash separator when no message");
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// ── formatRelativeTime ───────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
test("formatRelativeTime: just now for <60s", () => {
|
|
149
|
+
const epoch = Math.floor(Date.now() / 1000) - 30;
|
|
150
|
+
assert.equal(formatRelativeTime(epoch), "just now");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("formatRelativeTime: minutes", () => {
|
|
154
|
+
const epoch = Math.floor(Date.now() / 1000) - 300;
|
|
155
|
+
assert.equal(formatRelativeTime(epoch), "5m ago");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("formatRelativeTime: hours", () => {
|
|
159
|
+
const epoch = Math.floor(Date.now() / 1000) - 7200;
|
|
160
|
+
assert.equal(formatRelativeTime(epoch), "2h ago");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("formatRelativeTime: days", () => {
|
|
164
|
+
const epoch = Math.floor(Date.now() / 1000) - 172800;
|
|
165
|
+
assert.equal(formatRelativeTime(epoch), "2d ago");
|
|
166
|
+
});
|
|
167
|
+
|
|
101
168
|
test("detectHealthWidgetProjectState: metrics file alone does not imply project", (t) => {
|
|
102
169
|
const dir = makeTempDir("metrics-only");
|
|
103
170
|
t.after(() => { cleanup(dir); });
|