@opengsd/gsd-pi 1.2.0-dev.fb12b103 → 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/headless-events.js +7 -5
- package/dist/loader.js +6 -4
- package/dist/mcp-server.js +2 -1
- 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/GSD-WORKFLOW.md +5 -4
- 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/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +120 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- 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 +7 -1
- package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +167 -64
- 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 +11 -34
- package/dist/resources/extensions/gsd/auto-dispatch.js +39 -58
- package/dist/resources/extensions/gsd/auto-model-selection.js +11 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
- package/dist/resources/extensions/gsd/auto-prompts.js +66 -9
- package/dist/resources/extensions/gsd/auto-start.js +26 -8
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
- package/dist/resources/extensions/gsd/auto-verification.js +23 -30
- package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
- package/dist/resources/extensions/gsd/auto.js +52 -2
- package/dist/resources/extensions/gsd/blocked-models.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -45
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
- package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
- 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/consent-question.js +353 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- 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 +56 -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/dispatch-guard.js +10 -35
- 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/doctor-git-checks.js +2 -18
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- package/dist/resources/extensions/gsd/files.js +33 -19
- package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
- package/dist/resources/extensions/gsd/gsd-db.js +17 -21
- package/dist/resources/extensions/gsd/guidance.js +60 -0
- 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/markdown-renderer.js +10 -0
- 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-closeout.js +85 -24
- 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/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- 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 +8 -4
- 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/reactive-graph.js +8 -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 +11 -2
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- 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 +22 -12
- 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/tools/workflow-tool-executors.js +67 -2
- package/dist/resources/extensions/gsd/uat-policy.js +40 -15
- 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/verdict-parser.js +1 -1
- 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-lifecycle.js +3 -2
- 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/extensions/shared/gsd-browser-cli.js +21 -2
- package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
- package/dist/resources/shared/package-manager-detection.js +1 -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/update-check.d.ts +2 -0
- package/dist/update-check.js +24 -1
- package/dist/update-cmd.js +20 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- 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 +6 -6
- package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
- 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/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/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/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/moonshot-tool-schema.d.ts +29 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
- package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
- 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/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +4 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- 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 +18 -18
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +161 -81
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- 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/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +2 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +2 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +419 -221
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +468 -269
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +12 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
- package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-shared.js +12 -3
- package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
- package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- 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/GSD-WORKFLOW.md +5 -4
- package/src/resources/extensions/ask-user-questions.ts +7 -2
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +11 -0
- 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/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +168 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- 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 +7 -1
- package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +186 -66
- 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 +18 -48
- package/src/resources/extensions/gsd/auto-dispatch.ts +37 -62
- package/src/resources/extensions/gsd/auto-model-selection.ts +16 -7
- package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
- package/src/resources/extensions/gsd/auto-prompts.ts +78 -9
- package/src/resources/extensions/gsd/auto-start.ts +27 -11
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
- package/src/resources/extensions/gsd/auto-verification.ts +26 -28
- package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
- package/src/resources/extensions/gsd/auto.ts +64 -2
- package/src/resources/extensions/gsd/blocked-models.ts +49 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +118 -50
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
- package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
- 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/consent-question.ts +431 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- 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 +66 -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/dispatch-guard.ts +8 -31
- 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/doctor-git-checks.ts +2 -19
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- package/src/resources/extensions/gsd/files.ts +33 -12
- package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
- package/src/resources/extensions/gsd/gsd-db.ts +19 -22
- package/src/resources/extensions/gsd/guidance.ts +78 -0
- 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/markdown-renderer.ts +11 -0
- 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-closeout.ts +109 -24
- 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/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
- 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 +8 -4
- 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/reactive-graph.ts +11 -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 +12 -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 +75 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +257 -18
- 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/blocked-models.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- 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 +12 -11
- 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 +328 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
- package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -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-command-home.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -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 +217 -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-closeout.test.ts +95 -4
- 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-research-dispatch.test.ts +18 -0
- 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 +143 -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/prompt-db.test.ts +124 -6
- 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/uat-policy.test.ts +88 -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/workflow-tool-executors.test.ts +273 -38
- 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/tests/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- 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 +22 -12
- 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/tools/workflow-tool-executors.ts +81 -2
- package/src/resources/extensions/gsd/uat-policy.ts +60 -15
- 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/verdict-parser.ts +1 -1
- 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-lifecycle.ts +3 -8
- 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/extensions/shared/gsd-browser-cli.ts +23 -2
- package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
- package/src/resources/shared/package-manager-detection.ts +1 -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/extensions/gsd/user-input-boundary.js +0 -218
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// gsd-pi - Write-gate two-process seam tests.
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic interleaving tests for the host/child write-gate adapters
|
|
4
|
+
* (write-gate.ts). The "child" (workflow MCP server) runs in a separate
|
|
5
|
+
* process in production; these tests simulate its writes by stamping the
|
|
6
|
+
* snapshot file directly, exactly as childWriteGateAdapter persists it.
|
|
7
|
+
*
|
|
8
|
+
* Covered interleavings:
|
|
9
|
+
* (a) child verifies on disk while the host holds stale memory — the host
|
|
10
|
+
* re-arm must NOT clobber the verification, on BOTH windows
|
|
11
|
+
* (tool_execution_start re-arm and the tool_call defer path);
|
|
12
|
+
* (b) concurrent writes: every persist is an unconditional read-merge-write
|
|
13
|
+
* (read disk → union-merge → mutate → atomic rename), so a write the
|
|
14
|
+
* other process landed in between is folded in, never overwritten;
|
|
15
|
+
* (c) two basePaths defer approval gates in the same process — both stay
|
|
16
|
+
* deferred and both activate (regression for the old single global slot);
|
|
17
|
+
* (d) old snapshot files (including ones carrying the retired epoch field)
|
|
18
|
+
* keep loading; stale fields are dropped on the next write.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import test from "node:test";
|
|
22
|
+
import assert from "node:assert/strict";
|
|
23
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
24
|
+
import { join } from "node:path";
|
|
25
|
+
import { tmpdir } from "node:os";
|
|
26
|
+
|
|
27
|
+
import { registerHooks } from "../bootstrap/register-hooks.ts";
|
|
28
|
+
import {
|
|
29
|
+
childWriteGateAdapter,
|
|
30
|
+
clearDiscussionFlowState,
|
|
31
|
+
getPendingGate,
|
|
32
|
+
hostWriteGateAdapter,
|
|
33
|
+
loadWriteGateSnapshot,
|
|
34
|
+
markDepthVerified,
|
|
35
|
+
refreshWriteGateStateFromDisk,
|
|
36
|
+
setPendingGate,
|
|
37
|
+
type WriteGateSnapshot,
|
|
38
|
+
} from "../bootstrap/write-gate.ts";
|
|
39
|
+
|
|
40
|
+
function makeTempDir(prefix: string): string {
|
|
41
|
+
const dir = join(
|
|
42
|
+
tmpdir(),
|
|
43
|
+
`gsd-write-gate-seam-${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
44
|
+
);
|
|
45
|
+
mkdirSync(dir, { recursive: true });
|
|
46
|
+
return dir;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function snapshotPath(basePath: string): string {
|
|
50
|
+
return join(basePath, ".gsd", "runtime", "write-gate-state.json");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Simulate a write from the OTHER process by stamping the file directly. */
|
|
54
|
+
function foreignProcessWrites(basePath: string, snapshot: Partial<WriteGateSnapshot>): void {
|
|
55
|
+
mkdirSync(join(basePath, ".gsd", "runtime"), { recursive: true });
|
|
56
|
+
writeFileSync(snapshotPath(basePath), JSON.stringify({
|
|
57
|
+
verifiedDepthMilestones: [],
|
|
58
|
+
verifiedApprovalGates: [],
|
|
59
|
+
activeQueuePhase: false,
|
|
60
|
+
pendingGateId: null,
|
|
61
|
+
...snapshot,
|
|
62
|
+
}, null, 2), "utf-8");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function readDiskRaw(basePath: string): Record<string, unknown> {
|
|
66
|
+
return JSON.parse(readFileSync(snapshotPath(basePath), "utf-8"));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function makeHookHarness(): {
|
|
70
|
+
handlers: Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>;
|
|
71
|
+
pi: any;
|
|
72
|
+
} {
|
|
73
|
+
const handlers = new Map<string, Array<(event: any, ctx?: any) => Promise<any> | any>>();
|
|
74
|
+
const pi = {
|
|
75
|
+
on(event: string, handler: (event: any, ctx?: any) => Promise<any> | any) {
|
|
76
|
+
const existing = handlers.get(event) ?? [];
|
|
77
|
+
existing.push(handler);
|
|
78
|
+
handlers.set(event, existing);
|
|
79
|
+
},
|
|
80
|
+
} as any;
|
|
81
|
+
return { handlers, pi };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function cleanup(dir: string): void {
|
|
85
|
+
clearDiscussionFlowState(dir);
|
|
86
|
+
rmSync(dir, { recursive: true, force: true });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const GATE = "depth_verification_M007_confirm";
|
|
90
|
+
|
|
91
|
+
// ── (a) verified-on-disk wins over a host re-arm ────────────────────────────
|
|
92
|
+
|
|
93
|
+
test("seam: host setPending does not clobber a child verification on disk", (t) => {
|
|
94
|
+
const dir = makeTempDir("no-clobber-adapter");
|
|
95
|
+
t.after(() => cleanup(dir));
|
|
96
|
+
|
|
97
|
+
// Host has stale memory: it armed the gate earlier (persisted to disk).
|
|
98
|
+
assert.equal(setPendingGate(GATE, dir), true, "fresh gate must arm");
|
|
99
|
+
assert.equal(getPendingGate(dir), GATE);
|
|
100
|
+
|
|
101
|
+
// Child verifies the gate in its own process (newer write on disk).
|
|
102
|
+
foreignProcessWrites(dir, {
|
|
103
|
+
verifiedDepthMilestones: ["M007"],
|
|
104
|
+
verifiedApprovalGates: [GATE],
|
|
105
|
+
writer: "child",
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Host attempts a re-arm — adapter policy: verified on disk wins.
|
|
109
|
+
assert.equal(hostWriteGateAdapter.setPending(GATE, dir), false, "re-arm must be suppressed");
|
|
110
|
+
const snapshot = loadWriteGateSnapshot(dir);
|
|
111
|
+
assert.ok(snapshot.verifiedDepthMilestones.includes("M007"), "verification must survive");
|
|
112
|
+
assert.ok((snapshot.verifiedApprovalGates ?? []).includes(GATE));
|
|
113
|
+
assert.equal(getPendingGate(dir), null, "no pending gate after suppressed re-arm");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("seam: tool_call defer path does not block tools for a gate the child verified", async (t) => {
|
|
117
|
+
const dir = makeTempDir("no-clobber-defer");
|
|
118
|
+
t.after(() => cleanup(dir));
|
|
119
|
+
|
|
120
|
+
// Child verified the gate before the host ever saw the tool block.
|
|
121
|
+
foreignProcessWrites(dir, {
|
|
122
|
+
verifiedDepthMilestones: ["M007"],
|
|
123
|
+
verifiedApprovalGates: [GATE],
|
|
124
|
+
writer: "child",
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const { handlers, pi } = makeHookHarness();
|
|
128
|
+
registerHooks(pi, []);
|
|
129
|
+
const ctx = { cwd: dir, ui: { notify: () => undefined } } as any;
|
|
130
|
+
|
|
131
|
+
// tool_call defer window: ask_user_questions arrives post-hoc with the gate id.
|
|
132
|
+
for (const handler of handlers.get("tool_call") ?? []) {
|
|
133
|
+
await handler({
|
|
134
|
+
toolCallId: "t-gate",
|
|
135
|
+
toolName: "ask_user_questions",
|
|
136
|
+
input: { questions: [{ id: GATE }] },
|
|
137
|
+
}, ctx);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// A subsequent tool in the same turn must NOT hit the deferred-gate block.
|
|
141
|
+
let blocked: any;
|
|
142
|
+
for (const handler of handlers.get("tool_call") ?? []) {
|
|
143
|
+
const result = await handler({
|
|
144
|
+
toolCallId: "t-next",
|
|
145
|
+
toolName: "glob",
|
|
146
|
+
input: { pattern: "*.md" },
|
|
147
|
+
}, ctx);
|
|
148
|
+
if (result?.block) blocked = result;
|
|
149
|
+
}
|
|
150
|
+
assert.equal(blocked, undefined, "verified gate must not be deferred/blocking");
|
|
151
|
+
assert.equal(getPendingGate(dir), null);
|
|
152
|
+
const snapshot = loadWriteGateSnapshot(dir);
|
|
153
|
+
assert.ok(snapshot.verifiedDepthMilestones.includes("M007"), "verification must survive the defer window");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("seam: tool_execution_start re-arm window keeps the child verification", async (t) => {
|
|
157
|
+
const dir = makeTempDir("no-clobber-exec-start");
|
|
158
|
+
t.after(() => cleanup(dir));
|
|
159
|
+
|
|
160
|
+
foreignProcessWrites(dir, {
|
|
161
|
+
verifiedDepthMilestones: ["M007"],
|
|
162
|
+
verifiedApprovalGates: [GATE],
|
|
163
|
+
writer: "child",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const { handlers, pi } = makeHookHarness();
|
|
167
|
+
registerHooks(pi, []);
|
|
168
|
+
const ctx = { cwd: dir, ui: { notify: () => undefined } } as any;
|
|
169
|
+
|
|
170
|
+
for (const handler of handlers.get("tool_execution_start") ?? []) {
|
|
171
|
+
await handler({
|
|
172
|
+
toolCallId: "t-gate",
|
|
173
|
+
toolName: "mcp__gsd-workflow__ask_user_questions",
|
|
174
|
+
args: { questions: [{ id: GATE }] },
|
|
175
|
+
}, ctx);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
assert.equal(getPendingGate(dir), null, "post-hoc replay must not re-arm a verified gate");
|
|
179
|
+
assert.ok(loadWriteGateSnapshot(dir).verifiedDepthMilestones.includes("M007"));
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// ── (b) concurrent writes re-merge instead of overwriting ───────────────────
|
|
183
|
+
|
|
184
|
+
test("seam: host persist re-merges a concurrent child write (unconditional read-merge-write)", (t) => {
|
|
185
|
+
const dir = makeTempDir("concurrent-write");
|
|
186
|
+
t.after(() => cleanup(dir));
|
|
187
|
+
|
|
188
|
+
// Host persists its own verification.
|
|
189
|
+
markDepthVerified("M001", dir);
|
|
190
|
+
|
|
191
|
+
// Child lands a different verification on disk while the host is idle.
|
|
192
|
+
foreignProcessWrites(dir, {
|
|
193
|
+
verifiedDepthMilestones: ["M002"],
|
|
194
|
+
writer: "child",
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Host persists again — every mutation re-reads the disk snapshot and
|
|
198
|
+
// union-merges before writing, so the child's verification survives.
|
|
199
|
+
markDepthVerified("M003", dir);
|
|
200
|
+
const merged = loadWriteGateSnapshot(dir);
|
|
201
|
+
assert.deepEqual(merged.verifiedDepthMilestones, ["M001", "M002", "M003"]);
|
|
202
|
+
assert.equal(readDiskRaw(dir).writer, "host");
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test("seam: missing snapshot resets stale in-memory pending gate before mutation", (t) => {
|
|
206
|
+
const dir = makeTempDir("missing-snapshot-reset");
|
|
207
|
+
t.after(() => cleanup(dir));
|
|
208
|
+
|
|
209
|
+
assert.equal(setPendingGate(GATE, dir), true);
|
|
210
|
+
rmSync(snapshotPath(dir), { force: true });
|
|
211
|
+
|
|
212
|
+
markDepthVerified("M008", dir);
|
|
213
|
+
|
|
214
|
+
const snapshot = loadWriteGateSnapshot(dir);
|
|
215
|
+
assert.equal(snapshot.pendingGateId, null);
|
|
216
|
+
assert.deepEqual(snapshot.verifiedDepthMilestones, ["M008"]);
|
|
217
|
+
assert.equal(readDiskRaw(dir).pendingGateId, null);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test("seam: childWriteGateAdapter is write-through and stamps writer provenance", (t) => {
|
|
221
|
+
const dir = makeTempDir("child-write-through");
|
|
222
|
+
t.after(() => cleanup(dir));
|
|
223
|
+
|
|
224
|
+
foreignProcessWrites(dir, { verifiedDepthMilestones: ["M001"], writer: "host" });
|
|
225
|
+
childWriteGateAdapter.markDepthVerified("M002", dir);
|
|
226
|
+
|
|
227
|
+
const disk = readDiskRaw(dir);
|
|
228
|
+
assert.deepEqual(disk.verifiedDepthMilestones, ["M001", "M002"], "fresh disk read, then mutate");
|
|
229
|
+
assert.equal(disk.writer, "child");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// ── (c) per-basePath deferred gates ──────────────────────────────────────────
|
|
233
|
+
|
|
234
|
+
test("seam: two basePaths defer gates in one process and both activate", async (t) => {
|
|
235
|
+
const dirA = makeTempDir("defer-a");
|
|
236
|
+
const dirB = makeTempDir("defer-b");
|
|
237
|
+
t.after(() => {
|
|
238
|
+
cleanup(dirA);
|
|
239
|
+
cleanup(dirB);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const { handlers, pi } = makeHookHarness();
|
|
243
|
+
registerHooks(pi, []);
|
|
244
|
+
const gateA = "depth_verification_M010_confirm";
|
|
245
|
+
const gateB = "depth_verification_M020_confirm";
|
|
246
|
+
const ctxA = { cwd: dirA, ui: { notify: () => undefined } } as any;
|
|
247
|
+
const ctxB = { cwd: dirB, ui: { notify: () => undefined } } as any;
|
|
248
|
+
|
|
249
|
+
for (const handler of handlers.get("tool_call") ?? []) {
|
|
250
|
+
await handler({ toolCallId: "a-1", toolName: "ask_user_questions", input: { questions: [{ id: gateA }] } }, ctxA);
|
|
251
|
+
}
|
|
252
|
+
for (const handler of handlers.get("tool_call") ?? []) {
|
|
253
|
+
await handler({ toolCallId: "b-1", toolName: "ask_user_questions", input: { questions: [{ id: gateB }] } }, ctxB);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// With the old single global slot, project A's deferral was lost the moment
|
|
257
|
+
// project B deferred. Both must still block follow-up tools.
|
|
258
|
+
for (const [ctx, label] of [[ctxA, "A"], [ctxB, "B"]] as const) {
|
|
259
|
+
let blocked: any;
|
|
260
|
+
for (const handler of handlers.get("tool_call") ?? []) {
|
|
261
|
+
const result = await handler({ toolCallId: `chk-${label}`, toolName: "glob", input: { pattern: "*" } }, ctx);
|
|
262
|
+
if (result?.block) blocked = result;
|
|
263
|
+
}
|
|
264
|
+
assert.equal(blocked?.block, true, `project ${label} deferred gate must still block`);
|
|
265
|
+
assert.match(blocked?.reason ?? "", /Approval question/);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Activation happens via tool_execution_start in each project independently.
|
|
269
|
+
for (const [ctx, gate, dir] of [[ctxA, gateA, dirA], [ctxB, gateB, dirB]] as const) {
|
|
270
|
+
for (const handler of handlers.get("tool_execution_start") ?? []) {
|
|
271
|
+
await handler({ toolCallId: "act", toolName: "ask_user_questions", args: { questions: [{ id: gate }] } }, ctx);
|
|
272
|
+
}
|
|
273
|
+
assert.equal(getPendingGate(dir), gate, `gate must arm durably for ${dir}`);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// ── (d) backward compatibility: legacy snapshot fields ──────────────────────
|
|
278
|
+
|
|
279
|
+
test("seam: old snapshot with a retired epoch field loads and sheds it on write", (t) => {
|
|
280
|
+
const dir = makeTempDir("legacy-snapshot");
|
|
281
|
+
t.after(() => cleanup(dir));
|
|
282
|
+
|
|
283
|
+
writeFileSync(
|
|
284
|
+
(mkdirSync(join(dir, ".gsd", "runtime"), { recursive: true }), snapshotPath(dir)),
|
|
285
|
+
JSON.stringify({
|
|
286
|
+
verifiedDepthMilestones: ["M001"],
|
|
287
|
+
verifiedApprovalGates: ["depth_verification_M001_confirm"],
|
|
288
|
+
activeQueuePhase: false,
|
|
289
|
+
pendingGateId: null,
|
|
290
|
+
// Written by an older build that still stamped the write-only epoch.
|
|
291
|
+
epoch: 7,
|
|
292
|
+
}),
|
|
293
|
+
"utf-8",
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
const loaded = loadWriteGateSnapshot(dir);
|
|
297
|
+
assert.deepEqual(loaded.verifiedDepthMilestones, ["M001"]);
|
|
298
|
+
assert.equal("epoch" in loaded, false, "retired epoch field is not surfaced");
|
|
299
|
+
|
|
300
|
+
const refreshed = refreshWriteGateStateFromDisk(dir);
|
|
301
|
+
assert.ok(refreshed.verifiedDepthMilestones.includes("M001"));
|
|
302
|
+
|
|
303
|
+
markDepthVerified("M002", dir);
|
|
304
|
+
const upgraded = readDiskRaw(dir);
|
|
305
|
+
assert.deepEqual(upgraded.verifiedDepthMilestones, ["M001", "M002"]);
|
|
306
|
+
assert.equal("epoch" in upgraded, false, "retired epoch field is dropped on rewrite");
|
|
307
|
+
assert.equal(upgraded.writer, "host");
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// ── (e) corrupt snapshot is treated as a reset (matches "delete the file") ──
|
|
311
|
+
|
|
312
|
+
test("seam: corrupt snapshot file resets host state instead of persisting stale pendingGateId", (t) => {
|
|
313
|
+
const dir = makeTempDir("corrupt-snapshot");
|
|
314
|
+
t.after(() => cleanup(dir));
|
|
315
|
+
|
|
316
|
+
// Host arms a gate; stale pendingGateId now lives in memory and on disk.
|
|
317
|
+
assert.equal(setPendingGate(GATE, dir), true);
|
|
318
|
+
assert.equal(getPendingGate(dir), GATE);
|
|
319
|
+
|
|
320
|
+
// The snapshot file is corrupted out-of-band (e.g. partial write from a
|
|
321
|
+
// crashed editor, foreign tool, or filesystem fault).
|
|
322
|
+
writeFileSync(snapshotPath(dir), "{ not json", "utf-8");
|
|
323
|
+
|
|
324
|
+
// refreshWriteGateStateFromDisk must treat the unreadable file the same
|
|
325
|
+
// as a missing file: full reset, including dropping the stale pending id.
|
|
326
|
+
const refreshed = refreshWriteGateStateFromDisk(dir);
|
|
327
|
+
assert.equal(refreshed.pendingGateId, null, "stale pendingGateId must not survive a corrupt snapshot");
|
|
328
|
+
assert.deepEqual(refreshed.verifiedDepthMilestones, []);
|
|
329
|
+
assert.deepEqual(refreshed.verifiedApprovalGates, []);
|
|
330
|
+
assert.equal(getPendingGate(dir), null);
|
|
331
|
+
|
|
332
|
+
// A subsequent mutation must not write the stale gate back to disk.
|
|
333
|
+
markDepthVerified("M042", dir);
|
|
334
|
+
const persisted = readDiskRaw(dir);
|
|
335
|
+
assert.equal(persisted.pendingGateId, null, "next persist must not re-stamp the stale pending id");
|
|
336
|
+
assert.deepEqual(persisted.verifiedDepthMilestones, ["M042"]);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test("seam: mutateWriteGateState reset path drops stale pendingGateId on a corrupt snapshot", (t) => {
|
|
340
|
+
const dir = makeTempDir("corrupt-snapshot-mutate");
|
|
341
|
+
t.after(() => cleanup(dir));
|
|
342
|
+
|
|
343
|
+
// Host arms a gate first.
|
|
344
|
+
assert.equal(setPendingGate(GATE, dir), true);
|
|
345
|
+
|
|
346
|
+
// Corrupt the snapshot directly (skipping the refresh path so we exercise
|
|
347
|
+
// the reconcile-on-mutate branch in mutateWriteGateState).
|
|
348
|
+
writeFileSync(snapshotPath(dir), "}}}", "utf-8");
|
|
349
|
+
|
|
350
|
+
// markDepthVerified runs through mutateWriteGateState; the reconcile pass
|
|
351
|
+
// must reset the in-memory state when the disk read returns null, even
|
|
352
|
+
// though the file still exists on disk.
|
|
353
|
+
markDepthVerified("M099", dir);
|
|
354
|
+
|
|
355
|
+
const persisted = readDiskRaw(dir);
|
|
356
|
+
assert.equal(persisted.pendingGateId, null, "stale pending id must not be persisted after a corrupt-snapshot reconcile");
|
|
357
|
+
assert.deepEqual(persisted.verifiedDepthMilestones, ["M099"]);
|
|
358
|
+
});
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
setQueuePhaseActive,
|
|
25
25
|
} from '../index.ts';
|
|
26
26
|
import {
|
|
27
|
+
childWriteGateAdapter,
|
|
27
28
|
markDepthVerified,
|
|
28
29
|
isMilestoneDepthVerified,
|
|
29
30
|
markApprovalGateVerified,
|
|
@@ -317,7 +318,11 @@ test('write-gate: reopening a gate revokes its previous verified approval', () =
|
|
|
317
318
|
'precondition: verified approval unlocks the final project artifact',
|
|
318
319
|
);
|
|
319
320
|
|
|
320
|
-
|
|
321
|
+
// A genuine re-ask originates from the workflow MCP child (where
|
|
322
|
+
// ask_user_questions executes): the child adapter arms unconditionally,
|
|
323
|
+
// revoking the prior approval. Host-side setPendingGate is guarded
|
|
324
|
+
// (verified-on-disk wins) and would deliberately suppress this arm.
|
|
325
|
+
childWriteGateAdapter.setPending('depth_verification_project_confirm', base);
|
|
321
326
|
clearPendingGate(base);
|
|
322
327
|
|
|
323
328
|
assert.strictEqual(
|
|
@@ -458,6 +463,66 @@ test('write-gate: applyAskUserQuestionsGateResult verifies confirmed pending gat
|
|
|
458
463
|
}
|
|
459
464
|
});
|
|
460
465
|
|
|
466
|
+
test('write-gate: applyAskUserQuestionsGateResult reports declined pending gate (consent-verdict semantics)', () => {
|
|
467
|
+
const base = join(tmpdir(), `gsd-write-gate-ask-declined-${randomUUID()}`);
|
|
468
|
+
const gateId = 'depth_verification_M001_confirm';
|
|
469
|
+
|
|
470
|
+
try {
|
|
471
|
+
mkdirSync(base, { recursive: true });
|
|
472
|
+
clearDiscussionFlowState(base);
|
|
473
|
+
setPendingGate(gateId, base);
|
|
474
|
+
|
|
475
|
+
const result = applyAskUserQuestionsGateResult({
|
|
476
|
+
basePath: base,
|
|
477
|
+
questions: [{
|
|
478
|
+
id: gateId,
|
|
479
|
+
options: [{ label: 'Confirm depth (Recommended)' }, { label: 'Needs adjustment' }],
|
|
480
|
+
}],
|
|
481
|
+
details: {
|
|
482
|
+
response: { answers: { [gateId]: { selected: 'Needs adjustment' } } },
|
|
483
|
+
},
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
assert.deepEqual(result, { status: 'declined', gateId });
|
|
487
|
+
assert.strictEqual(getPendingGate(base), gateId, 'declined gate must stay pending');
|
|
488
|
+
assert.strictEqual(isMilestoneDepthVerified('M001', base), false, 'declined gate must not verify depth');
|
|
489
|
+
} finally {
|
|
490
|
+
clearDiscussionFlowState(base);
|
|
491
|
+
rmSync(base, { recursive: true, force: true });
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
test('write-gate: applyAskUserQuestionsGateResult keeps empty-selection pending gate waiting (consent-verdict semantics)', () => {
|
|
496
|
+
// An empty selection is never an answer (fail-closed): the round used to
|
|
497
|
+
// report "answered" here, silently treating a missing selection as resolved.
|
|
498
|
+
const base = join(tmpdir(), `gsd-write-gate-ask-empty-${randomUUID()}`);
|
|
499
|
+
const gateId = 'depth_verification_M001_confirm';
|
|
500
|
+
|
|
501
|
+
try {
|
|
502
|
+
mkdirSync(base, { recursive: true });
|
|
503
|
+
clearDiscussionFlowState(base);
|
|
504
|
+
setPendingGate(gateId, base);
|
|
505
|
+
|
|
506
|
+
const result = applyAskUserQuestionsGateResult({
|
|
507
|
+
basePath: base,
|
|
508
|
+
questions: [{
|
|
509
|
+
id: gateId,
|
|
510
|
+
options: [{ label: 'Confirm depth (Recommended)' }, { label: 'Needs adjustment' }],
|
|
511
|
+
}],
|
|
512
|
+
details: {
|
|
513
|
+
response: { answers: { [gateId]: { selected: '' } } },
|
|
514
|
+
},
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
assert.deepEqual(result, { status: 'waiting', pendingGateId: gateId, interrupted: false });
|
|
518
|
+
assert.strictEqual(getPendingGate(base), gateId, 'unanswered gate must stay pending');
|
|
519
|
+
assert.strictEqual(isMilestoneDepthVerified('M001', base), false, 'unanswered gate must not verify depth');
|
|
520
|
+
} finally {
|
|
521
|
+
clearDiscussionFlowState(base);
|
|
522
|
+
rmSync(base, { recursive: true, force: true });
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
|
|
461
526
|
// ─── Scenario 21: shouldBlockPendingGate blocks non-safe tools when gate is pending ──
|
|
462
527
|
|
|
463
528
|
test('write-gate: shouldBlockPendingGate blocks write/edit during pending gate', () => {
|
|
@@ -789,6 +854,7 @@ test('write-gate: resetWriteGateState persists through dangling .gsd symlink', (
|
|
|
789
854
|
verifiedApprovalGates: [],
|
|
790
855
|
activeQueuePhase: false,
|
|
791
856
|
pendingGateId: null,
|
|
857
|
+
writer: 'host',
|
|
792
858
|
});
|
|
793
859
|
} finally {
|
|
794
860
|
if (originalEnv === undefined) {
|
|
@@ -9,8 +9,14 @@ import {
|
|
|
9
9
|
type ToolsPolicy,
|
|
10
10
|
type UnitContextManifest,
|
|
11
11
|
} from "./unit-context-manifest.js";
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import {
|
|
13
|
+
getWorkflowTransportSupportError,
|
|
14
|
+
type WorkflowCapabilityOptions,
|
|
15
|
+
} from "./workflow-mcp.js";
|
|
16
|
+
import {
|
|
17
|
+
getRequiredWorkflowToolsForUnit,
|
|
18
|
+
getUnitToolSurfaceContract,
|
|
19
|
+
} from "./unit-tool-contracts.js";
|
|
14
20
|
import {
|
|
15
21
|
WHOLE_FILE_OBSERVATION_MAX_BYTES,
|
|
16
22
|
WHOLE_FILE_OBSERVATION_MAX_LINES,
|
|
@@ -68,6 +74,17 @@ export type UnitContextContractResult =
|
|
|
68
74
|
| { ok: true; contract: UnitPromptContextContract }
|
|
69
75
|
| { ok: false; reason: "unknown-unit-type"; detail: string };
|
|
70
76
|
|
|
77
|
+
export interface UnitWorkflowDispatchReadinessInput {
|
|
78
|
+
provider?: string;
|
|
79
|
+
unitType: string;
|
|
80
|
+
projectRoot?: string;
|
|
81
|
+
env?: NodeJS.ProcessEnv;
|
|
82
|
+
surface?: string;
|
|
83
|
+
authMode?: WorkflowCapabilityOptions["authMode"];
|
|
84
|
+
baseUrl?: string;
|
|
85
|
+
activeTools?: string[];
|
|
86
|
+
}
|
|
87
|
+
|
|
71
88
|
export function compileUnitContextContract(unitType: string): UnitContextContractResult {
|
|
72
89
|
const manifest = resolveManifest(unitType);
|
|
73
90
|
if (!manifest) {
|
|
@@ -80,6 +97,24 @@ export function compileUnitContextContract(unitType: string): UnitContextContrac
|
|
|
80
97
|
return { ok: true, contract: buildPromptContextContract(unitType, manifest) };
|
|
81
98
|
}
|
|
82
99
|
|
|
100
|
+
export function getUnitWorkflowDispatchReadinessError(
|
|
101
|
+
input: UnitWorkflowDispatchReadinessInput,
|
|
102
|
+
): string | null {
|
|
103
|
+
return getWorkflowTransportSupportError(
|
|
104
|
+
input.provider,
|
|
105
|
+
getRequiredWorkflowToolsForUnit(input.unitType),
|
|
106
|
+
{
|
|
107
|
+
projectRoot: input.projectRoot,
|
|
108
|
+
env: input.env,
|
|
109
|
+
surface: input.surface,
|
|
110
|
+
unitType: input.unitType,
|
|
111
|
+
authMode: input.authMode,
|
|
112
|
+
baseUrl: input.baseUrl,
|
|
113
|
+
activeTools: input.activeTools,
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
83
118
|
export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
84
119
|
const manifest = resolveManifest(unitType);
|
|
85
120
|
const surfaceContract = getUnitToolSurfaceContract(unitType);
|
|
@@ -91,7 +126,7 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
|
91
126
|
};
|
|
92
127
|
}
|
|
93
128
|
|
|
94
|
-
const requiredWorkflowTools =
|
|
129
|
+
const requiredWorkflowTools = getRequiredWorkflowToolsForUnit(unitType);
|
|
95
130
|
const forbiddenWorkflowTools = Object.entries(surfaceContract?.forbiddenGsdTools ?? {})
|
|
96
131
|
.map(([name, reason]) => ({ name, reason }));
|
|
97
132
|
const closeoutTools = requiredWorkflowTools.filter((tool) =>
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { parseMcpToolName, toMcpToolName } from "./mcp-tool-name.js";
|
|
11
11
|
import { createToolSurfaceSnapshot, type ToolSurfaceSnapshot } from "./tool-surface-snapshot.js";
|
|
12
12
|
import { uatTypeIncludesBrowser } from "./uat-policy.js";
|
|
13
|
-
import {
|
|
13
|
+
import { canonicalWorkflowToolName } from "./engine-hook-contract.js";
|
|
14
14
|
|
|
15
15
|
export {
|
|
16
16
|
RUN_UAT_BROWSER_TOOL_NAMES,
|
|
@@ -66,9 +66,9 @@ export const RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES = [
|
|
|
66
66
|
"Grep",
|
|
67
67
|
] as const;
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
69
|
+
// Normalizer seam lives in engine-hook-contract.ts; re-exported here for
|
|
70
|
+
// existing presentation importers (uat-run.ts).
|
|
71
|
+
export { canonicalWorkflowToolName };
|
|
72
72
|
|
|
73
73
|
export { parseMcpToolName } from "./mcp-tool-name.js";
|
|
74
74
|
|