@opengsd/gsd-pi 1.2.0-dev.e8563f58 → 1.2.0-dev.fbdca60b
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-model-override.d.ts +15 -0
- package/dist/cli-model-override.js +21 -0
- package/dist/cli.js +1 -18
- package/dist/loader.js +6 -4
- package/dist/register-agent-bundles.d.ts +11 -2
- package/dist/register-agent-bundles.js +18 -4
- package/dist/resource-loader.d.ts +10 -5
- package/dist/resource-loader.js +121 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +3 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
- package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +21 -6
- package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
- package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +85 -15
- package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
- package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
- package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
- package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +3 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +18 -6
- package/dist/resources/extensions/gsd/auto-start.js +23 -3
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
- package/dist/resources/extensions/gsd/auto.js +45 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/db/engine.js +24 -6
- package/dist/resources/extensions/gsd/db/queries.js +30 -0
- package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
- package/dist/resources/extensions/gsd/db-transaction.js +27 -23
- package/dist/resources/extensions/gsd/db-writer.js +8 -17
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
- package/dist/resources/extensions/gsd/gsd-db.js +15 -20
- package/dist/resources/extensions/gsd/guided-flow.js +93 -4
- package/dist/resources/extensions/gsd/health-widget.js +87 -28
- package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
- package/dist/resources/extensions/gsd/memory-relations.js +1 -1
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
- package/dist/resources/extensions/gsd/notifications.js +12 -7
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +3 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/skill-activation.js +3 -6
- package/dist/resources/extensions/gsd/state.js +6 -2
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
- package/dist/resources/extensions/gsd/unit-registry.js +34 -4
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
- package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/mcp-client/manager.js +6 -1
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/runtime-checks.d.ts +10 -0
- package/dist/runtime-checks.js +27 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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 +7 -7
- package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
- 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/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/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +3 -3
- 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/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +6 -4
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
- 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 +50 -6
- 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.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +12 -3
- package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
- package/packages/mcp-server/dist/cli-runner.js +137 -0
- package/packages/mcp-server/dist/cli-runner.js.map +1 -0
- package/packages/mcp-server/dist/cli.js +2 -53
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
- package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
- package/packages/mcp-server/dist/pid-registry.js +459 -0
- package/packages/mcp-server/dist/pid-registry.js.map +1 -0
- package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
- package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
- package/packages/mcp-server/dist/probe-mode.js +10 -0
- package/packages/mcp-server/dist/probe-mode.js.map +1 -0
- package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
- package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
- package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
- package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +62 -43
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -5
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +43 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/README.md +15 -0
- package/packages/pi-tui/dist/index.d.ts +2 -2
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -2
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
- package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal-image.js +54 -2
- package/packages/pi-tui/dist/terminal-image.js.map +1 -1
- package/packages/pi-tui/dist/terminal.d.ts +12 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +70 -25
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +15 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +106 -21
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +110 -36
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +45 -17
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +7 -2
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
- package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +22 -6
- package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
- package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +95 -15
- package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
- package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
- package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +10 -16
- package/src/resources/extensions/gsd/auto-dispatch.ts +11 -10
- package/src/resources/extensions/gsd/auto-post-unit.ts +21 -6
- package/src/resources/extensions/gsd/auto-start.ts +24 -4
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
- package/src/resources/extensions/gsd/auto.ts +56 -2
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/db/engine.ts +26 -6
- package/src/resources/extensions/gsd/db/queries.ts +29 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
- package/src/resources/extensions/gsd/db-transaction.ts +37 -20
- package/src/resources/extensions/gsd/db-writer.ts +11 -19
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
- package/src/resources/extensions/gsd/gsd-db.ts +15 -19
- package/src/resources/extensions/gsd/guided-flow.ts +145 -24
- package/src/resources/extensions/gsd/health-widget.ts +91 -27
- package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
- package/src/resources/extensions/gsd/memory-relations.ts +1 -1
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
- package/src/resources/extensions/gsd/notifications.ts +13 -6
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +3 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/skill-activation.ts +3 -6
- package/src/resources/extensions/gsd/state.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +76 -12
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
- package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
- package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
- package/src/resources/extensions/gsd/unit-registry.ts +34 -4
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
- package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/mcp-client/manager.ts +7 -1
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
|
@@ -5,103 +5,53 @@
|
|
|
5
5
|
* as a fire-and-forget side-effect so that Telegram/Slack/Discord channels
|
|
6
6
|
* receive the same events as native desktop notifications.
|
|
7
7
|
*
|
|
8
|
-
* Testing strategy (
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* 2. The sendDesktopNotification function body calls sendRemoteNotification
|
|
14
|
-
* with title and message as arguments.
|
|
15
|
-
* 3. The call uses the void fire-and-forget pattern with a .catch(() => {})
|
|
16
|
-
* suppressor so that async failures never break the synchronous caller.
|
|
8
|
+
* Testing strategy (behavioral):
|
|
9
|
+
* Import sendDesktopNotification and the swappable remoteNotificationDispatcher.
|
|
10
|
+
* Mock the dispatcher's send method, call sendDesktopNotification, and assert
|
|
11
|
+
* that the dispatcher received the same title/message and that the call is
|
|
12
|
+
* fire-and-forget (the function returns without awaiting).
|
|
17
13
|
*
|
|
18
14
|
* Relates to #4341.
|
|
19
15
|
*/
|
|
20
16
|
|
|
21
17
|
import test from "node:test";
|
|
22
18
|
import assert from "node:assert/strict";
|
|
23
|
-
import { readFileSync } from "node:fs";
|
|
24
|
-
import { join, dirname } from "node:path";
|
|
25
|
-
import { fileURLToPath } from "node:url";
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
import {
|
|
21
|
+
sendDesktopNotification,
|
|
22
|
+
remoteNotificationDispatcher,
|
|
23
|
+
} from "../notifications.js";
|
|
29
24
|
|
|
30
|
-
test("
|
|
31
|
-
const
|
|
32
|
-
SOURCE.includes('from "../remote-questions/notify.js"') ||
|
|
33
|
-
SOURCE.includes("from '../remote-questions/notify.js'");
|
|
34
|
-
assert.ok(
|
|
35
|
-
hasImport,
|
|
36
|
-
"notifications.ts must import from '../remote-questions/notify.js'",
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const importLine = SOURCE.split("\n").find(
|
|
40
|
-
(line) =>
|
|
41
|
-
line.includes("sendRemoteNotification") &&
|
|
42
|
-
(line.includes("remote-questions/notify") || line.includes("remote-questions/notify.js")),
|
|
43
|
-
);
|
|
44
|
-
assert.ok(
|
|
45
|
-
importLine,
|
|
46
|
-
"The import statement must include sendRemoteNotification from the remote-questions/notify module",
|
|
47
|
-
);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("sendDesktopNotification calls sendRemoteNotification(title, message)", () => {
|
|
51
|
-
// Extract the body of sendDesktopNotification — from its opening brace to the
|
|
52
|
-
// closing brace at the same indentation level.
|
|
53
|
-
const fnStart = SOURCE.indexOf("export function sendDesktopNotification(");
|
|
54
|
-
assert.ok(fnStart > -1, "sendDesktopNotification must be present in notifications.ts");
|
|
25
|
+
test("sendDesktopNotification calls sendRemoteNotification with title and message", async (t) => {
|
|
26
|
+
const sendMock = t.mock.method(remoteNotificationDispatcher, "send", async () => {});
|
|
55
27
|
|
|
56
|
-
|
|
57
|
-
const nextExportIdx = SOURCE.indexOf("\nexport ", fnStart + 1);
|
|
58
|
-
const fnBody = nextExportIdx > -1 ? SOURCE.slice(fnStart, nextExportIdx) : SOURCE.slice(fnStart);
|
|
59
|
-
|
|
60
|
-
assert.ok(
|
|
61
|
-
fnBody.includes("sendRemoteNotification"),
|
|
62
|
-
"sendDesktopNotification must call sendRemoteNotification",
|
|
63
|
-
);
|
|
28
|
+
sendDesktopNotification("Test Title", "Test Message");
|
|
64
29
|
|
|
65
|
-
assert.
|
|
66
|
-
|
|
67
|
-
"sendRemoteNotification must be called with title as first argument",
|
|
68
|
-
);
|
|
30
|
+
assert.equal(sendMock.mock.callCount(), 1);
|
|
31
|
+
assert.deepEqual(sendMock.mock.calls[0].arguments, ["Test Title", "Test Message"]);
|
|
69
32
|
});
|
|
70
33
|
|
|
71
|
-
test("
|
|
72
|
-
const
|
|
73
|
-
const nextExportIdx = SOURCE.indexOf("\nexport ", fnStart + 1);
|
|
74
|
-
const fnBody = nextExportIdx > -1 ? SOURCE.slice(fnStart, nextExportIdx) : SOURCE.slice(fnStart);
|
|
34
|
+
test("sendDesktopNotification does not await the remote notification", async (t) => {
|
|
35
|
+
const sendMock = t.mock.method(remoteNotificationDispatcher, "send", async () => {});
|
|
75
36
|
|
|
76
|
-
|
|
77
|
-
fnBody.includes("void sendRemoteNotification("),
|
|
78
|
-
"sendRemoteNotification must be called with void (fire-and-forget)",
|
|
79
|
-
);
|
|
37
|
+
const result = sendDesktopNotification("Async Title", "Async Message");
|
|
80
38
|
|
|
81
|
-
assert.
|
|
82
|
-
|
|
83
|
-
"sendRemoteNotification call must be followed by .catch() to suppress unhandled-rejection warnings",
|
|
84
|
-
);
|
|
39
|
+
assert.equal(result, undefined, "sendDesktopNotification must return void");
|
|
40
|
+
assert.equal(sendMock.mock.callCount(), 1);
|
|
85
41
|
});
|
|
86
42
|
|
|
87
|
-
test("
|
|
88
|
-
|
|
89
|
-
// gated behind the desktop-notification preference check. Users who disable
|
|
90
|
-
// desktop notifications must still receive Telegram/Slack/Discord messages.
|
|
91
|
-
const fnStart = SOURCE.indexOf("export function sendDesktopNotification(");
|
|
92
|
-
assert.ok(fnStart > -1, "sendDesktopNotification must be present in notifications.ts");
|
|
93
|
-
|
|
94
|
-
const nextExportIdx = SOURCE.indexOf("\nexport ", fnStart + 1);
|
|
95
|
-
const fnBody = nextExportIdx > -1 ? SOURCE.slice(fnStart, nextExportIdx) : SOURCE.slice(fnStart);
|
|
43
|
+
test("sendDesktopNotification fires remote notification even when desktop notifications are disabled", async (t) => {
|
|
44
|
+
const sendMock = t.mock.method(remoteNotificationDispatcher, "send", async () => {});
|
|
96
45
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
remoteCallIdx < guardIdx,
|
|
105
|
-
`sendRemoteNotification (pos ${remoteCallIdx}) must appear BEFORE the shouldSendDesktopNotification guard (pos ${guardIdx}) so that remote channels fire even when desktop notifications are disabled`,
|
|
46
|
+
sendDesktopNotification(
|
|
47
|
+
"Remote Title",
|
|
48
|
+
"Remote Message",
|
|
49
|
+
"info",
|
|
50
|
+
"complete",
|
|
51
|
+
undefined,
|
|
52
|
+
{ notifications: { enabled: false } },
|
|
106
53
|
);
|
|
54
|
+
|
|
55
|
+
assert.equal(sendMock.mock.callCount(), 1);
|
|
56
|
+
assert.deepEqual(sendMock.mock.calls[0].arguments, ["Remote Title", "Remote Message"]);
|
|
107
57
|
});
|
|
@@ -200,6 +200,74 @@ test("parseRoadmapSlices: checkbox slices with pipe characters do not switch to
|
|
|
200
200
|
assert.deepEqual(slices[2]?.depends, ["S01", "S02"]);
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
+
test("parseRoadmapSlices: demo markdown table does not switch checkbox roadmap to table mode (#721)", () => {
|
|
204
|
+
const checkboxWithDemoTable = [
|
|
205
|
+
"# M004: Demo Table Repro",
|
|
206
|
+
"",
|
|
207
|
+
"## Slices",
|
|
208
|
+
"",
|
|
209
|
+
"- [x] **S01: First** `risk:low` `depends:[]`",
|
|
210
|
+
" > After this: cli can render examples:",
|
|
211
|
+
"| Example | Meaning |",
|
|
212
|
+
"| --- | --- |",
|
|
213
|
+
"| S01 | Not a roadmap row |",
|
|
214
|
+
"- [ ] **S02: Second** `risk:medium` `depends:[S01]`",
|
|
215
|
+
" > After this: cat file | sort returns stable output.",
|
|
216
|
+
"",
|
|
217
|
+
].join("\n");
|
|
218
|
+
|
|
219
|
+
const slices = parseRoadmapSlices(checkboxWithDemoTable);
|
|
220
|
+
assert.equal(slices.length, 2);
|
|
221
|
+
assert.equal(slices[0]?.id, "S01");
|
|
222
|
+
assert.equal(slices[0]?.title, "First");
|
|
223
|
+
assert.equal(slices[0]?.done, true);
|
|
224
|
+
assert.equal(slices[1]?.id, "S02");
|
|
225
|
+
assert.deepEqual(slices[1]?.depends, ["S01"]);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("parseRoadmapSlices: table preceded by intro prose still parsed as table (#722)", () => {
|
|
229
|
+
const tableWithIntro = [
|
|
230
|
+
"# M005: Intro Before Table",
|
|
231
|
+
"",
|
|
232
|
+
"## Slices",
|
|
233
|
+
"",
|
|
234
|
+
"This milestone is broken into the following slices:",
|
|
235
|
+
"",
|
|
236
|
+
"| Slice | Title | Risk | Status |",
|
|
237
|
+
"| --- | --- | --- | --- |",
|
|
238
|
+
"| S01 | Foundation | Low | [x] Done |",
|
|
239
|
+
"| S02 | Core | High | [ ] Pending |",
|
|
240
|
+
"",
|
|
241
|
+
].join("\n");
|
|
242
|
+
|
|
243
|
+
const slices = parseRoadmapSlices(tableWithIntro);
|
|
244
|
+
assert.equal(slices.length, 2);
|
|
245
|
+
assert.equal(slices[0]?.id, "S01");
|
|
246
|
+
assert.equal(slices[0]?.done, true);
|
|
247
|
+
assert.equal(slices[1]?.id, "S02");
|
|
248
|
+
assert.equal(slices[1]?.done, false);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test("parseRoadmapSlices: table without markdown separator row still parsed as table (#722)", () => {
|
|
252
|
+
const tableWithoutSeparator = [
|
|
253
|
+
"# M006: No Separator",
|
|
254
|
+
"",
|
|
255
|
+
"## Slices",
|
|
256
|
+
"",
|
|
257
|
+
"| Slice | Title | Risk | Status |",
|
|
258
|
+
"| S01 | Foundation | Low | [x] Done |",
|
|
259
|
+
"| S02 | Core | High | [ ] Pending |",
|
|
260
|
+
"",
|
|
261
|
+
].join("\n");
|
|
262
|
+
|
|
263
|
+
const slices = parseRoadmapSlices(tableWithoutSeparator);
|
|
264
|
+
assert.equal(slices.length, 2);
|
|
265
|
+
assert.equal(slices[0]?.id, "S01");
|
|
266
|
+
assert.equal(slices[0]?.done, true);
|
|
267
|
+
assert.equal(slices[1]?.id, "S02");
|
|
268
|
+
assert.equal(slices[1]?.done, false);
|
|
269
|
+
});
|
|
270
|
+
|
|
203
271
|
// --- Prose slice header completion marker tests (#1803) ---
|
|
204
272
|
|
|
205
273
|
test("parseRoadmapSlices: prose headers with ✓ marker detected as done", () => {
|
|
@@ -6,7 +6,11 @@ import assert from "node:assert/strict";
|
|
|
6
6
|
|
|
7
7
|
import { classifyFailure } from "../recovery-classification.js";
|
|
8
8
|
import { reconcileBeforeDispatch } from "../state-reconciliation.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
compileUnitContextContract,
|
|
11
|
+
compileUnitToolContract,
|
|
12
|
+
getUnitWorkflowDispatchReadinessError,
|
|
13
|
+
} from "../tool-contract.js";
|
|
10
14
|
import { shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
|
|
11
15
|
import type { GSDState } from "../types.js";
|
|
12
16
|
|
|
@@ -63,7 +67,13 @@ test("Tool Contract compiles known Unit prompt and tool policy", () => {
|
|
|
63
67
|
|
|
64
68
|
assert.equal(result.ok, true);
|
|
65
69
|
assert.equal(result.ok && result.contract.unitType, "execute-task");
|
|
66
|
-
assert.deepEqual(result.ok && result.contract.requiredWorkflowTools, [
|
|
70
|
+
assert.deepEqual(result.ok && result.contract.requiredWorkflowTools, [
|
|
71
|
+
"gsd_task_complete",
|
|
72
|
+
"gsd_exec",
|
|
73
|
+
"gsd_exec_search",
|
|
74
|
+
"gsd_resume",
|
|
75
|
+
"gsd_capture_thought",
|
|
76
|
+
]);
|
|
67
77
|
assert.deepEqual(result.ok && result.contract.forbiddenWorkflowTools, []);
|
|
68
78
|
assert.equal(result.ok && result.contract.toolsPolicy.mode, "all");
|
|
69
79
|
assert.ok(result.ok && result.contract.validationRules.includes("closeout-tool-present"));
|
|
@@ -87,6 +97,20 @@ test("Tool Contract compiles known Unit prompt and tool policy", () => {
|
|
|
87
97
|
});
|
|
88
98
|
});
|
|
89
99
|
|
|
100
|
+
test("Tool Contract derives dispatch readiness from Unit workflow tools", () => {
|
|
101
|
+
const error = getUnitWorkflowDispatchReadinessError({
|
|
102
|
+
provider: "claude-code",
|
|
103
|
+
unitType: "plan-slice",
|
|
104
|
+
projectRoot: "/tmp/project",
|
|
105
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
106
|
+
surface: "auto-mode",
|
|
107
|
+
authMode: "externalCli",
|
|
108
|
+
baseUrl: "local://claude-code",
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
assert.equal(error, null);
|
|
112
|
+
});
|
|
113
|
+
|
|
90
114
|
test("Unit Context Contract exposes prompt context without workflow tool surface", () => {
|
|
91
115
|
const result = compileUnitContextContract("execute-task");
|
|
92
116
|
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
// Structural invariant: gsd-db.ts
|
|
1
|
+
// Structural invariant: gsd-db.ts and the typed writer layer own writes for .gsd/gsd.db.
|
|
2
2
|
//
|
|
3
3
|
// No file under src/resources/extensions/gsd/ may issue raw write SQL
|
|
4
4
|
// (INSERT/UPDATE/DELETE/REPLACE) or raw transaction control (BEGIN/COMMIT/
|
|
5
5
|
// ROLLBACK via `.exec(...)`) against the engine database. Every bypass must
|
|
6
|
-
// route through
|
|
6
|
+
// route through an explicitly allowlisted typed writer.
|
|
7
7
|
//
|
|
8
8
|
// Allowlist:
|
|
9
|
-
// - gsd-db.ts itself —
|
|
9
|
+
// - gsd-db.ts itself — compatibility barrel and remaining mid-migration wrappers
|
|
10
|
+
// - db/engine.ts — schema, migrations, lifecycle, and transaction primitives
|
|
11
|
+
// - db/writers/** — domain writers
|
|
12
|
+
// - typed coordination/runtime writer modules listed in TYPED_DB_WRITER_FILES
|
|
13
|
+
// - schema/migration helper modules listed in SCHEMA_DB_WRITER_FILES
|
|
14
|
+
// - ADR migration/backfill helpers listed in MIGRATION_BACKFILL_WRITER_FILES
|
|
10
15
|
// - unit-ownership.ts — manages a separate .gsd/unit-claims.db for
|
|
11
16
|
// cross-worktree claim races; intentionally outside this invariant
|
|
12
17
|
// - tests/** — fixtures and direct DB inspection are fair game
|
|
13
18
|
//
|
|
14
19
|
// When this test fails, do not add a new suppression. Instead:
|
|
15
|
-
// 1. Add a typed wrapper to
|
|
20
|
+
// 1. Add a typed wrapper to the explicit writer layer that captures the SQL
|
|
16
21
|
// 2. Switch the flagged site to call the wrapper
|
|
17
22
|
//
|
|
18
23
|
// See `.claude/plans/joyful-doodling-pony.md` for the full rationale.
|
|
@@ -29,17 +34,50 @@ const gsdDir = join(process.cwd(), "src/resources/extensions/gsd");
|
|
|
29
34
|
// - db/engine.ts — connection lifecycle, schema/migrations (DDL), and the
|
|
30
35
|
// BEGIN/COMMIT transaction primitives. The shared handle every writer reads.
|
|
31
36
|
// - db/writers/**.ts — the Single Writer Layer: one cohesive write subsystem
|
|
32
|
-
// per file
|
|
33
|
-
// legacy-import, cascades).
|
|
37
|
+
// per file.
|
|
34
38
|
// - gsd-db.ts — the barrel that re-exports the layer (still holds wrappers
|
|
35
39
|
// mid-migration).
|
|
40
|
+
// - typed coordination/runtime writers listed below.
|
|
41
|
+
// - schema/migration helpers listed below.
|
|
42
|
+
// - ADR migration/backfill helpers listed below.
|
|
36
43
|
// - unit-ownership.ts — a separate .gsd/unit-claims.db, intentionally outside.
|
|
37
44
|
// db/queries.ts is explicitly NOT allowed write SQL (asserted separately below).
|
|
45
|
+
const TYPED_DB_WRITER_FILES = new Set([
|
|
46
|
+
"db/auto-workers.ts",
|
|
47
|
+
"db/command-queue.ts",
|
|
48
|
+
"db/milestone-leases.ts",
|
|
49
|
+
"db/runtime-kv.ts",
|
|
50
|
+
"db/unit-dispatches.ts",
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
const SCHEMA_DB_WRITER_FILES = new Set([
|
|
54
|
+
"db-memory-fts-schema.ts",
|
|
55
|
+
"db-schema-metadata.ts",
|
|
56
|
+
"db-verification-evidence-schema.ts",
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
const MIGRATION_BACKFILL_WRITER_FILES = new Set([
|
|
60
|
+
"memory-backfill.ts",
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
const DB_WRITER_ALLOWLIST_GUIDANCE = [
|
|
64
|
+
"gsd-db.ts",
|
|
65
|
+
"db/engine.ts",
|
|
66
|
+
"db/writers/**",
|
|
67
|
+
...TYPED_DB_WRITER_FILES,
|
|
68
|
+
...SCHEMA_DB_WRITER_FILES,
|
|
69
|
+
...MIGRATION_BACKFILL_WRITER_FILES,
|
|
70
|
+
"unit-ownership.ts only for .gsd/unit-claims.db",
|
|
71
|
+
].join(", ");
|
|
72
|
+
|
|
38
73
|
function isSingleWriterFile(rel: string): boolean {
|
|
39
74
|
const norm = rel.split("\\").join("/");
|
|
40
75
|
if (norm === "gsd-db.ts" || norm === "unit-ownership.ts") return true;
|
|
41
76
|
if (norm === "db/engine.ts") return true;
|
|
42
77
|
if (norm.startsWith("db/writers/") && norm.endsWith(".ts")) return true;
|
|
78
|
+
if (TYPED_DB_WRITER_FILES.has(norm)) return true;
|
|
79
|
+
if (SCHEMA_DB_WRITER_FILES.has(norm)) return true;
|
|
80
|
+
if (MIGRATION_BACKFILL_WRITER_FILES.has(norm)) return true;
|
|
43
81
|
return false;
|
|
44
82
|
}
|
|
45
83
|
|
|
@@ -83,11 +121,126 @@ interface Violation {
|
|
|
83
121
|
kind: string;
|
|
84
122
|
}
|
|
85
123
|
|
|
86
|
-
|
|
87
|
-
const
|
|
124
|
+
const DB_CALL_RE = /\.(prepare|exec)\s*\(/g;
|
|
125
|
+
const PREPARE_WRITE_SQL_RE = /\b(INSERT|UPDATE|DELETE|REPLACE)\b/i;
|
|
126
|
+
const EXEC_WRITE_SQL_RE = /\b(INSERT|UPDATE|DELETE|REPLACE|BEGIN|COMMIT|ROLLBACK)\b/i;
|
|
127
|
+
|
|
128
|
+
function findRawWriteSqlViolations(file: string, content: string): Violation[] {
|
|
129
|
+
const violations: Violation[] = [];
|
|
130
|
+
DB_CALL_RE.lastIndex = 0;
|
|
131
|
+
|
|
132
|
+
let match: RegExpExecArray | null;
|
|
133
|
+
while ((match = DB_CALL_RE.exec(content)) !== null) {
|
|
134
|
+
const method = match[1] as "prepare" | "exec";
|
|
135
|
+
const sql = readFirstStringArgument(content, DB_CALL_RE.lastIndex);
|
|
136
|
+
if (sql === null) continue;
|
|
137
|
+
|
|
138
|
+
const keywordMatch =
|
|
139
|
+
method === "prepare"
|
|
140
|
+
? PREPARE_WRITE_SQL_RE.exec(sql)
|
|
141
|
+
: EXEC_WRITE_SQL_RE.exec(sql);
|
|
142
|
+
if (keywordMatch === null) continue;
|
|
143
|
+
|
|
144
|
+
violations.push({
|
|
145
|
+
file,
|
|
146
|
+
line: lineNumberAt(content, match.index),
|
|
147
|
+
snippet: lineSnippetAt(content, match.index),
|
|
148
|
+
kind: `${method}(${keywordMatch[1].toUpperCase()})`,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return violations;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function readFirstStringArgument(content: string, index: number): string | null {
|
|
156
|
+
const quoteIndex = skipWhitespace(content, index);
|
|
157
|
+
const quote = content[quoteIndex];
|
|
158
|
+
if (quote !== "`" && quote !== "'" && quote !== '"') return null;
|
|
159
|
+
return readStringLiteral(content, quoteIndex, quote);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function skipWhitespace(content: string, index: number): number {
|
|
163
|
+
let cursor = index;
|
|
164
|
+
while (cursor < content.length && /\s/.test(content[cursor] ?? "")) {
|
|
165
|
+
cursor++;
|
|
166
|
+
}
|
|
167
|
+
return cursor;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function readStringLiteral(content: string, quoteIndex: number, quote: string): string | null {
|
|
171
|
+
let value = "";
|
|
172
|
+
|
|
173
|
+
for (let cursor = quoteIndex + 1; cursor < content.length; cursor++) {
|
|
174
|
+
const char = content[cursor];
|
|
175
|
+
if (char === "\\") {
|
|
176
|
+
value += char;
|
|
177
|
+
cursor++;
|
|
178
|
+
if (cursor < content.length) value += content[cursor];
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (char === quote) return value;
|
|
182
|
+
value += char;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function lineNumberAt(content: string, index: number): number {
|
|
189
|
+
return content.slice(0, index).split("\n").length;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function lineSnippetAt(content: string, index: number): string {
|
|
193
|
+
const lineStart = content.lastIndexOf("\n", index) + 1;
|
|
194
|
+
const nextNewline = content.indexOf("\n", index);
|
|
195
|
+
const lineEnd = nextNewline === -1 ? content.length : nextNewline;
|
|
196
|
+
return content.slice(lineStart, lineEnd).trim();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
test("scanner catches multiline template-literal db.prepare write SQL", () => {
|
|
200
|
+
const violations = findRawWriteSqlViolations(
|
|
201
|
+
"fixture.ts",
|
|
202
|
+
[
|
|
203
|
+
"const stmt = db.prepare(",
|
|
204
|
+
" `INSERT INTO tasks (id)",
|
|
205
|
+
" VALUES (?)`",
|
|
206
|
+
");",
|
|
207
|
+
].join("\n"),
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
assert.deepEqual(violations.map(({ line, kind }) => ({ line, kind })), [
|
|
211
|
+
{ line: 1, kind: "prepare(INSERT)" },
|
|
212
|
+
]);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test("scanner catches multiline raw transaction control in exec", () => {
|
|
216
|
+
const violations = findRawWriteSqlViolations(
|
|
217
|
+
"fixture.ts",
|
|
218
|
+
[
|
|
219
|
+
"db.exec(",
|
|
220
|
+
" `BEGIN`",
|
|
221
|
+
");",
|
|
222
|
+
].join("\n"),
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
assert.deepEqual(violations.map(({ line, kind }) => ({ line, kind })), [
|
|
226
|
+
{ line: 1, kind: "exec(BEGIN)" },
|
|
227
|
+
]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test("scanner ignores multiline SELECT statements", () => {
|
|
231
|
+
const violations = findRawWriteSqlViolations(
|
|
232
|
+
"fixture.ts",
|
|
233
|
+
[
|
|
234
|
+
"const stmt = db.prepare(",
|
|
235
|
+
" `SELECT id",
|
|
236
|
+
" FROM tasks`",
|
|
237
|
+
");",
|
|
238
|
+
].join("\n"),
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
assert.deepEqual(violations, []);
|
|
242
|
+
});
|
|
88
243
|
|
|
89
|
-
// Match .exec("... INSERT|UPDATE|DELETE|REPLACE ...") or raw BEGIN/COMMIT/ROLLBACK.
|
|
90
|
-
const EXEC_WRITE_RE = /\.exec\s*\(\s*[`'"][^`'"]*\b(INSERT|UPDATE|DELETE|REPLACE|BEGIN|COMMIT|ROLLBACK)\b/i;
|
|
91
244
|
const DB_WORKSPACE_MECHANICS = new Set([
|
|
92
245
|
"backupDatabaseSnapshot",
|
|
93
246
|
"checkpointDatabase",
|
|
@@ -112,7 +265,7 @@ function importNames(specifierBlock: string): string[] {
|
|
|
112
265
|
.filter(Boolean);
|
|
113
266
|
}
|
|
114
267
|
|
|
115
|
-
test("no module outside
|
|
268
|
+
test("no module outside the explicit DB writer allowlist issues raw write SQL", () => {
|
|
116
269
|
const files = walkTsFiles(gsdDir);
|
|
117
270
|
assert.ok(files.length >= 20, `Expected at least 20 .ts files under gsd/, found ${files.length}`);
|
|
118
271
|
|
|
@@ -129,30 +282,7 @@ test("no module outside gsd-db.ts issues raw write SQL against the engine DB", (
|
|
|
129
282
|
continue;
|
|
130
283
|
}
|
|
131
284
|
|
|
132
|
-
|
|
133
|
-
for (let i = 0; i < lines.length; i++) {
|
|
134
|
-
const line = lines[i];
|
|
135
|
-
|
|
136
|
-
const prepareMatch = PREPARE_WRITE_RE.exec(line);
|
|
137
|
-
if (prepareMatch) {
|
|
138
|
-
violations.push({
|
|
139
|
-
file: rel,
|
|
140
|
-
line: i + 1,
|
|
141
|
-
snippet: line.trim(),
|
|
142
|
-
kind: `prepare(${prepareMatch[1].toUpperCase()})`,
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const execMatch = EXEC_WRITE_RE.exec(line);
|
|
147
|
-
if (execMatch) {
|
|
148
|
-
violations.push({
|
|
149
|
-
file: rel,
|
|
150
|
-
line: i + 1,
|
|
151
|
-
snippet: line.trim(),
|
|
152
|
-
kind: `exec(${execMatch[1].toUpperCase()})`,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
285
|
+
violations.push(...findRawWriteSqlViolations(rel, content));
|
|
156
286
|
}
|
|
157
287
|
|
|
158
288
|
if (violations.length > 0) {
|
|
@@ -160,9 +290,9 @@ test("no module outside gsd-db.ts issues raw write SQL against the engine DB", (
|
|
|
160
290
|
(v) => ` ${v.file}:${v.line} [${v.kind}] — ${v.snippet}`,
|
|
161
291
|
);
|
|
162
292
|
assert.fail(
|
|
163
|
-
`Found ${violations.length} raw write SQL bypass(es) outside
|
|
293
|
+
`Found ${violations.length} raw write SQL bypass(es) outside the explicit DB writer allowlist:\n` +
|
|
164
294
|
lines.join("\n") +
|
|
165
|
-
|
|
295
|
+
`\n\nMove each write to the appropriate allowlisted owner: ${DB_WRITER_ALLOWLIST_GUIDANCE}.`,
|
|
166
296
|
);
|
|
167
297
|
}
|
|
168
298
|
});
|
|
@@ -174,19 +304,11 @@ test("db/queries.ts (the Query Module) is read-only — contains no write SQL",
|
|
|
174
304
|
// db/writers/ — this is the explicit, positive statement of intent.)
|
|
175
305
|
const queriesPath = join(gsdDir, "db", "queries.ts");
|
|
176
306
|
const content = readFileSync(queriesPath, "utf-8");
|
|
177
|
-
const
|
|
178
|
-
const violations: Violation[] = [];
|
|
179
|
-
for (let i = 0; i < lines.length; i++) {
|
|
180
|
-
const line = lines[i];
|
|
181
|
-
const m = PREPARE_WRITE_RE.exec(line) ?? EXEC_WRITE_RE.exec(line);
|
|
182
|
-
if (m) {
|
|
183
|
-
violations.push({ file: "db/queries.ts", line: i + 1, snippet: line.trim(), kind: m[1].toUpperCase() });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
307
|
+
const violations = findRawWriteSqlViolations("db/queries.ts", content);
|
|
186
308
|
assert.equal(
|
|
187
309
|
violations.length,
|
|
188
310
|
0,
|
|
189
|
-
`db/queries.ts must contain no write SQL — move write wrappers to
|
|
311
|
+
`db/queries.ts must contain no write SQL — move write wrappers to the explicit DB writer allowlist:\n` +
|
|
190
312
|
violations.map((v) => ` db/queries.ts:${v.line} [${v.kind}] — ${v.snippet}`).join("\n"),
|
|
191
313
|
);
|
|
192
314
|
});
|
|
@@ -299,7 +421,7 @@ test("production modules do not import DB open-state mechanics from gsd-db.ts",
|
|
|
299
421
|
assert.fail(
|
|
300
422
|
`Found ${violations.length} DB open-state import(s) from gsd-db.ts:\n` +
|
|
301
423
|
lines.join("\n") +
|
|
302
|
-
"\n\nImport these through db-workspace.ts so gsd-db.ts stays the
|
|
424
|
+
"\n\nImport these through db-workspace.ts so gsd-db.ts stays the writer compatibility barrel, not the caller-facing DB Workspace Interface.",
|
|
303
425
|
);
|
|
304
426
|
}
|
|
305
427
|
});
|
|
@@ -92,14 +92,14 @@ test("buildSkillActivationBlock activates skills via prefer_skills when context
|
|
|
92
92
|
prefer_skills: ["react"],
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
assert.match(result, /
|
|
95
|
+
assert.match(result, /Read the installed 'react' skill file from <available_skills>/);
|
|
96
96
|
assert.doesNotMatch(result, /swiftui/);
|
|
97
97
|
} finally {
|
|
98
98
|
cleanup(base);
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
test("buildSkillActivationBlock includes always_use_skills
|
|
102
|
+
test("buildSkillActivationBlock includes always_use_skills using read-based skill loading", () => {
|
|
103
103
|
const base = makeTempBase();
|
|
104
104
|
try {
|
|
105
105
|
writeSkill(base, "swift-testing", "Use for Swift Testing assertions and verification patterns.");
|
|
@@ -109,7 +109,10 @@ test("buildSkillActivationBlock includes always_use_skills from preferences usin
|
|
|
109
109
|
always_use_skills: ["swift-testing"],
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
assert.equal(
|
|
112
|
+
assert.equal(
|
|
113
|
+
result,
|
|
114
|
+
"<skill_activation>Read the installed 'swift-testing' skill file from <available_skills>.</skill_activation>",
|
|
115
|
+
);
|
|
113
116
|
} finally {
|
|
114
117
|
cleanup(base);
|
|
115
118
|
}
|
|
@@ -137,8 +140,8 @@ test("buildSkillActivationBlock includes skill_rules matches and task-plan skill
|
|
|
137
140
|
skill_rules: [{ when: "prisma database schema", use: ["prisma"] }],
|
|
138
141
|
});
|
|
139
142
|
|
|
140
|
-
assert.match(result, /
|
|
141
|
-
assert.match(result, /
|
|
143
|
+
assert.match(result, /Read the installed 'accessibility' skill file from <available_skills>/);
|
|
144
|
+
assert.match(result, /Read the installed 'prisma' skill file from <available_skills>/);
|
|
142
145
|
} finally {
|
|
143
146
|
cleanup(base);
|
|
144
147
|
}
|
|
@@ -160,7 +163,7 @@ test("buildSkillActivationBlock matches skill_rules against exact unit type cont
|
|
|
160
163
|
],
|
|
161
164
|
});
|
|
162
165
|
|
|
163
|
-
assert.match(result, /
|
|
166
|
+
assert.match(result, /Read the installed 'complete-slice-policies' skill file from <available_skills>/);
|
|
164
167
|
assert.doesNotMatch(result, /slice-broad/);
|
|
165
168
|
} finally {
|
|
166
169
|
cleanup(base);
|
|
@@ -264,8 +267,8 @@ test("buildSkillActivationBlock allows valid skill names and rejects invalid one
|
|
|
264
267
|
});
|
|
265
268
|
|
|
266
269
|
assert.match(result, /skill_activation/);
|
|
267
|
-
assert.match(result, /
|
|
268
|
-
assert.match(result, /
|
|
270
|
+
assert.match(result, /Read the installed 'react' skill file from <available_skills>/);
|
|
271
|
+
assert.match(result, /Read the installed 'good-skill-2' skill file from <available_skills>/);
|
|
269
272
|
assert.doesNotMatch(result, /bad'name/);
|
|
270
273
|
} finally {
|
|
271
274
|
cleanup(base);
|
|
@@ -289,8 +292,8 @@ test("buildSkillActivationBlock: explicit always_use_skills bypass the unit-type
|
|
|
289
292
|
always_use_skills: ["write-docs", "swiftui"],
|
|
290
293
|
});
|
|
291
294
|
|
|
292
|
-
assert.match(result, /
|
|
293
|
-
assert.match(result, /
|
|
295
|
+
assert.match(result, /Read the installed 'write-docs' skill file from <available_skills>/);
|
|
296
|
+
assert.match(result, /Read the installed 'swiftui' skill file from <available_skills>/);
|
|
294
297
|
} finally {
|
|
295
298
|
cleanup(base);
|
|
296
299
|
}
|
|
@@ -307,7 +310,7 @@ test("buildSkillActivationBlock falls through to all skills for unknown unit typ
|
|
|
307
310
|
});
|
|
308
311
|
|
|
309
312
|
// Unknown unit type = wildcard fallback (pre-manifest behavior).
|
|
310
|
-
assert.match(result, /
|
|
313
|
+
assert.match(result, /Read the installed 'swiftui' skill file from <available_skills>/);
|
|
311
314
|
} finally {
|
|
312
315
|
cleanup(base);
|
|
313
316
|
}
|
|
@@ -324,7 +327,7 @@ test("buildSkillActivationBlock without unitType preserves pre-manifest behavior
|
|
|
324
327
|
always_use_skills: ["swiftui"],
|
|
325
328
|
});
|
|
326
329
|
|
|
327
|
-
assert.match(result, /
|
|
330
|
+
assert.match(result, /Read the installed 'swiftui' skill file from <available_skills>/);
|
|
328
331
|
} finally {
|
|
329
332
|
cleanup(base);
|
|
330
333
|
}
|
|
@@ -341,12 +344,12 @@ test("milestone prompt builders propagate always_use_skills through buildSkillAc
|
|
|
341
344
|
loadOnlyTestSkills(base);
|
|
342
345
|
|
|
343
346
|
const researchPrompt = await buildResearchMilestonePrompt("M001", "Test", base);
|
|
344
|
-
assert.match(researchPrompt, /
|
|
345
|
-
assert.match(researchPrompt, /
|
|
347
|
+
assert.match(researchPrompt, /Read the installed 'write-docs' skill file from <available_skills>/);
|
|
348
|
+
assert.match(researchPrompt, /Read the installed 'swiftui' skill file from <available_skills>/);
|
|
346
349
|
|
|
347
350
|
const planPrompt = await buildPlanMilestonePrompt("M001", "Test", base);
|
|
348
|
-
assert.match(planPrompt, /
|
|
349
|
-
assert.match(planPrompt, /
|
|
351
|
+
assert.match(planPrompt, /Read the installed 'write-docs' skill file from <available_skills>/);
|
|
352
|
+
assert.match(planPrompt, /Read the installed 'swiftui' skill file from <available_skills>/);
|
|
350
353
|
} finally {
|
|
351
354
|
cleanup(base);
|
|
352
355
|
}
|
|
@@ -377,7 +380,7 @@ test("complete-slice prompt propagates always_use_skills through buildSkillActiv
|
|
|
377
380
|
|
|
378
381
|
const prompt = await buildCompleteSlicePrompt("M001", "Test", "S01", "Slice", base);
|
|
379
382
|
|
|
380
|
-
assert.match(prompt, /
|
|
383
|
+
assert.match(prompt, /Read the installed 'write-docs' skill file from <available_skills>/);
|
|
381
384
|
} finally {
|
|
382
385
|
cleanup(base);
|
|
383
386
|
}
|