@opengsd/gsd-pi 1.9.0 → 1.10.0
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/README.md +10 -10
- package/dist/headless.js +2 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
- package/dist/resources/extensions/gsd/auto/loop.js +24 -4
- package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
- package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -8
- package/dist/resources/extensions/gsd/auto-dispatch.js +2 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
- package/dist/resources/extensions/gsd/auto-start.js +29 -9
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +4 -24
- package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
- package/dist/resources/extensions/gsd/compat/compat-marker.js +80 -5
- package/dist/resources/extensions/gsd/constants.js +12 -13
- package/dist/resources/extensions/gsd/context-masker.js +97 -21
- package/dist/resources/extensions/gsd/db/engine.js +5 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +22 -0
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +24 -8
- package/dist/resources/extensions/gsd/error-classifier.js +12 -2
- package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
- package/dist/resources/extensions/gsd/flat-phase-migration.js +12 -0
- package/dist/resources/extensions/gsd/git-service.js +19 -7
- package/dist/resources/extensions/gsd/gsd-db.js +75 -31
- package/dist/resources/extensions/gsd/guided-flow.js +11 -5
- package/dist/resources/extensions/gsd/markdown-renderer.js +5 -21
- package/dist/resources/extensions/gsd/md-importer.js +5 -6
- package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
- package/dist/resources/extensions/gsd/model-router.js +11 -0
- package/dist/resources/extensions/gsd/paths.js +66 -15
- package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
- package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
- package/dist/resources/extensions/gsd/preferences-types.js +5 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
- package/dist/resources/extensions/gsd/preferences.js +17 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
- package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
- package/dist/resources/extensions/gsd/skill-activation.js +17 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +98 -2
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +4 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
- package/dist/resources/extensions/gsd/stop-notice.js +9 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +12 -5
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
- package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
- package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
- package/dist/resources/extensions/gsd/workspace.js +2 -1
- package/dist/resources/extensions/gsd/worktree-state-projection.js +20 -18
- package/dist/resources/extensions/shared/interview-ui.js +43 -6
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- 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 +8 -8
- package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +7 -6
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +1 -0
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/README.md +9 -3
- package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/background-cli.test.js +248 -0
- package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cli.js +121 -15
- package/packages/gsd-cloud/dist/cli.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-config.d.ts +1 -1
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-config.js +7 -1
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +1 -3
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.js +9 -7
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -1
- package/packages/gsd-cloud/dist/runtime-process.d.ts +27 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.js +272 -0
- package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js +97 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
- package/packages/gsd-cloud/package.json +2 -2
- package/packages/mcp-server/README.md +7 -2
- package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
- package/packages/mcp-server/dist/cli-runner.js +119 -33
- package/packages/mcp-server/dist/cli-runner.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +5 -5
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +76 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +70 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +6 -1
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +54 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
- package/src/resources/extensions/gsd/auto/loop.ts +48 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
- package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -7
- package/src/resources/extensions/gsd/auto-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +118 -19
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
- package/src/resources/extensions/gsd/auto-start.ts +31 -8
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +20 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +7 -29
- package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
- package/src/resources/extensions/gsd/compat/compat-marker.ts +99 -5
- package/src/resources/extensions/gsd/constants.ts +14 -13
- package/src/resources/extensions/gsd/context-masker.ts +98 -2
- package/src/resources/extensions/gsd/db/engine.ts +5 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +22 -0
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +30 -7
- package/src/resources/extensions/gsd/error-classifier.ts +13 -2
- package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
- package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -0
- package/src/resources/extensions/gsd/git-service.ts +19 -6
- package/src/resources/extensions/gsd/gsd-db.ts +85 -33
- package/src/resources/extensions/gsd/guided-flow.ts +11 -4
- package/src/resources/extensions/gsd/markdown-renderer.ts +5 -23
- package/src/resources/extensions/gsd/md-importer.ts +5 -5
- package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
- package/src/resources/extensions/gsd/model-router.ts +12 -0
- package/src/resources/extensions/gsd/paths.ts +73 -15
- package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
- package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
- package/src/resources/extensions/gsd/preferences.ts +25 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
- package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
- package/src/resources/extensions/gsd/skill-activation.ts +17 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +132 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +4 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
- package/src/resources/extensions/gsd/stop-notice.ts +11 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +76 -1
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
- package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +8 -9
- package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
- package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -5
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
- package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
- package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
- package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
- package/src/resources/extensions/gsd/workspace.ts +2 -1
- package/src/resources/extensions/gsd/worktree-state-projection.ts +21 -24
- package/src/resources/extensions/shared/interview-ui.ts +47 -8
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
- /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → EAhnhYMt5UVOiG9-iPDjc}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → EAhnhYMt5UVOiG9-iPDjc}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -28,16 +28,16 @@ See [CHANGELOG.md](./CHANGELOG.md) for release-by-release fixes and [Legacy Rele
|
|
|
28
28
|
## Latest Release Highlights
|
|
29
29
|
|
|
30
30
|
<!-- release-highlights:start -->
|
|
31
|
-
Latest release: **v1.
|
|
32
|
-
|
|
33
|
-
- **
|
|
34
|
-
- **
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
- **gsd:**
|
|
39
|
-
- **gsd:**
|
|
40
|
-
- **gsd:**
|
|
31
|
+
Latest release: **v1.10.0**
|
|
32
|
+
|
|
33
|
+
- **pi-ai:** Add Meta Muse Spark 1.1 to the model catalog.
|
|
34
|
+
- **gsd:** Surface cacheRetention as a settable prompt-cache TTL preference.
|
|
35
|
+
- **models:** Add GPT-5.6 as a first-class model.
|
|
36
|
+
- **models:** Add Grok 4.5 as a first-class xAI model.
|
|
37
|
+
- **agent-core:** Pin compaction summarization reasoning to low, bound degenerate-chunk retry.
|
|
38
|
+
- **gsd:** Filter superseded context injections from provider payload.
|
|
39
|
+
- **gsd:** Stop advertising alias tool schemas on model-facing surfaces.
|
|
40
|
+
- **gsd:** Cap execute-task and discuss-slice inlined context; provider-aware budgets.
|
|
41
41
|
|
|
42
42
|
<!-- release-highlights:end -->
|
|
43
43
|
|
package/dist/headless.js
CHANGED
|
@@ -29,7 +29,8 @@ export function buildHeadlessSlashCommand(options) {
|
|
|
29
29
|
if (options.command === 'new-milestone' && options.auto && !commandArgs.includes(HEADLESS_CHAIN_AUTO_FLAG)) {
|
|
30
30
|
commandArgs.push(HEADLESS_CHAIN_AUTO_FLAG);
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
const serializedArgs = commandArgs.map(arg => /\s/.test(arg) ? JSON.stringify(arg) : arg);
|
|
33
|
+
return `/gsd ${options.command}${serializedArgs.length > 0 ? ' ' + serializedArgs.join(' ') : ''}`;
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
36
|
* Commands classified as multi-turn in headless mode: they involve multiple
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5f0f1c788a126951
|
|
@@ -367,7 +367,7 @@ When verification finds gaps, include a **Gaps** section with what's missing, im
|
|
|
367
367
|
### Phase 6: Summarize
|
|
368
368
|
|
|
369
369
|
**Purpose:** Record what happened for downstream tasks.
|
|
370
|
-
**Produces:** `T##-SUMMARY.md
|
|
370
|
+
**Produces:** `S##-T##-SUMMARY.md` in flat-phase projects, and when slice completes, `S##-SUMMARY.md`. Legacy flat `T##-SUMMARY.md` task summaries are still readable.
|
|
371
371
|
|
|
372
372
|
**Task summary format:**
|
|
373
373
|
```markdown
|
|
@@ -494,7 +494,7 @@ It is NOT the source of truth. It's a convenience dashboard.
|
|
|
494
494
|
**Sources of truth:**
|
|
495
495
|
- `ROADMAP.md` → which slices exist and which are done
|
|
496
496
|
- `<NN>-<MM>-PLAN.md` → which tasks exist within a slice and what each task must do
|
|
497
|
-
- `T##-SUMMARY.md` → what happened during a task
|
|
497
|
+
- `S##-T##-SUMMARY.md` → what happened during a task in flat-phase projects (legacy `T##-SUMMARY.md` is still readable)
|
|
498
498
|
- `S##-SUMMARY.md` and `M###-SUMMARY.md` → compressed slice and milestone outcomes
|
|
499
499
|
|
|
500
500
|
**Update `STATE.md`** after every significant action:
|
|
@@ -9,7 +9,7 @@ import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
|
|
|
9
9
|
import { isValidationTerminal } from "./state.js";
|
|
10
10
|
import { getErrorMessage } from "./error-utils.js";
|
|
11
11
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
12
|
-
import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relSliceFile, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
|
|
12
|
+
import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relSliceFile, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
|
|
13
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
14
14
|
import { execFileSync } from "node:child_process";
|
|
15
15
|
import { LAYOUT_SEGMENTS } from "./layout-policy.js";
|
|
@@ -185,10 +185,9 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
|
|
|
185
185
|
const batchIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
|
|
186
186
|
if (batchIds.length === 0)
|
|
187
187
|
return false;
|
|
188
|
-
const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
|
|
189
|
-
const existingSummaries = new Set(resolveTaskFiles(tDir, "SUMMARY").map((f) => f.replace(/-SUMMARY\.md$/i, "").toUpperCase()));
|
|
190
188
|
for (const tid of batchIds) {
|
|
191
|
-
|
|
189
|
+
const summaryPath = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
|
|
190
|
+
if (!summaryPath || !existsSync(summaryPath))
|
|
192
191
|
return false;
|
|
193
192
|
}
|
|
194
193
|
return true;
|
|
@@ -261,7 +261,22 @@ async function enforceMinRequestInterval(s, prefs) {
|
|
|
261
261
|
await new Promise(r => setTimeout(r, decision.waitMs));
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
|
-
function
|
|
264
|
+
async function snapshotCrashedUnitWork(ctx, s, deps, iterData) {
|
|
265
|
+
try {
|
|
266
|
+
const commitMsg = await deps.autoCommitUnit?.(s.basePath, iterData.unitType, iterData.unitId, ctx);
|
|
267
|
+
if (commitMsg) {
|
|
268
|
+
debugLog("autoLoop", {
|
|
269
|
+
phase: "crash-snapshot-commit",
|
|
270
|
+
unitType: iterData.unitType,
|
|
271
|
+
unitId: iterData.unitId,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (snapshotErr) {
|
|
276
|
+
logWarning("dispatch", `unit crash snapshot failed: ${snapshotErr instanceof Error ? snapshotErr.message : String(snapshotErr)}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function closeOutCrashedUnit(ctx, s, deps, iterData, err) {
|
|
265
280
|
const summary = formatDispatchExceptionSummary({ error: err });
|
|
266
281
|
try {
|
|
267
282
|
emitOpenUnitEndForUnit(s.basePath, iterData.unitType, iterData.unitId, "cancelled", {
|
|
@@ -278,6 +293,7 @@ function closeOutCrashedUnit(s, iterData, err) {
|
|
|
278
293
|
catch (closeoutErr) {
|
|
279
294
|
logWarning("dispatch", `unit crash closeout failed: ${closeoutErr instanceof Error ? closeoutErr.message : String(closeoutErr)}`);
|
|
280
295
|
}
|
|
296
|
+
await snapshotCrashedUnitWork(ctx, s, deps, iterData);
|
|
281
297
|
}
|
|
282
298
|
/**
|
|
283
299
|
* Main auto-mode execution loop. Iterates: orchestration.advance → guards →
|
|
@@ -400,11 +416,15 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
400
416
|
active: s.active,
|
|
401
417
|
iteration,
|
|
402
418
|
maxIterations: MAX_LOOP_ITERATIONS,
|
|
403
|
-
hasCommandContext:
|
|
419
|
+
hasCommandContext: typeof s.cmdCtx?.newSession === "function",
|
|
404
420
|
sessionLockValid: true,
|
|
405
421
|
});
|
|
406
422
|
if (commandContextDecision.action === "stop" && commandContextDecision.reason === "missing-command-context") {
|
|
407
423
|
debugLog("autoLoop", { phase: "exit", reason: "no-cmdCtx" });
|
|
424
|
+
if (s.currentUnit) {
|
|
425
|
+
await deps.autoCommitUnit?.(s.basePath, s.currentUnit.type, s.currentUnit.id, ctx);
|
|
426
|
+
}
|
|
427
|
+
await deps.stopAuto(ctx, pi, commandContextDecision.message, { preserveWorktree: true });
|
|
408
428
|
finishTurn("stopped", "manual-attention", commandContextDecision.reason);
|
|
409
429
|
break;
|
|
410
430
|
}
|
|
@@ -586,7 +606,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
586
606
|
if (err instanceof ModelPolicyDispatchBlockedError) {
|
|
587
607
|
throw err;
|
|
588
608
|
}
|
|
589
|
-
closeOutCrashedUnit(s, iterData, err);
|
|
609
|
+
await closeOutCrashedUnit(ctx, s, deps, iterData, err);
|
|
590
610
|
throw err;
|
|
591
611
|
}
|
|
592
612
|
if (unitPhaseResult.action === "next") {
|
|
@@ -1109,7 +1129,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
1109
1129
|
if (err instanceof ModelPolicyDispatchBlockedError) {
|
|
1110
1130
|
throw err;
|
|
1111
1131
|
}
|
|
1112
|
-
closeOutCrashedUnit(s, iterData, err);
|
|
1132
|
+
await closeOutCrashedUnit(ctx, s, deps, iterData, err);
|
|
1113
1133
|
dispatchSettled = settleDispatchFailed(dispatchId, formatDispatchExceptionSummary({ error: err }), {
|
|
1114
1134
|
markFailed: markDispatchFailed,
|
|
1115
1135
|
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
@@ -58,6 +58,24 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
58
58
|
debugLog("runUnit", { phase: "start", unitType, unitId });
|
|
59
59
|
// ── Session creation with timeout ──
|
|
60
60
|
debugLog("runUnit", { phase: "session-create", unitType, unitId });
|
|
61
|
+
const cmdCtx = s.cmdCtx;
|
|
62
|
+
if (typeof cmdCtx?.newSession !== "function") {
|
|
63
|
+
const msg = "command context is missing newSession";
|
|
64
|
+
debugLog("runUnit", {
|
|
65
|
+
phase: "session-error",
|
|
66
|
+
unitType,
|
|
67
|
+
unitId,
|
|
68
|
+
error: msg,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
status: "cancelled",
|
|
72
|
+
errorContext: {
|
|
73
|
+
message: `Session creation failed: ${msg}`,
|
|
74
|
+
category: "session-failed",
|
|
75
|
+
isTransient: false,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
61
79
|
let sessionResult;
|
|
62
80
|
let sessionTimeoutHandle;
|
|
63
81
|
const mySessionSwitchGeneration = ++sessionSwitchGeneration;
|
|
@@ -67,7 +85,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
67
85
|
const sessionAbortController = new AbortController();
|
|
68
86
|
_setSessionSwitchInFlight(true);
|
|
69
87
|
try {
|
|
70
|
-
const sessionPromise =
|
|
88
|
+
const sessionPromise = cmdCtx.newSession({
|
|
71
89
|
abortSignal: sessionAbortController.signal,
|
|
72
90
|
workspaceRoot: s.basePath,
|
|
73
91
|
}).finally(() => {
|
|
@@ -30,6 +30,25 @@ import { isIsolatedWorktreeSession, _resolveCurrentUnitStartedAtForTest, emitCan
|
|
|
30
30
|
import { MAX_RECOVERY_CHARS } from "./types.js";
|
|
31
31
|
const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) (?:hit|reached) your (?:\w+ )?limit\b|.*\b(?:usage|session|weekly|daily|monthly|quota) limit\b|limit\b.{0,40}\bresets?\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
|
|
32
32
|
const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE = /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
|
|
33
|
+
const ZERO_TOOL_PSEUDO_TOOL_CALL_RE = /<arg_key>[\s\S]*?<\/arg_key>\s*<arg_value>[\s\S]*?<\/arg_value>[\s\S]*?<\/tool_call>/i;
|
|
34
|
+
const ZERO_TOOL_PSEUDO_TOOL_CALL_SNIPPET_CHARS = 200;
|
|
35
|
+
function zeroToolMessageSnippet(message) {
|
|
36
|
+
const compact = message.trim().replace(/\s+/g, " ");
|
|
37
|
+
if (compact.length <= ZERO_TOOL_PSEUDO_TOOL_CALL_SNIPPET_CHARS)
|
|
38
|
+
return compact;
|
|
39
|
+
return `${compact.slice(0, ZERO_TOOL_PSEUDO_TOOL_CALL_SNIPPET_CHARS - 3)}...`;
|
|
40
|
+
}
|
|
41
|
+
// Provider serialization drift: the model emitted a tool call as plain assistant
|
|
42
|
+
// text (`toolName<arg_key>…</arg_key><arg_value>…</arg_value></tool_call>`)
|
|
43
|
+
// instead of a structured tool call. Returns an operator-visible snippet when
|
|
44
|
+
// detected. Kept separate from error classification so a drift snippet is never
|
|
45
|
+
// conflated with an ErrorClass (which would force a fragile union whose
|
|
46
|
+
// narrowing the root and extensions tsconfigs disagree on).
|
|
47
|
+
function zeroToolPseudoToolCallSnippet(message) {
|
|
48
|
+
if (!ZERO_TOOL_PSEUDO_TOOL_CALL_RE.test(message))
|
|
49
|
+
return null;
|
|
50
|
+
return zeroToolMessageSnippet(message);
|
|
51
|
+
}
|
|
33
52
|
function classifyZeroToolProviderMessage(message) {
|
|
34
53
|
const firstLine = message.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
35
54
|
if (!firstLine ||
|
|
@@ -39,6 +58,7 @@ function classifyZeroToolProviderMessage(message) {
|
|
|
39
58
|
return classifyError(firstLine);
|
|
40
59
|
}
|
|
41
60
|
export const _classifyZeroToolProviderMessageForTest = classifyZeroToolProviderMessage;
|
|
61
|
+
export const _zeroToolPseudoToolCallSnippetForTest = zeroToolPseudoToolCallSnippet;
|
|
42
62
|
export function resolveDispatchRecoveryAttempts(unitRecoveryCount, unitType, unitId) {
|
|
43
63
|
return (unitRecoveryCount.get(`${unitType}/${unitId}`) ?? 0) > 0
|
|
44
64
|
? 0
|
|
@@ -572,11 +592,23 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
572
592
|
const lastUnit = [...currentLedger.units].reverse().find((u) => u.type === unitType && u.id === unitId && u.startedAt === _resolveCurrentUnitStartedAtForTest(s.currentUnit));
|
|
573
593
|
if (lastUnit && lastUnit.toolCalls === 0) {
|
|
574
594
|
const lastAssistantMessage = lastAssistantText(s.lastUnitAgentEndMessages);
|
|
575
|
-
const
|
|
576
|
-
if (
|
|
577
|
-
|
|
595
|
+
const pseudoToolCallSnippet = zeroToolPseudoToolCallSnippet(lastAssistantMessage);
|
|
596
|
+
if (pseudoToolCallSnippet) {
|
|
597
|
+
debugLog("runUnitPhase", {
|
|
598
|
+
phase: "zero-tool-serialization-drift",
|
|
599
|
+
unitType,
|
|
600
|
+
unitId,
|
|
601
|
+
snippet: pseudoToolCallSnippet,
|
|
602
|
+
});
|
|
603
|
+
ctx.ui.notify(`${unitType} ${unitId} completed with 0 tool calls - provider serialization drift: model emitted pseudo-tool-call text. Snippet: ${pseudoToolCallSnippet}`, "error");
|
|
604
|
+
await deps.pauseAuto(ctx, pi);
|
|
605
|
+
return { action: "break", reason: "zero-tool-serialization-drift" };
|
|
606
|
+
}
|
|
607
|
+
const providerErrorClass = classifyZeroToolProviderMessage(lastAssistantMessage);
|
|
608
|
+
if (providerErrorClass && isTransient(providerErrorClass)) {
|
|
609
|
+
const retryAfterMs = "retryAfterMs" in providerErrorClass ? providerErrorClass.retryAfterMs : 15_000;
|
|
578
610
|
await pauseAutoForProviderError(ctx.ui, ` for ${unitType} ${unitId}`, () => deps.pauseAuto(ctx, pi), {
|
|
579
|
-
isRateLimit:
|
|
611
|
+
isRateLimit: providerErrorClass.kind === "rate-limit",
|
|
580
612
|
isTransient: true,
|
|
581
613
|
retryAfterMs,
|
|
582
614
|
resume: () => {
|
|
@@ -593,7 +625,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
593
625
|
});
|
|
594
626
|
return {
|
|
595
627
|
action: "break",
|
|
596
|
-
reason:
|
|
628
|
+
reason: providerErrorClass.kind === "rate-limit" ? "rate-limit" : "api-timeout",
|
|
597
629
|
};
|
|
598
630
|
}
|
|
599
631
|
if (USER_DRIVEN_DEEP_UNITS.has(unitType) && isAwaitingUserInput(s.lastUnitAgentEndMessages ?? undefined)) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// resolveExpectedArtifactPath and diagnoseExpectedArtifact moved here from
|
|
6
6
|
// auto-recovery.ts (Phase 5 dead-code cleanup). The artifact verification
|
|
7
7
|
// function was removed entirely — callers now query WorkflowEngine directly.
|
|
8
|
-
import { gsdRoot, resolveDir, resolveFile, resolveMilestonePath, resolveMilestoneFile, resolveSliceFile, relMilestoneFile, relSliceFile, buildTaskFileName, resolveSlicePath, resolveTasksDir, dirIsMetaOnlyLegacyMilestone, normalizeRealPath, } from "./paths.js";
|
|
8
|
+
import { gsdRoot, resolveDir, resolveFile, resolveMilestonePath, resolveMilestoneFile, resolveSliceFile, relMilestoneFile, relSliceFile, buildFlatTaskFileName, buildTaskFileName, resolveSlicePath, resolveTasksDir, dirIsMetaOnlyLegacyMilestone, normalizeRealPath, } from "./paths.js";
|
|
9
9
|
import { milestoneIdToPhaseNum } from "./layout-policy.js";
|
|
10
10
|
import { parseUnitId } from "./unit-id.js";
|
|
11
11
|
import { basename, dirname, join, relative } from "node:path";
|
|
@@ -79,12 +79,15 @@ function resolveProjectMilestonePath(base, mid) {
|
|
|
79
79
|
const dir = resolveDir(milestonesDir, mid);
|
|
80
80
|
if (!dir)
|
|
81
81
|
return null;
|
|
82
|
-
// git-service.ts
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
82
|
+
// Historically git-service.ts wrote integration-branch metadata into
|
|
83
|
+
// milestones/<MID>/<MID>-META.json, which could create that dir in flat-phase
|
|
84
|
+
// projects and poison layout detection. As of ADR-045 that META lives flat at
|
|
85
|
+
// .gsd/<MID>-META.json and no longer poisons detection. A dir that holds ONLY
|
|
86
|
+
// *-META.json files (a pre-migration on-disk tree) must still not be treated
|
|
87
|
+
// as a real legacy milestone dir — otherwise this early-return resolves
|
|
88
|
+
// CONTEXT/ROADMAP/SUMMARY to the legacy path (milestones/<MID>/<MID>-<SUFFIX>.md)
|
|
89
|
+
// before the flat-phase fallback can run, trapping the unit in a
|
|
90
|
+
// finalize-retry loop (#852 follow-up).
|
|
88
91
|
//
|
|
89
92
|
// We use dirIsMetaOnlyLegacyMilestone rather than !dirIsContentBearingLegacyMilestone
|
|
90
93
|
// so that an EMPTY dir (a new milestone before any content is written) is NOT
|
|
@@ -203,7 +206,10 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
|
|
|
203
206
|
const summaryDir = isLegacySlice
|
|
204
207
|
? (resolveTasksDir(base, mid, sid) ?? slicePath)
|
|
205
208
|
: slicePath;
|
|
206
|
-
|
|
209
|
+
const fileName = isLegacySlice
|
|
210
|
+
? buildTaskFileName(tid, "SUMMARY")
|
|
211
|
+
: buildFlatTaskFileName(sid, tid, "SUMMARY");
|
|
212
|
+
return join(summaryDir, fileName);
|
|
207
213
|
}
|
|
208
214
|
case "complete-slice": {
|
|
209
215
|
return resolveSliceArtifactPath(base, mid, sid, "SUMMARY");
|
|
@@ -1603,6 +1603,8 @@ function applyLanguageDirectiveToDispatch(action, prefs) {
|
|
|
1603
1603
|
const directive = renderLanguageDirectiveForPrompt(prefs);
|
|
1604
1604
|
if (!directive)
|
|
1605
1605
|
return action;
|
|
1606
|
+
if (action.prompt.startsWith(directive))
|
|
1607
|
+
return action;
|
|
1606
1608
|
return { ...action, prompt: `${directive}\n\n${action.prompt}` };
|
|
1607
1609
|
}
|
|
1608
1610
|
// ─── Resolver ─────────────────────────────────────────────────────────────
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection } from "./files.js";
|
|
11
11
|
import { extractVerdict } from "./verdict-parser.js";
|
|
12
12
|
import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
|
|
13
|
-
import { resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath, relTaskFile, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile, } from "./paths.js";
|
|
14
|
-
import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
13
|
+
import { resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, resolveTaskFiles, resolveTaskFile, taskIdFromTaskFileName, relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath, relTaskFile, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile, } from "./paths.js";
|
|
14
|
+
import { resolveInlineLevel, loadEffectiveGSDPreferences, renderLanguageDirectiveForPrompt } from "./preferences.js";
|
|
15
15
|
import { createRepositoryRegistryFromPreferences } from "./repository-registry.js";
|
|
16
16
|
import { isContextModeEnabled } from "./preferences-types.js";
|
|
17
17
|
import { parseRoadmap } from "./parsers-legacy.js";
|
|
18
|
-
import { join, relative, sep } from "node:path";
|
|
18
|
+
import { join, basename, relative, sep } from "node:path";
|
|
19
19
|
import { existsSync } from "node:fs";
|
|
20
20
|
import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary } from "./context-budget.js";
|
|
21
21
|
import { getBlockingReworkFindingsForTask, getGateResults, getPendingGatesForTurn } from "./gsd-db.js";
|
|
@@ -47,6 +47,12 @@ export { buildSkillActivationBlock, buildSkillDiscoveryVars };
|
|
|
47
47
|
* from their configured executor window.
|
|
48
48
|
*/
|
|
49
49
|
const MAX_PREAMBLE_CHARS = 20_000;
|
|
50
|
+
function prependLanguageDirectiveForBase(base, prompt) {
|
|
51
|
+
const directive = renderLanguageDirectiveForPrompt(loadEffectiveGSDPreferences(base)?.preferences);
|
|
52
|
+
if (!directive || prompt.startsWith(directive))
|
|
53
|
+
return prompt;
|
|
54
|
+
return `${directive}\n\n${prompt}`;
|
|
55
|
+
}
|
|
50
56
|
/**
|
|
51
57
|
* Resolve prompt budgets from the configured executor context window.
|
|
52
58
|
*
|
|
@@ -62,13 +68,29 @@ function resolvePromptBudgets() {
|
|
|
62
68
|
const prefs = loadEffectiveGSDPreferences();
|
|
63
69
|
const sessionWindow = prefs?.preferences.context_window_override;
|
|
64
70
|
const windowTokens = resolveExecutorContextWindow(undefined, prefs?.preferences, sessionWindow);
|
|
65
|
-
return computeBudgets(windowTokens);
|
|
71
|
+
return computeBudgets(windowTokens, resolveExecutionProvider(prefs?.preferences));
|
|
66
72
|
}
|
|
67
73
|
catch (e) {
|
|
68
74
|
logWarning("prompt", `resolvePromptBudgets failed: ${e.message}`);
|
|
69
75
|
return computeBudgets(200_000);
|
|
70
76
|
}
|
|
71
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Best-effort provider for the chars/token ratio: the executor's configured
|
|
80
|
+
* model profile is the only provider source reachable here (the runtime
|
|
81
|
+
* `sessionProvider` that reaches `formatExecutorConstraints` isn't threaded to
|
|
82
|
+
* `capPreamble`/summary callers). Undefined when no explicit provider is set —
|
|
83
|
+
* `computeBudgets` then uses the 4.0 default, i.e. today's behavior.
|
|
84
|
+
*/
|
|
85
|
+
function resolveExecutionProvider(prefs) {
|
|
86
|
+
const exec = prefs?.models?.execution;
|
|
87
|
+
if (exec && typeof exec === "object" && "provider" in exec) {
|
|
88
|
+
const provider = exec.provider;
|
|
89
|
+
if (typeof provider === "string" && provider)
|
|
90
|
+
return provider;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
72
94
|
/**
|
|
73
95
|
* Character budget for dependency/prior slice summaries injected into dispatch
|
|
74
96
|
* prompts. Scales with the executor's configured context window (issue #4435).
|
|
@@ -200,7 +222,7 @@ function formatCloseoutReviewInstructions(validationContent, validationRel, curr
|
|
|
200
222
|
`No passing validation artifact was found at \`${validationRel}\`. Use the full closeout review path before completion.`,
|
|
201
223
|
].join("\n");
|
|
202
224
|
}
|
|
203
|
-
function capPreamble(preamble) {
|
|
225
|
+
export function capPreamble(preamble) {
|
|
204
226
|
// Cap inlined context at min(static ceiling, scaled inline budget).
|
|
205
227
|
// The ceiling bounds repeated auto prompt payloads; the scaled
|
|
206
228
|
// budget tightens the cap for small-window users whose true safe limit is
|
|
@@ -210,6 +232,35 @@ function capPreamble(preamble) {
|
|
|
210
232
|
return preamble;
|
|
211
233
|
return truncateAtSectionBoundary(preamble, budget).content;
|
|
212
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Cap the execute-task inline blocks against one shared budget in priority
|
|
237
|
+
* order. Unlike `capPreamble` (single concatenated preamble), execute-task
|
|
238
|
+
* feeds these blocks into separate, non-contiguous template placeholders, so
|
|
239
|
+
* they can't be joined and re-split — the budget is spent block-by-block.
|
|
240
|
+
*
|
|
241
|
+
* The task plan is the authoritative execution contract: it is never truncated
|
|
242
|
+
* here (it consumes budget first, whole). Remaining budget flows to the slice
|
|
243
|
+
* excerpt, then templates, each truncated at section boundaries so the lowest-
|
|
244
|
+
* priority context drops whole trailing sections first. When the task plan
|
|
245
|
+
* alone meets or exceeds the budget, the trailing blocks are dropped rather
|
|
246
|
+
* than the task plan being cut.
|
|
247
|
+
*/
|
|
248
|
+
function capExecuteTaskInlineBlocks(taskPlan, slicePlan, templates, budgetChars) {
|
|
249
|
+
let remaining = budgetChars - taskPlan.length;
|
|
250
|
+
if (remaining <= 0) {
|
|
251
|
+
return { taskPlan, slicePlan: "", templates: "" };
|
|
252
|
+
}
|
|
253
|
+
const cappedSlice = slicePlan.length <= remaining
|
|
254
|
+
? slicePlan
|
|
255
|
+
: truncateAtSectionBoundary(slicePlan, remaining).content;
|
|
256
|
+
remaining -= cappedSlice.length;
|
|
257
|
+
const cappedTemplates = remaining <= 0
|
|
258
|
+
? ""
|
|
259
|
+
: templates.length <= remaining
|
|
260
|
+
? templates
|
|
261
|
+
: truncateAtSectionBoundary(templates, remaining).content;
|
|
262
|
+
return { taskPlan, slicePlan: cappedSlice, templates: cappedTemplates };
|
|
263
|
+
}
|
|
213
264
|
function trackPromptContext(entries, key, mode, body, reason) {
|
|
214
265
|
entries.push({
|
|
215
266
|
key,
|
|
@@ -253,7 +304,7 @@ function renderContextModeBlockForPrompt(unitType, base, renderMode = "standalon
|
|
|
253
304
|
return `${contextMode}\n\n## Context Snapshot\nSource: \`.gsd/last-snapshot.md\`\n\n${snapshot.trimEnd()}`;
|
|
254
305
|
}
|
|
255
306
|
function prependContextModeToBlock(unitType, base, block, renderMode = "standalone") {
|
|
256
|
-
const toolSurface = composeToolSurfaceInstructions(unitType, { renderMode });
|
|
307
|
+
const toolSurface = composeToolSurfaceInstructions(unitType, { renderMode, basePath: base });
|
|
257
308
|
const contextMode = renderContextModeBlockForPrompt(unitType, base, renderMode);
|
|
258
309
|
const guidance = [toolSurface, contextMode].filter(Boolean).join("\n\n");
|
|
259
310
|
if (!guidance)
|
|
@@ -310,7 +361,7 @@ function formatExecutorConstraints(sessionContextWindow, modelRegistry, sessionP
|
|
|
310
361
|
// so DEFAULT_CONTEXT_WINDOW stays the single source of truth.
|
|
311
362
|
windowTokens = resolveExecutorContextWindow(undefined, undefined, sessionContextWindow, sessionProvider);
|
|
312
363
|
}
|
|
313
|
-
const budgets = computeBudgets(windowTokens);
|
|
364
|
+
const budgets = computeBudgets(windowTokens, sessionProvider);
|
|
314
365
|
const { min, max } = budgets.taskCountRange;
|
|
315
366
|
const execWindowK = Math.round(windowTokens / 1000);
|
|
316
367
|
const perTaskBudgetK = Math.round(budgets.inlineContextBudgetChars / 1000);
|
|
@@ -1245,6 +1296,13 @@ function resolveTaskSummariesLocation(base, mid, sid) {
|
|
|
1245
1296
|
return { dir: tDir, relPrefix: `${sRel}/tasks` };
|
|
1246
1297
|
return { dir: slicePath, relPrefix: sRel };
|
|
1247
1298
|
}
|
|
1299
|
+
function summaryFileBelongsToSlice(fileName, base, mid, sid) {
|
|
1300
|
+
const tid = taskIdFromTaskFileName(fileName, "SUMMARY");
|
|
1301
|
+
if (!tid)
|
|
1302
|
+
return false;
|
|
1303
|
+
const resolved = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
|
|
1304
|
+
return resolved !== null && basename(resolved) === fileName;
|
|
1305
|
+
}
|
|
1248
1306
|
export async function getPriorTaskSummaryPaths(mid, sid, currentTid, base) {
|
|
1249
1307
|
const loc = resolveTaskSummariesLocation(base, mid, sid);
|
|
1250
1308
|
if (!loc)
|
|
@@ -1253,7 +1311,12 @@ export async function getPriorTaskSummaryPaths(mid, sid, currentTid, base) {
|
|
|
1253
1311
|
const currentNum = parseInt(currentTid.replace(/^T/, ""), 10);
|
|
1254
1312
|
return summaryFiles
|
|
1255
1313
|
.filter(f => {
|
|
1256
|
-
|
|
1314
|
+
if (!summaryFileBelongsToSlice(f, base, mid, sid))
|
|
1315
|
+
return false;
|
|
1316
|
+
const tid = taskIdFromTaskFileName(f, "SUMMARY");
|
|
1317
|
+
if (!tid)
|
|
1318
|
+
return false;
|
|
1319
|
+
const num = parseInt(tid.replace(/^T/, ""), 10);
|
|
1257
1320
|
return num < currentNum;
|
|
1258
1321
|
})
|
|
1259
1322
|
.map(f => `${loc.relPrefix}/${f}`);
|
|
@@ -1280,8 +1343,11 @@ export async function getDependencyTaskSummaryPaths(mid, sid, currentTid, depend
|
|
|
1280
1343
|
const depSet = new Set(dependsOn.map((d) => d.toUpperCase()));
|
|
1281
1344
|
return summaryFiles
|
|
1282
1345
|
.filter((f) => {
|
|
1283
|
-
|
|
1284
|
-
|
|
1346
|
+
if (!summaryFileBelongsToSlice(f, base, mid, sid))
|
|
1347
|
+
return false;
|
|
1348
|
+
const tid = taskIdFromTaskFileName(f, "SUMMARY");
|
|
1349
|
+
if (!tid)
|
|
1350
|
+
return false;
|
|
1285
1351
|
return depSet.has(tid);
|
|
1286
1352
|
})
|
|
1287
1353
|
.map((f) => `${loc.relPrefix}/${f}`);
|
|
@@ -1403,7 +1469,7 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base, structure
|
|
|
1403
1469
|
if (headless) {
|
|
1404
1470
|
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1405
1471
|
const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
|
|
1406
|
-
|
|
1472
|
+
const prompt = loadPrompt("discuss-headless", {
|
|
1407
1473
|
seedContext: roadmapContent ?? "",
|
|
1408
1474
|
inlinedTemplates: contextTemplate,
|
|
1409
1475
|
workingDirectory: base,
|
|
@@ -1412,6 +1478,7 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base, structure
|
|
|
1412
1478
|
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1413
1479
|
multiMilestoneCommitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1414
1480
|
});
|
|
1481
|
+
return prependLanguageDirectiveForBase(base, prompt);
|
|
1415
1482
|
}
|
|
1416
1483
|
const rawInlinedContext = await buildDiscussMilestoneInlinedContext(mid, base);
|
|
1417
1484
|
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
@@ -1438,9 +1505,10 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base, structure
|
|
|
1438
1505
|
const truncationNote = cappedDraftSeed !== draftSeed
|
|
1439
1506
|
? `\n\n_(Draft seed truncated; read the full draft at \`${draftRelPath}\` if needed.)_`
|
|
1440
1507
|
: "";
|
|
1441
|
-
|
|
1508
|
+
const promptWithDraftSeed = `${promptWithContextMode}\n\n## Prior Discussion (Draft Seed)\n\nThe following draft was captured from a prior multi-milestone discussion. Use it as seed material — the user has already provided this context. Start with a brief reflection on what the draft covers, then probe for any gaps or open questions before writing the full CONTEXT.md.\n\n${cappedDraftSeed}${truncationNote}`;
|
|
1509
|
+
return prependLanguageDirectiveForBase(base, promptWithDraftSeed);
|
|
1442
1510
|
}
|
|
1443
|
-
return promptWithContextMode;
|
|
1511
|
+
return prependLanguageDirectiveForBase(base, promptWithContextMode);
|
|
1444
1512
|
}
|
|
1445
1513
|
/**
|
|
1446
1514
|
* Build a prompt for the workflow-preferences unit type (deep mode).
|
|
@@ -2307,7 +2375,7 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
|
|
|
2307
2375
|
// Compute verification budget for the executor's context window (issue #707)
|
|
2308
2376
|
const prefs = loadEffectiveGSDPreferences();
|
|
2309
2377
|
const contextWindow = resolveExecutorContextWindow(opts.modelRegistry, prefs?.preferences, opts.sessionContextWindow, opts.sessionProvider);
|
|
2310
|
-
const budgets = computeBudgets(contextWindow);
|
|
2378
|
+
const budgets = computeBudgets(contextWindow, opts.sessionProvider);
|
|
2311
2379
|
const verificationBudget = `~${Math.round(budgets.verificationBudgetChars / 1000)}K chars`;
|
|
2312
2380
|
// Truncate carry-forward section when it exceeds 40% of inline context budget.
|
|
2313
2381
|
const carryForwardBudget = Math.floor(budgets.inlineContextBudgetChars * 0.4);
|
|
@@ -2409,10 +2477,19 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
|
|
|
2409
2477
|
}
|
|
2410
2478
|
},
|
|
2411
2479
|
});
|
|
2412
|
-
const
|
|
2413
|
-
const
|
|
2480
|
+
const rawTaskPlanInline = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "task-plan");
|
|
2481
|
+
const rawSlicePlanExcerpt = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "slice-plan");
|
|
2414
2482
|
const contractedCarryForward = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "prior-task-summaries");
|
|
2415
|
-
const
|
|
2483
|
+
const rawContractedTemplates = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "templates");
|
|
2484
|
+
// Cap the static inline blocks against one shared budget so a small-window
|
|
2485
|
+
// executor can't overflow (the sibling builders cap via `capPreamble`;
|
|
2486
|
+
// execute-task's blocks feed separate template slots, so they share a budget
|
|
2487
|
+
// block-by-block). Carry-forward already has its own truncation above.
|
|
2488
|
+
const inlineBudget = Math.min(MAX_PREAMBLE_CHARS, budgets.inlineContextBudgetChars);
|
|
2489
|
+
const { taskPlan: taskPlanInline, slicePlan: slicePlanExcerpt, templates: contractedTemplates } = capExecuteTaskInlineBlocks(rawTaskPlanInline, rawSlicePlanExcerpt, rawContractedTemplates, inlineBudget);
|
|
2490
|
+
const inlineDropped = (rawTaskPlanInline.length + rawSlicePlanExcerpt.length + rawContractedTemplates.length)
|
|
2491
|
+
- (taskPlanInline.length + slicePlanExcerpt.length + contractedTemplates.length);
|
|
2492
|
+
trackPromptContext(contextTelemetry, "inline-cap", inlineDropped > 0 ? "excerpt" : "skipped", null, inlineDropped > 0 ? `dropped ${inlineDropped} chars (budget ${inlineBudget})` : "within budget");
|
|
2416
2493
|
const onDemandResult = renderExecuteTaskOnDemandContext(base, mid, sid, contractedContext.onDemand);
|
|
2417
2494
|
const onDemandContext = onDemandResult.text;
|
|
2418
2495
|
trackPromptContext(contextTelemetry, "slice-research", onDemandContext ? "on-demand" : "skipped", onDemandContext, onDemandContext ? undefined : onDemandResult.skipReason ?? undefined);
|
|
@@ -2497,12 +2574,14 @@ export async function buildCompleteSlicePrompt(mid, midTitle, sid, sTitle, base,
|
|
|
2497
2574
|
trackPromptContext(contextTelemetry, "prior-task-summaries", "skipped", null, "missing tasks dir");
|
|
2498
2575
|
return null;
|
|
2499
2576
|
}
|
|
2500
|
-
const summaryFiles = resolveTaskFiles(loc.dir, "SUMMARY")
|
|
2577
|
+
const summaryFiles = resolveTaskFiles(loc.dir, "SUMMARY")
|
|
2578
|
+
.filter((file) => summaryFileBelongsToSlice(file, base, mid, sid))
|
|
2579
|
+
.sort();
|
|
2501
2580
|
const blocks = [];
|
|
2502
2581
|
for (const file of summaryFiles) {
|
|
2503
2582
|
const absPath = join(loc.dir, file);
|
|
2504
2583
|
const relPath = `${loc.relPrefix}/${file}`;
|
|
2505
|
-
const taskId = file.replace(/-SUMMARY\.md$/i, "");
|
|
2584
|
+
const taskId = taskIdFromTaskFileName(file, "SUMMARY") ?? file.replace(/-SUMMARY\.md$/i, "");
|
|
2506
2585
|
blocks.push(await buildTaskSummaryExcerpt(absPath, relPath, taskId));
|
|
2507
2586
|
}
|
|
2508
2587
|
const body = blocks.length > 0 ? blocks.join("\n\n---\n\n") : null;
|
|
@@ -3072,7 +3151,9 @@ export async function buildReplanSlicePrompt(mid, midTitle, sid, sTitle, base) {
|
|
|
3072
3151
|
let blockerTaskId = "";
|
|
3073
3152
|
const summaryLoc = resolveTaskSummariesLocation(base, mid, sid);
|
|
3074
3153
|
if (summaryLoc) {
|
|
3075
|
-
const summaryFiles = resolveTaskFiles(summaryLoc.dir, "SUMMARY")
|
|
3154
|
+
const summaryFiles = resolveTaskFiles(summaryLoc.dir, "SUMMARY")
|
|
3155
|
+
.filter((file) => summaryFileBelongsToSlice(file, base, mid, sid))
|
|
3156
|
+
.sort();
|
|
3076
3157
|
for (const file of summaryFiles) {
|
|
3077
3158
|
const absPath = join(summaryLoc.dir, file);
|
|
3078
3159
|
const content = await loadFile(absPath);
|
|
@@ -3081,7 +3162,7 @@ export async function buildReplanSlicePrompt(mid, midTitle, sid, sTitle, base) {
|
|
|
3081
3162
|
const summary = parseSummary(content);
|
|
3082
3163
|
const relPath = `${summaryLoc.relPrefix}/${file}`;
|
|
3083
3164
|
if (summary.frontmatter.blocker_discovered) {
|
|
3084
|
-
blockerTaskId = summary.frontmatter.id || file.replace(/-SUMMARY\.md$/i, "");
|
|
3165
|
+
blockerTaskId = summary.frontmatter.id || taskIdFromTaskFileName(file, "SUMMARY") || file.replace(/-SUMMARY\.md$/i, "");
|
|
3085
3166
|
inlined.push(await buildTaskSummaryExcerpt(absPath, relPath, blockerTaskId, { blocker: true }));
|
|
3086
3167
|
}
|
|
3087
3168
|
}
|
|
@@ -17,7 +17,7 @@ import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
|
|
|
17
17
|
import { getErrorMessage } from "./error-utils.js";
|
|
18
18
|
import { logWarning } from "./workflow-logger.js";
|
|
19
19
|
import { isClosedStatus, isInactiveStatus } from "./status-guards.js";
|
|
20
|
-
import { resolveSlicePath,
|
|
20
|
+
import { resolveSlicePath, resolveTaskFile, relMilestoneFile, relSliceFile, clearPathCache, } from "./paths.js";
|
|
21
21
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
22
22
|
import { dirname } from "node:path";
|
|
23
23
|
import { resolveExpectedArtifactPath, diagnoseExpectedArtifact, } from "./auto-artifact-paths.js";
|
|
@@ -227,10 +227,15 @@ export function writeReactiveExecuteBlocker(unitId, base, reason) {
|
|
|
227
227
|
const slicePath = resolveSlicePath(base, mid, sid);
|
|
228
228
|
if (!slicePath)
|
|
229
229
|
return null;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const
|
|
230
|
+
// Resolve each batch task's SUMMARY with slice-qualified paths so flat-phase
|
|
231
|
+
// slices that reuse a task id (e.g. two T03s in one phase) don't collide: a
|
|
232
|
+
// sibling slice's summary must never make this slice's task look complete.
|
|
233
|
+
const hasSummary = (tid) => {
|
|
234
|
+
const summaryPath = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
|
|
235
|
+
return summaryPath !== null && existsSync(summaryPath);
|
|
236
|
+
};
|
|
237
|
+
const summaryPresent = batchIds.filter((tid) => hasSummary(tid));
|
|
238
|
+
const summaryMissing = batchIds.filter((tid) => !hasSummary(tid));
|
|
234
239
|
const completedTaskIds = [];
|
|
235
240
|
const skippedTaskIds = [];
|
|
236
241
|
const unchangedTaskIds = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// GSD auto-mode runtime state
|
|
2
2
|
import { AutoSession } from "./auto/session.js";
|
|
3
|
-
import {
|
|
3
|
+
import { markToolEnd as markTrackedToolEnd, markToolStart as markTrackedToolStart, shouldClearToolInvocationErrorAfterSuccess, updateToolInvocationError, } from "./auto-tool-tracking.js";
|
|
4
4
|
// Re-exported as a pure pass-through. Must stay UNGATED (no autoSession.active
|
|
5
5
|
// argument, unlike markToolStart at the bottom of this file) so it is true in
|
|
6
6
|
// foreground where the foreground approval-gate pause consults it.
|
|
@@ -61,13 +61,13 @@ export function markToolEnd(toolCallId) {
|
|
|
61
61
|
export function recordToolInvocationError(toolName, errorMsg) {
|
|
62
62
|
if (!autoSession.active)
|
|
63
63
|
return;
|
|
64
|
-
|
|
65
|
-
autoSession.lastToolInvocationError = `${toolName}: ${errorMsg}`;
|
|
66
|
-
}
|
|
64
|
+
autoSession.lastToolInvocationError = updateToolInvocationError(autoSession.lastToolInvocationError, toolName, errorMsg);
|
|
67
65
|
}
|
|
68
|
-
export function clearToolInvocationError() {
|
|
66
|
+
export function clearToolInvocationError(successfulToolName) {
|
|
69
67
|
if (!autoSession.active)
|
|
70
68
|
return;
|
|
69
|
+
if (!shouldClearToolInvocationErrorAfterSuccess(autoSession.lastToolInvocationError, successfulToolName))
|
|
70
|
+
return;
|
|
71
71
|
autoSession.lastToolInvocationError = null;
|
|
72
72
|
}
|
|
73
73
|
export function getSourceObservationStore() {
|