@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.955e4da0
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/cli-web-branch.d.ts +2 -0
- package/dist/cli-web-branch.js +9 -2
- package/dist/help-text.js +5 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/bg-shell/utilities.js +2 -2
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +92 -230
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
- package/dist/resources/extensions/github-sync/templates.js +3 -3
- package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
- package/dist/resources/extensions/gsd/auto/loop.js +74 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +142 -15
- package/dist/resources/extensions/gsd/auto/phases.js +34 -4
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
- package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
- package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +12 -9
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
- package/dist/resources/extensions/gsd/auto-start.js +20 -36
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
- package/dist/resources/extensions/gsd/auto-verification.js +7 -7
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +34 -289
- package/dist/resources/extensions/gsd/auto.js +15 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +20 -43
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +131 -140
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +89 -8
- package/dist/resources/extensions/gsd/captures.js +5 -13
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
- package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
- package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
- package/dist/resources/extensions/gsd/db/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +372 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- package/dist/resources/extensions/gsd/db-workspace.js +103 -0
- package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
- package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +8 -10
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +9 -2
- package/dist/resources/extensions/gsd/doctor.js +16 -9
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-db.js +183 -2048
- package/dist/resources/extensions/gsd/guided-flow.js +68 -471
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
- package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
- package/dist/resources/extensions/gsd/md-importer.js +4 -3
- package/dist/resources/extensions/gsd/migrate/safety.js +19 -11
- package/dist/resources/extensions/gsd/migration-auto-check.js +27 -5
- package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
- package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
- package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
- package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +7 -5
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/paths.js +10 -24
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +161 -29
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
- package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
- package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
- package/dist/resources/extensions/gsd/question-transport.js +86 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +12 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +13 -5
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/templates/plan.md +7 -0
- package/dist/resources/extensions/gsd/templates/project.md +1 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/dist/resources/extensions/gsd/templates/uat.md +5 -1
- package/dist/resources/extensions/gsd/tool-contract.js +52 -8
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
- package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -5
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/uat-policy.js +16 -10
- package/dist/resources/extensions/gsd/uat-run.js +9 -14
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
- package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
- package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
- package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
- package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +287 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +17 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -10
- package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
- package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
- package/dist/resources/extensions/shared/interview-ui.js +2 -2
- package/dist/resources/shared/claude-runtime-floor.js +182 -0
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-cmd.js +20 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- 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 +8 -8
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
- package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
- package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/dist/worktree-status-banner.js +7 -3
- package/package.json +2 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts +10 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +8 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +32 -22
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +295 -98
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +309 -154
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/components/input.js +1 -1
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +39 -30
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +22 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/bg-shell/utilities.ts +2 -2
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +114 -281
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +268 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
- package/src/resources/extensions/github-sync/templates.ts +3 -3
- package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
- package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -1
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +164 -17
- package/src/resources/extensions/gsd/auto/phases.ts +45 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
- package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +16 -8
- package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
- package/src/resources/extensions/gsd/auto-start.ts +25 -34
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
- package/src/resources/extensions/gsd/auto-verification.ts +7 -8
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +53 -306
- package/src/resources/extensions/gsd/auto.ts +27 -17
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +20 -43
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +147 -153
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +132 -6
- package/src/resources/extensions/gsd/captures.ts +5 -14
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
- package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
- package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
- package/src/resources/extensions/gsd/db/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +453 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- package/src/resources/extensions/gsd/db-workspace.ts +170 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
- package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +8 -11
- package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +10 -3
- package/src/resources/extensions/gsd/doctor.ts +15 -5
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-db.ts +185 -2373
- package/src/resources/extensions/gsd/guided-flow.ts +81 -561
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
- package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -3
- package/src/resources/extensions/gsd/migrate/safety.ts +17 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +30 -5
- package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
- package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
- package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
- package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/paths.ts +9 -22
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +191 -28
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
- package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
- package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
- package/src/resources/extensions/gsd/question-transport.ts +138 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +14 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +15 -5
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/templates/plan.md +7 -0
- package/src/resources/extensions/gsd/templates/project.md +1 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/src/resources/extensions/gsd/templates/uat.md +5 -1
- package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +444 -5
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +143 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +185 -1
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +121 -0
- package/src/resources/extensions/gsd/tool-contract.ts +86 -8
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
- package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
- package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -5
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/uat-policy.ts +19 -10
- package/src/resources/extensions/gsd/uat-run.ts +10 -14
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
- package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
- package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
- package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
- package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +308 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +17 -17
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +17 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +12 -10
- package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
- package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
- package/src/resources/extensions/shared/interview-ui.ts +15 -2
- package/src/resources/shared/claude-runtime-floor.ts +248 -0
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
- package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → C24pqUd-aru-l0Dp0gLZP}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → C24pqUd-aru-l0Dp0gLZP}/_ssgManifest.js +0 -0
|
@@ -26,6 +26,24 @@ test("filterDoctorIssues keeps project and environment issues in scoped reports"
|
|
|
26
26
|
);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
test("filterDoctorIssues keeps invalid_preferences issues regardless of preferences file scope", () => {
|
|
30
|
+
// Both global and project preference diagnostics should survive scope filtering.
|
|
31
|
+
// doctor.ts uses unitId: "project" for all invalid_preferences issues so they
|
|
32
|
+
// pass through the scope filter the same way other project-level issues do.
|
|
33
|
+
const issues = [
|
|
34
|
+
{ severity: "error", code: "invalid_preferences", scope: "project", unitId: "project", message: "global PREFERENCES.md parse error", fixable: false },
|
|
35
|
+
{ severity: "error", code: "invalid_preferences", scope: "project", unitId: "project", message: "project PREFERENCES.md parse error", fixable: false },
|
|
36
|
+
{ severity: "error", code: "invalid_preferences", scope: "project", unitId: "global", message: "stale unitId — should be filtered out", fixable: false },
|
|
37
|
+
] as const;
|
|
38
|
+
|
|
39
|
+
const filtered = filterDoctorIssues([...issues], { scope: "M016", includeWarnings: true });
|
|
40
|
+
assert.deepEqual(
|
|
41
|
+
filtered.map((issue) => issue.message),
|
|
42
|
+
["global PREFERENCES.md parse error", "project PREFERENCES.md parse error"],
|
|
43
|
+
"invalid_preferences issues with unitId: project survive scope filtering; unitId: global is dropped",
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
29
47
|
test("checkEngineHealth reports db_unavailable when gsd.db exists but the DB is closed", async (t) => {
|
|
30
48
|
const base = mkdtempSync(join(tmpdir(), "gsd-doctor-db-unavailable-"));
|
|
31
49
|
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Regression tests for evidence cross-referencing of gsd_exec /
|
|
3
|
+
// gsd_uat_exec tool calls. Mirrors the live false-positive where an
|
|
4
|
+
// execute-task agent ran its verification commands through gsd_exec (script
|
|
5
|
+
// body in the `script` argument) and the cross-referencer reported
|
|
6
|
+
// "No bash tool call found" despite successful execution.
|
|
7
|
+
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
resetEvidence,
|
|
16
|
+
getEvidence,
|
|
17
|
+
recordToolCall,
|
|
18
|
+
recordToolResult,
|
|
19
|
+
isExecutionToolName,
|
|
20
|
+
type BashEvidence,
|
|
21
|
+
} from "../safety/evidence-collector.ts";
|
|
22
|
+
import { crossReferenceEvidence } from "../safety/evidence-cross-ref.ts";
|
|
23
|
+
|
|
24
|
+
function gsdExecResult(exitCode: number, id = "4858202d-2ed7-4a0a-9ef7-4e159e65da83"): unknown {
|
|
25
|
+
return {
|
|
26
|
+
content: [{
|
|
27
|
+
type: "text",
|
|
28
|
+
text: JSON.stringify({
|
|
29
|
+
operation: "gsd_exec",
|
|
30
|
+
id,
|
|
31
|
+
runtime: "bash",
|
|
32
|
+
exit_code: exitCode,
|
|
33
|
+
signal: null,
|
|
34
|
+
timed_out: false,
|
|
35
|
+
duration_ms: 272,
|
|
36
|
+
stdout_bytes: 592,
|
|
37
|
+
stderr_bytes: 0,
|
|
38
|
+
meta_path: `/tmp/does-not-exist/.gsd/exec/${id}.meta.json`,
|
|
39
|
+
}),
|
|
40
|
+
}],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
test("evidence-xref: verification run through gsd_exec script matches the claimed command", () => {
|
|
45
|
+
resetEvidence();
|
|
46
|
+
|
|
47
|
+
// The live false positive: agent runs `node --test tests/verify-s01.test.js`
|
|
48
|
+
// inside a gsd_exec script with a cd prefix and exit-code echo suffix.
|
|
49
|
+
recordToolCall("tc-exec-1", "gsd_exec", {
|
|
50
|
+
script: 'cd /work/.gsd/worktrees/M001 && node --test tests/verify-s01.test.js; echo "EXIT=$?"',
|
|
51
|
+
purpose: "T02: run node --test contract checks against T01 index.html",
|
|
52
|
+
});
|
|
53
|
+
recordToolResult("tc-exec-1", "gsd_exec", gsdExecResult(0), false);
|
|
54
|
+
|
|
55
|
+
const mismatches = crossReferenceEvidence(
|
|
56
|
+
[{ command: "node --test tests/verify-s01.test.js", exitCode: 0, verdict: "passed" }],
|
|
57
|
+
getEvidence(),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
assert.deepEqual(mismatches, [], "gsd_exec-executed verification must not be flagged as missing");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("evidence-xref: multi-line gsd_exec script matches claims for each embedded command", () => {
|
|
64
|
+
resetEvidence();
|
|
65
|
+
|
|
66
|
+
recordToolCall("tc-exec-2", "gsd_exec", {
|
|
67
|
+
script: [
|
|
68
|
+
"cd /work/.gsd/worktrees/M001",
|
|
69
|
+
"sed -i '' \"s/'todos'/'tasks-v1'/\" index.html",
|
|
70
|
+
"node --test tests/verify-s01.test.js > /dev/null 2>&1",
|
|
71
|
+
'echo "BROKEN_EXIT=$?"',
|
|
72
|
+
].join("\n"),
|
|
73
|
+
purpose: "T02: deliberate contract break must fail, then restore",
|
|
74
|
+
});
|
|
75
|
+
recordToolResult("tc-exec-2", "gsd_exec", gsdExecResult(0), false);
|
|
76
|
+
|
|
77
|
+
const mismatches = crossReferenceEvidence(
|
|
78
|
+
[{ command: "node --test tests/verify-s01.test.js > /dev/null 2>&1", exitCode: 0, verdict: "passed" }],
|
|
79
|
+
getEvidence(),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
assert.deepEqual(mismatches, [], "command embedded in a multi-line script must match");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("evidence-xref: claimed pass with failing gsd_exec exit_code is still an error", () => {
|
|
86
|
+
resetEvidence();
|
|
87
|
+
|
|
88
|
+
recordToolCall("tc-exec-3", "gsd_exec", {
|
|
89
|
+
script: "node --test tests/verify-s01.test.js",
|
|
90
|
+
purpose: "verification",
|
|
91
|
+
});
|
|
92
|
+
// gsd_exec reports failures via the JSON envelope's exit_code (and isError).
|
|
93
|
+
recordToolResult("tc-exec-3", "gsd_exec", gsdExecResult(1), true);
|
|
94
|
+
|
|
95
|
+
const mismatches = crossReferenceEvidence(
|
|
96
|
+
[{ command: "node --test tests/verify-s01.test.js", exitCode: 0, verdict: "passed" }],
|
|
97
|
+
getEvidence(),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
assert.equal(mismatches.length, 1);
|
|
101
|
+
assert.equal(mismatches[0].severity, "error");
|
|
102
|
+
assert.match(mismatches[0].reason, /Claimed exitCode=0 but actual exitCode=1/);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("evidence-collector: gsd_uat_exec and MCP-namespaced variants are execution tools", () => {
|
|
106
|
+
assert.equal(isExecutionToolName("gsd_uat_exec"), true);
|
|
107
|
+
assert.equal(isExecutionToolName("mcp__gsd-workflow__gsd_uat_exec"), true);
|
|
108
|
+
assert.equal(isExecutionToolName("mcp__gsd-workflow__gsd_exec"), true);
|
|
109
|
+
|
|
110
|
+
resetEvidence();
|
|
111
|
+
recordToolCall("tc-uat-1", "gsd_uat_exec", { script: "curl -fsS http://localhost:3000/health" });
|
|
112
|
+
const bash = getEvidence().filter((e): e is BashEvidence => e.kind === "bash");
|
|
113
|
+
assert.equal(bash.length, 1, "gsd_uat_exec must record bash evidence");
|
|
114
|
+
assert.equal(bash[0].command, "curl -fsS http://localhost:3000/health");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("evidence-xref: blank-command evidence does not satisfy arbitrary claims", () => {
|
|
118
|
+
// Before script extraction existed, gsd_exec calls were recorded with
|
|
119
|
+
// command: "" — and `"x".includes("")` made them match every claim,
|
|
120
|
+
// masking genuine fabrications. Blank entries must never match.
|
|
121
|
+
const mismatches = crossReferenceEvidence(
|
|
122
|
+
[{ command: "node --test tests/verify-s01.test.js", exitCode: 0, verdict: "passed" }],
|
|
123
|
+
[{
|
|
124
|
+
kind: "bash",
|
|
125
|
+
toolCallId: "tc-blank",
|
|
126
|
+
command: "",
|
|
127
|
+
exitCode: 0,
|
|
128
|
+
outputSnippet: "",
|
|
129
|
+
timestamp: 1,
|
|
130
|
+
}],
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
assert.equal(mismatches.length, 1);
|
|
134
|
+
assert.equal(mismatches[0].severity, "warning");
|
|
135
|
+
assert.match(mismatches[0].reason, /No bash tool call found/);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("evidence-collector: exit code falls back to .gsd/exec meta.json when result text omits it", (t) => {
|
|
139
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-exec-meta-"));
|
|
140
|
+
t.after(() => rmSync(dir, { recursive: true, force: true }));
|
|
141
|
+
|
|
142
|
+
const metaPath = join(dir, "run-1.meta.json");
|
|
143
|
+
writeFileSync(metaPath, JSON.stringify({ id: "run-1", exit_code: 7 }));
|
|
144
|
+
|
|
145
|
+
resetEvidence();
|
|
146
|
+
recordToolCall("tc-meta-1", "gsd_exec", { script: "exit 7" });
|
|
147
|
+
// Truncated result: meta_path survives but exit_code was cut off.
|
|
148
|
+
recordToolResult(
|
|
149
|
+
"tc-meta-1",
|
|
150
|
+
"gsd_exec",
|
|
151
|
+
{ content: [{ type: "text", text: `{"operation":"gsd_exec","meta_path":${JSON.stringify(metaPath)}` }] },
|
|
152
|
+
false,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const bash = getEvidence().filter((e): e is BashEvidence => e.kind === "bash");
|
|
156
|
+
assert.equal(bash[0].exitCode, 7, "exit code must be recovered from meta.json");
|
|
157
|
+
});
|
|
@@ -38,6 +38,7 @@ test("execute-task prompt renders compact execution and completion gates", async
|
|
|
38
38
|
planPath: ".gsd/milestones/M001/slices/S01/S01-PLAN.md",
|
|
39
39
|
taskPlanPath: ".gsd/milestones/M001/slices/S01/tasks/T01-PLAN.md",
|
|
40
40
|
priorTaskLines: "- None",
|
|
41
|
+
onDemandContext: "",
|
|
41
42
|
skillActivation: "Load relevant skills.",
|
|
42
43
|
inlinedTemplates: "### Output Template: Task Summary\nSource: `templates/task-summary.md`",
|
|
43
44
|
templatesDir: join(fixtureRoot, "templates"),
|
|
@@ -5,7 +5,7 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
|
|
8
|
-
import { validateFileChanges } from "../safety/file-change-validator.ts";
|
|
8
|
+
import { validateFileChanges, effectiveFileChangeAllowlist } from "../safety/file-change-validator.ts";
|
|
9
9
|
|
|
10
10
|
function git(cwd: string, ...args: string[]): string {
|
|
11
11
|
return execFileSync("git", args, {
|
|
@@ -106,3 +106,35 @@ test("validateFileChanges ignores inline descriptions in expected output paths",
|
|
|
106
106
|
"described expected output should not trigger unexpected-file warnings",
|
|
107
107
|
);
|
|
108
108
|
});
|
|
109
|
+
|
|
110
|
+
test("effectiveFileChangeAllowlist includes .gitignore when GSD manages it", () => {
|
|
111
|
+
assert.deepEqual(effectiveFileChangeAllowlist([], undefined), [".gitignore"]);
|
|
112
|
+
assert.deepEqual(effectiveFileChangeAllowlist(["docs/**"], true), ["docs/**", ".gitignore"]);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("effectiveFileChangeAllowlist keeps .gitignore auditable when management is disabled", () => {
|
|
116
|
+
assert.deepEqual(effectiveFileChangeAllowlist(["docs/**"], false), ["docs/**"]);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("GSD-managed .gitignore edit swept into a task commit is not flagged", (t) => {
|
|
120
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-file-change-validator-"));
|
|
121
|
+
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
122
|
+
|
|
123
|
+
git(base, "init");
|
|
124
|
+
git(base, "config", "user.email", "test@example.com");
|
|
125
|
+
git(base, "config", "user.name", "Test User");
|
|
126
|
+
writeFileSync(join(base, "index.html"), "<main></main>\n");
|
|
127
|
+
writeFileSync(join(base, ".gitignore"), "# ── GSD baseline (auto-generated) ──\n.gsd\n");
|
|
128
|
+
git(base, "add", ".");
|
|
129
|
+
git(base, "commit", "-m", "task commit with swept gitignore");
|
|
130
|
+
|
|
131
|
+
const audit = validateFileChanges(
|
|
132
|
+
base,
|
|
133
|
+
["index.html"],
|
|
134
|
+
[],
|
|
135
|
+
effectiveFileChangeAllowlist([], undefined),
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
assert.ok(audit, "audit should be produced");
|
|
139
|
+
assert.deepEqual(audit.unexpectedFiles, [], ".gitignore must not be flagged when GSD manages it");
|
|
140
|
+
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
6
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
insertSlice,
|
|
19
19
|
} from "../gsd-db.ts";
|
|
20
20
|
import type { GateVerdict } from "../types.ts";
|
|
21
|
+
import { closeQualityGatesFromEvidence } from "../quality-gate-closure.ts";
|
|
21
22
|
|
|
22
23
|
describe("gate-state canonicalization (#4950)", () => {
|
|
23
24
|
let tmpDir: string;
|
|
@@ -99,4 +100,50 @@ describe("gate-state canonicalization (#4950)", () => {
|
|
|
99
100
|
assert.notEqual(g.verdict, "", `gate ${g.gate_id} verdict must not be empty string`);
|
|
100
101
|
}
|
|
101
102
|
});
|
|
103
|
+
|
|
104
|
+
test("closeQualityGatesFromEvidence repairs pending gate from durable section", () => {
|
|
105
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
106
|
+
mkdirSync(join(tmpDir, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
|
|
107
|
+
writeFileSync(
|
|
108
|
+
join(tmpDir, ".gsd", "milestones", "M001", "slices", "S01", "S01-PLAN.md"),
|
|
109
|
+
[
|
|
110
|
+
"# S01",
|
|
111
|
+
"",
|
|
112
|
+
"## Threat Surface",
|
|
113
|
+
"",
|
|
114
|
+
"- Credential stuffing is rate-limited.",
|
|
115
|
+
].join("\n"),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const result = closeQualityGatesFromEvidence("M001", { artifactBasePath: tmpDir });
|
|
119
|
+
|
|
120
|
+
assert.deepEqual(result.unresolved, []);
|
|
121
|
+
assert.deepEqual(result.repaired, [{ gateId: "Q3", sliceId: "S01", verdict: "pass" }]);
|
|
122
|
+
assert.equal(getPendingGates("M001", "S01").length, 0);
|
|
123
|
+
assert.equal(getGateResults("M001", "S01")[0].verdict, "pass");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("closeQualityGatesFromEvidence omits stale pending gate after validation pass", () => {
|
|
127
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
128
|
+
|
|
129
|
+
const result = closeQualityGatesFromEvidence("M001", {
|
|
130
|
+
artifactBasePath: tmpDir,
|
|
131
|
+
milestoneValidationPassed: true,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
assert.deepEqual(result.unresolved, []);
|
|
135
|
+
assert.deepEqual(result.repaired, [{ gateId: "Q4", sliceId: "S01", verdict: "omitted" }]);
|
|
136
|
+
assert.equal(getGateResults("M001", "S01")[0].verdict, "omitted");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("closeQualityGatesFromEvidence leaves pending gate unresolved without evidence", () => {
|
|
140
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
141
|
+
|
|
142
|
+
const result = closeQualityGatesFromEvidence("M001", { artifactBasePath: tmpDir });
|
|
143
|
+
|
|
144
|
+
assert.deepEqual(result.repaired, []);
|
|
145
|
+
assert.equal(result.unresolved.length, 1);
|
|
146
|
+
assert.equal(result.unresolved[0].gate_id, "Q3");
|
|
147
|
+
assert.equal(getPendingGates("M001", "S01").length, 1);
|
|
148
|
+
});
|
|
102
149
|
});
|
package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts
CHANGED
|
@@ -746,7 +746,7 @@ describe("auto-worktree-milestone-merge", { timeout: 300_000 }, () => {
|
|
|
746
746
|
});
|
|
747
747
|
|
|
748
748
|
test("#2156: mergeMilestoneToMain removes external-state worktrees using the milestone branch name", () => {
|
|
749
|
-
const { repo
|
|
749
|
+
const { repo } = freshRepoWithExternalGsd();
|
|
750
750
|
const wtPath = createAutoWorktree(repo, "M215");
|
|
751
751
|
|
|
752
752
|
addSliceToMilestone(repo, wtPath, "M215", "S01", "External cleanup", [
|
|
@@ -754,9 +754,10 @@ describe("auto-worktree-milestone-merge", { timeout: 300_000 }, () => {
|
|
|
754
754
|
]);
|
|
755
755
|
|
|
756
756
|
const realWtPath = realpathSync(wtPath);
|
|
757
|
-
assert.
|
|
758
|
-
realWtPath
|
|
759
|
-
|
|
757
|
+
assert.equal(
|
|
758
|
+
realWtPath,
|
|
759
|
+
join(repo, ".gsd-worktrees", "M215"),
|
|
760
|
+
`worktree should use canonical path under project root, got ${realWtPath}`,
|
|
760
761
|
);
|
|
761
762
|
|
|
762
763
|
// Recreate the exact divergence from #1852: local .gsd/ is replaced with a
|
|
@@ -157,7 +157,7 @@ describe("auto-worktree lifecycle", () => {
|
|
|
157
157
|
try {
|
|
158
158
|
const wtPath = createAutoWorktree(tempDir, "M001");
|
|
159
159
|
const realWtPath = realpathSync(wtPath);
|
|
160
|
-
assert.
|
|
160
|
+
assert.equal(realWtPath, join(tempDir, ".gsd-worktrees", "M001"), "worktree uses canonical path under project root, not through the .gsd symlink");
|
|
161
161
|
|
|
162
162
|
_resetAutoWorktreeOriginalBaseForTests();
|
|
163
163
|
process.chdir(realWtPath);
|
|
@@ -293,11 +293,12 @@ describe('git-service', async () => {
|
|
|
293
293
|
|
|
294
294
|
assert.deepStrictEqual(
|
|
295
295
|
RUNTIME_EXCLUSION_PATHS.length,
|
|
296
|
-
|
|
297
|
-
"exactly
|
|
296
|
+
17,
|
|
297
|
+
"exactly 17 runtime exclusion paths"
|
|
298
298
|
);
|
|
299
299
|
|
|
300
300
|
const expectedPaths = [
|
|
301
|
+
".gsd-worktrees/",
|
|
301
302
|
".gsd/activity/",
|
|
302
303
|
".gsd/audit/",
|
|
303
304
|
".gsd/forensics/",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Regression coverage for shared MCP tool-name parsing helpers.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
mcpToolMatchesBaseName,
|
|
9
|
+
parseMcpToolName,
|
|
10
|
+
stripMcpToolPrefix,
|
|
11
|
+
toMcpToolName,
|
|
12
|
+
toMcpWildcardToolName,
|
|
13
|
+
} from "../mcp-tool-name.ts";
|
|
14
|
+
|
|
15
|
+
test("parseMcpToolName parses exact and wildcard MCP tool names", () => {
|
|
16
|
+
assert.deepEqual(parseMcpToolName("mcp__gsd-workflow__ask_user_questions"), {
|
|
17
|
+
serverName: "gsd-workflow",
|
|
18
|
+
toolName: "ask_user_questions",
|
|
19
|
+
});
|
|
20
|
+
assert.deepEqual(parseMcpToolName("mcp__gsd-browser__*"), {
|
|
21
|
+
serverName: "gsd-browser",
|
|
22
|
+
toolName: "*",
|
|
23
|
+
});
|
|
24
|
+
assert.equal(parseMcpToolName("browser_navigate"), null);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("MCP tool-name helpers strip, match, and format names consistently", () => {
|
|
28
|
+
assert.equal(stripMcpToolPrefix("mcp__custom-workflow__gsd_exec"), "gsd_exec");
|
|
29
|
+
assert.equal(stripMcpToolPrefix("read"), "read");
|
|
30
|
+
assert.equal(mcpToolMatchesBaseName("mcp__custom-workflow__gsd_exec", "gsd_exec"), true);
|
|
31
|
+
assert.equal(mcpToolMatchesBaseName("mcp__custom-workflow__gsd_exec", "gsd_summary_save"), false);
|
|
32
|
+
assert.equal(toMcpToolName("custom-workflow", "gsd_exec"), "mcp__custom-workflow__gsd_exec");
|
|
33
|
+
assert.equal(toMcpWildcardToolName("custom-workflow"), "mcp__custom-workflow__*");
|
|
34
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import { copyFileSync, mkdtempSync, renameSync, rmSync } from "node:fs";
|
|
3
|
+
import { copyFileSync, mkdirSync, mkdtempSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import test from "node:test";
|
|
@@ -287,3 +287,145 @@ test("migration auto-check refreshes a stale open DB handle before comparing", a
|
|
|
287
287
|
cleanup(base);
|
|
288
288
|
}
|
|
289
289
|
});
|
|
290
|
+
|
|
291
|
+
function writeScratchMilestoneDir(base: string, milestoneId: string, file?: string): void {
|
|
292
|
+
const dir = join(base, ".gsd", "milestones", milestoneId);
|
|
293
|
+
mkdirSync(dir, { recursive: true });
|
|
294
|
+
if (file) writeFileSync(join(dir, file), `# ${milestoneId} discussion context\n`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
test("migration auto-check ignores discussion-scratch milestone dirs (CONTEXT only, no DB row)", async () => {
|
|
298
|
+
const base = makeBase();
|
|
299
|
+
try {
|
|
300
|
+
await writeGSDDirectory(projectFixture(), base); // markdown: M001 / S01 / T01
|
|
301
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
302
|
+
insertMilestone({ id: "M001", title: "Legacy Milestone", status: "active" });
|
|
303
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Legacy Slice", status: "pending", risk: "medium", depends: [], demo: "Legacy slice demo", sequence: 1 });
|
|
304
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M001", title: "Legacy Task", status: "pending" });
|
|
305
|
+
|
|
306
|
+
// Mid-discussion artifacts: dirs with no ROADMAP and no DB row. The queued
|
|
307
|
+
// DB row is only inserted at discussion handoff, so these are expected to
|
|
308
|
+
// be DB-less — not drift, and recover must not be recommended (it would
|
|
309
|
+
// import them as ghost active milestones).
|
|
310
|
+
writeScratchMilestoneDir(base, "M002", "M002-CONTEXT.md");
|
|
311
|
+
writeScratchMilestoneDir(base, "M003", "M003-CONTEXT-DRAFT.md");
|
|
312
|
+
writeScratchMilestoneDir(base, "M004"); // empty dir
|
|
313
|
+
|
|
314
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
315
|
+
assert.equal(result.action, "none");
|
|
316
|
+
assert.equal(result.reason, "in-sync");
|
|
317
|
+
assert.deepEqual(result.markdown, { milestones: 1, slices: 1, tasks: 1 });
|
|
318
|
+
} finally {
|
|
319
|
+
cleanup(base);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test("migration auto-check stays quiet mid-first-discussion (scratch dir over empty DB)", async () => {
|
|
324
|
+
const base = makeBase();
|
|
325
|
+
try {
|
|
326
|
+
await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
|
|
327
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
328
|
+
writeScratchMilestoneDir(base, "M001", "M001-CONTEXT.md");
|
|
329
|
+
|
|
330
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
331
|
+
assert.equal(result.action, "none");
|
|
332
|
+
assert.equal(result.reason, "no-markdown");
|
|
333
|
+
} finally {
|
|
334
|
+
cleanup(base);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("migration auto-check still reports real drift with scratch dirs excluded from counts", async () => {
|
|
339
|
+
const base = makeBase();
|
|
340
|
+
try {
|
|
341
|
+
await writeGSDDirectory(projectFixture(), base); // markdown: M001 / S01 / T01, DB empty
|
|
342
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
343
|
+
writeScratchMilestoneDir(base, "M002", "M002-CONTEXT.md");
|
|
344
|
+
|
|
345
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
346
|
+
assert.equal(result.action, "recovery-required");
|
|
347
|
+
assert.equal(result.reason, "db-empty");
|
|
348
|
+
assert.equal(result.recoveryCommand, "/gsd recover --confirm");
|
|
349
|
+
// The scratch dir must not inflate the reported markdown count.
|
|
350
|
+
assert.deepEqual(result.markdown, { milestones: 1, slices: 1, tasks: 1 });
|
|
351
|
+
} finally {
|
|
352
|
+
cleanup(base);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("migration auto-check still compares a roadmapless milestone that HAS a DB row", async () => {
|
|
357
|
+
const base = makeBase();
|
|
358
|
+
try {
|
|
359
|
+
await writeGSDDirectory({ projectContent: "# P\n", decisionsContent: "", requirements: [], milestones: [] }, base);
|
|
360
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
361
|
+
// Post-handoff queued milestone: CONTEXT-only dir WITH a DB row. It must
|
|
362
|
+
// stay in the comparison (both sides have it → in-sync).
|
|
363
|
+
insertMilestone({ id: "M001", title: "M001", status: "queued" });
|
|
364
|
+
writeScratchMilestoneDir(base, "M001", "M001-CONTEXT.md");
|
|
365
|
+
|
|
366
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
367
|
+
assert.equal(result.action, "none");
|
|
368
|
+
assert.equal(result.reason, "in-sync");
|
|
369
|
+
assert.deepEqual(result.markdown, { milestones: 1, slices: 0, tasks: 0 });
|
|
370
|
+
} finally {
|
|
371
|
+
cleanup(base);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test("rebuildMarkdownProjectionsFromDb realigns markdown when DB holds extra rows", async () => {
|
|
376
|
+
const base = makeBase();
|
|
377
|
+
try {
|
|
378
|
+
await writeGSDDirectory(projectFixture(), base); // markdown: M001 / S01 / T01
|
|
379
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
380
|
+
insertMilestone({ id: "M001", title: "Legacy Milestone", status: "active" });
|
|
381
|
+
insertSlice({
|
|
382
|
+
id: "S01",
|
|
383
|
+
milestoneId: "M001",
|
|
384
|
+
title: "Legacy Slice",
|
|
385
|
+
status: "pending",
|
|
386
|
+
risk: "medium",
|
|
387
|
+
depends: [],
|
|
388
|
+
demo: "Legacy slice demo",
|
|
389
|
+
sequence: 1,
|
|
390
|
+
});
|
|
391
|
+
insertTask({
|
|
392
|
+
id: "T01",
|
|
393
|
+
sliceId: "S01",
|
|
394
|
+
milestoneId: "M001",
|
|
395
|
+
title: "Legacy Task",
|
|
396
|
+
status: "pending",
|
|
397
|
+
});
|
|
398
|
+
insertSlice({
|
|
399
|
+
id: "S02",
|
|
400
|
+
milestoneId: "M001",
|
|
401
|
+
title: "Added in DB",
|
|
402
|
+
status: "pending",
|
|
403
|
+
risk: "medium",
|
|
404
|
+
depends: [],
|
|
405
|
+
demo: "d",
|
|
406
|
+
sequence: 2,
|
|
407
|
+
});
|
|
408
|
+
insertTask({
|
|
409
|
+
id: "T02",
|
|
410
|
+
sliceId: "S02",
|
|
411
|
+
milestoneId: "M001",
|
|
412
|
+
title: "Added task",
|
|
413
|
+
status: "pending",
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
const before = await checkMarkdownHierarchyAgainstDb(base);
|
|
417
|
+
assert.equal(before.recoveryCommand, "/gsd rebuild markdown");
|
|
418
|
+
|
|
419
|
+
const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
|
|
420
|
+
const rebuild = await rebuildMarkdownProjectionsFromDb(base);
|
|
421
|
+
assert.ok(rebuild.rendered > 0, "expected markdown projections to render");
|
|
422
|
+
|
|
423
|
+
const after = await checkMarkdownHierarchyAgainstDb(base);
|
|
424
|
+
assert.equal(after.action, "none");
|
|
425
|
+
assert.equal(after.reason, "in-sync");
|
|
426
|
+
assert.deepEqual(after.markdown, { milestones: 1, slices: 2, tasks: 2 });
|
|
427
|
+
assert.deepEqual(after.beforeDb, { milestones: 1, slices: 2, tasks: 2 });
|
|
428
|
+
} finally {
|
|
429
|
+
cleanup(base);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Tests for the shared milestone closeout proof surface.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
closeDatabase,
|
|
12
|
+
insertAssessment,
|
|
13
|
+
insertMilestone,
|
|
14
|
+
insertSlice,
|
|
15
|
+
openDatabase,
|
|
16
|
+
} from "../gsd-db.js";
|
|
17
|
+
import { proveMilestoneCloseout } from "../milestone-closeout-proof.js";
|
|
18
|
+
|
|
19
|
+
const tmpDirs: string[] = [];
|
|
20
|
+
|
|
21
|
+
function makeBase(): string {
|
|
22
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-closeout-proof-"));
|
|
23
|
+
tmpDirs.push(base);
|
|
24
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
25
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
26
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
27
|
+
return base;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function insertValidationPass(): void {
|
|
31
|
+
insertAssessment({
|
|
32
|
+
path: "milestones/M001/M001-VALIDATION.md",
|
|
33
|
+
milestoneId: "M001",
|
|
34
|
+
status: "pass",
|
|
35
|
+
scope: "milestone-validation",
|
|
36
|
+
fullContent: "verdict: pass",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeSummary(base: string, status = "complete"): void {
|
|
41
|
+
writeFileSync(
|
|
42
|
+
join(base, ".gsd", "milestones", "M001", "M001-SUMMARY.md"),
|
|
43
|
+
`---\nstatus: ${status}\n---\n\n# Summary\n`,
|
|
44
|
+
"utf-8",
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test.after(() => {
|
|
49
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
50
|
+
for (const dir of tmpDirs) {
|
|
51
|
+
rmSync(dir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("proveMilestoneCloseout accepts closed DB state plus summary artifact", () => {
|
|
56
|
+
const base = makeBase();
|
|
57
|
+
insertMilestone({ id: "M001", title: "Done", status: "complete" });
|
|
58
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete" });
|
|
59
|
+
insertValidationPass();
|
|
60
|
+
writeSummary(base);
|
|
61
|
+
|
|
62
|
+
const result = proveMilestoneCloseout("M001", {
|
|
63
|
+
summaryArtifactBasePath: base,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
assert.deepEqual(result, { ok: true });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("proveMilestoneCloseout can prove readiness before DB milestone is closed", () => {
|
|
70
|
+
const base = makeBase();
|
|
71
|
+
insertMilestone({ id: "M001", title: "Ready", status: "active" });
|
|
72
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete" });
|
|
73
|
+
insertValidationPass();
|
|
74
|
+
writeSummary(base);
|
|
75
|
+
|
|
76
|
+
const result = proveMilestoneCloseout("M001", {
|
|
77
|
+
allowOpenMilestone: true,
|
|
78
|
+
summaryArtifactBasePath: base,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
assert.deepEqual(result, { ok: true });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("proveMilestoneCloseout rejects explicit failure summaries", () => {
|
|
85
|
+
const base = makeBase();
|
|
86
|
+
insertMilestone({ id: "M001", title: "Done", status: "complete" });
|
|
87
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete" });
|
|
88
|
+
insertValidationPass();
|
|
89
|
+
writeSummary(base, "failed");
|
|
90
|
+
|
|
91
|
+
const result = proveMilestoneCloseout("M001", {
|
|
92
|
+
summaryArtifactBasePath: base,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
assert.equal(result.ok, false);
|
|
96
|
+
if (!result.ok) {
|
|
97
|
+
assert.equal(result.reason, "summary-artifact-failed");
|
|
98
|
+
}
|
|
99
|
+
});
|