@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0-dev.5fc22c6f
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 +11 -11
- package/dist/cli.js +17 -4
- package/dist/headless-answers.js +1 -1
- package/dist/headless-ui.d.ts +1 -1
- package/dist/headless-ui.js +1 -1
- package/dist/headless.js +1 -1
- package/dist/onboarding.js +11 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +20 -25
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +61 -50
- package/dist/resources/extensions/cursor-cli/index.js +16 -0
- package/dist/resources/extensions/cursor-cli/models.js +63 -0
- package/dist/resources/extensions/cursor-cli/package.json +11 -0
- package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
- package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
- package/dist/resources/extensions/gsd/activity-log.js +4 -1
- package/dist/resources/extensions/gsd/artifact-verification.js +431 -0
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
- package/dist/resources/extensions/gsd/auto-budget.js +5 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +32 -11
- package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
- package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +83 -25
- package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
- package/dist/resources/extensions/gsd/auto-start.js +4 -3
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -3
- package/dist/resources/extensions/gsd/auto-verification.js +5 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +38 -11
- package/dist/resources/extensions/gsd/auto.js +32 -10
- package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +8 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +147 -23
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +56 -36
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +29 -5
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
- package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +154 -2
- package/dist/resources/extensions/gsd/commands-usage.js +1 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
- package/dist/resources/extensions/gsd/db/engine.js +4 -1
- package/dist/resources/extensions/gsd/db/queries.js +39 -0
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
- package/dist/resources/extensions/gsd/db-workspace.js +55 -3
- package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
- package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -4
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +227 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
- package/dist/resources/extensions/gsd/doctor.js +93 -3
- package/dist/resources/extensions/gsd/exec-sandbox.js +14 -4
- package/dist/resources/extensions/gsd/flat-phase-migration.js +119 -23
- package/dist/resources/extensions/gsd/git-service.js +61 -8
- package/dist/resources/extensions/gsd/gitignore.js +4 -1
- package/dist/resources/extensions/gsd/guidance.js +1 -0
- package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
- package/dist/resources/extensions/gsd/guided-flow.js +40 -2
- package/dist/resources/extensions/gsd/json-persistence.js +20 -0
- package/dist/resources/extensions/gsd/key-manager.js +1 -0
- package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
- package/dist/resources/extensions/gsd/layout-policy.js +3 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +27 -15
- package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
- package/dist/resources/extensions/gsd/metrics.js +4 -4
- package/dist/resources/extensions/gsd/migrate-external.js +22 -5
- package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
- package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
- package/dist/resources/extensions/gsd/preferences-models.js +6 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +25 -2
- package/dist/resources/extensions/gsd/preferences.js +29 -2
- package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
- package/dist/resources/extensions/gsd/repository-registry.js +6 -1
- package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
- package/dist/resources/extensions/gsd/safe-fs.js +23 -2
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
- package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -1
- package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
- package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
- package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
- package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
- package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
- package/dist/resources/extensions/gsd/state.js +12 -611
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
- package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
- package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
- package/dist/resources/extensions/gsd/tools/plan-task.js +103 -12
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
- package/dist/resources/extensions/gsd/undo.js +43 -6
- package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
- package/dist/resources/extensions/gsd/unit-registry.js +11 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
- package/dist/resources/extensions/gsd/verification-gate.js +7 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
- package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
- package/dist/resources/extensions/gsd/workspace.js +26 -8
- package/dist/resources/extensions/gsd/worktree-manager.js +140 -5
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/wizard.d.ts +8 -0
- package/dist/wizard.js +8 -1
- package/integrations/hermes/__init__.py +31 -0
- package/integrations/hermes/tests/test_directory_loader.py +37 -0
- package/package.json +8 -8
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
- package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
- package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-runtime.js +25 -1
- package/packages/daemon/dist/cloud-runtime.js.map +1 -1
- package/packages/daemon/dist/cloud-runtime.test.js +51 -0
- package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
- package/packages/daemon/dist/message-batcher.d.ts +7 -0
- package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
- package/packages/daemon/dist/message-batcher.js +13 -0
- package/packages/daemon/dist/message-batcher.js.map +1 -1
- package/packages/daemon/dist/message-batcher.test.js +48 -0
- package/packages/daemon/dist/message-batcher.test.js.map +1 -1
- package/packages/daemon/package.json +5 -5
- package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
- package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/agent-session.js +3 -0
- package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
- package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
- package/packages/gsd-agent-core/dist/index.d.ts +2 -0
- package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/index.js +2 -0
- package/packages/gsd-agent-core/dist/index.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
- package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
- package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
- package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
- package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
- package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -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 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
- 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 +26 -841
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +259 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +24 -6
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
- package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.js +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-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/env-api-keys.d.ts.map +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +3 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +46 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +38 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -2
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +3 -2
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
- package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
- package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
- package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
- package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
- package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
- package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
- package/packages/pi-coding-agent/dist/theme/theme.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/dist/rpc-client.js +1 -1
- package/packages/rpc-client/dist/rpc-client.js.map +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme-schema.d.ts +75 -75
- package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
- package/pkg/dist/theme/theme-schema.js +1 -1
- package/pkg/dist/theme/theme-schema.js.map +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +11 -7
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/scripts/link-workspace-packages.cjs +14 -4
- package/src/resources/GSD-WORKFLOW.md +20 -25
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +67 -49
- package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +159 -0
- package/src/resources/extensions/cursor-cli/index.ts +18 -0
- package/src/resources/extensions/cursor-cli/models.ts +65 -0
- package/src/resources/extensions/cursor-cli/package.json +11 -0
- package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
- package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
- package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
- package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
- package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
- package/src/resources/extensions/gsd/activity-log.ts +4 -1
- package/src/resources/extensions/gsd/artifact-verification.ts +468 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/session.ts +14 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
- package/src/resources/extensions/gsd/auto-budget.ts +12 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +34 -12
- package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
- package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +80 -25
- package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
- package/src/resources/extensions/gsd/auto-start.ts +4 -3
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +7 -2
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +50 -11
- package/src/resources/extensions/gsd/auto.ts +36 -8
- package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +8 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +171 -23
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +60 -37
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -5
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +136 -2
- package/src/resources/extensions/gsd/commands-usage.ts +1 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
- package/src/resources/extensions/gsd/db/engine.ts +8 -1
- package/src/resources/extensions/gsd/db/queries.ts +40 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
- package/src/resources/extensions/gsd/db-workspace.ts +61 -3
- package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
- package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -4
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +275 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
- package/src/resources/extensions/gsd/doctor-types.ts +8 -1
- package/src/resources/extensions/gsd/doctor.ts +95 -3
- package/src/resources/extensions/gsd/exec-sandbox.ts +13 -4
- package/src/resources/extensions/gsd/flat-phase-migration.ts +142 -22
- package/src/resources/extensions/gsd/git-service.ts +70 -9
- package/src/resources/extensions/gsd/gitignore.ts +4 -1
- package/src/resources/extensions/gsd/guidance.ts +2 -0
- package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
- package/src/resources/extensions/gsd/guided-flow.ts +45 -2
- package/src/resources/extensions/gsd/json-persistence.ts +20 -0
- package/src/resources/extensions/gsd/key-manager.ts +1 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
- package/src/resources/extensions/gsd/layout-policy.ts +2 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +27 -17
- package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
- package/src/resources/extensions/gsd/metrics.ts +4 -4
- package/src/resources/extensions/gsd/migrate-external.ts +17 -4
- package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
- package/src/resources/extensions/gsd/model-router.ts +4 -5
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
- package/src/resources/extensions/gsd/preferences-models.ts +6 -3
- package/src/resources/extensions/gsd/preferences-validation.ts +28 -2
- package/src/resources/extensions/gsd/preferences.ts +38 -4
- package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
- package/src/resources/extensions/gsd/repository-registry.ts +7 -1
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
- package/src/resources/extensions/gsd/safe-fs.ts +22 -2
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -1
- package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
- package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
- package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
- package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
- package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
- package/src/resources/extensions/gsd/state.ts +32 -732
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
- package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
- package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +138 -1
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +296 -2
- package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +74 -2
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +307 -1
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
- package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +214 -6
- package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +31 -1
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
- package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
- package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
- package/src/resources/extensions/gsd/tools/plan-task.ts +135 -12
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
- package/src/resources/extensions/gsd/undo.ts +47 -6
- package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
- package/src/resources/extensions/gsd/unit-registry.ts +11 -3
- package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
- package/src/resources/extensions/gsd/verification-gate.ts +8 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
- package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
- package/src/resources/extensions/gsd/workspace.ts +42 -8
- package/src/resources/extensions/gsd/worktree-manager.ts +183 -5
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
- package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_ssgManifest.js +0 -0
|
@@ -32,9 +32,16 @@ import {
|
|
|
32
32
|
recordAutoToolSurfaceSnapshot,
|
|
33
33
|
recordToolInvocationError,
|
|
34
34
|
} from "../auto-runtime-state.js";
|
|
35
|
+
import {
|
|
36
|
+
isDeterministicPolicyError,
|
|
37
|
+
isQueuedUserMessageSkip,
|
|
38
|
+
isToolInvocationError,
|
|
39
|
+
isToolUnavailableError,
|
|
40
|
+
} from "../auto-tool-tracking.js";
|
|
35
41
|
import { applyProviderPayloadPolicy } from "../provider-payload-policy.js";
|
|
36
42
|
|
|
37
|
-
import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
43
|
+
import { checkToolCallLoop, recordToolCallLoopMutation, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
|
|
44
|
+
import { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
|
|
38
45
|
import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
|
|
39
46
|
import { saveActivityLog } from "../activity-log.js";
|
|
40
47
|
import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
|
|
@@ -75,9 +82,25 @@ import { supportsSourceObservationsForUnit } from "../source-observations.js";
|
|
|
75
82
|
import { clearPendingAutoStart } from "../pending-auto-start.js";
|
|
76
83
|
import { resolveWorkflowToolBasePath } from "./dynamic-tools.js";
|
|
77
84
|
import { getRequiredWorkflowToolsForUnit } from "../unit-tool-contracts.js";
|
|
85
|
+
import { flushAllManifests } from "../workflow-manifest.js";
|
|
86
|
+
import { recordUnitHarnessAbort, type UnitHarnessAbortRecord } from "../unit-runtime.js";
|
|
78
87
|
|
|
79
88
|
let approvalQuestionAbortInFlight = false;
|
|
80
89
|
|
|
90
|
+
function recordCurrentUnitHarnessAbort(
|
|
91
|
+
abort: Omit<UnitHarnessAbortRecord, "recordedAt"> & { recordedAt?: number },
|
|
92
|
+
): void {
|
|
93
|
+
const dash = getAutoRuntimeSnapshot();
|
|
94
|
+
if (!dash.active || !dash.basePath || !dash.currentUnit) return;
|
|
95
|
+
recordUnitHarnessAbort(
|
|
96
|
+
dash.basePath,
|
|
97
|
+
dash.currentUnit.type,
|
|
98
|
+
dash.currentUnit.id,
|
|
99
|
+
dash.currentUnit.startedAt,
|
|
100
|
+
abort,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
81
104
|
type WelcomeScreenModule = {
|
|
82
105
|
buildWelcomeScreenLines(opts: { version: string; remoteChannel?: string; width?: number }): string[];
|
|
83
106
|
};
|
|
@@ -178,22 +201,7 @@ export const MINIMAL_GSD_TOOL_NAMES = [
|
|
|
178
201
|
"gsd_capture_thought",
|
|
179
202
|
] as const;
|
|
180
203
|
|
|
181
|
-
export
|
|
182
|
-
"ask_user_questions",
|
|
183
|
-
"bash",
|
|
184
|
-
"bg_shell",
|
|
185
|
-
"edit",
|
|
186
|
-
"find",
|
|
187
|
-
"glob",
|
|
188
|
-
"grep",
|
|
189
|
-
"fetch_page",
|
|
190
|
-
"search-the-web",
|
|
191
|
-
"ls",
|
|
192
|
-
"read",
|
|
193
|
-
"subagent",
|
|
194
|
-
"write",
|
|
195
|
-
"ToolSearch",
|
|
196
|
-
] as const;
|
|
204
|
+
export { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
|
|
197
205
|
|
|
198
206
|
function withPreservedShimTools(toolNames: readonly string[]): string[] {
|
|
199
207
|
return [...new Set([...toolNames, ...ALWAYS_PRESERVED_SHIM_TOOL_NAMES])];
|
|
@@ -222,10 +230,26 @@ const WORKFLOW_GSD_TOOL_NAMES = [
|
|
|
222
230
|
...Object.values(AUTO_UNIT_SCOPED_TOOLS).flat(),
|
|
223
231
|
].filter(isGsdManagedTool);
|
|
224
232
|
|
|
233
|
+
const WORKFLOW_ONLY_AUTO_BASE_TOOL_NAMES = [
|
|
234
|
+
"find",
|
|
235
|
+
"glob",
|
|
236
|
+
"grep",
|
|
237
|
+
"ls",
|
|
238
|
+
"read",
|
|
239
|
+
"subagent",
|
|
240
|
+
] as const;
|
|
241
|
+
|
|
225
242
|
function isGsdManagedTool(name: string): boolean {
|
|
226
243
|
return name.startsWith("gsd_") || name === "memory_query" || name === "capture_thought" || name === "gsd_graph";
|
|
227
244
|
}
|
|
228
245
|
|
|
246
|
+
function autoBaseToolNamesForUnit(unitType: string | undefined): readonly string[] {
|
|
247
|
+
const manifest = unitType ? resolveManifest(unitType) : null;
|
|
248
|
+
return manifest?.tools.mode === "workflow-only"
|
|
249
|
+
? WORKFLOW_ONLY_AUTO_BASE_TOOL_NAMES
|
|
250
|
+
: MINIMAL_AUTO_BASE_TOOL_NAMES;
|
|
251
|
+
}
|
|
252
|
+
|
|
229
253
|
/**
|
|
230
254
|
* Resolves requested tool names against active tools using exact and MCP-scoped matches.
|
|
231
255
|
*
|
|
@@ -288,7 +312,7 @@ export function buildMinimalAutoGsdToolSet(
|
|
|
288
312
|
return buildRunUatGsdToolSet(activeToolNames, registeredToolNames);
|
|
289
313
|
}
|
|
290
314
|
const unitTools = unitType ? AUTO_UNIT_SCOPED_TOOLS[unitType] ?? [] : [];
|
|
291
|
-
const autoBaseTools = new Set<string>(
|
|
315
|
+
const autoBaseTools = new Set<string>(autoBaseToolNamesForUnit(unitType));
|
|
292
316
|
const availableBaseTools = registeredToolNames.filter((name) => autoBaseTools.has(name));
|
|
293
317
|
const preserved = [...new Set([
|
|
294
318
|
...activeToolNames.filter((name) => autoBaseTools.has(name)),
|
|
@@ -597,6 +621,87 @@ function contextBasePath(ctx?: { cwd?: string }): string {
|
|
|
597
621
|
return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
|
|
598
622
|
}
|
|
599
623
|
|
|
624
|
+
const LOOP_GUARD_INTERACTIVE_INSTRUCTIONS = [
|
|
625
|
+
"Do not retry this tool or call other tools this turn — stop and respond to the user in text.",
|
|
626
|
+
"Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.",
|
|
627
|
+
];
|
|
628
|
+
const LOOP_GUARD_AUTO_INSTRUCTION =
|
|
629
|
+
"Do not re-issue this blocked tool. In /gsd auto, stop tool calls for this turn and return control to the auto-mode recovery/replan path.";
|
|
630
|
+
|
|
631
|
+
function formatLoopGuardBlockReason(reason: string | undefined): string | undefined {
|
|
632
|
+
if (!reason || !getAutoRuntimeSnapshot().active) return reason;
|
|
633
|
+
return LOOP_GUARD_INTERACTIVE_INSTRUCTIONS.reduce(
|
|
634
|
+
(formatted, instruction) => formatted.replace(instruction, LOOP_GUARD_AUTO_INSTRUCTION),
|
|
635
|
+
reason,
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function isGateResultPersistenceTool(toolName: string): boolean {
|
|
640
|
+
return toolName === "gsd_save_gate_result" || toolName === "gsd_uat_result_save";
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function resultDetails(result: unknown): Record<string, unknown> {
|
|
644
|
+
if (!result || typeof result !== "object") return {};
|
|
645
|
+
const details = (result as { details?: unknown }).details;
|
|
646
|
+
return details && typeof details === "object" ? details as Record<string, unknown> : {};
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
function isAbortedExecutionToolResult(toolName: string, result: unknown): boolean {
|
|
650
|
+
if (toolName !== "gsd_exec" && toolName !== "gsd_uat_exec") return false;
|
|
651
|
+
const details = resultDetails(result);
|
|
652
|
+
return details.aborted === true || details.force_resolved === true || details.timed_out === true;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function isRetryableHarnessToolError(toolName: string, result: unknown, errorText: string): boolean {
|
|
656
|
+
if (isGateResultPersistenceTool(toolName)) return false;
|
|
657
|
+
if (isDeterministicPolicyError(errorText)) return false;
|
|
658
|
+
if (toolName === "gsd_exec" || toolName === "gsd_uat_exec") {
|
|
659
|
+
if (isAbortedExecutionToolResult(toolName, result)) return true;
|
|
660
|
+
if (isToolUnavailableError(errorText)) return true;
|
|
661
|
+
if (isQueuedUserMessageSkip(errorText)) return true;
|
|
662
|
+
return isToolInvocationError(errorText);
|
|
663
|
+
}
|
|
664
|
+
if (isToolUnavailableError(errorText)) return true;
|
|
665
|
+
if (isQueuedUserMessageSkip(errorText)) return true;
|
|
666
|
+
return false;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function recordRetryableHarnessToolError(toolName: string, result: unknown, errorText: string): void {
|
|
670
|
+
if (!isRetryableHarnessToolError(toolName, result, errorText)) return;
|
|
671
|
+
recordCurrentUnitHarnessAbort({
|
|
672
|
+
kind: "tool-error",
|
|
673
|
+
reason: errorText || "Tool execution failed before the unit could complete its gate evaluation.",
|
|
674
|
+
toolName,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function recordRetryableTurnAbort(event: { abortOrigin?: unknown; messages?: unknown[] }): void {
|
|
679
|
+
const origin = typeof event.abortOrigin === "string" ? event.abortOrigin : undefined;
|
|
680
|
+
if (origin === "session-transition") return;
|
|
681
|
+
|
|
682
|
+
const messages = Array.isArray(event.messages) ? event.messages : [];
|
|
683
|
+
const lastMsg = messages[messages.length - 1];
|
|
684
|
+
const stopReason = lastMsg && typeof lastMsg === "object"
|
|
685
|
+
? (lastMsg as { stopReason?: unknown }).stopReason
|
|
686
|
+
: undefined;
|
|
687
|
+
if (stopReason !== "aborted" && stopReason !== "error") return;
|
|
688
|
+
|
|
689
|
+
const errorMessage = lastMsg && typeof lastMsg === "object"
|
|
690
|
+
? (lastMsg as { errorMessage?: unknown }).errorMessage
|
|
691
|
+
: undefined;
|
|
692
|
+
const reason = [
|
|
693
|
+
"Agent turn aborted before the unit could complete its gate evaluation.",
|
|
694
|
+
origin ? `origin=${origin}` : undefined,
|
|
695
|
+
typeof stopReason === "string" ? `stopReason=${stopReason}` : undefined,
|
|
696
|
+
typeof errorMessage === "string" && errorMessage.trim() ? `error=${errorMessage.trim()}` : undefined,
|
|
697
|
+
].filter(Boolean).join(" ");
|
|
698
|
+
|
|
699
|
+
recordCurrentUnitHarnessAbort({
|
|
700
|
+
kind: "turn-abort",
|
|
701
|
+
reason,
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
|
|
600
705
|
function beginSourceObservationStoreForCurrentUnit(
|
|
601
706
|
ctx?: { cwd?: string },
|
|
602
707
|
): ReturnType<typeof getSourceObservationStore> | null {
|
|
@@ -900,8 +1005,8 @@ export function registerHooks(
|
|
|
900
1005
|
await prepareWorkflowMcpForHookContext(ctx, basePath);
|
|
901
1006
|
|
|
902
1007
|
// Migrate legacy .gsd/milestones/ to flat-phase .gsd/phases/ when detected.
|
|
903
|
-
//
|
|
904
|
-
//
|
|
1008
|
+
// Fail closed on migration errors: resolvers assume flat-phase paths after
|
|
1009
|
+
// startup, so continuing with nested disk state corrupts later checks.
|
|
905
1010
|
try {
|
|
906
1011
|
const { isInAutoWorktree } = await import("../auto-worktree.js");
|
|
907
1012
|
if (!isInAutoWorktree(basePath)) {
|
|
@@ -915,13 +1020,32 @@ export function registerHooks(
|
|
|
915
1020
|
} else {
|
|
916
1021
|
safetyLogWarning(
|
|
917
1022
|
"bootstrap",
|
|
918
|
-
"flat-phase migration
|
|
1023
|
+
"flat-phase migration required: legacy .gsd/milestones/ layout detected but the workflow database could not be opened — fix database access before starting GSD",
|
|
1024
|
+
);
|
|
1025
|
+
throw new Error(
|
|
1026
|
+
"flat-phase migration required but the workflow database could not be opened; fix database access before starting GSD",
|
|
919
1027
|
);
|
|
920
1028
|
}
|
|
921
1029
|
}
|
|
922
1030
|
}
|
|
923
1031
|
} catch (err) {
|
|
924
|
-
|
|
1032
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1033
|
+
safetyLogWarning("bootstrap", `flat-phase migration failed: ${message}`);
|
|
1034
|
+
throw new Error(`flat-phase migration failed: ${message}`);
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
try {
|
|
1038
|
+
const projectRoot = resolveWorktreeProjectRoot(basePath);
|
|
1039
|
+
const { pruneStaleFlatPhaseBackups } = await import("../flat-phase-migration.js");
|
|
1040
|
+
const pruned = pruneStaleFlatPhaseBackups(projectRoot);
|
|
1041
|
+
if (pruned > 0) {
|
|
1042
|
+
safetyLogWarning(
|
|
1043
|
+
"bootstrap",
|
|
1044
|
+
`pruned ${pruned} stale flat-phase migration backup(s) from .gsd-backups/ (retention exceeded)`,
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
} catch (err) {
|
|
1048
|
+
safetyLogWarning("bootstrap", `flat-phase backup pruning: ${err instanceof Error ? err.message : String(err)}`);
|
|
925
1049
|
}
|
|
926
1050
|
|
|
927
1051
|
// Apply show_token_cost preference (#1515)
|
|
@@ -1079,12 +1203,26 @@ export function registerHooks(
|
|
|
1079
1203
|
|
|
1080
1204
|
pi.on("agent_end", async (event, ctx: ExtensionContext) => {
|
|
1081
1205
|
approvalQuestionAbortInFlight = false;
|
|
1206
|
+
recordRetryableTurnAbort(event);
|
|
1082
1207
|
resetToolCallLoopGuard();
|
|
1083
1208
|
resetPendingGatePauseGuard();
|
|
1084
1209
|
await resetAskUserQuestionsTurnCache();
|
|
1085
1210
|
const { handleAgentEnd } = await import("./agent-end-recovery.js");
|
|
1086
1211
|
const agentEndBasePath = contextBasePath(ctx);
|
|
1087
1212
|
try {
|
|
1213
|
+
// The manifest is a non-critical projection (the append-only event log is
|
|
1214
|
+
// the authoritative recovery source), so a flush failure must not skip
|
|
1215
|
+
// agent_end recovery. drainManifestWrites still propagates write failures
|
|
1216
|
+
// to explicit flush callers; here we deliberately log and continue so
|
|
1217
|
+
// handleAgentEnd (and the finally below) always run.
|
|
1218
|
+
try {
|
|
1219
|
+
await flushAllManifests();
|
|
1220
|
+
} catch (err) {
|
|
1221
|
+
safetyLogWarning(
|
|
1222
|
+
"manifest",
|
|
1223
|
+
`flushAllManifests on agent_end failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1088
1226
|
await handleAgentEnd(pi, event, ctx);
|
|
1089
1227
|
} finally {
|
|
1090
1228
|
activateDeferredApprovalGate(agentEndBasePath);
|
|
@@ -1291,7 +1429,13 @@ export function registerHooks(
|
|
|
1291
1429
|
// ── Loop guard: block repeated identical tool calls ──
|
|
1292
1430
|
const loopCheck = checkToolCallLoop(toolName, event.input as Record<string, unknown>);
|
|
1293
1431
|
if (loopCheck.block) {
|
|
1294
|
-
|
|
1432
|
+
recordCurrentUnitHarnessAbort({
|
|
1433
|
+
kind: "tool-loop-guard",
|
|
1434
|
+
reason: loopCheck.reason ?? "Tool-call loop guard blocked a repeated tool call.",
|
|
1435
|
+
toolName,
|
|
1436
|
+
count: loopCheck.count,
|
|
1437
|
+
});
|
|
1438
|
+
return { block: true, reason: formatLoopGuardBlockReason(loopCheck.reason) };
|
|
1295
1439
|
}
|
|
1296
1440
|
|
|
1297
1441
|
const deferredGateGuard = shouldBlockDeferredApprovalTool(
|
|
@@ -1563,6 +1707,7 @@ export function registerHooks(
|
|
|
1563
1707
|
}
|
|
1564
1708
|
}
|
|
1565
1709
|
if (!event.isError) {
|
|
1710
|
+
recordToolCallLoopMutation(toolName);
|
|
1566
1711
|
refreshSourceObservationAfterMutation(toolName, event.input, ctx);
|
|
1567
1712
|
clearSourceObservationsAfterShell(toolName);
|
|
1568
1713
|
}
|
|
@@ -1578,6 +1723,7 @@ export function registerHooks(
|
|
|
1578
1723
|
// Let recordToolInvocationError classify the failure so non-gsd_ harness
|
|
1579
1724
|
// errors and deterministic policy rejections are handled consistently.
|
|
1580
1725
|
recordToolInvocationError(event.toolName, errorText);
|
|
1726
|
+
recordRetryableHarnessToolError(toolName, resultPayload, errorText);
|
|
1581
1727
|
} else if (isAutoActive()) {
|
|
1582
1728
|
clearToolInvocationError();
|
|
1583
1729
|
}
|
|
@@ -1774,6 +1920,7 @@ export function registerHooks(
|
|
|
1774
1920
|
// for every finalized tool call on every engine, so error classification
|
|
1775
1921
|
// and evidence persistence here cover external engines that skip tool_result.
|
|
1776
1922
|
pi.on("tool_execution_end", async (event) => {
|
|
1923
|
+
const toolName = canonicalToolName(event.toolName);
|
|
1777
1924
|
markToolEnd(event.toolCallId);
|
|
1778
1925
|
// #2883/#4974: Capture deterministic invocation/policy errors
|
|
1779
1926
|
// so postUnitPreVerification can break the retry loop instead of re-dispatching.
|
|
@@ -1784,6 +1931,7 @@ export function registerHooks(
|
|
|
1784
1931
|
// Let recordToolInvocationError classify the failure so non-gsd_ harness
|
|
1785
1932
|
// errors and deterministic policy rejections are handled consistently.
|
|
1786
1933
|
recordToolInvocationError(event.toolName, errorText);
|
|
1934
|
+
recordRetryableHarnessToolError(toolName, event.result, errorText);
|
|
1787
1935
|
} else if (isAutoActive()) {
|
|
1788
1936
|
clearToolInvocationError();
|
|
1789
1937
|
}
|
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
|
|
10
10
|
import { test, describe, before, after } from "node:test";
|
|
11
11
|
import assert from "node:assert/strict";
|
|
12
|
-
import { mkdtempSync, rmSync, existsSync } from "node:fs";
|
|
12
|
+
import { mkdtempSync, rmSync, existsSync, mkdirSync } from "node:fs";
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
|
|
16
16
|
import {
|
|
17
17
|
markDepthVerified,
|
|
18
18
|
loadWriteGateSnapshot,
|
|
19
|
+
shouldBlockContextArtifactSaveInSnapshot,
|
|
19
20
|
clearDiscussionFlowState,
|
|
20
21
|
} from "../write-gate.js";
|
|
21
22
|
|
|
@@ -100,4 +101,51 @@ describe("write-gate basePath regression", () => {
|
|
|
100
101
|
"loadWriteGateSnapshot(baseDirB) must not bleed state from baseDirA",
|
|
101
102
|
);
|
|
102
103
|
});
|
|
104
|
+
|
|
105
|
+
test("worktree basePath reads depth verification from project-root snapshot", (t) => {
|
|
106
|
+
const prev = process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
107
|
+
t.after(() => {
|
|
108
|
+
if (prev === undefined) {
|
|
109
|
+
delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
|
|
110
|
+
} else {
|
|
111
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = prev;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
process.env.GSD_PERSIST_WRITE_GATE_STATE = "1";
|
|
115
|
+
|
|
116
|
+
const projectRoot = makeTempDir();
|
|
117
|
+
const worktreePath = join(projectRoot, ".gsd-worktrees", "M020");
|
|
118
|
+
t.after(() => {
|
|
119
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
clearDiscussionFlowState(projectRoot);
|
|
123
|
+
clearDiscussionFlowState(worktreePath);
|
|
124
|
+
|
|
125
|
+
// Simulate MCP routing: verification recorded at project root.
|
|
126
|
+
markDepthVerified("M020", projectRoot);
|
|
127
|
+
|
|
128
|
+
// Worktree has a local .gsd projection but no write-gate snapshot file.
|
|
129
|
+
mkdirSync(join(worktreePath, ".gsd", "runtime"), { recursive: true });
|
|
130
|
+
mkdirSync(join(projectRoot, ".gsd", "milestones"), { recursive: true });
|
|
131
|
+
|
|
132
|
+
const projectSnapshotPath = join(projectRoot, ".gsd", "runtime", "write-gate-state.json");
|
|
133
|
+
const worktreeSnapshotPath = join(worktreePath, ".gsd", "runtime", "write-gate-state.json");
|
|
134
|
+
assert.ok(existsSync(projectSnapshotPath), "verification snapshot lives at project root");
|
|
135
|
+
assert.ok(!existsSync(worktreeSnapshotPath), "worktree must not have its own snapshot file");
|
|
136
|
+
|
|
137
|
+
const snapshotFromWorktree = loadWriteGateSnapshot(worktreePath);
|
|
138
|
+
assert.ok(
|
|
139
|
+
snapshotFromWorktree.verifiedDepthMilestones.includes("M020"),
|
|
140
|
+
"loadWriteGateSnapshot(worktree) must inherit project-root verification",
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const guard = shouldBlockContextArtifactSaveInSnapshot(
|
|
144
|
+
snapshotFromWorktree,
|
|
145
|
+
"CONTEXT",
|
|
146
|
+
"M020",
|
|
147
|
+
null,
|
|
148
|
+
);
|
|
149
|
+
assert.equal(guard.block, false, "CONTEXT save must unblock once project-root gate is verified");
|
|
150
|
+
});
|
|
103
151
|
});
|
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tool-call loop guard.
|
|
3
3
|
*
|
|
4
|
-
* Detects when a model calls
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Detects when a model repeats tool calls within a single Agent Turn.
|
|
5
|
+
* Works in both auto-mode and interactive sessions by hooking into the
|
|
6
|
+
* native engine's `tool_call` event, which fires before execution and can
|
|
7
|
+
* block the call.
|
|
8
8
|
*
|
|
9
|
-
* The guard
|
|
10
|
-
* and
|
|
11
|
-
*
|
|
12
|
-
* and
|
|
9
|
+
* The guard has two independent checks: a sliding window for identical
|
|
10
|
+
* tool signatures, and a per-tool-name cap for repeated calls with varied
|
|
11
|
+
* arguments. State resets at Agent Turn boundaries (session_start,
|
|
12
|
+
* agent_end) and the identical-signature streak also resets when a
|
|
13
|
+
* different tool call breaks the streak. Block messages instruct the model
|
|
14
|
+
* to stop tooling for the rest of that turn and answer in text.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* The per-tool-name check (#783 Brief C) tracks call counts within a
|
|
17
|
+
* turn regardless of args, decaying after successful state-mutating tools.
|
|
18
|
+
* This catches improvisation
|
|
16
19
|
* loops where the model attempts the same missing workflow tool through
|
|
17
20
|
* varied surfaces (bash → `node -e` → CLI), each with a different
|
|
18
|
-
* signature, so the identical-args streak never trips
|
|
21
|
+
* signature, so the identical-args streak never trips, while allowing
|
|
22
|
+
* tool-heavy turns that are making file-mutation progress. Whichever guard
|
|
19
23
|
* trips first blocks.
|
|
20
24
|
*/
|
|
21
25
|
|
|
22
26
|
import { createHash } from "node:crypto";
|
|
27
|
+
import { INHERENTLY_REPEATABLE_TOOL_SET } from "./core-session-tools.js";
|
|
28
|
+
import { hasBrowserContractPrefix } from "../../shared/browser-contract.js";
|
|
29
|
+
import { canonicalToolName } from "../engine-hook-contract.js";
|
|
23
30
|
|
|
24
31
|
const MAX_CONSECUTIVE_IDENTICAL_CALLS = 4;
|
|
25
32
|
|
|
@@ -39,27 +46,8 @@ const MAX_CONSECUTIVE_STRICT = 1;
|
|
|
39
46
|
*/
|
|
40
47
|
const PER_TOOL_DEFAULT_CAP = 6;
|
|
41
48
|
const PER_TOOL_REPEATABLE_CAP = 15;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
* Inherently-repeatable tools: called many times per turn in normal work
|
|
45
|
-
* (reading/writing several files, running several commands, searching). These
|
|
46
|
-
* get PER_TOOL_REPEATABLE_CAP rather than the default. Keep this list
|
|
47
|
-
* conservative — a tool here can be invoked up to PER_TOOL_REPEATABLE_CAP times
|
|
48
|
-
* per turn before the guard blocks.
|
|
49
|
-
*/
|
|
50
|
-
const REPEATABLE_TOOLS = new Set([
|
|
51
|
-
"read",
|
|
52
|
-
"write",
|
|
53
|
-
"edit",
|
|
54
|
-
"multi_edit",
|
|
55
|
-
"bash",
|
|
56
|
-
"grep",
|
|
57
|
-
"glob",
|
|
58
|
-
"search-the-web",
|
|
59
|
-
"fetch_page",
|
|
60
|
-
"todo_write",
|
|
61
|
-
"notebook_edit",
|
|
62
|
-
]);
|
|
49
|
+
const PER_TOOL_CAP_EXEMPT_TOOLS = new Set(["find", "glob", "grep", "ls", "read", "search_and_read"]);
|
|
50
|
+
const STATE_MUTATING_TOOL_SET = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
|
|
63
51
|
|
|
64
52
|
let consecutiveCount = 0;
|
|
65
53
|
let lastSignature = "";
|
|
@@ -68,6 +56,8 @@ let enabled = true;
|
|
|
68
56
|
|
|
69
57
|
/** Per-tool-name call counts within the current turn (#783 Brief C). */
|
|
70
58
|
const perToolCounts = new Map<string, number>();
|
|
59
|
+
let mutationEpoch = 0;
|
|
60
|
+
const perToolLastMutationEpoch = new Map<string, number>();
|
|
71
61
|
|
|
72
62
|
/** Hash tool name + args into a compact signature for comparison. */
|
|
73
63
|
function hashToolCall(toolName: string, args: Record<string, unknown>): string {
|
|
@@ -95,7 +85,8 @@ function hashToolCall(toolName: string, args: Record<string, unknown>): string {
|
|
|
95
85
|
* 1. Identical-signature streak (MAX_CONSECUTIVE_IDENTICAL_CALLS, strict for
|
|
96
86
|
* ask_user_questions).
|
|
97
87
|
* 2. Per-tool-name cap (PER_TOOL_DEFAULT_CAP / PER_TOOL_REPEATABLE_CAP),
|
|
98
|
-
* independent of args
|
|
88
|
+
* independent of args, reset after file-mutation progress — catches
|
|
89
|
+
* improvisation loops (#783).
|
|
99
90
|
*/
|
|
100
91
|
export function checkToolCallLoop(
|
|
101
92
|
toolName: string,
|
|
@@ -124,7 +115,7 @@ export function checkToolCallLoop(
|
|
|
124
115
|
reason:
|
|
125
116
|
`Tool loop detected (identical args): ${toolName} called ${consecutiveCount} times ` +
|
|
126
117
|
`with identical arguments. Blocking to prevent infinite loop. ` +
|
|
127
|
-
`
|
|
118
|
+
`Do not retry this tool or call other tools this turn — stop and respond to the user in text.`,
|
|
128
119
|
count: consecutiveCount,
|
|
129
120
|
};
|
|
130
121
|
}
|
|
@@ -132,9 +123,29 @@ export function checkToolCallLoop(
|
|
|
132
123
|
// ── Guard 2: per-tool-name cap, independent of args (#783 Brief C) ──
|
|
133
124
|
// Catches improvisation loops where the same tool is invoked many times with
|
|
134
125
|
// varied args (e.g. retrying a missing workflow tool via bash/node -e/CLI).
|
|
135
|
-
const
|
|
126
|
+
const priorPerToolCount =
|
|
127
|
+
(perToolLastMutationEpoch.get(toolName) ?? mutationEpoch) < mutationEpoch
|
|
128
|
+
? 0
|
|
129
|
+
: (perToolCounts.get(toolName) ?? 0);
|
|
130
|
+
const perToolCount = priorPerToolCount + 1;
|
|
136
131
|
perToolCounts.set(toolName, perToolCount);
|
|
137
|
-
|
|
132
|
+
perToolLastMutationEpoch.set(toolName, mutationEpoch);
|
|
133
|
+
|
|
134
|
+
// Read-only navigation tools are normal context gathering; Guard 1 still
|
|
135
|
+
// catches true reread loops with identical arguments. Browser Automation
|
|
136
|
+
// Contract tools (browser_*) are the same shape: a browser-backed UAT makes
|
|
137
|
+
// many distinct-arg calls (read a message, count edits, inspect a card, …),
|
|
138
|
+
// so the arg-independent per-tool cap misfires on legitimate verification;
|
|
139
|
+
// Guard 1's identical-signature streak still catches a genuinely stuck
|
|
140
|
+
// browser loop.
|
|
141
|
+
if (
|
|
142
|
+
PER_TOOL_CAP_EXEMPT_TOOLS.has(toolName) ||
|
|
143
|
+
hasBrowserContractPrefix(canonicalToolName(toolName))
|
|
144
|
+
) {
|
|
145
|
+
return { block: false, count: consecutiveCount };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const perToolCap = INHERENTLY_REPEATABLE_TOOL_SET.has(toolName)
|
|
138
149
|
? PER_TOOL_REPEATABLE_CAP
|
|
139
150
|
: PER_TOOL_DEFAULT_CAP;
|
|
140
151
|
|
|
@@ -144,7 +155,8 @@ export function checkToolCallLoop(
|
|
|
144
155
|
reason:
|
|
145
156
|
`Tool loop detected (repeated tool): ${toolName} called ${perToolCount} times ` +
|
|
146
157
|
`this turn (cap ${perToolCap}). Blocking to prevent infinite loop. ` +
|
|
147
|
-
`The tool may be unavailable or failing repeatedly
|
|
158
|
+
`The tool may be unavailable or failing repeatedly. ` +
|
|
159
|
+
`Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.`,
|
|
148
160
|
count: perToolCount,
|
|
149
161
|
};
|
|
150
162
|
}
|
|
@@ -152,6 +164,13 @@ export function checkToolCallLoop(
|
|
|
152
164
|
return { block: false, count: consecutiveCount };
|
|
153
165
|
}
|
|
154
166
|
|
|
167
|
+
/** Record successful mutation progress so Guard 2 can decay on the next count. */
|
|
168
|
+
export function recordToolCallLoopMutation(toolName: string): void {
|
|
169
|
+
if (!enabled) return;
|
|
170
|
+
if (!STATE_MUTATING_TOOL_SET.has(toolName)) return;
|
|
171
|
+
mutationEpoch++;
|
|
172
|
+
}
|
|
173
|
+
|
|
155
174
|
/** Reset the guard state. Call at agent turn boundaries. */
|
|
156
175
|
export function resetToolCallLoopGuard(): void {
|
|
157
176
|
consecutiveCount = 0;
|
|
@@ -159,6 +178,8 @@ export function resetToolCallLoopGuard(): void {
|
|
|
159
178
|
lastToolName = "";
|
|
160
179
|
enabled = true;
|
|
161
180
|
perToolCounts.clear();
|
|
181
|
+
mutationEpoch = 0;
|
|
182
|
+
perToolLastMutationEpoch.clear();
|
|
162
183
|
}
|
|
163
184
|
|
|
164
185
|
/** Disable the guard (e.g. during shutdown). */
|
|
@@ -168,6 +189,8 @@ export function disableToolCallLoopGuard(): void {
|
|
|
168
189
|
lastSignature = "";
|
|
169
190
|
lastToolName = "";
|
|
170
191
|
perToolCounts.clear();
|
|
192
|
+
mutationEpoch = 0;
|
|
193
|
+
perToolLastMutationEpoch.clear();
|
|
171
194
|
}
|
|
172
195
|
|
|
173
196
|
/** Get current consecutive count for diagnostics. */
|
|
@@ -97,8 +97,19 @@ function createEmptyWriteGateState(): InMemoryWriteGateState {
|
|
|
97
97
|
|
|
98
98
|
const writeGateStatesByBasePath = new Map<string, InMemoryWriteGateState>();
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Write-gate snapshots are project-scoped, not worktree-scoped. When auto-mode
|
|
102
|
+
* routes MCP tool writes to `.gsd-worktrees/<MID>/`, depth verification still
|
|
103
|
+
* lands in the authoritative project `.gsd/runtime/` tree (or external-state
|
|
104
|
+
* symlink target). Without this canonicalization, `loadWriteGateSnapshot(worktree)`
|
|
105
|
+
* sees an empty snapshot and CONTEXT saves loop forever (#M020 gate loop).
|
|
106
|
+
*/
|
|
107
|
+
function resolveWriteGateSnapshotRoot(basePath: string): string {
|
|
108
|
+
return resolve(resolveWorktreeProjectRoot(basePath));
|
|
109
|
+
}
|
|
110
|
+
|
|
100
111
|
function writeGateStateKey(basePath: string): string {
|
|
101
|
-
return
|
|
112
|
+
return resolveWriteGateSnapshotRoot(basePath);
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
function getWriteGateState(basePath: string = process.cwd()): InMemoryWriteGateState {
|
|
@@ -161,17 +172,18 @@ function shouldPersistWriteGateSnapshot(env: NodeJS.ProcessEnv = process.env): b
|
|
|
161
172
|
}
|
|
162
173
|
|
|
163
174
|
function writeGateSnapshotPath(basePath: string): string {
|
|
164
|
-
return join(basePath, ".gsd", "runtime", "write-gate-state.json");
|
|
175
|
+
return join(resolveWriteGateSnapshotRoot(basePath), ".gsd", "runtime", "write-gate-state.json");
|
|
165
176
|
}
|
|
166
177
|
|
|
167
178
|
function ensureWriteGateSnapshotDirectory(basePath: string): void {
|
|
168
|
-
const
|
|
179
|
+
const snapshotRoot = resolveWriteGateSnapshotRoot(basePath);
|
|
180
|
+
const gsdPath = join(snapshotRoot, ".gsd");
|
|
169
181
|
if (!existsSync(gsdPath)) {
|
|
170
182
|
try {
|
|
171
183
|
const stat = lstatSync(gsdPath);
|
|
172
184
|
if (stat.isSymbolicLink()) {
|
|
173
185
|
const target = readlinkSync(gsdPath);
|
|
174
|
-
mkdirSync(isAbsolute(target) ? target : resolve(
|
|
186
|
+
mkdirSync(isAbsolute(target) ? target : resolve(snapshotRoot, target), { recursive: true });
|
|
175
187
|
}
|
|
176
188
|
} catch {
|
|
177
189
|
// If .gsd truly does not exist, the runtime mkdir below will create it.
|
|
@@ -1157,7 +1169,7 @@ function allowsControlledSubagentDispatch(
|
|
|
1157
1169
|
policy: ToolsPolicy,
|
|
1158
1170
|
): policy is ToolsPolicy & { readonly allowedSubagents: readonly string[] } {
|
|
1159
1171
|
return (
|
|
1160
|
-
(policy.mode === "planning-dispatch" || policy.mode === "verification") &&
|
|
1172
|
+
(policy.mode === "planning-dispatch" || policy.mode === "verification" || policy.mode === "workflow-only") &&
|
|
1161
1173
|
Array.isArray((policy as { readonly allowedSubagents?: unknown }).allowedSubagents)
|
|
1162
1174
|
);
|
|
1163
1175
|
}
|
|
@@ -1187,6 +1199,7 @@ function warnMissingControlledDispatchAgentClasses(unitType: string, mode: strin
|
|
|
1187
1199
|
const PLANNING_SAFE_TOOLS = new Set([
|
|
1188
1200
|
"read", "grep", "find", "ls", "glob",
|
|
1189
1201
|
"ask_user_questions",
|
|
1202
|
+
"memory_query",
|
|
1190
1203
|
"search-the-web", "resolve_library", "get_library_docs", "fetch_page",
|
|
1191
1204
|
"search_and_read",
|
|
1192
1205
|
]);
|
|
@@ -1253,6 +1266,9 @@ type PlanningUnitBlockResult = {
|
|
|
1253
1266
|
* → allows Bash for project verification commands, keeps
|
|
1254
1267
|
* writes restricted to .gsd/, and permits subagent dispatch
|
|
1255
1268
|
* only when the manifest declares allowedSubagents.
|
|
1269
|
+
* - "workflow-only"
|
|
1270
|
+
* → allows reads, GSD workflow tools, and declared read-only
|
|
1271
|
+
* subagents; blocks generic Bash and direct file writes.
|
|
1256
1272
|
*
|
|
1257
1273
|
* `pathOrCommand` is the file path for write/edit-shaped tools and the
|
|
1258
1274
|
* shell command for bash. Other tools ignore this argument.
|
|
@@ -1342,6 +1358,24 @@ export function shouldBlockPlanningUnit(
|
|
|
1342
1358
|
return planningBlock(unitType, policy.mode, "subagent dispatch is not permitted in planning units");
|
|
1343
1359
|
}
|
|
1344
1360
|
|
|
1361
|
+
if (policy.mode === "workflow-only") {
|
|
1362
|
+
if (tool === "bash") {
|
|
1363
|
+
return planningBlock(
|
|
1364
|
+
unitType,
|
|
1365
|
+
policy.mode,
|
|
1366
|
+
`bash is not permitted; use the unit's dedicated GSD workflow tools for durable validation output`,
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
if (PLANNING_WRITE_TOOLS.has(tool)) {
|
|
1370
|
+
return planningBlock(
|
|
1371
|
+
unitType,
|
|
1372
|
+
policy.mode,
|
|
1373
|
+
`cannot ${tool} "${pathOrCommand}" — direct artifact writes are disabled; call the required GSD workflow tool instead`,
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
return planningBlock(unitType, policy.mode, `tool "${tool}" is not on the workflow-only allowlist`);
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1345
1379
|
if (tool === "bash") {
|
|
1346
1380
|
if (policy.mode === "verification") {
|
|
1347
1381
|
if (BASH_VERIFICATION_RE.test(pathOrCommand) || BASH_READ_ONLY_RE.test(pathOrCommand)) return { block: false };
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
getWorkflowDatabasePath,
|
|
19
19
|
refreshWorkflowDatabaseFromDisk,
|
|
20
20
|
} from "./db-workspace.js";
|
|
21
|
-
import { isClosedStatus } from "./status-guards.js";
|
|
21
|
+
import { isClosedStatus, isDeferredStatus } from "./status-guards.js";
|
|
22
22
|
import { closeQualityGatesFromEvidence } from "./quality-gate-closure.js";
|
|
23
23
|
import { insertMilestoneValidationGates } from "./milestone-validation-gates.js";
|
|
24
24
|
import { relMilestoneFile, resolveSliceFile } from "./paths.js";
|
|
@@ -229,6 +229,7 @@ export function checkCloseoutConsistencyGate(
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
for (const slice of slices) {
|
|
232
|
+
if (isDeferredStatus(slice.status)) continue;
|
|
232
233
|
if (!isClosedStatus(slice.status)) {
|
|
233
234
|
return blocked(
|
|
234
235
|
"slice-open",
|