gsd-pi 2.65.0-dev.5c8557b → 2.65.0-dev.6cc5110
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 +4 -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 +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +220 -29
- 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/guided-discuss-milestone.md +4 -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/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 +112 -22
- 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-logger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
- 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 +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/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 +4 -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 +13 -2
- package/src/resources/extensions/gsd/guided-flow.ts +254 -30
- 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/guided-discuss-milestone.md +4 -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/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 +112 -20
- 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/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/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 +1 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
- 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 → iueakR5x5bQbax2sGz8Yr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{qq3YfHPfyqvh3DIMVmsRH → iueakR5x5bQbax2sGz8Yr}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel research slices dispatch — structural tests.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the dispatch rule and prompt builder exist with correct structure.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { join, dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
|
|
15
|
+
const dispatchSrc = readFileSync(join(__dirname, "..", "auto-dispatch.ts"), "utf-8");
|
|
16
|
+
const promptsSrc = readFileSync(join(__dirname, "..", "auto-prompts.ts"), "utf-8");
|
|
17
|
+
const templatePath = join(__dirname, "..", "prompts", "parallel-research-slices.md");
|
|
18
|
+
const templateSrc = readFileSync(templatePath, "utf-8");
|
|
19
|
+
|
|
20
|
+
// ─── Dispatch rule ────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
test("dispatch: parallel-research-slices rule exists", () => {
|
|
23
|
+
assert.ok(
|
|
24
|
+
dispatchSrc.includes("parallel-research-slices"),
|
|
25
|
+
"dispatch table should have parallel-research-slices rule",
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("dispatch: parallel-research-slices requires 2+ slices", () => {
|
|
30
|
+
assert.ok(
|
|
31
|
+
dispatchSrc.includes("researchReadySlices.length < 2"),
|
|
32
|
+
"rule should require at least 2 slices for parallel dispatch",
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("dispatch: parallel-research-slices respects skip_research", () => {
|
|
37
|
+
const ruleIdx = dispatchSrc.indexOf("parallel-research-slices");
|
|
38
|
+
const ruleBlock = dispatchSrc.slice(ruleIdx, ruleIdx + 500);
|
|
39
|
+
assert.ok(
|
|
40
|
+
ruleBlock.includes("skip_research") || dispatchSrc.slice(ruleIdx - 300, ruleIdx).includes("skip_research"),
|
|
41
|
+
"rule should check skip_research preference",
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// ─── Prompt builder ───────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
test("prompt: buildParallelResearchSlicesPrompt exported", () => {
|
|
48
|
+
assert.ok(
|
|
49
|
+
promptsSrc.includes("export async function buildParallelResearchSlicesPrompt"),
|
|
50
|
+
"buildParallelResearchSlicesPrompt should be exported",
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("prompt: builds per-slice subagent prompts", () => {
|
|
55
|
+
assert.ok(
|
|
56
|
+
promptsSrc.includes("buildResearchSlicePrompt"),
|
|
57
|
+
"parallel prompt builder should delegate to per-slice research prompts",
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// ─── Template ─────────────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
test("template: parallel-research-slices.md has required variables", () => {
|
|
64
|
+
assert.ok(templateSrc.includes("{{sliceCount}}"), "template should use sliceCount");
|
|
65
|
+
assert.ok(templateSrc.includes("{{mid}}"), "template should use mid");
|
|
66
|
+
assert.ok(templateSrc.includes("{{subagentPrompts}}"), "template should use subagentPrompts");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ─── Validate milestone prompt ────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
test("template: validate-milestone uses parallel reviewers", () => {
|
|
72
|
+
const validateSrc = readFileSync(join(__dirname, "..", "prompts", "validate-milestone.md"), "utf-8");
|
|
73
|
+
assert.ok(
|
|
74
|
+
validateSrc.includes("Reviewer A") && validateSrc.includes("Reviewer B") && validateSrc.includes("Reviewer C"),
|
|
75
|
+
"validate-milestone should dispatch 3 parallel reviewers",
|
|
76
|
+
);
|
|
77
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3671 — isGhostMilestone detects phantom queued rows
|
|
3
|
+
*
|
|
4
|
+
* gsd_milestone_generate_id inserts a DB row with status "queued" as a side
|
|
5
|
+
* effect. If the milestone is never planned, isGhostMilestone previously
|
|
6
|
+
* returned false for any milestone with a DB row, blocking the state machine.
|
|
7
|
+
*
|
|
8
|
+
* The fix makes isGhostMilestone treat a "queued" DB row with no disk
|
|
9
|
+
* artifacts (CONTEXT, ROADMAP, SUMMARY) as a ghost.
|
|
10
|
+
*
|
|
11
|
+
* This structural test verifies the dbRow.status === 'queued' guard exists.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, test } from 'node:test';
|
|
15
|
+
import assert from 'node:assert/strict';
|
|
16
|
+
import { readFileSync } from 'node:fs';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
|
|
20
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
+
const __dirname = dirname(__filename);
|
|
22
|
+
|
|
23
|
+
const source = readFileSync(join(__dirname, '..', 'state.ts'), 'utf-8');
|
|
24
|
+
|
|
25
|
+
describe('isGhostMilestone phantom queued detection (#3671)', () => {
|
|
26
|
+
test('isGhostMilestone function exists', () => {
|
|
27
|
+
assert.match(source, /export function isGhostMilestone\(/,
|
|
28
|
+
'isGhostMilestone should be exported');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('checks dbRow.status === queued', () => {
|
|
32
|
+
assert.match(source, /dbRow\.status\s*===\s*['"]queued['"]/,
|
|
33
|
+
'isGhostMilestone should check dbRow.status === "queued"');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('checks for CONTEXT disk artifact', () => {
|
|
37
|
+
assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']CONTEXT["']\)/,
|
|
38
|
+
'should check for CONTEXT file');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('checks for ROADMAP disk artifact', () => {
|
|
42
|
+
assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']ROADMAP["']\)/,
|
|
43
|
+
'should check for ROADMAP file');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('checks for SUMMARY disk artifact', () => {
|
|
47
|
+
assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']SUMMARY["']\)/,
|
|
48
|
+
'should check for SUMMARY file');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('returns !hasContent for queued rows (ghost if no artifacts)', () => {
|
|
52
|
+
assert.match(source, /return !hasContent/,
|
|
53
|
+
'should return !hasContent for queued phantom milestones');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3695 — insertMilestone defaults status to "queued"
|
|
3
|
+
*
|
|
4
|
+
* Milestones were being auto-created with status "active", causing phantom
|
|
5
|
+
* milestones to appear as active work. The fix defaults to "queued" so
|
|
6
|
+
* new milestones must be explicitly activated.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, test } from 'node:test';
|
|
10
|
+
import assert from 'node:assert/strict';
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { dirname, join } from 'node:path';
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
|
|
18
|
+
const dbSrc = readFileSync(
|
|
19
|
+
join(__dirname, '..', 'gsd-db.ts'),
|
|
20
|
+
'utf-8',
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
describe('insertMilestone defaults status to queued (#3695)', () => {
|
|
24
|
+
test('insertMilestone function exists', () => {
|
|
25
|
+
assert.match(dbSrc, /export function insertMilestone\(/,
|
|
26
|
+
'insertMilestone should be exported from gsd-db.ts');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('default status is "queued" not "active"', () => {
|
|
30
|
+
// The status parameter should default to "queued" via nullish coalescing
|
|
31
|
+
assert.match(dbSrc, /m\.status\s*\?\?\s*"queued"/,
|
|
32
|
+
'insertMilestone should default status to "queued"');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('comment explains the rationale', () => {
|
|
36
|
+
assert.match(dbSrc, /never auto-create milestones as "active"/i,
|
|
37
|
+
'should have a comment explaining why default is queued');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for #3626 / #3649 — pre-execution-checks false positives
|
|
3
|
+
*
|
|
4
|
+
* Two sources of false positives were fixed:
|
|
5
|
+
* 1. normalizeFilePath did not strip backtick wrapping from LLM-generated
|
|
6
|
+
* paths like `src/foo.ts`, causing file-existence checks to fail (#3649).
|
|
7
|
+
* 2. checkFilePathConsistency checked both task.files and task.inputs, but
|
|
8
|
+
* task.files ("files likely touched") intentionally includes files that
|
|
9
|
+
* will be created by the task, so they don't need to pre-exist (#3626).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, it } from 'node:test'
|
|
13
|
+
import assert from 'node:assert/strict'
|
|
14
|
+
import { normalizeFilePath, checkFilePathConsistency } from '../pre-execution-checks.ts'
|
|
15
|
+
import { readFileSync } from 'node:fs'
|
|
16
|
+
import { resolve } from 'node:path'
|
|
17
|
+
|
|
18
|
+
const src = readFileSync(
|
|
19
|
+
resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'pre-execution-checks.ts'),
|
|
20
|
+
'utf-8',
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
describe('normalizeFilePath backtick stripping (#3649)', () => {
|
|
24
|
+
it('strips backticks from file paths', () => {
|
|
25
|
+
assert.equal(normalizeFilePath('`src/foo.ts`'), 'src/foo.ts')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('strips backticks even when mixed with other normalization', () => {
|
|
29
|
+
assert.equal(normalizeFilePath('`./src//bar.ts`'), 'src/bar.ts')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('leaves normal paths unchanged', () => {
|
|
33
|
+
assert.equal(normalizeFilePath('src/foo.ts'), 'src/foo.ts')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('handles empty string', () => {
|
|
37
|
+
assert.equal(normalizeFilePath(''), '')
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('checkFilePathConsistency checks task.inputs not task.files (#3626)', () => {
|
|
42
|
+
it('source uses only task.inputs in filesToCheck', () => {
|
|
43
|
+
// Verify the fix structurally: the spread should be [...task.inputs] only
|
|
44
|
+
const fnStart = src.indexOf('export function checkFilePathConsistency(')
|
|
45
|
+
assert.ok(fnStart !== -1, 'checkFilePathConsistency function must exist')
|
|
46
|
+
|
|
47
|
+
// Find the filesToCheck assignment
|
|
48
|
+
const filesToCheckLine = src.indexOf('filesToCheck', fnStart)
|
|
49
|
+
assert.ok(filesToCheckLine !== -1, 'filesToCheck assignment must exist')
|
|
50
|
+
|
|
51
|
+
// Extract the line
|
|
52
|
+
const lineEnd = src.indexOf('\n', filesToCheckLine)
|
|
53
|
+
const line = src.slice(filesToCheckLine, lineEnd)
|
|
54
|
+
|
|
55
|
+
// Must include task.inputs
|
|
56
|
+
assert.ok(
|
|
57
|
+
line.includes('task.inputs'),
|
|
58
|
+
'filesToCheck must reference task.inputs',
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
// Must NOT include task.files
|
|
62
|
+
assert.ok(
|
|
63
|
+
!line.includes('task.files'),
|
|
64
|
+
'filesToCheck must NOT reference task.files — files likely touched include ' +
|
|
65
|
+
'files the task will create, so they do not need to pre-exist',
|
|
66
|
+
)
|
|
67
|
+
})
|
|
68
|
+
})
|
|
@@ -193,7 +193,7 @@ describe("checkFilePathConsistency", () => {
|
|
|
193
193
|
}
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
-
test("fails when
|
|
196
|
+
test("fails when inputs don't exist and not in prior outputs", () => {
|
|
197
197
|
tempDir = join(tmpdir(), `pre-exec-test-${Date.now()}`);
|
|
198
198
|
mkdirSync(tempDir, { recursive: true });
|
|
199
199
|
|
|
@@ -201,8 +201,8 @@ describe("checkFilePathConsistency", () => {
|
|
|
201
201
|
const tasks = [
|
|
202
202
|
createTask({
|
|
203
203
|
id: "T01",
|
|
204
|
-
files: [
|
|
205
|
-
inputs: [],
|
|
204
|
+
files: [],
|
|
205
|
+
inputs: ["nonexistent.ts"],
|
|
206
206
|
expected_output: [],
|
|
207
207
|
}),
|
|
208
208
|
];
|
|
@@ -218,7 +218,7 @@ describe("checkFilePathConsistency", () => {
|
|
|
218
218
|
}
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
test("checks
|
|
221
|
+
test("checks only inputs array, not files array", () => {
|
|
222
222
|
tempDir = join(tmpdir(), `pre-exec-test-${Date.now()}`);
|
|
223
223
|
mkdirSync(tempDir, { recursive: true });
|
|
224
224
|
|
|
@@ -232,10 +232,13 @@ describe("checkFilePathConsistency", () => {
|
|
|
232
232
|
}),
|
|
233
233
|
];
|
|
234
234
|
|
|
235
|
+
// Only inputs are checked — files ("files likely touched") are excluded
|
|
236
|
+
// because they may include files the task will create (#3626)
|
|
235
237
|
const results = checkFilePathConsistency(tasks, tempDir);
|
|
236
|
-
assert.equal(results.length,
|
|
237
|
-
assert.ok(results.some((r) => r.target === "missing-file.ts"));
|
|
238
|
+
assert.equal(results.length, 1);
|
|
238
239
|
assert.ok(results.some((r) => r.target === "missing-input.ts"));
|
|
240
|
+
// missing-file.ts should NOT produce a failure
|
|
241
|
+
assert.ok(!results.some((r) => r.target === "missing-file.ts"));
|
|
239
242
|
} finally {
|
|
240
243
|
rmSync(tempDir, { recursive: true, force: true });
|
|
241
244
|
}
|
|
@@ -388,13 +391,13 @@ describe("checkFilePathConsistency with path normalization", () => {
|
|
|
388
391
|
});
|
|
389
392
|
|
|
390
393
|
describe("checkTaskOrdering with path normalization", () => {
|
|
391
|
-
test("./path triggers ordering check for path in expected_output", () => {
|
|
394
|
+
test("./path in inputs triggers ordering check for path in expected_output", () => {
|
|
392
395
|
const tasks = [
|
|
393
396
|
createTask({
|
|
394
397
|
id: "T01",
|
|
395
398
|
sequence: 0,
|
|
396
|
-
files: [
|
|
397
|
-
inputs: [],
|
|
399
|
+
files: [],
|
|
400
|
+
inputs: ["./generated.ts"], // Reads with ./
|
|
398
401
|
expected_output: [],
|
|
399
402
|
}),
|
|
400
403
|
createTask({
|
|
@@ -412,13 +415,13 @@ describe("checkTaskOrdering with path normalization", () => {
|
|
|
412
415
|
assert.ok(results[0].message.includes("T02"));
|
|
413
416
|
});
|
|
414
417
|
|
|
415
|
-
test("path triggers ordering check for ./path in expected_output", () => {
|
|
418
|
+
test("path in inputs triggers ordering check for ./path in expected_output", () => {
|
|
416
419
|
const tasks = [
|
|
417
420
|
createTask({
|
|
418
421
|
id: "T01",
|
|
419
422
|
sequence: 0,
|
|
420
|
-
files: [
|
|
421
|
-
inputs: [],
|
|
423
|
+
files: [],
|
|
424
|
+
inputs: ["generated.ts"], // Reads without ./
|
|
422
425
|
expected_output: [],
|
|
423
426
|
}),
|
|
424
427
|
createTask({
|
|
@@ -483,13 +486,13 @@ describe("checkTaskOrdering", () => {
|
|
|
483
486
|
assert.deepEqual(results, []);
|
|
484
487
|
});
|
|
485
488
|
|
|
486
|
-
test("fails when task
|
|
489
|
+
test("fails when task inputs reference file created by later task", () => {
|
|
487
490
|
const tasks = [
|
|
488
491
|
createTask({
|
|
489
492
|
id: "T01",
|
|
490
493
|
sequence: 0,
|
|
491
|
-
files: [
|
|
492
|
-
inputs: [],
|
|
494
|
+
files: [],
|
|
495
|
+
inputs: ["generated.ts"], // Reads file that doesn't exist yet
|
|
493
496
|
expected_output: [],
|
|
494
497
|
}),
|
|
495
498
|
createTask({
|
|
@@ -534,13 +537,13 @@ describe("checkTaskOrdering", () => {
|
|
|
534
537
|
assert.ok(results[0].message.includes("schema.json"));
|
|
535
538
|
});
|
|
536
539
|
|
|
537
|
-
test("handles multiple ordering violations", () => {
|
|
540
|
+
test("handles multiple ordering violations via inputs", () => {
|
|
538
541
|
const tasks = [
|
|
539
542
|
createTask({
|
|
540
543
|
id: "T01",
|
|
541
544
|
sequence: 0,
|
|
542
|
-
files: [
|
|
543
|
-
inputs: [],
|
|
545
|
+
files: [],
|
|
546
|
+
inputs: ["a.ts", "b.ts"],
|
|
544
547
|
expected_output: [],
|
|
545
548
|
}),
|
|
546
549
|
createTask({
|
|
@@ -825,8 +828,8 @@ describe("runPreExecutionChecks", () => {
|
|
|
825
828
|
const tasks = [
|
|
826
829
|
createTask({
|
|
827
830
|
id: "T01",
|
|
828
|
-
files: [
|
|
829
|
-
inputs: [],
|
|
831
|
+
files: [],
|
|
832
|
+
inputs: ["nonexistent.ts"],
|
|
830
833
|
expected_output: [],
|
|
831
834
|
}),
|
|
832
835
|
];
|
|
@@ -952,6 +955,201 @@ function check(a: number): void
|
|
|
952
955
|
});
|
|
953
956
|
});
|
|
954
957
|
|
|
958
|
+
// ─── Regression Tests: checkTaskOrdering false positive (#3677) ──────────────
|
|
959
|
+
|
|
960
|
+
describe("checkTaskOrdering false positive regression (#3677)", () => {
|
|
961
|
+
test("task.files should not trigger ordering violation when file is in later expected_output", () => {
|
|
962
|
+
// T01 has files: ["component.tsx"] — this is a file the task will CREATE,
|
|
963
|
+
// not read. Including task.files in the ordering check causes a false positive.
|
|
964
|
+
// After fix (check only task.inputs), this should return 0 results.
|
|
965
|
+
const tasks = [
|
|
966
|
+
createTask({
|
|
967
|
+
id: "T01",
|
|
968
|
+
sequence: 0,
|
|
969
|
+
files: ["component.tsx"],
|
|
970
|
+
inputs: [],
|
|
971
|
+
expected_output: [],
|
|
972
|
+
}),
|
|
973
|
+
createTask({
|
|
974
|
+
id: "T02",
|
|
975
|
+
sequence: 1,
|
|
976
|
+
files: [],
|
|
977
|
+
inputs: [],
|
|
978
|
+
expected_output: ["component.tsx"],
|
|
979
|
+
}),
|
|
980
|
+
];
|
|
981
|
+
|
|
982
|
+
const results = checkTaskOrdering(tasks, "/tmp");
|
|
983
|
+
assert.equal(results.length, 0, "task.files should not be checked for ordering violations");
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
test("task.files with multiple files should not trigger false positives", () => {
|
|
987
|
+
// T01 lists several files it will touch/create — none should trigger ordering
|
|
988
|
+
// violations just because T02 declares one of them as expected_output.
|
|
989
|
+
const tasks = [
|
|
990
|
+
createTask({
|
|
991
|
+
id: "T01",
|
|
992
|
+
sequence: 0,
|
|
993
|
+
files: ["a.ts", "b.ts", "c.ts"],
|
|
994
|
+
inputs: [],
|
|
995
|
+
expected_output: [],
|
|
996
|
+
}),
|
|
997
|
+
createTask({
|
|
998
|
+
id: "T02",
|
|
999
|
+
sequence: 1,
|
|
1000
|
+
files: [],
|
|
1001
|
+
inputs: [],
|
|
1002
|
+
expected_output: ["b.ts"],
|
|
1003
|
+
}),
|
|
1004
|
+
];
|
|
1005
|
+
|
|
1006
|
+
const results = checkTaskOrdering(tasks, "/tmp");
|
|
1007
|
+
assert.equal(results.length, 0, "Multiple task.files should not generate false positive violations");
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
test("task.inputs SHOULD still trigger ordering violation", () => {
|
|
1011
|
+
// task.inputs represents files a task genuinely needs to READ, so a sequence
|
|
1012
|
+
// violation here is a real error and must still be detected.
|
|
1013
|
+
const tasks = [
|
|
1014
|
+
createTask({
|
|
1015
|
+
id: "T01",
|
|
1016
|
+
sequence: 0,
|
|
1017
|
+
files: [],
|
|
1018
|
+
inputs: ["config.json"],
|
|
1019
|
+
expected_output: [],
|
|
1020
|
+
}),
|
|
1021
|
+
createTask({
|
|
1022
|
+
id: "T02",
|
|
1023
|
+
sequence: 1,
|
|
1024
|
+
files: [],
|
|
1025
|
+
inputs: [],
|
|
1026
|
+
expected_output: ["config.json"],
|
|
1027
|
+
}),
|
|
1028
|
+
];
|
|
1029
|
+
|
|
1030
|
+
const results = checkTaskOrdering(tasks, "/tmp");
|
|
1031
|
+
assert.equal(results.length, 1, "task.inputs ordering violation must still be detected");
|
|
1032
|
+
assert.equal(results[0].blocking, true);
|
|
1033
|
+
assert.ok(results[0].message.includes("T01"));
|
|
1034
|
+
assert.ok(results[0].message.includes("T02"));
|
|
1035
|
+
assert.ok(results[0].message.includes("sequence violation"));
|
|
1036
|
+
});
|
|
1037
|
+
|
|
1038
|
+
test("mixed files and inputs — only inputs trigger ordering violation", () => {
|
|
1039
|
+
// T01 will create "created.ts" (files) and also needs to READ "needed.json" (inputs).
|
|
1040
|
+
// T02 creates both. Only the inputs dependency is a real violation.
|
|
1041
|
+
const tasks = [
|
|
1042
|
+
createTask({
|
|
1043
|
+
id: "T01",
|
|
1044
|
+
sequence: 0,
|
|
1045
|
+
files: ["created.ts"],
|
|
1046
|
+
inputs: ["needed.json"],
|
|
1047
|
+
expected_output: [],
|
|
1048
|
+
}),
|
|
1049
|
+
createTask({
|
|
1050
|
+
id: "T02",
|
|
1051
|
+
sequence: 1,
|
|
1052
|
+
files: [],
|
|
1053
|
+
inputs: [],
|
|
1054
|
+
expected_output: ["created.ts", "needed.json"],
|
|
1055
|
+
}),
|
|
1056
|
+
];
|
|
1057
|
+
|
|
1058
|
+
const results = checkTaskOrdering(tasks, "/tmp");
|
|
1059
|
+
assert.equal(results.length, 1, "Only the inputs entry should produce a violation, not files");
|
|
1060
|
+
assert.ok(results[0].target === "needed.json", "Violation target should be the input, not the file");
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
test("task.files with normalized paths should not false-positive", () => {
|
|
1064
|
+
// Path normalization (./src/new-file.ts → src/new-file.ts) should not cause
|
|
1065
|
+
// task.files to match against expected_output and produce a false positive.
|
|
1066
|
+
const tasks = [
|
|
1067
|
+
createTask({
|
|
1068
|
+
id: "T01",
|
|
1069
|
+
sequence: 0,
|
|
1070
|
+
files: ["./src/new-file.ts"],
|
|
1071
|
+
inputs: [],
|
|
1072
|
+
expected_output: [],
|
|
1073
|
+
}),
|
|
1074
|
+
createTask({
|
|
1075
|
+
id: "T02",
|
|
1076
|
+
sequence: 1,
|
|
1077
|
+
files: [],
|
|
1078
|
+
inputs: [],
|
|
1079
|
+
expected_output: ["src/new-file.ts"],
|
|
1080
|
+
}),
|
|
1081
|
+
];
|
|
1082
|
+
|
|
1083
|
+
const results = checkTaskOrdering(tasks, "/tmp");
|
|
1084
|
+
assert.equal(results.length, 0, "Normalized task.files path should not trigger a false positive");
|
|
1085
|
+
});
|
|
1086
|
+
});
|
|
1087
|
+
|
|
1088
|
+
// ─── checkFilePathConsistency additional edge cases ──────────────────────────
|
|
1089
|
+
|
|
1090
|
+
describe("checkFilePathConsistency additional edge cases", () => {
|
|
1091
|
+
test("inputs referencing glob-like patterns should not crash", () => {
|
|
1092
|
+
// A glob pattern in inputs is unusual but should be handled gracefully.
|
|
1093
|
+
// The file won't exist on disk, so it should produce a blocking result.
|
|
1094
|
+
const tasks = [
|
|
1095
|
+
createTask({
|
|
1096
|
+
id: "T01",
|
|
1097
|
+
files: [],
|
|
1098
|
+
inputs: ["src/**/*.ts"],
|
|
1099
|
+
expected_output: [],
|
|
1100
|
+
}),
|
|
1101
|
+
];
|
|
1102
|
+
|
|
1103
|
+
// Should not throw
|
|
1104
|
+
let results: ReturnType<typeof checkFilePathConsistency>;
|
|
1105
|
+
assert.doesNotThrow(() => {
|
|
1106
|
+
results = checkFilePathConsistency(tasks, "/tmp");
|
|
1107
|
+
});
|
|
1108
|
+
assert.equal(results!.length, 1, "Glob-pattern input that doesn't exist should produce a blocking result");
|
|
1109
|
+
assert.equal(results![0].blocking, true);
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
test("empty inputs array produces no results", () => {
|
|
1113
|
+
// A task with no inputs and only files should produce zero results from
|
|
1114
|
+
// consistency check — files are not checked (#3626).
|
|
1115
|
+
const tasks = [
|
|
1116
|
+
createTask({
|
|
1117
|
+
id: "T01",
|
|
1118
|
+
files: ["anything.ts"],
|
|
1119
|
+
inputs: [],
|
|
1120
|
+
expected_output: [],
|
|
1121
|
+
}),
|
|
1122
|
+
];
|
|
1123
|
+
|
|
1124
|
+
const results = checkFilePathConsistency(tasks, "/tmp");
|
|
1125
|
+
assert.equal(results.length, 0, "Empty inputs should produce no consistency check results");
|
|
1126
|
+
});
|
|
1127
|
+
|
|
1128
|
+
test("inputs with absolute paths are checked correctly", () => {
|
|
1129
|
+
// An absolute path in inputs should resolve to itself and pass when the file exists.
|
|
1130
|
+
const tempDir = join(tmpdir(), `pre-exec-test-abs-${Date.now()}`);
|
|
1131
|
+
mkdirSync(tempDir, { recursive: true });
|
|
1132
|
+
const absFilePath = join(tempDir, "real-file.ts");
|
|
1133
|
+
writeFileSync(absFilePath, "// content");
|
|
1134
|
+
|
|
1135
|
+
try {
|
|
1136
|
+
const tasks = [
|
|
1137
|
+
createTask({
|
|
1138
|
+
id: "T01",
|
|
1139
|
+
files: [],
|
|
1140
|
+
inputs: [absFilePath],
|
|
1141
|
+
expected_output: [],
|
|
1142
|
+
}),
|
|
1143
|
+
];
|
|
1144
|
+
|
|
1145
|
+
const results = checkFilePathConsistency(tasks, tempDir);
|
|
1146
|
+
assert.equal(results.length, 0, "Absolute path to an existing file should pass consistency check");
|
|
1147
|
+
} finally {
|
|
1148
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
});
|
|
1152
|
+
|
|
955
1153
|
// ─── PreExecutionResult Type Tests ───────────────────────────────────────────
|
|
956
1154
|
|
|
957
1155
|
describe("PreExecutionResult type", () => {
|
|
@@ -225,9 +225,9 @@ describe("Pre-execution fail-closed behavior", () => {
|
|
|
225
225
|
planning: {
|
|
226
226
|
description: "References missing file",
|
|
227
227
|
estimate: "1h",
|
|
228
|
-
files: [
|
|
228
|
+
files: [],
|
|
229
229
|
verify: "npm test",
|
|
230
|
-
inputs: [],
|
|
230
|
+
inputs: ["nonexistent-file.ts"],
|
|
231
231
|
expectedOutput: [],
|
|
232
232
|
observabilityImpact: "",
|
|
233
233
|
},
|
|
@@ -189,9 +189,9 @@ function createFailingTasks(): void {
|
|
|
189
189
|
planning: {
|
|
190
190
|
description: "This task references a non-existent file",
|
|
191
191
|
estimate: "1h",
|
|
192
|
-
files: [
|
|
192
|
+
files: [],
|
|
193
193
|
verify: "npm test",
|
|
194
|
-
inputs: [],
|
|
194
|
+
inputs: ["nonexistent-file-that-does-not-exist.ts"],
|
|
195
195
|
expectedOutput: [],
|
|
196
196
|
observabilityImpact: "",
|
|
197
197
|
},
|