gsd-pi 2.76.0-dev.fe143342a → 2.77.0-dev.1d17f366c
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 +17 -35
- package/dist/claude-cli-check.js +32 -3
- package/dist/cli-web-branch.d.ts +1 -0
- package/dist/cli-web-branch.js +3 -0
- package/dist/cli.js +38 -2
- package/dist/extension-discovery.d.ts +6 -0
- package/dist/extension-discovery.js +37 -0
- package/dist/extension-registry.d.ts +3 -0
- package/dist/extension-sort.d.ts +18 -0
- package/dist/extension-sort.js +114 -0
- package/dist/extension-validator.d.ts +47 -0
- package/dist/extension-validator.js +127 -0
- package/dist/loader.js +35 -7
- package/dist/onboarding.js +45 -0
- package/dist/provider-migrations.d.ts +18 -0
- package/dist/provider-migrations.js +14 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +78 -59
- package/dist/resources/extensions/cmux/index.js +20 -0
- package/dist/resources/extensions/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
- package/dist/resources/extensions/google-search/index.js +3 -375
- package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
- package/dist/resources/extensions/gsd/auto/loop.js +90 -2
- package/dist/resources/extensions/gsd/auto/phases.js +95 -21
- package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +48 -4
- package/dist/resources/extensions/gsd/auto/session.js +18 -1
- package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +115 -17
- package/dist/resources/extensions/gsd/auto-loop.js +1 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +1 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +90 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +46 -1
- package/dist/resources/extensions/gsd/auto-start.js +45 -39
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +109 -61
- package/dist/resources/extensions/gsd/auto.js +97 -31
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +27 -1
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +11 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
- package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
- package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
- package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
- package/dist/resources/extensions/gsd/file-lock.js +49 -9
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +2 -0
- package/dist/resources/extensions/gsd/gsd-db.js +90 -30
- package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
- package/dist/resources/extensions/gsd/guided-flow.js +212 -9
- package/dist/resources/extensions/gsd/health-widget.js +4 -1
- package/dist/resources/extensions/gsd/journal.js +17 -2
- package/dist/resources/extensions/gsd/key-manager.js +22 -0
- package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
- package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
- package/dist/resources/extensions/gsd/model-router.js +36 -3
- package/dist/resources/extensions/gsd/notifications.js +30 -16
- package/dist/resources/extensions/gsd/pre-execution-checks.js +31 -6
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -0
- package/dist/resources/extensions/gsd/reports.js +5 -4
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +12 -4
- package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +25 -25
- package/dist/resources/extensions/gsd/token-counter.js +22 -5
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
- package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
- package/dist/resources/extensions/gsd/uok/audit.js +18 -2
- package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +30 -7
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
- package/dist/resources/extensions/mcp-client/auth.js +10 -1
- package/dist/resources/extensions/mcp-client/index.js +118 -9
- package/dist/resources/extensions/shared/cmux-events.js +12 -0
- package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
- package/dist/resources/skills/create-skill/SKILL.md +2 -2
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
- package/dist/resources/skills/write-docs/SKILL.md +2 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- 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.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/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 +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
- package/dist/welcome-screen.js +6 -1
- package/dist/wizard.js +2 -0
- package/package.json +16 -14
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/README.md +3 -3
- package/packages/mcp-server/dist/env-writer.d.ts +1 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
- package/packages/mcp-server/dist/env-writer.js +74 -6
- package/packages/mcp-server/dist/env-writer.js.map +1 -1
- package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
- package/packages/mcp-server/dist/remote-questions.js +732 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +7 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +95 -10
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.d.ts +14 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +49 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +9 -3
- package/packages/mcp-server/src/env-writer.test.ts +79 -1
- package/packages/mcp-server/src/env-writer.ts +76 -6
- package/packages/mcp-server/src/mcp-server.test.ts +67 -0
- package/packages/mcp-server/src/readers/readers.test.ts +5 -1
- package/packages/mcp-server/src/remote-questions.test.ts +294 -0
- package/packages/mcp-server/src/remote-questions.ts +916 -0
- package/packages/mcp-server/src/server.ts +118 -16
- package/packages/mcp-server/src/session-manager.ts +43 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +44 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +6 -1
- package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +6 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +220 -15
- package/packages/pi-ai/dist/models/custom.d.ts +38 -0
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/custom.js +41 -0
- package/packages/pi-ai/dist/models/custom.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.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 +27 -4
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +8 -3
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +16 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/package.json +6 -1
- package/packages/pi-ai/src/models/custom.ts +42 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
- package/packages/pi-ai/src/providers/anthropic.ts +9 -3
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
- package/packages/pi-ai/src/providers/simple-options.ts +17 -1
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -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 +7 -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 +25 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
- package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
- package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
- package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +3 -2
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +24 -8
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +14 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +11 -0
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +14 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +21 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +3 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
- package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +6 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
- package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
- package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
- package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +24 -11
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +15 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +13 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -2
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +16 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
- package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +30 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +1 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +3 -3
- package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +14 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +12 -5
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +21 -0
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +20 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +6 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -5
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +27 -0
- package/packages/pi-tui/src/stdin-buffer.ts +26 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +6 -1
- package/pkg/package.json +1 -1
- package/scripts/install.js +512 -0
- package/scripts/lib/workspace-manifest.cjs +86 -0
- package/scripts/link-workspace-packages.cjs +5 -17
- package/scripts/postinstall.js +9 -178
- package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +91 -63
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +114 -12
- package/src/resources/extensions/cmux/index.ts +35 -10
- package/src/resources/extensions/github-sync/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/templates.test.ts +59 -0
- package/src/resources/extensions/google-search/extension-manifest.json +5 -4
- package/src/resources/extensions/google-search/index.ts +9 -470
- package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -1
- package/src/resources/extensions/gsd/auto/loop.ts +104 -2
- package/src/resources/extensions/gsd/auto/phases.ts +123 -21
- package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +56 -4
- package/src/resources/extensions/gsd/auto/session.ts +28 -1
- package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
- package/src/resources/extensions/gsd/auto/types.ts +1 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +117 -16
- package/src/resources/extensions/gsd/auto-loop.ts +1 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +1 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +92 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +40 -1
- package/src/resources/extensions/gsd/auto-start.ts +48 -52
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +122 -68
- package/src/resources/extensions/gsd/auto.ts +105 -35
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -1
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +11 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +13 -9
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
- package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
- package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
- package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
- package/src/resources/extensions/gsd/file-lock.ts +84 -11
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +2 -1
- package/src/resources/extensions/gsd/gsd-db.ts +92 -32
- package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
- package/src/resources/extensions/gsd/guided-flow.ts +259 -10
- package/src/resources/extensions/gsd/health-widget.ts +3 -1
- package/src/resources/extensions/gsd/journal.ts +29 -3
- package/src/resources/extensions/gsd/key-manager.ts +22 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/model-router.ts +42 -1
- package/src/resources/extensions/gsd/notifications.ts +27 -15
- package/src/resources/extensions/gsd/pre-execution-checks.ts +33 -7
- package/src/resources/extensions/gsd/preferences-types.ts +8 -0
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -0
- package/src/resources/extensions/gsd/reports.ts +5 -4
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +16 -3
- package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +35 -30
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +238 -4
- package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +161 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +1 -2
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
- package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +296 -1
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +337 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +39 -25
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +42 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +138 -5
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
- package/src/resources/extensions/gsd/token-counter.ts +22 -5
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
- package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
- package/src/resources/extensions/gsd/uok/audit.ts +20 -2
- package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +39 -8
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +23 -3
- package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
- package/src/resources/extensions/mcp-client/auth.ts +12 -1
- package/src/resources/extensions/mcp-client/index.ts +129 -10
- package/src/resources/extensions/shared/cmux-events.ts +59 -0
- package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
- package/src/resources/skills/create-skill/SKILL.md +2 -2
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
- package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
- package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
- package/src/resources/skills/write-docs/SKILL.md +2 -1
- package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
- /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_ssgManifest.js +0 -0
|
@@ -13,7 +13,7 @@ import { buildCompleteMilestonePrompt, buildValidateMilestonePrompt } from "../a
|
|
|
13
13
|
import type { GSDState } from "../types.ts";
|
|
14
14
|
import { clearPathCache } from "../paths.ts";
|
|
15
15
|
import { clearParseCache } from "../files.ts";
|
|
16
|
-
import { closeDatabase, insertMilestone, insertSlice, openDatabase } from "../gsd-db.ts";
|
|
16
|
+
import { closeDatabase, insertMilestone, insertSlice, openDatabase, getMilestone } from "../gsd-db.ts";
|
|
17
17
|
|
|
18
18
|
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
19
19
|
|
|
@@ -41,6 +41,12 @@ function writeRoadmap(base: string, mid: string, content: string): void {
|
|
|
41
41
|
writeFileSync(join(dir, `${mid}-ROADMAP.md`), content);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
function writeContext(base: string, mid: string, content = "# M001 Context\n\nValidated context."): void {
|
|
45
|
+
const dir = join(base, ".gsd", "milestones", mid);
|
|
46
|
+
mkdirSync(dir, { recursive: true });
|
|
47
|
+
writeFileSync(join(dir, `${mid}-CONTEXT.md`), content);
|
|
48
|
+
}
|
|
49
|
+
|
|
44
50
|
function writeMilestoneSummary(base: string, mid: string, content: string): void {
|
|
45
51
|
const dir = join(base, ".gsd", "milestones", mid);
|
|
46
52
|
mkdirSync(dir, { recursive: true });
|
|
@@ -257,8 +263,8 @@ Test
|
|
|
257
263
|
`);
|
|
258
264
|
openTestDb(base);
|
|
259
265
|
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
260
|
-
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: []
|
|
261
|
-
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: []
|
|
266
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: [] });
|
|
267
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: [] });
|
|
262
268
|
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDelivered.");
|
|
263
269
|
|
|
264
270
|
const prompt = await buildCompleteMilestonePrompt("M001", "Test Milestone", base);
|
|
@@ -296,8 +302,8 @@ Test
|
|
|
296
302
|
`);
|
|
297
303
|
openTestDb(base);
|
|
298
304
|
insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
|
|
299
|
-
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: []
|
|
300
|
-
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: []
|
|
305
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "First slice", status: "complete", depends: [] });
|
|
306
|
+
insertSlice({ id: "S02", milestoneId: "M001", title: "Skipped slice", status: "skipped", depends: [] });
|
|
301
307
|
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDelivered.");
|
|
302
308
|
writeSliceAssessment(base, "M001", "S01", "---\nverdict: PASS\n---\n# Assessment\nEvidence captured.");
|
|
303
309
|
|
|
@@ -328,6 +334,7 @@ test("dispatch rule matches validating-milestone phase", async () => {
|
|
|
328
334
|
const base = makeTmpBase();
|
|
329
335
|
try {
|
|
330
336
|
// Set up minimal milestone structure for the prompt builder
|
|
337
|
+
writeContext(base, "M001");
|
|
331
338
|
writeRoadmap(base, "M001", ALL_DONE_ROADMAP);
|
|
332
339
|
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDone."); // Guard requires slice summaries (#1368)
|
|
333
340
|
|
|
@@ -364,6 +371,7 @@ test("dispatch rule skips when skip_milestone_validation preference is set", asy
|
|
|
364
371
|
|
|
365
372
|
const base = makeTmpBase();
|
|
366
373
|
try {
|
|
374
|
+
writeContext(base, "M001");
|
|
367
375
|
writeRoadmap(base, "M001", ALL_DONE_ROADMAP);
|
|
368
376
|
writeSliceSummary(base, "M001", "S01", "# S01 Summary\nDone."); // Guard requires slice summaries (#1368)
|
|
369
377
|
|
|
@@ -385,6 +393,131 @@ test("dispatch rule skips when skip_milestone_validation preference is set", asy
|
|
|
385
393
|
}
|
|
386
394
|
});
|
|
387
395
|
|
|
396
|
+
test("dispatch rule fails closed for failure-path SUMMARY when DB milestone is not complete (#4658)", async () => {
|
|
397
|
+
const state: GSDState = {
|
|
398
|
+
activeMilestone: { id: "M001", title: "Test" },
|
|
399
|
+
activeSlice: null,
|
|
400
|
+
activeTask: null,
|
|
401
|
+
phase: "completing-milestone",
|
|
402
|
+
recentDecisions: [],
|
|
403
|
+
blockers: [],
|
|
404
|
+
nextAction: "Complete milestone M001.",
|
|
405
|
+
registry: [{ id: "M001", title: "Test", status: "active" }],
|
|
406
|
+
progress: { milestones: { done: 0, total: 1 } },
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
const base = makeTmpBase();
|
|
410
|
+
try {
|
|
411
|
+
openTestDb(base);
|
|
412
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
413
|
+
writeContext(base, "M001");
|
|
414
|
+
writeMilestoneSummary(base, "M001", "# Milestone Summary\nverification FAILED — not complete.");
|
|
415
|
+
|
|
416
|
+
const ctx: DispatchContext = {
|
|
417
|
+
basePath: base,
|
|
418
|
+
mid: "M001",
|
|
419
|
+
midTitle: "Test",
|
|
420
|
+
state,
|
|
421
|
+
prefs: undefined,
|
|
422
|
+
};
|
|
423
|
+
const result = await resolveDispatch(ctx);
|
|
424
|
+
assert.equal(result.action, "stop");
|
|
425
|
+
if (result.action === "stop") {
|
|
426
|
+
assert.equal(result.level, "warning");
|
|
427
|
+
assert.match(result.reason, /failure-path SUMMARY/i);
|
|
428
|
+
}
|
|
429
|
+
} finally {
|
|
430
|
+
cleanup(base);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
test("dispatch rule reconciles DB for successful stale SUMMARY (#4658)", async () => {
|
|
435
|
+
const state: GSDState = {
|
|
436
|
+
activeMilestone: { id: "M001", title: "Test" },
|
|
437
|
+
activeSlice: null,
|
|
438
|
+
activeTask: null,
|
|
439
|
+
phase: "completing-milestone",
|
|
440
|
+
recentDecisions: [],
|
|
441
|
+
blockers: [],
|
|
442
|
+
nextAction: "Complete milestone M001.",
|
|
443
|
+
registry: [{ id: "M001", title: "Test", status: "active" }],
|
|
444
|
+
progress: { milestones: { done: 0, total: 1 } },
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
const base = makeTmpBase();
|
|
448
|
+
try {
|
|
449
|
+
openTestDb(base);
|
|
450
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
451
|
+
writeContext(base, "M001");
|
|
452
|
+
writeMilestoneSummary(
|
|
453
|
+
base,
|
|
454
|
+
"M001",
|
|
455
|
+
[
|
|
456
|
+
"---",
|
|
457
|
+
"id: M001",
|
|
458
|
+
"status: complete",
|
|
459
|
+
"---",
|
|
460
|
+
"",
|
|
461
|
+
"# M001: Test",
|
|
462
|
+
"",
|
|
463
|
+
"**Complete.**",
|
|
464
|
+
].join("\n"),
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
const ctx: DispatchContext = {
|
|
468
|
+
basePath: base,
|
|
469
|
+
mid: "M001",
|
|
470
|
+
midTitle: "Test",
|
|
471
|
+
state,
|
|
472
|
+
prefs: undefined,
|
|
473
|
+
};
|
|
474
|
+
const result = await resolveDispatch(ctx);
|
|
475
|
+
assert.equal(result.action, "skip");
|
|
476
|
+
const milestone = getMilestone("M001");
|
|
477
|
+
assert.equal(milestone?.status, "complete");
|
|
478
|
+
} finally {
|
|
479
|
+
cleanup(base);
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test("dispatch rule fails closed for ambiguous stale SUMMARY (#4658)", async () => {
|
|
484
|
+
const state: GSDState = {
|
|
485
|
+
activeMilestone: { id: "M001", title: "Test" },
|
|
486
|
+
activeSlice: null,
|
|
487
|
+
activeTask: null,
|
|
488
|
+
phase: "completing-milestone",
|
|
489
|
+
recentDecisions: [],
|
|
490
|
+
blockers: [],
|
|
491
|
+
nextAction: "Complete milestone M001.",
|
|
492
|
+
registry: [{ id: "M001", title: "Test", status: "active" }],
|
|
493
|
+
progress: { milestones: { done: 0, total: 1 } },
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
const base = makeTmpBase();
|
|
497
|
+
try {
|
|
498
|
+
openTestDb(base);
|
|
499
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
500
|
+
writeContext(base, "M001");
|
|
501
|
+
writeMilestoneSummary(base, "M001", "# M001 Summary\nSome notes without completion metadata.");
|
|
502
|
+
|
|
503
|
+
const ctx: DispatchContext = {
|
|
504
|
+
basePath: base,
|
|
505
|
+
mid: "M001",
|
|
506
|
+
midTitle: "Test",
|
|
507
|
+
state,
|
|
508
|
+
prefs: undefined,
|
|
509
|
+
};
|
|
510
|
+
const result = await resolveDispatch(ctx);
|
|
511
|
+
assert.equal(result.action, "stop");
|
|
512
|
+
if (result.action === "stop") {
|
|
513
|
+
assert.equal(result.level, "warning");
|
|
514
|
+
assert.match(result.reason, /ambiguous SUMMARY/i);
|
|
515
|
+
}
|
|
516
|
+
} finally {
|
|
517
|
+
cleanup(base);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
388
521
|
// ─── Artifact resolution & verification ───────────────────────────────────
|
|
389
522
|
|
|
390
523
|
test("resolveExpectedArtifactPath returns VALIDATION path for validate-milestone", () => {
|
|
@@ -180,6 +180,11 @@ test("detectWorkflowMcpLaunchConfig resolves the bundled server relative to the
|
|
|
180
180
|
test("workflow MCP launch config reaches mutation tools over stdio", async () => {
|
|
181
181
|
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-transport-"));
|
|
182
182
|
mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
|
|
183
|
+
// Isolate the spawned MCP server from the developer's real ~/.gsd so it
|
|
184
|
+
// can't pick up a configured Discord/Slack/Telegram channel from global
|
|
185
|
+
// PREFERENCES.md and route ask_user_questions through a remote adapter
|
|
186
|
+
// instead of MCP elicitation.
|
|
187
|
+
const isolatedGsdHome = mkdtempSync(join(tmpdir(), "gsd-workflow-home-"));
|
|
183
188
|
|
|
184
189
|
const launch = detectWorkflowMcpLaunchConfig(projectRoot, {});
|
|
185
190
|
assert.ok(launch, "expected a workflow MCP launch config");
|
|
@@ -219,7 +224,14 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
|
|
|
219
224
|
const transport = new StdioClientTransport({
|
|
220
225
|
command: launch.command,
|
|
221
226
|
args: launch.args,
|
|
222
|
-
env: {
|
|
227
|
+
env: {
|
|
228
|
+
...process.env,
|
|
229
|
+
...launch.env,
|
|
230
|
+
GSD_HOME: isolatedGsdHome,
|
|
231
|
+
DISCORD_BOT_TOKEN: "",
|
|
232
|
+
SLACK_BOT_TOKEN: "",
|
|
233
|
+
TELEGRAM_BOT_TOKEN: "",
|
|
234
|
+
} as Record<string, string>,
|
|
223
235
|
cwd: launch.cwd,
|
|
224
236
|
stderr: "pipe",
|
|
225
237
|
});
|
|
@@ -345,12 +357,14 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
|
|
|
345
357
|
} finally {
|
|
346
358
|
await client.close().catch(() => {});
|
|
347
359
|
rmSync(projectRoot, { recursive: true, force: true });
|
|
360
|
+
rmSync(isolatedGsdHome, { recursive: true, force: true });
|
|
348
361
|
}
|
|
349
362
|
});
|
|
350
363
|
|
|
351
364
|
test("workflow MCP ask_user_questions uses stdio elicitation round-trip", async () => {
|
|
352
365
|
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-workflow-elicit-"));
|
|
353
366
|
mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
|
|
367
|
+
const isolatedGsdHome = mkdtempSync(join(tmpdir(), "gsd-workflow-home-"));
|
|
354
368
|
|
|
355
369
|
const launch = detectWorkflowMcpLaunchConfig(projectRoot, {});
|
|
356
370
|
assert.ok(launch, "expected a workflow MCP launch config");
|
|
@@ -381,7 +395,14 @@ test("workflow MCP ask_user_questions uses stdio elicitation round-trip", async
|
|
|
381
395
|
const transport = new StdioClientTransport({
|
|
382
396
|
command: launch.command,
|
|
383
397
|
args: launch.args,
|
|
384
|
-
env: {
|
|
398
|
+
env: {
|
|
399
|
+
...process.env,
|
|
400
|
+
...launch.env,
|
|
401
|
+
GSD_HOME: isolatedGsdHome,
|
|
402
|
+
DISCORD_BOT_TOKEN: "",
|
|
403
|
+
SLACK_BOT_TOKEN: "",
|
|
404
|
+
TELEGRAM_BOT_TOKEN: "",
|
|
405
|
+
} as Record<string, string>,
|
|
385
406
|
cwd: launch.cwd,
|
|
386
407
|
stderr: "pipe",
|
|
387
408
|
});
|
|
@@ -432,6 +453,8 @@ test("workflow MCP ask_user_questions uses stdio elicitation round-trip", async
|
|
|
432
453
|
);
|
|
433
454
|
} finally {
|
|
434
455
|
await client.close();
|
|
456
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
457
|
+
rmSync(isolatedGsdHome, { recursive: true, force: true });
|
|
435
458
|
}
|
|
436
459
|
});
|
|
437
460
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { mkdirSync, rmSync, readFileSync, existsSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { mkdirSync, rmSync, readFileSync, existsSync, writeFileSync, unlinkSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
_getAdapter,
|
|
12
12
|
insertGateRow,
|
|
13
13
|
} from "../gsd-db.ts";
|
|
14
|
-
import { markDepthVerified, clearDiscussionFlowState } from "../bootstrap/write-gate.ts";
|
|
14
|
+
import { markDepthVerified, clearDiscussionFlowState, loadWriteGateSnapshot } from "../bootstrap/write-gate.ts";
|
|
15
15
|
import {
|
|
16
16
|
executeCompleteMilestone,
|
|
17
17
|
executePlanMilestone,
|
|
@@ -742,3 +742,66 @@ test("executeSummarySave leaves sibling CONTEXT-DRAFT intact for non-CONTEXT art
|
|
|
742
742
|
cleanup(base);
|
|
743
743
|
}
|
|
744
744
|
});
|
|
745
|
+
|
|
746
|
+
test("executeSummarySave CONTEXT HARD BLOCK clears after write-gate state file is deleted (#4343)", async () => {
|
|
747
|
+
const base = makeTmpBase();
|
|
748
|
+
const originalEnv = process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
749
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = "1";
|
|
750
|
+
try {
|
|
751
|
+
openTestDb(base);
|
|
752
|
+
clearDiscussionFlowState();
|
|
753
|
+
|
|
754
|
+
// First call: CONTEXT artifact without depth verification → HARD BLOCK
|
|
755
|
+
const blocked = await inProjectDir(base, () => executeSummarySave({
|
|
756
|
+
milestone_id: "M001",
|
|
757
|
+
artifact_type: "CONTEXT",
|
|
758
|
+
content: "# Context\n\ncontent",
|
|
759
|
+
}, base));
|
|
760
|
+
assert.equal(blocked.isError, true, "should be blocked without depth verification");
|
|
761
|
+
assert.match(
|
|
762
|
+
blocked.content[0].text,
|
|
763
|
+
/HARD BLOCK/,
|
|
764
|
+
"blocked result should mention HARD BLOCK",
|
|
765
|
+
);
|
|
766
|
+
|
|
767
|
+
// Verify the state file was written (persist mode is active)
|
|
768
|
+
const stateFilePath = join(base, ".gsd", "runtime", "write-gate-state.json");
|
|
769
|
+
// The state file may or may not exist at this point (block doesn't write state).
|
|
770
|
+
// Write a fake state file simulating stale persisted block state.
|
|
771
|
+
mkdirSync(join(base, ".gsd", "runtime"), { recursive: true });
|
|
772
|
+
writeFileSync(stateFilePath, JSON.stringify({
|
|
773
|
+
verifiedDepthMilestones: [],
|
|
774
|
+
activeQueuePhase: false,
|
|
775
|
+
pendingGateId: "depth_verification_M001",
|
|
776
|
+
}));
|
|
777
|
+
|
|
778
|
+
// User deletes the state file to reset the block
|
|
779
|
+
unlinkSync(stateFilePath);
|
|
780
|
+
assert.ok(!existsSync(stateFilePath), "state file deleted");
|
|
781
|
+
|
|
782
|
+
// The snapshot loaded after deletion should be clean (no pending gate, no block)
|
|
783
|
+
const snapshot = loadWriteGateSnapshot(base);
|
|
784
|
+
assert.equal(snapshot.pendingGateId, null, "pendingGateId should be null after file deletion");
|
|
785
|
+
assert.deepEqual(snapshot.verifiedDepthMilestones, [], "verifiedDepthMilestones should be empty after file deletion");
|
|
786
|
+
|
|
787
|
+
// Depth-verify and re-attempt: should succeed after deletion clears stale state
|
|
788
|
+
markDepthVerified("M001", base);
|
|
789
|
+
|
|
790
|
+
const unblocked = await inProjectDir(base, () => executeSummarySave({
|
|
791
|
+
milestone_id: "M001",
|
|
792
|
+
artifact_type: "CONTEXT",
|
|
793
|
+
content: "# Context\n\nfinal content",
|
|
794
|
+
}, base));
|
|
795
|
+
assert.equal(unblocked.isError, undefined, "should not be blocked after depth verification");
|
|
796
|
+
assert.equal(unblocked.details.operation, "save_summary");
|
|
797
|
+
} finally {
|
|
798
|
+
if (originalEnv === undefined) {
|
|
799
|
+
delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
800
|
+
} else {
|
|
801
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = originalEnv;
|
|
802
|
+
}
|
|
803
|
+
clearDiscussionFlowState();
|
|
804
|
+
closeDatabase();
|
|
805
|
+
cleanup(base);
|
|
806
|
+
}
|
|
807
|
+
});
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
insertDecision,
|
|
11
11
|
insertRequirement,
|
|
12
12
|
insertArtifact,
|
|
13
|
+
insertMilestone,
|
|
14
|
+
getMilestone,
|
|
13
15
|
getDecisionById,
|
|
14
16
|
getRequirementById,
|
|
15
17
|
_getAdapter,
|
|
@@ -442,4 +444,37 @@ console.log('\n=== worktree-db: reconcileWorktreeDb ===');
|
|
|
442
444
|
cleanup(mainDir, wtDir);
|
|
443
445
|
}
|
|
444
446
|
|
|
447
|
+
// Test: reconcileWorktreeDb must NOT downgrade milestone status complete→active (#4372)
|
|
448
|
+
{
|
|
449
|
+
const mainDir = tempDir();
|
|
450
|
+
const wtDir = tempDir();
|
|
451
|
+
const mainDb = path.join(mainDir, 'gsd.db');
|
|
452
|
+
const wtDb = path.join(wtDir, 'gsd.db');
|
|
453
|
+
|
|
454
|
+
// Seed main with a milestone already marked complete
|
|
455
|
+
seedMainDb(mainDb);
|
|
456
|
+
const mainAdapter = _getAdapter()!;
|
|
457
|
+
insertMilestone({ id: 'M-COMP', title: 'Completed Milestone', status: 'complete' });
|
|
458
|
+
// Manually mark completed_at so it's a realistic complete record
|
|
459
|
+
mainAdapter.prepare(`UPDATE milestones SET completed_at = '2025-06-01T00:00:00.000Z' WHERE id = 'M-COMP'`).run();
|
|
460
|
+
closeDatabase();
|
|
461
|
+
|
|
462
|
+
// Copy to worktree — the worktree has the milestone as 'active' (stale / older snapshot)
|
|
463
|
+
copyWorktreeDb(mainDb, wtDb);
|
|
464
|
+
openDatabase(wtDb);
|
|
465
|
+
const wtAdapter = _getAdapter()!;
|
|
466
|
+
wtAdapter.prepare(`UPDATE milestones SET status = 'active', completed_at = NULL WHERE id = 'M-COMP'`).run();
|
|
467
|
+
closeDatabase();
|
|
468
|
+
|
|
469
|
+
// Reconcile: main should win and keep 'complete'
|
|
470
|
+
openDatabase(mainDb);
|
|
471
|
+
reconcileWorktreeDb(mainDb, wtDb);
|
|
472
|
+
|
|
473
|
+
const m = getMilestone('M-COMP');
|
|
474
|
+
assert.ok(m !== null, 'milestone M-COMP still exists after reconcile');
|
|
475
|
+
assert.strictEqual(m!.status, 'complete', 'complete milestone must not be downgraded to active by stale worktree');
|
|
476
|
+
|
|
477
|
+
cleanup(mainDir, wtDir);
|
|
478
|
+
}
|
|
479
|
+
|
|
445
480
|
// ─── Final Report ──────────────────────────────────────────────────────────
|
|
@@ -190,7 +190,12 @@ describe("worktree journal events", () => {
|
|
|
190
190
|
});
|
|
191
191
|
const resolver = new WorktreeResolver(s, deps);
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
// Since #4380, mergeAndExit re-throws all errors after emitting the journal
|
|
194
|
+
// event and restoring state — callers must handle the throw.
|
|
195
|
+
assert.throws(
|
|
196
|
+
() => resolver.mergeAndExit("M001", makeNotifyCtx()),
|
|
197
|
+
/conflict in main/,
|
|
198
|
+
);
|
|
194
199
|
|
|
195
200
|
const entries = readJournalEntries(tmp);
|
|
196
201
|
const failed = entries.find(e => e.eventType === "worktree-merge-failed");
|
|
@@ -313,6 +313,43 @@ test("enterMilestone uses originalBasePath as base for worktree ops", () => {
|
|
|
313
313
|
assert.equal(createdFrom, "/project"); // uses originalBasePath, not current basePath
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
+
test("enterMilestone does not create double-nested worktree when originalBasePath is empty and basePath is a worktree path", () => {
|
|
317
|
+
// Regression test for #3729: when s.originalBasePath is "" (falsy) and
|
|
318
|
+
// s.basePath is already a worktree path, the expression
|
|
319
|
+
// `this.s.originalBasePath || this.s.basePath` evaluates to the worktree
|
|
320
|
+
// path. Passing that to createAutoWorktree produces a doubly-nested path
|
|
321
|
+
// like /project/.gsd/worktrees/M001/.gsd/worktrees/M002.
|
|
322
|
+
const wtPath = "/project/.gsd/worktrees/M001";
|
|
323
|
+
const s = makeSession({
|
|
324
|
+
basePath: wtPath,
|
|
325
|
+
originalBasePath: "/project", // will be overwritten below to simulate the bug
|
|
326
|
+
});
|
|
327
|
+
// Simulate the real bug: originalBasePath is "" (falsy) as it is when AutoSession
|
|
328
|
+
// is constructed fresh or reset() is called without auto-start re-setting it.
|
|
329
|
+
s.originalBasePath = "";
|
|
330
|
+
|
|
331
|
+
let createdFromPath = "";
|
|
332
|
+
const deps = makeDeps({
|
|
333
|
+
getAutoWorktreePath: () => null,
|
|
334
|
+
createAutoWorktree: (basePath: string, _mid: string) => {
|
|
335
|
+
createdFromPath = basePath;
|
|
336
|
+
return `/project/.gsd/worktrees/M002`;
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
const ctx = makeNotifyCtx();
|
|
340
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
341
|
+
|
|
342
|
+
resolver.enterMilestone("M002", ctx);
|
|
343
|
+
|
|
344
|
+
// The path passed to createAutoWorktree must be the project root, NOT the
|
|
345
|
+
// worktree path. If it equals wtPath the worktree would be created at
|
|
346
|
+
// /project/.gsd/worktrees/M001/.gsd/worktrees/M002 (double-nesting).
|
|
347
|
+
assert.ok(
|
|
348
|
+
!createdFromPath.includes("/.gsd/worktrees/"),
|
|
349
|
+
`createAutoWorktree must be called with project root, got: "${createdFromPath}"`,
|
|
350
|
+
);
|
|
351
|
+
});
|
|
352
|
+
|
|
316
353
|
// ─── enterMilestone Tests (branch mode) ──────────────────────────────────────
|
|
317
354
|
|
|
318
355
|
test("enterMilestone in branch mode calls enterBranchModeForMilestone and rebuilds GitService", () => {
|
|
@@ -577,9 +614,11 @@ test("mergeAndExit in worktree mode restores to project root on merge failure",
|
|
|
577
614
|
const ctx = makeNotifyCtx();
|
|
578
615
|
const resolver = new WorktreeResolver(s, deps);
|
|
579
616
|
|
|
580
|
-
|
|
617
|
+
// Error propagates (#4380) — callers handle recovery. restoreToProjectRoot()
|
|
618
|
+
// still runs before re-throw so state is consistent for the caller.
|
|
619
|
+
assert.throws(() => resolver.mergeAndExit("M001", ctx), /conflict in main/);
|
|
581
620
|
|
|
582
|
-
assert.equal(s.basePath, "/project"); // error recovery — restored
|
|
621
|
+
assert.equal(s.basePath, "/project"); // error recovery — restored before re-throw
|
|
583
622
|
assert.ok(
|
|
584
623
|
ctx.messages.some(
|
|
585
624
|
(m) => m.level === "warning" && m.msg.includes("conflict in main"),
|
|
@@ -607,7 +646,8 @@ test("mergeAndExit failure message tells user worktree and branch are preserved
|
|
|
607
646
|
const ctx = makeNotifyCtx();
|
|
608
647
|
const resolver = new WorktreeResolver(s, deps);
|
|
609
648
|
|
|
610
|
-
|
|
649
|
+
// Error propagates (#4380) — notification is still emitted before re-throw
|
|
650
|
+
assert.throws(() => resolver.mergeAndExit("M001", ctx), /pathspec 'main' did not match/);
|
|
611
651
|
|
|
612
652
|
const warning = ctx.messages.find((m) => m.level === "warning");
|
|
613
653
|
assert.ok(warning, "a warning message is emitted");
|
|
@@ -643,7 +683,8 @@ test("mergeAndExit failure message references /gsd dispatch complete-milestone,
|
|
|
643
683
|
const ctx = makeNotifyCtx();
|
|
644
684
|
const resolver = new WorktreeResolver(s, deps);
|
|
645
685
|
|
|
646
|
-
|
|
686
|
+
// Error propagates (#4380) — notification is still emitted before re-throw
|
|
687
|
+
assert.throws(() => resolver.mergeAndExit("M001", ctx), /dirty working tree/);
|
|
647
688
|
|
|
648
689
|
const warning = ctx.messages.find((m) => m.level === "warning");
|
|
649
690
|
assert.ok(warning, "a warning message is emitted");
|
|
@@ -709,7 +750,8 @@ test("mergeAndExit in branch mode handles merge failure gracefully", () => {
|
|
|
709
750
|
const ctx = makeNotifyCtx();
|
|
710
751
|
const resolver = new WorktreeResolver(s, deps);
|
|
711
752
|
|
|
712
|
-
|
|
753
|
+
// Error propagates (#4380) — notification is still emitted before re-throw
|
|
754
|
+
assert.throws(() => resolver.mergeAndExit("M001", ctx), /branch merge conflict/);
|
|
713
755
|
|
|
714
756
|
assert.ok(
|
|
715
757
|
ctx.messages.some(
|
|
@@ -1069,3 +1111,34 @@ test("mergeAndExit in none mode remains a no-op when NOT in a worktree (#2625)",
|
|
|
1069
1111
|
assert.equal(findCalls(deps.calls, "mergeMilestoneToMain").length, 0,
|
|
1070
1112
|
"must NOT merge when not in a worktree and mode is none");
|
|
1071
1113
|
});
|
|
1114
|
+
|
|
1115
|
+
// ─── #4380 — Non-MergeConflictError must not be swallowed ────────────────────
|
|
1116
|
+
|
|
1117
|
+
test("mergeAndExit propagates non-MergeConflictError to caller (#4380)", () => {
|
|
1118
|
+
// Regression test: previously the catch block in _mergeWorktreeMode only
|
|
1119
|
+
// re-threw MergeConflictError. Permission errors, filesystem errors, and other
|
|
1120
|
+
// non-conflict failures were swallowed silently, making broken states impossible
|
|
1121
|
+
// to diagnose and preventing callers (phases.ts) from applying their own
|
|
1122
|
+
// error-recovery logic.
|
|
1123
|
+
const permissionError = new Error("EACCES: permission denied, open '/project/.git/SQUASH_MSG'");
|
|
1124
|
+
const s = makeSession({
|
|
1125
|
+
basePath: "/project/.gsd/worktrees/M001",
|
|
1126
|
+
originalBasePath: "/project",
|
|
1127
|
+
});
|
|
1128
|
+
const deps = makeDeps({
|
|
1129
|
+
isInAutoWorktree: () => true,
|
|
1130
|
+
getIsolationMode: () => "worktree",
|
|
1131
|
+
mergeMilestoneToMain: () => {
|
|
1132
|
+
throw permissionError;
|
|
1133
|
+
},
|
|
1134
|
+
});
|
|
1135
|
+
const ctx = makeNotifyCtx();
|
|
1136
|
+
const resolver = new WorktreeResolver(s, deps);
|
|
1137
|
+
|
|
1138
|
+
// The error must propagate — callers need it to apply their own recovery logic
|
|
1139
|
+
assert.throws(
|
|
1140
|
+
() => resolver.mergeAndExit("M001", ctx),
|
|
1141
|
+
(err: unknown) => err === permissionError,
|
|
1142
|
+
"non-MergeConflictError must propagate to the caller, not be swallowed",
|
|
1143
|
+
);
|
|
1144
|
+
});
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
import test from 'node:test';
|
|
13
13
|
import assert from 'node:assert/strict';
|
|
14
|
+
import { mkdirSync, writeFileSync, unlinkSync, existsSync, rmSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { tmpdir } from 'node:os';
|
|
17
|
+
import { randomUUID } from 'node:crypto';
|
|
14
18
|
import {
|
|
15
19
|
isDepthConfirmationAnswer,
|
|
16
20
|
shouldBlockContextWrite,
|
|
@@ -20,8 +24,10 @@ import {
|
|
|
20
24
|
markDepthVerified,
|
|
21
25
|
isMilestoneDepthVerified,
|
|
22
26
|
shouldBlockContextArtifactSave,
|
|
27
|
+
shouldBlockContextArtifactSaveInSnapshot,
|
|
23
28
|
clearDiscussionFlowState,
|
|
24
29
|
resetWriteGateState,
|
|
30
|
+
loadWriteGateSnapshot,
|
|
25
31
|
} from '../bootstrap/write-gate.ts';
|
|
26
32
|
|
|
27
33
|
// ─── Scenario 1: Blocks CONTEXT.md write during discussion without depth verification (absolute path) ──
|
|
@@ -488,3 +494,61 @@ test('write-gate: isDepthConfirmationAnswer falls back to (Recommended) match wi
|
|
|
488
494
|
'should reject non-Recommended via fallback',
|
|
489
495
|
);
|
|
490
496
|
});
|
|
497
|
+
|
|
498
|
+
// ─── Scenario 29: loadWriteGateSnapshot returns clean state when persist file deleted (#4343) ──
|
|
499
|
+
|
|
500
|
+
test('write-gate: loadWriteGateSnapshot returns empty default when persist file is deleted (#4343)', () => {
|
|
501
|
+
const base = join(tmpdir(), `gsd-write-gate-4343-${randomUUID()}`);
|
|
502
|
+
mkdirSync(join(base, '.gsd', 'runtime'), { recursive: true });
|
|
503
|
+
const stateFilePath = join(base, '.gsd', 'runtime', 'write-gate-state.json');
|
|
504
|
+
const originalEnv = process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
505
|
+
|
|
506
|
+
try {
|
|
507
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = '1';
|
|
508
|
+
|
|
509
|
+
// Write a state file with a pending gate and verified milestone
|
|
510
|
+
writeFileSync(stateFilePath, JSON.stringify({
|
|
511
|
+
verifiedDepthMilestones: ['M001'],
|
|
512
|
+
activeQueuePhase: false,
|
|
513
|
+
pendingGateId: 'depth_verification_M001',
|
|
514
|
+
}));
|
|
515
|
+
assert.ok(existsSync(stateFilePath), 'precondition: state file exists');
|
|
516
|
+
|
|
517
|
+
// While file exists, snapshot reflects its contents
|
|
518
|
+
const beforeDeletion = loadWriteGateSnapshot(base);
|
|
519
|
+
assert.strictEqual(beforeDeletion.pendingGateId, 'depth_verification_M001', 'pending gate from file');
|
|
520
|
+
assert.deepEqual(beforeDeletion.verifiedDepthMilestones, ['M001'], 'verified milestones from file');
|
|
521
|
+
|
|
522
|
+
// User deletes the state file to clear the HARD BLOCK
|
|
523
|
+
unlinkSync(stateFilePath);
|
|
524
|
+
assert.ok(!existsSync(stateFilePath), 'state file deleted');
|
|
525
|
+
|
|
526
|
+
// After deletion in persist mode, snapshot should be clean (not stale in-memory)
|
|
527
|
+
const afterDeletion = loadWriteGateSnapshot(base);
|
|
528
|
+
assert.strictEqual(afterDeletion.pendingGateId, null, 'pendingGateId cleared after file deletion');
|
|
529
|
+
assert.deepEqual(afterDeletion.verifiedDepthMilestones, [], 'verifiedDepthMilestones cleared after file deletion');
|
|
530
|
+
assert.strictEqual(afterDeletion.activeQueuePhase, false, 'activeQueuePhase cleared after file deletion');
|
|
531
|
+
|
|
532
|
+
// The CONTEXT artifact block check must also resolve to unblocked after deletion+verification
|
|
533
|
+
// (simulate the re-verify flow users would do: delete → depth verify → save)
|
|
534
|
+
const stillBlocked = shouldBlockContextArtifactSaveInSnapshot(afterDeletion, 'CONTEXT', 'M001', null);
|
|
535
|
+
assert.strictEqual(stillBlocked.block, true, 'still blocked without new depth verification');
|
|
536
|
+
|
|
537
|
+
const verifiedSnapshot = {
|
|
538
|
+
...afterDeletion,
|
|
539
|
+
verifiedDepthMilestones: ['M001'],
|
|
540
|
+
};
|
|
541
|
+
const unblocked = shouldBlockContextArtifactSaveInSnapshot(verifiedSnapshot, 'CONTEXT', 'M001', null);
|
|
542
|
+
assert.strictEqual(unblocked.block, false, 'unblocked after fresh depth verification');
|
|
543
|
+
} finally {
|
|
544
|
+
if (originalEnv === undefined) {
|
|
545
|
+
delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
546
|
+
} else {
|
|
547
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = originalEnv;
|
|
548
|
+
}
|
|
549
|
+
clearDiscussionFlowState();
|
|
550
|
+
try {
|
|
551
|
+
rmSync(base, { recursive: true, force: true });
|
|
552
|
+
} catch { /* swallow */ }
|
|
553
|
+
}
|
|
554
|
+
});
|
|
@@ -22,7 +22,11 @@ async function getEncoder(): Promise<TokenEncoder | null> {
|
|
|
22
22
|
try {
|
|
23
23
|
// @ts-ignore — tiktoken may not have type declarations in extensions tsconfig
|
|
24
24
|
const tiktoken = await import("tiktoken");
|
|
25
|
-
|
|
25
|
+
// Use cl100k_base — the most conservative and broadly compatible BPE encoding.
|
|
26
|
+
// It is shared by GPT-3.5/GPT-4 and gives a safer (larger) estimate than
|
|
27
|
+
// gpt-4o's o200k_base encoding, which produces fewer tokens for the same text
|
|
28
|
+
// and would cause context windows for non-OpenAI providers to be under-counted.
|
|
29
|
+
encoder = tiktoken.get_encoding("cl100k_base") as TokenEncoder;
|
|
26
30
|
return encoder;
|
|
27
31
|
} catch {
|
|
28
32
|
encoderFailed = true;
|
|
@@ -30,20 +34,33 @@ async function getEncoder(): Promise<TokenEncoder | null> {
|
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Count tokens in `text` using tiktoken (cl100k_base) when available.
|
|
39
|
+
*
|
|
40
|
+
* When tiktoken is not loaded, falls back to a provider-aware character-ratio
|
|
41
|
+
* estimate via `estimateTokensForProvider`. Passing `provider` is recommended
|
|
42
|
+
* so the heuristic fallback is as accurate as possible.
|
|
43
|
+
*/
|
|
44
|
+
export async function countTokens(text: string, provider?: TokenProvider): Promise<number> {
|
|
34
45
|
const enc = await getEncoder();
|
|
35
46
|
if (enc) {
|
|
36
47
|
const tokens = enc.encode(text);
|
|
37
48
|
return tokens.length;
|
|
38
49
|
}
|
|
39
|
-
return
|
|
50
|
+
return estimateTokensForProvider(text, provider ?? "unknown");
|
|
40
51
|
}
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Synchronous token count — only accurate after `initTokenCounter()` resolves.
|
|
55
|
+
*
|
|
56
|
+
* Before init, or when tiktoken is unavailable, falls back to a provider-aware
|
|
57
|
+
* character-ratio estimate. Passing `provider` is recommended.
|
|
58
|
+
*/
|
|
59
|
+
export function countTokensSync(text: string, provider?: TokenProvider): number {
|
|
43
60
|
if (encoder) {
|
|
44
61
|
return encoder.encode(text).length;
|
|
45
62
|
}
|
|
46
|
-
return
|
|
63
|
+
return estimateTokensForProvider(text, provider ?? "unknown");
|
|
47
64
|
}
|
|
48
65
|
|
|
49
66
|
export async function initTokenCounter(): Promise<boolean> {
|