gsd-pi 2.65.0-dev.5c8557b → 2.65.0-dev.d0517ff
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/run-unit.js +13 -2
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- 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 +42 -11
- 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/write-gate.js +31 -1
- package/dist/resources/extensions/gsd/commands/context.js +8 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +20 -0
- 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/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/parallel-orchestrator.js +17 -11
- package/dist/resources/extensions/gsd/pre-execution-checks.js +12 -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/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/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- 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 +15 -15
- 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/src/components/image.test.ts +36 -0
- package/packages/pi-tui/src/components/image.ts +5 -0
- 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/run-unit.ts +12 -2
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- 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 +45 -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/write-gate.ts +36 -1
- package/src/resources/extensions/gsd/commands/context.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -0
- 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/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/parallel-orchestrator.ts +19 -11
- package/src/resources/extensions/gsd/pre-execution-checks.ts +15 -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/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/find-missing-summaries-closed.test.ts +48 -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/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/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 +218 -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/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/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
- /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → JwdBI3y1H8vtBKiYvWfEK}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → JwdBI3y1H8vtBKiYvWfEK}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3696 — prompt step ordering and runtime fixes
|
|
3
|
+
*
|
|
4
|
+
* 1. complete-milestone.md: gsd_requirement_update (step 9) before
|
|
5
|
+
* gsd_complete_milestone (step 10)
|
|
6
|
+
* 2. complete-slice.md: uses gsd_requirement_update
|
|
7
|
+
* 3. register-extension.ts: _gsdEpipeGuard logs instead of re-throwing
|
|
8
|
+
* 4. register-hooks.ts: session_before_compact only checks isAutoActive
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, test } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { dirname, join } from 'node:path';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = dirname(__filename);
|
|
19
|
+
|
|
20
|
+
const completeMilestoneMd = readFileSync(
|
|
21
|
+
join(__dirname, '..', 'prompts', 'complete-milestone.md'),
|
|
22
|
+
'utf-8',
|
|
23
|
+
);
|
|
24
|
+
const completeSliceMd = readFileSync(
|
|
25
|
+
join(__dirname, '..', 'prompts', 'complete-slice.md'),
|
|
26
|
+
'utf-8',
|
|
27
|
+
);
|
|
28
|
+
const registerExtSrc = readFileSync(
|
|
29
|
+
join(__dirname, '..', 'bootstrap', 'register-extension.ts'),
|
|
30
|
+
'utf-8',
|
|
31
|
+
);
|
|
32
|
+
const registerHooksSrc = readFileSync(
|
|
33
|
+
join(__dirname, '..', 'bootstrap', 'register-hooks.ts'),
|
|
34
|
+
'utf-8',
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
describe('prompt step ordering (#3696)', () => {
|
|
38
|
+
test('gsd_requirement_update step appears before gsd_complete_milestone step', () => {
|
|
39
|
+
// Search for the numbered step definitions, not early "Do NOT call" warnings
|
|
40
|
+
const reqUpdateMatch = completeMilestoneMd.match(/^\d+\.\s.*gsd_requirement_update/m);
|
|
41
|
+
const completeMilestoneMatch = completeMilestoneMd.match(/^\d+\.\s.*gsd_complete_milestone/m);
|
|
42
|
+
assert.ok(reqUpdateMatch, 'gsd_requirement_update should appear in a numbered step');
|
|
43
|
+
assert.ok(completeMilestoneMatch, 'gsd_complete_milestone should appear in a numbered step');
|
|
44
|
+
const reqUpdateIdx = completeMilestoneMd.indexOf(reqUpdateMatch![0]);
|
|
45
|
+
const completeMilestoneIdx = completeMilestoneMd.indexOf(completeMilestoneMatch![0]);
|
|
46
|
+
assert.ok(
|
|
47
|
+
reqUpdateIdx < completeMilestoneIdx,
|
|
48
|
+
'gsd_requirement_update step must come before gsd_complete_milestone step',
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('complete-slice.md uses gsd_requirement_update', () => {
|
|
53
|
+
assert.match(completeSliceMd, /gsd_requirement_update/,
|
|
54
|
+
'complete-slice.md should reference gsd_requirement_update');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('register-extension _gsdEpipeGuard (#3696)', () => {
|
|
59
|
+
test('_gsdEpipeGuard exists and does not re-throw', () => {
|
|
60
|
+
assert.match(registerExtSrc, /_gsdEpipeGuard/,
|
|
61
|
+
'_gsdEpipeGuard should be defined in register-extension.ts');
|
|
62
|
+
// After the fix, the handler logs instead of throwing
|
|
63
|
+
assert.ok(
|
|
64
|
+
!registerExtSrc.includes('throw err'),
|
|
65
|
+
'_gsdEpipeGuard should NOT contain "throw err"',
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('register-hooks session_before_compact (#3696)', () => {
|
|
71
|
+
test('session_before_compact only checks isAutoActive', () => {
|
|
72
|
+
// Extract the session_before_compact handler
|
|
73
|
+
const compactIdx = registerHooksSrc.indexOf('session_before_compact');
|
|
74
|
+
assert.ok(compactIdx > -1, 'session_before_compact hook should exist');
|
|
75
|
+
// The first check in the handler should be isAutoActive(), not isAutoPaused()
|
|
76
|
+
const afterCompact = registerHooksSrc.slice(compactIdx, compactIdx + 300);
|
|
77
|
+
assert.match(afterCompact, /isAutoActive\(\)/,
|
|
78
|
+
'session_before_compact should check isAutoActive()');
|
|
79
|
+
// Should NOT block compaction when paused
|
|
80
|
+
assert.ok(
|
|
81
|
+
!afterCompact.includes('isAutoPaused()'),
|
|
82
|
+
'session_before_compact should not check isAutoPaused',
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -464,7 +464,8 @@ test("agent-session retryable error regex matches server_error (underscore)", ()
|
|
|
464
464
|
// This regex is extracted from _isRetryableError in agent-session.ts.
|
|
465
465
|
// It must match both "server error" (space) and "server_error" (underscore)
|
|
466
466
|
// to properly classify Codex streaming errors as retryable.
|
|
467
|
-
|
|
467
|
+
// "temporarily backed off" intentionally excluded — see #3429
|
|
468
|
+
const retryableRegex = /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\s+)?unavailable|credentials.*expired|extra usage is required/i;
|
|
468
469
|
|
|
469
470
|
// server_error (with underscore — Codex streaming error format)
|
|
470
471
|
assert.ok(retryableRegex.test("Codex server_error: An error occurred"));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3672 — query-tools uses ensureDbOpen
|
|
3
|
+
*
|
|
4
|
+
* gsd_milestone_status previously called isDbAvailable() but never
|
|
5
|
+
* ensureDbOpen(), making it always fail outside auto-mode sessions.
|
|
6
|
+
* The fix imports ensureDbOpen from dynamic-tools and calls it before
|
|
7
|
+
* querying the DB.
|
|
8
|
+
*
|
|
9
|
+
* This structural test verifies the ensureDbOpen import and usage exist
|
|
10
|
+
* in query-tools.ts.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test } from 'node:test';
|
|
14
|
+
import assert from 'node:assert/strict';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
|
|
22
|
+
const source = readFileSync(join(__dirname, '..', 'bootstrap', 'query-tools.ts'), 'utf-8');
|
|
23
|
+
|
|
24
|
+
describe('query-tools ensureDbOpen usage (#3672)', () => {
|
|
25
|
+
test('imports ensureDbOpen from dynamic-tools', () => {
|
|
26
|
+
assert.match(source, /ensureDbOpen.*import\(|import.*ensureDbOpen/,
|
|
27
|
+
'query-tools should import ensureDbOpen');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('calls ensureDbOpen() before DB queries', () => {
|
|
31
|
+
assert.match(source, /await ensureDbOpen\(\)/,
|
|
32
|
+
'query-tools should call await ensureDbOpen()');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('no longer imports isDbAvailable in the execute path', () => {
|
|
36
|
+
// The old code imported isDbAvailable and checked it; the fix removed that
|
|
37
|
+
// The execute function should not destructure isDbAvailable from gsd-db
|
|
38
|
+
const executeBlock = source.slice(source.indexOf('async execute('));
|
|
39
|
+
assert.doesNotMatch(executeBlock, /isDbAvailable,/,
|
|
40
|
+
'execute path should not destructure isDbAvailable (replaced by ensureDbOpen)');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('uses dbAvailable result from ensureDbOpen', () => {
|
|
44
|
+
assert.match(source, /dbAvailable\s*=\s*await ensureDbOpen\(\)/,
|
|
45
|
+
'should store ensureDbOpen result in dbAvailable');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
|
|
9
|
+
function guidedFlowSrc(): string {
|
|
10
|
+
return readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function promptSrc(): string {
|
|
14
|
+
return readFileSync(join(__dirname, "..", "prompts", "guided-discuss-milestone.md"), "utf-8");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("queued-discuss-fast-path", () => {
|
|
18
|
+
test("1. guided-discuss-milestone.md contains {{fastPathInstruction}}", () => {
|
|
19
|
+
const prompt = promptSrc();
|
|
20
|
+
assert.ok(
|
|
21
|
+
prompt.includes("{{fastPathInstruction}}"),
|
|
22
|
+
"guided-discuss-milestone.md must contain {{fastPathInstruction}} template variable",
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("2. dispatchDiscussForMilestone computes fastPathInstruction and passes it to loadPrompt", () => {
|
|
27
|
+
const source = guidedFlowSrc();
|
|
28
|
+
const fnStart = source.indexOf("async function dispatchDiscussForMilestone(");
|
|
29
|
+
assert.ok(fnStart > 0, "dispatchDiscussForMilestone must exist");
|
|
30
|
+
const fnEnd = source.indexOf("\nasync function ", fnStart + 1);
|
|
31
|
+
const fnBody = fnEnd > 0 ? source.slice(fnStart, fnEnd) : source.slice(fnStart, fnStart + 2000);
|
|
32
|
+
assert.ok(
|
|
33
|
+
fnBody.includes("fastPathInstruction"),
|
|
34
|
+
"dispatchDiscussForMilestone must compute fastPathInstruction",
|
|
35
|
+
);
|
|
36
|
+
assert.ok(
|
|
37
|
+
fnBody.includes("loadPrompt("),
|
|
38
|
+
"dispatchDiscussForMilestone must call loadPrompt",
|
|
39
|
+
);
|
|
40
|
+
const loadPromptIdx = fnBody.indexOf("loadPrompt(");
|
|
41
|
+
const fastPathIdx = fnBody.indexOf("fastPathInstruction", loadPromptIdx);
|
|
42
|
+
assert.ok(
|
|
43
|
+
fastPathIdx > loadPromptIdx,
|
|
44
|
+
"fastPathInstruction must be passed to loadPrompt in dispatchDiscussForMilestone",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("3. fast path instruction mentions scouting and conflict checking", () => {
|
|
49
|
+
const source = guidedFlowSrc();
|
|
50
|
+
assert.ok(
|
|
51
|
+
source.includes("scouting pass"),
|
|
52
|
+
"fast path instruction must mention scouting pass",
|
|
53
|
+
);
|
|
54
|
+
assert.ok(
|
|
55
|
+
source.includes("conflicts with existing work"),
|
|
56
|
+
"fast path instruction must mention conflict checking",
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("4. showDiscussQueuedMilestone shows a mode picker when no draft", () => {
|
|
61
|
+
const source = guidedFlowSrc();
|
|
62
|
+
const fnStart = source.indexOf("async function showDiscussQueuedMilestone(");
|
|
63
|
+
assert.ok(fnStart > 0, "showDiscussQueuedMilestone must exist");
|
|
64
|
+
const fnEnd = source.indexOf("\nasync function ", fnStart + 1);
|
|
65
|
+
const fnBody = fnEnd > 0 ? source.slice(fnStart, fnEnd) : source.slice(fnStart, fnStart + 3000);
|
|
66
|
+
assert.ok(
|
|
67
|
+
fnBody.includes("hasDraft"),
|
|
68
|
+
"showDiscussQueuedMilestone must check hasDraft",
|
|
69
|
+
);
|
|
70
|
+
assert.ok(
|
|
71
|
+
fnBody.includes('"full"') || fnBody.includes("\"full\""),
|
|
72
|
+
"showDiscussQueuedMilestone must offer a 'full' discussion mode",
|
|
73
|
+
);
|
|
74
|
+
assert.ok(
|
|
75
|
+
fnBody.includes('"fast"') || fnBody.includes("\"fast\""),
|
|
76
|
+
"showDiscussQueuedMilestone must offer a 'fast' path mode",
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("5. showDiscussQueuedMilestone fast-paths automatically when draft exists", () => {
|
|
81
|
+
const source = guidedFlowSrc();
|
|
82
|
+
const fnStart = source.indexOf("async function showDiscussQueuedMilestone(");
|
|
83
|
+
assert.ok(fnStart > 0, "showDiscussQueuedMilestone must exist");
|
|
84
|
+
const fnEnd = source.indexOf("\nasync function ", fnStart + 1);
|
|
85
|
+
const fnBody = fnEnd > 0 ? source.slice(fnStart, fnEnd) : source.slice(fnStart, fnStart + 3000);
|
|
86
|
+
assert.ok(
|
|
87
|
+
fnBody.includes("let fastPath = hasDraft"),
|
|
88
|
+
"showDiscussQueuedMilestone must set fastPath = hasDraft so draft presence auto-enables fast path",
|
|
89
|
+
);
|
|
90
|
+
assert.ok(
|
|
91
|
+
fnBody.includes("if (!hasDraft)"),
|
|
92
|
+
"showDiscussQueuedMilestone must skip the mode picker when hasDraft is true",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("6. dispatchDiscussForMilestone accepts opts with fastPath parameter", () => {
|
|
97
|
+
const source = guidedFlowSrc();
|
|
98
|
+
const fnStart = source.indexOf("async function dispatchDiscussForMilestone(");
|
|
99
|
+
assert.ok(fnStart > 0, "dispatchDiscussForMilestone must exist");
|
|
100
|
+
const signatureEnd = source.indexOf("): Promise<void>", fnStart);
|
|
101
|
+
const signature = source.slice(fnStart, signatureEnd + 16);
|
|
102
|
+
assert.ok(
|
|
103
|
+
signature.includes("opts") && signature.includes("fastPath"),
|
|
104
|
+
"dispatchDiscussForMilestone must accept opts: { fastPath?: boolean } parameter",
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getReadyTasks,
|
|
6
6
|
chooseNonConflictingSubset,
|
|
7
7
|
isGraphAmbiguous,
|
|
8
|
+
getMissingAnnotationTasks,
|
|
8
9
|
detectDeadlock,
|
|
9
10
|
graphMetrics,
|
|
10
11
|
} from "../reactive-graph.ts";
|
|
@@ -297,3 +298,47 @@ test("graphMetrics computes correct values", () => {
|
|
|
297
298
|
assert.equal(metrics.readySetSize, 2); // T02 (T01 done) and T03 (no deps)
|
|
298
299
|
assert.equal(metrics.ambiguous, false);
|
|
299
300
|
});
|
|
301
|
+
|
|
302
|
+
// ─── getMissingAnnotationTasks ─────────────────────────────────────────────
|
|
303
|
+
|
|
304
|
+
test("getMissingAnnotationTasks: returns empty array when all tasks have annotations", () => {
|
|
305
|
+
const graph: DerivedTaskNode[] = [
|
|
306
|
+
{ id: "T01", title: "A", inputFiles: ["src/a.ts"], outputFiles: ["src/b.ts"], done: false, dependsOn: [] },
|
|
307
|
+
{ id: "T02", title: "B", inputFiles: [], outputFiles: ["src/c.ts"], done: false, dependsOn: [] },
|
|
308
|
+
];
|
|
309
|
+
assert.deepEqual(getMissingAnnotationTasks(graph), []);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("getMissingAnnotationTasks: returns tasks with missing annotations", () => {
|
|
313
|
+
const graph: DerivedTaskNode[] = [
|
|
314
|
+
{ id: "T01", title: "A", inputFiles: [], outputFiles: [], done: false, dependsOn: [] },
|
|
315
|
+
{ id: "T02", title: "B", inputFiles: ["src/a.ts"], outputFiles: ["src/b.ts"], done: false, dependsOn: [] },
|
|
316
|
+
{ id: "T03", title: "C", inputFiles: [], outputFiles: [], done: false, dependsOn: [] },
|
|
317
|
+
];
|
|
318
|
+
assert.deepEqual(getMissingAnnotationTasks(graph), [
|
|
319
|
+
{ id: "T01", title: "A" },
|
|
320
|
+
{ id: "T03", title: "C" },
|
|
321
|
+
]);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test("getMissingAnnotationTasks: skips done tasks", () => {
|
|
325
|
+
const graph: DerivedTaskNode[] = [
|
|
326
|
+
{ id: "T01", title: "A", inputFiles: [], outputFiles: [], done: true, dependsOn: [] },
|
|
327
|
+
{ id: "T02", title: "B", inputFiles: [], outputFiles: [], done: false, dependsOn: [] },
|
|
328
|
+
];
|
|
329
|
+
assert.deepEqual(getMissingAnnotationTasks(graph), [
|
|
330
|
+
{ id: "T02", title: "B" },
|
|
331
|
+
]);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test("getMissingAnnotationTasks: returns only tasks missing BOTH inputFiles and outputFiles", () => {
|
|
335
|
+
const graph: DerivedTaskNode[] = [
|
|
336
|
+
{ id: "T01", title: "InputOnly", inputFiles: ["src/a.ts"], outputFiles: [], done: false, dependsOn: [] },
|
|
337
|
+
{ id: "T02", title: "OutputOnly", inputFiles: [], outputFiles: ["src/b.ts"], done: false, dependsOn: [] },
|
|
338
|
+
{ id: "T03", title: "Neither", inputFiles: [], outputFiles: [], done: false, dependsOn: [] },
|
|
339
|
+
{ id: "T04", title: "Both", inputFiles: ["src/c.ts"], outputFiles: ["src/d.ts"], done: false, dependsOn: [] },
|
|
340
|
+
];
|
|
341
|
+
assert.deepEqual(getMissingAnnotationTasks(graph), [
|
|
342
|
+
{ id: "T03", title: "Neither" },
|
|
343
|
+
]);
|
|
344
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3628 — restore tool set after discuss flow scoping
|
|
3
|
+
*
|
|
4
|
+
* The discuss flow narrows the active tool set to avoid "grammar too complex"
|
|
5
|
+
* errors. Without restoring after sendMessage, the narrowed tools leaked into
|
|
6
|
+
* subsequent dispatches, breaking plan/execute flows.
|
|
7
|
+
*
|
|
8
|
+
* The fix saves the full tool set before scoping and restores it after
|
|
9
|
+
* sendMessage returns.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, it } from 'node:test'
|
|
13
|
+
import assert from 'node:assert/strict'
|
|
14
|
+
import { readFileSync } from 'node:fs'
|
|
15
|
+
import { resolve } from 'node:path'
|
|
16
|
+
|
|
17
|
+
const src = readFileSync(
|
|
18
|
+
resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'guided-flow.ts'),
|
|
19
|
+
'utf-8',
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
describe('restore tools after discuss flow scoping (#3628)', () => {
|
|
23
|
+
it('savedTools is declared before the discuss scoping block', () => {
|
|
24
|
+
// savedTools must be declared before the discuss-* check
|
|
25
|
+
const savedToolsDecl = src.indexOf('let savedTools')
|
|
26
|
+
const discussCheck = src.indexOf('if (unitType?.startsWith("discuss-"))')
|
|
27
|
+
assert.ok(savedToolsDecl !== -1, 'savedTools variable must be declared')
|
|
28
|
+
assert.ok(discussCheck !== -1, 'discuss-* type check must exist')
|
|
29
|
+
assert.ok(
|
|
30
|
+
savedToolsDecl < discussCheck,
|
|
31
|
+
'savedTools must be declared before the discuss scoping block',
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('savedTools captures current tools inside the discuss block', () => {
|
|
36
|
+
const discussCheck = src.indexOf('if (unitType?.startsWith("discuss-"))')
|
|
37
|
+
assert.ok(discussCheck !== -1)
|
|
38
|
+
|
|
39
|
+
// Look for savedTools assignment within the discuss block
|
|
40
|
+
const blockAfter = src.slice(discussCheck, discussCheck + 500)
|
|
41
|
+
assert.ok(
|
|
42
|
+
blockAfter.includes('savedTools = currentTools'),
|
|
43
|
+
'savedTools must be assigned from currentTools inside the discuss block',
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('savedTools is restored after sendMessage', () => {
|
|
48
|
+
// Find the sendMessage call
|
|
49
|
+
const sendMsg = src.indexOf('triggerTurn: true')
|
|
50
|
+
assert.ok(sendMsg !== -1, 'sendMessage with triggerTurn must exist')
|
|
51
|
+
|
|
52
|
+
// After sendMessage, savedTools should be restored via setActiveTools
|
|
53
|
+
const afterSend = src.slice(sendMsg, sendMsg + 500)
|
|
54
|
+
assert.ok(
|
|
55
|
+
afterSend.includes('if (savedTools)'),
|
|
56
|
+
'savedTools restoration guard must exist after sendMessage',
|
|
57
|
+
)
|
|
58
|
+
assert.ok(
|
|
59
|
+
afterSend.includes('setActiveTools(savedTools)'),
|
|
60
|
+
'setActiveTools(savedTools) must be called to restore the full tool set',
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
})
|
|
@@ -149,7 +149,7 @@ test("rogue detection: DB not available → returns empty array (graceful degrad
|
|
|
149
149
|
}
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
test("rogue detection: slice summary on disk, no DB row →
|
|
152
|
+
test("rogue detection: slice summary on disk, no DB row → auto-remediated (not rogue)", () => {
|
|
153
153
|
const basePath = createTmpBase();
|
|
154
154
|
const dbPath = join(basePath, ".gsd", "gsd.db");
|
|
155
155
|
mkdirSync(join(basePath, ".gsd"), { recursive: true });
|
|
@@ -160,11 +160,10 @@ test("rogue detection: slice summary on disk, no DB row → detected as rogue",
|
|
|
160
160
|
const summaryPath = createSliceSummaryOnDisk(basePath, "M001", "S01");
|
|
161
161
|
assert.ok(existsSync(summaryPath), "Slice summary file should exist on disk");
|
|
162
162
|
|
|
163
|
+
// Fix #3633: stale slice DB status is auto-remediated via updateSliceStatus()
|
|
164
|
+
// instead of being reported as rogue, so rogues array should be empty.
|
|
163
165
|
const rogues = detectRogueFileWrites("complete-slice", "M001/S01", basePath);
|
|
164
|
-
assert.equal(rogues.length,
|
|
165
|
-
assert.equal(rogues[0].path, summaryPath);
|
|
166
|
-
assert.equal(rogues[0].unitType, "complete-slice");
|
|
167
|
-
assert.equal(rogues[0].unitId, "M001/S01");
|
|
166
|
+
assert.equal(rogues.length, 0, "Should auto-remediate stale slice, not report as rogue");
|
|
168
167
|
} finally {
|
|
169
168
|
closeDatabase();
|
|
170
169
|
rmSync(basePath, { recursive: true, force: true });
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3624 — cap run-uat dispatch attempts
|
|
3
|
+
*
|
|
4
|
+
* When verification commands fail before writing a verdict, the run-uat
|
|
5
|
+
* dispatch rule fires repeatedly in an infinite loop. The fix adds a
|
|
6
|
+
* MAX_UAT_ATTEMPTS constant and calls incrementUatCount before dispatch
|
|
7
|
+
* to cap the number of attempts.
|
|
8
|
+
*
|
|
9
|
+
* Structural verification test — reads source to confirm MAX_UAT_ATTEMPTS
|
|
10
|
+
* and incrementUatCount exist.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test } from 'node:test';
|
|
14
|
+
import assert from 'node:assert/strict';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { dirname, join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
|
|
22
|
+
const source = readFileSync(join(__dirname, '..', 'auto-dispatch.ts'), 'utf-8');
|
|
23
|
+
|
|
24
|
+
describe('run-uat replay cap (#3624)', () => {
|
|
25
|
+
test('MAX_UAT_ATTEMPTS constant is defined', () => {
|
|
26
|
+
assert.match(source, /const MAX_UAT_ATTEMPTS\s*=\s*\d+/,
|
|
27
|
+
'MAX_UAT_ATTEMPTS constant should be defined');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('incrementUatCount function is exported', () => {
|
|
31
|
+
assert.match(source, /export function incrementUatCount\(/,
|
|
32
|
+
'incrementUatCount should be an exported function');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('getUatCount function is exported', () => {
|
|
36
|
+
assert.match(source, /export function getUatCount\(/,
|
|
37
|
+
'getUatCount should be an exported function');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('incrementUatCount is called before dispatch in rule', () => {
|
|
41
|
+
// incrementUatCount should be called before the dispatch return
|
|
42
|
+
const ruleSection = source.slice(source.indexOf('checkNeedsRunUat'));
|
|
43
|
+
assert.match(ruleSection, /incrementUatCount\(/,
|
|
44
|
+
'incrementUatCount should be called in the dispatch rule');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('attempts are compared against MAX_UAT_ATTEMPTS', () => {
|
|
48
|
+
assert.match(source, /attempts\s*>\s*MAX_UAT_ATTEMPTS/,
|
|
49
|
+
'dispatch should check attempts > MAX_UAT_ATTEMPTS');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /gsd show-config command — structural tests.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the config overlay class and command handler exist
|
|
5
|
+
* with correct structure.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { join, dirname } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
|
|
16
|
+
const overlaySrc = readFileSync(join(__dirname, "..", "config-overlay.ts"), "utf-8");
|
|
17
|
+
const coreSrc = readFileSync(join(__dirname, "..", "commands", "handlers", "core.ts"), "utf-8");
|
|
18
|
+
|
|
19
|
+
// ─── Config overlay ───────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
test("GSDConfigOverlay class is exported", () => {
|
|
22
|
+
assert.ok(
|
|
23
|
+
overlaySrc.includes("export class GSDConfigOverlay"),
|
|
24
|
+
"GSDConfigOverlay should be exported",
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("GSDConfigOverlay implements Component interface methods", () => {
|
|
29
|
+
assert.ok(overlaySrc.includes("render("), "should have render method");
|
|
30
|
+
assert.ok(overlaySrc.includes("handleInput("), "should have handleInput method");
|
|
31
|
+
assert.ok(overlaySrc.includes("invalidate("), "should have invalidate method");
|
|
32
|
+
assert.ok(overlaySrc.includes("dispose("), "should have dispose method");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("formatConfigText function is exported", () => {
|
|
36
|
+
assert.ok(
|
|
37
|
+
overlaySrc.includes("export function formatConfigText"),
|
|
38
|
+
"formatConfigText should be exported for non-overlay fallback",
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ─── Command handler ──────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
test("core handler routes show-config command", () => {
|
|
45
|
+
assert.ok(
|
|
46
|
+
coreSrc.includes('"show-config"'),
|
|
47
|
+
"core handler should match show-config command",
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("show-config has text fallback via formatConfigText", () => {
|
|
52
|
+
assert.ok(
|
|
53
|
+
coreSrc.includes("formatConfigText"),
|
|
54
|
+
"show-config should use formatConfigText as fallback",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3477: gsd_skip_slice tool must rebuild STATE.md
|
|
3
|
+
* after updating the DB so auto-mode reads the correct state.
|
|
4
|
+
*/
|
|
5
|
+
import { test } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
test("gsd_skip_slice tool calls rebuildState after DB update (#3477)", () => {
|
|
11
|
+
const src = readFileSync(
|
|
12
|
+
join(import.meta.dirname, "..", "bootstrap", "db-tools.ts"),
|
|
13
|
+
"utf-8",
|
|
14
|
+
);
|
|
15
|
+
// The fix adds a rebuildState call after updateSliceStatus in skip_slice
|
|
16
|
+
assert.ok(
|
|
17
|
+
src.includes("rebuildState"),
|
|
18
|
+
"gsd_skip_slice must call rebuildState after updating slice status",
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("rethink prompt warns against markdown-only edits for skip (#3477)", () => {
|
|
23
|
+
const prompt = readFileSync(
|
|
24
|
+
join(import.meta.dirname, "..", "prompts", "rethink.md"),
|
|
25
|
+
"utf-8",
|
|
26
|
+
);
|
|
27
|
+
assert.ok(
|
|
28
|
+
prompt.includes("MUST") && prompt.includes("gsd_skip_slice"),
|
|
29
|
+
"Rethink prompt must emphasize gsd_skip_slice tool requirement",
|
|
30
|
+
);
|
|
31
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3698 — allow milestone completion when validation
|
|
3
|
+
* was skipped by preference
|
|
4
|
+
*
|
|
5
|
+
* When validation is skipped due to user preference (e.g. budget profile),
|
|
6
|
+
* auto-dispatch should recognize the "skipped by preference" pattern and
|
|
7
|
+
* allow completion instead of treating it as a missing validation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, test } from 'node:test';
|
|
11
|
+
import assert from 'node:assert/strict';
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
|
|
19
|
+
const autoDispatchSrc = readFileSync(
|
|
20
|
+
join(__dirname, '..', 'auto-dispatch.ts'),
|
|
21
|
+
'utf-8',
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
describe('skipped validation completion (#3698)', () => {
|
|
25
|
+
test('skippedByPreference regex detection exists', () => {
|
|
26
|
+
assert.match(autoDispatchSrc, /skippedByPreference/,
|
|
27
|
+
'skippedByPreference variable should exist in auto-dispatch.ts');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('regex matches skip-by-preference patterns', () => {
|
|
31
|
+
assert.match(autoDispatchSrc, /skip\(\?:ped\)\?\[\\s\\-\]\+\(\?:by\|per\|due to\)/,
|
|
32
|
+
'should have regex matching "skipped by/per/due to" patterns');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('skippedByPreference feeds into operational check', () => {
|
|
36
|
+
assert.match(autoDispatchSrc, /hasOperationalCheck\s*=\s*skippedByPreference/,
|
|
37
|
+
'skippedByPreference should be part of hasOperationalCheck');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3697 — set slice sequence on insert
|
|
3
|
+
*
|
|
4
|
+
* All three insertSlice call sites must pass a sequence value so slices
|
|
5
|
+
* are ordered correctly instead of defaulting to 0.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, test } from 'node:test';
|
|
9
|
+
import assert from 'node:assert/strict';
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { dirname, join } from 'node:path';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
|
|
17
|
+
const planMilestoneSrc = readFileSync(
|
|
18
|
+
join(__dirname, '..', 'tools', 'plan-milestone.ts'),
|
|
19
|
+
'utf-8',
|
|
20
|
+
);
|
|
21
|
+
const reassessRoadmapSrc = readFileSync(
|
|
22
|
+
join(__dirname, '..', 'tools', 'reassess-roadmap.ts'),
|
|
23
|
+
'utf-8',
|
|
24
|
+
);
|
|
25
|
+
const mdImporterSrc = readFileSync(
|
|
26
|
+
join(__dirname, '..', 'md-importer.ts'),
|
|
27
|
+
'utf-8',
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
describe('slice sequence on insert (#3697)', () => {
|
|
31
|
+
test('plan-milestone.ts passes sequence to insertSlice', () => {
|
|
32
|
+
assert.match(planMilestoneSrc, /insertSlice\(/,
|
|
33
|
+
'plan-milestone.ts should call insertSlice');
|
|
34
|
+
assert.match(planMilestoneSrc, /sequence:\s*i\s*\+\s*1/,
|
|
35
|
+
'plan-milestone.ts should pass sequence: i + 1');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('reassess-roadmap.ts passes sequence to insertSlice', () => {
|
|
39
|
+
assert.match(reassessRoadmapSrc, /insertSlice\(/,
|
|
40
|
+
'reassess-roadmap.ts should call insertSlice');
|
|
41
|
+
assert.match(reassessRoadmapSrc, /sequence:\s*existingCount\s*\+\s*i\s*\+\s*1/,
|
|
42
|
+
'reassess-roadmap.ts should pass sequence: existingCount + i + 1');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('md-importer.ts passes sequence to insertSlice', () => {
|
|
46
|
+
assert.match(mdImporterSrc, /insertSlice\(/,
|
|
47
|
+
'md-importer.ts should call insertSlice');
|
|
48
|
+
assert.match(mdImporterSrc, /sequence:\s*si\s*\+\s*1/,
|
|
49
|
+
'md-importer.ts should pass sequence: si + 1');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -49,5 +49,5 @@ test("guided-flow complete branch offers a chooser for next milestone or status"
|
|
|
49
49
|
assert.match(branchChunk, /showNextAction\(/, "complete branch should present a chooser");
|
|
50
50
|
assert.match(branchChunk, /findMilestoneIds\(basePath\)/, "complete branch should compute the next milestone id");
|
|
51
51
|
assert.match(branchChunk, /nextMilestoneId(?:Reserved)?\(milestoneIds, uniqueMilestoneIds\)/, "complete branch should derive the next milestone id");
|
|
52
|
-
assert.match(branchChunk, /dispatchWorkflow\(pi,
|
|
52
|
+
assert.match(branchChunk, /dispatchWorkflow\(pi, await prepareAndBuildDiscussPrompt\(/, "complete branch should dispatch the prepared discuss prompt");
|
|
53
53
|
});
|