@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.955e4da0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-web-branch.d.ts +2 -0
- package/dist/cli-web-branch.js +9 -2
- package/dist/help-text.js +5 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/bg-shell/utilities.js +2 -2
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +92 -230
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
- package/dist/resources/extensions/github-sync/templates.js +3 -3
- package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
- package/dist/resources/extensions/gsd/auto/loop.js +74 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +142 -15
- package/dist/resources/extensions/gsd/auto/phases.js +34 -4
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
- package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
- package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +12 -9
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
- package/dist/resources/extensions/gsd/auto-start.js +20 -36
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
- package/dist/resources/extensions/gsd/auto-verification.js +7 -7
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +34 -289
- package/dist/resources/extensions/gsd/auto.js +15 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +20 -43
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +131 -140
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +89 -8
- package/dist/resources/extensions/gsd/captures.js +5 -13
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
- package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
- package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
- package/dist/resources/extensions/gsd/db/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +372 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- package/dist/resources/extensions/gsd/db-workspace.js +103 -0
- package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
- package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +8 -10
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +9 -2
- package/dist/resources/extensions/gsd/doctor.js +16 -9
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
- package/dist/resources/extensions/gsd/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-db.js +183 -2048
- package/dist/resources/extensions/gsd/guided-flow.js +68 -471
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
- package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
- package/dist/resources/extensions/gsd/md-importer.js +4 -3
- package/dist/resources/extensions/gsd/migrate/safety.js +19 -11
- package/dist/resources/extensions/gsd/migration-auto-check.js +27 -5
- package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
- package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
- package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
- package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +7 -5
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/paths.js +10 -24
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +161 -29
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
- package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
- package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
- package/dist/resources/extensions/gsd/question-transport.js +86 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +12 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +13 -5
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/templates/plan.md +7 -0
- package/dist/resources/extensions/gsd/templates/project.md +1 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/dist/resources/extensions/gsd/templates/uat.md +5 -1
- package/dist/resources/extensions/gsd/tool-contract.js +52 -8
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
- package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -5
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/uat-policy.js +16 -10
- package/dist/resources/extensions/gsd/uat-run.js +9 -14
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
- package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
- package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
- package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
- package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +287 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +17 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -10
- package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
- package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
- package/dist/resources/extensions/shared/interview-ui.js +2 -2
- package/dist/resources/shared/claude-runtime-floor.js +182 -0
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-cmd.js +20 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
- package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
- package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/dist/worktree-status-banner.js +7 -3
- package/package.json +2 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts +10 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +8 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +32 -22
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +295 -98
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +309 -154
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/components/input.js +1 -1
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +39 -30
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +22 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/bg-shell/utilities.ts +2 -2
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +114 -281
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +268 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
- package/src/resources/extensions/github-sync/templates.ts +3 -3
- package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
- package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -1
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +164 -17
- package/src/resources/extensions/gsd/auto/phases.ts +45 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
- package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +16 -8
- package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
- package/src/resources/extensions/gsd/auto-start.ts +25 -34
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
- package/src/resources/extensions/gsd/auto-verification.ts +7 -8
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +53 -306
- package/src/resources/extensions/gsd/auto.ts +27 -17
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +20 -43
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +147 -153
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +132 -6
- package/src/resources/extensions/gsd/captures.ts +5 -14
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
- package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
- package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
- package/src/resources/extensions/gsd/db/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +453 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- package/src/resources/extensions/gsd/db-workspace.ts +170 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
- package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +8 -11
- package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +10 -3
- package/src/resources/extensions/gsd/doctor.ts +15 -5
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
- package/src/resources/extensions/gsd/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-db.ts +185 -2373
- package/src/resources/extensions/gsd/guided-flow.ts +81 -561
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
- package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -3
- package/src/resources/extensions/gsd/migrate/safety.ts +17 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +30 -5
- package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
- package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
- package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
- package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/paths.ts +9 -22
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +191 -28
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
- package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
- package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
- package/src/resources/extensions/gsd/question-transport.ts +138 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +14 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +15 -5
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/templates/plan.md +7 -0
- package/src/resources/extensions/gsd/templates/project.md +1 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/src/resources/extensions/gsd/templates/uat.md +5 -1
- package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +444 -5
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +143 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +185 -1
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +121 -0
- package/src/resources/extensions/gsd/tool-contract.ts +86 -8
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
- package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
- package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -5
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/uat-policy.ts +19 -10
- package/src/resources/extensions/gsd/uat-run.ts +10 -14
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
- package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
- package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
- package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
- package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +308 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +17 -17
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +17 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +12 -10
- package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
- package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
- package/src/resources/extensions/shared/interview-ui.ts +15 -2
- package/src/resources/shared/claude-runtime-floor.ts +248 -0
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
- package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → C24pqUd-aru-l0Dp0gLZP}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → C24pqUd-aru-l0Dp0gLZP}/_ssgManifest.js +0 -0
|
@@ -7,11 +7,12 @@ import { isToolCallEventType } from "@gsd/pi-coding-agent";
|
|
|
7
7
|
import { ALWAYS_PRESERVED_SHIM_TOOL_NAMES } from "@gsd/pi-ai";
|
|
8
8
|
import { updateSnapshot } from "../ecosystem/gsd-extension-api.js";
|
|
9
9
|
import { buildMilestoneFileName, clearPathCache, milestonesDir, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
10
|
-
import { canonicalToolName, clearDiscussionFlowState,
|
|
10
|
+
import { applyAskUserQuestionsGateResult, canonicalToolName, clearDiscussionFlowState, formatPendingAskUserQuestionsGateMessage, isApprovalGateVerifiedInSnapshot, isMilestoneDepthVerified, isMilestoneDepthVerifiedInSnapshot, isQueuePhaseActive, loadWriteGateSnapshot, markApprovalGateVerified, markDepthVerified, refreshWriteGateStateFromDisk, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
|
|
11
11
|
import { resolveManifest } from "../unit-context-manifest.js";
|
|
12
12
|
import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
|
|
13
13
|
import { loadFile, saveFile, formatContinue } from "../files.js";
|
|
14
|
-
import { clearAutoCompletionStopInProgress, clearToolInvocationError, getAutoRuntimeSnapshot, getSourceObservationStore, isAutoActive, isAutoCompletionStopInProgress, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError, } from "../auto-runtime-state.js";
|
|
14
|
+
import { clearAutoCompletionStopInProgress, clearToolInvocationError, getAutoRuntimeSnapshot, getSourceObservationStore, isAutoActive, isAutoCompletionStopInProgress, isAutoPaused, isInteractiveElicitationInFlight, markToolEnd, markToolStart, recordAutoToolSurfaceSnapshot, recordToolInvocationError, } from "../auto-runtime-state.js";
|
|
15
|
+
import { applyProviderPayloadPolicy } from "../provider-payload-policy.js";
|
|
15
16
|
import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
16
17
|
import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
|
|
17
18
|
import { saveActivityLog } from "../activity-log.js";
|
|
@@ -22,16 +23,19 @@ import { logWarning as safetyLogWarning } from "../workflow-logger.js";
|
|
|
22
23
|
import { installNotifyInterceptor } from "./notify-interceptor.js";
|
|
23
24
|
import { initNotificationStore } from "../notification-store.js";
|
|
24
25
|
import { initNotificationWidget } from "../notification-widget.js";
|
|
26
|
+
import { notifyPreferenceDiagnostics } from "../preferences-diagnostics.js";
|
|
25
27
|
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
26
28
|
import { extractSubagentAgentClasses } from "./subagent-input.js";
|
|
27
|
-
import { approvalGateIdForUnit, isExplicitApprovalResponse, shouldPauseForUserApprovalQuestion } from "../user-input-boundary.js";
|
|
29
|
+
import { approvalGateIdForUnit, isExplicitApprovalResponse, messageHasPendingAskUserQuestionsTool, shouldPauseForUserApprovalQuestion, } from "../user-input-boundary.js";
|
|
28
30
|
import { applyUnitSkillVisibility, unitHasSkillManifest } from "../skill-scope.js";
|
|
29
31
|
import { getGuidedUnitContext } from "../guided-unit-context.js";
|
|
30
32
|
import { registerPlanMilestoneSchemaRecovery } from "./plan-milestone-schema-recovery.js";
|
|
31
|
-
import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
|
|
33
|
+
import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, canonicalWorkflowToolName, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
|
|
32
34
|
import { filterToolsForProvider } from "../model-router.js";
|
|
35
|
+
import { mcpToolMatchesBaseName } from "../mcp-tool-name.js";
|
|
33
36
|
import { RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES } from "../tool-presentation-plan.js";
|
|
34
|
-
import {
|
|
37
|
+
import { supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
38
|
+
import { clearPendingAutoStart } from "../pending-auto-start.js";
|
|
35
39
|
let approvalQuestionAbortInFlight = false;
|
|
36
40
|
async function loadWelcomeScreenModule() {
|
|
37
41
|
const candidates = [];
|
|
@@ -165,15 +169,19 @@ function resolveScopedToolNames(activeToolNames, requestedToolNames) {
|
|
|
165
169
|
const resolved = new Set();
|
|
166
170
|
for (const requested of requestedToolNames) {
|
|
167
171
|
const scopedMatches = [];
|
|
172
|
+
const aliasFallbacks = [];
|
|
168
173
|
for (const activeName of activeToolNames) {
|
|
169
|
-
if (
|
|
170
|
-
continue;
|
|
171
|
-
const toolSeparator = activeName.indexOf("__", "mcp__".length);
|
|
172
|
-
if (toolSeparator < 0)
|
|
173
|
-
continue;
|
|
174
|
-
if (activeName.slice(toolSeparator + 2) === requested) {
|
|
174
|
+
if (mcpToolMatchesBaseName(activeName, requested)) {
|
|
175
175
|
scopedMatches.push(activeName);
|
|
176
176
|
}
|
|
177
|
+
else if (isWorkflowAliasTool(activeName) && canonicalWorkflowToolName(activeName) === requested) {
|
|
178
|
+
aliasFallbacks.push(activeName);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Only use alias as fallback when canonical is absent — not directly and not via MCP scoping.
|
|
182
|
+
// Prevents the alias from resurfacing alongside the canonical when both are in the active set.
|
|
183
|
+
if (!exact.has(requested) && scopedMatches.length === 0) {
|
|
184
|
+
scopedMatches.push(...aliasFallbacks);
|
|
177
185
|
}
|
|
178
186
|
if (requested.startsWith("browser_") && scopedMatches.length > 0) {
|
|
179
187
|
for (const match of scopedMatches)
|
|
@@ -214,7 +222,7 @@ export function buildRunUatGsdToolSet(activeToolNames, registeredToolNames = act
|
|
|
214
222
|
...RUN_UAT_BROWSER_TOOL_NAMES,
|
|
215
223
|
]);
|
|
216
224
|
const resolved = [...new Set(scoped)];
|
|
217
|
-
const unresolved = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((tool) => !resolved.some((name) => name === tool || (name
|
|
225
|
+
const unresolved = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((tool) => !resolved.some((name) => name === tool || mcpToolMatchesBaseName(name, tool)));
|
|
218
226
|
if (unresolved.length > 0) {
|
|
219
227
|
safetyLogWarning("bootstrap", `buildRunUatGsdToolSet: required run-uat workflow tool(s) not found in active/registered surface: ${unresolved.join(", ")}. Session may lack gsd-workflow MCP connection.`);
|
|
220
228
|
}
|
|
@@ -271,7 +279,17 @@ function applyMinimalGsdToolSurface(pi) {
|
|
|
271
279
|
return;
|
|
272
280
|
const dash = getAutoRuntimeSnapshot();
|
|
273
281
|
if (dash.active && dash.currentUnit) {
|
|
274
|
-
|
|
282
|
+
const currentToolNames = pi.getActiveTools();
|
|
283
|
+
const registeredToolNames = resolveRegisteredToolNames(pi, currentToolNames);
|
|
284
|
+
const scopedToolNames = buildMinimalAutoGsdToolSet(currentToolNames, dash.currentUnit.type, registeredToolNames);
|
|
285
|
+
recordAutoToolSurfaceSnapshot({
|
|
286
|
+
source: "runtime-scope",
|
|
287
|
+
unitType: dash.currentUnit.type,
|
|
288
|
+
modelFacingToolNames: scopedToolNames,
|
|
289
|
+
registeredToolNames,
|
|
290
|
+
scopedToolNames,
|
|
291
|
+
});
|
|
292
|
+
pi.setActiveTools(scopedToolNames);
|
|
275
293
|
return;
|
|
276
294
|
}
|
|
277
295
|
if (!isGeneralGsdToolScopingRequested())
|
|
@@ -286,6 +304,13 @@ export function scopeGsdWorkflowToolsForDispatch(pi, unitType) {
|
|
|
286
304
|
const scoped = unitType
|
|
287
305
|
? buildMinimalAutoGsdToolSet(current, unitType, registeredToolNames)
|
|
288
306
|
: buildMinimalGsdWorkflowToolSet(current, registeredToolNames);
|
|
307
|
+
recordAutoToolSurfaceSnapshot({
|
|
308
|
+
source: "dispatch-scope",
|
|
309
|
+
unitType,
|
|
310
|
+
modelFacingToolNames: scoped,
|
|
311
|
+
registeredToolNames,
|
|
312
|
+
scopedToolNames: scoped,
|
|
313
|
+
});
|
|
289
314
|
const toolsChanged = !(scoped.length === current.length && scoped.every((name, index) => name === current[index]));
|
|
290
315
|
const canScopeSkills = unitHasSkillManifest(unitType) && pi.getVisibleSkills && pi.setVisibleSkills;
|
|
291
316
|
if (!toolsChanged && !canScopeSkills) {
|
|
@@ -420,8 +445,16 @@ function isShellExecutionTool(canonicalName) {
|
|
|
420
445
|
function activateDeferredApprovalGate(basePath) {
|
|
421
446
|
if (deferredApprovalGate?.basePath !== basePath)
|
|
422
447
|
return;
|
|
423
|
-
|
|
448
|
+
const gateId = deferredApprovalGate.gateId;
|
|
424
449
|
deferredApprovalGate = null;
|
|
450
|
+
refreshWriteGateStateFromDisk(basePath);
|
|
451
|
+
const snapshot = loadWriteGateSnapshot(basePath);
|
|
452
|
+
const milestoneId = extractDepthVerificationMilestoneId(gateId);
|
|
453
|
+
if (isApprovalGateVerifiedInSnapshot(snapshot, gateId))
|
|
454
|
+
return;
|
|
455
|
+
if (milestoneId && isMilestoneDepthVerifiedInSnapshot(snapshot, milestoneId))
|
|
456
|
+
return;
|
|
457
|
+
setPendingGate(gateId, basePath);
|
|
425
458
|
}
|
|
426
459
|
function extractGateQuestionId(input) {
|
|
427
460
|
const questions = input?.questions ?? [];
|
|
@@ -540,6 +573,7 @@ function initSessionNotifications(ctx) {
|
|
|
540
573
|
initNotificationStore(resolveNotificationStoreBasePath(contextBasePath(ctx)));
|
|
541
574
|
installNotifyInterceptor(ctx);
|
|
542
575
|
initNotificationWidget(ctx);
|
|
576
|
+
notifyPreferenceDiagnostics(ctx, contextBasePath(ctx), { surface: "session-start" });
|
|
543
577
|
}
|
|
544
578
|
async function prepareWorkflowMcpForHookContext(ctx, basePath) {
|
|
545
579
|
// Skip MCP auto-prep when running inside an auto-worktree. The worktree
|
|
@@ -601,7 +635,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
601
635
|
catch { /* non-fatal */ }
|
|
602
636
|
}
|
|
603
637
|
});
|
|
604
|
-
pi.on("session_switch", async (
|
|
638
|
+
pi.on("session_switch", async (event, ctx) => {
|
|
605
639
|
const basePath = contextBasePath(ctx);
|
|
606
640
|
const preserveCloseoutSurface = isAutoCompletionStopInProgress();
|
|
607
641
|
initSessionNotifications(ctx);
|
|
@@ -610,6 +644,13 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
610
644
|
clearDeferredApprovalGate();
|
|
611
645
|
await resetAskUserQuestionsTurnCache();
|
|
612
646
|
clearDiscussionFlowState(basePath);
|
|
647
|
+
// /clear or /new destroys the conversation holding a discuss interview, so
|
|
648
|
+
// its pending discuss→auto handoff can never be answered — clear it. Resume
|
|
649
|
+
// restores the interview transcript, so the entry survives. Auto-mode's own
|
|
650
|
+
// newSession() calls are safe: the handoff consumes the entry on agent_end.
|
|
651
|
+
if (event.reason === "new") {
|
|
652
|
+
clearPendingAutoStart(basePath);
|
|
653
|
+
}
|
|
613
654
|
await syncServiceTierStatus(ctx);
|
|
614
655
|
await applyDisabledModelProviderPolicy(ctx);
|
|
615
656
|
await applyCompactionThresholdOverride(ctx);
|
|
@@ -803,6 +844,20 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
803
844
|
pi.on("message_update", async (event, ctx) => {
|
|
804
845
|
if (approvalQuestionAbortInFlight)
|
|
805
846
|
return;
|
|
847
|
+
// If the model asked via ask_user_questions, that in-flight elicitation IS
|
|
848
|
+
// the human boundary. Arming the pause/gate here (and emitting the "waiting
|
|
849
|
+
// for your approval - pausing" notice) would tear it down and trigger the
|
|
850
|
+
// foreground self-cancel/re-ask loop. The marker is set only by the
|
|
851
|
+
// claude-code-cli SDK elicitation handler and is ungated, so it is true in
|
|
852
|
+
// foreground; under the native-TUI provider it is always false and this path
|
|
853
|
+
// runs unchanged (#cc-elicitation-self-cancel).
|
|
854
|
+
if (isInteractiveElicitationInFlight())
|
|
855
|
+
return;
|
|
856
|
+
// Prose with "?" can stream before the MCP tool/elicitation starts. When the
|
|
857
|
+
// structured ask_user_questions call is already in the partial message, the
|
|
858
|
+
// tool IS the human boundary — do not arm the text-based approval pause.
|
|
859
|
+
if (messageHasPendingAskUserQuestionsTool(event.message))
|
|
860
|
+
return;
|
|
806
861
|
const dash = getAutoRuntimeSnapshot();
|
|
807
862
|
if (dash.active)
|
|
808
863
|
return;
|
|
@@ -1071,77 +1126,32 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1071
1126
|
const basePath = contextBasePath(ctx);
|
|
1072
1127
|
const milestoneId = await getDiscussionMilestoneIdFor(basePath);
|
|
1073
1128
|
const details = event.details;
|
|
1074
|
-
// ── Discussion gate enforcement: handle gate question responses ──
|
|
1075
|
-
// If the result is cancelled or has no response, the pending gate stays active
|
|
1076
|
-
// so the model is blocked from non-read-only tools until it re-asks.
|
|
1077
|
-
// If the user responded at all (even "needs adjustment"), clear the pending gate
|
|
1078
|
-
// because the user engaged — the prompt handles the re-ask-after-adjustment flow.
|
|
1079
1129
|
const questions = event.input?.questions ?? [];
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
await maybePauseAutoForApprovalGate(ctx, pi, true, interrupted
|
|
1093
|
-
? "Depth confirmation was interrupted — pausing auto-mode until you respond."
|
|
1094
|
-
: "Depth confirmation is waiting for your answer — pausing auto-mode.");
|
|
1095
|
-
}
|
|
1096
|
-
return {
|
|
1097
|
-
content: [{
|
|
1098
|
-
type: "text",
|
|
1099
|
-
text: [
|
|
1100
|
-
`Waiting for depth confirmation on gate "${currentPendingGate}".`,
|
|
1101
|
-
interrupted
|
|
1102
|
-
? "The confirmation question was interrupted before a response was recorded."
|
|
1103
|
-
: "No user response was received for the confirmation question.",
|
|
1104
|
-
"Do not infer approval from earlier or prior messages.",
|
|
1105
|
-
"Do not proceed, write files, save artifacts, or call other tools.",
|
|
1106
|
-
`Re-call ask_user_questions with the same gate question id ("${currentPendingGate}") and wait for the user's response.`,
|
|
1107
|
-
].join(" "),
|
|
1108
|
-
}],
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
const pendingQuestion = questions.find((question) => question?.id === currentPendingGate);
|
|
1113
|
-
if (pendingQuestion) {
|
|
1114
|
-
const answer = details.response?.answers?.[currentPendingGate];
|
|
1115
|
-
if (isDepthConfirmationAnswer(answer?.selected, pendingQuestion.options)) {
|
|
1116
|
-
markApprovalGateVerified(currentPendingGate, basePath);
|
|
1117
|
-
const milestoneIdFromGate = extractDepthVerificationMilestoneId(currentPendingGate);
|
|
1118
|
-
if (milestoneIdFromGate)
|
|
1119
|
-
markDepthVerified(milestoneIdFromGate, basePath);
|
|
1120
|
-
clearPendingGate(basePath);
|
|
1121
|
-
clearDeferredApprovalGate(basePath);
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1130
|
+
const gateResult = applyAskUserQuestionsGateResult({
|
|
1131
|
+
basePath,
|
|
1132
|
+
questions,
|
|
1133
|
+
details,
|
|
1134
|
+
fallbackMilestoneId: milestoneId,
|
|
1135
|
+
});
|
|
1136
|
+
if (gateResult.status === "waiting") {
|
|
1137
|
+
resetToolCallLoopGuard();
|
|
1138
|
+
if (ctx) {
|
|
1139
|
+
await maybePauseAutoForApprovalGate(ctx, pi, true, gateResult.interrupted
|
|
1140
|
+
? "Depth confirmation was interrupted — pausing auto-mode until you respond."
|
|
1141
|
+
: "Depth confirmation is waiting for your answer — pausing auto-mode.");
|
|
1124
1142
|
}
|
|
1143
|
+
return {
|
|
1144
|
+
content: [{
|
|
1145
|
+
type: "text",
|
|
1146
|
+
text: formatPendingAskUserQuestionsGateMessage(gateResult.pendingGateId, gateResult.interrupted),
|
|
1147
|
+
}],
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
if (gateResult.status === "verified") {
|
|
1151
|
+
clearDeferredApprovalGate(basePath);
|
|
1125
1152
|
}
|
|
1126
1153
|
if (details?.cancelled || !details?.response)
|
|
1127
1154
|
return;
|
|
1128
|
-
for (const question of questions) {
|
|
1129
|
-
if (typeof question.id === "string" && question.id.includes("depth_verification")) {
|
|
1130
|
-
// Only unlock the gate if the user selected the first option (confirmation).
|
|
1131
|
-
// Cross-references against the question's defined options to reject free-form "Other" text.
|
|
1132
|
-
const answer = details.response?.answers?.[question.id];
|
|
1133
|
-
const inferredMilestoneId = extractDepthVerificationMilestoneId(question.id) ?? milestoneId;
|
|
1134
|
-
if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
|
|
1135
|
-
if (currentPendingGate && question.id !== currentPendingGate)
|
|
1136
|
-
break;
|
|
1137
|
-
markApprovalGateVerified(question.id, basePath);
|
|
1138
|
-
markDepthVerified(inferredMilestoneId, basePath);
|
|
1139
|
-
clearPendingGate(basePath);
|
|
1140
|
-
clearDeferredApprovalGate(basePath);
|
|
1141
|
-
}
|
|
1142
|
-
break;
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
1155
|
if (!milestoneId)
|
|
1146
1156
|
return;
|
|
1147
1157
|
await saveDiscussionQuestionRound(basePath, milestoneId, questions, details);
|
|
@@ -1156,6 +1166,19 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1156
1166
|
clearDeferredApprovalGate(basePath);
|
|
1157
1167
|
}
|
|
1158
1168
|
}
|
|
1169
|
+
// Safety harness: record evidence here, not only in tool_call. External
|
|
1170
|
+
// engines (claude-code-cli) pre-execute tools, so the agent loop skips
|
|
1171
|
+
// beforeToolCall/tool_call for them — tool_execution_start is the only
|
|
1172
|
+
// event that fires for every tool call. recordToolCall dedupes by
|
|
1173
|
+
// toolCallId, so native tools (which hit both events) record once.
|
|
1174
|
+
safetyRecordToolCall(event.toolCallId, event.toolName, (event.args ?? {}));
|
|
1175
|
+
const execDash = getAutoRuntimeSnapshot();
|
|
1176
|
+
if (execDash.basePath && execDash.currentUnit?.type === "execute-task") {
|
|
1177
|
+
const { milestone: xMid, slice: xSid, task: xTid } = parseUnitId(execDash.currentUnit.id);
|
|
1178
|
+
if (xMid && xSid && xTid) {
|
|
1179
|
+
saveEvidenceToDisk(execDash.basePath, xMid, xSid, xTid);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1159
1182
|
if (!isAutoActive())
|
|
1160
1183
|
return;
|
|
1161
1184
|
markToolStart(event.toolCallId, event.toolName);
|
|
@@ -1196,61 +1219,10 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1196
1219
|
const payload = event.payload;
|
|
1197
1220
|
if (!payload || typeof payload !== "object")
|
|
1198
1221
|
return;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
const { createObservationMask, createResponsesInputObservationMask, truncateContextResultMessages, truncateResponsesInputResultItems, } = await import("../context-masker.js");
|
|
1204
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
1205
|
-
const cmConfig = prefs?.preferences.context_management;
|
|
1206
|
-
// Observation masking: replace old tool results with placeholders.
|
|
1207
|
-
// Only active during auto-mode when context_management.observation_masking is enabled.
|
|
1208
|
-
if (isAutoActive() && cmConfig?.observation_masking !== false) {
|
|
1209
|
-
const keepTurns = cmConfig?.observation_mask_turns ?? 8;
|
|
1210
|
-
const messages = payload.messages;
|
|
1211
|
-
if (Array.isArray(messages)) {
|
|
1212
|
-
payload.messages = createObservationMask(keepTurns)(messages);
|
|
1213
|
-
}
|
|
1214
|
-
const input = payload.input;
|
|
1215
|
-
if (Array.isArray(input)) {
|
|
1216
|
-
payload.input = createResponsesInputObservationMask(keepTurns)(input);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
// Tool result truncation: cap individual tool result content length.
|
|
1220
|
-
// Applies in ALL modes (auto + interactive) to prevent context bloat.
|
|
1221
|
-
// In pi-ai format, toolResult messages have role: "toolResult" and content: TextContent[].
|
|
1222
|
-
// Creates new objects to avoid mutating shared conversation state.
|
|
1223
|
-
const maxChars = cmConfig?.tool_result_max_chars ?? 800;
|
|
1224
|
-
const msgs = payload.messages;
|
|
1225
|
-
if (Array.isArray(msgs)) {
|
|
1226
|
-
payload.messages = truncateContextResultMessages(msgs, maxChars);
|
|
1227
|
-
}
|
|
1228
|
-
const input = payload.input;
|
|
1229
|
-
if (Array.isArray(input)) {
|
|
1230
|
-
payload.input = truncateResponsesInputResultItems(input, maxChars);
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
catch { /* non-fatal */ }
|
|
1234
|
-
try {
|
|
1235
|
-
if (isAutoActive()) {
|
|
1236
|
-
const sourceContextBlock = getSourceObservationStore().renderActiveBlock();
|
|
1237
|
-
if (sourceContextBlock) {
|
|
1238
|
-
const nextPayload = injectSourceContextBlockIntoPayload(payload, sourceContextBlock);
|
|
1239
|
-
Object.assign(payload, nextPayload);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
catch { /* non-fatal */ }
|
|
1244
|
-
// ── Service Tier ────────────────────────────────────────────────────
|
|
1245
|
-
const modelId = event.model?.id;
|
|
1246
|
-
if (!modelId)
|
|
1247
|
-
return payload;
|
|
1248
|
-
const { getEffectiveServiceTier, supportsServiceTier } = await import("../service-tier.js");
|
|
1249
|
-
const tier = getEffectiveServiceTier();
|
|
1250
|
-
if (!tier || !supportsServiceTier(modelId))
|
|
1251
|
-
return payload;
|
|
1252
|
-
payload.service_tier = tier;
|
|
1253
|
-
return payload;
|
|
1222
|
+
return applyProviderPayloadPolicy({
|
|
1223
|
+
payload,
|
|
1224
|
+
modelId: event.model?.id,
|
|
1225
|
+
});
|
|
1254
1226
|
});
|
|
1255
1227
|
// Capability-aware model routing hook (ADR-004)
|
|
1256
1228
|
// Extensions can override model selection by returning { modelId: "..." }
|
|
@@ -1282,16 +1254,35 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1282
1254
|
const registeredToolNames = resolveRegisteredToolNames(pi, event.activeToolNames);
|
|
1283
1255
|
const compatibleRegisteredToolNames = filterToolsForProvider(registeredToolNames, event.selectedModelApi, event.selectedModelProvider).compatible.filter((name) => !(dropAliases && isWorkflowAliasTool(name)));
|
|
1284
1256
|
const guidedUnit = getGuidedUnitContext();
|
|
1285
|
-
const
|
|
1257
|
+
const requestRegisteredToolNames = guidedUnit?.unitType === "run-uat"
|
|
1258
|
+
? compatibleRegisteredToolNames
|
|
1259
|
+
: registeredToolNames;
|
|
1260
|
+
const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, requestRegisteredToolNames, guidedUnit?.unitType);
|
|
1286
1261
|
if (requestScoped) {
|
|
1262
|
+
recordAutoToolSurfaceSnapshot({
|
|
1263
|
+
source: "provider-adjustment",
|
|
1264
|
+
unitType: guidedUnit?.unitType,
|
|
1265
|
+
modelFacingToolNames: requestScoped,
|
|
1266
|
+
registeredToolNames: requestRegisteredToolNames,
|
|
1267
|
+
scopedToolNames: requestScoped,
|
|
1268
|
+
});
|
|
1287
1269
|
return { toolNames: requestScoped };
|
|
1288
1270
|
}
|
|
1289
1271
|
const dash = getAutoRuntimeSnapshot();
|
|
1290
1272
|
if (dash.active && dash.currentUnit) {
|
|
1273
|
+
const registeredForUnit = dash.currentUnit.type === "run-uat"
|
|
1274
|
+
? compatibleRegisteredToolNames
|
|
1275
|
+
: resolveRegisteredToolNames(pi, event.activeToolNames);
|
|
1276
|
+
const scopedToolNames = buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, registeredForUnit);
|
|
1277
|
+
recordAutoToolSurfaceSnapshot({
|
|
1278
|
+
source: "provider-adjustment",
|
|
1279
|
+
unitType: dash.currentUnit.type,
|
|
1280
|
+
modelFacingToolNames: scopedToolNames,
|
|
1281
|
+
registeredToolNames: registeredForUnit,
|
|
1282
|
+
scopedToolNames,
|
|
1283
|
+
});
|
|
1291
1284
|
return {
|
|
1292
|
-
toolNames:
|
|
1293
|
-
? compatibleRegisteredToolNames
|
|
1294
|
-
: resolveRegisteredToolNames(pi, event.activeToolNames)),
|
|
1285
|
+
toolNames: scopedToolNames,
|
|
1295
1286
|
};
|
|
1296
1287
|
}
|
|
1297
1288
|
if (isGeneralGsdToolScopingRequested()) {
|
|
@@ -3,10 +3,12 @@ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkS
|
|
|
3
3
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { minimatch } from "minimatch";
|
|
5
5
|
import { GSD_PHASE_SCOPE_DISPLAY_REASON, shouldBlockAutoUnitToolCall } from "../auto-unit-tool-scope.js";
|
|
6
|
+
import { stripMcpToolPrefix } from "../mcp-tool-name.js";
|
|
6
7
|
import { getIsolationMode } from "../preferences.js";
|
|
7
8
|
import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
|
|
8
9
|
import { logWarning } from "../workflow-logger.js";
|
|
9
10
|
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
11
|
+
import { worktreesDirs } from "../worktree-placement.js";
|
|
10
12
|
/**
|
|
11
13
|
* Regex matching milestone CONTEXT.md file names in both legacy M001
|
|
12
14
|
* and unique M001-abc123 formats. Exported so regex-hardening tests
|
|
@@ -102,10 +104,7 @@ const GATE_SAFE_TOOLS = new Set([
|
|
|
102
104
|
"ask_user_questions",
|
|
103
105
|
]);
|
|
104
106
|
export function canonicalToolName(toolName) {
|
|
105
|
-
|
|
106
|
-
return toolName;
|
|
107
|
-
const toolSeparator = toolName.indexOf("__", "mcp__".length);
|
|
108
|
-
return toolSeparator >= 0 ? toolName.slice(toolSeparator + 2) : toolName;
|
|
107
|
+
return stripMcpToolPrefix(toolName);
|
|
109
108
|
}
|
|
110
109
|
/**
|
|
111
110
|
* Persistence is ON by default (opt-out).
|
|
@@ -216,6 +215,23 @@ export function loadWriteGateSnapshot(basePath) {
|
|
|
216
215
|
return currentWriteGateSnapshot(basePath);
|
|
217
216
|
}
|
|
218
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Merge the persisted write-gate snapshot into the in-process Map entry.
|
|
220
|
+
* The workflow MCP server runs in a child process and records depth
|
|
221
|
+
* verification there; without this refresh the extension host keeps stale
|
|
222
|
+
* pending-gate memory and `activateDeferredApprovalGate` can re-arm a gate
|
|
223
|
+
* that the subprocess already cleared on disk.
|
|
224
|
+
*/
|
|
225
|
+
export function refreshWriteGateStateFromDisk(basePath) {
|
|
226
|
+
if (!shouldPersistWriteGateSnapshot())
|
|
227
|
+
return;
|
|
228
|
+
const snapshot = loadWriteGateSnapshot(basePath);
|
|
229
|
+
const state = getWriteGateState(basePath);
|
|
230
|
+
state.pendingGateId = snapshot.pendingGateId;
|
|
231
|
+
state.activeQueuePhase = snapshot.activeQueuePhase;
|
|
232
|
+
state.verifiedDepthMilestones = new Set(snapshot.verifiedDepthMilestones);
|
|
233
|
+
state.verifiedApprovalGates = new Set(snapshot.verifiedApprovalGates ?? []);
|
|
234
|
+
}
|
|
219
235
|
export function isDepthVerified(basePath = process.cwd()) {
|
|
220
236
|
return getWriteGateState(basePath).verifiedDepthMilestones.size > 0;
|
|
221
237
|
}
|
|
@@ -225,6 +241,7 @@ export function isDepthVerified(basePath = process.cwd()) {
|
|
|
225
241
|
export function isMilestoneDepthVerified(milestoneId, basePath = process.cwd()) {
|
|
226
242
|
if (!milestoneId)
|
|
227
243
|
return false;
|
|
244
|
+
refreshWriteGateStateFromDisk(basePath);
|
|
228
245
|
return getWriteGateState(basePath).verifiedDepthMilestones.has(milestoneId);
|
|
229
246
|
}
|
|
230
247
|
export function isMilestoneDepthVerifiedInSnapshot(snapshot, milestoneId) {
|
|
@@ -311,6 +328,7 @@ export function clearPendingGate(basePath) {
|
|
|
311
328
|
* Get the currently pending gate, if any.
|
|
312
329
|
*/
|
|
313
330
|
export function getPendingGate(basePath = process.cwd()) {
|
|
331
|
+
refreshWriteGateStateFromDisk(basePath);
|
|
314
332
|
return getWriteGateState(basePath).pendingGateId;
|
|
315
333
|
}
|
|
316
334
|
/**
|
|
@@ -385,6 +403,67 @@ export function isDepthConfirmationAnswer(selected, options) {
|
|
|
385
403
|
// Returning false prevents any free-form string from unlocking the gate.
|
|
386
404
|
return false;
|
|
387
405
|
}
|
|
406
|
+
function findGateQuestion(questions, gateId) {
|
|
407
|
+
return questions.find((question) => question?.id === gateId);
|
|
408
|
+
}
|
|
409
|
+
function readSelectedGateAnswer(details, questionId) {
|
|
410
|
+
return details.response?.answers?.[questionId]?.selected;
|
|
411
|
+
}
|
|
412
|
+
function verifyAnsweredGate(basePath, question, fallbackMilestoneId) {
|
|
413
|
+
const gateId = typeof question.id === "string" ? question.id : "";
|
|
414
|
+
const milestoneId = extractDepthVerificationMilestoneId(gateId) ?? fallbackMilestoneId ?? null;
|
|
415
|
+
markApprovalGateVerified(gateId, basePath);
|
|
416
|
+
markDepthVerified(milestoneId, basePath);
|
|
417
|
+
clearPendingGate(basePath);
|
|
418
|
+
return { status: "verified", gateId, milestoneId };
|
|
419
|
+
}
|
|
420
|
+
export function applyAskUserQuestionsGateResult(options) {
|
|
421
|
+
const { basePath, questions, details, fallbackMilestoneId } = options;
|
|
422
|
+
const currentPendingGate = getPendingGate(basePath);
|
|
423
|
+
if (currentPendingGate) {
|
|
424
|
+
if (details.cancelled || !details.response) {
|
|
425
|
+
return {
|
|
426
|
+
status: "waiting",
|
|
427
|
+
pendingGateId: currentPendingGate,
|
|
428
|
+
interrupted: details.interrupted === true,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
const pendingQuestion = findGateQuestion(questions, currentPendingGate);
|
|
432
|
+
if (pendingQuestion) {
|
|
433
|
+
const selected = readSelectedGateAnswer(details, currentPendingGate);
|
|
434
|
+
if (isDepthConfirmationAnswer(selected, pendingQuestion.options)) {
|
|
435
|
+
return verifyAnsweredGate(basePath, pendingQuestion, fallbackMilestoneId);
|
|
436
|
+
}
|
|
437
|
+
return { status: "answered", gateId: currentPendingGate };
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (details.cancelled || !details.response)
|
|
441
|
+
return { status: "not-gate" };
|
|
442
|
+
for (const question of questions) {
|
|
443
|
+
if (typeof question.id !== "string" || !isGateQuestionId(question.id))
|
|
444
|
+
continue;
|
|
445
|
+
const selected = readSelectedGateAnswer(details, question.id);
|
|
446
|
+
if (!isDepthConfirmationAnswer(selected, question.options)) {
|
|
447
|
+
return { status: "answered", gateId: question.id };
|
|
448
|
+
}
|
|
449
|
+
if (currentPendingGate && question.id !== currentPendingGate) {
|
|
450
|
+
return { status: "answered", gateId: currentPendingGate };
|
|
451
|
+
}
|
|
452
|
+
return verifyAnsweredGate(basePath, question, fallbackMilestoneId);
|
|
453
|
+
}
|
|
454
|
+
return { status: "not-gate" };
|
|
455
|
+
}
|
|
456
|
+
export function formatPendingAskUserQuestionsGateMessage(pendingGateId, interrupted) {
|
|
457
|
+
return [
|
|
458
|
+
`Waiting for depth confirmation on gate "${pendingGateId}".`,
|
|
459
|
+
interrupted
|
|
460
|
+
? "The confirmation question was interrupted before a response was recorded."
|
|
461
|
+
: "No user response was received for the confirmation question.",
|
|
462
|
+
"Do not infer approval from earlier or prior messages.",
|
|
463
|
+
"Do not proceed, write files, save artifacts, or call other tools.",
|
|
464
|
+
`Re-call ask_user_questions with the same gate question id ("${pendingGateId}") and wait for the user's response.`,
|
|
465
|
+
].join(" ");
|
|
466
|
+
}
|
|
388
467
|
export function shouldBlockContextWrite(toolName, inputPath, milestoneId, _queuePhaseActive, basePath = process.cwd()) {
|
|
389
468
|
if (toolName !== "write")
|
|
390
469
|
return { block: false };
|
|
@@ -860,10 +939,12 @@ export function shouldBlockWorktreeWrite(toolName, targetPath, effectiveBasePath
|
|
|
860
939
|
const realTarget = realpathOrResolve(absTarget);
|
|
861
940
|
const realRoot = realpathOrResolve(projectRoot);
|
|
862
941
|
const realGsd = realpathOrResolve(join(projectRoot, ".gsd"));
|
|
863
|
-
|
|
864
|
-
//
|
|
865
|
-
|
|
866
|
-
|
|
942
|
+
// Allow writes inside a legitimate worktrees subtree (canonical
|
|
943
|
+
// .gsd-worktrees/ or legacy .gsd/worktrees/).
|
|
944
|
+
for (const container of worktreesDirs(projectRoot)) {
|
|
945
|
+
if (isPathContained(realTarget, realpathOrResolve(container)))
|
|
946
|
+
return { block: false };
|
|
947
|
+
}
|
|
867
948
|
// Allow writes to .gsd/ planning artifacts, but reject siblings whose name
|
|
868
949
|
// starts with "worktrees" (the worktrees-extra prefix trick — case 4).
|
|
869
950
|
if (isPathContained(realTarget, realGsd)) {
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* `.gsd/CAPTURES.md`, not the worktree's local `.gsd/`.
|
|
9
9
|
*/
|
|
10
10
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
11
|
-
import { join, resolve
|
|
11
|
+
import { join, resolve } from "node:path";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
13
|
import { gsdRoot } from "./paths.js";
|
|
14
|
+
import { findWorktreeSegment } from "./worktree-root.js";
|
|
14
15
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
15
16
|
const CAPTURES_FILENAME = "CAPTURES.md";
|
|
16
17
|
const VALID_CLASSIFICATIONS = [
|
|
@@ -30,19 +31,10 @@ const VALID_CLASSIFICATIONS = [
|
|
|
30
31
|
*/
|
|
31
32
|
export function resolveCapturesPath(basePath) {
|
|
32
33
|
const resolved = resolve(basePath);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let idx = resolved.indexOf(worktreeMarker);
|
|
36
|
-
if (idx === -1) {
|
|
37
|
-
// Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/
|
|
38
|
-
const symlinkRe = new RegExp(`\\${sep}\\.gsd\\${sep}projects\\${sep}[a-f0-9]+\\${sep}worktrees\\${sep}`);
|
|
39
|
-
const match = resolved.match(symlinkRe);
|
|
40
|
-
if (match && match.index !== undefined)
|
|
41
|
-
idx = match.index;
|
|
42
|
-
}
|
|
43
|
-
if (idx !== -1) {
|
|
34
|
+
const segment = findWorktreeSegment(resolved.replaceAll("\\", "/"));
|
|
35
|
+
if (segment) {
|
|
44
36
|
// basePath is inside a worktree — resolve to project root
|
|
45
|
-
const projectRoot = resolved.slice(0,
|
|
37
|
+
const projectRoot = resolved.slice(0, segment.gsdIdx);
|
|
46
38
|
return join(projectRoot, ".gsd", CAPTURES_FILENAME);
|
|
47
39
|
}
|
|
48
40
|
return join(gsdRoot(basePath), CAPTURES_FILENAME);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Shared DB-backed guard for milestone closeout finalization.
|
|
3
|
-
import {
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
import { getLatestAssessmentByScope, getMilestone, getMilestoneSlices, getPendingGates, getSliceTasks, isDbAvailable, } from "./gsd-db.js";
|
|
5
|
+
import { getWorkflowDatabasePath, refreshWorkflowDatabaseFromDisk, } from "./db-workspace.js";
|
|
4
6
|
import { isClosedStatus } from "./status-guards.js";
|
|
7
|
+
import { closeQualityGatesFromEvidence } from "./quality-gate-closure.js";
|
|
5
8
|
export const CLOSEOUT_CONSISTENCY_BLOCKED_REASON = "closeout-consistency-blocked";
|
|
6
9
|
function blocked(reason, message) {
|
|
7
10
|
return {
|
|
@@ -14,22 +17,30 @@ function blocked(reason, message) {
|
|
|
14
17
|
function isFileBackedDbPath(path) {
|
|
15
18
|
return Boolean(path && path !== ":memory:");
|
|
16
19
|
}
|
|
20
|
+
function artifactBasePathFromDb() {
|
|
21
|
+
const dbPath = getWorkflowDatabasePath();
|
|
22
|
+
if (!isFileBackedDbPath(dbPath))
|
|
23
|
+
return undefined;
|
|
24
|
+
return dirname(dirname(dbPath));
|
|
25
|
+
}
|
|
17
26
|
export function checkCloseoutConsistencyGate(milestoneId, options = {}) {
|
|
18
27
|
if (!isDbAvailable()) {
|
|
19
28
|
return blocked("db-unavailable", `Closeout consistency blocked for ${milestoneId}: canonical DB is unavailable.`);
|
|
20
29
|
}
|
|
21
|
-
if (options.refreshFromDisk && isFileBackedDbPath(
|
|
30
|
+
if (options.refreshFromDisk && isFileBackedDbPath(getWorkflowDatabasePath()) && !refreshWorkflowDatabaseFromDisk()) {
|
|
22
31
|
return blocked("db-refresh-failed", `Closeout consistency blocked for ${milestoneId}: canonical DB refresh failed.`);
|
|
23
32
|
}
|
|
24
33
|
const milestone = getMilestone(milestoneId);
|
|
25
34
|
if (!milestone) {
|
|
26
35
|
return blocked("milestone-missing", `Closeout consistency blocked for ${milestoneId}: milestone is missing from canonical DB.`);
|
|
27
36
|
}
|
|
28
|
-
if (!isClosedStatus(milestone.status)) {
|
|
37
|
+
if (!isClosedStatus(milestone.status) && !options.allowOpenMilestone) {
|
|
29
38
|
return blocked("milestone-open", `Closeout consistency blocked for ${milestoneId}: canonical DB milestone status is "${milestone.status}".`);
|
|
30
39
|
}
|
|
40
|
+
const validation = milestone.status === "skipped"
|
|
41
|
+
? null
|
|
42
|
+
: getLatestAssessmentByScope(milestoneId, "milestone-validation");
|
|
31
43
|
if (milestone.status !== "skipped") {
|
|
32
|
-
const validation = getLatestAssessmentByScope(milestoneId, "milestone-validation");
|
|
33
44
|
if (validation?.status !== "pass") {
|
|
34
45
|
return blocked("validation-not-pass", `Closeout consistency blocked for ${milestoneId}: latest milestone validation is "${validation?.status ?? "absent"}".`);
|
|
35
46
|
}
|
|
@@ -38,6 +49,12 @@ export function checkCloseoutConsistencyGate(milestoneId, options = {}) {
|
|
|
38
49
|
if (slices.length === 0 && milestone.status !== "skipped") {
|
|
39
50
|
return blocked("slice-missing", `Closeout consistency blocked for ${milestoneId}: no slices exist in canonical DB.`);
|
|
40
51
|
}
|
|
52
|
+
if (milestone.status !== "skipped") {
|
|
53
|
+
closeQualityGatesFromEvidence(milestoneId, {
|
|
54
|
+
artifactBasePath: options.artifactBasePath ?? artifactBasePathFromDb(),
|
|
55
|
+
milestoneValidationPassed: validation?.status === "pass",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
41
58
|
for (const slice of slices) {
|
|
42
59
|
if (!isClosedStatus(slice.status)) {
|
|
43
60
|
return blocked("slice-open", `Closeout consistency blocked for ${milestoneId}: slice ${slice.id} status is "${slice.status}".`);
|