@opengsd/gsd-pi 1.2.0-dev.b1abb545 → 1.2.0-dev.fb12b103
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-style.d.ts +17 -0
- package/dist/cli-style.js +28 -0
- package/dist/cli.js +1 -1
- package/dist/headless-events.d.ts +4 -2
- package/dist/headless-events.js +7 -29
- package/dist/models-resolver.d.ts +3 -13
- package/dist/models-resolver.js +3 -22
- package/dist/resource-loader.js +2 -14
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +30 -64
- package/dist/resources/extensions/async-jobs/await-tool.js +80 -12
- package/dist/resources/extensions/async-jobs/index.js +65 -0
- package/dist/resources/extensions/async-jobs/job-manager.js +12 -1
- package/dist/resources/extensions/bg-shell/bg-shell-command.js +6 -6
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +10 -7
- package/dist/resources/extensions/bg-shell/overlay.js +9 -6
- package/dist/resources/extensions/bg-shell/process-manager.js +54 -25
- package/dist/resources/extensions/bg-shell/readiness-detector.js +11 -0
- package/dist/resources/extensions/bg-shell/utilities.js +5 -2
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +209 -88
- package/dist/resources/extensions/browser-tools/engine/selection.js +73 -5
- package/dist/resources/extensions/browser-tools/index.js +69 -12
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +38 -6
- package/dist/resources/extensions/gsd/auto/orchestrator.js +40 -9
- package/dist/resources/extensions/gsd/auto/phases.js +6 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +12 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +15 -10
- package/dist/resources/extensions/gsd/auto-start.js +21 -21
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
- package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
- package/dist/resources/extensions/gsd/auto.js +8 -20
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -12
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +151 -20
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +30 -4
- package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
- package/dist/resources/extensions/gsd/browser-daemon-auto-prep.js +83 -0
- package/dist/resources/extensions/gsd/browser-evidence.js +8 -2
- package/dist/resources/extensions/gsd/captures.js +5 -15
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- package/dist/resources/extensions/gsd/constants.js +0 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
- 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/doctor-environment.js +5 -11
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
- package/dist/resources/extensions/gsd/error-classifier.js +9 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +30 -10
- 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 +171 -2048
- package/dist/resources/extensions/gsd/guidance.js +98 -0
- package/dist/resources/extensions/gsd/guided-flow.js +51 -5
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -19
- package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
- package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
- package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
- 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/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
- package/dist/resources/extensions/gsd/paths.js +37 -24
- package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
- package/dist/resources/extensions/gsd/preferences-models.js +14 -48
- package/dist/resources/extensions/gsd/preferences.js +14 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.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/run-uat.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +5 -2
- package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
- package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
- package/dist/resources/extensions/gsd/publication.js +87 -0
- package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- 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/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +1 -20
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
- package/dist/resources/extensions/gsd/tools/exec-tool.js +10 -8
- package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
- 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/uat-policy.js +2 -1
- package/dist/resources/extensions/gsd/undo.js +8 -7
- package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +74 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
- package/dist/resources/extensions/gsd/unit-registry.js +337 -0
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
- package/dist/resources/extensions/gsd/web-app-uat.js +45 -8
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
- package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -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 +28 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
- package/dist/resources/extensions/search-the-web/native-search.js +5 -3
- package/dist/resources/extensions/shared/browser-contract.js +59 -0
- package/dist/resources/extensions/shared/gsd-browser-cli.js +96 -5
- package/dist/resources/shared/package.json +3 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +1 -1
- package/dist/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/dist/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/dist/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +9 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- 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 +1 -1
- 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/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/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 +10 -10
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- 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/{796.cf859a427a2cb2ac.js → 796.e0bdc932325d7e03.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-fbea77b5f9953368.js → webpack-f0285ce91d4ec9ef.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/container.js +18 -26
- package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +14 -47
- 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 +29 -54
- package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +37 -47
- package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +9 -26
- package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +55 -57
- package/dist/web/standalone/node_modules/postcss/lib/node.js +31 -99
- package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
- package/dist/web/standalone/node_modules/postcss/lib/parser.js +9 -10
- package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
- package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +11 -30
- 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 +28 -69
- package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +2 -6
- package/dist/web/standalone/node_modules/postcss/package.json +48 -48
- package/dist/web/standalone/package.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -11
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +4 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +5 -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 +8 -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 +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +8 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +11 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +4 -4
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/cli.js +6 -3
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +46 -21
- 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/dist/harness/env/nodejs.d.ts +1 -0
- package/packages/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/env/nodejs.js +34 -3
- package/packages/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +3 -0
- package/packages/pi-agent-core/dist/index.js.map +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 +478 -484
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +500 -533
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +19 -13
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +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/dist/core/provider-readiness.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/provider-readiness.js +13 -6
- package/packages/pi-coding-agent/dist/core/provider-readiness.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +53 -11
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.d.ts +28 -2
- package/packages/pi-coding-agent/dist/utils/shell.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/shell.js +56 -10
- package/packages/pi-coding-agent/dist/utils/shell.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.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/async-jobs/async-bash-cancel.test.ts +360 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +33 -56
- package/src/resources/extensions/async-jobs/await-tool.test.ts +139 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +82 -12
- package/src/resources/extensions/async-jobs/index.ts +79 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +21 -1
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +6 -6
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +10 -6
- package/src/resources/extensions/bg-shell/overlay.ts +9 -5
- package/src/resources/extensions/bg-shell/process-manager.ts +50 -25
- package/src/resources/extensions/bg-shell/readiness-detector.ts +12 -0
- package/src/resources/extensions/bg-shell/tests/lifecycle-and-utilities.test.ts +48 -1
- package/src/resources/extensions/bg-shell/utilities.ts +5 -2
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +265 -98
- package/src/resources/extensions/browser-tools/engine/selection.ts +90 -4
- package/src/resources/extensions/browser-tools/index.ts +71 -13
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +83 -13
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +29 -1
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +136 -0
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +40 -4
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +46 -10
- package/src/resources/extensions/gsd/auto/phases.ts +10 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +12 -0
- package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +40 -26
- package/src/resources/extensions/gsd/auto-start.ts +21 -22
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
- package/src/resources/extensions/gsd/auto.ts +20 -24
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +33 -12
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +180 -15
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +29 -3
- package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
- package/src/resources/extensions/gsd/browser-daemon-auto-prep.ts +108 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +18 -2
- package/src/resources/extensions/gsd/captures.ts +5 -16
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- package/src/resources/extensions/gsd/constants.ts +0 -3
- package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
- 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/doctor-environment.ts +5 -13
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
- package/src/resources/extensions/gsd/error-classifier.ts +11 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
- 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 +173 -2373
- package/src/resources/extensions/gsd/guidance.ts +139 -0
- package/src/resources/extensions/gsd/guided-flow.ts +50 -5
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -23
- package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
- package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
- package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
- 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/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
- package/src/resources/extensions/gsd/paths.ts +42 -22
- package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
- package/src/resources/extensions/gsd/preferences-models.ts +12 -47
- package/src/resources/extensions/gsd/preferences.ts +18 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.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/run-uat.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +5 -2
- package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
- package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
- package/src/resources/extensions/gsd/publication.ts +122 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- 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/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +4 -21
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +16 -19
- 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-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/browser-automation-contract-fixture.ts +39 -0
- package/src/resources/extensions/gsd/tests/browser-contract.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/browser-daemon-auto-prep.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dynamic-bash-no-cap.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/exec-tool.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +35 -1
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +58 -15
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +74 -59
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/oauth-api-model-routing.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/publication.test.ts +120 -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 +248 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -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 +43 -6
- 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/stop-notice.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +24 -29
- package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +67 -2
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- 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/write-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
- package/src/resources/extensions/gsd/tools/exec-tool.ts +9 -8
- package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
- 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/uat-policy.ts +2 -1
- package/src/resources/extensions/gsd/undo.ts +9 -8
- package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +111 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
- package/src/resources/extensions/gsd/unit-registry.ts +412 -0
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
- package/src/resources/extensions/gsd/web-app-uat.ts +51 -8
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
- package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
- 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 +29 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
- package/src/resources/extensions/search-the-web/native-search.ts +5 -3
- package/src/resources/extensions/shared/browser-contract.ts +66 -0
- package/src/resources/extensions/shared/gsd-browser-cli.ts +119 -5
- package/src/resources/shared/package.json +3 -0
- package/src/resources/skills/create-skill/references/executable-code.md +1 -1
- package/src/resources/skills/create-skill/workflows/add-reference.md +8 -3
- package/src/resources/skills/create-skill/workflows/add-script.md +4 -2
- package/src/resources/skills/create-skill/workflows/add-template.md +3 -1
- package/src/resources/skills/create-skill/workflows/add-workflow.md +8 -3
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +10 -5
- package/src/resources/skills/create-skill/workflows/verify-skill.md +9 -4
- package/src/resources/skills/gsd-browser/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +9 -9
- /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → mU4QIDlpVHDdjDpeEKh5W}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{3PtrU9qGPEXwNLWkIyiqk → mU4QIDlpVHDdjDpeEKh5W}/_ssgManifest.js +0 -0
|
@@ -13,6 +13,7 @@ import { registerHooks } from "./register-hooks.js";
|
|
|
13
13
|
import { registerShortcuts } from "./register-shortcuts.js";
|
|
14
14
|
import { writeCrashLog } from "./crash-log.js";
|
|
15
15
|
import { logWarning } from "../workflow-logger.js";
|
|
16
|
+
import { UNIT_TOOL_CONTRACTS } from "../unit-tool-contracts.js";
|
|
16
17
|
// Static import so cmux event listeners are registered synchronously during
|
|
17
18
|
// extension bootstrap. Prior implementation used `void import().then()` which
|
|
18
19
|
// queued listener registration as a microtask — any CMUX_CHANNELS emit fired
|
|
@@ -30,6 +31,9 @@ const EPIPE_STORM_THRESHOLD = 100;
|
|
|
30
31
|
const EPIPE_STORM_WINDOW_MS = 10_000;
|
|
31
32
|
let epipeCount = 0;
|
|
32
33
|
let epipeWindowStart = 0;
|
|
34
|
+
export const CRITICAL_GSD_WORKFLOW_TOOL_NAMES = [...new Set(Object.values(UNIT_TOOL_CONTRACTS)
|
|
35
|
+
.flatMap((contract) => contract.requiredWorkflowTools)
|
|
36
|
+
.filter((toolName) => toolName.startsWith("gsd_")))].sort();
|
|
33
37
|
/** Write to stderr without ever re-throwing — stderr can EPIPE too, which would
|
|
34
38
|
* re-enter this handler and re-loop. */
|
|
35
39
|
function safeStderr(msg) {
|
|
@@ -121,6 +125,20 @@ export function installEpipeGuard() {
|
|
|
121
125
|
process.on("unhandledRejection", _gsdRejectionGuard);
|
|
122
126
|
}
|
|
123
127
|
}
|
|
128
|
+
function assertCriticalGsdWorkflowToolsRegistered(pi) {
|
|
129
|
+
if (typeof pi.getAllTools !== "function")
|
|
130
|
+
return;
|
|
131
|
+
const registered = new Set(pi.getAllTools().map((tool) => tool.name));
|
|
132
|
+
const missing = CRITICAL_GSD_WORKFLOW_TOOL_NAMES.filter((toolName) => !registered.has(toolName));
|
|
133
|
+
if (missing.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
const message = [
|
|
136
|
+
`Critical GSD workflow tool registration failed; missing required tool(s): ${missing.join(", ")}.`,
|
|
137
|
+
"Check earlier bootstrap warnings for the registration slot that failed.",
|
|
138
|
+
].join(" ");
|
|
139
|
+
logWarning("bootstrap", message);
|
|
140
|
+
throw new Error(message);
|
|
141
|
+
}
|
|
124
142
|
export function registerGsdExtension(pi) {
|
|
125
143
|
// Note: registerGSDCommand is called by index.ts before this function,
|
|
126
144
|
// so we intentionally skip it here to avoid double-registration.
|
|
@@ -186,4 +204,5 @@ export function registerGsdExtension(pi) {
|
|
|
186
204
|
logWarning("bootstrap", `Failed to register ${name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
187
205
|
}
|
|
188
206
|
}
|
|
207
|
+
assertCriticalGsdWorkflowToolsRegistered(pi);
|
|
189
208
|
}
|
|
@@ -7,7 +7,7 @@ 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 { applyAskUserQuestionsGateResult, canonicalToolName, clearDiscussionFlowState, formatPendingAskUserQuestionsGateMessage, isMilestoneDepthVerified, isQueuePhaseActive, markApprovalGateVerified, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
|
|
10
|
+
import { applyAskUserQuestionsGateResult, canonicalToolName, clearDiscussionFlowState, formatPendingAskUserQuestionsGateMessage, isApprovalGateVerifiedInSnapshot, isDepthConfirmationAnswer, isMilestoneDepthVerified, isMilestoneDepthVerifiedInSnapshot, isQueuePhaseActive, 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";
|
|
@@ -19,7 +19,9 @@ import { saveActivityLog } from "../activity-log.js";
|
|
|
19
19
|
import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
|
|
20
20
|
import { parseUnitId } from "../unit-id.js";
|
|
21
21
|
import { classifyCommand } from "../safety/destructive-guard.js";
|
|
22
|
+
import { confirmDestructiveCommand, consumeDestructiveConfirmation, isDestructiveConfirmGateId, requestDestructiveConfirmation, } from "../safety/destructive-confirmation.js";
|
|
22
23
|
import { logWarning as safetyLogWarning } from "../workflow-logger.js";
|
|
24
|
+
import { isUnitCloseoutTool, runInteractiveUnitCloseout } from "../unit-closeout.js";
|
|
23
25
|
import { installNotifyInterceptor } from "./notify-interceptor.js";
|
|
24
26
|
import { initNotificationStore } from "../notification-store.js";
|
|
25
27
|
import { initNotificationWidget } from "../notification-widget.js";
|
|
@@ -31,10 +33,14 @@ import { applyUnitSkillVisibility, unitHasSkillManifest } from "../skill-scope.j
|
|
|
31
33
|
import { getGuidedUnitContext } from "../guided-unit-context.js";
|
|
32
34
|
import { registerPlanMilestoneSchemaRecovery } from "./plan-milestone-schema-recovery.js";
|
|
33
35
|
import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, canonicalWorkflowToolName, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
|
|
36
|
+
import { hasBrowserContractPrefix } from "../../shared/browser-contract.js";
|
|
34
37
|
import { filterToolsForProvider } from "../model-router.js";
|
|
35
38
|
import { mcpToolMatchesBaseName } from "../mcp-tool-name.js";
|
|
36
39
|
import { RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES } from "../tool-presentation-plan.js";
|
|
37
40
|
import { supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
41
|
+
import { clearPendingAutoStart } from "../pending-auto-start.js";
|
|
42
|
+
import { resolveWorkflowToolBasePath } from "./dynamic-tools.js";
|
|
43
|
+
import { getRequiredWorkflowToolsForUnit } from "../unit-tool-contracts.js";
|
|
38
44
|
let approvalQuestionAbortInFlight = false;
|
|
39
45
|
async function loadWelcomeScreenModule() {
|
|
40
46
|
const candidates = [];
|
|
@@ -137,7 +143,7 @@ function withPreservedShimTools(toolNames) {
|
|
|
137
143
|
}
|
|
138
144
|
/** True for the browser automation tools (browser_navigate, browser_click, ...). */
|
|
139
145
|
function isBrowserTool(toolName) {
|
|
140
|
-
return canonicalToolName(toolName)
|
|
146
|
+
return hasBrowserContractPrefix(canonicalToolName(toolName));
|
|
141
147
|
}
|
|
142
148
|
/**
|
|
143
149
|
* True when any message in the request is driven by a GSD workflow command
|
|
@@ -199,7 +205,7 @@ export function buildMinimalGsdToolSet(activeToolNames) {
|
|
|
199
205
|
const minimal = resolveScopedToolNames(activeToolNames, MINIMAL_GSD_TOOL_NAMES);
|
|
200
206
|
return withPreservedShimTools([...new Set([...preserved, ...minimal])]);
|
|
201
207
|
}
|
|
202
|
-
export function buildMinimalAutoGsdToolSet(activeToolNames, unitType, registeredToolNames = activeToolNames) {
|
|
208
|
+
export function buildMinimalAutoGsdToolSet(activeToolNames, unitType, registeredToolNames = activeToolNames, warnOnUnresolvedRequiredTools = registeredToolNames !== activeToolNames) {
|
|
203
209
|
if (unitType === "run-uat") {
|
|
204
210
|
return buildRunUatGsdToolSet(activeToolNames, registeredToolNames);
|
|
205
211
|
}
|
|
@@ -211,7 +217,20 @@ export function buildMinimalAutoGsdToolSet(activeToolNames, unitType, registered
|
|
|
211
217
|
...availableBaseTools,
|
|
212
218
|
])];
|
|
213
219
|
const scoped = resolveScopedToolNames([...activeToolNames, ...registeredToolNames], [...MINIMAL_GSD_TOOL_NAMES, ...unitTools]);
|
|
214
|
-
|
|
220
|
+
const result = withPreservedShimTools([...new Set([...preserved, ...scoped])]);
|
|
221
|
+
warnIfRequiredWorkflowToolsUnresolved(unitType, result, warnOnUnresolvedRequiredTools);
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
function hasResolvedWorkflowTool(resolvedToolNames, requiredToolName) {
|
|
225
|
+
return resolvedToolNames.some((name) => name === requiredToolName || mcpToolMatchesBaseName(name, requiredToolName));
|
|
226
|
+
}
|
|
227
|
+
function warnIfRequiredWorkflowToolsUnresolved(unitType, scopedToolNames, shouldWarn) {
|
|
228
|
+
if (!unitType || !shouldWarn)
|
|
229
|
+
return;
|
|
230
|
+
const unresolved = getRequiredWorkflowToolsForUnit(unitType).filter((toolName) => !hasResolvedWorkflowTool(scopedToolNames, toolName));
|
|
231
|
+
if (unresolved.length === 0)
|
|
232
|
+
return;
|
|
233
|
+
safetyLogWarning("bootstrap", `buildMinimalAutoGsdToolSet(${unitType}): required workflow tool(s) not in active/registered surface after scoping: ${unresolved.join(", ")}. Tool registration may have partially failed, provider filtering may have removed a required tool, or workflow MCP may be disconnected.`);
|
|
215
234
|
}
|
|
216
235
|
export function buildRunUatGsdToolSet(activeToolNames, registeredToolNames = activeToolNames) {
|
|
217
236
|
const scoped = resolveScopedToolNames([...activeToolNames, ...registeredToolNames], [
|
|
@@ -237,7 +256,7 @@ export function buildMinimalGsdWorkflowToolSet(activeToolNames, registeredToolNa
|
|
|
237
256
|
const scoped = resolveScopedToolNames([...activeToolNames, ...registeredToolNames], WORKFLOW_GSD_TOOL_NAMES);
|
|
238
257
|
return withPreservedShimTools([...new Set([...preserved, ...scoped])]);
|
|
239
258
|
}
|
|
240
|
-
export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessages, registeredToolNames = activeToolNames, guidedUnitType) {
|
|
259
|
+
export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessages, registeredToolNames = activeToolNames, guidedUnitType, warnOnUnresolvedRequiredTools = registeredToolNames !== activeToolNames) {
|
|
241
260
|
for (let index = (requestCustomMessages?.length ?? 0) - 1; index >= 0; index--) {
|
|
242
261
|
const currentCustomType = requestCustomMessages?.[index]?.customType;
|
|
243
262
|
if (currentCustomType === "gsd-run" ||
|
|
@@ -245,7 +264,7 @@ export function buildRequestScopedGsdToolSet(activeToolNames, requestCustomMessa
|
|
|
245
264
|
currentCustomType === "gsd-doctor-heal" ||
|
|
246
265
|
currentCustomType === "gsd-triage") {
|
|
247
266
|
if (guidedUnitType) {
|
|
248
|
-
return buildMinimalAutoGsdToolSet(activeToolNames, guidedUnitType, registeredToolNames);
|
|
267
|
+
return buildMinimalAutoGsdToolSet(activeToolNames, guidedUnitType, registeredToolNames, warnOnUnresolvedRequiredTools);
|
|
249
268
|
}
|
|
250
269
|
return buildMinimalGsdWorkflowToolSet(activeToolNames, registeredToolNames);
|
|
251
270
|
}
|
|
@@ -279,8 +298,9 @@ function applyMinimalGsdToolSurface(pi) {
|
|
|
279
298
|
const dash = getAutoRuntimeSnapshot();
|
|
280
299
|
if (dash.active && dash.currentUnit) {
|
|
281
300
|
const currentToolNames = pi.getActiveTools();
|
|
301
|
+
const hasRegisteredSurface = typeof pi.getAllTools === "function";
|
|
282
302
|
const registeredToolNames = resolveRegisteredToolNames(pi, currentToolNames);
|
|
283
|
-
const scopedToolNames = buildMinimalAutoGsdToolSet(currentToolNames, dash.currentUnit.type, registeredToolNames);
|
|
303
|
+
const scopedToolNames = buildMinimalAutoGsdToolSet(currentToolNames, dash.currentUnit.type, registeredToolNames, hasRegisteredSurface);
|
|
284
304
|
recordAutoToolSurfaceSnapshot({
|
|
285
305
|
source: "runtime-scope",
|
|
286
306
|
unitType: dash.currentUnit.type,
|
|
@@ -299,9 +319,10 @@ export function scopeGsdWorkflowToolsForDispatch(pi, unitType) {
|
|
|
299
319
|
if (isFullGsdToolSurfaceRequested())
|
|
300
320
|
return null;
|
|
301
321
|
const current = pi.getActiveTools();
|
|
322
|
+
const hasRegisteredSurface = typeof pi.getAllTools === "function";
|
|
302
323
|
const registeredToolNames = resolveRegisteredToolNames(pi, current);
|
|
303
324
|
const scoped = unitType
|
|
304
|
-
? buildMinimalAutoGsdToolSet(current, unitType, registeredToolNames)
|
|
325
|
+
? buildMinimalAutoGsdToolSet(current, unitType, registeredToolNames, hasRegisteredSurface)
|
|
305
326
|
: buildMinimalGsdWorkflowToolSet(current, registeredToolNames);
|
|
306
327
|
recordAutoToolSurfaceSnapshot({
|
|
307
328
|
source: "dispatch-scope",
|
|
@@ -444,8 +465,15 @@ function isShellExecutionTool(canonicalName) {
|
|
|
444
465
|
function activateDeferredApprovalGate(basePath) {
|
|
445
466
|
if (deferredApprovalGate?.basePath !== basePath)
|
|
446
467
|
return;
|
|
447
|
-
|
|
468
|
+
const gateId = deferredApprovalGate.gateId;
|
|
448
469
|
deferredApprovalGate = null;
|
|
470
|
+
const snapshot = refreshWriteGateStateFromDisk(basePath);
|
|
471
|
+
const milestoneId = extractDepthVerificationMilestoneId(gateId);
|
|
472
|
+
if (isApprovalGateVerifiedInSnapshot(snapshot, gateId))
|
|
473
|
+
return;
|
|
474
|
+
if (milestoneId && isMilestoneDepthVerifiedInSnapshot(snapshot, milestoneId))
|
|
475
|
+
return;
|
|
476
|
+
setPendingGate(gateId, basePath);
|
|
449
477
|
}
|
|
450
478
|
function extractGateQuestionId(input) {
|
|
451
479
|
const questions = input?.questions ?? [];
|
|
@@ -463,6 +491,25 @@ function isContextDraftSummarySave(toolName, input) {
|
|
|
463
491
|
return false;
|
|
464
492
|
return input.artifact_type === "CONTEXT-DRAFT";
|
|
465
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* External engines (claude-code-cli) deliver ask_user_questions results as
|
|
496
|
+
* relayed MCP tool results: the structured round payload arrives in
|
|
497
|
+
* `result.structuredContent`, not in pi-native `event.details`. Without this
|
|
498
|
+
* fallback, applyAskUserQuestionsGateResult sees no response for an answered
|
|
499
|
+
* gate question and lands in the "waiting" branch — leaving a re-armed gate
|
|
500
|
+
* permanently pending and the discuss→auto handoff blocked.
|
|
501
|
+
*/
|
|
502
|
+
function resolveAskUserQuestionsGateDetails(event) {
|
|
503
|
+
const hasRoundShape = (value) => !!value && typeof value === "object" &&
|
|
504
|
+
(value.cancelled !== undefined || value.response !== undefined);
|
|
505
|
+
const details = event.details;
|
|
506
|
+
if (hasRoundShape(details))
|
|
507
|
+
return details;
|
|
508
|
+
const structured = event.result?.structuredContent;
|
|
509
|
+
if (hasRoundShape(structured))
|
|
510
|
+
return structured;
|
|
511
|
+
return details ?? {};
|
|
512
|
+
}
|
|
466
513
|
function selectedAnswerLabel(selected) {
|
|
467
514
|
if (Array.isArray(selected))
|
|
468
515
|
return selected.map(String).join(", ");
|
|
@@ -626,7 +673,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
626
673
|
catch { /* non-fatal */ }
|
|
627
674
|
}
|
|
628
675
|
});
|
|
629
|
-
pi.on("session_switch", async (
|
|
676
|
+
pi.on("session_switch", async (event, ctx) => {
|
|
630
677
|
const basePath = contextBasePath(ctx);
|
|
631
678
|
const preserveCloseoutSurface = isAutoCompletionStopInProgress();
|
|
632
679
|
initSessionNotifications(ctx);
|
|
@@ -635,6 +682,13 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
635
682
|
clearDeferredApprovalGate();
|
|
636
683
|
await resetAskUserQuestionsTurnCache();
|
|
637
684
|
clearDiscussionFlowState(basePath);
|
|
685
|
+
// /clear or /new destroys the conversation holding a discuss interview, so
|
|
686
|
+
// its pending discuss→auto handoff can never be answered — clear it. Resume
|
|
687
|
+
// restores the interview transcript, so the entry survives. Auto-mode's own
|
|
688
|
+
// newSession() calls are safe: the handoff consumes the entry on agent_end.
|
|
689
|
+
if (event.reason === "new") {
|
|
690
|
+
clearPendingAutoStart(basePath);
|
|
691
|
+
}
|
|
638
692
|
await syncServiceTierStatus(ctx);
|
|
639
693
|
await applyDisabledModelProviderPolicy(ctx);
|
|
640
694
|
await applyCompactionThresholdOverride(ctx);
|
|
@@ -1056,19 +1110,35 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1056
1110
|
}
|
|
1057
1111
|
// Destructive command classification + hard gate in all modes.
|
|
1058
1112
|
if (isToolCallEventType("bash", event)) {
|
|
1059
|
-
const
|
|
1113
|
+
const command = event.input.command;
|
|
1114
|
+
const classification = classifyCommand(command);
|
|
1060
1115
|
if (classification.destructive) {
|
|
1116
|
+
const guardBasePath = contextBasePath(ctx);
|
|
1117
|
+
// Escape hatch: if the user already confirmed this exact command via a
|
|
1118
|
+
// destructive_confirm gate, consume the one-shot token and let it run.
|
|
1119
|
+
// Without this, the block below loops forever — the model cannot satisfy
|
|
1120
|
+
// "confirm in the current turn" because nothing ever clears the gate.
|
|
1121
|
+
if (consumeDestructiveConfirmation(command, guardBasePath)) {
|
|
1122
|
+
safetyLogWarning("safety", `destructive command confirmed: ${classification.labels.join(", ")}`, {
|
|
1123
|
+
command: String(command).slice(0, 200),
|
|
1124
|
+
});
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
// Record the command as pending so an affirmative answer to a
|
|
1128
|
+
// destructive_confirm gate (handled in tool_result) can confirm it.
|
|
1129
|
+
requestDestructiveConfirmation(command, guardBasePath);
|
|
1061
1130
|
const reason = [
|
|
1062
1131
|
"HARD BLOCK: destructive Bash command requires explicit human confirmation.",
|
|
1063
1132
|
`Detected: ${classification.labels.join(", ")}`,
|
|
1064
|
-
"
|
|
1065
|
-
"
|
|
1133
|
+
"Call ask_user_questions with a question id containing \"destructive_confirm\"",
|
|
1134
|
+
"and a first option that affirms the action; wait for the user's response,",
|
|
1135
|
+
"then re-issue this exact command in the same turn to run it once.",
|
|
1066
1136
|
].join(" ");
|
|
1067
1137
|
safetyLogWarning("safety", `destructive command: ${classification.labels.join(", ")}`, {
|
|
1068
|
-
command: String(
|
|
1138
|
+
command: String(command).slice(0, 200),
|
|
1069
1139
|
});
|
|
1070
1140
|
if (ctx) {
|
|
1071
|
-
await maybePauseAutoForApprovalGate(ctx, pi, isAutoActive(), "
|
|
1141
|
+
await maybePauseAutoForApprovalGate(ctx, pi, isAutoActive(), "Destructive-command confirmation is waiting for your answer — pausing auto-mode.");
|
|
1072
1142
|
}
|
|
1073
1143
|
return { block: true, reason };
|
|
1074
1144
|
}
|
|
@@ -1105,12 +1175,27 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1105
1175
|
else if (isAutoActive()) {
|
|
1106
1176
|
clearToolInvocationError();
|
|
1107
1177
|
}
|
|
1178
|
+
// Interactive Closeout adapter (ADR-032): auto-mode owns closeout for its
|
|
1179
|
+
// own units; interactive completions get the durable git subset (commit +
|
|
1180
|
+
// Closeout Git Verdict) instead of silently bypassing git.isolation.
|
|
1181
|
+
if (!event.isError && !isAutoActive() && isUnitCloseoutTool(toolName)) {
|
|
1182
|
+
try {
|
|
1183
|
+
runInteractiveUnitCloseout({
|
|
1184
|
+
basePath: resolveWorkflowToolBasePath(ctx, event.input),
|
|
1185
|
+
canonicalToolName: toolName,
|
|
1186
|
+
input: event.input,
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
catch (err) {
|
|
1190
|
+
safetyLogWarning("engine", `interactive unit closeout failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1108
1193
|
if (toolName !== "ask_user_questions")
|
|
1109
1194
|
return;
|
|
1110
1195
|
const basePath = contextBasePath(ctx);
|
|
1111
1196
|
const milestoneId = await getDiscussionMilestoneIdFor(basePath);
|
|
1112
|
-
const details = event
|
|
1113
|
-
const questions = event.input?.questions ?? [];
|
|
1197
|
+
const details = resolveAskUserQuestionsGateDetails(event);
|
|
1198
|
+
const questions = event.input?.questions ?? details?.questions ?? [];
|
|
1114
1199
|
const gateResult = applyAskUserQuestionsGateResult({
|
|
1115
1200
|
basePath,
|
|
1116
1201
|
questions,
|
|
@@ -1136,6 +1221,22 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1136
1221
|
}
|
|
1137
1222
|
if (details?.cancelled || !details?.response)
|
|
1138
1223
|
return;
|
|
1224
|
+
// Destructive-command confirmation: an affirmative answer to a
|
|
1225
|
+
// destructive_confirm gate promotes the pending blocked command to a
|
|
1226
|
+
// one-shot confirmed token, which the bash tool_call guard consumes on the
|
|
1227
|
+
// next attempt. Rejecting/declining leaves the command blocked.
|
|
1228
|
+
// (Depth-verification gate handling now lives in
|
|
1229
|
+
// applyAskUserQuestionsGateResult above; only the destructive-confirm gate
|
|
1230
|
+
// is handled inline here.)
|
|
1231
|
+
for (const question of questions) {
|
|
1232
|
+
if (isDestructiveConfirmGateId(question?.id)) {
|
|
1233
|
+
const answer = details.response?.answers?.[question.id];
|
|
1234
|
+
if (isDepthConfirmationAnswer(answer?.selected, question.options)) {
|
|
1235
|
+
confirmDestructiveCommand(basePath);
|
|
1236
|
+
}
|
|
1237
|
+
break;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1139
1240
|
if (!milestoneId)
|
|
1140
1241
|
return;
|
|
1141
1242
|
await saveDiscussionQuestionRound(basePath, milestoneId, questions, details);
|
|
@@ -1146,10 +1247,39 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1146
1247
|
if (toolName === "ask_user_questions") {
|
|
1147
1248
|
const questionId = extractGateQuestionId(event.args);
|
|
1148
1249
|
if (typeof questionId === "string") {
|
|
1149
|
-
|
|
1250
|
+
// External engines (claude-code-cli) ingest the SDK turn's tool blocks
|
|
1251
|
+
// post-hoc, so this event can fire AFTER the workflow MCP child already
|
|
1252
|
+
// verified this gate and allowed the CONTEXT save. setPendingGate also
|
|
1253
|
+
// revokes verifiedDepthMilestones/verifiedApprovalGates, so an
|
|
1254
|
+
// unconditional re-arm here wipes the child's verification and leaves
|
|
1255
|
+
// the discuss→auto handoff permanently blocked. Skip the re-arm when
|
|
1256
|
+
// the snapshot already records this exact gate as verified — mirrors
|
|
1257
|
+
// activateDeferredApprovalGate's guard. Stale verified state cannot
|
|
1258
|
+
// leak into a later re-discussion: a successful handoff deletes the
|
|
1259
|
+
// snapshot via clearDiscussionFlowState.
|
|
1260
|
+
const snapshot = refreshWriteGateStateFromDisk(basePath);
|
|
1261
|
+
const gateMilestoneId = extractDepthVerificationMilestoneId(questionId);
|
|
1262
|
+
const alreadyVerified = isApprovalGateVerifiedInSnapshot(snapshot, questionId) ||
|
|
1263
|
+
isMilestoneDepthVerifiedInSnapshot(snapshot, gateMilestoneId);
|
|
1264
|
+
if (!alreadyVerified) {
|
|
1265
|
+
setPendingGate(questionId, basePath);
|
|
1266
|
+
}
|
|
1150
1267
|
clearDeferredApprovalGate(basePath);
|
|
1151
1268
|
}
|
|
1152
1269
|
}
|
|
1270
|
+
// Safety harness: record evidence here, not only in tool_call. External
|
|
1271
|
+
// engines (claude-code-cli) pre-execute tools, so the agent loop skips
|
|
1272
|
+
// beforeToolCall/tool_call for them — tool_execution_start is the only
|
|
1273
|
+
// event that fires for every tool call. recordToolCall dedupes by
|
|
1274
|
+
// toolCallId, so native tools (which hit both events) record once.
|
|
1275
|
+
safetyRecordToolCall(event.toolCallId, event.toolName, (event.args ?? {}));
|
|
1276
|
+
const execDash = getAutoRuntimeSnapshot();
|
|
1277
|
+
if (execDash.basePath && execDash.currentUnit?.type === "execute-task") {
|
|
1278
|
+
const { milestone: xMid, slice: xSid, task: xTid } = parseUnitId(execDash.currentUnit.id);
|
|
1279
|
+
if (xMid && xSid && xTid) {
|
|
1280
|
+
saveEvidenceToDisk(execDash.basePath, xMid, xSid, xTid);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1153
1283
|
if (!isAutoActive())
|
|
1154
1284
|
return;
|
|
1155
1285
|
markToolStart(event.toolCallId, event.toolName);
|
|
@@ -1223,12 +1353,13 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1223
1353
|
return surfaceReduced ? { toolNames: providerCompatible } : undefined;
|
|
1224
1354
|
}
|
|
1225
1355
|
const registeredToolNames = resolveRegisteredToolNames(pi, event.activeToolNames);
|
|
1356
|
+
const hasRegisteredSurface = typeof pi.getAllTools === "function";
|
|
1226
1357
|
const compatibleRegisteredToolNames = filterToolsForProvider(registeredToolNames, event.selectedModelApi, event.selectedModelProvider).compatible.filter((name) => !(dropAliases && isWorkflowAliasTool(name)));
|
|
1227
1358
|
const guidedUnit = getGuidedUnitContext();
|
|
1228
1359
|
const requestRegisteredToolNames = guidedUnit?.unitType === "run-uat"
|
|
1229
1360
|
? compatibleRegisteredToolNames
|
|
1230
1361
|
: registeredToolNames;
|
|
1231
|
-
const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, requestRegisteredToolNames, guidedUnit?.unitType);
|
|
1362
|
+
const requestScoped = buildRequestScopedGsdToolSet(guidedUnit?.unitType === "run-uat" ? aliasFilteredCompatible : providerCompatible, event.requestCustomMessages, requestRegisteredToolNames, guidedUnit?.unitType, hasRegisteredSurface);
|
|
1232
1363
|
if (requestScoped) {
|
|
1233
1364
|
recordAutoToolSurfaceSnapshot({
|
|
1234
1365
|
source: "provider-adjustment",
|
|
@@ -1244,7 +1375,7 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1244
1375
|
const registeredForUnit = dash.currentUnit.type === "run-uat"
|
|
1245
1376
|
? compatibleRegisteredToolNames
|
|
1246
1377
|
: resolveRegisteredToolNames(pi, event.activeToolNames);
|
|
1247
|
-
const scopedToolNames = buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, registeredForUnit);
|
|
1378
|
+
const scopedToolNames = buildMinimalAutoGsdToolSet(dash.currentUnit.type === "run-uat" ? aliasFilteredCompatible : providerCompatible, dash.currentUnit.type, registeredForUnit, hasRegisteredSurface);
|
|
1248
1379
|
recordAutoToolSurfaceSnapshot({
|
|
1249
1380
|
source: "provider-adjustment",
|
|
1250
1381
|
unitType: dash.currentUnit.type,
|
|
@@ -8,6 +8,7 @@ import { getIsolationMode } from "../preferences.js";
|
|
|
8
8
|
import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
|
|
9
9
|
import { logWarning } from "../workflow-logger.js";
|
|
10
10
|
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
11
|
+
import { worktreesDirs } from "../worktree-placement.js";
|
|
11
12
|
/**
|
|
12
13
|
* Regex matching milestone CONTEXT.md file names in both legacy M001
|
|
13
14
|
* and unique M001-abc123 formats. Exported so regex-hardening tests
|
|
@@ -214,6 +215,27 @@ export function loadWriteGateSnapshot(basePath) {
|
|
|
214
215
|
return currentWriteGateSnapshot(basePath);
|
|
215
216
|
}
|
|
216
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
|
+
* Returns the snapshot used for the refresh so callers that need to inspect
|
|
226
|
+
* it (e.g. re-arm guards) avoid a second disk read.
|
|
227
|
+
*/
|
|
228
|
+
export function refreshWriteGateStateFromDisk(basePath) {
|
|
229
|
+
const snapshot = loadWriteGateSnapshot(basePath);
|
|
230
|
+
if (!shouldPersistWriteGateSnapshot())
|
|
231
|
+
return snapshot;
|
|
232
|
+
const state = getWriteGateState(basePath);
|
|
233
|
+
state.pendingGateId = snapshot.pendingGateId;
|
|
234
|
+
state.activeQueuePhase = snapshot.activeQueuePhase;
|
|
235
|
+
state.verifiedDepthMilestones = new Set(snapshot.verifiedDepthMilestones);
|
|
236
|
+
state.verifiedApprovalGates = new Set(snapshot.verifiedApprovalGates ?? []);
|
|
237
|
+
return snapshot;
|
|
238
|
+
}
|
|
217
239
|
export function isDepthVerified(basePath = process.cwd()) {
|
|
218
240
|
return getWriteGateState(basePath).verifiedDepthMilestones.size > 0;
|
|
219
241
|
}
|
|
@@ -223,6 +245,7 @@ export function isDepthVerified(basePath = process.cwd()) {
|
|
|
223
245
|
export function isMilestoneDepthVerified(milestoneId, basePath = process.cwd()) {
|
|
224
246
|
if (!milestoneId)
|
|
225
247
|
return false;
|
|
248
|
+
refreshWriteGateStateFromDisk(basePath);
|
|
226
249
|
return getWriteGateState(basePath).verifiedDepthMilestones.has(milestoneId);
|
|
227
250
|
}
|
|
228
251
|
export function isMilestoneDepthVerifiedInSnapshot(snapshot, milestoneId) {
|
|
@@ -309,6 +332,7 @@ export function clearPendingGate(basePath) {
|
|
|
309
332
|
* Get the currently pending gate, if any.
|
|
310
333
|
*/
|
|
311
334
|
export function getPendingGate(basePath = process.cwd()) {
|
|
335
|
+
refreshWriteGateStateFromDisk(basePath);
|
|
312
336
|
return getWriteGateState(basePath).pendingGateId;
|
|
313
337
|
}
|
|
314
338
|
/**
|
|
@@ -919,10 +943,12 @@ export function shouldBlockWorktreeWrite(toolName, targetPath, effectiveBasePath
|
|
|
919
943
|
const realTarget = realpathOrResolve(absTarget);
|
|
920
944
|
const realRoot = realpathOrResolve(projectRoot);
|
|
921
945
|
const realGsd = realpathOrResolve(join(projectRoot, ".gsd"));
|
|
922
|
-
|
|
923
|
-
//
|
|
924
|
-
|
|
925
|
-
|
|
946
|
+
// Allow writes inside a legitimate worktrees subtree (canonical
|
|
947
|
+
// .gsd-worktrees/ or legacy .gsd/worktrees/).
|
|
948
|
+
for (const container of worktreesDirs(projectRoot)) {
|
|
949
|
+
if (isPathContained(realTarget, realpathOrResolve(container)))
|
|
950
|
+
return { block: false };
|
|
951
|
+
}
|
|
926
952
|
// Allow writes to .gsd/ planning artifacts, but reject siblings whose name
|
|
927
953
|
// starts with "worktrees" (the worktrees-extra prefix trick — case 4).
|
|
928
954
|
if (isPathContained(realTarget, realGsd)) {
|
|
@@ -11,3 +11,5 @@ export const SLICE_BRANCH_RE = /^gsd\/(?:([a-zA-Z0-9_-]+)\/)?(M\d+(?:-[a-z0-9]{6
|
|
|
11
11
|
export const QUICK_BRANCH_RE = /^gsd\/quick\//;
|
|
12
12
|
/** Matches GSD-generated workflow template branches, not arbitrary user gsd/* branches. */
|
|
13
13
|
export const WORKFLOW_BRANCH_RE = /^gsd\/(?:hotfix|bugfix|small-feature|refactor|spike|security-audit|dep-upgrade|full-project)\//;
|
|
14
|
+
/** Auto-mode milestone branch prefix: milestone/<MID>. */
|
|
15
|
+
export const MILESTONE_BRANCH_PREFIX = "milestone/";
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { resolveAmbientBrowserEngineResolution, resolveBrowserEngineResolution, } from "../browser-tools/engine/selection.js";
|
|
4
|
+
import { resolveGsdBrowserCliAvailability, resolveGsdBrowserDaemonStartInvocation, } from "../shared/gsd-browser-cli.js";
|
|
5
|
+
import { uatTypeIncludesBrowser } from "./uat-policy.js";
|
|
6
|
+
const DEFAULT_DAEMON_START_TIMEOUT_MS = 30_000;
|
|
7
|
+
function isEnvDisabled(value) {
|
|
8
|
+
if (!value)
|
|
9
|
+
return false;
|
|
10
|
+
const normalized = value.trim().toLowerCase();
|
|
11
|
+
return normalized === "0" || normalized === "false" || normalized === "off";
|
|
12
|
+
}
|
|
13
|
+
function isWarmUpDisabled(env = process.env) {
|
|
14
|
+
const value = env.GSD_BROWSER_WARMUP?.trim().toLowerCase();
|
|
15
|
+
return value === "0" || value === "false" || value === "off";
|
|
16
|
+
}
|
|
17
|
+
/** Active engine for warm-up: explicit env override, else session-committed ambient resolution. */
|
|
18
|
+
function resolveActiveBrowserEngine(projectRoot, env) {
|
|
19
|
+
if (env.GSD_BROWSER_ENGINE?.trim()) {
|
|
20
|
+
return resolveBrowserEngineResolution(env, projectRoot).engine;
|
|
21
|
+
}
|
|
22
|
+
return resolveAmbientBrowserEngineResolution(projectRoot).engine;
|
|
23
|
+
}
|
|
24
|
+
export function shouldWarmBrowserDaemonForUat(ctx) {
|
|
25
|
+
if (!uatTypeIncludesBrowser(ctx.uatType))
|
|
26
|
+
return false;
|
|
27
|
+
const env = ctx.env ?? process.env;
|
|
28
|
+
if (isWarmUpDisabled(env))
|
|
29
|
+
return false;
|
|
30
|
+
if (isEnvDisabled(env.GSD_BROWSER_MCP_ENABLED))
|
|
31
|
+
return false;
|
|
32
|
+
const availability = resolveGsdBrowserCliAvailability(env);
|
|
33
|
+
if (!availability.available)
|
|
34
|
+
return false;
|
|
35
|
+
const projectRoot = resolve(ctx.projectRoot);
|
|
36
|
+
return resolveActiveBrowserEngine(projectRoot, env) === "gsd-browser";
|
|
37
|
+
}
|
|
38
|
+
export function ensureBrowserDaemonStarted(projectRoot, options = {}) {
|
|
39
|
+
const env = options.env ?? process.env;
|
|
40
|
+
const availability = resolveGsdBrowserCliAvailability(env);
|
|
41
|
+
if (!availability.available) {
|
|
42
|
+
return { ok: false, error: availability.detail };
|
|
43
|
+
}
|
|
44
|
+
let invocation;
|
|
45
|
+
try {
|
|
46
|
+
invocation = resolveGsdBrowserDaemonStartInvocation(projectRoot, env);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
error: error instanceof Error ? error.message : String(error),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
execFileSync(invocation.command, invocation.args, {
|
|
56
|
+
cwd: invocation.cwd,
|
|
57
|
+
env: { ...process.env, ...env, ...(invocation.env ?? {}) },
|
|
58
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
59
|
+
timeout: options.timeoutMs ?? DEFAULT_DAEMON_START_TIMEOUT_MS,
|
|
60
|
+
encoding: "utf-8",
|
|
61
|
+
});
|
|
62
|
+
return { ok: true };
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
error: error instanceof Error ? error.message : String(error),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Best-effort pre-warm of the gsd-browser session daemon before browser-backed
|
|
73
|
+
* run-uat dispatch. Returns an actionable stop reason when warm-up is required
|
|
74
|
+
* but fails; returns null when warm-up is skipped or succeeds.
|
|
75
|
+
*/
|
|
76
|
+
export function prepareBrowserDaemonForUat(ctx) {
|
|
77
|
+
if (!shouldWarmBrowserDaemonForUat(ctx))
|
|
78
|
+
return null;
|
|
79
|
+
const result = ensureBrowserDaemonStarted(ctx.projectRoot, { env: ctx.env });
|
|
80
|
+
if (result.ok)
|
|
81
|
+
return null;
|
|
82
|
+
return `Cannot dispatch browser-backed run-uat: gsd-browser daemon failed to start (${result.error}). Ensure Chrome/Chromium is installed, run \`gsd-browser daemon health\` with the project session flags from .mcp.json, or set GSD_BROWSER_PATH to a Chromium binary.`;
|
|
83
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Shared browser-observable UAT requirement and evidence detection.
|
|
3
|
-
|
|
3
|
+
import { BROWSER_EVIDENCE_SIGNAL_TOOL_NAMES } from "../shared/browser-contract.js";
|
|
4
|
+
// Alternation fragment over the contract's evidence-signal names, e.g.
|
|
5
|
+
// `browser_(?:assert|batch|...)`. The names are `browser_`-prefixed
|
|
6
|
+
// identifiers (pinned by tests/browser-contract.test.ts), so no escaping is
|
|
7
|
+
// needed.
|
|
8
|
+
const BROWSER_TOOL_SIGNAL = `browser_(?:${BROWSER_EVIDENCE_SIGNAL_TOOL_NAMES.map((name) => name.slice("browser_".length)).join("|")})`;
|
|
9
|
+
export const BROWSER_REQUIREMENT_RE = new RegExp(String.raw `\b(?:file://|localhost|playwright|chrome|screenshot|snapshot|${BROWSER_TOOL_SIGNAL})\b|\b(?:open|launch|navigate|load|visit|serve|start)\b.{0,80}\b(?:browser|page|localhost|file://)\b|\bbrowser\s+(?:check|session|test|uat|tool|automation|interaction|flow)\b`, "i");
|
|
4
10
|
export const NO_BROWSER_EVIDENCE_RE = /\b(?:no|without|not|wasn'?t|isn'?t)\s+(?:automated\s+)?(?:live\s+)?browser(?:\s+(?:session|test|uat))?|\bno\s+automated\s+browser\b|\bnot\s+conducted\b/i;
|
|
5
|
-
export const BROWSER_RUNTIME_RE =
|
|
11
|
+
export const BROWSER_RUNTIME_RE = new RegExp(String.raw `\b(?:browser|playwright|chrome|camoufox|${BROWSER_TOOL_SIGNAL}|screenshot|snapshot|file://|localhost)\b`, "i");
|
|
6
12
|
export const BROWSER_ACTION_RE = /\b(?:open(?:ed)?|navigate(?:d)?|click(?:ed)?|type(?:d)?|reload(?:ed)?|capture(?:d)?|screenshot|snapshot)\b/i;
|
|
7
13
|
export const BROWSER_ASSERTION_RE = /\b(?:assert(?:ed|ion)?|observed|confirmed|verified|expected|visible|text|count|label|strikethrough|localstorage|screenshot|snapshot|passed)\b/i;
|
|
8
14
|
const NON_REQUIREMENT_BROWSER_HEADING_RE = /^(?:not\s+proven|not\s+covered|out\s+of\s+scope|deferred|follow-?ups?|known\s+limitations|notes\s+for\s+tester)\b/i;
|
|
@@ -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 { projectRootFromWorktreePath } from "./worktree-root.js";
|
|
14
15
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
15
16
|
const CAPTURES_FILENAME = "CAPTURES.md";
|
|
16
17
|
const VALID_CLASSIFICATIONS = [
|
|
@@ -29,20 +30,9 @@ const VALID_CLASSIFICATIONS = [
|
|
|
29
30
|
* directory that contains `.gsd/worktrees/` — that's the project root.
|
|
30
31
|
*/
|
|
31
32
|
export function resolveCapturesPath(basePath) {
|
|
32
|
-
|
|
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) {
|
|
44
|
-
// basePath is inside a worktree — resolve to project root
|
|
45
|
-
const projectRoot = resolved.slice(0, idx);
|
|
33
|
+
// If basePath is inside a worktree, resolve to the project root.
|
|
34
|
+
const projectRoot = projectRootFromWorktreePath(resolve(basePath));
|
|
35
|
+
if (projectRoot) {
|
|
46
36
|
return join(projectRoot, ".gsd", CAPTURES_FILENAME);
|
|
47
37
|
}
|
|
48
38
|
return join(gsdRoot(basePath), CAPTURES_FILENAME);
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
// File Purpose: Closeout git failure discovery, retry, and manual resolution helpers.
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
import { existsSync, realpathSync } from "node:fs";
|
|
5
|
-
import { isAbsolute,
|
|
5
|
+
import { isAbsolute, resolve } from "node:path";
|
|
6
6
|
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
7
7
|
import { runTurnGitAction } from "./git-service.js";
|
|
8
8
|
import { _getAdapter, upsertTurnGitTransaction } from "./gsd-db.js";
|
|
9
9
|
import { probeGitConflictState } from "./git-conflict-state.js";
|
|
10
10
|
import { parseUnitId } from "./unit-id.js";
|
|
11
|
+
import { worktreePathFor } from "./worktree-placement.js";
|
|
11
12
|
function parseMetadata(value) {
|
|
12
13
|
if (typeof value !== "string" || !value.trim())
|
|
13
14
|
return {};
|
|
@@ -121,7 +122,7 @@ export function resolveCloseoutRecoveryBasePath(projectRoot, record) {
|
|
|
121
122
|
const parsed = parseUnitId(record.unitId);
|
|
122
123
|
const milestoneId = parsed.milestone ?? (/^M\d+(?:-[a-z0-9]{6})?/.exec(record.unitId)?.[0] ?? "");
|
|
123
124
|
if (milestoneId) {
|
|
124
|
-
const worktreePath = existingRealPath(
|
|
125
|
+
const worktreePath = existingRealPath(worktreePathFor(projectRoot, milestoneId));
|
|
125
126
|
if (worktreePath)
|
|
126
127
|
return worktreePath;
|
|
127
128
|
}
|