@opengsd/gsd-pi 1.2.0-dev.955e4da0 → 1.2.0-dev.d6c5343c
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 +14 -34
- 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/GSD-WORKFLOW.md +5 -4
- 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 +3 -0
- 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/stream-adapter.js +30 -4
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
- package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +105 -0
- package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +61 -44
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +8 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +40 -57
- package/dist/resources/extensions/gsd/auto-model-selection.js +25 -6
- package/dist/resources/extensions/gsd/auto-post-unit.js +23 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -19
- package/dist/resources/extensions/gsd/auto-start.js +18 -15
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +12 -20
- package/dist/resources/extensions/gsd/auto-verification.js +9 -28
- package/dist/resources/extensions/gsd/auto-worktree.js +30 -90
- package/dist/resources/extensions/gsd/auto.js +4 -13
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +23 -6
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +19 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +212 -48
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +303 -77
- 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 +4 -6
- package/dist/resources/extensions/gsd/consent-question.js +337 -0
- package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
- 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/queries.js +26 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
- package/dist/resources/extensions/gsd/doctor-environment.js +2 -6
- package/dist/resources/extensions/gsd/doctor-format.js +9 -6
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +13 -15
- package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
- 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/files.js +33 -19
- package/dist/resources/extensions/gsd/guidance.js +158 -0
- package/dist/resources/extensions/gsd/guided-flow.js +17 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
- 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 +4 -1
- package/dist/resources/extensions/gsd/milestone-closeout.js +13 -23
- package/dist/resources/extensions/gsd/notification-store.js +11 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +6 -4
- package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
- package/dist/resources/extensions/gsd/paths.js +27 -0
- 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/prompts/complete-slice.md +2 -2
- 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 +6 -4
- 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/reactive-graph.js +8 -1
- package/dist/resources/extensions/gsd/recovery-classification.js +37 -94
- package/dist/resources/extensions/gsd/safety/destructive-confirmation.js +108 -0
- package/dist/resources/extensions/gsd/state.js +6 -20
- package/dist/resources/extensions/gsd/stop-notice.js +57 -0
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +20 -10
- package/dist/resources/extensions/gsd/tools/exec-tool.js +9 -7
- package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
- package/dist/resources/extensions/gsd/uat-policy.js +42 -16
- 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/verdict-parser.js +1 -1
- 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 +15 -9
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
- package/dist/resources/extensions/gsd/worktree-root.js +11 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +4 -5
- 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/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 +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 +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/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/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/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/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/package.json +1 -1
- package/dist/worktree-cli.js +3 -6
- package/dist/worktree-status-banner.js +7 -15
- 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 +5 -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 +17 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/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/README.md +1 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +35 -125
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +46 -120
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- 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/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/GSD-WORKFLOW.md +5 -4
- 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 +3 -0
- 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/stream-adapter.ts +34 -4
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +152 -0
- package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +70 -46
- package/src/resources/extensions/gsd/auto/phases.ts +2 -2
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -32
- package/src/resources/extensions/gsd/auto-dispatch.ts +38 -52
- package/src/resources/extensions/gsd/auto-model-selection.ts +25 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -8
- package/src/resources/extensions/gsd/auto-prompts.ts +118 -35
- package/src/resources/extensions/gsd/auto-start.ts +18 -17
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +14 -21
- package/src/resources/extensions/gsd/auto-verification.ts +8 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +30 -93
- package/src/resources/extensions/gsd/auto.ts +8 -15
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +23 -6
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +24 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +251 -47
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +352 -84
- 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 +4 -6
- package/src/resources/extensions/gsd/consent-question.ts +416 -0
- package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
- 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/queries.ts +37 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
- package/src/resources/extensions/gsd/doctor-environment.ts +2 -7
- package/src/resources/extensions/gsd/doctor-format.ts +12 -7
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +13 -15
- package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
- 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/files.ts +33 -12
- package/src/resources/extensions/gsd/guidance.ts +217 -0
- package/src/resources/extensions/gsd/guided-flow.ts +16 -2
- package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
- 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 +4 -1
- package/src/resources/extensions/gsd/milestone-closeout.ts +13 -23
- package/src/resources/extensions/gsd/notification-store.ts +26 -3
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -4
- package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
- package/src/resources/extensions/gsd/paths.ts +33 -0
- 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/prompts/complete-slice.md +2 -2
- 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 +6 -4
- 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/reactive-graph.ts +11 -1
- package/src/resources/extensions/gsd/recovery-classification.ts +42 -96
- package/src/resources/extensions/gsd/safety/destructive-confirmation.ts +134 -0
- package/src/resources/extensions/gsd/state.ts +9 -21
- package/src/resources/extensions/gsd/stop-notice.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +101 -26
- 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 +22 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/consent-question.test.ts +336 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +10 -10
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +273 -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/engine-hook-contract.test.ts +148 -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/gsd-db.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/guidance.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +53 -11
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +73 -58
- package/src/resources/extensions/gsd/tests/integration/gsd-integration-fixture.ts +80 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +3 -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/parallel-research-dispatch.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
- 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/register-hooks-depth-verification.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -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 +112 -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/write-gate-seam.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +20 -10
- package/src/resources/extensions/gsd/tools/exec-tool.ts +8 -7
- package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
- package/src/resources/extensions/gsd/uat-policy.ts +62 -16
- 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/verdict-parser.ts +1 -1
- 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 +15 -9
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
- package/src/resources/extensions/gsd/worktree-root.ts +12 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +3 -5
- 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/spike-wrap-up/SKILL.md +9 -9
- package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
- package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
- /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{C24pqUd-aru-l0Dp0gLZP → jmTLg6xZmAuq_LIqKOxrH}/_ssgManifest.js +0 -0
|
@@ -39,6 +39,7 @@ import { markLatestActiveForWorkerCanceled, type DispatchStatus } from "./db/uni
|
|
|
39
39
|
import { getRuntimeKv, setRuntimeKv, deleteRuntimeKv } from "./db/runtime-kv.js";
|
|
40
40
|
import { _getAdapter, isDbAvailable } from "./gsd-db.js";
|
|
41
41
|
import { gsdRoot, normalizeRealPath } from "./paths.js";
|
|
42
|
+
import { crashResumeHint } from "./guidance.js";
|
|
42
43
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
43
44
|
import { effectiveLockFile } from "./session-lock.js";
|
|
44
45
|
import { isInFlightRuntimePhase, listUnitRuntimeRecords, type AutoUnitRuntimeRecord } from "./unit-runtime.js";
|
|
@@ -321,15 +322,8 @@ export function formatCrashInfo(lock: LockData): string {
|
|
|
321
322
|
` PID: ${lock.pid}`,
|
|
322
323
|
];
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
} else if (lock.unitType.includes("research") || lock.unitType.includes("plan")) {
|
|
327
|
-
lines.push(`The ${lock.unitType} unit may be incomplete. Run /gsd auto to re-run it.`);
|
|
328
|
-
} else if (lock.unitType.includes("execute")) {
|
|
329
|
-
lines.push(`Task execution was interrupted. Run /gsd auto to resume — completed work is preserved.`);
|
|
330
|
-
} else if (lock.unitType.includes("complete")) {
|
|
331
|
-
lines.push(`Slice/milestone completion was interrupted. Run /gsd auto to finish.`);
|
|
332
|
-
}
|
|
325
|
+
const hint = crashResumeHint(lock.unitType, lock.unitId);
|
|
326
|
+
if (hint) lines.push(hint);
|
|
333
327
|
|
|
334
328
|
return lines.join("\n");
|
|
335
329
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Read-only callers (forensics, dashboard, doctor) depend on this seam, not on
|
|
6
6
|
// the single-writer surface.
|
|
7
7
|
import { getDbOrNull } from "./engine.js";
|
|
8
|
+
import { isClosedStatus } from "../status-guards.js";
|
|
8
9
|
import { getGateIdsForTurn, type OwnerTurn } from "../gate-registry.js";
|
|
9
10
|
import type { Decision, Requirement, GateRow, GateScope } from "../types.js";
|
|
10
11
|
import {
|
|
@@ -269,6 +270,42 @@ export function getMilestoneSlices(milestoneId: string): SliceRow[] {
|
|
|
269
270
|
return rows.map(rowToSlice);
|
|
270
271
|
}
|
|
271
272
|
|
|
273
|
+
/** Dispatch-eligibility shape consumed by decision-path callers (ADR-017). */
|
|
274
|
+
export interface MilestoneSliceSummary {
|
|
275
|
+
id: string;
|
|
276
|
+
title: string;
|
|
277
|
+
/** Closed per the canonical status vocabulary (complete/done/skipped/closed). */
|
|
278
|
+
done: boolean;
|
|
279
|
+
depends: string[];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Consolidated DB read for dispatch/gate/completion decisions (ADR-017).
|
|
284
|
+
* `done` uses the canonical closed-status predicate (`isClosedStatus`) — the
|
|
285
|
+
* same vocabulary the SQL terminal-status fragment derives from. Decision
|
|
286
|
+
* paths must consume this instead of parsing `.gsd/*.md` projections.
|
|
287
|
+
* Rows keep `getMilestoneSlices` ordering (sequence, then id).
|
|
288
|
+
*/
|
|
289
|
+
export function getMilestoneSliceSummaries(milestoneId: string): MilestoneSliceSummary[] {
|
|
290
|
+
return getMilestoneSlices(milestoneId).map((s) => ({
|
|
291
|
+
id: s.id,
|
|
292
|
+
title: s.title,
|
|
293
|
+
done: isClosedStatus(s.status),
|
|
294
|
+
depends: s.depends ?? [],
|
|
295
|
+
}));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Ids of slices closed per the canonical status vocabulary (ADR-017), in
|
|
300
|
+
* milestone order. Thin wrapper over `getMilestoneSliceSummaries` for the
|
|
301
|
+
* common "which slices are done?" decision-path read.
|
|
302
|
+
*/
|
|
303
|
+
export function getClosedSliceIds(milestoneId: string): string[] {
|
|
304
|
+
return getMilestoneSliceSummaries(milestoneId)
|
|
305
|
+
.filter((s) => s.done)
|
|
306
|
+
.map((s) => s.id);
|
|
307
|
+
}
|
|
308
|
+
|
|
272
309
|
export function getArtifact(path: string): ArtifactRow | null {
|
|
273
310
|
if (!getDbOrNull()!) return null;
|
|
274
311
|
const row = getDbOrNull()!.prepare("SELECT * FROM artifacts WHERE path = :path").get({ ":path": path });
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
import { resolveMilestoneFile } from "./paths.js";
|
|
4
4
|
import { findMilestoneIds } from "./guided-flow.js";
|
|
5
5
|
import { parseUnitId } from "./unit-id.js";
|
|
6
|
-
import { isDbAvailable,
|
|
7
|
-
import {
|
|
8
|
-
import { isClosedStatus, isSkippedForDispatch } from "./status-guards.js";
|
|
6
|
+
import { isDbAvailable, getMilestoneSliceSummaries, getMilestone } from "./gsd-db.js";
|
|
7
|
+
import { isSkippedForDispatch } from "./status-guards.js";
|
|
9
8
|
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
10
9
|
import { readFileSync } from "node:fs";
|
|
11
10
|
import type { LoopState } from "./auto/types.js";
|
|
@@ -117,34 +116,12 @@ export function getPriorSliceCompletionBlocker(
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (rows.length > 0) {
|
|
127
|
-
slices = rows.map((r) => ({
|
|
128
|
-
id: r.id,
|
|
129
|
-
done: isClosedStatus(r.status),
|
|
130
|
-
depends: r.depends ?? [],
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (!slices) {
|
|
135
|
-
// File-based fallback: parse roadmap checkboxes
|
|
136
|
-
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
137
|
-
if (!roadmapPath) continue;
|
|
138
|
-
let roadmapContent: string;
|
|
139
|
-
try { roadmapContent = readFileSync(roadmapPath, "utf-8"); } catch { continue; }
|
|
140
|
-
const parsed = parseRoadmap(roadmapContent);
|
|
141
|
-
if (parsed.slices.length === 0) continue;
|
|
142
|
-
slices = parsed.slices.map((s) => ({
|
|
143
|
-
id: s.id,
|
|
144
|
-
done: s.done,
|
|
145
|
-
depends: s.depends ?? [],
|
|
146
|
-
}));
|
|
147
|
-
}
|
|
119
|
+
// DB-authoritative eligibility list (ADR-017) — markdown projections are
|
|
120
|
+
// never parsed for dispatch decisions. No DB / no rows → skip this
|
|
121
|
+
// milestone's check (unknown is not a blocker).
|
|
122
|
+
if (!isDbAvailable()) continue;
|
|
123
|
+
const slices = getMilestoneSliceSummaries(mid);
|
|
124
|
+
if (slices.length === 0) continue;
|
|
148
125
|
|
|
149
126
|
if (mid !== targetMid) {
|
|
150
127
|
const incomplete = slices.find((slice) => !slice.done);
|
|
@@ -15,7 +15,7 @@ import { join } from "node:path";
|
|
|
15
15
|
|
|
16
16
|
import type { DoctorIssue, DoctorIssueCode } from "./doctor-types.js";
|
|
17
17
|
import { detectPythonExecutable } from "./python-resolver.js";
|
|
18
|
-
import {
|
|
18
|
+
import { projectRootFromWorktreePath } from "./worktree-root.js";
|
|
19
19
|
|
|
20
20
|
// ── Types ──────────────────────────────────────────────────────────────────
|
|
21
21
|
|
|
@@ -50,12 +50,7 @@ const CMD_TIMEOUT = 5_000;
|
|
|
50
50
|
function resolveWorktreeProjectRoot(basePath: string): string | null {
|
|
51
51
|
const envRoot = process.env.GSD_WORKTREE;
|
|
52
52
|
if (envRoot) return envRoot;
|
|
53
|
-
|
|
54
|
-
const segment = findWorktreeSegment(basePath.replace(/\\/g, "/"));
|
|
55
|
-
if (!segment) return null;
|
|
56
|
-
|
|
57
|
-
// Everything before the worktree segment is the project root
|
|
58
|
-
return basePath.slice(0, segment.gsdIdx);
|
|
53
|
+
return projectRootFromWorktreePath(basePath);
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
function tryExec(cmd: string, cwd: string): string | null {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type { DoctorIssue, DoctorIssueCode, DoctorReport, DoctorSummary } from "./doctor-types.js";
|
|
1
|
+
import type { DoctorIssue, DoctorIssueCode, DoctorReport, DoctorSummary, DoctorSeverity } from "./doctor-types.js";
|
|
2
|
+
import { doctorFixHint } from "./guidance.js";
|
|
3
|
+
|
|
4
|
+
function severityTag(severity: DoctorSeverity): string {
|
|
5
|
+
return severity === "error" ? "ERROR" : severity === "warning" ? "WARN" : "INFO";
|
|
6
|
+
}
|
|
2
7
|
|
|
3
8
|
function matchesScope(unitId: string, scope?: string): boolean {
|
|
4
9
|
if (!scope) return true;
|
|
@@ -53,8 +58,9 @@ export function formatDoctorReport(
|
|
|
53
58
|
if (scopedIssues.length > 0) {
|
|
54
59
|
lines.push("Priority issues:");
|
|
55
60
|
for (const issue of scopedIssues.slice(0, maxIssues)) {
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
lines.push(`- [${severityTag(issue.severity)}] ${issue.unitId}: ${issue.message}${issue.file ? ` (${issue.file})` : ""}`);
|
|
62
|
+
const hint = doctorFixHint(issue.code);
|
|
63
|
+
if (hint && issue.severity !== "info") lines.push(` Fix: ${hint}`);
|
|
58
64
|
}
|
|
59
65
|
if (scopedIssues.length > maxIssues) {
|
|
60
66
|
lines.push(`- ...and ${scopedIssues.length - maxIssues} more in scope`);
|
|
@@ -72,10 +78,9 @@ export function formatDoctorReport(
|
|
|
72
78
|
|
|
73
79
|
export function formatDoctorIssuesForPrompt(issues: DoctorIssue[]): string {
|
|
74
80
|
if (issues.length === 0) return "- No remaining issues in scope.";
|
|
75
|
-
return issues.map(issue =>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}).join("\n");
|
|
81
|
+
return issues.map(issue =>
|
|
82
|
+
`- [${severityTag(issue.severity)}] ${issue.unitId} | ${issue.code} | ${issue.message}${issue.file ? ` | file: ${issue.file}` : ""} | fixable: ${issue.fixable ? "yes" : "no"}`
|
|
83
|
+
).join("\n");
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
/**
|
|
@@ -425,22 +425,20 @@ export async function checkRuntimeHealth(
|
|
|
425
425
|
missing.push(...criticalPatterns.filter(p => !existingLines.has(p)));
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
{
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
});
|
|
428
|
+
if (missing.length > 0) {
|
|
429
|
+
issues.push({
|
|
430
|
+
severity: "warning",
|
|
431
|
+
code: "gitignore_missing_patterns",
|
|
432
|
+
scope: "project",
|
|
433
|
+
unitId: "project",
|
|
434
|
+
message: `${missing.length} critical GSD runtime pattern(s) missing from .gitignore: ${missing.join(", ")}`,
|
|
435
|
+
file: ".gitignore",
|
|
436
|
+
fixable: true,
|
|
437
|
+
});
|
|
439
438
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
439
|
+
if (shouldFix("gitignore_missing_patterns")) {
|
|
440
|
+
ensureGitignore(basePath, { manageGitignore });
|
|
441
|
+
fixesApplied.push("added missing GSD runtime patterns to .gitignore");
|
|
444
442
|
}
|
|
445
443
|
}
|
|
446
444
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Typed contract for which tool lifecycle hooks fire under which
|
|
3
|
+
// engine, plus the single seam for tool-name normalization.
|
|
4
|
+
//
|
|
5
|
+
// ── Why this contract exists ────────────────────────────────────────────────
|
|
6
|
+
// External engines (claude-code-cli) pre-execute tools inside the vendor CLI
|
|
7
|
+
// and hand the agent loop a `toolCall.externalResult`. The loop short-circuits
|
|
8
|
+
// before `beforeToolCall`/`afterToolCall` ever run for those calls
|
|
9
|
+
// (packages/pi-agent-core/src/agent-loop.ts, prepareToolCall: the
|
|
10
|
+
// externalResult branch returns an "immediate" outcome before the
|
|
11
|
+
// config.beforeToolCall invocation, and "immediate" outcomes skip
|
|
12
|
+
// finalizeExecutedToolCall where config.afterToolCall lives).
|
|
13
|
+
// `beforeToolCall`/`afterToolCall` are exactly what the extension runner maps
|
|
14
|
+
// to the `tool_call`/`tool_result` extension events
|
|
15
|
+
// (packages/gsd-agent-core/src/session/agent-session-extensions.ts,
|
|
16
|
+
// installAgentToolHooks).
|
|
17
|
+
//
|
|
18
|
+
// `tool_execution_start` is emitted unconditionally before prepareToolCall
|
|
19
|
+
// and `tool_execution_end` after every finalized outcome — immediate or
|
|
20
|
+
// executed — so those two are the ONLY tool lifecycle hooks that fire for
|
|
21
|
+
// every tool call on every engine.
|
|
22
|
+
//
|
|
23
|
+
// Consequence: any enforcement attached only to `tool_call` (blocking) or
|
|
24
|
+
// `tool_result` (rewriting) is silently dead under external engines. Safety
|
|
25
|
+
// enforcement must ride `tool_execution_start`/`tool_execution_end`, or
|
|
26
|
+
// mirror across both with toolCallId dedup. See the per-registration contract
|
|
27
|
+
// comments in bootstrap/register-hooks.ts for how each registered hook
|
|
28
|
+
// honors (or knowingly violates) this contract.
|
|
29
|
+
|
|
30
|
+
import { stripMcpToolPrefix } from "./mcp-tool-name.js";
|
|
31
|
+
import { canonicalWorkflowSurfaceToolName } from "./workflow-tool-surface.js";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Tool lifecycle hooks that fire for EVERY tool call on EVERY engine,
|
|
35
|
+
* including external engines (claude-code-cli) that pre-execute tools.
|
|
36
|
+
* Attach safety-critical enforcement and evidence collection here.
|
|
37
|
+
*/
|
|
38
|
+
export const UNIVERSAL_TOOL_HOOKS = ["tool_execution_start", "tool_execution_end"] as const;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tool lifecycle hooks that fire ONLY for natively executed tools. External
|
|
42
|
+
* engines pre-execute tools (externalResult), short-circuiting the agent
|
|
43
|
+
* loop's beforeToolCall/afterToolCall — so handlers on these events never run
|
|
44
|
+
* for those calls. Blocking guards attached only here are dead under external
|
|
45
|
+
* engines; they need a tool_execution_start mirror to be universal.
|
|
46
|
+
*/
|
|
47
|
+
export const NATIVE_ONLY_TOOL_HOOKS = ["tool_call", "tool_result"] as const;
|
|
48
|
+
|
|
49
|
+
export type UniversalToolHook = (typeof UNIVERSAL_TOOL_HOOKS)[number];
|
|
50
|
+
export type NativeOnlyToolHook = (typeof NATIVE_ONLY_TOOL_HOOKS)[number];
|
|
51
|
+
|
|
52
|
+
// Non-tool lifecycle events (session_start, agent_end, message_update, ...)
|
|
53
|
+
// are intentionally NOT classified here: they are emitted by the session
|
|
54
|
+
// host / extension runner independent of tool execution, so the external
|
|
55
|
+
// engine short-circuit above does not apply to them. Only classify events
|
|
56
|
+
// whose engine behavior has been verified against the agent loop.
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Canonical tool name: strips the `mcp__<server>__` prefix when present,
|
|
60
|
+
* nothing else. Use for identity checks against host/native tool names and
|
|
61
|
+
* for any guard that must NOT conflate workflow aliases with their canonical
|
|
62
|
+
* tools (e.g. write gates, evidence keys).
|
|
63
|
+
*
|
|
64
|
+
* Malformed MCP names (empty server or empty tool segment, e.g.
|
|
65
|
+
* `mcp____tool` or `mcp__server__`) are returned unchanged.
|
|
66
|
+
*/
|
|
67
|
+
export function canonicalToolName(toolName: string): string {
|
|
68
|
+
return stripMcpToolPrefix(toolName);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Workflow-aware canonical tool name: strips the MCP prefix AND resolves
|
|
73
|
+
* workflow tool aliases to their canonical contract names. Use whenever the
|
|
74
|
+
* name is compared against the workflow tool surface (scoping, presentation,
|
|
75
|
+
* dispatch) — plain {@link canonicalToolName} would miss alias spellings.
|
|
76
|
+
*/
|
|
77
|
+
export function canonicalWorkflowToolName(toolName: string): string {
|
|
78
|
+
return canonicalWorkflowSurfaceToolName(toolName);
|
|
79
|
+
}
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* @see https://github.com/open-gsd/gsd-pi/issues/2577
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { TOOL_SURFACE_NOT_READY } from "./tool-surface-readiness.js";
|
|
14
|
+
|
|
13
15
|
// ── ErrorClass discriminated union ──────────────────────────────────────────
|
|
14
16
|
|
|
15
17
|
export type ErrorClass =
|
|
@@ -70,6 +72,10 @@ const CONNECTION_RE = /terminated|connection.?(?:refused|error)|other side close
|
|
|
70
72
|
const STREAM_RE = /in JSON at position \d+|Unexpected end of JSON|SyntaxError.*JSON/i;
|
|
71
73
|
const RESET_DELAY_RE = /reset in (\d+)s/i;
|
|
72
74
|
const TOOL_SCHEMA_RE = /schema overload|consecutive tool validation failures/i;
|
|
75
|
+
// GSD tool-surface readiness abort (claude-code stream adapter): the workflow
|
|
76
|
+
// MCP server had not registered the Unit's required tools at SDK init. The
|
|
77
|
+
// server typically finishes connecting within seconds — same-model retry.
|
|
78
|
+
const TOOL_SURFACE_NOT_READY_RE = new RegExp(TOOL_SURFACE_NOT_READY, "i");
|
|
73
79
|
// Provider rejected the request shape for the selected model (400 bad request,
|
|
74
80
|
// grammar limits, etc.). Not transient — try a different model/fallback.
|
|
75
81
|
// Context-window 400s stay in SERVER_RE (checked earlier).
|
|
@@ -108,6 +114,11 @@ export function classifyError(errorMsg: string, retryAfterMs?: number): ErrorCla
|
|
|
108
114
|
return { kind: "tool-schema", retryAfterMs: 0 };
|
|
109
115
|
}
|
|
110
116
|
|
|
117
|
+
// Tool-surface readiness abort — transient; retry the same model shortly.
|
|
118
|
+
if (TOOL_SURFACE_NOT_READY_RE.test(errorMsg)) {
|
|
119
|
+
return { kind: "network", retryAfterMs: retryAfterMs ?? 3_000 };
|
|
120
|
+
}
|
|
121
|
+
|
|
111
122
|
const isPermanent = PERMANENT_RE.test(errorMsg);
|
|
112
123
|
const isRateLimit = RATE_LIMIT_RE.test(errorMsg) || AFFORDABILITY_RE.test(errorMsg);
|
|
113
124
|
const isUnsupportedModel =
|
|
@@ -12,6 +12,7 @@ import { spawn } from "node:child_process";
|
|
|
12
12
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
14
|
import { resolve } from "node:path";
|
|
15
|
+
import { killProcessTree, SIGKILL_GRACE_MS, HARD_DEADLINE_MS } from "@gsd/pi-coding-agent";
|
|
15
16
|
|
|
16
17
|
export interface ExecSandboxRequest {
|
|
17
18
|
/** Interpreter to use. */
|
|
@@ -47,6 +48,17 @@ export interface ExecSandboxOptions {
|
|
|
47
48
|
now?: () => Date;
|
|
48
49
|
/** Optional override for id generation (tests). */
|
|
49
50
|
generateId?: () => string;
|
|
51
|
+
/**
|
|
52
|
+
* Grace period (ms) between SIGTERM and SIGKILL on timeout.
|
|
53
|
+
* Defaults to SIGKILL_GRACE_MS. Exposed as a test seam.
|
|
54
|
+
*/
|
|
55
|
+
kill_grace_ms?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Delay (ms) after a kill is initiated before the hard-deadline force-resolves
|
|
58
|
+
* the promise (handles D-state / non-closing children).
|
|
59
|
+
* Defaults to SIGKILL_GRACE_MS + HARD_DEADLINE_MS. Exposed as a test seam.
|
|
60
|
+
*/
|
|
61
|
+
force_resolve_delay_ms?: number;
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
export interface ExecSandboxResult {
|
|
@@ -55,6 +67,12 @@ export interface ExecSandboxResult {
|
|
|
55
67
|
exit_code: number | null;
|
|
56
68
|
signal: NodeJS.Signals | null;
|
|
57
69
|
timed_out: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* True when the result came from the hard-deadline force-resolve (a non-closing
|
|
72
|
+
* D-state child that never emitted 'close') rather than an observed process exit.
|
|
73
|
+
* In that case `signal` is the synthetic "SIGKILL" marker, not a delivered signal.
|
|
74
|
+
*/
|
|
75
|
+
force_resolved: boolean;
|
|
58
76
|
duration_ms: number;
|
|
59
77
|
stdout_bytes: number;
|
|
60
78
|
stderr_bytes: number;
|
|
@@ -68,6 +86,10 @@ export interface ExecSandboxResult {
|
|
|
68
86
|
|
|
69
87
|
const ALWAYS_FORWARD_ENV = ["PATH", "HOME"] as const;
|
|
70
88
|
|
|
89
|
+
// SIGKILL_GRACE_MS / HARD_DEADLINE_MS are imported from @gsd/pi-coding-agent
|
|
90
|
+
// (shell.ts) — the single source of truth for the graceful-kill timing ladder —
|
|
91
|
+
// so this sandbox can never drift from the canonical kill path it delegates to.
|
|
92
|
+
|
|
71
93
|
export const EXEC_DEFAULTS = {
|
|
72
94
|
clampTimeoutMs: 600_000,
|
|
73
95
|
defaultTimeoutMs: 30_000,
|
|
@@ -180,6 +202,7 @@ export function runExecSandbox(
|
|
|
180
202
|
exit_code: null,
|
|
181
203
|
signal: null,
|
|
182
204
|
timed_out: false,
|
|
205
|
+
force_resolved: false,
|
|
183
206
|
duration_ms: duration,
|
|
184
207
|
stdout_bytes: 0,
|
|
185
208
|
stderr_bytes: Buffer.byteLength(`spawn error: ${message}\n`),
|
|
@@ -233,23 +256,39 @@ export function runExecSandbox(
|
|
|
233
256
|
}
|
|
234
257
|
});
|
|
235
258
|
|
|
259
|
+
const effectiveGraceMs = opts.kill_grace_ms ?? SIGKILL_GRACE_MS;
|
|
260
|
+
const effectiveForceResolveDelay = opts.force_resolve_delay_ms ?? (effectiveGraceMs + HARD_DEADLINE_MS);
|
|
261
|
+
|
|
236
262
|
let timedOut = false;
|
|
263
|
+
let settled = false;
|
|
264
|
+
let forceResolveTimer: NodeJS.Timeout | undefined;
|
|
265
|
+
|
|
237
266
|
const timer = setTimeout(() => {
|
|
238
267
|
timedOut = true;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
268
|
+
// killProcessTree handles both platforms and kills the whole tree: on Unix
|
|
269
|
+
// it signals the process group (SIGTERM -> grace -> SIGKILL); on Windows it
|
|
270
|
+
// force-kills the tree via taskkill /F /T. Using child.kill("SIGTERM") here
|
|
271
|
+
// would only terminate the direct child on Windows, orphaning grandchildren.
|
|
272
|
+
if (child.pid != null) {
|
|
273
|
+
killProcessTree(child.pid, { graceMs: effectiveGraceMs });
|
|
245
274
|
} else {
|
|
246
|
-
child.kill("
|
|
275
|
+
child.kill("SIGTERM");
|
|
247
276
|
}
|
|
277
|
+
// Arm hard-deadline force-resolve in case child never closes (D-state).
|
|
278
|
+
// The "SIGKILL" here is a synthetic marker (the process may not have actually
|
|
279
|
+
// received it); force_resolved=true records that this was a deadline, not an exit.
|
|
280
|
+
forceResolveTimer = setTimeout(() => {
|
|
281
|
+
finalize(null, "SIGKILL", true);
|
|
282
|
+
}, effectiveForceResolveDelay);
|
|
283
|
+
forceResolveTimer.unref?.();
|
|
248
284
|
}, timeoutMs);
|
|
249
285
|
timer.unref?.();
|
|
250
286
|
|
|
251
|
-
const finalize = (exitCode: number | null, signal: NodeJS.Signals | null) => {
|
|
287
|
+
const finalize = (exitCode: number | null, signal: NodeJS.Signals | null, forceResolved = false) => {
|
|
288
|
+
if (settled) return;
|
|
289
|
+
settled = true;
|
|
252
290
|
clearTimeout(timer);
|
|
291
|
+
clearTimeout(forceResolveTimer);
|
|
253
292
|
const duration = Date.now() - started;
|
|
254
293
|
const stdoutBuf = Buffer.concat(stdoutChunks);
|
|
255
294
|
const stderrBuf = Buffer.concat(stderrChunks);
|
|
@@ -274,6 +313,7 @@ export function runExecSandbox(
|
|
|
274
313
|
exit_code: exitCode,
|
|
275
314
|
signal,
|
|
276
315
|
timed_out: timedOut,
|
|
316
|
+
force_resolved: forceResolved,
|
|
277
317
|
duration_ms: duration,
|
|
278
318
|
stdout_bytes: stdoutBytes,
|
|
279
319
|
stderr_bytes: stderrBytes,
|
|
@@ -324,6 +364,7 @@ function writeMeta(
|
|
|
324
364
|
exit_code: result.exit_code,
|
|
325
365
|
signal: result.signal,
|
|
326
366
|
timed_out: result.timed_out,
|
|
367
|
+
force_resolved: result.force_resolved,
|
|
327
368
|
duration_ms: result.duration_ms,
|
|
328
369
|
stdout_bytes: result.stdout_bytes,
|
|
329
370
|
stderr_bytes: result.stderr_bytes,
|
|
@@ -331,7 +372,6 @@ function writeMeta(
|
|
|
331
372
|
stderr_truncated: result.stderr_truncated,
|
|
332
373
|
stdout_path: result.stdout_path,
|
|
333
374
|
stderr_path: result.stderr_path,
|
|
334
|
-
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
335
375
|
};
|
|
336
376
|
writeFileSync(path, `${JSON.stringify(meta, null, 2)}\n`);
|
|
337
377
|
}
|
|
@@ -671,33 +671,54 @@ export function parseTaskPlanIO(content: string): { inputFiles: string[]; output
|
|
|
671
671
|
*/
|
|
672
672
|
export type UatType = 'artifact-driven' | 'live-runtime' | 'human-experience' | 'mixed' | 'browser-executable' | 'runtime-executable';
|
|
673
673
|
|
|
674
|
+
/** Canonical list of recognised UAT types — uat-policy.ts re-exports this as UAT_TYPES. */
|
|
675
|
+
export const UAT_TYPE_KEYWORDS: readonly UatType[] = [
|
|
676
|
+
'artifact-driven',
|
|
677
|
+
'browser-executable',
|
|
678
|
+
'runtime-executable',
|
|
679
|
+
'live-runtime',
|
|
680
|
+
'mixed',
|
|
681
|
+
'human-experience',
|
|
682
|
+
];
|
|
683
|
+
|
|
684
|
+
/** Match a value against the recognised UAT type keywords (leading-keyword-only). */
|
|
685
|
+
function matchUatTypeKeyword(value: string): UatType | undefined {
|
|
686
|
+
const normalized = value.trim().toLowerCase();
|
|
687
|
+
return UAT_TYPE_KEYWORDS.find(keyword => normalized.startsWith(keyword));
|
|
688
|
+
}
|
|
689
|
+
|
|
674
690
|
/**
|
|
675
691
|
* Extract the UAT type from a UAT file's raw content.
|
|
676
692
|
*
|
|
677
693
|
* UAT files have no YAML frontmatter - pass raw file content directly.
|
|
678
694
|
* Classification is leading-keyword-only: e.g. `mixed (artifact-driven + live-runtime)` → `'mixed'`.
|
|
679
695
|
*
|
|
696
|
+
* The canonical form is a `- UAT mode: <type>` bullet under `## UAT Type`
|
|
697
|
+
* (case-insensitive prefix, `**bold**` tolerated). When no such line exists,
|
|
698
|
+
* a line that itself starts with a recognised keyword — e.g. a bare
|
|
699
|
+
* `browser-executable` under the heading — is accepted, so agent-authored
|
|
700
|
+
* format drift does not silently fall back to artifact-driven.
|
|
701
|
+
*
|
|
680
702
|
* Returns `undefined` when:
|
|
681
703
|
* - the `## UAT Type` section is absent
|
|
682
|
-
* -
|
|
683
|
-
* -
|
|
704
|
+
* - a `UAT mode:` line exists but its value starts with no recognised keyword
|
|
705
|
+
* - no line in the section starts with `UAT mode:` or a recognised keyword
|
|
684
706
|
*/
|
|
685
707
|
export function extractUatType(content: string): UatType | undefined {
|
|
686
708
|
const sectionText = extractSection(content, 'UAT Type');
|
|
687
709
|
if (!sectionText) return undefined;
|
|
688
710
|
|
|
689
|
-
const
|
|
690
|
-
const modeBullet = bullets.find(b => b.startsWith('UAT mode:'));
|
|
691
|
-
if (!modeBullet) return undefined;
|
|
711
|
+
const lines = parseBullets(sectionText).map(line => line.replace(/\*\*/g, ''));
|
|
692
712
|
|
|
693
|
-
const
|
|
713
|
+
for (const line of lines) {
|
|
714
|
+
const declared = /^uat mode:\s*(.*)$/i.exec(line);
|
|
715
|
+
if (declared) return matchUatTypeKeyword(declared[1]);
|
|
716
|
+
}
|
|
694
717
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (rawValue.startsWith('human-experience')) return 'human-experience';
|
|
700
|
-
if (rawValue.startsWith('mixed')) return 'mixed';
|
|
718
|
+
for (const line of lines) {
|
|
719
|
+
const matched = matchUatTypeKeyword(line);
|
|
720
|
+
if (matched) return matched;
|
|
721
|
+
}
|
|
701
722
|
|
|
702
723
|
return undefined;
|
|
703
724
|
}
|