gsd-pi 2.65.0-dev.5c8557b → 2.65.0-dev.800ece0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp-server.js +6 -2
- package/dist/resources/extensions/browser-tools/capture.js +20 -1
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
- package/dist/resources/extensions/gsd/auto/finalize-timeout.js +2 -0
- package/dist/resources/extensions/gsd/auto/loop.js +2 -2
- package/dist/resources/extensions/gsd/auto/phases.js +48 -5
- package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto/types.js +2 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +2 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +99 -9
- package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +40 -22
- package/dist/resources/extensions/gsd/auto-start.js +175 -12
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
- package/dist/resources/extensions/gsd/auto.js +21 -15
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -3
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +31 -1
- package/dist/resources/extensions/gsd/commands/context.js +8 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -2
- package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.js +312 -0
- package/dist/resources/extensions/gsd/db-writer.js +13 -3
- package/dist/resources/extensions/gsd/detection.js +1 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
- package/dist/resources/extensions/gsd/doctor.js +2 -1
- package/dist/resources/extensions/gsd/files.js +17 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +47 -4
- package/dist/resources/extensions/gsd/guided-flow.js +220 -29
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/json-persistence.js +5 -2
- package/dist/resources/extensions/gsd/md-importer.js +14 -7
- package/dist/resources/extensions/gsd/notification-overlay.js +1 -1
- package/dist/resources/extensions/gsd/notification-widget.js +2 -1
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +1 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
- package/dist/resources/extensions/gsd/pre-execution-checks.js +26 -5
- package/dist/resources/extensions/gsd/preferences-types.js +3 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +45 -1
- package/dist/resources/extensions/gsd/preferences.js +9 -2
- package/dist/resources/extensions/gsd/preparation.js +1092 -0
- package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
- package/dist/resources/extensions/gsd/prompts/queue.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
- package/dist/resources/extensions/gsd/quick.js +19 -15
- package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
- package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
- package/dist/resources/extensions/gsd/session-lock.js +23 -1
- package/dist/resources/extensions/gsd/state.js +115 -28
- package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -3
- package/dist/resources/extensions/gsd/tools/complete-slice.js +27 -6
- package/dist/resources/extensions/gsd/tools/complete-task.js +31 -7
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
- package/dist/resources/extensions/gsd/triage-resolution.js +33 -16
- package/dist/resources/extensions/gsd/undo.js +3 -2
- package/dist/resources/extensions/gsd/workflow-events.js +1 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +7 -9
- package/dist/resources/extensions/gsd/workflow-reconcile.js +100 -9
- package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
- package/dist/resources/extensions/gsd/worktree.js +9 -0
- package/dist/resources/extensions/shared/interview-ui.js +1 -1
- package/dist/resources/extensions/subagent/agents.js +19 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
- 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 +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.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/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 +18 -18
- 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.8874bcae249c02e1.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +20 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -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 +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
- package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +20 -4
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +5 -0
- package/packages/pi-tui/dist/components/image.d.ts +2 -0
- package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/image.js +4 -0
- package/packages/pi-tui/dist/components/image.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
- package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/image.test.js +32 -0
- package/packages/pi-tui/dist/components/image.test.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +3 -1
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/components/image.test.ts +36 -0
- package/packages/pi-tui/src/components/image.ts +5 -0
- package/packages/pi-tui/src/tui.ts +3 -1
- package/src/resources/extensions/browser-tools/capture.ts +19 -1
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
- package/src/resources/extensions/gsd/auto/finalize-timeout.ts +3 -0
- package/src/resources/extensions/gsd/auto/loop.ts +2 -2
- package/src/resources/extensions/gsd/auto/phases.ts +68 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto/types.ts +5 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +110 -9
- package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +16 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -23
- package/src/resources/extensions/gsd/auto-start.ts +188 -10
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
- package/src/resources/extensions/gsd/auto.ts +19 -8
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +36 -1
- package/src/resources/extensions/gsd/commands/context.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +26 -2
- package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +331 -0
- package/src/resources/extensions/gsd/db-writer.ts +11 -3
- package/src/resources/extensions/gsd/detection.ts +1 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -1
- package/src/resources/extensions/gsd/files.ts +19 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +46 -4
- package/src/resources/extensions/gsd/guided-flow.ts +254 -30
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/json-persistence.ts +6 -3
- package/src/resources/extensions/gsd/md-importer.ts +13 -6
- package/src/resources/extensions/gsd/notification-overlay.ts +1 -1
- package/src/resources/extensions/gsd/notification-widget.ts +2 -1
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +1 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -7
- package/src/resources/extensions/gsd/preferences-types.ts +25 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +45 -1
- package/src/resources/extensions/gsd/preferences.ts +9 -2
- package/src/resources/extensions/gsd/preparation.ts +1419 -0
- package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
- package/src/resources/extensions/gsd/prompts/queue.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
- package/src/resources/extensions/gsd/quick.ts +20 -15
- package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
- package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
- package/src/resources/extensions/gsd/session-lock.ts +17 -1
- package/src/resources/extensions/gsd/state.ts +115 -26
- package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +11 -9
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
- package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
- package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +11 -10
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +284 -20
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/subagent-agent-discovery.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/wave5-consistency-regressions.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
- package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +127 -2
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +13 -3
- package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -6
- package/src/resources/extensions/gsd/tools/complete-task.ts +29 -7
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +37 -17
- package/src/resources/extensions/gsd/types.ts +4 -0
- package/src/resources/extensions/gsd/undo.ts +3 -2
- package/src/resources/extensions/gsd/workflow-events.ts +5 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +7 -8
- package/src/resources/extensions/gsd/workflow-reconcile.ts +109 -8
- package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
- package/src/resources/extensions/gsd/worktree.ts +10 -0
- package/src/resources/extensions/shared/interview-ui.ts +1 -1
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
- package/src/resources/extensions/subagent/agents.ts +30 -6
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
- /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → E0hBt4ifuG7QBbhUR5-6U}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → E0hBt4ifuG7QBbhUR5-6U}/_ssgManifest.js +0 -0
|
@@ -31,7 +31,11 @@ function installEpipeGuard() {
|
|
|
31
31
|
if (handleRecoverableExtensionProcessError(err)) {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
// Log unhandled errors instead of re-throwing — throwing inside an
|
|
35
|
+
// uncaughtException handler is a fatal double-fault in Node.js (#3163).
|
|
36
|
+
process.stderr.write(`[gsd] uncaught extension error (non-fatal): ${err.message}\n`);
|
|
37
|
+
if (err.stack)
|
|
38
|
+
process.stderr.write(`${err.stack}\n`);
|
|
35
39
|
};
|
|
36
40
|
process.on("uncaughtException", _gsdEpipeGuard);
|
|
37
41
|
}
|
|
@@ -3,7 +3,7 @@ import { isToolCallEventType } from "@gsd/pi-coding-agent";
|
|
|
3
3
|
import { buildMilestoneFileName, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
4
4
|
import { buildBeforeAgentStartResult } from "./system-context.js";
|
|
5
5
|
import { handleAgentEnd } from "./agent-end-recovery.js";
|
|
6
|
-
import { clearDiscussionFlowState, isDepthVerified, isQueuePhaseActive, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockQueueExecution } from "./write-gate.js";
|
|
6
|
+
import { clearDiscussionFlowState, isDepthVerified, isDepthConfirmationAnswer, isQueuePhaseActive, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockQueueExecution } from "./write-gate.js";
|
|
7
7
|
import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
|
|
8
8
|
import { cleanupQuickBranch } from "../quick.js";
|
|
9
9
|
import { getDiscussionMilestoneId } from "../guided-flow.js";
|
|
@@ -98,7 +98,10 @@ export function registerHooks(pi) {
|
|
|
98
98
|
}
|
|
99
99
|
});
|
|
100
100
|
pi.on("session_before_compact", async () => {
|
|
101
|
-
|
|
101
|
+
// Only cancel compaction while auto-mode is actively running.
|
|
102
|
+
// Paused auto-mode should allow compaction — the user may be doing
|
|
103
|
+
// interactive work (#3165).
|
|
104
|
+
if (isAutoActive()) {
|
|
102
105
|
return { cancel: true };
|
|
103
106
|
}
|
|
104
107
|
const basePath = process.cwd();
|
|
@@ -227,7 +230,12 @@ export function registerHooks(pi) {
|
|
|
227
230
|
const questions = event.input?.questions ?? [];
|
|
228
231
|
for (const question of questions) {
|
|
229
232
|
if (typeof question.id === "string" && question.id.includes("depth_verification")) {
|
|
230
|
-
|
|
233
|
+
// Only unlock the gate if the user selected the first option (confirmation).
|
|
234
|
+
// Cross-references against the question's defined options to reject free-form "Other" text.
|
|
235
|
+
const answer = details.response?.answers?.[question.id];
|
|
236
|
+
if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
|
|
237
|
+
markDepthVerified();
|
|
238
|
+
}
|
|
231
239
|
break;
|
|
232
240
|
}
|
|
233
241
|
}
|
|
@@ -12,7 +12,7 @@ import { hasSkillSnapshot, detectNewSkills, formatSkillsXml } from "../skill-dis
|
|
|
12
12
|
import { getActiveAutoWorktreeContext } from "../auto-worktree.js";
|
|
13
13
|
import { getActiveWorktreeName, getWorktreeOriginalCwd } from "../worktree-command.js";
|
|
14
14
|
import { deriveState } from "../state.js";
|
|
15
|
-
import { formatOverridesSection, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
|
|
15
|
+
import { formatOverridesSection, formatShortcut, loadActiveOverrides, loadFile, parseContinue, parseSummary } from "../files.js";
|
|
16
16
|
import { toPosixPath } from "../../shared/mod.js";
|
|
17
17
|
import { markCmuxPromptShown, shouldPromptToEnableCmux } from "../../cmux/index.js";
|
|
18
18
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
@@ -60,6 +60,8 @@ export async function buildBeforeAgentStartResult(event, ctx) {
|
|
|
60
60
|
const systemContent = loadPrompt("system", {
|
|
61
61
|
bundledSkillsTable: buildBundledSkillsTable(),
|
|
62
62
|
templatesDir: getTemplatesDir(),
|
|
63
|
+
shortcutDashboard: formatShortcut("Ctrl+Alt+G"),
|
|
64
|
+
shortcutShell: formatShortcut("Ctrl+Alt+B"),
|
|
63
65
|
});
|
|
64
66
|
const loadedPreferences = loadEffectiveGSDPreferences();
|
|
65
67
|
if (shouldPromptToEnableCmux(loadedPreferences?.preferences)) {
|
|
@@ -43,6 +43,30 @@ export function clearDiscussionFlowState() {
|
|
|
43
43
|
export function markDepthVerified() {
|
|
44
44
|
depthVerificationDone = true;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Check whether a depth_verification answer confirms the discussion is complete.
|
|
48
|
+
* Uses structural validation: the selected answer must exactly match the first
|
|
49
|
+
* option label from the question definition (the confirmation option by convention).
|
|
50
|
+
* This rejects free-form "Other" text, decline options, and garbage input without
|
|
51
|
+
* coupling to any specific label substring.
|
|
52
|
+
*
|
|
53
|
+
* @param selected The answer's selected value from details.response.answers[id].selected
|
|
54
|
+
* @param options The question's options array from event.input.questions[n].options
|
|
55
|
+
*/
|
|
56
|
+
export function isDepthConfirmationAnswer(selected, options) {
|
|
57
|
+
const value = Array.isArray(selected) ? selected[0] : selected;
|
|
58
|
+
if (typeof value !== "string" || !value)
|
|
59
|
+
return false;
|
|
60
|
+
// If options are available, structurally validate: selected must exactly match
|
|
61
|
+
// the first option (confirmation) label. Rejects free-form "Other" and decline options.
|
|
62
|
+
if (Array.isArray(options) && options.length > 0) {
|
|
63
|
+
const confirmLabel = options[0]?.label;
|
|
64
|
+
return typeof confirmLabel === "string" && value === confirmLabel;
|
|
65
|
+
}
|
|
66
|
+
// Fallback when options aren't available (e.g., older call sites):
|
|
67
|
+
// accept only if it contains "(Recommended)" — the prompt convention suffix.
|
|
68
|
+
return value.includes("(Recommended)");
|
|
69
|
+
}
|
|
46
70
|
export function shouldBlockContextWrite(toolName, inputPath, milestoneId, depthVerified, queuePhaseActive) {
|
|
47
71
|
if (toolName !== "write")
|
|
48
72
|
return { block: false };
|
|
@@ -56,7 +80,13 @@ export function shouldBlockContextWrite(toolName, inputPath, milestoneId, depthV
|
|
|
56
80
|
return { block: false };
|
|
57
81
|
return {
|
|
58
82
|
block: true,
|
|
59
|
-
reason:
|
|
83
|
+
reason: [
|
|
84
|
+
`HARD BLOCK: Cannot write to milestone CONTEXT.md without depth verification.`,
|
|
85
|
+
`This is a mechanical gate — you MUST NOT proceed, retry, or rationalize past this block.`,
|
|
86
|
+
`Required action: call ask_user_questions with question id containing "depth_verification".`,
|
|
87
|
+
`The user MUST select the "(Recommended)" confirmation option to unlock this gate.`,
|
|
88
|
+
`If the user declines, cancels, or the tool fails, you must re-ask — not bypass.`,
|
|
89
|
+
].join(" "),
|
|
60
90
|
};
|
|
61
91
|
}
|
|
62
92
|
/**
|
|
@@ -4,7 +4,14 @@ import { resolveProjectRoot } from "../worktree.js";
|
|
|
4
4
|
import { showNextAction } from "../../shared/tui.js";
|
|
5
5
|
import { handleStatus } from "./handlers/core.js";
|
|
6
6
|
export function projectRoot() {
|
|
7
|
-
|
|
7
|
+
let cwd;
|
|
8
|
+
try {
|
|
9
|
+
cwd = process.cwd();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// cwd directory was deleted (e.g. worktree teardown) — fall back to HOME (#3598)
|
|
13
|
+
cwd = process.env.HOME ?? "/";
|
|
14
|
+
}
|
|
8
15
|
const root = resolveProjectRoot(cwd);
|
|
9
16
|
if (root !== cwd) {
|
|
10
17
|
assertSafeDirectory(cwd);
|
|
@@ -5,6 +5,7 @@ import { runEnvironmentChecks } from "../../doctor-environment.js";
|
|
|
5
5
|
import { deriveState } from "../../state.js";
|
|
6
6
|
import { handleCmux } from "../../commands-cmux.js";
|
|
7
7
|
import { projectRoot } from "../context.js";
|
|
8
|
+
import { formatShortcut } from "../../files.js";
|
|
8
9
|
export function showHelp(ctx) {
|
|
9
10
|
const lines = [
|
|
10
11
|
"GSD — Get Shit Done\n",
|
|
@@ -20,12 +21,12 @@ export function showHelp(ctx) {
|
|
|
20
21
|
" /gsd new-milestone Create milestone from headless context (used by gsd headless)",
|
|
21
22
|
"",
|
|
22
23
|
"VISIBILITY",
|
|
23
|
-
|
|
24
|
+
` /gsd status Show progress dashboard (${formatShortcut("Ctrl+Alt+G")})`,
|
|
24
25
|
" /gsd visualize Interactive 10-tab TUI (progress, timeline, deps, metrics, health, agent, changes, knowledge, captures, export)",
|
|
25
26
|
" /gsd queue Show queued/dispatched units and execution order",
|
|
26
27
|
" /gsd history View execution history [--cost] [--phase] [--model] [N]",
|
|
27
28
|
" /gsd changelog Show categorized release notes [version]",
|
|
28
|
-
|
|
29
|
+
` /gsd notifications View persistent notification history [clear|tail|filter] (${formatShortcut("Ctrl+Alt+N")})`,
|
|
29
30
|
"",
|
|
30
31
|
"COURSE CORRECTION",
|
|
31
32
|
" /gsd steer <desc> Apply user override to active work",
|
|
@@ -48,6 +49,7 @@ export function showHelp(ctx) {
|
|
|
48
49
|
" /gsd cmux Manage cmux integration [status|on|off|notifications|sidebar|splits|browser]",
|
|
49
50
|
" /gsd config Set API keys for external tools",
|
|
50
51
|
" /gsd keys API key manager [list|add|remove|test|rotate|doctor]",
|
|
52
|
+
" /gsd show-config Show effective configuration (models, routing, toggles)",
|
|
51
53
|
" /gsd hooks Show post-unit hook configuration",
|
|
52
54
|
" /gsd extensions Manage extensions [list|enable|disable|info]",
|
|
53
55
|
" /gsd fast Toggle OpenAI service tier [on|off|flex|status]",
|
|
@@ -66,6 +68,9 @@ export function showHelp(ctx) {
|
|
|
66
68
|
}
|
|
67
69
|
export async function handleStatus(ctx) {
|
|
68
70
|
const basePath = projectRoot();
|
|
71
|
+
// Open DB in cold sessions so status uses DB-backed state, not filesystem fallback (#3385)
|
|
72
|
+
const { ensureDbOpen } = await import("../../bootstrap/dynamic-tools.js");
|
|
73
|
+
await ensureDbOpen();
|
|
69
74
|
const state = await deriveState(basePath);
|
|
70
75
|
if (state.registry.length === 0) {
|
|
71
76
|
ctx.ui.notify("No GSD milestones found. Run /gsd to start.", "info");
|
|
@@ -188,6 +193,22 @@ export async function handleCoreCommand(trimmed, ctx) {
|
|
|
188
193
|
await handleCmux(trimmed.replace(/^cmux\s*/, "").trim(), ctx);
|
|
189
194
|
return true;
|
|
190
195
|
}
|
|
196
|
+
if (trimmed === "show-config") {
|
|
197
|
+
const { GSDConfigOverlay, formatConfigText } = await import("../../config-overlay.js");
|
|
198
|
+
const result = await ctx.ui.custom((tui, theme, _kb, done) => new GSDConfigOverlay(tui, theme, () => done()), {
|
|
199
|
+
overlay: true,
|
|
200
|
+
overlayOptions: {
|
|
201
|
+
width: "65%",
|
|
202
|
+
minWidth: 55,
|
|
203
|
+
maxHeight: "85%",
|
|
204
|
+
anchor: "center",
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
if (result === undefined) {
|
|
208
|
+
ctx.ui.notify(formatConfigText(), "info");
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
191
212
|
if (trimmed === "setup" || trimmed.startsWith("setup ")) {
|
|
192
213
|
await handleSetup(trimmed.replace(/^setup\s*/, "").trim(), ctx);
|
|
193
214
|
return true;
|
|
@@ -68,7 +68,7 @@ function discoverManifests() {
|
|
|
68
68
|
if (!existsSync(extDir))
|
|
69
69
|
return manifests;
|
|
70
70
|
for (const entry of readdirSync(extDir, { withFileTypes: true })) {
|
|
71
|
-
if (!entry.isDirectory())
|
|
71
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
72
72
|
continue;
|
|
73
73
|
const m = readManifest(join(extDir, entry.name));
|
|
74
74
|
if (m)
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD Configuration Overlay
|
|
3
|
+
*
|
|
4
|
+
* Read-only TUI overlay showing the effective GSD configuration:
|
|
5
|
+
* token profile, model assignments, dynamic routing, git settings,
|
|
6
|
+
* budget, workflow toggles, and preference file sources.
|
|
7
|
+
* Opened via `/gsd show-config` or `/gsd config`.
|
|
8
|
+
*/
|
|
9
|
+
import { matchesKey, Key, truncateToWidth } from "@gsd/pi-tui";
|
|
10
|
+
import { loadEffectiveGSDPreferences, loadGlobalGSDPreferences, loadProjectGSDPreferences, getGlobalGSDPreferencesPath, getProjectGSDPreferencesPath, resolveDynamicRoutingConfig, resolveEffectiveProfile, resolveModelWithFallbacksForUnit, resolveAutoSupervisorConfig, } from "./preferences.js";
|
|
11
|
+
function collectConfigSections() {
|
|
12
|
+
const sections = [];
|
|
13
|
+
const globalPrefs = loadGlobalGSDPreferences();
|
|
14
|
+
const projectPrefs = loadProjectGSDPreferences();
|
|
15
|
+
const effective = loadEffectiveGSDPreferences();
|
|
16
|
+
const prefs = effective?.preferences;
|
|
17
|
+
// ─── Sources ─────────────────────────────────────────────────────────
|
|
18
|
+
sections.push({
|
|
19
|
+
title: "Sources",
|
|
20
|
+
rows: [
|
|
21
|
+
{ label: "Global", value: globalPrefs ? globalPrefs.path : `(none) ${getGlobalGSDPreferencesPath()}` },
|
|
22
|
+
{ label: "Project", value: projectPrefs ? projectPrefs.path : `(none) ${getProjectGSDPreferencesPath()}` },
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
// ─── Profile ─────────────────────────────────────────────────────────
|
|
26
|
+
const profile = resolveEffectiveProfile();
|
|
27
|
+
const profileRows = [
|
|
28
|
+
{ label: "Token profile", value: `${profile}${!prefs?.token_profile ? " (default)" : ""}`, accent: true },
|
|
29
|
+
];
|
|
30
|
+
if (prefs?.mode)
|
|
31
|
+
profileRows.push({ label: "Workflow mode", value: prefs.mode });
|
|
32
|
+
sections.push({ title: "Profile", rows: profileRows });
|
|
33
|
+
// ─── Models ──────────────────────────────────────────────────────────
|
|
34
|
+
const unitTypes = [
|
|
35
|
+
["research", "research-milestone"],
|
|
36
|
+
["planning", "plan-milestone"],
|
|
37
|
+
["discuss", "discuss-milestone"],
|
|
38
|
+
["execution", "execute-task"],
|
|
39
|
+
["completion", "complete-slice"],
|
|
40
|
+
["validation", "run-uat"],
|
|
41
|
+
];
|
|
42
|
+
const modelRows = [];
|
|
43
|
+
for (const [label, unitType] of unitTypes) {
|
|
44
|
+
const resolved = resolveModelWithFallbacksForUnit(unitType);
|
|
45
|
+
if (resolved) {
|
|
46
|
+
let val = resolved.primary;
|
|
47
|
+
if (resolved.fallbacks.length > 0) {
|
|
48
|
+
val += ` \u2192 ${resolved.fallbacks.join(" \u2192 ")}`;
|
|
49
|
+
}
|
|
50
|
+
modelRows.push({ label, value: val });
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
modelRows.push({ label, value: "(inherit)" });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// subagent is a direct config key
|
|
57
|
+
const models = prefs?.models;
|
|
58
|
+
const subVal = models?.subagent;
|
|
59
|
+
if (subVal) {
|
|
60
|
+
const model = typeof subVal === "string" ? subVal : subVal?.model ?? "?";
|
|
61
|
+
modelRows.push({ label: "subagent", value: model });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
modelRows.push({ label: "subagent", value: "(inherit)" });
|
|
65
|
+
}
|
|
66
|
+
sections.push({ title: "Models", rows: modelRows });
|
|
67
|
+
// ─── Dynamic Routing ─────────────────────────────────────────────────
|
|
68
|
+
const routing = resolveDynamicRoutingConfig();
|
|
69
|
+
const routingRows = [
|
|
70
|
+
{ label: "Enabled", value: routing.enabled ? "yes" : "no", accent: routing.enabled },
|
|
71
|
+
];
|
|
72
|
+
if (routing.enabled) {
|
|
73
|
+
routingRows.push({ label: "Escalate on fail", value: routing.escalate_on_failure !== false ? "yes" : "no" });
|
|
74
|
+
routingRows.push({ label: "Budget pressure", value: routing.budget_pressure !== false ? "yes" : "no" });
|
|
75
|
+
routingRows.push({ label: "Cross-provider", value: routing.cross_provider !== false ? "yes" : "no" });
|
|
76
|
+
if (routing.tier_models) {
|
|
77
|
+
const tm = routing.tier_models;
|
|
78
|
+
if (tm.light)
|
|
79
|
+
routingRows.push({ label: "[L] light", value: tm.light });
|
|
80
|
+
if (tm.standard)
|
|
81
|
+
routingRows.push({ label: "[S] standard", value: tm.standard });
|
|
82
|
+
if (tm.heavy)
|
|
83
|
+
routingRows.push({ label: "[H] heavy", value: tm.heavy });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
sections.push({ title: "Dynamic Routing", rows: routingRows });
|
|
87
|
+
// ─── Git ─────────────────────────────────────────────────────────────
|
|
88
|
+
if (prefs?.git) {
|
|
89
|
+
const g = prefs.git;
|
|
90
|
+
const gitRows = [];
|
|
91
|
+
if (g.isolation !== undefined)
|
|
92
|
+
gitRows.push({ label: "Isolation", value: String(g.isolation) });
|
|
93
|
+
if (g.auto_push !== undefined)
|
|
94
|
+
gitRows.push({ label: "Auto push", value: String(g.auto_push) });
|
|
95
|
+
if (g.push_branches !== undefined)
|
|
96
|
+
gitRows.push({ label: "Push branches", value: String(g.push_branches) });
|
|
97
|
+
if (g.merge_strategy)
|
|
98
|
+
gitRows.push({ label: "Merge strategy", value: g.merge_strategy });
|
|
99
|
+
if (g.main_branch)
|
|
100
|
+
gitRows.push({ label: "Main branch", value: g.main_branch });
|
|
101
|
+
if (g.remote)
|
|
102
|
+
gitRows.push({ label: "Remote", value: g.remote });
|
|
103
|
+
if (gitRows.length > 0)
|
|
104
|
+
sections.push({ title: "Git", rows: gitRows });
|
|
105
|
+
}
|
|
106
|
+
// ─── Budget ──────────────────────────────────────────────────────────
|
|
107
|
+
if (prefs?.budget_ceiling !== undefined || prefs?.budget_enforcement) {
|
|
108
|
+
const budgetRows = [];
|
|
109
|
+
if (prefs.budget_ceiling !== undefined)
|
|
110
|
+
budgetRows.push({ label: "Ceiling", value: `$${prefs.budget_ceiling}` });
|
|
111
|
+
if (prefs.budget_enforcement)
|
|
112
|
+
budgetRows.push({ label: "Enforcement", value: String(prefs.budget_enforcement) });
|
|
113
|
+
sections.push({ title: "Budget", rows: budgetRows });
|
|
114
|
+
}
|
|
115
|
+
// ─── Auto Supervisor ─────────────────────────────────────────────────
|
|
116
|
+
if (prefs?.auto_supervisor) {
|
|
117
|
+
const sup = resolveAutoSupervisorConfig();
|
|
118
|
+
const supRows = [];
|
|
119
|
+
if (sup.model)
|
|
120
|
+
supRows.push({ label: "Model", value: sup.model });
|
|
121
|
+
supRows.push({ label: "Soft timeout", value: `${sup.soft_timeout_minutes}m` });
|
|
122
|
+
supRows.push({ label: "Idle timeout", value: `${sup.idle_timeout_minutes}m` });
|
|
123
|
+
supRows.push({ label: "Hard timeout", value: `${sup.hard_timeout_minutes}m` });
|
|
124
|
+
sections.push({ title: "Auto Supervisor", rows: supRows });
|
|
125
|
+
}
|
|
126
|
+
// ─── Toggles ─────────────────────────────────────────────────────────
|
|
127
|
+
const toggleRows = [];
|
|
128
|
+
if (prefs?.phases) {
|
|
129
|
+
const p = prefs.phases;
|
|
130
|
+
if (p.skip_research)
|
|
131
|
+
toggleRows.push({ label: "skip_research", value: "on" });
|
|
132
|
+
if (p.skip_reassess)
|
|
133
|
+
toggleRows.push({ label: "skip_reassess", value: "on" });
|
|
134
|
+
if (p.skip_slice_research)
|
|
135
|
+
toggleRows.push({ label: "skip_slice_research", value: "on" });
|
|
136
|
+
if (p.skip_milestone_validation)
|
|
137
|
+
toggleRows.push({ label: "skip_milestone_validation", value: "on" });
|
|
138
|
+
if (p.require_slice_discussion)
|
|
139
|
+
toggleRows.push({ label: "require_slice_discussion", value: "on" });
|
|
140
|
+
}
|
|
141
|
+
if (prefs?.uat_dispatch)
|
|
142
|
+
toggleRows.push({ label: "uat_dispatch", value: "on" });
|
|
143
|
+
if (prefs?.auto_visualize)
|
|
144
|
+
toggleRows.push({ label: "auto_visualize", value: "on" });
|
|
145
|
+
if (prefs?.auto_report === false)
|
|
146
|
+
toggleRows.push({ label: "auto_report", value: "off" });
|
|
147
|
+
if (prefs?.show_token_cost)
|
|
148
|
+
toggleRows.push({ label: "show_token_cost", value: "on" });
|
|
149
|
+
if (prefs?.forensics_dedup)
|
|
150
|
+
toggleRows.push({ label: "forensics_dedup", value: "on" });
|
|
151
|
+
if (prefs?.unique_milestone_ids)
|
|
152
|
+
toggleRows.push({ label: "unique_milestone_ids", value: "on" });
|
|
153
|
+
if (prefs?.service_tier)
|
|
154
|
+
toggleRows.push({ label: "service_tier", value: prefs.service_tier });
|
|
155
|
+
if (prefs?.search_provider && prefs.search_provider !== "auto")
|
|
156
|
+
toggleRows.push({ label: "search_provider", value: prefs.search_provider });
|
|
157
|
+
if (prefs?.context_selection)
|
|
158
|
+
toggleRows.push({ label: "context_selection", value: prefs.context_selection });
|
|
159
|
+
if (prefs?.widget_mode && prefs.widget_mode !== "full")
|
|
160
|
+
toggleRows.push({ label: "widget_mode", value: prefs.widget_mode });
|
|
161
|
+
if (prefs?.experimental?.rtk)
|
|
162
|
+
toggleRows.push({ label: "experimental.rtk", value: "on" });
|
|
163
|
+
if (toggleRows.length > 0)
|
|
164
|
+
sections.push({ title: "Toggles", rows: toggleRows });
|
|
165
|
+
// ─── Parallel ────────────────────────────────────────────────────────
|
|
166
|
+
if (prefs?.parallel) {
|
|
167
|
+
const pc = prefs.parallel;
|
|
168
|
+
const parallelRows = [];
|
|
169
|
+
if (pc.max_workers !== undefined)
|
|
170
|
+
parallelRows.push({ label: "Max workers", value: String(pc.max_workers) });
|
|
171
|
+
if (pc.merge_strategy)
|
|
172
|
+
parallelRows.push({ label: "Merge strategy", value: pc.merge_strategy });
|
|
173
|
+
if (pc.auto_merge)
|
|
174
|
+
parallelRows.push({ label: "Auto merge", value: pc.auto_merge });
|
|
175
|
+
if (parallelRows.length > 0)
|
|
176
|
+
sections.push({ title: "Parallel", rows: parallelRows });
|
|
177
|
+
}
|
|
178
|
+
// ─── Hooks ───────────────────────────────────────────────────────────
|
|
179
|
+
const postHooks = prefs?.post_unit_hooks?.filter(h => h.enabled !== false) ?? [];
|
|
180
|
+
const preHooks = prefs?.pre_dispatch_hooks?.filter(h => h.enabled !== false) ?? [];
|
|
181
|
+
if (postHooks.length > 0 || preHooks.length > 0) {
|
|
182
|
+
const hookRows = [];
|
|
183
|
+
if (preHooks.length > 0)
|
|
184
|
+
hookRows.push({ label: "Pre-dispatch", value: `${preHooks.length} active` });
|
|
185
|
+
if (postHooks.length > 0)
|
|
186
|
+
hookRows.push({ label: "Post-unit", value: `${postHooks.length} active` });
|
|
187
|
+
sections.push({ title: "Hooks", rows: hookRows });
|
|
188
|
+
}
|
|
189
|
+
// ─── Warnings ────────────────────────────────────────────────────────
|
|
190
|
+
const warnings = [
|
|
191
|
+
...(globalPrefs?.warnings ?? []),
|
|
192
|
+
...(projectPrefs?.warnings ?? []),
|
|
193
|
+
];
|
|
194
|
+
if (warnings.length > 0) {
|
|
195
|
+
sections.push({
|
|
196
|
+
title: "Warnings",
|
|
197
|
+
rows: warnings.map(w => ({ label: "\u26a0", value: w })),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return sections;
|
|
201
|
+
}
|
|
202
|
+
// ─── Plain Text Formatter (headless/RPC fallback) ─────────────────────────
|
|
203
|
+
export function formatConfigText() {
|
|
204
|
+
const sections = collectConfigSections();
|
|
205
|
+
const lines = ["GSD Configuration\n"];
|
|
206
|
+
let maxLabel = 0;
|
|
207
|
+
for (const section of sections) {
|
|
208
|
+
for (const row of section.rows) {
|
|
209
|
+
if (row.label.length > maxLabel)
|
|
210
|
+
maxLabel = row.label.length;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const pad = Math.min(maxLabel + 2, 24);
|
|
214
|
+
for (const section of sections) {
|
|
215
|
+
lines.push("");
|
|
216
|
+
lines.push(section.title.toUpperCase());
|
|
217
|
+
for (const row of section.rows) {
|
|
218
|
+
lines.push(` ${row.label.padEnd(pad)}${row.value}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return lines.join("\n");
|
|
222
|
+
}
|
|
223
|
+
// ─── Overlay Class ────────────────────────────────────────────────────────
|
|
224
|
+
export class GSDConfigOverlay {
|
|
225
|
+
tui;
|
|
226
|
+
theme;
|
|
227
|
+
onClose;
|
|
228
|
+
sections;
|
|
229
|
+
cachedLines;
|
|
230
|
+
scrollOffset = 0;
|
|
231
|
+
disposed = false;
|
|
232
|
+
constructor(tui, theme, onClose) {
|
|
233
|
+
this.tui = tui;
|
|
234
|
+
this.theme = theme;
|
|
235
|
+
this.onClose = onClose;
|
|
236
|
+
this.sections = collectConfigSections();
|
|
237
|
+
}
|
|
238
|
+
invalidate() {
|
|
239
|
+
this.cachedLines = undefined;
|
|
240
|
+
}
|
|
241
|
+
dispose() {
|
|
242
|
+
this.disposed = true;
|
|
243
|
+
}
|
|
244
|
+
handleInput(data) {
|
|
245
|
+
if (matchesKey(data, Key.escape) || data === "q") {
|
|
246
|
+
this.dispose();
|
|
247
|
+
this.onClose();
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (matchesKey(data, Key.down) || data === "j") {
|
|
251
|
+
this.scrollOffset++;
|
|
252
|
+
this.cachedLines = undefined;
|
|
253
|
+
this.tui.requestRender();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (matchesKey(data, Key.up) || data === "k") {
|
|
257
|
+
this.scrollOffset = Math.max(0, this.scrollOffset - 1);
|
|
258
|
+
this.cachedLines = undefined;
|
|
259
|
+
this.tui.requestRender();
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (matchesKey(data, Key.pageDown)) {
|
|
263
|
+
this.scrollOffset += 10;
|
|
264
|
+
this.cachedLines = undefined;
|
|
265
|
+
this.tui.requestRender();
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (matchesKey(data, Key.pageUp)) {
|
|
269
|
+
this.scrollOffset = Math.max(0, this.scrollOffset - 10);
|
|
270
|
+
this.cachedLines = undefined;
|
|
271
|
+
this.tui.requestRender();
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
render(width) {
|
|
276
|
+
if (this.cachedLines)
|
|
277
|
+
return this.cachedLines;
|
|
278
|
+
const t = this.theme;
|
|
279
|
+
const w = Math.max(width, 50);
|
|
280
|
+
const allLines = [];
|
|
281
|
+
// Header
|
|
282
|
+
allLines.push(t.bold(t.fg("accent", " GSD Configuration ")));
|
|
283
|
+
allLines.push(t.fg("muted", "\u2500".repeat(w)));
|
|
284
|
+
// Find max label width for alignment
|
|
285
|
+
let maxLabel = 0;
|
|
286
|
+
for (const section of this.sections) {
|
|
287
|
+
for (const row of section.rows) {
|
|
288
|
+
if (row.label.length > maxLabel)
|
|
289
|
+
maxLabel = row.label.length;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const labelPad = Math.min(maxLabel + 2, 24);
|
|
293
|
+
for (const section of this.sections) {
|
|
294
|
+
allLines.push("");
|
|
295
|
+
allLines.push(t.bold(t.fg("accent", ` ${section.title}`)));
|
|
296
|
+
for (const row of section.rows) {
|
|
297
|
+
const label = t.fg("muted", ` ${row.label.padEnd(labelPad)}`);
|
|
298
|
+
const value = row.accent ? t.bold(row.value) : row.value;
|
|
299
|
+
allLines.push(truncateToWidth(`${label}${value}`, w));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
allLines.push("");
|
|
303
|
+
allLines.push(t.fg("muted", ` ${"\u2500".repeat(w - 4)}`));
|
|
304
|
+
allLines.push(t.fg("muted", " esc/q close \u2502 \u2191\u2193/jk scroll \u2502 /gsd prefs to edit"));
|
|
305
|
+
// Apply scroll
|
|
306
|
+
const maxScroll = Math.max(0, allLines.length - 20);
|
|
307
|
+
this.scrollOffset = Math.min(this.scrollOffset, maxScroll);
|
|
308
|
+
const visible = allLines.slice(this.scrollOffset);
|
|
309
|
+
this.cachedLines = visible;
|
|
310
|
+
return visible;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
@@ -300,8 +300,13 @@ export async function saveRequirementToDb(fields, basePath) {
|
|
|
300
300
|
}
|
|
301
301
|
catch (diskErr) {
|
|
302
302
|
logError('manifest', 'disk write failed, rolling back DB row', { fn: 'saveRequirementToDb', error: String(diskErr.message) });
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
try {
|
|
304
|
+
const rollbackAdapter = db._getAdapter();
|
|
305
|
+
rollbackAdapter?.prepare('DELETE FROM requirements WHERE id = :id').run({ ':id': id });
|
|
306
|
+
}
|
|
307
|
+
catch (rollbackErr) {
|
|
308
|
+
logError('manifest', 'SPLIT BRAIN: disk write failed AND DB rollback failed — DB has orphaned row', { fn: 'saveRequirementToDb', id, error: String(rollbackErr.message) });
|
|
309
|
+
}
|
|
305
310
|
throw diskErr;
|
|
306
311
|
}
|
|
307
312
|
invalidateStateCache();
|
|
@@ -399,7 +404,12 @@ export async function saveDecisionToDb(fields, basePath) {
|
|
|
399
404
|
}
|
|
400
405
|
catch (diskErr) {
|
|
401
406
|
logError('manifest', 'disk write failed, rolling back DB row', { fn: 'saveDecisionToDb', error: String(diskErr.message) });
|
|
402
|
-
|
|
407
|
+
try {
|
|
408
|
+
adapter?.prepare('DELETE FROM decisions WHERE id = :id').run({ ':id': id });
|
|
409
|
+
}
|
|
410
|
+
catch (rollbackErr) {
|
|
411
|
+
logError('manifest', 'SPLIT BRAIN: disk write failed AND DB rollback failed — DB has orphaned row', { fn: 'saveDecisionToDb', id, error: String(rollbackErr.message) });
|
|
412
|
+
}
|
|
403
413
|
throw diskErr;
|
|
404
414
|
}
|
|
405
415
|
// #2661: When a decision defers a slice, update the slice status in the DB
|
|
@@ -945,7 +945,7 @@ function resolveVersionCatalogAccessors(basePath, versionCatalogFiles, settingsF
|
|
|
945
945
|
}
|
|
946
946
|
return accessors;
|
|
947
947
|
}
|
|
948
|
-
function scanProjectFiles(basePath) {
|
|
948
|
+
export function scanProjectFiles(basePath) {
|
|
949
949
|
const files = [];
|
|
950
950
|
const queue = [{ path: basePath, depth: 0 }];
|
|
951
951
|
while (queue.length > 0 && files.length < MAX_RECURSIVE_SCAN_FILES) {
|
|
@@ -4,6 +4,7 @@ import { findMilestoneIds } from "./guided-flow.js";
|
|
|
4
4
|
import { parseUnitId } from "./unit-id.js";
|
|
5
5
|
import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
|
|
6
6
|
import { parseRoadmap } from "./parsers-legacy.js";
|
|
7
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
7
8
|
import { readFileSync } from "node:fs";
|
|
8
9
|
const SLICE_DISPATCH_TYPES = new Set([
|
|
9
10
|
"research-slice",
|
|
@@ -46,7 +47,7 @@ export function getPriorSliceCompletionBlocker(base, _mainBranch, unitType, unit
|
|
|
46
47
|
if (rows.length > 0) {
|
|
47
48
|
slices = rows.map((r) => ({
|
|
48
49
|
id: r.id,
|
|
49
|
-
done: r.status
|
|
50
|
+
done: isClosedStatus(r.status),
|
|
50
51
|
depends: r.depends ?? [],
|
|
51
52
|
}));
|
|
52
53
|
}
|
|
@@ -211,6 +211,7 @@ Setting `prefer_skills: []` does **not** disable skill discovery — it just mea
|
|
|
211
211
|
- `budget_ceiling`: number — optional per-parallel-run budget ceiling.
|
|
212
212
|
- `merge_strategy`: `"per-slice"` or `"per-milestone"` — when to merge worktree results back. Default: `"per-milestone"`.
|
|
213
213
|
- `auto_merge`: `"auto"`, `"confirm"`, or `"manual"` — merge behavior after completion. `"auto"` merges immediately; `"confirm"` asks first; `"manual"` leaves branches for you. Default: `"confirm"`.
|
|
214
|
+
- `worker_model`: string — optional model override for parallel milestone workers. When set, workers use this model (e.g. `"claude-haiku-4-5"`) instead of inheriting the coordinator's model. Useful for cost savings on execution-heavy milestones.
|
|
214
215
|
|
|
215
216
|
- `verification_commands`: string[] — shell commands to run as verification after task execution (e.g., `["npm test", "npm run lint"]`). Commands run in order; if any fails, the task is marked as needing fixes.
|
|
216
217
|
|
|
@@ -75,7 +75,8 @@ function validatePreferenceShape(preferences) {
|
|
|
75
75
|
}
|
|
76
76
|
return issues;
|
|
77
77
|
}
|
|
78
|
-
|
|
78
|
+
/** Build STATE.md content from derived state. Exported for guided-flow pre-dispatch rebuild (#3475). */
|
|
79
|
+
export function buildStateMarkdown(state) {
|
|
79
80
|
const lines = [];
|
|
80
81
|
lines.push("# GSD State", "");
|
|
81
82
|
const activeMilestone = state.activeMilestone
|
|
@@ -52,6 +52,23 @@ export function clearParseCache() {
|
|
|
52
52
|
for (const cb of _cacheClearCallbacks)
|
|
53
53
|
cb();
|
|
54
54
|
}
|
|
55
|
+
// ─── Platform shortcuts ───────────────────────────────────────────────────
|
|
56
|
+
const IS_MAC = process.platform === "darwin";
|
|
57
|
+
/**
|
|
58
|
+
* Format a keyboard shortcut for the current OS.
|
|
59
|
+
* Input: modifier key combo like "Ctrl+Alt+G"
|
|
60
|
+
* Output: "⌃⌥G" on macOS, "Ctrl+Alt+G" on Windows/Linux.
|
|
61
|
+
*/
|
|
62
|
+
export function formatShortcut(combo) {
|
|
63
|
+
if (!IS_MAC)
|
|
64
|
+
return combo;
|
|
65
|
+
return combo
|
|
66
|
+
.replace(/Ctrl\+Alt\+/i, "⌃⌥")
|
|
67
|
+
.replace(/Ctrl\+/i, "⌃")
|
|
68
|
+
.replace(/Alt\+/i, "⌥")
|
|
69
|
+
.replace(/Shift\+/i, "⇧")
|
|
70
|
+
.replace(/Cmd\+/i, "⌘");
|
|
71
|
+
}
|
|
55
72
|
// ─── Helpers ───────────────────────────────────────────────────────────────
|
|
56
73
|
/** Extract the text after a heading at a given level, up to the next heading of same or higher level. */
|
|
57
74
|
export function extractSection(body, heading, level = 2) {
|