@opengsd/gsd-pi 1.1.1-dev.a5a2de8 → 1.1.1-dev.b2556262
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/headless-recover.js +56 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +18 -2
- package/dist/resources/extensions/browser-tools/engine/selection.js +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/index.js +68 -24
- package/dist/resources/extensions/browser-tools/state.js +12 -0
- package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
- package/dist/resources/extensions/browser-tools/utils.js +3 -3
- package/dist/resources/extensions/browser-tools/web-app-detect.js +52 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +87 -12
- package/dist/resources/extensions/gsd/auto/session.js +22 -1
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +1 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +81 -13
- package/dist/resources/extensions/gsd/auto-model-selection.js +154 -9
- package/dist/resources/extensions/gsd/auto-post-unit.js +19 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +26 -21
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -2
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-timers.js +24 -10
- package/dist/resources/extensions/gsd/auto.js +40 -15
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +192 -77
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
- package/dist/resources/extensions/gsd/closeout-wizard.js +32 -9
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -9
- package/dist/resources/extensions/gsd/commands-maintenance.js +93 -15
- package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +2 -2
- package/dist/resources/extensions/gsd/config-overlay.js +1 -0
- package/dist/resources/extensions/gsd/context-masker.js +129 -5
- package/dist/resources/extensions/gsd/db-writer.js +35 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/dist/resources/extensions/gsd/gsd-db.js +480 -172
- package/dist/resources/extensions/gsd/guided-flow.js +4 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +37 -53
- package/dist/resources/extensions/gsd/md-importer.js +38 -3
- package/dist/resources/extensions/gsd/migration-auto-check.js +126 -31
- package/dist/resources/extensions/gsd/parsers-legacy.js +23 -0
- package/dist/resources/extensions/gsd/planner-handoff.js +98 -0
- package/dist/resources/extensions/gsd/planning-path-scope.js +22 -4
- package/dist/resources/extensions/gsd/pre-execution-checks.js +10 -2
- package/dist/resources/extensions/gsd/preferences-models.js +111 -43
- package/dist/resources/extensions/gsd/preferences-types.js +13 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +68 -3
- package/dist/resources/extensions/gsd/preferences.js +4 -1
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +2 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -1
- package/dist/resources/extensions/gsd/safety/content-validator.js +6 -4
- package/dist/resources/extensions/gsd/skill-manifest.js +12 -0
- package/dist/resources/extensions/gsd/source-observations.js +306 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +15 -8
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +33 -5
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +34 -13
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +39 -14
- package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +4 -4
- package/dist/resources/extensions/gsd/state.js +7 -3
- package/dist/resources/extensions/gsd/tool-contract.js +15 -1
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +24 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +28 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +42 -11
- package/dist/resources/extensions/gsd/tools/plan-task.js +7 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +62 -406
- package/dist/resources/extensions/gsd/uat-policy.js +130 -0
- package/dist/resources/extensions/gsd/uat-run.js +414 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +3 -4
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +38 -14
- package/dist/resources/extensions/gsd/verdict-parser.js +3 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +132 -5
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -3
- package/dist/resources/extensions/gsd/workflow-projections.js +8 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +26 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +96 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +18 -17
- package/dist/resources/extensions/shared/gsd-browser-cli.js +6 -0
- package/dist/resources/extensions/subagent/agents.js +1 -0
- package/dist/resources/extensions/subagent/index.js +27 -12
- package/dist/resources/extensions/subagent/launch.js +7 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/@gsd/native/dist/native.js +22 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +4 -4
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +3 -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 +25 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +66 -12
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.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 +18 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-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 +16 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/dist/native.js +22 -0
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
- package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/image-models.generated.js +30 -0
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +174 -29
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +178 -54
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +8 -1
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js +1 -1
- package/packages/pi-coding-agent/dist/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/utils.d.ts +11 -0
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +119 -6
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/themes.js +1 -1
- package/pkg/dist/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install/handoff.js +16 -3
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +21 -2
- package/src/resources/extensions/browser-tools/engine/selection.ts +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +75 -27
- package/src/resources/extensions/browser-tools/state.ts +13 -0
- package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +2 -2
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +37 -0
- package/src/resources/extensions/browser-tools/tests/web-app-detect.test.mjs +68 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
- package/src/resources/extensions/browser-tools/utils.ts +3 -3
- package/src/resources/extensions/browser-tools/web-app-detect.ts +63 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +89 -15
- package/src/resources/extensions/gsd/auto/session.ts +24 -1
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +1 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +117 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +190 -12
- package/src/resources/extensions/gsd/auto-post-unit.ts +20 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +25 -22
- package/src/resources/extensions/gsd/auto-recovery.ts +22 -3
- package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-timers.ts +25 -9
- package/src/resources/extensions/gsd/auto.ts +41 -14
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +250 -78
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
- package/src/resources/extensions/gsd/closeout-wizard.ts +47 -13
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -17
- package/src/resources/extensions/gsd/commands-maintenance.ts +124 -13
- package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +2 -2
- package/src/resources/extensions/gsd/config-overlay.ts +1 -0
- package/src/resources/extensions/gsd/context-masker.ts +152 -5
- package/src/resources/extensions/gsd/db-writer.ts +38 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +50 -1
- package/src/resources/extensions/gsd/gsd-db.ts +564 -186
- package/src/resources/extensions/gsd/guided-flow.ts +4 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +44 -66
- package/src/resources/extensions/gsd/md-importer.ts +49 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +154 -34
- package/src/resources/extensions/gsd/parsers-legacy.ts +20 -0
- package/src/resources/extensions/gsd/planner-handoff.ts +149 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +22 -4
- package/src/resources/extensions/gsd/pre-execution-checks.ts +9 -2
- package/src/resources/extensions/gsd/preferences-models.ts +113 -43
- package/src/resources/extensions/gsd/preferences-types.ts +47 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +76 -2
- package/src/resources/extensions/gsd/preferences.ts +5 -0
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +2 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +6 -1
- package/src/resources/extensions/gsd/safety/content-validator.ts +8 -5
- package/src/resources/extensions/gsd/skill-manifest.ts +12 -0
- package/src/resources/extensions/gsd/source-observations.ts +402 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +20 -8
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +44 -5
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +39 -11
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +45 -15
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +4 -4
- package/src/resources/extensions/gsd/state.ts +7 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +66 -4
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +299 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +75 -3
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -0
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/closeout-wizard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/content-validator.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +17 -2
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +1 -11
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +62 -1
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +99 -2
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/planner-handoff.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +162 -18
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/source-observations.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -21
- package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +77 -10
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +260 -5
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +511 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +44 -0
- package/src/resources/extensions/gsd/tool-contract.ts +29 -1
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +41 -6
- package/src/resources/extensions/gsd/tools/complete-slice.ts +29 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +54 -12
- package/src/resources/extensions/gsd/tools/plan-task.ts +8 -1
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +71 -489
- package/src/resources/extensions/gsd/types.ts +1 -0
- package/src/resources/extensions/gsd/uat-policy.ts +191 -0
- package/src/resources/extensions/gsd/uat-run.ts +550 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +3 -4
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +38 -14
- package/src/resources/extensions/gsd/verdict-parser.ts +3 -10
- package/src/resources/extensions/gsd/workflow-manifest.ts +193 -7
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -3
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +32 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +103 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +22 -22
- package/src/resources/extensions/shared/gsd-browser-cli.ts +6 -0
- package/src/resources/extensions/shared/tests/format-utils.test.ts +8 -3
- package/src/resources/extensions/subagent/agents.ts +4 -0
- package/src/resources/extensions/subagent/index.ts +28 -3
- package/src/resources/extensions/subagent/launch.ts +8 -0
- package/src/resources/extensions/subagent/tests/model-override.test.ts +31 -0
- /package/dist/web/standalone/.next/static/{9y3LeeR2uGr2yRj9RjY3D → tJOKQbQRO-9MiFDO8DIDS}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{9y3LeeR2uGr2yRj9RjY3D → tJOKQbQRO-9MiFDO8DIDS}/_ssgManifest.js +0 -0
|
@@ -1208,7 +1208,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
1208
1208
|
s.autoStartTime = Date.now();
|
|
1209
1209
|
s.resourceVersionOnStart = readResourceVersion();
|
|
1210
1210
|
s.pendingQuickTasks = [];
|
|
1211
|
-
s.
|
|
1211
|
+
s.clearCurrentUnit();
|
|
1212
1212
|
s.currentMilestoneId ??=
|
|
1213
1213
|
strandedRecoveryAction?.milestoneId ??
|
|
1214
1214
|
(deepProjectStagePending ? null : state.activeMilestone?.id ?? null);
|
|
@@ -104,6 +104,14 @@ export function startUnitSupervision(sctx) {
|
|
|
104
104
|
const softTimeoutMs = supervisionTimeouts.softTimeoutMs;
|
|
105
105
|
const idleTimeoutMs = supervisionTimeouts.idleTimeoutMs;
|
|
106
106
|
const hardTimeoutMs = supervisionTimeouts.hardTimeoutMs;
|
|
107
|
+
// A single hung tool gets its own short budget, NOT the general idle window:
|
|
108
|
+
// a long-but-progressing session is not idle, but a tool stuck for minutes
|
|
109
|
+
// is. Falls back to the idle window only if misconfigured to zero. The
|
|
110
|
+
// hung-tool budget is intentionally not scaled by task estimate — a stuck
|
|
111
|
+
// tool call is stuck regardless of how long the overall task should take.
|
|
112
|
+
const stalledToolTimeoutMs = (supervisor.stalled_tool_timeout_minutes ?? 0) > 0
|
|
113
|
+
? supervisor.stalled_tool_timeout_minutes * 60 * 1000
|
|
114
|
+
: idleTimeoutMs;
|
|
107
115
|
// ── 1. Soft timeout warning ──
|
|
108
116
|
s.wrapupWarningHandle = setTimeout(() => {
|
|
109
117
|
s.wrapupWarningHandle = null;
|
|
@@ -144,10 +152,12 @@ export function startUnitSupervision(sctx) {
|
|
|
144
152
|
const runtime = readUnitRuntimeRecord(s.basePath, unitType, unitId);
|
|
145
153
|
if (!runtime)
|
|
146
154
|
return;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
//
|
|
155
|
+
// In-flight tool handling runs on its own dedicated hung-tool budget,
|
|
156
|
+
// independent of the general idle gate below, so a genuinely stuck tool
|
|
157
|
+
// is caught in minutes instead of waiting out the (typically much longer)
|
|
158
|
+
// idle window (#2527, follow-up). A tool actively executing within budget
|
|
159
|
+
// is real progress, so refreshing lastProgressAt here also keeps the idle
|
|
160
|
+
// gate from firing during legitimate long-running tool calls.
|
|
151
161
|
let stalledToolDetected = false;
|
|
152
162
|
if (getInFlightToolCount() > 0) {
|
|
153
163
|
// User-interactive tools (ask_user_questions, secure_env_collect) block
|
|
@@ -161,21 +171,25 @@ export function startUnitSupervision(sctx) {
|
|
|
161
171
|
}
|
|
162
172
|
const oldestStart = getOldestInFlightToolStart();
|
|
163
173
|
const toolAgeMs = Date.now() - oldestStart;
|
|
164
|
-
if (toolAgeMs <
|
|
174
|
+
if (toolAgeMs < stalledToolTimeoutMs) {
|
|
165
175
|
writeUnitRuntimeRecord(s.basePath, unitType, unitId, s.currentUnit.startedAt, {
|
|
166
176
|
lastProgressAt: Date.now(),
|
|
167
177
|
lastProgressKind: "tool-in-flight",
|
|
168
178
|
});
|
|
169
179
|
return;
|
|
170
180
|
}
|
|
171
|
-
// Tool has been in-flight longer than
|
|
172
|
-
// Clear the stale entries so subsequent ticks don't re-detect
|
|
173
|
-
// and set the flag so the filesystem-activity check
|
|
174
|
-
// override the stall verdict (#2527).
|
|
181
|
+
// Tool has been in-flight longer than the hung-tool budget — treat as
|
|
182
|
+
// hung. Clear the stale entries so subsequent ticks don't re-detect
|
|
183
|
+
// them, and set the flag so the idle gate and filesystem-activity check
|
|
184
|
+
// below do not override the stall verdict (#2527).
|
|
175
185
|
stalledToolDetected = true;
|
|
176
186
|
clearInFlightTools();
|
|
177
|
-
ctx.ui.notify(`Stalled tool detected: a tool has been in-flight for ${Math.round(toolAgeMs / 60000)}min. Treating as hung — attempting idle recovery.`, "warning");
|
|
187
|
+
ctx.ui.notify(`Stalled tool detected: a tool has been in-flight for ${Math.round(toolAgeMs / 60000)}min (budget ${Math.round(stalledToolTimeoutMs / 60000)}min). Treating as hung — attempting idle recovery.`, "warning");
|
|
178
188
|
}
|
|
189
|
+
// No hung tool — apply the general idle gate. A unit that has made
|
|
190
|
+
// meaningful progress within the idle window is not idle yet.
|
|
191
|
+
if (!stalledToolDetected && Date.now() - runtime.lastProgressAt < idleTimeoutMs)
|
|
192
|
+
return;
|
|
179
193
|
// Check if the agent is producing work on disk.
|
|
180
194
|
// Skip this when a stalled tool was just detected — filesystem changes
|
|
181
195
|
// from earlier in the task should not override the stall verdict (#2527).
|
|
@@ -30,7 +30,7 @@ import { playNotificationBell, sendDesktopNotification } from "./notifications.j
|
|
|
30
30
|
import { getBudgetAlertLevel, getNewBudgetAlertLevel, getBudgetEnforcementAction, resolveCompactionThresholdPercent, shouldRerootStepSessionForContext, } from "./auto-budget.js";
|
|
31
31
|
import { markToolStart as _markToolStart, markToolEnd as _markToolEnd, getOldestInFlightToolAgeMs as _getOldestInFlightToolAgeMs, clearInFlightTools, isToolInvocationError, isQueuedUserMessageSkip, isDeterministicPolicyError, } from "./auto-tool-tracking.js";
|
|
32
32
|
import { closeoutUnit } from "./auto-unit-closeout.js";
|
|
33
|
-
import { selectAndApplyModel, resolveModelId, clearToolBaseline } from "./auto-model-selection.js";
|
|
33
|
+
import { selectAndApplyModel, resolveModelId, clearToolBaseline, getToolBaselineSnapshot } from "./auto-model-selection.js";
|
|
34
34
|
import { resetRoutingHistory, recordOutcome } from "./routing-history.js";
|
|
35
35
|
import { resetHookState, runPreDispatchHooks, restoreHookState, clearPersistedHookState, } from "./post-unit-hooks.js";
|
|
36
36
|
import { runGSDDoctor, rebuildState } from "./doctor.js";
|
|
@@ -287,8 +287,24 @@ export function _synthesizePausedSessionRecoveryForTest(basePath, unitType, unit
|
|
|
287
287
|
function handlePausedSessionResumeRecovery(basePath, state, notify) {
|
|
288
288
|
if (!state.pausedSessionFile)
|
|
289
289
|
return { skippedReplay: false };
|
|
290
|
-
const pausedRecoveryUnitType = state.currentUnit?.type ?? state.pausedUnitType ??
|
|
291
|
-
const pausedRecoveryUnitId = state.currentUnit?.id ?? state.pausedUnitId ??
|
|
290
|
+
const pausedRecoveryUnitType = state.currentUnit?.type ?? state.pausedUnitType ?? null;
|
|
291
|
+
const pausedRecoveryUnitId = state.currentUnit?.id ?? state.pausedUnitId ?? null;
|
|
292
|
+
// When the paused-session metadata never captured the unit identity (the
|
|
293
|
+
// pause happened between units, or the worker died before currentUnit was
|
|
294
|
+
// set), we have nothing to verify against and nothing correct to target. A
|
|
295
|
+
// replay synthesized with an "unknown" unit re-injects an unbounded,
|
|
296
|
+
// mis-identified tool-call blob into the fresh resume context — exactly the
|
|
297
|
+
// thrash that turns one stuck unit into several. Disk state has already been
|
|
298
|
+
// rebuilt (rebuildState + doctor) before this runs, so skip the replay and
|
|
299
|
+
// let the normal dispatcher recompute the next unit from disk.
|
|
300
|
+
if (!pausedRecoveryUnitType || !pausedRecoveryUnitId) {
|
|
301
|
+
state.pausedSessionFile = null;
|
|
302
|
+
state.pausedUnitType = null;
|
|
303
|
+
state.pausedUnitId = null;
|
|
304
|
+
state.pendingCrashRecovery = null;
|
|
305
|
+
notify("Paused session had no recorded unit identity. Skipping tool-call replay and resuming from disk state.");
|
|
306
|
+
return { skippedReplay: true };
|
|
307
|
+
}
|
|
292
308
|
const completedPausedUnit = verifyExpectedArtifact(pausedRecoveryUnitType, pausedRecoveryUnitId, basePath);
|
|
293
309
|
if (completedPausedUnit) {
|
|
294
310
|
state.pausedSessionFile = null;
|
|
@@ -806,7 +822,7 @@ export async function cleanupAfterLoopExit(ctx) {
|
|
|
806
822
|
const preserveStepSurface = s.preserveStepSurfaceAfterLoopExit;
|
|
807
823
|
const preserveCompletionSurface = s.completionStopInProgress;
|
|
808
824
|
const preservePausedSurface = s.paused;
|
|
809
|
-
s.
|
|
825
|
+
s.clearCurrentUnit();
|
|
810
826
|
s.active = false;
|
|
811
827
|
deactivateGSD();
|
|
812
828
|
clearUnitTimeout();
|
|
@@ -831,12 +847,15 @@ export async function cleanupAfterLoopExit(ctx) {
|
|
|
831
847
|
// A transient provider-error pause intentionally leaves the paused badge
|
|
832
848
|
// visible so the user still has a resumable auto-mode signal on screen.
|
|
833
849
|
if (!s.paused) {
|
|
834
|
-
if (
|
|
835
|
-
s.preserveStepSurfaceAfterLoopExit = false;
|
|
836
|
-
}
|
|
837
|
-
else if (preserveCompletionSurface) {
|
|
850
|
+
if (preserveCompletionSurface) {
|
|
838
851
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
839
852
|
s.completionStopInProgress = false;
|
|
853
|
+
if (preserveStepSurface) {
|
|
854
|
+
s.preserveStepSurfaceAfterLoopExit = false;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
else if (preserveStepSurface) {
|
|
858
|
+
s.preserveStepSurfaceAfterLoopExit = false;
|
|
840
859
|
}
|
|
841
860
|
else {
|
|
842
861
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
@@ -1476,7 +1495,7 @@ export async function pauseAuto(ctx, _pi, _errorContext, options = {}) {
|
|
|
1476
1495
|
// Non-fatal — best-effort closeout on pause
|
|
1477
1496
|
logWarning("engine", `unit closeout on pause failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1478
1497
|
}
|
|
1479
|
-
s.
|
|
1498
|
+
s.clearCurrentUnit();
|
|
1480
1499
|
}
|
|
1481
1500
|
// Keep STATE.md aligned with the DB-backed state before releasing pause state.
|
|
1482
1501
|
// Without this, an interrupted deep run can leave STATE.md saying "no active
|
|
@@ -1637,7 +1656,10 @@ export function createWiredDispatchAdapter(ctx, pi, dispatchBasePath, session) {
|
|
|
1637
1656
|
const authMode = sessionProvider && typeof ctx.modelRegistry?.getProviderAuthMode === "function"
|
|
1638
1657
|
? ctx.modelRegistry.getProviderAuthMode(sessionProvider)
|
|
1639
1658
|
: undefined;
|
|
1640
|
-
|
|
1659
|
+
// Use baseline snapshot — same reason as phases.ts:runDispatch: the live
|
|
1660
|
+
// active set may be narrowed by the prior unit before selectAndApplyModel
|
|
1661
|
+
// restores it, causing false transport-preflight failures (#477 follow-up).
|
|
1662
|
+
const activeTools = getToolBaselineSnapshot(pi);
|
|
1641
1663
|
// Mirrors runDispatch: deep-planning keeps approval gates in plain chat
|
|
1642
1664
|
// because structured questions can be cancelled outside the chat turn on
|
|
1643
1665
|
// some transports.
|
|
@@ -1678,6 +1700,9 @@ export function createWiredDispatchAdapter(ctx, pi, dispatchBasePath, session) {
|
|
|
1678
1700
|
sessionContextWindow,
|
|
1679
1701
|
sessionProvider,
|
|
1680
1702
|
modelRegistry,
|
|
1703
|
+
activeTools,
|
|
1704
|
+
sessionAuthMode: authMode,
|
|
1705
|
+
sessionBaseUrl: ctx.model?.baseUrl,
|
|
1681
1706
|
});
|
|
1682
1707
|
if (action.action === "stop") {
|
|
1683
1708
|
if (session)
|
|
@@ -2605,7 +2630,7 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
|
|
|
2605
2630
|
s.stepMode = true;
|
|
2606
2631
|
s.cmdCtx = ctx;
|
|
2607
2632
|
s.autoStartTime = Date.now();
|
|
2608
|
-
s.
|
|
2633
|
+
s.clearCurrentUnit();
|
|
2609
2634
|
s.pendingQuickTasks = [];
|
|
2610
2635
|
}
|
|
2611
2636
|
// ADR-016 phase 2 / B2 (#5620): hook-trigger basePath transition. Treats
|
|
@@ -2619,23 +2644,23 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
|
|
|
2619
2644
|
}
|
|
2620
2645
|
const hookUnitType = `hook/${hookName}`;
|
|
2621
2646
|
const hookStartedAt = Date.now();
|
|
2622
|
-
s.
|
|
2647
|
+
s.setCurrentUnit({
|
|
2623
2648
|
type: triggerUnitType,
|
|
2624
2649
|
id: triggerUnitId,
|
|
2625
2650
|
startedAt: hookStartedAt,
|
|
2626
2651
|
workspaceRoot: s.basePath,
|
|
2627
|
-
};
|
|
2652
|
+
});
|
|
2628
2653
|
const result = await s.cmdCtx.newSession({ workspaceRoot: s.basePath });
|
|
2629
2654
|
if (result.cancelled) {
|
|
2630
2655
|
await stopAuto(ctx, pi);
|
|
2631
2656
|
return false;
|
|
2632
2657
|
}
|
|
2633
|
-
s.
|
|
2658
|
+
s.setCurrentUnit({
|
|
2634
2659
|
type: hookUnitType,
|
|
2635
2660
|
id: triggerUnitId,
|
|
2636
2661
|
startedAt: hookStartedAt,
|
|
2637
2662
|
workspaceRoot: s.basePath,
|
|
2638
|
-
};
|
|
2663
|
+
});
|
|
2639
2664
|
if (hookModel) {
|
|
2640
2665
|
const availableModels = ctx.modelRegistry.getAvailable();
|
|
2641
2666
|
const match = resolveModelId(hookModel, availableModels, ctx.model?.provider);
|
|
@@ -664,7 +664,7 @@ export function registerDbTools(pi) {
|
|
|
664
664
|
files: Type.Array(Type.String(), { description: "Array<string> of files likely touched; pass [\"path\"] or [], never a single string" }),
|
|
665
665
|
verify: Type.String({ description: "Verification command or block" }),
|
|
666
666
|
inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
|
|
667
|
-
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of
|
|
667
|
+
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
|
|
668
668
|
observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
|
|
669
669
|
}), { description: "Planned tasks for the slice" }),
|
|
670
670
|
// ── Enrichment metadata (optional — defaults to empty) ────────────
|
|
@@ -740,7 +740,7 @@ export function registerDbTools(pi) {
|
|
|
740
740
|
files: Type.Array(Type.String(), { description: "Array<string> of files likely touched; pass [\"path\"] or [], never a single string" }),
|
|
741
741
|
verify: Type.String({ description: "Verification command or block" }),
|
|
742
742
|
inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
|
|
743
|
-
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of
|
|
743
|
+
expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
|
|
744
744
|
observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
|
|
745
745
|
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
746
746
|
actorName: Type.Optional(Type.String({ description: "Caller-provided actor identity for the audit trail (e.g. 'executor-01', 'gsd-orchestrator')" })),
|
|
@@ -1069,7 +1069,7 @@ export function registerDbTools(pi) {
|
|
|
1069
1069
|
files: Type.Array(Type.String(), { description: "Files likely touched" }),
|
|
1070
1070
|
verify: Type.String({ description: "Verification command or block" }),
|
|
1071
1071
|
inputs: Type.Array(Type.String(), { description: "Input files or references" }),
|
|
1072
|
-
expectedOutput: Type.Array(Type.String(), { description: "
|
|
1072
|
+
expectedOutput: Type.Array(Type.String(), { description: "Files this task creates or overwrites" }),
|
|
1073
1073
|
}), { description: "Tasks to upsert (update existing or insert new)" }),
|
|
1074
1074
|
removedTaskIds: Type.Array(Type.String(), { description: "Task IDs to remove from the slice" }),
|
|
1075
1075
|
// Single-writer v3 audit trail (Stream 2): caller-provided actor identity + causation.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Registers GSD extension runtime hooks and token-saving tool policies.
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
3
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
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
|
-
import { buildMilestoneFileName, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
9
|
+
import { buildMilestoneFileName, clearPathCache, milestonesDir, resolveMilestonePath, resolveSliceFile, resolveSlicePath } from "../paths.js";
|
|
10
10
|
import { canonicalToolName, clearDiscussionFlowState, isDepthConfirmationAnswer, isMilestoneDepthVerified, isQueuePhaseActive, markApprovalGateVerified, markDepthVerified, resetWriteGateState, shouldBlockContextWrite, shouldBlockPlanningUnit, shouldBlockQueueExecution, shouldBlockWorktreeWrite, isGateQuestionId, setPendingGate, clearPendingGate, getPendingGate, shouldBlockPendingGate, shouldBlockPendingGateBash, extractDepthVerificationMilestoneId } from "./write-gate.js";
|
|
11
11
|
import { resolveManifest } from "../unit-context-manifest.js";
|
|
12
12
|
import { isBlockedStateFile, isBashWriteToStateFile, BLOCKED_WRITE_ERROR } from "../write-intercept.js";
|
|
13
13
|
import { loadFile, saveFile, formatContinue } from "../files.js";
|
|
14
|
-
import { clearToolInvocationError, getAutoRuntimeSnapshot, isAutoActive, isAutoCompletionStopInProgress, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError } from "../auto-runtime-state.js";
|
|
14
|
+
import { clearToolInvocationError, getAutoRuntimeSnapshot, getSourceObservationStore, isAutoActive, isAutoCompletionStopInProgress, isAutoPaused, markToolEnd, markToolStart, recordToolInvocationError, } from "../auto-runtime-state.js";
|
|
15
15
|
import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
16
16
|
import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
|
|
17
17
|
import { saveActivityLog } from "../activity-log.js";
|
|
@@ -31,6 +31,7 @@ import { registerPlanMilestoneSchemaRecovery } from "./plan-milestone-schema-rec
|
|
|
31
31
|
import { AUTO_UNIT_SCOPED_TOOLS, RUN_UAT_BROWSER_TOOL_NAMES, isWorkflowAliasTool } from "../auto-unit-tool-scope.js";
|
|
32
32
|
import { filterToolsForProvider } from "../model-router.js";
|
|
33
33
|
import { RUN_UAT_READ_ONLY_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES } from "../tool-presentation-plan.js";
|
|
34
|
+
import { injectSourceContextBlockIntoPayload, supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
34
35
|
let approvalQuestionAbortInFlight = false;
|
|
35
36
|
async function loadWelcomeScreenModule() {
|
|
36
37
|
const candidates = [];
|
|
@@ -210,7 +211,12 @@ export function buildRunUatGsdToolSet(activeToolNames, registeredToolNames = act
|
|
|
210
211
|
"subagent",
|
|
211
212
|
...RUN_UAT_BROWSER_TOOL_NAMES,
|
|
212
213
|
]);
|
|
213
|
-
|
|
214
|
+
const resolved = [...new Set(scoped)];
|
|
215
|
+
const unresolved = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((tool) => !resolved.some((name) => name === tool || (name.startsWith("mcp__") && name.endsWith(`__${tool}`))));
|
|
216
|
+
if (unresolved.length > 0) {
|
|
217
|
+
safetyLogWarning("bootstrap", `buildRunUatGsdToolSet: required run-uat workflow tool(s) not found in active/registered surface: ${unresolved.join(", ")}. Session may lack gsd-workflow MCP connection.`);
|
|
218
|
+
}
|
|
219
|
+
return resolved;
|
|
214
220
|
}
|
|
215
221
|
export function buildMinimalGsdWorkflowToolSet(activeToolNames, registeredToolNames = activeToolNames) {
|
|
216
222
|
const autoBaseTools = new Set(MINIMAL_AUTO_BASE_TOOL_NAMES);
|
|
@@ -365,6 +371,50 @@ function deferApprovalGate(gateId, basePath) {
|
|
|
365
371
|
function contextBasePath(ctx) {
|
|
366
372
|
return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
|
|
367
373
|
}
|
|
374
|
+
function beginSourceObservationStoreForCurrentUnit(ctx) {
|
|
375
|
+
if (!isAutoActive())
|
|
376
|
+
return null;
|
|
377
|
+
const dash = getAutoRuntimeSnapshot();
|
|
378
|
+
if (!dash.currentUnit)
|
|
379
|
+
return null;
|
|
380
|
+
if (!supportsSourceObservationsForUnit(dash.currentUnit.type))
|
|
381
|
+
return null;
|
|
382
|
+
const store = getSourceObservationStore();
|
|
383
|
+
store.beginUnit({
|
|
384
|
+
unitType: dash.currentUnit.type,
|
|
385
|
+
unitId: dash.currentUnit.id,
|
|
386
|
+
startedAt: dash.currentUnit.startedAt,
|
|
387
|
+
basePath: dash.currentUnit.workspaceRoot ?? (dash.basePath || contextBasePath(ctx)),
|
|
388
|
+
});
|
|
389
|
+
return store;
|
|
390
|
+
}
|
|
391
|
+
function refreshSourceObservationAfterMutation(canonicalName, input, ctx) {
|
|
392
|
+
if (canonicalName !== "edit" && canonicalName !== "write")
|
|
393
|
+
return;
|
|
394
|
+
if (!input || typeof input !== "object")
|
|
395
|
+
return;
|
|
396
|
+
const store = beginSourceObservationStoreForCurrentUnit(ctx);
|
|
397
|
+
if (!store)
|
|
398
|
+
return;
|
|
399
|
+
store.observeMutation(input);
|
|
400
|
+
}
|
|
401
|
+
function clearSourceObservationsAfterShell(canonicalName) {
|
|
402
|
+
if (!isAutoActive())
|
|
403
|
+
return;
|
|
404
|
+
if (!isShellExecutionTool(canonicalName))
|
|
405
|
+
return;
|
|
406
|
+
const dash = getAutoRuntimeSnapshot();
|
|
407
|
+
if (!dash.currentUnit || !supportsSourceObservationsForUnit(dash.currentUnit.type))
|
|
408
|
+
return;
|
|
409
|
+
getSourceObservationStore().clear();
|
|
410
|
+
}
|
|
411
|
+
function isShellExecutionTool(canonicalName) {
|
|
412
|
+
return canonicalName === "bash" ||
|
|
413
|
+
canonicalName === "bg_shell" ||
|
|
414
|
+
canonicalName === "async_bash" ||
|
|
415
|
+
canonicalName === "shell" ||
|
|
416
|
+
canonicalName === "powershell";
|
|
417
|
+
}
|
|
368
418
|
function activateDeferredApprovalGate(basePath) {
|
|
369
419
|
if (deferredApprovalGate?.basePath !== basePath)
|
|
370
420
|
return;
|
|
@@ -387,6 +437,79 @@ function isContextDraftSummarySave(toolName, input) {
|
|
|
387
437
|
return false;
|
|
388
438
|
return input.artifact_type === "CONTEXT-DRAFT";
|
|
389
439
|
}
|
|
440
|
+
function selectedAnswerLabel(selected) {
|
|
441
|
+
if (Array.isArray(selected))
|
|
442
|
+
return selected.map(String).join(", ");
|
|
443
|
+
if (selected == null)
|
|
444
|
+
return "";
|
|
445
|
+
return String(selected);
|
|
446
|
+
}
|
|
447
|
+
function formatQuestionExchange(questions, answers) {
|
|
448
|
+
const lines = [];
|
|
449
|
+
for (const question of questions) {
|
|
450
|
+
lines.push(`### ${question.header ?? "Question"}`, "", question.question ?? "");
|
|
451
|
+
if (Array.isArray(question.options)) {
|
|
452
|
+
lines.push("");
|
|
453
|
+
for (const opt of question.options) {
|
|
454
|
+
lines.push(`- **${opt.label ?? ""}** — ${opt.description ?? ""}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const answer = question.id ? answers?.[question.id] : undefined;
|
|
458
|
+
if (answer) {
|
|
459
|
+
lines.push("");
|
|
460
|
+
const selected = selectedAnswerLabel(answer.selected);
|
|
461
|
+
if (selected)
|
|
462
|
+
lines.push(`**Selected:** ${selected}`);
|
|
463
|
+
if (answer.notes)
|
|
464
|
+
lines.push(`**Notes:** ${String(answer.notes)}`);
|
|
465
|
+
}
|
|
466
|
+
lines.push("");
|
|
467
|
+
}
|
|
468
|
+
return lines.join("\n");
|
|
469
|
+
}
|
|
470
|
+
async function ensureMilestoneShell(basePath, milestoneId) {
|
|
471
|
+
const milestoneDir = resolveMilestonePath(basePath, milestoneId)
|
|
472
|
+
?? join(milestonesDir(basePath), milestoneId);
|
|
473
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
474
|
+
clearPathCache();
|
|
475
|
+
try {
|
|
476
|
+
const { ensureDbOpen } = await import("./dynamic-tools.js");
|
|
477
|
+
if (await ensureDbOpen(basePath)) {
|
|
478
|
+
const { getMilestone, insertMilestone } = await import("../gsd-db.js");
|
|
479
|
+
if (!getMilestone(milestoneId)) {
|
|
480
|
+
insertMilestone({
|
|
481
|
+
id: milestoneId,
|
|
482
|
+
title: `New milestone ${milestoneId}`,
|
|
483
|
+
status: "queued",
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
catch (err) {
|
|
489
|
+
safetyLogWarning("guided", `failed to persist milestone shell for ${milestoneId}: ${err.message}`);
|
|
490
|
+
}
|
|
491
|
+
return milestoneDir;
|
|
492
|
+
}
|
|
493
|
+
async function saveDiscussionQuestionRound(basePath, milestoneId, questions, details) {
|
|
494
|
+
const milestoneDir = await ensureMilestoneShell(basePath, milestoneId);
|
|
495
|
+
const answers = details?.response?.answers;
|
|
496
|
+
const timestamp = new Date().toISOString();
|
|
497
|
+
const exchange = formatQuestionExchange(questions, answers);
|
|
498
|
+
const discussionPath = join(milestoneDir, buildMilestoneFileName(milestoneId, "DISCUSSION"));
|
|
499
|
+
const existingDiscussion = await loadFile(discussionPath) ?? `# ${milestoneId} Discussion Log\n\n`;
|
|
500
|
+
await saveFile(discussionPath, `${existingDiscussion}## Exchange — ${timestamp}\n\n${exchange}---\n\n`);
|
|
501
|
+
const draftPath = join(milestoneDir, buildMilestoneFileName(milestoneId, "CONTEXT-DRAFT"));
|
|
502
|
+
const existingDraft = await loadFile(draftPath);
|
|
503
|
+
const draftHeader = existingDraft
|
|
504
|
+
?? [
|
|
505
|
+
`# ${milestoneId}: New milestone ${milestoneId}`,
|
|
506
|
+
"",
|
|
507
|
+
"This draft was captured automatically from structured question responses.",
|
|
508
|
+
"Use it so `/gsd` can resume the in-flight milestone discussion.",
|
|
509
|
+
"",
|
|
510
|
+
].join("\n");
|
|
511
|
+
await saveFile(draftPath, `${draftHeader.trimEnd()}\n\n## Captured Question Round — ${timestamp}\n\n${exchange}`);
|
|
512
|
+
}
|
|
390
513
|
function withDepthGateDisplayReason(result, displayReason = "Depth confirmation is waiting for your answer.") {
|
|
391
514
|
if (!result.block)
|
|
392
515
|
return result;
|
|
@@ -463,6 +586,18 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
463
586
|
if (isAutoActive() || preserveCloseoutSurface) {
|
|
464
587
|
ctx.ui.setWidget("gsd-health", undefined);
|
|
465
588
|
}
|
|
589
|
+
// Cold start after /quit relaunches with cwd at the project root. When
|
|
590
|
+
// auto-mode is neither active nor paused (its own resume path re-enters the
|
|
591
|
+
// worktree with a lease check — auto.ts:3032), proactively chdir back into
|
|
592
|
+
// the active milestone's worktree so subsequent work isn't stranded at the
|
|
593
|
+
// root. Best-effort and a no-op when already inside a worktree.
|
|
594
|
+
if (!isAutoActive() && !isAutoPaused() && !preserveCloseoutSurface) {
|
|
595
|
+
try {
|
|
596
|
+
const { reenterActiveWorktreeIfNeeded } = await import("../worktree-reentry.js");
|
|
597
|
+
await reenterActiveWorktreeIfNeeded(basePath);
|
|
598
|
+
}
|
|
599
|
+
catch { /* non-fatal */ }
|
|
600
|
+
}
|
|
466
601
|
});
|
|
467
602
|
pi.on("session_switch", async (_event, ctx) => {
|
|
468
603
|
const basePath = contextBasePath(ctx);
|
|
@@ -901,6 +1036,17 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
901
1036
|
if (isAutoActive() && typeof event.toolCallId === "string") {
|
|
902
1037
|
markToolEnd(event.toolCallId);
|
|
903
1038
|
}
|
|
1039
|
+
const toolName = canonicalToolName(event.toolName);
|
|
1040
|
+
if (isAutoActive() && toolName === "read" && !event.isError) {
|
|
1041
|
+
const store = beginSourceObservationStoreForCurrentUnit(ctx);
|
|
1042
|
+
if (store) {
|
|
1043
|
+
store.observeRead(event.input);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
if (!event.isError) {
|
|
1047
|
+
refreshSourceObservationAfterMutation(toolName, event.input, ctx);
|
|
1048
|
+
clearSourceObservationsAfterShell(toolName);
|
|
1049
|
+
}
|
|
904
1050
|
if (isAutoActive() && event.isError) {
|
|
905
1051
|
const resultPayload = ("result" in event ? event.result : undefined);
|
|
906
1052
|
const errorText = typeof resultPayload === "string"
|
|
@@ -917,12 +1063,10 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
917
1063
|
else if (isAutoActive()) {
|
|
918
1064
|
clearToolInvocationError();
|
|
919
1065
|
}
|
|
920
|
-
const toolName = canonicalToolName(event.toolName);
|
|
921
1066
|
if (toolName !== "ask_user_questions")
|
|
922
1067
|
return;
|
|
923
1068
|
const basePath = contextBasePath(ctx);
|
|
924
1069
|
const milestoneId = await getDiscussionMilestoneIdFor(basePath);
|
|
925
|
-
const queueActive = isQueuePhaseActive(basePath);
|
|
926
1070
|
const details = event.details;
|
|
927
1071
|
// ── Discussion gate enforcement: handle gate question responses ──
|
|
928
1072
|
// If the result is cancelled or has no response, the pending gate stays active
|
|
@@ -995,38 +1139,9 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
995
1139
|
break;
|
|
996
1140
|
}
|
|
997
1141
|
}
|
|
998
|
-
if (!milestoneId && !queueActive)
|
|
999
|
-
return;
|
|
1000
1142
|
if (!milestoneId)
|
|
1001
1143
|
return;
|
|
1002
|
-
|
|
1003
|
-
if (!milestoneDir)
|
|
1004
|
-
return;
|
|
1005
|
-
const discussionPath = join(milestoneDir, buildMilestoneFileName(milestoneId, "DISCUSSION"));
|
|
1006
|
-
const timestamp = new Date().toISOString();
|
|
1007
|
-
const lines = [`## Exchange — ${timestamp}`, ""];
|
|
1008
|
-
for (const question of questions) {
|
|
1009
|
-
lines.push(`### ${question.header ?? "Question"}`, "", question.question ?? "");
|
|
1010
|
-
if (Array.isArray(question.options)) {
|
|
1011
|
-
lines.push("");
|
|
1012
|
-
for (const opt of question.options) {
|
|
1013
|
-
lines.push(`- **${opt.label}** — ${opt.description ?? ""}`);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
const answer = details.response?.answers?.[question.id];
|
|
1017
|
-
if (answer) {
|
|
1018
|
-
lines.push("");
|
|
1019
|
-
const selected = Array.isArray(answer.selected) ? answer.selected.join(", ") : answer.selected;
|
|
1020
|
-
lines.push(`**Selected:** ${selected}`);
|
|
1021
|
-
if (answer.notes) {
|
|
1022
|
-
lines.push(`**Notes:** ${answer.notes}`);
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
lines.push("");
|
|
1026
|
-
}
|
|
1027
|
-
lines.push("---", "");
|
|
1028
|
-
const existing = await loadFile(discussionPath) ?? `# ${milestoneId} Discussion Log\n\n`;
|
|
1029
|
-
await saveFile(discussionPath, existing + lines.join("\n"));
|
|
1144
|
+
await saveDiscussionQuestionRound(basePath, milestoneId, questions, details);
|
|
1030
1145
|
});
|
|
1031
1146
|
pi.on("tool_execution_start", async (event, ctx) => {
|
|
1032
1147
|
const basePath = contextBasePath(ctx);
|
|
@@ -1078,51 +1193,51 @@ export function registerHooks(pi, ecosystemHandlers) {
|
|
|
1078
1193
|
const payload = event.payload;
|
|
1079
1194
|
if (!payload || typeof payload !== "object")
|
|
1080
1195
|
return;
|
|
1081
|
-
// ──
|
|
1082
|
-
//
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
if (Array.isArray(messages)) {
|
|
1096
|
-
payload.messages = mask(messages);
|
|
1097
|
-
}
|
|
1196
|
+
// ── Context Management ──────────────────────────────────────────────
|
|
1197
|
+
// Load preferences once for both masking and truncation.
|
|
1198
|
+
try {
|
|
1199
|
+
const { loadEffectiveGSDPreferences } = await import("../preferences.js");
|
|
1200
|
+
const { createObservationMask, createResponsesInputObservationMask, truncateContextResultMessages, truncateResponsesInputResultItems, } = await import("../context-masker.js");
|
|
1201
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
1202
|
+
const cmConfig = prefs?.preferences.context_management;
|
|
1203
|
+
// Observation masking: replace old tool results with placeholders.
|
|
1204
|
+
// Only active during auto-mode when context_management.observation_masking is enabled.
|
|
1205
|
+
if (isAutoActive() && cmConfig?.observation_masking !== false) {
|
|
1206
|
+
const keepTurns = cmConfig?.observation_mask_turns ?? 8;
|
|
1207
|
+
const messages = payload.messages;
|
|
1208
|
+
if (Array.isArray(messages)) {
|
|
1209
|
+
payload.messages = createObservationMask(keepTurns)(messages);
|
|
1098
1210
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1211
|
+
const input = payload.input;
|
|
1212
|
+
if (Array.isArray(input)) {
|
|
1213
|
+
payload.input = createResponsesInputObservationMask(keepTurns)(input);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
// Tool result truncation: cap individual tool result content length.
|
|
1217
|
+
// Applies in ALL modes (auto + interactive) to prevent context bloat.
|
|
1218
|
+
// In pi-ai format, toolResult messages have role: "toolResult" and content: TextContent[].
|
|
1219
|
+
// Creates new objects to avoid mutating shared conversation state.
|
|
1220
|
+
const maxChars = cmConfig?.tool_result_max_chars ?? 800;
|
|
1221
|
+
const msgs = payload.messages;
|
|
1222
|
+
if (Array.isArray(msgs)) {
|
|
1223
|
+
payload.messages = truncateContextResultMessages(msgs, maxChars);
|
|
1224
|
+
}
|
|
1225
|
+
const input = payload.input;
|
|
1226
|
+
if (Array.isArray(input)) {
|
|
1227
|
+
payload.input = truncateResponsesInputResultItems(input, maxChars);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
catch { /* non-fatal */ }
|
|
1231
|
+
try {
|
|
1232
|
+
if (isAutoActive()) {
|
|
1233
|
+
const sourceContextBlock = getSourceObservationStore().renderActiveBlock();
|
|
1234
|
+
if (sourceContextBlock) {
|
|
1235
|
+
const nextPayload = injectSourceContextBlockIntoPayload(payload, sourceContextBlock);
|
|
1236
|
+
Object.assign(payload, nextPayload);
|
|
1122
1237
|
}
|
|
1123
1238
|
}
|
|
1124
|
-
catch { /* non-fatal */ }
|
|
1125
1239
|
}
|
|
1240
|
+
catch { /* non-fatal */ }
|
|
1126
1241
|
// ── Service Tier ────────────────────────────────────────────────────
|
|
1127
1242
|
const modelId = event.model?.id;
|
|
1128
1243
|
if (!modelId)
|
|
@@ -56,7 +56,7 @@ export const BUNDLED_SKILL_TRIGGERS = [
|
|
|
56
56
|
{ trigger: "Core Web Vitals — fix LCP, CLS, INP; layout shifts; page experience optimization", skill: "core-web-vitals" },
|
|
57
57
|
{ trigger: "GitHub Actions CI/CD — write, run, and debug workflow files; live syntax and run monitoring", skill: "github-workflows" },
|
|
58
58
|
{ trigger: "Comprehensive web quality audit — performance, accessibility, SEO, and best-practices (Lighthouse-style)", skill: "web-quality-audit" },
|
|
59
|
-
{ trigger: "gsd-browser
|
|
59
|
+
{ trigger: "gsd-browser opt-in and External MCP UAT — screenshots, assertions, console/network diagnostics", skill: "gsd-browser" },
|
|
60
60
|
{ trigger: "Browser automation — open sites, fill forms, click, screenshot, scrape, or test web apps programmatically", skill: "agent-browser" },
|
|
61
61
|
{ trigger: "Review UI code for Web Interface Guidelines compliance — UX, design, and accessibility patterns", skill: "web-design-guidelines" },
|
|
62
62
|
{ trigger: "UI/UX patterns reference — animations, CSS, typography, prefetching, icons (file:line findings)", skill: "userinterface-wiki" },
|