@opengsd/gsd-pi 1.1.1-dev.b2556262 → 1.2.0-dev.4813ead6
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/project-sessions.js +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +101 -237
- 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/contracts.js +8 -1
- package/dist/resources/extensions/gsd/auto/loop.js +74 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +763 -63
- package/dist/resources/extensions/gsd/auto/phases.js +28 -3
- 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 +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +191 -9
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +17 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -23
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +37 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +33 -29
- package/dist/resources/extensions/gsd/auto-verification.js +7 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +45 -36
- package/dist/resources/extensions/gsd/auto.js +73 -471
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +103 -138
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- 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-workspace.js +103 -0
- package/dist/resources/extensions/gsd/debug-logger.js +10 -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-proactive.js +7 -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/gsd-db.js +12 -0
- package/dist/resources/extensions/gsd/guided-flow.js +36 -470
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +33 -33
- package/dist/resources/extensions/gsd/mcp-filter.js +8 -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 +2 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
- 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/native-git-bridge.js +45 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +147 -29
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +6 -7
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
- 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/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
- package/dist/resources/extensions/gsd/state.js +13 -5
- 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/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +169 -20
- 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/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 +65 -4
- 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-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/tsconfig.extensions.tsbuildinfo +1 -0
- 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 +5 -5
- 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 +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 +5 -5
- package/dist/web/standalone/.next/server/chunks/5047.js +2 -0
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- 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/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
- package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
- package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
- package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
- package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
- package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
- package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
- package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
- package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/package.json +17 -11
- 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/components/transcript-design.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.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 +2 -1
- 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 +30 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +30 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +8 -127
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +47 -166
- 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/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +11 -3
- package/packages/pi-coding-agent/dist/core/auth-storage.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/scripts/install/deps.js +10 -0
- package/scripts/link-workspace-packages.cjs +7 -40
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +126 -289
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +242 -2
- 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 +40 -121
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +913 -64
- package/src/resources/extensions/gsd/auto/phases.ts +35 -3
- 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 +4 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +220 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +30 -0
- package/src/resources/extensions/gsd/auto-start.ts +17 -20
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +40 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +42 -30
- package/src/resources/extensions/gsd/auto-verification.ts +7 -8
- package/src/resources/extensions/gsd/auto-worktree.ts +57 -42
- package/src/resources/extensions/gsd/auto.ts +96 -508
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +120 -151
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- 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-workspace.ts +170 -0
- package/src/resources/extensions/gsd/debug-logger.ts +11 -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-proactive.ts +8 -2
- 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/gsd-db.ts +12 -0
- package/src/resources/extensions/gsd/guided-flow.ts +49 -560
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +40 -20
- package/src/resources/extensions/gsd/mcp-filter.ts +9 -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 +2 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
- 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/native-git-bridge.ts +48 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- 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 +173 -28
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +6 -7
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +5 -7
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +6 -6
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +1 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -6
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/research-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -3
- 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/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
- package/src/resources/extensions/gsd/state.ts +15 -5
- 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/artifact-db-drift-memo.test.ts +66 -0
- 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-dispatch-baseline-harness.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -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 +709 -845
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +38 -10
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -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/debug-logger.test.ts +15 -0
- 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/execute-summary-save-empty-project.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- 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/merge-strategy-regular.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
- 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/native-merge-regular.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +6 -2
- 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 +75 -2
- 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/register-hooks-depth-verification.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +65 -0
- 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/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +21 -6
- package/src/resources/extensions/gsd/tests/token-tool-gating.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 +147 -0
- 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-manager.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -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/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +183 -21
- 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/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 +55 -5
- 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-lifecycle.ts +7 -16
- 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/dist/web/standalone/.next/server/chunks/678.js +0 -2
- 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/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +0 -21
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +0 -213
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts +0 -28
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js +0 -249
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-density-prototype.js.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts +0 -19
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.d.ts.map +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js +0 -797
- package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/transcript-design-prototype.js.map +0 -1
- package/scripts/ensure-workspace-builds.cjs +0 -129
- /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → tkLHUSzPA2kMmWz4DmGwI}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tJOKQbQRO-9MiFDO8DIDS → tkLHUSzPA2kMmWz4DmGwI}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Regression tests for nativeMergeRegular (#549 — merge_strategy: merge).
|
|
2
|
+
//
|
|
3
|
+
// nativeMergeRegular is the new `git merge --no-ff --no-commit` path called
|
|
4
|
+
// when `git.merge_strategy: merge` is configured. These tests verify:
|
|
5
|
+
// 1. Success path: returns { success: true, conflicts: [] } and leaves MERGE_HEAD
|
|
6
|
+
// so nativeCommit can supply the commit message and git records two parents.
|
|
7
|
+
// 2. Dirty-tree path: returns __dirty_working_tree__ sentinel (matching
|
|
8
|
+
// nativeMergeSquash behaviour) when uncommitted changes would be overwritten.
|
|
9
|
+
// 3. Content-conflict path: returns the conflicted file names (not the dirty-tree
|
|
10
|
+
// sentinel) when both branches modified the same region of a file.
|
|
11
|
+
|
|
12
|
+
import { describe, test, afterEach } from "node:test";
|
|
13
|
+
import assert from "node:assert/strict";
|
|
14
|
+
import {
|
|
15
|
+
existsSync,
|
|
16
|
+
mkdtempSync,
|
|
17
|
+
rmSync,
|
|
18
|
+
writeFileSync,
|
|
19
|
+
} from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { tmpdir } from "node:os";
|
|
22
|
+
import { execFileSync } from "node:child_process";
|
|
23
|
+
|
|
24
|
+
import { nativeMergeRegular } from "../native-git-bridge.ts";
|
|
25
|
+
|
|
26
|
+
function git(cwd: string, ...args: string[]): string {
|
|
27
|
+
return execFileSync("git", args, {
|
|
28
|
+
cwd,
|
|
29
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
30
|
+
encoding: "utf-8",
|
|
31
|
+
}).trim();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function makeRepo(prefix: string): string {
|
|
35
|
+
const dir = mkdtempSync(join(tmpdir(), prefix));
|
|
36
|
+
git(dir, "init");
|
|
37
|
+
git(dir, "config", "user.email", "test@test.com");
|
|
38
|
+
git(dir, "config", "user.name", "Test");
|
|
39
|
+
git(dir, "config", "core.autocrlf", "false");
|
|
40
|
+
writeFileSync(join(dir, "README.md"), "# init\n");
|
|
41
|
+
git(dir, "add", "-A");
|
|
42
|
+
git(dir, "commit", "-m", "init");
|
|
43
|
+
git(dir, "branch", "-M", "main");
|
|
44
|
+
return dir;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe("nativeMergeRegular (#549)", () => {
|
|
48
|
+
const tempDirs: string[] = [];
|
|
49
|
+
|
|
50
|
+
function freshRepo(prefix: string = "nmr-"): string {
|
|
51
|
+
const d = makeRepo(prefix);
|
|
52
|
+
tempDirs.push(d);
|
|
53
|
+
return d;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
for (const d of tempDirs) {
|
|
58
|
+
try {
|
|
59
|
+
git(d, "merge", "--abort");
|
|
60
|
+
} catch {
|
|
61
|
+
// no merge in progress — that is fine
|
|
62
|
+
}
|
|
63
|
+
if (existsSync(d)) rmSync(d, { recursive: true, force: true });
|
|
64
|
+
}
|
|
65
|
+
tempDirs.length = 0;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("success: returns { success: true, conflicts: [] } and sets MERGE_HEAD", () => {
|
|
69
|
+
const repo = freshRepo("nmr-success-");
|
|
70
|
+
git(repo, "checkout", "-b", "feature");
|
|
71
|
+
writeFileSync(join(repo, "feature.ts"), "export const a = 1;\n");
|
|
72
|
+
git(repo, "add", "feature.ts");
|
|
73
|
+
git(repo, "commit", "-m", "add feature");
|
|
74
|
+
git(repo, "checkout", "main");
|
|
75
|
+
|
|
76
|
+
const result = nativeMergeRegular(repo, "feature");
|
|
77
|
+
|
|
78
|
+
assert.equal(result.success, true);
|
|
79
|
+
assert.deepEqual(result.conflicts, []);
|
|
80
|
+
// --no-commit leaves MERGE_HEAD; nativeCommit sees it and creates two parents.
|
|
81
|
+
assert.ok(
|
|
82
|
+
existsSync(join(repo, ".git", "MERGE_HEAD")),
|
|
83
|
+
"MERGE_HEAD must exist after --no-ff --no-commit so the caller commits a true merge",
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("dirty working tree: returns __dirty_working_tree__ sentinel", () => {
|
|
88
|
+
const repo = freshRepo("nmr-dirty-");
|
|
89
|
+
|
|
90
|
+
// feature branch introduces feature.ts
|
|
91
|
+
git(repo, "checkout", "-b", "feature");
|
|
92
|
+
writeFileSync(join(repo, "feature.ts"), "export const x = 1;\n");
|
|
93
|
+
git(repo, "add", "feature.ts");
|
|
94
|
+
git(repo, "commit", "-m", "add feature");
|
|
95
|
+
git(repo, "checkout", "main");
|
|
96
|
+
|
|
97
|
+
// dirty uncommitted local file that the merge would overwrite
|
|
98
|
+
writeFileSync(join(repo, "feature.ts"), "// local dirty version\n");
|
|
99
|
+
|
|
100
|
+
const result = nativeMergeRegular(repo, "feature");
|
|
101
|
+
|
|
102
|
+
assert.equal(result.success, false);
|
|
103
|
+
assert.ok(
|
|
104
|
+
result.conflicts.includes("__dirty_working_tree__"),
|
|
105
|
+
`expected __dirty_working_tree__ sentinel, got: ${JSON.stringify(result.conflicts)}`,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("content conflict: returns conflicted file names, not dirty-tree sentinel", () => {
|
|
110
|
+
const repo = freshRepo("nmr-conflict-");
|
|
111
|
+
|
|
112
|
+
// Diverging history: both main and feature modify the same file region.
|
|
113
|
+
writeFileSync(join(repo, "shared.ts"), "// base\nexport const v = 0;\n");
|
|
114
|
+
git(repo, "add", "shared.ts");
|
|
115
|
+
git(repo, "commit", "-m", "base version");
|
|
116
|
+
|
|
117
|
+
git(repo, "checkout", "-b", "feature");
|
|
118
|
+
writeFileSync(join(repo, "shared.ts"), "// feature version\nexport const v = 2;\n");
|
|
119
|
+
git(repo, "add", "shared.ts");
|
|
120
|
+
git(repo, "commit", "-m", "feature changes shared");
|
|
121
|
+
|
|
122
|
+
git(repo, "checkout", "main");
|
|
123
|
+
writeFileSync(join(repo, "shared.ts"), "// main version\nexport const v = 1;\n");
|
|
124
|
+
git(repo, "add", "shared.ts");
|
|
125
|
+
git(repo, "commit", "-m", "main changes shared");
|
|
126
|
+
|
|
127
|
+
const result = nativeMergeRegular(repo, "feature");
|
|
128
|
+
|
|
129
|
+
assert.equal(result.success, false);
|
|
130
|
+
assert.ok(
|
|
131
|
+
result.conflicts.includes("shared.ts"),
|
|
132
|
+
`expected shared.ts in conflicts, got: ${JSON.stringify(result.conflicts)}`,
|
|
133
|
+
);
|
|
134
|
+
assert.ok(
|
|
135
|
+
!result.conflicts.includes("__dirty_working_tree__"),
|
|
136
|
+
"content conflict must not be misclassified as dirty-tree",
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: #442 Phase 3.14 — characterization battery proving the
|
|
3
|
+
// Orchestrator's dispatch DECISION matches what the legacy
|
|
4
|
+
// runPreDispatch/runDispatch path would produce, across representative
|
|
5
|
+
// resolveDispatch outcomes. This is the safety net that licenses deleting the
|
|
6
|
+
// dead legacy `else` branch in auto/loop.ts (loop never reaches it because
|
|
7
|
+
// ensureOrchestrationModule runs unconditionally before autoLoop, so
|
|
8
|
+
// s.orchestration is always set).
|
|
9
|
+
//
|
|
10
|
+
// Both paths delegate to the same resolveDispatch rule engine; the only thing
|
|
11
|
+
// that differs is how each TRANSLATES a resolveDispatch action into a loop
|
|
12
|
+
// outcome. We pin that translation equivalence here:
|
|
13
|
+
// resolveDispatch action | legacy runDispatch -> loop | orchestrator decision
|
|
14
|
+
// ------------------------|----------------------------|----------------------
|
|
15
|
+
// dispatch | IterationData(unit) | { unitType, unitId } (advanced)
|
|
16
|
+
// stop | break -> stopped/blocked | { kind: "blocked", action } | stopped
|
|
17
|
+
// skip | continue -> skipped | { kind: "skipped" }
|
|
18
|
+
// (no rule matches) | stop/no-unit | null -> stopped(no remaining)
|
|
19
|
+
|
|
20
|
+
import test from "node:test";
|
|
21
|
+
import assert from "node:assert/strict";
|
|
22
|
+
|
|
23
|
+
import { decideOrchestratorDispatch } from "../auto/orchestrator.ts";
|
|
24
|
+
import { resolveDispatch, type DispatchContext } from "../auto-dispatch.ts";
|
|
25
|
+
import { RuleRegistry, setRegistry, resetRegistry } from "../rule-registry.ts";
|
|
26
|
+
import type { UnifiedRule } from "../rule-types.ts";
|
|
27
|
+
import type { GSDState } from "../types.ts";
|
|
28
|
+
|
|
29
|
+
function makeState(): GSDState {
|
|
30
|
+
return {
|
|
31
|
+
activeMilestone: { id: "M001", title: "Milestone" },
|
|
32
|
+
activeSlice: null,
|
|
33
|
+
activeTask: null,
|
|
34
|
+
phase: "executing",
|
|
35
|
+
recentDecisions: [],
|
|
36
|
+
blockers: [],
|
|
37
|
+
nextAction: "Execute task",
|
|
38
|
+
registry: [],
|
|
39
|
+
requirements: { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 },
|
|
40
|
+
progress: { milestones: { done: 0, total: 1 } },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const fakeCtx = {
|
|
45
|
+
model: { provider: "anthropic", baseUrl: "https://api.anthropic.com", contextWindow: 200_000 },
|
|
46
|
+
modelRegistry: { getAll: () => [], getProviderAuthMode: (_p: string) => "apiKey" as const },
|
|
47
|
+
} as never;
|
|
48
|
+
const fakePi = { getActiveTools: () => ["read_file", "write_file"] } as never;
|
|
49
|
+
const BASE = "/tmp/orchestrator-legacy-parity";
|
|
50
|
+
|
|
51
|
+
function installRule(where: UnifiedRule["where"]): void {
|
|
52
|
+
setRegistry(new RuleRegistry([{
|
|
53
|
+
name: "parity-rule",
|
|
54
|
+
when: "dispatch",
|
|
55
|
+
evaluation: "first-match",
|
|
56
|
+
where,
|
|
57
|
+
then: (r: unknown) => r,
|
|
58
|
+
}]));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function directCtx(state: GSDState): DispatchContext {
|
|
62
|
+
return {
|
|
63
|
+
basePath: BASE,
|
|
64
|
+
mid: state.activeMilestone!.id,
|
|
65
|
+
midTitle: state.activeMilestone!.title,
|
|
66
|
+
state,
|
|
67
|
+
prefs: undefined,
|
|
68
|
+
structuredQuestionsAvailable: "true",
|
|
69
|
+
sessionContextWindow: 200_000,
|
|
70
|
+
sessionProvider: "anthropic",
|
|
71
|
+
modelRegistry: (fakeCtx as { modelRegistry: unknown }).modelRegistry as never,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
test("#442 characterization: dispatch action → orchestrator picks the same unit the legacy path would", async (t) => {
|
|
76
|
+
t.after(() => resetRegistry());
|
|
77
|
+
const state = makeState();
|
|
78
|
+
installRule(async () => ({ action: "dispatch", unitType: "execute-task", unitId: "T07", prompt: "p" }));
|
|
79
|
+
|
|
80
|
+
const legacy = await resolveDispatch(directCtx(state));
|
|
81
|
+
const decision = await decideOrchestratorDispatch(fakeCtx, fakePi, BASE, undefined, { stateSnapshot: state });
|
|
82
|
+
|
|
83
|
+
assert.equal((legacy as { action: string }).action, "dispatch");
|
|
84
|
+
assert.ok(decision && "unitType" in decision, "orchestrator must produce a unit decision");
|
|
85
|
+
assert.equal(decision.unitType, (legacy as { unitType: string }).unitType);
|
|
86
|
+
assert.equal(decision.unitId, (legacy as { unitId: string }).unitId);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("#442 characterization: stop action → orchestrator blocks with stop, matching legacy break", async (t) => {
|
|
90
|
+
t.after(() => resetRegistry());
|
|
91
|
+
const state = makeState();
|
|
92
|
+
installRule(async () => ({ action: "stop", reason: "milestone blocked" }));
|
|
93
|
+
|
|
94
|
+
const legacy = await resolveDispatch(directCtx(state));
|
|
95
|
+
const decision = await decideOrchestratorDispatch(fakeCtx, fakePi, BASE, undefined, { stateSnapshot: state });
|
|
96
|
+
|
|
97
|
+
assert.equal((legacy as { action: string }).action, "stop");
|
|
98
|
+
assert.ok(decision && "kind" in decision && decision.kind === "blocked", "stop must translate to a blocked decision");
|
|
99
|
+
assert.equal((decision as { action: string }).action, "stop");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("#442 characterization: skip action → orchestrator skips, matching legacy continue", async (t) => {
|
|
103
|
+
t.after(() => resetRegistry());
|
|
104
|
+
const state = makeState();
|
|
105
|
+
installRule(async () => ({ action: "skip", reason: "nothing to do this pass" }));
|
|
106
|
+
|
|
107
|
+
const legacy = await resolveDispatch(directCtx(state));
|
|
108
|
+
const decision = await decideOrchestratorDispatch(fakeCtx, fakePi, BASE, undefined, { stateSnapshot: state });
|
|
109
|
+
|
|
110
|
+
assert.equal((legacy as { action: string }).action, "skip");
|
|
111
|
+
assert.ok(decision && "kind" in decision && decision.kind === "skipped", "skip must translate to a skipped decision");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("#442 characterization: no matching rule → orchestrator yields no unit (legacy 'no remaining units')", async (t) => {
|
|
115
|
+
t.after(() => resetRegistry());
|
|
116
|
+
const state = makeState();
|
|
117
|
+
installRule(async () => null);
|
|
118
|
+
|
|
119
|
+
const legacy = await resolveDispatch(directCtx(state));
|
|
120
|
+
const decision = await decideOrchestratorDispatch(fakeCtx, fakePi, BASE, undefined, { stateSnapshot: state });
|
|
121
|
+
|
|
122
|
+
// resolveDispatch with no match yields no dispatch action; the orchestrator
|
|
123
|
+
// surfaces that as a null decision, which advance() turns into a "stopped:
|
|
124
|
+
// no remaining units" outcome — the same terminal the legacy path reaches.
|
|
125
|
+
assert.ok(legacy == null || (legacy as { action?: string }).action !== "dispatch");
|
|
126
|
+
assert.ok(decision == null || !("unitType" in decision), "no-match must not yield a unit dispatch");
|
|
127
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// gsd-pi / parseProject MILESTONE_LINE_RE bridging regression
|
|
2
|
+
//
|
|
3
|
+
// Guards against a silent data-integrity bug: MILESTONE_LINE_RE used `\s+`
|
|
4
|
+
// around its separator, and `\s` matches newlines. A milestone line lacking a
|
|
5
|
+
// valid internal separator could therefore "bridge" onto the NEXT bullet's
|
|
6
|
+
// `- `, consuming it as the separator and swallowing the following well-formed
|
|
7
|
+
// milestone. The separator gaps are now horizontal-whitespace-only so a line
|
|
8
|
+
// can never span a newline.
|
|
9
|
+
import { describe, test } from "node:test";
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
|
|
12
|
+
import { parseProject } from "../schemas/parsers.ts";
|
|
13
|
+
|
|
14
|
+
function milestoneSection(...lines: string[]): string {
|
|
15
|
+
return ["# Project", "", "## Milestone Sequence", "", ...lines, ""].join("\n");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe("parseProject milestone bridging", () => {
|
|
19
|
+
test("a malformed milestone line does not swallow the following well-formed one", () => {
|
|
20
|
+
// M001 uses an invalid " : " separator; M002 is canonical. Before the fix
|
|
21
|
+
// this returned a SINGLE match (M001 with oneLiner "[ ] M002: Baz — qux"),
|
|
22
|
+
// dropping M002 entirely.
|
|
23
|
+
const content = milestoneSection(
|
|
24
|
+
"- [ ] M001: Foo : bar",
|
|
25
|
+
"- [ ] M002: Baz — qux",
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const { milestones } = parseProject(content);
|
|
29
|
+
|
|
30
|
+
// M002 must survive intact — it must NOT be consumed as M001's one-liner.
|
|
31
|
+
const m002 = milestones.find(m => m.id === "M002");
|
|
32
|
+
assert.ok(m002, "M002 must be registered, not swallowed by the malformed M001 line");
|
|
33
|
+
assert.equal(m002!.title, "Baz", "M002 title parsed cleanly");
|
|
34
|
+
assert.equal(m002!.oneLiner, "qux", "M002 one-liner parsed cleanly");
|
|
35
|
+
|
|
36
|
+
// No milestone may have bridged the M002 bullet into its own one-liner.
|
|
37
|
+
assert.ok(
|
|
38
|
+
!milestones.some(m => m.oneLiner.includes("M002")),
|
|
39
|
+
"no milestone may bridge across the newline and consume the M002 bullet",
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// M001 has no valid separator, so it is skipped — consistent with the
|
|
43
|
+
// empty-parse hard-fail in execute-summary-save-empty-project.test.ts.
|
|
44
|
+
// The fixture therefore yields exactly the one well-formed milestone.
|
|
45
|
+
assert.deepEqual(milestones.map(m => m.id), ["M002"], "only the well-formed milestone parses");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("two well-formed milestones on adjacent lines both parse", () => {
|
|
49
|
+
const content = milestoneSection(
|
|
50
|
+
"- [x] M001: Foo — bar",
|
|
51
|
+
"- [ ] M002: Baz — qux",
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const { milestones } = parseProject(content);
|
|
55
|
+
assert.deepEqual(
|
|
56
|
+
milestones.map(m => ({ id: m.id, title: m.title, oneLiner: m.oneLiner, done: m.done })),
|
|
57
|
+
[
|
|
58
|
+
{ id: "M001", title: "Foo", oneLiner: "bar", done: true },
|
|
59
|
+
{ id: "M002", title: "Baz", oneLiner: "qux", done: false },
|
|
60
|
+
],
|
|
61
|
+
"adjacent canonical milestone lines are parsed independently",
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("a trailing malformed line cannot bridge onto a following bullet of any kind", () => {
|
|
66
|
+
// The last milestone is malformed and is followed by a non-milestone list
|
|
67
|
+
// bullet. The malformed line must be skipped without consuming the bullet.
|
|
68
|
+
const content = milestoneSection(
|
|
69
|
+
"- [ ] M001: Foo — bar",
|
|
70
|
+
"- [ ] M002: Baz : qux",
|
|
71
|
+
"- some unrelated bullet",
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const { milestones } = parseProject(content);
|
|
75
|
+
assert.deepEqual(milestones.map(m => m.id), ["M001"], "malformed M002 is skipped, not bridged onto the unrelated bullet");
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -347,3 +347,48 @@ test('handlePlanMilestone updates depends_on when a queued milestone row already
|
|
|
347
347
|
cleanup(base);
|
|
348
348
|
}
|
|
349
349
|
});
|
|
350
|
+
|
|
351
|
+
// Regression #566: bracket-wrapped slice ID in depends should be rejected
|
|
352
|
+
test('handlePlanMilestone rejects bracket-wrapped depends like ["[S01]"]', async () => {
|
|
353
|
+
const base = makeTmpBase();
|
|
354
|
+
const dbPath = join(base, '.gsd', 'gsd.db');
|
|
355
|
+
openDatabase(dbPath);
|
|
356
|
+
|
|
357
|
+
try {
|
|
358
|
+
const params = validParams();
|
|
359
|
+
// Simulate the LLM sending "[S01]" (the markdown fragment) instead of "S01"
|
|
360
|
+
const corruptSlices = [
|
|
361
|
+
params.slices[0],
|
|
362
|
+
{ ...params.slices[1], depends: ['[S01]'] },
|
|
363
|
+
];
|
|
364
|
+
const result = await handlePlanMilestone({ ...params, slices: corruptSlices }, base);
|
|
365
|
+
assert.ok('error' in result, 'should return an error for bracket-wrapped depends');
|
|
366
|
+
assert.match(result.error, /slices\[1\]\.depends must be an array of valid slice IDs/,
|
|
367
|
+
'error should mention invalid slice ID format');
|
|
368
|
+
assert.equal(getMilestoneSlices('M001').length, 0, 'no slices should persist on validation failure');
|
|
369
|
+
} finally {
|
|
370
|
+
cleanup(base);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Regression #566: unknown slice ID in depends should be rejected
|
|
375
|
+
test('handlePlanMilestone rejects depends referencing a slice not in the same milestone', async () => {
|
|
376
|
+
const base = makeTmpBase();
|
|
377
|
+
const dbPath = join(base, '.gsd', 'gsd.db');
|
|
378
|
+
openDatabase(dbPath);
|
|
379
|
+
|
|
380
|
+
try {
|
|
381
|
+
const params = validParams();
|
|
382
|
+
const corruptSlices = [
|
|
383
|
+
params.slices[0],
|
|
384
|
+
{ ...params.slices[1], depends: ['S99'] },
|
|
385
|
+
];
|
|
386
|
+
const result = await handlePlanMilestone({ ...params, slices: corruptSlices }, base);
|
|
387
|
+
assert.ok('error' in result, 'should return an error for unknown depends slice');
|
|
388
|
+
assert.match(result.error, /references unknown slice "S99"/,
|
|
389
|
+
'error should name the unknown slice');
|
|
390
|
+
assert.equal(getMilestoneSlices('M001').length, 0, 'no slices should persist on validation failure');
|
|
391
|
+
} finally {
|
|
392
|
+
cleanup(base);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
@@ -76,8 +76,10 @@ test("plan-slice prompt: compact planning gates survive template substitution",
|
|
|
76
76
|
assert.ok(result.includes("Bias toward \"roadmap is fine.\""), "roadmap reassessment brake should remain visible");
|
|
77
77
|
assert.ok(result.includes("Self-audit before finishing"), "self-audit gate should remain visible");
|
|
78
78
|
assert.ok(result.includes("Quality gates: non-trivial slices/tasks include specific Q3-Q7 coverage where applicable."));
|
|
79
|
-
assert.ok(result.includes("
|
|
80
|
-
assert.ok(result.includes("
|
|
79
|
+
assert.ok(result.includes("Use the inlined Output Template sections already present in this prompt."));
|
|
80
|
+
assert.ok(result.includes("Do not read template files from disk."));
|
|
81
|
+
assert.ok(!result.includes("C:\\Users\\Test\\.gsd\\agent\\extensions\\gsd\\templates\\plan.md"));
|
|
82
|
+
assert.ok(!result.includes("C:\\Users\\Test\\.gsd\\agent\\extensions\\gsd\\templates\\task-plan.md"));
|
|
81
83
|
assert.ok(!result.includes("{{templatesDir}}/plan.md"));
|
|
82
84
|
assert.ok(!result.includes("{{templatesDir}}/task-plan.md"));
|
|
83
85
|
assert.ok(!result.includes("{{"));
|
|
@@ -135,6 +137,7 @@ test("skillActivation default leaves no unresolved placeholder", () => {
|
|
|
135
137
|
carryForwardSection: "Carry forward",
|
|
136
138
|
resumeSection: "Resume",
|
|
137
139
|
priorTaskLines: "- (no prior tasks)",
|
|
140
|
+
onDemandContext: "",
|
|
138
141
|
templatesDir: join(fixtureRoot, "templates"),
|
|
139
142
|
taskSummaryPath: join(fixtureRoot, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"),
|
|
140
143
|
inlinedTemplates: "Template",
|
|
@@ -161,6 +164,7 @@ test("custom skillActivation is substituted into execute-task", () => {
|
|
|
161
164
|
carryForwardSection: "Carry forward",
|
|
162
165
|
resumeSection: "Resume",
|
|
163
166
|
priorTaskLines: "- (no prior tasks)",
|
|
167
|
+
onDemandContext: "",
|
|
164
168
|
templatesDir: join(fixtureRoot, "templates"),
|
|
165
169
|
taskSummaryPath: join(fixtureRoot, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-SUMMARY.md"),
|
|
166
170
|
inlinedTemplates: "Template",
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
insertTask,
|
|
16
16
|
getMilestoneSlices,
|
|
17
17
|
getSliceTasks,
|
|
18
|
+
_getAdapter,
|
|
18
19
|
} from '../gsd-db.ts';
|
|
19
20
|
import {
|
|
20
21
|
renderRoadmapFromDb,
|
|
@@ -423,4 +424,48 @@ console.log('\n=== planning-crossval Test 6: ROADMAP descriptor projection dir =
|
|
|
423
424
|
}
|
|
424
425
|
}
|
|
425
426
|
|
|
427
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
428
|
+
// Test 7: Renderer strips bracket-wrapped depends from corrupt DB rows (#566)
|
|
429
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
430
|
+
// Simulates a DB that was corrupted before the insertSlice validation guard
|
|
431
|
+
// was added (issue #566). The renderer must recover "[S01]" → "S01" rather
|
|
432
|
+
// than silently dropping the dependency and rendering depends:[].
|
|
433
|
+
|
|
434
|
+
console.log('\n=== planning-crossval Test 7: renderer recovers bracket-wrapped depends (#566) ===');
|
|
435
|
+
{
|
|
436
|
+
const base = realpathSync(createFixtureBase());
|
|
437
|
+
const dbPath = join(base, '.gsd', 'gsd.db');
|
|
438
|
+
openDatabase(dbPath);
|
|
439
|
+
try {
|
|
440
|
+
scaffoldDirs(base, 'M001', ['S01', 'S02']);
|
|
441
|
+
|
|
442
|
+
insertMilestone({
|
|
443
|
+
id: 'M001',
|
|
444
|
+
title: 'Bracket Recovery',
|
|
445
|
+
status: 'active',
|
|
446
|
+
planning: { vision: 'Recover bracket-wrapped depends from corrupt DB.' },
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
insertSlice({ id: 'S01', milestoneId: 'M001', title: 'Foundation', status: 'pending', risk: 'low', depends: [], demo: 'Foundation done.', sequence: 1 });
|
|
450
|
+
insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Build', status: 'pending', risk: 'medium', depends: [], demo: 'Build done.', sequence: 2 });
|
|
451
|
+
|
|
452
|
+
// Bypass insertSlice validation to simulate pre-fix corrupt DB state
|
|
453
|
+
// (insertSlice now rejects bracket-wrapped IDs, but old DBs may have them)
|
|
454
|
+
_getAdapter()?.prepare('UPDATE slices SET depends = ? WHERE id = ? AND milestone_id = ?')
|
|
455
|
+
.run('["[S01]"]', 'S02', 'M001');
|
|
456
|
+
|
|
457
|
+
const rendered = await renderRoadmapFromDb(base, 'M001');
|
|
458
|
+
const content = readFileSync(rendered.roadmapPath, 'utf-8');
|
|
459
|
+
const parsed = parseRoadmapSlices(content);
|
|
460
|
+
|
|
461
|
+
assertEq(parsed.length, 2, 'T7: 2 slices parsed');
|
|
462
|
+
assertEq(parsed[1]?.depends.length, 1, 'T7: S02 has 1 dependency after bracket recovery');
|
|
463
|
+
assertEq(parsed[1]?.depends[0], 'S01', 'T7: recovered dependency is "S01", not "[S01]"');
|
|
464
|
+
assertTrue(content.includes('`depends:[S01]`'), 'T7: S02 renders with recovered depends:[S01] not empty depends:[]');
|
|
465
|
+
} finally {
|
|
466
|
+
closeDatabase();
|
|
467
|
+
cleanup(base);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
426
471
|
report();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
_resetPreferenceDiagnosticNotificationsForTests,
|
|
9
|
+
notifyPreferenceDiagnostics,
|
|
10
|
+
} from "../preferences-diagnostics.ts";
|
|
11
|
+
import { _resetParseWarningFlag } from "../preferences.ts";
|
|
12
|
+
|
|
13
|
+
test("notifyPreferenceDiagnostics dedupes within a surface but re-surfaces across surfaces", (t) => {
|
|
14
|
+
const originalCwd = process.cwd();
|
|
15
|
+
const originalGsdHome = process.env.GSD_HOME;
|
|
16
|
+
const tempProject = mkdtempSync(join(tmpdir(), "gsd-prefs-notify-project-"));
|
|
17
|
+
const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-prefs-notify-home-"));
|
|
18
|
+
t.after(() => {
|
|
19
|
+
process.chdir(originalCwd);
|
|
20
|
+
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
|
|
21
|
+
else process.env.GSD_HOME = originalGsdHome;
|
|
22
|
+
rmSync(tempProject, { recursive: true, force: true });
|
|
23
|
+
rmSync(tempGsdHome, { recursive: true, force: true });
|
|
24
|
+
_resetPreferenceDiagnosticNotificationsForTests();
|
|
25
|
+
_resetParseWarningFlag();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
mkdirSync(join(tempProject, ".gsd"), { recursive: true });
|
|
29
|
+
process.env.GSD_HOME = tempGsdHome;
|
|
30
|
+
process.chdir(tempProject);
|
|
31
|
+
_resetPreferenceDiagnosticNotificationsForTests();
|
|
32
|
+
_resetParseWarningFlag();
|
|
33
|
+
|
|
34
|
+
writeFileSync(
|
|
35
|
+
join(tempProject, ".gsd", "PREFERENCES.md"),
|
|
36
|
+
"---\nversion: 3\n---\n",
|
|
37
|
+
"utf-8",
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const notifications: Array<{ message: string; type?: string }> = [];
|
|
41
|
+
const ctx = {
|
|
42
|
+
ui: {
|
|
43
|
+
notify(message: string, type?: "info" | "warning" | "error" | "success") {
|
|
44
|
+
notifications.push({ message, type });
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
assert.equal(
|
|
50
|
+
notifyPreferenceDiagnostics(ctx, tempProject, { surface: "session-start" }),
|
|
51
|
+
1,
|
|
52
|
+
);
|
|
53
|
+
assert.equal(
|
|
54
|
+
notifyPreferenceDiagnostics(ctx, tempProject, { surface: "session-start" }),
|
|
55
|
+
0,
|
|
56
|
+
);
|
|
57
|
+
assert.equal(
|
|
58
|
+
notifyPreferenceDiagnostics(ctx, tempProject, { surface: "auto-preflight" }),
|
|
59
|
+
1,
|
|
60
|
+
);
|
|
61
|
+
assert.equal(notifications.length, 2);
|
|
62
|
+
assert.equal(notifications[0]!.type, "error");
|
|
63
|
+
assert.match(notifications[0]!.message, /GSD project preferences error/);
|
|
64
|
+
assert.match(notifications[0]!.message, /unsupported version 3/);
|
|
65
|
+
assert.match(notifications[0]!.message, /Run \/gsd doctor for details/);
|
|
66
|
+
assert.equal(notifications[1]!.message, notifications[0]!.message);
|
|
67
|
+
});
|