@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
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* auto-session-encapsulation.test.ts enforce that auto.ts has no module-level
|
|
18
18
|
* `let` or `var` declarations.
|
|
19
19
|
*/
|
|
20
|
+
import { SourceObservationStore, supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
20
21
|
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
21
22
|
import { normalizeRealPath } from "../paths.js";
|
|
22
23
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
@@ -76,6 +77,7 @@ export class AutoSession {
|
|
|
76
77
|
currentTurnId = null;
|
|
77
78
|
currentUnitRouting = null;
|
|
78
79
|
currentMilestoneId = null;
|
|
80
|
+
sourceObservations = new SourceObservationStore();
|
|
79
81
|
// ── Model state ──────────────────────────────────────────────────────────
|
|
80
82
|
autoModeStartModel = null;
|
|
81
83
|
/** Explicit /gsd model pin captured at bootstrap (session-scoped policy override). */
|
|
@@ -94,6 +96,7 @@ export class AutoSession {
|
|
|
94
96
|
verificationRetryCount = new Map();
|
|
95
97
|
verificationRetryFailureHashes = new Map();
|
|
96
98
|
exhaustedVerificationUnits = new Set();
|
|
99
|
+
zeroToolRetryCount = new Map();
|
|
97
100
|
pausedSessionFile = null;
|
|
98
101
|
pausedUnitType = null;
|
|
99
102
|
pausedUnitId = null;
|
|
@@ -195,6 +198,23 @@ export class AutoSession {
|
|
|
195
198
|
this.unitDispatchCount.clear();
|
|
196
199
|
this.unitLifetimeDispatches.clear();
|
|
197
200
|
}
|
|
201
|
+
setCurrentUnit(unit) {
|
|
202
|
+
this.currentUnit = unit;
|
|
203
|
+
if (!supportsSourceObservationsForUnit(unit.type)) {
|
|
204
|
+
this.sourceObservations.clear();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
this.sourceObservations.beginUnit({
|
|
208
|
+
unitType: unit.type,
|
|
209
|
+
unitId: unit.id,
|
|
210
|
+
startedAt: unit.startedAt,
|
|
211
|
+
basePath: unit.workspaceRoot ?? this.basePath,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
clearCurrentUnit() {
|
|
215
|
+
this.currentUnit = null;
|
|
216
|
+
this.sourceObservations.clear();
|
|
217
|
+
}
|
|
198
218
|
get lockBasePath() {
|
|
199
219
|
return resolveWorktreeProjectRoot(this.basePath, this.originalBasePath);
|
|
200
220
|
}
|
|
@@ -245,7 +265,7 @@ export class AutoSession {
|
|
|
245
265
|
this.unitLifetimeDispatches.clear();
|
|
246
266
|
this.unitRecoveryCount.clear();
|
|
247
267
|
// Unit
|
|
248
|
-
this.
|
|
268
|
+
this.clearCurrentUnit();
|
|
249
269
|
this.currentTraceId = null;
|
|
250
270
|
this.currentTurnId = null;
|
|
251
271
|
this.currentUnitRouting = null;
|
|
@@ -266,6 +286,7 @@ export class AutoSession {
|
|
|
266
286
|
this.verificationRetryCount.clear();
|
|
267
287
|
this.verificationRetryFailureHashes.clear();
|
|
268
288
|
this.exhaustedVerificationUnits.clear();
|
|
289
|
+
this.zeroToolRetryCount.clear();
|
|
269
290
|
this.pausedSessionFile = null;
|
|
270
291
|
this.pausedUnitType = null;
|
|
271
292
|
this.pausedUnitId = null;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Declarative auto-mode dispatch rules and dispatch resolver.
|
|
3
3
|
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getUatBrowserToolSupportError } from "./uat-policy.js";
|
|
5
|
+
import { isDbAvailable, getMilestoneSlices, getPendingGatesForTurn, markPendingGatesOmittedForTurn, getMilestone, insertArtifact, insertAssessment, setSliceSketchFlag, transaction, getAssessment, } from "./gsd-db.js";
|
|
5
6
|
import { isClosedStatus } from "./status-guards.js";
|
|
6
7
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
7
8
|
import { gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveTaskFile, relTaskFile, relSliceFile, buildMilestoneFileName, buildSliceFileName, buildTaskFileName, gsdProjectionRoot, } from "./paths.js";
|
|
@@ -12,7 +13,7 @@ import { logWarning, logError } from "./workflow-logger.js";
|
|
|
12
13
|
import { dirname, join } from "node:path";
|
|
13
14
|
import { hasImplementationArtifacts } from "./milestone-implementation-evidence.js";
|
|
14
15
|
import { buildDiscussMilestonePrompt, buildDiscussProjectPrompt, buildDiscussRequirementsPrompt, buildResearchDecisionPrompt, buildResearchProjectPrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
15
|
-
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
16
|
+
import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit } from "./preferences-models.js";
|
|
16
17
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
17
18
|
import { selectReactiveDispatchBatch } from "./uok/execution-graph.js";
|
|
18
19
|
import { getMilestonePipelineVariant } from "./milestone-scope-classifier.js";
|
|
@@ -21,6 +22,7 @@ import { isAutoActive } from "./auto.js";
|
|
|
21
22
|
import { markDepthVerified } from "./bootstrap/write-gate.js";
|
|
22
23
|
import { ensureWorkflowPreferencesCaptured } from "./planning-depth.js";
|
|
23
24
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
25
|
+
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, } from "./workflow-mcp.js";
|
|
24
26
|
import { PROJECT_RESEARCH_INFLIGHT_MARKER, } from "./project-research-policy.js";
|
|
25
27
|
import { isWorkflowPrefsCaptured, resolveDeepProjectSetupState, } from "./deep-project-setup-policy.js";
|
|
26
28
|
import { annotateBackgroundable } from "./delegation-policy.js";
|
|
@@ -249,6 +251,43 @@ export function findMissingSummaries(basePath, mid) {
|
|
|
249
251
|
})
|
|
250
252
|
.map(s => s.id);
|
|
251
253
|
}
|
|
254
|
+
function stringField(row, key) {
|
|
255
|
+
const value = row?.[key];
|
|
256
|
+
return typeof value === "string" ? value : null;
|
|
257
|
+
}
|
|
258
|
+
function stripGsdPrefix(path) {
|
|
259
|
+
return path.startsWith(".gsd/") ? path.slice(".gsd/".length) : path;
|
|
260
|
+
}
|
|
261
|
+
function persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content) {
|
|
262
|
+
const artifactPath = stripGsdPrefix(assessmentRelPath);
|
|
263
|
+
const existingAssessment = getAssessment(assessmentRelPath) ??
|
|
264
|
+
getAssessment(artifactPath);
|
|
265
|
+
const scope = stringField(existingAssessment, "scope") ?? "run-uat";
|
|
266
|
+
const status = stringField(existingAssessment, "status") ??
|
|
267
|
+
extractVerdict(content)?.toLowerCase() ??
|
|
268
|
+
"unknown";
|
|
269
|
+
transaction(() => {
|
|
270
|
+
insertArtifact({
|
|
271
|
+
path: artifactPath,
|
|
272
|
+
artifact_type: "ASSESSMENT",
|
|
273
|
+
milestone_id: mid,
|
|
274
|
+
slice_id: sliceId,
|
|
275
|
+
task_id: null,
|
|
276
|
+
full_content: content,
|
|
277
|
+
});
|
|
278
|
+
if (!getAssessment(assessmentRelPath)) {
|
|
279
|
+
insertAssessment({
|
|
280
|
+
path: assessmentRelPath,
|
|
281
|
+
milestoneId: mid,
|
|
282
|
+
sliceId,
|
|
283
|
+
taskId: null,
|
|
284
|
+
status,
|
|
285
|
+
scope,
|
|
286
|
+
fullContent: content,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
252
291
|
function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
253
292
|
const completedSliceIds = new Set();
|
|
254
293
|
if (isDbAvailable()) {
|
|
@@ -280,11 +319,12 @@ function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
|
280
319
|
const slicePath = resolveSlicePath(basePath, mid, sliceId);
|
|
281
320
|
const assessmentPath = resolveSliceFile(basePath, mid, sliceId, "ASSESSMENT")
|
|
282
321
|
?? (slicePath ? join(slicePath, buildSliceFileName(sliceId, "ASSESSMENT")) : null);
|
|
283
|
-
if (!assessmentPath
|
|
322
|
+
if (!assessmentPath)
|
|
284
323
|
continue;
|
|
285
|
-
|
|
324
|
+
const assessmentRelPath = relSliceFile(basePath, mid, sliceId, "ASSESSMENT");
|
|
286
325
|
const now = new Date().toISOString();
|
|
287
|
-
const
|
|
326
|
+
const didCreateAssessment = !existsSync(assessmentPath);
|
|
327
|
+
const content = didCreateAssessment ? [
|
|
288
328
|
"---",
|
|
289
329
|
`sliceId: ${sliceId}`,
|
|
290
330
|
"verdict: PASS",
|
|
@@ -296,8 +336,19 @@ function backfillMissingAssessmentsFromSummaries(basePath, mid) {
|
|
|
296
336
|
"Auto-created during milestone validation because this completed slice had a SUMMARY but no ASSESSMENT artifact.",
|
|
297
337
|
"No additional reassessment changes were detected in this backfill step.",
|
|
298
338
|
"",
|
|
299
|
-
].join("\n");
|
|
300
|
-
|
|
339
|
+
].join("\n") : readFileSync(assessmentPath, "utf-8");
|
|
340
|
+
if (isDbAvailable()) {
|
|
341
|
+
try {
|
|
342
|
+
persistSliceAssessmentBackfill(assessmentRelPath, mid, sliceId, content);
|
|
343
|
+
}
|
|
344
|
+
catch (err) {
|
|
345
|
+
logWarning("dispatch", `failed to backfill assessment DB rows for ${mid}/${sliceId}: ${err.message}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (didCreateAssessment) {
|
|
349
|
+
mkdirSync(dirname(assessmentPath), { recursive: true });
|
|
350
|
+
writeFileSync(assessmentPath, content, "utf-8");
|
|
351
|
+
}
|
|
301
352
|
}
|
|
302
353
|
}
|
|
303
354
|
// ─── Rewrite Circuit Breaker ──────────────────────────────────────────────
|
|
@@ -467,11 +518,27 @@ export const DISPATCH_RULES = [
|
|
|
467
518
|
},
|
|
468
519
|
{
|
|
469
520
|
name: "run-uat (post-completion)",
|
|
470
|
-
match: async ({ state, mid, basePath, prefs }) => {
|
|
521
|
+
match: async ({ state, mid, basePath, prefs, sessionProvider, sessionAuthMode, activeTools, sessionBaseUrl }) => {
|
|
471
522
|
const needsRunUat = await checkNeedsRunUat(basePath, mid, state, prefs);
|
|
472
523
|
if (!needsRunUat)
|
|
473
524
|
return null;
|
|
474
525
|
const { sliceId, uatType } = needsRunUat;
|
|
526
|
+
// Transport preflight: verify required MCP tools are actually connected
|
|
527
|
+
// before consuming a retry attempt. Fixes tool-starved sessions burning
|
|
528
|
+
// all MAX_UAT_ATTEMPTS before stopping (#477).
|
|
529
|
+
const transportError = getWorkflowTransportSupportError(sessionProvider, getRequiredWorkflowToolsForAutoUnit("run-uat"), { projectRoot: basePath, surface: "auto-mode", unitType: "run-uat", authMode: sessionAuthMode, baseUrl: sessionBaseUrl, activeTools });
|
|
530
|
+
if (transportError) {
|
|
531
|
+
return { action: "stop", reason: transportError, level: "warning" };
|
|
532
|
+
}
|
|
533
|
+
const browserToolError = getUatBrowserToolSupportError({
|
|
534
|
+
uatType,
|
|
535
|
+
activeTools,
|
|
536
|
+
milestoneId: mid,
|
|
537
|
+
sliceId,
|
|
538
|
+
});
|
|
539
|
+
if (browserToolError) {
|
|
540
|
+
return { action: "stop", reason: browserToolError, level: "warning" };
|
|
541
|
+
}
|
|
475
542
|
// Cap run-uat dispatch attempts to prevent infinite replay (#3624).
|
|
476
543
|
// Check before incrementing so an exhausted counter cannot create a
|
|
477
544
|
// no-progress skip loop that starves later dispatch rules.
|
|
@@ -877,7 +944,7 @@ export const DISPATCH_RULES = [
|
|
|
877
944
|
action: "dispatch",
|
|
878
945
|
unitType: "research-slice",
|
|
879
946
|
unitId: `${mid}/parallel-research`,
|
|
880
|
-
prompt: await buildParallelResearchSlicesPrompt(mid, midTitle, researchReadySlices, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary),
|
|
947
|
+
prompt: await buildParallelResearchSlicesPrompt(mid, midTitle, researchReadySlices, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary, resolveThinkingLevelForUnit("subagent")),
|
|
881
948
|
};
|
|
882
949
|
},
|
|
883
950
|
},
|
|
@@ -1029,17 +1096,17 @@ export const DISPATCH_RULES = [
|
|
|
1029
1096
|
// Gate evaluation is opt-in via preferences
|
|
1030
1097
|
const gateConfig = prefs?.gate_evaluation;
|
|
1031
1098
|
if (!gateConfig?.enabled) {
|
|
1032
|
-
|
|
1099
|
+
markPendingGatesOmittedForTurn(mid, sid, "gate-evaluate");
|
|
1033
1100
|
return { action: "skip" };
|
|
1034
1101
|
}
|
|
1035
|
-
const pending =
|
|
1102
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
1036
1103
|
if (pending.length === 0)
|
|
1037
1104
|
return { action: "skip" };
|
|
1038
1105
|
return {
|
|
1039
1106
|
action: "dispatch",
|
|
1040
1107
|
unitType: "gate-evaluate",
|
|
1041
1108
|
unitId: `${mid}/${sid}/gates+${pending.map(g => g.gate_id).join(",")}`,
|
|
1042
|
-
prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary),
|
|
1109
|
+
prompt: await buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, basePath, resolveModelWithFallbacksForUnit("subagent")?.primary, resolveThinkingLevelForUnit("subagent")),
|
|
1043
1110
|
};
|
|
1044
1111
|
},
|
|
1045
1112
|
},
|
|
@@ -1082,6 +1149,7 @@ export const DISPATCH_RULES = [
|
|
|
1082
1149
|
return null;
|
|
1083
1150
|
const maxParallel = reactiveConfig?.max_parallel ?? 2;
|
|
1084
1151
|
const subagentModel = reactiveConfig?.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
|
|
1152
|
+
const subagentThinking = resolveThinkingLevelForUnit("subagent");
|
|
1085
1153
|
// Default-on safety threshold: only activate reactive dispatch when at
|
|
1086
1154
|
// least N tasks are ready. Users who explicitly enabled reactive_execution
|
|
1087
1155
|
// keep the legacy threshold of 2 (matches the prior "any parallelism is
|
|
@@ -1139,7 +1207,7 @@ export const DISPATCH_RULES = [
|
|
|
1139
1207
|
action: "dispatch",
|
|
1140
1208
|
unitType: "reactive-execute",
|
|
1141
1209
|
unitId: `${mid}/${sid}/reactive+${batchSuffix}`,
|
|
1142
|
-
prompt: await buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, selected, basePath, subagentModel, { sessionContextWindow, modelRegistry, sessionProvider }),
|
|
1210
|
+
prompt: await buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, selected, basePath, subagentModel, { sessionContextWindow, modelRegistry, sessionProvider, subagentThinking }),
|
|
1143
1211
|
};
|
|
1144
1212
|
}
|
|
1145
1213
|
catch (err) {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Handles complexity-based routing, model resolution across providers,
|
|
4
4
|
* and fallback chains.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { clampThinkingLevel } from "@gsd/pi-ai";
|
|
7
|
+
import { resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit, resolveDynamicRoutingConfig } from "./preferences.js";
|
|
7
8
|
import { classifyUnitComplexity, extractTaskMetadata, tierLabel } from "./complexity-classifier.js";
|
|
8
9
|
import { resolveModelForComplexity, escalateTier, getEligibleModels, loadCapabilityOverrides, adjustToolSet } from "./model-router.js";
|
|
9
10
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
@@ -63,6 +64,32 @@ const TOOL_BASELINE = new WeakMap();
|
|
|
63
64
|
export function clearToolBaseline(pi) {
|
|
64
65
|
TOOL_BASELINE.delete(pi);
|
|
65
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Return the union of the pre-dispatch baseline tool set and the current live
|
|
69
|
+
* active tools, or just the live tools when no baseline has been recorded yet.
|
|
70
|
+
*
|
|
71
|
+
* Use this instead of `pi.getActiveTools()` anywhere you need the full tool
|
|
72
|
+
* surface for a preflight/routing check that runs BEFORE `selectAndApplyModel`
|
|
73
|
+
* restores the baseline — e.g. in `runDispatch` and `decideNextUnit`.
|
|
74
|
+
*
|
|
75
|
+
* The union is intentional:
|
|
76
|
+
* - Baseline covers tools that a prior unit's per-provider narrowing (hook
|
|
77
|
+
* overrides, Groq 128-tool cap, etc.) has removed from the live set.
|
|
78
|
+
* Those tools will be restored by `selectAndApplyModel` before dispatch, so
|
|
79
|
+
* dropping them from the preflight check would be a false negative.
|
|
80
|
+
* - Live set covers tools connected after the baseline was first captured
|
|
81
|
+
* (e.g. MCP servers attached mid-session or after a paused resume).
|
|
82
|
+
* Without the live merge, a stale baseline permanently hides newly
|
|
83
|
+
* connected MCP tools and prevents transport-preflight from clearing on
|
|
84
|
+
* resume (#477 follow-up).
|
|
85
|
+
*/
|
|
86
|
+
export function getToolBaselineSnapshot(pi) {
|
|
87
|
+
const live = typeof pi.getActiveTools === "function" ? pi.getActiveTools() : [];
|
|
88
|
+
const baseline = TOOL_BASELINE.get(pi);
|
|
89
|
+
if (baseline === undefined)
|
|
90
|
+
return live;
|
|
91
|
+
return [...new Set([...baseline, ...live])];
|
|
92
|
+
}
|
|
66
93
|
/**
|
|
67
94
|
* Models eligible for the pre-dispatch policy gate. Prefer registry-available
|
|
68
95
|
* models; when that list is empty (common after worktree resume before registry
|
|
@@ -202,10 +229,88 @@ function restoreToolBaseline(pi) {
|
|
|
202
229
|
pi.setActiveTools([...baseline]);
|
|
203
230
|
}
|
|
204
231
|
}
|
|
205
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Apply the desired reasoning effort for the just-selected model, clamping to
|
|
234
|
+
* what the model actually supports (ADR-026). An unsupported level is never
|
|
235
|
+
* sent to the provider — it is clamped via `clampThinkingLevel` and the
|
|
236
|
+
* mismatch is surfaced once per (model, requested-level). Returns the level
|
|
237
|
+
* actually applied so callers can record it.
|
|
238
|
+
*/
|
|
239
|
+
export function applyThinkingLevelForModel(pi, desired, model, ctx) {
|
|
240
|
+
if (!desired)
|
|
241
|
+
return desired;
|
|
242
|
+
// Capability-clamp only when we have a bare string level AND the model
|
|
243
|
+
// advertises reasoning capability (`reasoning` is always present on real
|
|
244
|
+
// registry models). Richer host snapshot shapes (e.g. `{ effort: "high" }`)
|
|
245
|
+
// and partial model objects are applied verbatim — we never coerce an unknown
|
|
246
|
+
// shape into a string or guess capability we can't see.
|
|
247
|
+
if (typeof desired === "string" && model != null && typeof model === "object" && "reasoning" in model) {
|
|
248
|
+
const clamped = clampThinkingLevel(model, desired);
|
|
249
|
+
pi.setThinkingLevel(clamped);
|
|
250
|
+
if (clamped !== desired) {
|
|
251
|
+
const key = `${model.provider}/${model.id}:${desired}`;
|
|
252
|
+
if (!_warnedThinkingClamp.has(key)) {
|
|
253
|
+
_warnedThinkingClamp.add(key);
|
|
254
|
+
ctx.ui.notify(`Thinking level '${desired}' not supported by ${model.provider}/${model.id}; using '${clamped}'.`, "warning");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return clamped;
|
|
258
|
+
}
|
|
259
|
+
pi.setThinkingLevel(desired);
|
|
260
|
+
return desired;
|
|
261
|
+
}
|
|
262
|
+
/** Warn-once guard for capability clamps, keyed by `provider/id:requested`. */
|
|
263
|
+
const _warnedThinkingClamp = new Set();
|
|
264
|
+
/** Warn-once guard for the execute-task floor punch-through advisory. */
|
|
265
|
+
let _warnedExecuteTaskFloorBypass = false;
|
|
266
|
+
/**
|
|
267
|
+
* Ascending severity order for reasoning levels (matches @gsd/pi-agent-core
|
|
268
|
+
* `ThinkingLevel`). Used only for floor comparisons below.
|
|
269
|
+
*/
|
|
270
|
+
const THINKING_LEVEL_ORDER = [
|
|
271
|
+
"off",
|
|
272
|
+
"minimal",
|
|
273
|
+
"low",
|
|
274
|
+
"medium",
|
|
275
|
+
"high",
|
|
276
|
+
"xhigh",
|
|
277
|
+
];
|
|
278
|
+
/**
|
|
279
|
+
* Minimum reasoning level for code-writing units.
|
|
280
|
+
*
|
|
281
|
+
* `execute-task` is the only unit that edits source. With a low/minimal
|
|
282
|
+
* thinking level a model does not plan its edits and compensates by re-reading
|
|
283
|
+
* the same files dozens of times per task (measured: index.html read ~49× in a
|
|
284
|
+
* single task on a minimal-thinking model) and shelling out to `nl`/`sed` to
|
|
285
|
+
* re-locate code after every edit invalidates its line numbers. Flooring the
|
|
286
|
+
* level for this unit type removes that read/bash thrash. Planning, research,
|
|
287
|
+
* and lifecycle units are unaffected.
|
|
288
|
+
*/
|
|
289
|
+
const EXECUTE_TASK_MIN_THINKING_LEVEL = "medium";
|
|
290
|
+
function thinkingLevelRank(level) {
|
|
291
|
+
const idx = THINKING_LEVEL_ORDER.indexOf(level);
|
|
292
|
+
return idx === -1 ? 0 : idx;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Raise (never lower) the thinking level for code-writing units to a sane
|
|
296
|
+
* floor. Returns the input unchanged for non-`execute-task` units, when no
|
|
297
|
+
* level was captured, or when the captured level already meets the floor.
|
|
298
|
+
*/
|
|
299
|
+
export function floorThinkingLevelForUnit(unitType, level) {
|
|
300
|
+
if (unitType !== "execute-task")
|
|
301
|
+
return level;
|
|
206
302
|
if (!level)
|
|
207
|
-
return;
|
|
208
|
-
|
|
303
|
+
return level;
|
|
304
|
+
// Only act on the recognized string levels. Any other shape (e.g. a richer
|
|
305
|
+
// host snapshot object) is passed through untouched so we never coerce an
|
|
306
|
+
// unknown representation into a bare string the host can't apply.
|
|
307
|
+
if (!THINKING_LEVEL_ORDER.includes(level)) {
|
|
308
|
+
return level;
|
|
309
|
+
}
|
|
310
|
+
if (thinkingLevelRank(level) >= thinkingLevelRank(EXECUTE_TASK_MIN_THINKING_LEVEL)) {
|
|
311
|
+
return level;
|
|
312
|
+
}
|
|
313
|
+
return EXECUTE_TASK_MIN_THINKING_LEVEL;
|
|
209
314
|
}
|
|
210
315
|
export function resolvePreferredModelConfig(unitType, autoModeStartModel, isAutoMode = true) {
|
|
211
316
|
const explicitConfig = resolveModelWithFallbacksForUnit(unitType);
|
|
@@ -256,6 +361,32 @@ sessionModelOverride,
|
|
|
256
361
|
/** Thinking level captured at auto-mode start and re-applied after model swaps. */
|
|
257
362
|
autoModeStartThinkingLevel) {
|
|
258
363
|
const uokFlags = resolveUokFlags(prefs);
|
|
364
|
+
// Resolve reasoning effort for this dispatch (ADR-026). An explicit per-phase
|
|
365
|
+
// thinking config (inline `models.<phase>.thinking` or the separate `thinking`
|
|
366
|
+
// block) expresses hard user intent: it bypasses the execute-task floor and is
|
|
367
|
+
// honored verbatim, then capability-clamped per model at apply time below.
|
|
368
|
+
// With no explicit level, fall back to the auto-start session level and raise
|
|
369
|
+
// the code-writing floor — preserving prior behavior exactly. Recomputed per
|
|
370
|
+
// dispatch so neither the floor nor a phase override leaks to other units.
|
|
371
|
+
const explicitThinkingLevel = resolveThinkingLevelForUnit(unitType);
|
|
372
|
+
const desiredThinkingLevel = explicitThinkingLevel
|
|
373
|
+
?? floorThinkingLevelForUnit(unitType, autoModeStartThinkingLevel);
|
|
374
|
+
if (explicitThinkingLevel) {
|
|
375
|
+
if (unitType === "execute-task" &&
|
|
376
|
+
thinkingLevelRank(explicitThinkingLevel) < thinkingLevelRank(EXECUTE_TASK_MIN_THINKING_LEVEL) &&
|
|
377
|
+
!_warnedExecuteTaskFloorBypass) {
|
|
378
|
+
_warnedExecuteTaskFloorBypass = true;
|
|
379
|
+
ctx.ui.notify(`Explicit execution thinking '${explicitThinkingLevel}' is below the measured execute-task floor ` +
|
|
380
|
+
`(${EXECUTE_TASK_MIN_THINKING_LEVEL}); honoring it as configured. Low reasoning on code edits can ` +
|
|
381
|
+
`cause repeated file re-reads.`, "warning");
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else if (verbose &&
|
|
385
|
+
desiredThinkingLevel &&
|
|
386
|
+
desiredThinkingLevel !== autoModeStartThinkingLevel) {
|
|
387
|
+
ctx.ui.notify(`Thinking level raised to ${desiredThinkingLevel} for ${unitType} (was ${autoModeStartThinkingLevel ?? "unset"})`, "info");
|
|
388
|
+
}
|
|
389
|
+
let appliedThinkingLevel = null;
|
|
259
390
|
const effectiveSessionModelOverride = sessionModelOverride === undefined
|
|
260
391
|
? getSessionModelOverride(ctx.sessionManager.getSessionId())
|
|
261
392
|
: (sessionModelOverride ?? undefined);
|
|
@@ -533,7 +664,7 @@ autoModeStartThinkingLevel) {
|
|
|
533
664
|
const ok = await pi.setModel(model, { persist: false });
|
|
534
665
|
if (ok) {
|
|
535
666
|
appliedModel = model;
|
|
536
|
-
|
|
667
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, model, ctx);
|
|
537
668
|
// ADR-005: Adjust active tool set for the selected model's provider capabilities.
|
|
538
669
|
// Hard-filter incompatible tools, then let extensions override via adjust_tool_set hook.
|
|
539
670
|
const activeToolNames = pi.getActiveTools();
|
|
@@ -591,7 +722,7 @@ autoModeStartThinkingLevel) {
|
|
|
591
722
|
if (!ok)
|
|
592
723
|
continue;
|
|
593
724
|
appliedModel = model;
|
|
594
|
-
|
|
725
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, model, ctx);
|
|
595
726
|
attemptedPolicyEligible = true;
|
|
596
727
|
if (verbose) {
|
|
597
728
|
ctx.ui.notify(`Model policy: configured model unavailable; using ${model.provider}/${model.id}`, "info");
|
|
@@ -621,18 +752,32 @@ autoModeStartThinkingLevel) {
|
|
|
621
752
|
const fallbackOk = await pi.setModel(byId, { persist: false });
|
|
622
753
|
if (fallbackOk) {
|
|
623
754
|
appliedModel = byId;
|
|
624
|
-
|
|
755
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, byId, ctx);
|
|
625
756
|
}
|
|
626
757
|
}
|
|
627
758
|
}
|
|
628
759
|
else {
|
|
629
760
|
appliedModel = startModel;
|
|
630
|
-
|
|
761
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, desiredThinkingLevel, startModel, ctx);
|
|
631
762
|
}
|
|
632
763
|
}
|
|
633
764
|
}
|
|
634
765
|
}
|
|
635
|
-
|
|
766
|
+
// If no model branch applied a thinking level (e.g. interactive guided-flow
|
|
767
|
+
// with a `thinking:` block but no per-phase model and no start model), still
|
|
768
|
+
// honor an explicitly configured phase thinking level against the current
|
|
769
|
+
// session model. Only the explicit path runs here — the floored session
|
|
770
|
+
// default is intentionally left untouched so no-config interactive runs keep
|
|
771
|
+
// the user's /model thinking level. (ADR-026)
|
|
772
|
+
if (appliedThinkingLevel == null && explicitThinkingLevel && ctx.model) {
|
|
773
|
+
// Prefer the full registry model (carries reasoning capability so the level
|
|
774
|
+
// can be clamped); fall back to ctx.model. Always route through
|
|
775
|
+
// applyThinkingLevelForModel so the clamp runs whenever capability metadata
|
|
776
|
+
// exists — never a raw verbatim setThinkingLevel that bypasses it (ADR-026).
|
|
777
|
+
const current = resolveModelId(`${ctx.model.provider}/${ctx.model.id}`, ctx.modelRegistry?.getAvailable?.() ?? [], ctx.model.provider) ?? ctx.model;
|
|
778
|
+
appliedThinkingLevel = applyThinkingLevelForModel(pi, explicitThinkingLevel, current, ctx);
|
|
779
|
+
}
|
|
780
|
+
return { routing, appliedModel, appliedThinkingLevel };
|
|
636
781
|
}
|
|
637
782
|
/**
|
|
638
783
|
* Resolve a model ID string to a model object from the available models list.
|
|
@@ -1280,6 +1280,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1280
1280
|
logError("engine", "triage resolution failed", { error: err.message });
|
|
1281
1281
|
}
|
|
1282
1282
|
}
|
|
1283
|
+
let blockingContentViolation = null;
|
|
1283
1284
|
// ── Safety harness: post-unit validation ──
|
|
1284
1285
|
try {
|
|
1285
1286
|
const { loadEffectiveGSDPreferences } = await import("./preferences.js");
|
|
@@ -1399,8 +1400,15 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1399
1400
|
const artifactPath = resolveArtifactForContent(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
1400
1401
|
const contentViolations = validateContent(s.currentUnit.type, artifactPath);
|
|
1401
1402
|
for (const v of contentViolations) {
|
|
1402
|
-
|
|
1403
|
-
|
|
1403
|
+
if (v.severity === "error") {
|
|
1404
|
+
blockingContentViolation ??= v.reason;
|
|
1405
|
+
logError("safety", `content: ${v.reason}`);
|
|
1406
|
+
ctx.ui.notify(`Content validation: ${v.reason}`, "error");
|
|
1407
|
+
}
|
|
1408
|
+
else {
|
|
1409
|
+
logWarning("safety", `content: ${v.reason}`);
|
|
1410
|
+
ctx.ui.notify(`Content validation: ${v.reason}`, "warning");
|
|
1411
|
+
}
|
|
1404
1412
|
}
|
|
1405
1413
|
}
|
|
1406
1414
|
catch (e) {
|
|
@@ -1573,6 +1581,15 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
1573
1581
|
return "continue";
|
|
1574
1582
|
}
|
|
1575
1583
|
}
|
|
1584
|
+
if (blockingContentViolation && triggerArtifactVerified) {
|
|
1585
|
+
triggerArtifactVerified = false;
|
|
1586
|
+
debugLog("postUnit", {
|
|
1587
|
+
phase: "content-validation-blocked-artifact",
|
|
1588
|
+
unitType: s.currentUnit.type,
|
|
1589
|
+
unitId: s.currentUnit.id,
|
|
1590
|
+
reason: blockingContentViolation,
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1576
1593
|
// When artifact verification fails for a unit type that has a known expected
|
|
1577
1594
|
// artifact, ask the caller to retry so it re-dispatches with failure context
|
|
1578
1595
|
// instead of blindly re-dispatching the same unit (#1571).
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* utility.
|
|
9
9
|
*/
|
|
10
10
|
import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection } from "./files.js";
|
|
11
|
-
import { hasVerdict,
|
|
11
|
+
import { hasVerdict, extractVerdict } from "./verdict-parser.js";
|
|
12
12
|
import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
|
|
13
13
|
import { resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile, } from "./paths.js";
|
|
14
14
|
import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
@@ -27,11 +27,11 @@ import { logWarning } from "./workflow-logger.js";
|
|
|
27
27
|
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
28
28
|
import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
|
|
29
29
|
import { classifyProject } from "./detection.js";
|
|
30
|
-
import { hasBrowserRequiredText } from "./browser-evidence.js";
|
|
31
30
|
import { debugLog } from "./debug-logger.js";
|
|
32
31
|
import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
|
|
33
32
|
import { findMilestoneIds } from "./milestone-ids.js";
|
|
34
|
-
import {
|
|
33
|
+
import { buildRunUatPresentationForType, RUN_UAT_TOOL_PRESENTATION_PLAN_ID } from "./tool-presentation-plan.js";
|
|
34
|
+
import { resolveEffectiveUatType, shouldDispatchUatForContent } from "./uat-policy.js";
|
|
35
35
|
export { buildSkillActivationBlock, buildSkillDiscoveryVars };
|
|
36
36
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
37
37
|
/**
|
|
@@ -228,17 +228,6 @@ function prependContextModeToBlock(unitType, base, block, renderMode = "standalo
|
|
|
228
228
|
return contextMode;
|
|
229
229
|
return `${contextMode}\n\n${block}`;
|
|
230
230
|
}
|
|
231
|
-
function resolveEffectiveUatType(content) {
|
|
232
|
-
const uatType = getUatType(content);
|
|
233
|
-
if (uatType === "artifact-driven" && hasBrowserRequiredText(content)) {
|
|
234
|
-
return "browser-executable";
|
|
235
|
-
}
|
|
236
|
-
return uatType;
|
|
237
|
-
}
|
|
238
|
-
function shouldDispatchUatForContent(content, prefs) {
|
|
239
|
-
const uatType = resolveEffectiveUatType(content);
|
|
240
|
-
return !!prefs?.uat_dispatch || uatType !== "artifact-driven" || hasBrowserRequiredText(content);
|
|
241
|
-
}
|
|
242
231
|
// ─── Executor Constraints ─────────────────────────────────────────────────────
|
|
243
232
|
/**
|
|
244
233
|
* Format executor context constraints for injection into the plan-slice prompt.
|
|
@@ -2940,7 +2929,7 @@ export async function buildRunUatPrompt(mid, sliceId, uatPath, uatContent, base)
|
|
|
2940
2929
|
emitPromptContextTelemetry("run-uat", contextTelemetry, inlinedContext);
|
|
2941
2930
|
const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
|
|
2942
2931
|
const uatType = resolveEffectiveUatType(uatContent);
|
|
2943
|
-
const canonicalPresentation = JSON.stringify(
|
|
2932
|
+
const canonicalPresentation = JSON.stringify(buildRunUatPresentationForType(uatType), null, 2);
|
|
2944
2933
|
return loadPrompt("run-uat", {
|
|
2945
2934
|
workingDirectory: base,
|
|
2946
2935
|
milestoneId: mid,
|
|
@@ -3077,7 +3066,23 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
|
|
|
3077
3066
|
});
|
|
3078
3067
|
}
|
|
3079
3068
|
// ─── Reactive Execute Prompt ──────────────────────────────────────────────
|
|
3080
|
-
|
|
3069
|
+
/**
|
|
3070
|
+
* Build the `with model: "…" and thinking: "…"` suffix injected into a prompt
|
|
3071
|
+
* that instructs the coordinator how to dispatch a `subagent` call. Either or
|
|
3072
|
+
* both may be absent (ADR-026 / #508).
|
|
3073
|
+
*/
|
|
3074
|
+
function subagentCallSuffix(model, thinking) {
|
|
3075
|
+
const parts = [];
|
|
3076
|
+
if (model)
|
|
3077
|
+
parts.push(`model: "${model}"`);
|
|
3078
|
+
if (thinking)
|
|
3079
|
+
parts.push(`thinking: "${thinking}"`);
|
|
3080
|
+
return parts.length > 0 ? ` with ${parts.join(" and ")}` : "";
|
|
3081
|
+
}
|
|
3082
|
+
export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, readyTaskIds, base, subagentModel,
|
|
3083
|
+
// Reasoning effort travels inside opts here (not as a positional param) so
|
|
3084
|
+
// existing positional `opts` callers don't shift (#508).
|
|
3085
|
+
opts) {
|
|
3081
3086
|
const { loadSliceTaskIO, deriveTaskGraph, graphMetrics } = await import("./reactive-graph.js");
|
|
3082
3087
|
// Build graph for context
|
|
3083
3088
|
const taskIO = await loadSliceTaskIO(base, mid, sid);
|
|
@@ -3151,7 +3156,7 @@ export async function buildReactiveExecutePrompt(mid, midTitle, sid, sTitle, rea
|
|
|
3151
3156
|
"",
|
|
3152
3157
|
`When done, say: "Task ${tid} complete."`,
|
|
3153
3158
|
].join("\n");
|
|
3154
|
-
const modelSuffix = subagentModel
|
|
3159
|
+
const modelSuffix = subagentCallSuffix(subagentModel, opts?.subagentThinking);
|
|
3155
3160
|
subagentSections.push([
|
|
3156
3161
|
`### ${tid}: ${tTitle}`,
|
|
3157
3162
|
"",
|
|
@@ -3217,10 +3222,10 @@ function renderGatesToCloseBlock(gates, opts) {
|
|
|
3217
3222
|
}
|
|
3218
3223
|
return lines.join("\n").trimEnd();
|
|
3219
3224
|
}
|
|
3220
|
-
export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, basePath, subagentModel) {
|
|
3225
|
+
export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, basePath, subagentModel, subagentThinking) {
|
|
3221
3226
|
// Build individual research-slice prompts for each slice
|
|
3222
3227
|
const subagentSections = [];
|
|
3223
|
-
const modelSuffix = subagentModel
|
|
3228
|
+
const modelSuffix = subagentCallSuffix(subagentModel, subagentThinking);
|
|
3224
3229
|
for (const slice of slices) {
|
|
3225
3230
|
const slicePrompt = await buildResearchSlicePrompt(mid, midTitle, slice.id, slice.title, basePath, { contextModeRenderMode: "nested" });
|
|
3226
3231
|
subagentSections.push([
|
|
@@ -3242,7 +3247,7 @@ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, b
|
|
|
3242
3247
|
subagentPrompts: subagentSections.join("\n\n---\n\n"),
|
|
3243
3248
|
});
|
|
3244
3249
|
}
|
|
3245
|
-
export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base, subagentModel) {
|
|
3250
|
+
export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base, subagentModel, subagentThinking) {
|
|
3246
3251
|
// Pull only the gates this turn actually owns (Q3/Q4). Filter via the
|
|
3247
3252
|
// registry so that scope:"slice" gates owned by other turns (Q8) can't
|
|
3248
3253
|
// leak into this prompt and can't block dispatch via silent skip.
|
|
@@ -3291,7 +3296,7 @@ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base,
|
|
|
3291
3296
|
"- `rationale`: one-sentence justification",
|
|
3292
3297
|
"- `findings`: detailed markdown findings (or empty if omitted)",
|
|
3293
3298
|
].join("\n");
|
|
3294
|
-
const modelSuffix = subagentModel
|
|
3299
|
+
const modelSuffix = subagentCallSuffix(subagentModel, subagentThinking);
|
|
3295
3300
|
subagentSections.push([
|
|
3296
3301
|
`### ${def.id}: ${def.question}`,
|
|
3297
3302
|
"",
|
|
@@ -14,7 +14,7 @@ import { appendEvent } from "./workflow-events.js";
|
|
|
14
14
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
15
15
|
import { clearParseCache } from "./files.js";
|
|
16
16
|
import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
|
|
17
|
-
import { isDbAvailable, getTask, getSlice, getSliceTasks,
|
|
17
|
+
import { isDbAvailable, getTask, getSlice, getSliceTasks, getPendingGatesForTurn, updateTaskStatus, updateSliceStatus, insertSlice, getMilestone, getMilestoneSlices, getLatestAssessmentByScope, updateMilestoneStatus, refreshOpenDatabaseFromDisk, transaction, } from "./gsd-db.js";
|
|
18
18
|
import { isValidationTerminal } from "./state.js";
|
|
19
19
|
import { getErrorMessage } from "./error-utils.js";
|
|
20
20
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
@@ -329,7 +329,9 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
329
329
|
if (gateIds.length === 0)
|
|
330
330
|
return true;
|
|
331
331
|
try {
|
|
332
|
-
|
|
332
|
+
if (!isDbAvailable())
|
|
333
|
+
return false;
|
|
334
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
333
335
|
const pendingIds = new Set(pending.map((g) => g.gate_id));
|
|
334
336
|
// All dispatched gates must no longer be pending
|
|
335
337
|
for (const gid of gateIds) {
|