gsd-pi 2.79.0-dev.ece5fd8ba → 2.80.0-dev.c5f2443b3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/github-sync/templates.js +55 -70
- package/dist/resources/extensions/gsd/auto/contracts.js +1 -0
- package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +53 -0
- package/dist/resources/extensions/gsd/auto/loop.js +359 -523
- package/dist/resources/extensions/gsd/auto/orchestrator.js +146 -0
- package/dist/resources/extensions/gsd/auto/phases.js +55 -6
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.js +12 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-iteration.js +24 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.js +33 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.js +26 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-retry.js +49 -0
- package/dist/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.js +25 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +48 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-ledger.js +26 -0
- package/dist/resources/extensions/gsd/auto/workflow-iteration-completion.js +10 -0
- package/dist/resources/extensions/gsd/auto/workflow-journal-reporter.js +16 -0
- package/dist/resources/extensions/gsd/auto/workflow-kernel.js +263 -0
- package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +36 -0
- package/dist/resources/extensions/gsd/auto/workflow-phase-reporter.js +9 -0
- package/dist/resources/extensions/gsd/auto/workflow-session-lock.js +35 -0
- package/dist/resources/extensions/gsd/auto/workflow-sidecar-iteration.js +24 -0
- package/dist/resources/extensions/gsd/auto/workflow-sidecar-queue.js +26 -0
- package/dist/resources/extensions/gsd/auto/workflow-turn-reporter.js +36 -0
- package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +44 -0
- package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +15 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +3 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +168 -3
- package/dist/resources/extensions/gsd/auto-recovery.js +45 -52
- package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -0
- package/dist/resources/extensions/gsd/auto-verification.js +2 -11
- package/dist/resources/extensions/gsd/auto-worktree.js +87 -38
- package/dist/resources/extensions/gsd/auto.js +159 -2
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -5
- package/dist/resources/extensions/gsd/commands-ship.js +23 -46
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +12 -7
- package/dist/resources/extensions/gsd/component-loader.js +5 -11
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +4 -0
- package/dist/resources/extensions/gsd/db-adapter.js +47 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +337 -0
- package/dist/resources/extensions/gsd/db-connection-cache.js +31 -0
- package/dist/resources/extensions/gsd/db-coordination-schema.js +104 -0
- package/dist/resources/extensions/gsd/db-decision-requirement-rows.js +71 -0
- package/dist/resources/extensions/gsd/db-gate-rows.js +16 -0
- package/dist/resources/extensions/gsd/db-lightweight-query-rows.js +29 -0
- package/dist/resources/extensions/gsd/db-memory-fts-schema.js +56 -0
- package/dist/resources/extensions/gsd/db-migration-backup.js +22 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +394 -0
- package/dist/resources/extensions/gsd/db-milestone-artifact-rows.js +35 -0
- package/dist/resources/extensions/gsd/db-open-state.js +32 -0
- package/dist/resources/extensions/gsd/db-provider.js +108 -0
- package/dist/resources/extensions/gsd/db-runtime-kv-schema.js +27 -0
- package/dist/resources/extensions/gsd/db-schema-metadata.js +23 -0
- package/dist/resources/extensions/gsd/db-task-slice-rows.js +86 -0
- package/dist/resources/extensions/gsd/db-transaction.js +63 -0
- package/dist/resources/extensions/gsd/db-verification-evidence-rows.js +3 -0
- package/dist/resources/extensions/gsd/db-verification-evidence-schema.js +19 -0
- package/dist/resources/extensions/gsd/escalation.js +2 -0
- package/dist/resources/extensions/gsd/gsd-db.js +215 -1519
- package/dist/resources/extensions/gsd/legacy-telemetry.js +70 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -0
- package/dist/resources/extensions/gsd/model-router.js +9 -6
- package/dist/resources/extensions/gsd/notification-widget.js +21 -3
- package/dist/resources/extensions/gsd/post-execution-checks.js +27 -6
- package/dist/resources/extensions/gsd/pr-evidence.js +76 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +2 -0
- package/dist/resources/extensions/gsd/process-task-path.js +61 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +9 -5
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +32 -30
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +23 -34
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +50 -96
- package/dist/resources/extensions/gsd/prompts/discuss.md +81 -181
- package/dist/resources/extensions/gsd/prompts/execute-task.md +40 -67
- package/dist/resources/extensions/gsd/prompts/forensics.md +41 -84
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +29 -39
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +30 -65
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +25 -52
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +36 -36
- package/dist/resources/extensions/gsd/prompts/guided-research-project.md +20 -38
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +45 -59
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +25 -87
- package/dist/resources/extensions/gsd/prompts/queue.md +46 -53
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +23 -23
- package/dist/resources/extensions/gsd/prompts/research-slice.md +23 -23
- package/dist/resources/extensions/gsd/prompts/rethink.md +10 -10
- package/dist/resources/extensions/gsd/prompts/system.md +65 -107
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +15 -15
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +24 -24
- package/dist/resources/extensions/gsd/prompts/worktree-merge.md +35 -35
- package/dist/resources/extensions/gsd/state.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +14 -9
- package/dist/resources/extensions/gsd/tools/complete-task.js +2 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +6 -1
- package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
- package/dist/resources/extensions/gsd/uok/kernel.js +8 -3
- package/dist/resources/extensions/gsd/uok/plan-v2.js +2 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +13 -13
- package/dist/resources/extensions/gsd/workflow-manifest.js +2 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -0
- package/dist/resources/extensions/gsd/workflow-templates.js +9 -0
- package/dist/resources/extensions/shared/interview-ui.js +15 -4
- 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 +13 -13
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- package/dist/web/standalone/.next/server/chunks/167.js +2 -0
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/package.json +1 -0
- package/dist/web/standalone/server.js +1 -1
- package/package.json +9 -2
- package/packages/contracts/dist/index.d.ts +3 -0
- package/packages/contracts/dist/index.d.ts.map +1 -0
- package/packages/contracts/dist/index.js +5 -0
- package/packages/contracts/dist/index.js.map +1 -0
- package/packages/contracts/dist/rpc.d.ts +549 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -0
- package/packages/contracts/dist/rpc.js +53 -0
- package/packages/contracts/dist/rpc.js.map +1 -0
- package/packages/contracts/dist/rpc.test.d.ts +2 -0
- package/packages/contracts/dist/rpc.test.d.ts.map +1 -0
- package/packages/contracts/dist/rpc.test.js +47 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -0
- package/packages/contracts/dist/workflow.d.ts +180 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -0
- package/packages/contracts/dist/workflow.js +201 -0
- package/packages/contracts/dist/workflow.js.map +1 -0
- package/packages/contracts/package.json +39 -0
- package/packages/contracts/src/index.ts +5 -0
- package/packages/contracts/src/rpc.test.ts +72 -0
- package/packages/contracts/src/rpc.ts +286 -0
- package/packages/contracts/src/workflow.ts +213 -0
- package/packages/contracts/tsconfig.json +25 -0
- package/packages/contracts/tsconfig.tsbuildinfo +1 -0
- package/packages/daemon/package.json +3 -2
- package/packages/daemon/src/event-bridge.test.ts +2 -1
- package/packages/daemon/src/event-bridge.ts +1 -1
- package/packages/daemon/src/event-formatter.test.ts +1 -2
- package/packages/daemon/src/event-formatter.ts +1 -2
- package/packages/daemon/src/session-manager.ts +2 -2
- package/packages/daemon/src/types.ts +3 -18
- package/packages/mcp-server/dist/server.d.ts +13 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +77 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +1 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/types.d.ts +3 -11
- package/packages/mcp-server/dist/types.d.ts.map +1 -1
- package/packages/mcp-server/dist/types.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +2 -40
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -2
- package/packages/mcp-server/src/mcp-server.test.ts +138 -0
- package/packages/mcp-server/src/server.ts +99 -1
- package/packages/mcp-server/src/session-manager.ts +2 -2
- package/packages/mcp-server/src/types.ts +7 -18
- package/packages/mcp-server/src/workflow-tools.ts +2 -40
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +20 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +6 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +9 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +31 -10
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -512
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js +3 -7
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/packages/pi-coding-agent/package.json +2 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +23 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +6 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +50 -9
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +3 -336
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts +1 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +8 -2
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/tui.ts +8 -2
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/README.md +3 -3
- package/packages/rpc-client/dist/index.d.ts +1 -1
- package/packages/rpc-client/dist/index.d.ts.map +1 -1
- package/packages/rpc-client/dist/index.js.map +1 -1
- package/packages/rpc-client/dist/rpc-client.d.ts +2 -6
- package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -1
- package/packages/rpc-client/dist/rpc-client.js.map +1 -1
- package/packages/rpc-client/dist/rpc-types.d.ts +1 -565
- package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -1
- package/packages/rpc-client/dist/rpc-types.js +3 -11
- package/packages/rpc-client/dist/rpc-types.js.map +1 -1
- package/packages/rpc-client/package.json +4 -1
- package/packages/rpc-client/src/index.ts +1 -1
- package/packages/rpc-client/src/rpc-client.ts +3 -6
- package/packages/rpc-client/src/rpc-types.ts +3 -398
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/github-sync/templates.ts +59 -84
- package/src/resources/extensions/github-sync/tests/templates.test.ts +10 -2
- package/src/resources/extensions/gsd/auto/contracts.ts +87 -0
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +72 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +10 -3
- package/src/resources/extensions/gsd/auto/loop.ts +411 -598
- package/src/resources/extensions/gsd/auto/orchestrator.ts +161 -0
- package/src/resources/extensions/gsd/auto/phases.ts +82 -8
- package/src/resources/extensions/gsd/auto/session.ts +11 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.ts +28 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-iteration.ts +52 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.ts +58 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.ts +71 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-retry.ts +90 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.ts +50 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +97 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-ledger.ts +45 -0
- package/src/resources/extensions/gsd/auto/workflow-iteration-completion.ts +26 -0
- package/src/resources/extensions/gsd/auto/workflow-journal-reporter.ts +33 -0
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +520 -0
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +58 -0
- package/src/resources/extensions/gsd/auto/workflow-phase-reporter.ts +22 -0
- package/src/resources/extensions/gsd/auto/workflow-session-lock.ts +68 -0
- package/src/resources/extensions/gsd/auto/workflow-sidecar-iteration.ts +46 -0
- package/src/resources/extensions/gsd/auto/workflow-sidecar-queue.ts +46 -0
- package/src/resources/extensions/gsd/auto/workflow-turn-reporter.ts +68 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +89 -0
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +38 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +4 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +170 -3
- package/src/resources/extensions/gsd/auto-recovery.ts +42 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +7 -0
- package/src/resources/extensions/gsd/auto-verification.ts +5 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +85 -36
- package/src/resources/extensions/gsd/auto.ts +167 -1
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +14 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +11 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +13 -5
- package/src/resources/extensions/gsd/commands-ship.ts +24 -51
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +13 -0
- package/src/resources/extensions/gsd/component-loader.ts +5 -11
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +6 -0
- package/src/resources/extensions/gsd/db-adapter.ts +75 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +368 -0
- package/src/resources/extensions/gsd/db-connection-cache.ts +45 -0
- package/src/resources/extensions/gsd/db-coordination-schema.ts +109 -0
- package/src/resources/extensions/gsd/db-decision-requirement-rows.ts +77 -0
- package/src/resources/extensions/gsd/db-gate-rows.ts +19 -0
- package/src/resources/extensions/gsd/db-lightweight-query-rows.ts +50 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +66 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +34 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +434 -0
- package/src/resources/extensions/gsd/db-milestone-artifact-rows.ts +70 -0
- package/src/resources/extensions/gsd/db-open-state.ts +47 -0
- package/src/resources/extensions/gsd/db-provider.ts +148 -0
- package/src/resources/extensions/gsd/db-runtime-kv-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +33 -0
- package/src/resources/extensions/gsd/db-task-slice-rows.ts +146 -0
- package/src/resources/extensions/gsd/db-transaction.ts +76 -0
- package/src/resources/extensions/gsd/db-verification-evidence-rows.ts +14 -0
- package/src/resources/extensions/gsd/db-verification-evidence-schema.ts +22 -0
- package/src/resources/extensions/gsd/escalation.ts +3 -1
- package/src/resources/extensions/gsd/gsd-db.ts +260 -1659
- package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
- package/src/resources/extensions/gsd/legacy-telemetry.ts +99 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +4 -1
- package/src/resources/extensions/gsd/model-router.ts +10 -6
- package/src/resources/extensions/gsd/notification-widget.ts +25 -4
- package/src/resources/extensions/gsd/post-execution-checks.ts +35 -7
- package/src/resources/extensions/gsd/pr-evidence.ts +124 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +4 -1
- package/src/resources/extensions/gsd/process-task-path.ts +81 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +9 -5
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +32 -30
- package/src/resources/extensions/gsd/prompts/complete-slice.md +23 -34
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +50 -96
- package/src/resources/extensions/gsd/prompts/discuss.md +81 -181
- package/src/resources/extensions/gsd/prompts/execute-task.md +40 -67
- package/src/resources/extensions/gsd/prompts/forensics.md +41 -84
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +29 -39
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +30 -65
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +25 -52
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +36 -36
- package/src/resources/extensions/gsd/prompts/guided-research-project.md +20 -38
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +45 -59
- package/src/resources/extensions/gsd/prompts/plan-slice.md +25 -87
- package/src/resources/extensions/gsd/prompts/queue.md +46 -53
- package/src/resources/extensions/gsd/prompts/refine-slice.md +23 -23
- package/src/resources/extensions/gsd/prompts/research-slice.md +23 -23
- package/src/resources/extensions/gsd/prompts/rethink.md +10 -10
- package/src/resources/extensions/gsd/prompts/system.md +65 -107
- package/src/resources/extensions/gsd/prompts/triage-captures.md +15 -15
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +24 -24
- package/src/resources/extensions/gsd/prompts/worktree-merge.md +35 -35
- package/src/resources/extensions/gsd/state.ts +6 -3
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +353 -0
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/commands-eval-review.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/commands-ship-eval-warn.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +19 -5
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +2 -9
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/db-adapter.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/db-base-schema.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/db-connection-cache.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/db-coordination-schema.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/db-decision-requirement-rows.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/db-gate-rows.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/db-lightweight-query-rows.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/db-migration-steps.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-milestone-artifact-rows.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/db-open-state.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/db-provider.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/db-runtime-kv-schema.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/db-verification-evidence-schema.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/discuss-headless-rendering.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-requirements-prompt-rendering.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/legacy-component-format-telemetry.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/legacy-telemetry.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +40 -16
- package/src/resources/extensions/gsd/tests/model-router.test.ts +33 -12
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +40 -1
- package/src/resources/extensions/gsd/tests/paused-session-via-db.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-rendering.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +65 -16
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/pr-evidence.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/process-task-path.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/queue-prompt-rendering.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +32 -9
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-dispatch-outcome.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-iteration.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile-outcome.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-retry.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-verify-outcome.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/workflow-dispatch-ledger.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-iteration-completion.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/workflow-journal-reporter.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +607 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +20 -4
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/workflow-phase-reporter.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/workflow-session-lock.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/workflow-sidecar-iteration.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/workflow-sidecar-queue.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/workflow-turn-reporter.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/workflow-unit-dispatch.test.ts +160 -0
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +17 -33
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
- package/src/resources/extensions/gsd/tools/complete-task.ts +4 -1
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +6 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
- package/src/resources/extensions/gsd/uok/kernel.ts +10 -3
- package/src/resources/extensions/gsd/uok/plan-v2.ts +5 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +13 -13
- package/src/resources/extensions/gsd/workflow-manifest.ts +6 -15
- package/src/resources/extensions/gsd/workflow-projections.ts +5 -1
- package/src/resources/extensions/gsd/workflow-templates.ts +11 -0
- package/src/resources/extensions/shared/interview-ui.ts +18 -5
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +41 -0
- package/dist/web/standalone/.next/server/chunks/6336.js +0 -1
- /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → bQDK5_LtkGVS64AirQgQG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{TzEVJ1Lh8vbez4n4Q9TqQ → bQDK5_LtkGVS64AirQgQG}/_ssgManifest.js +0 -0
|
@@ -10,11 +10,10 @@
|
|
|
10
10
|
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
11
11
|
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
|
-
import type { AutoSession
|
|
13
|
+
import type { AutoSession } from "./session.js";
|
|
14
14
|
import type { LoopDeps } from "./loop-deps.js";
|
|
15
15
|
import {
|
|
16
16
|
MAX_LOOP_ITERATIONS,
|
|
17
|
-
type PhaseResult,
|
|
18
17
|
type LoopState,
|
|
19
18
|
type IterationContext,
|
|
20
19
|
type IterationData,
|
|
@@ -24,7 +23,6 @@ import {
|
|
|
24
23
|
runPreDispatch,
|
|
25
24
|
runDispatch,
|
|
26
25
|
runGuards,
|
|
27
|
-
runUnitPhase,
|
|
28
26
|
runFinalize,
|
|
29
27
|
} from "./phases.js";
|
|
30
28
|
import { debugLog } from "../debug-logger.js";
|
|
@@ -32,27 +30,68 @@ import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterM
|
|
|
32
30
|
import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
|
|
33
31
|
import { resolveEngine } from "../engine-resolver.js";
|
|
34
32
|
import { logWarning } from "../workflow-logger.js";
|
|
35
|
-
import { gsdRoot } from "../paths.js";
|
|
36
|
-
import { heartbeatAutoWorker } from "../db/auto-workers.js";
|
|
37
33
|
import {
|
|
38
34
|
recordDispatchClaim,
|
|
39
35
|
markRunning as markDispatchRunning,
|
|
40
36
|
markCompleted as markDispatchCompleted,
|
|
41
37
|
markFailed as markDispatchFailed,
|
|
42
|
-
markStuck as markDispatchStuck,
|
|
43
38
|
getRecentForUnit as getRecentDispatchesForUnit,
|
|
44
39
|
getRecentUnitKeysForProjectRoot,
|
|
45
40
|
} from "../db/unit-dispatches.js";
|
|
46
41
|
import { refreshMilestoneLease } from "../db/milestone-leases.js";
|
|
42
|
+
import { heartbeatAutoWorker } from "../db/auto-workers.js";
|
|
47
43
|
import { getRuntimeKv, setRuntimeKv } from "../db/runtime-kv.js";
|
|
48
|
-
import { atomicWriteSync } from "../atomic-write.js";
|
|
49
44
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
50
45
|
import { scheduleSidecarQueue } from "../uok/execution-graph.js";
|
|
51
|
-
import { ExecutionGraphScheduler } from "../uok/execution-graph.js";
|
|
52
|
-
import type { UokGraphNode } from "../uok/contracts.js";
|
|
53
|
-
import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
|
54
|
-
import { join } from "node:path";
|
|
55
46
|
import { normalizeRealPath } from "../paths.js";
|
|
47
|
+
import {
|
|
48
|
+
decideCooldownRecovery,
|
|
49
|
+
decideDispatchClaim,
|
|
50
|
+
decideEngineDispatch,
|
|
51
|
+
decideFinalizeResult,
|
|
52
|
+
decideInfrastructureError,
|
|
53
|
+
decideIterationErrorRecovery,
|
|
54
|
+
decideMemoryPressure,
|
|
55
|
+
decideModelPolicyBlocked,
|
|
56
|
+
decideMinRequestInterval,
|
|
57
|
+
decideWorkflowLoop,
|
|
58
|
+
formatDispatchExceptionSummary,
|
|
59
|
+
formatUnhandledDispatchErrorSummary,
|
|
60
|
+
resolveUnitRequestTimestamp,
|
|
61
|
+
shouldUseCustomEnginePath,
|
|
62
|
+
} from "./workflow-kernel.js";
|
|
63
|
+
import {
|
|
64
|
+
hydrateCustomVerifyRetryCounts,
|
|
65
|
+
saveCustomVerifyRetryCounts,
|
|
66
|
+
} from "./custom-verify-retry-store.js";
|
|
67
|
+
import {
|
|
68
|
+
settleDispatchCompleted,
|
|
69
|
+
settleDispatchFailed,
|
|
70
|
+
} from "./workflow-dispatch-ledger.js";
|
|
71
|
+
import { openDispatchClaim } from "./workflow-dispatch-claim.js";
|
|
72
|
+
import { completeWorkflowIteration } from "./workflow-iteration-completion.js";
|
|
73
|
+
import { createWorkflowJournalReporter } from "./workflow-journal-reporter.js";
|
|
74
|
+
import { createWorkflowPhaseReporter } from "./workflow-phase-reporter.js";
|
|
75
|
+
import { createWorkflowTurnReporter } from "./workflow-turn-reporter.js";
|
|
76
|
+
import { validateWorkflowSessionLock } from "./workflow-session-lock.js";
|
|
77
|
+
import { dequeueSidecarItem } from "./workflow-sidecar-queue.js";
|
|
78
|
+
import { maintainWorkerHeartbeat } from "./workflow-worker-heartbeat.js";
|
|
79
|
+
import { measureMemoryPressure } from "./workflow-memory-pressure.js";
|
|
80
|
+
import { buildSidecarIterationData } from "./workflow-sidecar-iteration.js";
|
|
81
|
+
import {
|
|
82
|
+
createExecutionGraphUnitDispatchDeps,
|
|
83
|
+
runUnitPhaseViaContract,
|
|
84
|
+
type DispatchContract,
|
|
85
|
+
} from "./workflow-unit-dispatch.js";
|
|
86
|
+
import { handleCustomEngineDispatchOutcome } from "./workflow-custom-engine-dispatch-outcome.js";
|
|
87
|
+
import { buildCustomEngineIterationData } from "./workflow-custom-engine-iteration.js";
|
|
88
|
+
import { handleCustomEngineVerifyRetry } from "./workflow-custom-engine-retry.js";
|
|
89
|
+
import {
|
|
90
|
+
handleCustomEngineVerifyPause,
|
|
91
|
+
handleCustomEngineVerifyRetryOutcome,
|
|
92
|
+
} from "./workflow-custom-engine-verify-outcome.js";
|
|
93
|
+
import { handleCustomEngineReconcile } from "./workflow-custom-engine-reconcile.js";
|
|
94
|
+
import { handleCustomEngineReconcileOutcome } from "./workflow-custom-engine-reconcile-outcome.js";
|
|
56
95
|
|
|
57
96
|
// ── Stuck detection persistence (#3704) ──────────────────────────────────
|
|
58
97
|
// Phase C migration: stuck-state.json deleted in favor of DB-backed
|
|
@@ -98,132 +137,44 @@ function saveStuckState(s: AutoSession, state: LoopState): void {
|
|
|
98
137
|
}
|
|
99
138
|
}
|
|
100
139
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return s.activeRunDir ? join(s.activeRunDir, "runtime") : join(gsdRoot(s.basePath), "runtime");
|
|
140
|
+
function logDispatchLedgerWriteFailure(err: unknown): void {
|
|
141
|
+
debugLog("autoLoop", {
|
|
142
|
+
phase: "dispatch-ledger-write-failed",
|
|
143
|
+
error: err instanceof Error ? err.message : String(err),
|
|
144
|
+
});
|
|
107
145
|
}
|
|
108
146
|
|
|
109
|
-
function
|
|
110
|
-
|
|
147
|
+
function logDispatchClaimRejected(details: {
|
|
148
|
+
unitId: string;
|
|
149
|
+
reason: string;
|
|
150
|
+
existingId?: number;
|
|
151
|
+
existingWorker?: string;
|
|
152
|
+
}): void {
|
|
153
|
+
debugLog("autoLoop", {
|
|
154
|
+
phase: "dispatch-claim-rejected",
|
|
155
|
+
...details,
|
|
156
|
+
});
|
|
111
157
|
}
|
|
112
158
|
|
|
113
|
-
function
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
const raw = JSON.parse(readFileSync(customVerifyRetryStatePath(s), "utf-8"));
|
|
120
|
-
const counts = raw && typeof raw === "object" && raw.counts && typeof raw.counts === "object"
|
|
121
|
-
? raw.counts as Record<string, unknown>
|
|
122
|
-
: {};
|
|
123
|
-
for (const [key, value] of Object.entries(counts)) {
|
|
124
|
-
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
125
|
-
s.verificationRetryCount.set(key, Math.floor(value));
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} catch (err) {
|
|
129
|
-
debugLog("autoLoop", { phase: "load-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return s.verificationRetryCount;
|
|
159
|
+
function logDispatchClaimFailed(err: unknown): void {
|
|
160
|
+
debugLog("autoLoop", {
|
|
161
|
+
phase: "dispatch-claim-failed",
|
|
162
|
+
error: err instanceof Error ? err.message : String(err),
|
|
163
|
+
});
|
|
133
164
|
}
|
|
134
165
|
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (!retryCounts || retryCounts.size === 0) {
|
|
141
|
-
unlinkSync(filePath);
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
mkdirSync(customVerifyRetryStateDir(s), { recursive: true });
|
|
145
|
-
atomicWriteSync(filePath, JSON.stringify({
|
|
146
|
-
counts: Object.fromEntries(retryCounts),
|
|
147
|
-
updatedAt: new Date().toISOString(),
|
|
148
|
-
}) + "\n");
|
|
149
|
-
} catch (err) {
|
|
150
|
-
const code = err && typeof err === "object" && "code" in err ? (err as { code?: string }).code : undefined;
|
|
151
|
-
if (code !== "ENOENT") {
|
|
152
|
-
debugLog("autoLoop", { phase: "save-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
|
|
153
|
-
}
|
|
154
|
-
}
|
|
166
|
+
function logCustomVerifyRetryLoadFailure(err: unknown): void {
|
|
167
|
+
debugLog("autoLoop", {
|
|
168
|
+
phase: "load-custom-verify-retries-failed",
|
|
169
|
+
error: err instanceof Error ? err.message : String(err),
|
|
170
|
+
});
|
|
155
171
|
}
|
|
156
172
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
*
|
|
163
|
-
* Single-worker compatibility: this function is best-effort and never
|
|
164
|
-
* throws. The auto-loop must continue to behave identically when the
|
|
165
|
-
* ledger is degraded.
|
|
166
|
-
*/
|
|
167
|
-
type DispatchClaimOutcome =
|
|
168
|
-
| { kind: "opened"; dispatchId: number }
|
|
169
|
-
| { kind: "skip"; reason: "already-active" | "stale-lease"; existingId?: number; existingWorker?: string }
|
|
170
|
-
| { kind: "degraded" };
|
|
171
|
-
|
|
172
|
-
function openDispatchClaim(
|
|
173
|
-
s: AutoSession,
|
|
174
|
-
flowId: string,
|
|
175
|
-
turnId: string,
|
|
176
|
-
iterData: IterationData,
|
|
177
|
-
): DispatchClaimOutcome {
|
|
178
|
-
if (!s.workerId || s.milestoneLeaseToken === null) return { kind: "degraded" };
|
|
179
|
-
const mid = iterData.mid;
|
|
180
|
-
if (!mid) return { kind: "degraded" };
|
|
181
|
-
|
|
182
|
-
const recent = getRecentDispatchesForUnit(iterData.unitId, 1);
|
|
183
|
-
const attemptN = (recent[0]?.attempt_n ?? 0) + 1;
|
|
184
|
-
|
|
185
|
-
let claim: ReturnType<typeof recordDispatchClaim>;
|
|
186
|
-
try {
|
|
187
|
-
claim = recordDispatchClaim({
|
|
188
|
-
traceId: flowId,
|
|
189
|
-
turnId,
|
|
190
|
-
workerId: s.workerId,
|
|
191
|
-
milestoneLeaseToken: s.milestoneLeaseToken,
|
|
192
|
-
milestoneId: mid,
|
|
193
|
-
sliceId: iterData.state.activeSlice?.id ?? null,
|
|
194
|
-
taskId: iterData.state.activeTask?.id ?? null,
|
|
195
|
-
unitType: iterData.unitType,
|
|
196
|
-
unitId: iterData.unitId,
|
|
197
|
-
attemptN,
|
|
198
|
-
});
|
|
199
|
-
if (!claim.ok) {
|
|
200
|
-
debugLog("autoLoop", {
|
|
201
|
-
phase: "dispatch-claim-rejected",
|
|
202
|
-
unitId: iterData.unitId,
|
|
203
|
-
reason: claim.error,
|
|
204
|
-
existingId: "existingId" in claim ? claim.existingId : undefined,
|
|
205
|
-
existingWorker: "existingWorker" in claim ? claim.existingWorker : undefined,
|
|
206
|
-
});
|
|
207
|
-
if (claim.error === "already_active") {
|
|
208
|
-
return {
|
|
209
|
-
kind: "skip",
|
|
210
|
-
reason: "already-active",
|
|
211
|
-
existingId: claim.existingId,
|
|
212
|
-
existingWorker: claim.existingWorker,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
return { kind: "skip", reason: "stale-lease" };
|
|
216
|
-
}
|
|
217
|
-
markDispatchRunning(claim.dispatchId);
|
|
218
|
-
return { kind: "opened", dispatchId: claim.dispatchId };
|
|
219
|
-
} catch (err) {
|
|
220
|
-
debugLog("autoLoop", {
|
|
221
|
-
phase: "dispatch-claim-failed",
|
|
222
|
-
error: err instanceof Error ? err.message : String(err),
|
|
223
|
-
});
|
|
224
|
-
return { kind: "degraded" };
|
|
225
|
-
}
|
|
226
|
-
|
|
173
|
+
function logCustomVerifyRetrySaveFailure(err: unknown): void {
|
|
174
|
+
debugLog("autoLoop", {
|
|
175
|
+
phase: "save-custom-verify-retries-failed",
|
|
176
|
+
error: err instanceof Error ? err.message : String(err),
|
|
177
|
+
});
|
|
227
178
|
}
|
|
228
179
|
|
|
229
180
|
// ── Memory pressure monitoring (#3331) ──────────────────────────────────
|
|
@@ -231,110 +182,25 @@ function openDispatchClaim(
|
|
|
231
182
|
// the OS OOM killer sends SIGKILL. The threshold is 90% of the V8 heap
|
|
232
183
|
// limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
233
184
|
const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
|
|
234
|
-
const MEMORY_PRESSURE_THRESHOLD = 0.85; // 85% of heap limit
|
|
235
185
|
const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
|
|
236
186
|
|
|
237
|
-
type DispatchContract = "legacy-direct" | "uok-scheduler";
|
|
238
|
-
|
|
239
187
|
interface AutoLoopOptions {
|
|
240
188
|
dispatchContract?: DispatchContract;
|
|
241
189
|
}
|
|
242
190
|
|
|
243
|
-
function checkMemoryPressure(): { pressured: boolean; heapMB: number; limitMB: number; pct: number } {
|
|
244
|
-
const mem = process.memoryUsage();
|
|
245
|
-
// v8.getHeapStatistics() gives heap_size_limit but requires import
|
|
246
|
-
// Use a conservative estimate: RSS > 3GB is danger zone on most systems
|
|
247
|
-
const heapMB = Math.round(mem.heapUsed / 1024 / 1024);
|
|
248
|
-
const rssMB = Math.round(mem.rss / 1024 / 1024);
|
|
249
|
-
// Try to get the actual V8 heap limit
|
|
250
|
-
let limitMB = 4096; // conservative default
|
|
251
|
-
try {
|
|
252
|
-
const v8 = require("node:v8");
|
|
253
|
-
const stats = v8.getHeapStatistics();
|
|
254
|
-
limitMB = Math.round(stats.heap_size_limit / 1024 / 1024);
|
|
255
|
-
} catch { limitMB = 4096; /* v8 stats unavailable — use conservative default */ }
|
|
256
|
-
const pct = heapMB / limitMB;
|
|
257
|
-
return { pressured: pct > MEMORY_PRESSURE_THRESHOLD, heapMB, limitMB, pct };
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function resolveDispatchNodeKind(
|
|
261
|
-
unitType: string,
|
|
262
|
-
sidecarItem?: SidecarItem,
|
|
263
|
-
): UokGraphNode["kind"] {
|
|
264
|
-
if (sidecarItem?.kind === "hook") return "hook";
|
|
265
|
-
if (sidecarItem?.kind === "triage") return "verification";
|
|
266
|
-
if (sidecarItem?.kind === "quick-task") return "team-worker";
|
|
267
|
-
|
|
268
|
-
if (unitType.startsWith("hook/")) return "hook";
|
|
269
|
-
if (unitType === "reactive-execute") return "subagent";
|
|
270
|
-
if (
|
|
271
|
-
unitType === "gate-evaluate"
|
|
272
|
-
|| unitType === "validate-milestone"
|
|
273
|
-
|| unitType === "run-uat"
|
|
274
|
-
|| unitType === "complete-slice"
|
|
275
|
-
) {
|
|
276
|
-
return "verification";
|
|
277
|
-
}
|
|
278
|
-
if (unitType === "replan-slice" || unitType === "reassess-roadmap") {
|
|
279
|
-
return "reprocess";
|
|
280
|
-
}
|
|
281
|
-
return "unit";
|
|
282
|
-
}
|
|
283
|
-
|
|
284
191
|
async function enforceMinRequestInterval(s: AutoSession, prefs: IterationContext["prefs"]): Promise<void> {
|
|
285
192
|
const minInterval = prefs?.min_request_interval_ms ?? 0;
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
193
|
+
const decision = decideMinRequestInterval({
|
|
194
|
+
minIntervalMs: minInterval,
|
|
195
|
+
lastRequestTimestamp: s.lastRequestTimestamp,
|
|
196
|
+
nowMs: Date.now(),
|
|
197
|
+
});
|
|
198
|
+
if (decision.action === "wait") {
|
|
199
|
+
debugLog("autoLoop", { phase: "rate-limit-wait", waitMs: decision.waitMs });
|
|
200
|
+
await new Promise<void>(r => setTimeout(r, decision.waitMs));
|
|
293
201
|
}
|
|
294
202
|
}
|
|
295
203
|
|
|
296
|
-
async function runUnitPhaseViaContract(
|
|
297
|
-
dispatchContract: DispatchContract,
|
|
298
|
-
ic: IterationContext,
|
|
299
|
-
iterData: IterationData,
|
|
300
|
-
loopState: LoopState,
|
|
301
|
-
sidecarItem?: SidecarItem,
|
|
302
|
-
): Promise<PhaseResult<{ unitStartedAt?: number; requestDispatchedAt?: number }>> {
|
|
303
|
-
if (dispatchContract === "legacy-direct") {
|
|
304
|
-
return runUnitPhase(ic, iterData, loopState, sidecarItem);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const scheduler = new ExecutionGraphScheduler();
|
|
308
|
-
let outcome: PhaseResult<{ unitStartedAt?: number; requestDispatchedAt?: number }> | null = null;
|
|
309
|
-
const executeNode = async (): Promise<void> => {
|
|
310
|
-
outcome = await runUnitPhase(ic, iterData, loopState, sidecarItem);
|
|
311
|
-
};
|
|
312
|
-
const kinds: UokGraphNode["kind"][] = [
|
|
313
|
-
"unit",
|
|
314
|
-
"hook",
|
|
315
|
-
"subagent",
|
|
316
|
-
"team-worker",
|
|
317
|
-
"verification",
|
|
318
|
-
"reprocess",
|
|
319
|
-
];
|
|
320
|
-
for (const kind of kinds) scheduler.registerHandler(kind, executeNode);
|
|
321
|
-
|
|
322
|
-
const nodeId = `dispatch:${ic.iteration}:${iterData.unitType}:${iterData.unitId}`;
|
|
323
|
-
await scheduler.run([
|
|
324
|
-
{
|
|
325
|
-
id: nodeId,
|
|
326
|
-
kind: resolveDispatchNodeKind(iterData.unitType, sidecarItem),
|
|
327
|
-
dependsOn: [],
|
|
328
|
-
metadata: {
|
|
329
|
-
unitType: iterData.unitType,
|
|
330
|
-
unitId: iterData.unitId,
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
], { parallel: false, maxWorkers: 1 });
|
|
334
|
-
|
|
335
|
-
return outcome ?? { action: "break", reason: "scheduler-dispatch-missing-result" };
|
|
336
|
-
}
|
|
337
|
-
|
|
338
204
|
/**
|
|
339
205
|
* Main auto-mode execution loop. Iterates: derive → dispatch → guards →
|
|
340
206
|
* runUnit → finalize → repeat. Exits when s.active becomes false or a
|
|
@@ -353,6 +219,7 @@ export async function autoLoop(
|
|
|
353
219
|
debugLog("autoLoop", { phase: "enter" });
|
|
354
220
|
let iteration = 0;
|
|
355
221
|
const dispatchContract = options?.dispatchContract ?? "legacy-direct";
|
|
222
|
+
const unitDispatchDeps = createExecutionGraphUnitDispatchDeps();
|
|
356
223
|
// Load persisted stuck state so counters survive session restarts (#3704)
|
|
357
224
|
const persisted = loadStuckState(s);
|
|
358
225
|
const loopState: LoopState = {
|
|
@@ -368,69 +235,71 @@ export async function autoLoop(
|
|
|
368
235
|
iteration++;
|
|
369
236
|
debugLog("autoLoop", { phase: "loop-top", iteration });
|
|
370
237
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
} catch (err) {
|
|
381
|
-
debugLog("autoLoop", {
|
|
382
|
-
phase: "heartbeat-failed",
|
|
383
|
-
error: err instanceof Error ? err.message : String(err),
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}
|
|
238
|
+
maintainWorkerHeartbeat(s, {
|
|
239
|
+
heartbeatAutoWorker,
|
|
240
|
+
refreshMilestoneLease,
|
|
241
|
+
logHeartbeatFailure: err => debugLog("autoLoop", {
|
|
242
|
+
phase: "heartbeat-failed",
|
|
243
|
+
error: err instanceof Error ? err.message : String(err),
|
|
244
|
+
}),
|
|
245
|
+
});
|
|
387
246
|
|
|
388
247
|
// ── Journal: per-iteration flow grouping ──
|
|
389
248
|
const flowId = randomUUID();
|
|
390
249
|
let seqCounter = 0;
|
|
391
250
|
const nextSeq = () => ++seqCounter;
|
|
251
|
+
const journalReporter = createWorkflowJournalReporter({
|
|
252
|
+
emitJournalEvent: deps.emitJournalEvent,
|
|
253
|
+
flowId,
|
|
254
|
+
nextSeq,
|
|
255
|
+
});
|
|
392
256
|
const turnId = randomUUID();
|
|
393
257
|
s.currentTraceId = flowId;
|
|
394
258
|
s.currentTurnId = turnId;
|
|
395
259
|
const turnStartedAt = new Date().toISOString();
|
|
396
260
|
let observedUnitType: string | undefined;
|
|
397
261
|
let observedUnitId: string | undefined;
|
|
398
|
-
|
|
262
|
+
const phaseReporter = createWorkflowPhaseReporter({
|
|
263
|
+
observer: deps.uokObserver,
|
|
264
|
+
});
|
|
265
|
+
const turnReporter = createWorkflowTurnReporter({
|
|
266
|
+
observer: deps.uokObserver,
|
|
267
|
+
traceId: flowId,
|
|
268
|
+
turnId,
|
|
269
|
+
iteration,
|
|
270
|
+
basePath: s.basePath,
|
|
271
|
+
startedAt: turnStartedAt,
|
|
272
|
+
clearCurrentTurn: () => {
|
|
273
|
+
s.currentTraceId = null;
|
|
274
|
+
s.currentTurnId = null;
|
|
275
|
+
},
|
|
276
|
+
});
|
|
399
277
|
const finishTurn = (
|
|
400
278
|
status: "completed" | "failed" | "paused" | "stopped" | "skipped" | "retry",
|
|
401
279
|
failureClass: "none" | "unknown" | "manual-attention" | "timeout" | "execution" | "closeout" | "git" = "none",
|
|
402
280
|
error?: string,
|
|
403
281
|
): void => {
|
|
404
|
-
|
|
405
|
-
turnFinished = true;
|
|
406
|
-
deps.uokObserver?.onTurnResult({
|
|
407
|
-
traceId: flowId,
|
|
408
|
-
turnId,
|
|
409
|
-
iteration,
|
|
282
|
+
turnReporter.finish({
|
|
410
283
|
unitType: observedUnitType,
|
|
411
284
|
unitId: observedUnitId,
|
|
412
285
|
status,
|
|
413
286
|
failureClass,
|
|
414
|
-
phaseResults: [],
|
|
415
287
|
error,
|
|
416
|
-
startedAt: turnStartedAt,
|
|
417
|
-
finishedAt: new Date().toISOString(),
|
|
418
288
|
});
|
|
419
|
-
s.currentTraceId = null;
|
|
420
|
-
s.currentTurnId = null;
|
|
421
289
|
};
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
290
|
+
turnReporter.start();
|
|
291
|
+
|
|
292
|
+
const iterationDecision = decideWorkflowLoop({
|
|
293
|
+
active: s.active,
|
|
425
294
|
iteration,
|
|
426
|
-
|
|
427
|
-
|
|
295
|
+
maxIterations: MAX_LOOP_ITERATIONS,
|
|
296
|
+
hasCommandContext: true,
|
|
297
|
+
sessionLockValid: true,
|
|
428
298
|
});
|
|
429
|
-
|
|
430
|
-
if (iteration > MAX_LOOP_ITERATIONS) {
|
|
299
|
+
if (iterationDecision.action === "stop" && iterationDecision.reason === "max-iterations") {
|
|
431
300
|
debugLog("autoLoop", {
|
|
432
301
|
phase: "exit",
|
|
433
|
-
reason:
|
|
302
|
+
reason: iterationDecision.reason,
|
|
434
303
|
iteration,
|
|
435
304
|
});
|
|
436
305
|
await deps.stopAuto(
|
|
@@ -445,78 +314,85 @@ export async function autoLoop(
|
|
|
445
314
|
// ── Memory pressure check (#3331) ──
|
|
446
315
|
// Graceful shutdown before OOM killer sends SIGKILL.
|
|
447
316
|
if (iteration % MEMORY_CHECK_INTERVAL === 0) {
|
|
448
|
-
const mem =
|
|
317
|
+
const mem = measureMemoryPressure();
|
|
449
318
|
debugLog("autoLoop", { phase: "memory-check", ...mem });
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
`Memory pressure: heap at ${mem.heapMB}MB / ${mem.limitMB}MB (${Math.round(mem.pct * 100)}%). ` +
|
|
456
|
-
`Stopping gracefully to prevent OOM kill after ${iteration} iterations. ` +
|
|
457
|
-
`Resume with /gsd auto to continue from where you left off.`,
|
|
458
|
-
);
|
|
459
|
-
finishTurn("stopped", "timeout", "memory-pressure");
|
|
319
|
+
const memoryDecision = decideMemoryPressure({ ...mem, iteration });
|
|
320
|
+
if (memoryDecision.action === "stop") {
|
|
321
|
+
logWarning("dispatch", memoryDecision.warningMessage);
|
|
322
|
+
await deps.stopAuto(ctx, pi, memoryDecision.stopMessage);
|
|
323
|
+
finishTurn("stopped", "timeout", memoryDecision.turnError);
|
|
460
324
|
break;
|
|
461
325
|
}
|
|
462
326
|
}
|
|
463
327
|
|
|
464
|
-
|
|
328
|
+
const commandContextDecision = decideWorkflowLoop({
|
|
329
|
+
active: s.active,
|
|
330
|
+
iteration,
|
|
331
|
+
maxIterations: MAX_LOOP_ITERATIONS,
|
|
332
|
+
hasCommandContext: Boolean(s.cmdCtx),
|
|
333
|
+
sessionLockValid: true,
|
|
334
|
+
});
|
|
335
|
+
if (commandContextDecision.action === "stop" && commandContextDecision.reason === "missing-command-context") {
|
|
465
336
|
debugLog("autoLoop", { phase: "exit", reason: "no-cmdCtx" });
|
|
466
|
-
finishTurn("stopped", "manual-attention",
|
|
337
|
+
finishTurn("stopped", "manual-attention", commandContextDecision.reason);
|
|
467
338
|
break;
|
|
468
339
|
}
|
|
469
340
|
|
|
470
341
|
let dispatchId: number | null = null;
|
|
471
342
|
let dispatchSettled = false;
|
|
343
|
+
const completeIteration = (): void => {
|
|
344
|
+
completeWorkflowIteration({
|
|
345
|
+
get consecutiveErrors() { return consecutiveErrors; },
|
|
346
|
+
set consecutiveErrors(value) { consecutiveErrors = value; },
|
|
347
|
+
get consecutiveCooldowns() { return consecutiveCooldowns; },
|
|
348
|
+
set consecutiveCooldowns(value) { consecutiveCooldowns = value; },
|
|
349
|
+
recentErrorMessages,
|
|
350
|
+
}, {
|
|
351
|
+
emitIterationEnd: () => journalReporter.emit("iteration-end", { iteration }),
|
|
352
|
+
saveStuckState: () => saveStuckState(s, loopState),
|
|
353
|
+
logIterationComplete: () => debugLog("autoLoop", { phase: "iteration-complete", iteration }),
|
|
354
|
+
});
|
|
355
|
+
};
|
|
472
356
|
|
|
473
357
|
try {
|
|
474
358
|
// ── Blanket try/catch: one bad iteration must not kill the session
|
|
475
359
|
const prefs = deps.loadEffectiveGSDPreferences()?.preferences;
|
|
476
360
|
const uokFlags = resolveUokFlags(prefs);
|
|
477
361
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
sidecarItem = s.sidecarQueue.shift()!;
|
|
489
|
-
debugLog("autoLoop", {
|
|
490
|
-
phase: "sidecar-dequeue",
|
|
491
|
-
kind: sidecarItem.kind,
|
|
492
|
-
unitType: sidecarItem.unitType,
|
|
493
|
-
unitId: sidecarItem.unitId,
|
|
494
|
-
});
|
|
495
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "sidecar-dequeue", data: { kind: sidecarItem.kind, unitType: sidecarItem.unitType, unitId: sidecarItem.unitId } });
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
const sessionLockBase = deps.lockBase();
|
|
499
|
-
if (sessionLockBase) {
|
|
500
|
-
const lockStatus = deps.validateSessionLock(sessionLockBase);
|
|
501
|
-
if (!lockStatus.valid) {
|
|
502
|
-
debugLog("autoLoop", {
|
|
362
|
+
const sessionLockOutcome = validateWorkflowSessionLock({
|
|
363
|
+
active: s.active,
|
|
364
|
+
iteration,
|
|
365
|
+
maxIterations: MAX_LOOP_ITERATIONS,
|
|
366
|
+
deps: {
|
|
367
|
+
lockBase: deps.lockBase,
|
|
368
|
+
validateSessionLock: deps.validateSessionLock,
|
|
369
|
+
handleLostSessionLock: lockStatus => deps.handleLostSessionLock(ctx, lockStatus),
|
|
370
|
+
logInvalidSessionLock: details => debugLog("autoLoop", {
|
|
503
371
|
phase: "session-lock-invalid",
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
});
|
|
508
|
-
deps.handleLostSessionLock(ctx, lockStatus);
|
|
509
|
-
debugLog("autoLoop", {
|
|
372
|
+
...details,
|
|
373
|
+
}),
|
|
374
|
+
logSessionLockExit: details => debugLog("autoLoop", {
|
|
510
375
|
phase: "exit",
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
376
|
+
...details,
|
|
377
|
+
}),
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
if (sessionLockOutcome.action === "stop" && sessionLockOutcome.reason === "session-lock-lost") {
|
|
381
|
+
break;
|
|
516
382
|
}
|
|
517
383
|
|
|
384
|
+
// ── Check sidecar queue before deriveState ──
|
|
385
|
+
const sidecarItem = await dequeueSidecarItem({
|
|
386
|
+
queue: s.sidecarQueue,
|
|
387
|
+
executionGraphEnabled: uokFlags.executionGraph,
|
|
388
|
+
scheduleQueue: scheduleSidecarQueue,
|
|
389
|
+
warnSchedulingFailure: message => logWarning("dispatch", `sidecar queue scheduling failed: ${message}`),
|
|
390
|
+
logDequeue: payload => debugLog("autoLoop", { phase: "sidecar-dequeue", ...payload }),
|
|
391
|
+
emitDequeue: payload => journalReporter.emit("sidecar-dequeue", payload),
|
|
392
|
+
});
|
|
393
|
+
|
|
518
394
|
const ic: IterationContext = { ctx, pi, s, deps, prefs, iteration, flowId, nextSeq };
|
|
519
|
-
|
|
395
|
+
journalReporter.emit("iteration-start", { iteration });
|
|
520
396
|
let iterData: IterationData;
|
|
521
397
|
|
|
522
398
|
// ── Custom engine path ──────────────────────────────────────────────
|
|
@@ -527,7 +403,11 @@ export async function autoLoop(
|
|
|
527
403
|
//
|
|
528
404
|
// GSD_ENGINE_BYPASS=1 skips the engine layer entirely — falls through
|
|
529
405
|
// to the dev path below.
|
|
530
|
-
if (
|
|
406
|
+
if (shouldUseCustomEnginePath({
|
|
407
|
+
activeEngineId: s.activeEngineId,
|
|
408
|
+
hasSidecarItem: Boolean(sidecarItem),
|
|
409
|
+
engineBypass: process.env.GSD_ENGINE_BYPASS === "1",
|
|
410
|
+
})) {
|
|
531
411
|
debugLog("autoLoop", { phase: "custom-engine-derive", iteration, engineId: s.activeEngineId });
|
|
532
412
|
|
|
533
413
|
const { engine, policy } = resolveEngine({
|
|
@@ -553,39 +433,41 @@ export async function autoLoop(
|
|
|
553
433
|
|
|
554
434
|
debugLog("autoLoop", { phase: "custom-engine-dispatch", iteration });
|
|
555
435
|
const dispatch = await engine.resolveDispatch(engineState, { basePath: s.basePath });
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
436
|
+
const engineDispatchDecision = decideEngineDispatch(dispatch.action === "stop"
|
|
437
|
+
? { action: "stop", reason: dispatch.reason }
|
|
438
|
+
: { action: dispatch.action });
|
|
439
|
+
const dispatchFlow = await handleCustomEngineDispatchOutcome({
|
|
440
|
+
decision: engineDispatchDecision,
|
|
441
|
+
deps: {
|
|
442
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
if (dispatchFlow.action === "break") {
|
|
446
|
+
finishTurn("stopped", "manual-attention", "custom-engine-dispatch-stop");
|
|
559
447
|
break;
|
|
560
448
|
}
|
|
561
|
-
if (
|
|
449
|
+
if (dispatchFlow.action === "continue") {
|
|
450
|
+
finishTurn("skipped");
|
|
562
451
|
continue;
|
|
563
452
|
}
|
|
564
453
|
|
|
565
454
|
// dispatch.action === "dispatch"
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
455
|
+
if (dispatch.action !== "dispatch") {
|
|
456
|
+
finishTurn("skipped");
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
const step = dispatch.step;
|
|
460
|
+
iterData = await buildCustomEngineIterationData({
|
|
461
|
+
step,
|
|
571
462
|
basePath: s.basePath,
|
|
572
463
|
canonicalProjectRoot: s.canonicalProjectRoot,
|
|
573
|
-
|
|
574
|
-
|
|
464
|
+
currentMilestoneId: s.currentMilestoneId,
|
|
465
|
+
deriveState: deps.deriveState,
|
|
466
|
+
logPostDerive: details => debugLog("autoLoop", {
|
|
467
|
+
phase: "post-derive",
|
|
468
|
+
...details,
|
|
469
|
+
}),
|
|
575
470
|
});
|
|
576
|
-
|
|
577
|
-
iterData = {
|
|
578
|
-
unitType: step.unitType,
|
|
579
|
-
unitId: step.unitId,
|
|
580
|
-
prompt: step.prompt,
|
|
581
|
-
finalPrompt: step.prompt,
|
|
582
|
-
pauseAfterUatDispatch: false,
|
|
583
|
-
state: gsdState,
|
|
584
|
-
mid: s.currentMilestoneId ?? "workflow",
|
|
585
|
-
midTitle: "Workflow",
|
|
586
|
-
isRetry: false,
|
|
587
|
-
previousTier: undefined,
|
|
588
|
-
};
|
|
589
471
|
observedUnitType = iterData.unitType;
|
|
590
472
|
observedUnitId = iterData.unitId;
|
|
591
473
|
|
|
@@ -594,7 +476,7 @@ export async function autoLoop(
|
|
|
594
476
|
|
|
595
477
|
// ── Guards (shared with dev path) ──
|
|
596
478
|
const guardsResult = await runGuards(ic, s.currentMilestoneId ?? "workflow");
|
|
597
|
-
|
|
479
|
+
phaseReporter.report("guard", guardsResult.action, {
|
|
598
480
|
unitType: iterData.unitType,
|
|
599
481
|
unitId: iterData.unitId,
|
|
600
482
|
});
|
|
@@ -610,12 +492,14 @@ export async function autoLoop(
|
|
|
610
492
|
ic,
|
|
611
493
|
iterData,
|
|
612
494
|
loopState,
|
|
495
|
+
undefined,
|
|
496
|
+
unitDispatchDeps,
|
|
613
497
|
);
|
|
614
498
|
if (unitPhaseResult.action === "next") {
|
|
615
|
-
const requestTimestamp = unitPhaseResult.data
|
|
616
|
-
if (
|
|
499
|
+
const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
|
|
500
|
+
if (requestTimestamp !== undefined) s.lastRequestTimestamp = requestTimestamp;
|
|
617
501
|
}
|
|
618
|
-
|
|
502
|
+
phaseReporter.report("unit", unitPhaseResult.action, {
|
|
619
503
|
unitType: iterData.unitType,
|
|
620
504
|
unitId: iterData.unitId,
|
|
621
505
|
});
|
|
@@ -628,116 +512,93 @@ export async function autoLoop(
|
|
|
628
512
|
debugLog("autoLoop", { phase: "custom-engine-verify", iteration, unitId: iterData.unitId });
|
|
629
513
|
const verifyResult = await policy.verify(iterData.unitType, iterData.unitId, { basePath: s.basePath });
|
|
630
514
|
if (verifyResult === "pause") {
|
|
631
|
-
await
|
|
632
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "pause", {
|
|
515
|
+
const verifyFlow = await handleCustomEngineVerifyPause({
|
|
633
516
|
unitType: iterData.unitType,
|
|
634
517
|
unitId: iterData.unitId,
|
|
518
|
+
deps: {
|
|
519
|
+
pauseAuto: () => deps.pauseAuto(ctx, pi),
|
|
520
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
521
|
+
reportPause: details => phaseReporter.report("custom-engine", "pause", details),
|
|
522
|
+
finishTurn,
|
|
523
|
+
},
|
|
635
524
|
});
|
|
636
|
-
|
|
637
|
-
break;
|
|
525
|
+
if (verifyFlow.action === "break") break;
|
|
638
526
|
}
|
|
639
527
|
if (verifyResult === "retry") {
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
const attempts = (retryCounts.get(recoveryKey) ?? 0) + 1;
|
|
643
|
-
retryCounts.set(recoveryKey, attempts);
|
|
644
|
-
saveCustomVerifyRetryCounts(s);
|
|
645
|
-
debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId, attempts });
|
|
646
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "retry", {
|
|
528
|
+
const retryOutcome = await handleCustomEngineVerifyRetry({
|
|
529
|
+
session: s,
|
|
647
530
|
unitType: iterData.unitType,
|
|
648
531
|
unitId: iterData.unitId,
|
|
649
|
-
|
|
532
|
+
basePath: s.basePath,
|
|
533
|
+
iteration,
|
|
534
|
+
maxRetries: MAX_CUSTOM_ENGINE_VERIFY_RETRIES,
|
|
535
|
+
deps: {
|
|
536
|
+
hydrateRetryCounts: () => hydrateCustomVerifyRetryCounts(s, {
|
|
537
|
+
logFailure: logCustomVerifyRetryLoadFailure,
|
|
538
|
+
}),
|
|
539
|
+
saveRetryCounts: () => saveCustomVerifyRetryCounts(s, {
|
|
540
|
+
logFailure: logCustomVerifyRetrySaveFailure,
|
|
541
|
+
}),
|
|
542
|
+
recover: (unitType, unitId, options) => policy.recover(unitType, unitId, options),
|
|
543
|
+
logRetry: details => debugLog("autoLoop", {
|
|
544
|
+
phase: "custom-engine-verify-retry",
|
|
545
|
+
...details,
|
|
546
|
+
}),
|
|
547
|
+
reportRetry: details => phaseReporter.report("custom-engine", "retry", details),
|
|
548
|
+
},
|
|
650
549
|
});
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
pi,
|
|
662
|
-
recovery.reason ??
|
|
663
|
-
`Custom workflow verification for ${iterData.unitId} requested skip after retry exhaustion, but the custom engine cannot reconcile skipped steps.`,
|
|
664
|
-
);
|
|
665
|
-
finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
|
|
666
|
-
break;
|
|
667
|
-
}
|
|
668
|
-
const exhaustedReason =
|
|
669
|
-
`Custom workflow verification for ${iterData.unitId} requested retry ${attempts} times without passing.`;
|
|
670
|
-
await deps.stopAuto(
|
|
671
|
-
ctx,
|
|
672
|
-
pi,
|
|
673
|
-
recovery.outcome === "stop" && recovery.reason ? recovery.reason : exhaustedReason,
|
|
674
|
-
);
|
|
675
|
-
finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
|
|
676
|
-
break;
|
|
677
|
-
}
|
|
678
|
-
finishTurn("retry");
|
|
550
|
+
const retryFlow = await handleCustomEngineVerifyRetryOutcome({
|
|
551
|
+
outcome: retryOutcome,
|
|
552
|
+
deps: {
|
|
553
|
+
pauseAuto: () => deps.pauseAuto(ctx, pi),
|
|
554
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
555
|
+
reportPause: details => phaseReporter.report("custom-engine", "pause", details),
|
|
556
|
+
finishTurn,
|
|
557
|
+
},
|
|
558
|
+
});
|
|
559
|
+
if (retryFlow.action === "break") break;
|
|
679
560
|
continue;
|
|
680
561
|
}
|
|
681
562
|
|
|
682
563
|
// Verification passed — mark step complete
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
564
|
+
const reconcileOutcome = await handleCustomEngineReconcile({
|
|
565
|
+
session: s,
|
|
566
|
+
engineState,
|
|
567
|
+
iterData,
|
|
568
|
+
iteration,
|
|
569
|
+
deps: {
|
|
570
|
+
saveRetryCounts: () => saveCustomVerifyRetryCounts(s, {
|
|
571
|
+
logFailure: logCustomVerifyRetrySaveFailure,
|
|
572
|
+
}),
|
|
573
|
+
logReconcile: details => debugLog("autoLoop", {
|
|
574
|
+
phase: "custom-engine-reconcile",
|
|
575
|
+
...details,
|
|
576
|
+
}),
|
|
577
|
+
reconcile: (state, completedStep) => engine.reconcile(state, completedStep),
|
|
578
|
+
now: () => Date.now(),
|
|
579
|
+
clearUnitTimeout: deps.clearUnitTimeout,
|
|
580
|
+
completeIteration,
|
|
581
|
+
},
|
|
691
582
|
});
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
consecutiveErrors = 0;
|
|
695
|
-
consecutiveCooldowns = 0;
|
|
696
|
-
recentErrorMessages.length = 0;
|
|
697
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
|
|
698
|
-
saveStuckState(s, loopState); // persist across session restarts (#3704)
|
|
699
|
-
debugLog("autoLoop", { phase: "iteration-complete", iteration });
|
|
700
|
-
|
|
701
|
-
if (reconcileResult.outcome === "milestone-complete") {
|
|
702
|
-
await deps.stopAuto(ctx, pi, "Workflow complete");
|
|
703
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "milestone-complete", {
|
|
704
|
-
unitType: iterData.unitType,
|
|
705
|
-
unitId: iterData.unitId,
|
|
706
|
-
});
|
|
707
|
-
finishTurn("completed");
|
|
708
|
-
break;
|
|
709
|
-
}
|
|
710
|
-
if (reconcileResult.outcome === "pause") {
|
|
711
|
-
await deps.pauseAuto(ctx, pi);
|
|
712
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "pause", {
|
|
713
|
-
unitType: iterData.unitType,
|
|
714
|
-
unitId: iterData.unitId,
|
|
715
|
-
});
|
|
716
|
-
finishTurn("paused", "manual-attention");
|
|
717
|
-
break;
|
|
718
|
-
}
|
|
719
|
-
if (reconcileResult.outcome === "stop") {
|
|
720
|
-
await deps.stopAuto(ctx, pi, reconcileResult.reason ?? "Engine stopped");
|
|
721
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "stop", {
|
|
722
|
-
unitType: iterData.unitType,
|
|
723
|
-
unitId: iterData.unitId,
|
|
724
|
-
reason: reconcileResult.reason,
|
|
725
|
-
});
|
|
726
|
-
finishTurn("stopped", "manual-attention", reconcileResult.reason);
|
|
727
|
-
break;
|
|
728
|
-
}
|
|
729
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "continue", {
|
|
583
|
+
const reconcileFlow = await handleCustomEngineReconcileOutcome({
|
|
584
|
+
outcome: reconcileOutcome,
|
|
730
585
|
unitType: iterData.unitType,
|
|
731
586
|
unitId: iterData.unitId,
|
|
587
|
+
deps: {
|
|
588
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
589
|
+
pauseAuto: () => deps.pauseAuto(ctx, pi),
|
|
590
|
+
report: (action, details) => phaseReporter.report("custom-engine", action, details),
|
|
591
|
+
finishTurn,
|
|
592
|
+
},
|
|
732
593
|
});
|
|
733
|
-
|
|
594
|
+
if (reconcileFlow.action === "break") break;
|
|
734
595
|
continue;
|
|
735
596
|
}
|
|
736
597
|
|
|
737
598
|
if (!sidecarItem) {
|
|
738
599
|
// ── Phase 1: Pre-dispatch ─────────────────────────────────────────
|
|
739
600
|
const preDispatchResult = await runPreDispatch(ic, loopState);
|
|
740
|
-
|
|
601
|
+
phaseReporter.report("pre-dispatch", preDispatchResult.action);
|
|
741
602
|
if (preDispatchResult.action === "break") {
|
|
742
603
|
finishTurn("stopped", "manual-attention", "pre-dispatch-break");
|
|
743
604
|
break;
|
|
@@ -751,7 +612,7 @@ export async function autoLoop(
|
|
|
751
612
|
|
|
752
613
|
// ── Phase 2: Guards ───────────────────────────────────────────────
|
|
753
614
|
const guardsResult = await runGuards(ic, preData.mid);
|
|
754
|
-
|
|
615
|
+
phaseReporter.report("guard", guardsResult.action);
|
|
755
616
|
if (guardsResult.action === "break") {
|
|
756
617
|
finishTurn("stopped", "manual-attention", "guard-break");
|
|
757
618
|
break;
|
|
@@ -759,7 +620,7 @@ export async function autoLoop(
|
|
|
759
620
|
|
|
760
621
|
// ── Phase 3: Dispatch ─────────────────────────────────────────────
|
|
761
622
|
const dispatchResult = await runDispatch(ic, preData, loopState);
|
|
762
|
-
|
|
623
|
+
phaseReporter.report("dispatch", dispatchResult.action);
|
|
763
624
|
if (dispatchResult.action === "break") {
|
|
764
625
|
finishTurn("stopped", "manual-attention", "dispatch-break");
|
|
765
626
|
break;
|
|
@@ -772,30 +633,19 @@ export async function autoLoop(
|
|
|
772
633
|
observedUnitType = iterData.unitType;
|
|
773
634
|
observedUnitId = iterData.unitId;
|
|
774
635
|
} else {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
debugLog("autoLoop", {
|
|
778
|
-
phase: "post-derive",
|
|
779
|
-
site: "sidecar",
|
|
636
|
+
iterData = await buildSidecarIterationData({
|
|
637
|
+
sidecarItem,
|
|
780
638
|
basePath: s.basePath,
|
|
781
639
|
canonicalProjectRoot: s.canonicalProjectRoot,
|
|
782
|
-
|
|
783
|
-
|
|
640
|
+
deriveState: deps.deriveState,
|
|
641
|
+
logPostDerive: details => debugLog("autoLoop", {
|
|
642
|
+
phase: "post-derive",
|
|
643
|
+
...details,
|
|
644
|
+
}),
|
|
784
645
|
});
|
|
785
|
-
iterData = {
|
|
786
|
-
unitType: sidecarItem.unitType,
|
|
787
|
-
unitId: sidecarItem.unitId,
|
|
788
|
-
prompt: sidecarItem.prompt,
|
|
789
|
-
finalPrompt: sidecarItem.prompt,
|
|
790
|
-
pauseAfterUatDispatch: false,
|
|
791
|
-
state: sidecarState,
|
|
792
|
-
mid: sidecarState.activeMilestone?.id,
|
|
793
|
-
midTitle: sidecarState.activeMilestone?.title,
|
|
794
|
-
isRetry: false, previousTier: undefined,
|
|
795
|
-
};
|
|
796
646
|
observedUnitType = iterData.unitType;
|
|
797
647
|
observedUnitId = iterData.unitId;
|
|
798
|
-
|
|
648
|
+
phaseReporter.report("dispatch", "sidecar", {
|
|
799
649
|
unitType: iterData.unitType,
|
|
800
650
|
unitId: iterData.unitId,
|
|
801
651
|
sidecarKind: sidecarItem.kind,
|
|
@@ -810,12 +660,25 @@ export async function autoLoop(
|
|
|
810
660
|
// null when DB unavailable, no worker registered, or no active lease
|
|
811
661
|
// — those degraded paths fall through to the existing single-worker
|
|
812
662
|
// semantics with no ledger entry, preserving back-compat.
|
|
813
|
-
const dispatchClaim = openDispatchClaim(s, flowId, turnId, iterData
|
|
814
|
-
|
|
815
|
-
|
|
663
|
+
const dispatchClaim = openDispatchClaim(s, flowId, turnId, iterData, {
|
|
664
|
+
getRecentDispatchesForUnit,
|
|
665
|
+
recordDispatchClaim,
|
|
666
|
+
markDispatchRunning,
|
|
667
|
+
logClaimRejected: logDispatchClaimRejected,
|
|
668
|
+
logClaimFailed: logDispatchClaimFailed,
|
|
669
|
+
});
|
|
670
|
+
const dispatchDecision = decideDispatchClaim(
|
|
671
|
+
dispatchClaim.kind === "opened"
|
|
672
|
+
? { kind: "opened", dispatchId: dispatchClaim.dispatchId }
|
|
673
|
+
: dispatchClaim.kind === "skip"
|
|
674
|
+
? { kind: "skip", reason: dispatchClaim.reason }
|
|
675
|
+
: { kind: "degraded" },
|
|
676
|
+
);
|
|
677
|
+
if (dispatchDecision.action === "skip") {
|
|
678
|
+
finishTurn("skipped", "execution", dispatchDecision.reason);
|
|
816
679
|
continue;
|
|
817
680
|
}
|
|
818
|
-
dispatchId =
|
|
681
|
+
dispatchId = dispatchDecision.dispatchId;
|
|
819
682
|
|
|
820
683
|
let unitPhaseResult: Awaited<ReturnType<typeof runUnitPhaseViaContract>>;
|
|
821
684
|
try {
|
|
@@ -825,40 +688,35 @@ export async function autoLoop(
|
|
|
825
688
|
iterData,
|
|
826
689
|
loopState,
|
|
827
690
|
sidecarItem,
|
|
691
|
+
unitDispatchDeps,
|
|
828
692
|
);
|
|
829
693
|
} catch (err) {
|
|
830
694
|
if (err instanceof ModelPolicyDispatchBlockedError) {
|
|
831
695
|
throw err;
|
|
832
696
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
}
|
|
842
|
-
}
|
|
697
|
+
dispatchSettled = settleDispatchFailed(
|
|
698
|
+
dispatchId,
|
|
699
|
+
formatDispatchExceptionSummary({ error: err }),
|
|
700
|
+
{
|
|
701
|
+
markFailed: markDispatchFailed,
|
|
702
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
703
|
+
},
|
|
704
|
+
) || dispatchSettled;
|
|
843
705
|
throw err;
|
|
844
706
|
}
|
|
845
707
|
if (unitPhaseResult.action === "next") {
|
|
846
|
-
const requestTimestamp = unitPhaseResult.data
|
|
847
|
-
if (
|
|
708
|
+
const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
|
|
709
|
+
if (requestTimestamp !== undefined) s.lastRequestTimestamp = requestTimestamp;
|
|
848
710
|
}
|
|
849
|
-
|
|
711
|
+
phaseReporter.report("unit", unitPhaseResult.action, {
|
|
850
712
|
unitType: iterData.unitType,
|
|
851
713
|
unitId: iterData.unitId,
|
|
852
714
|
});
|
|
853
715
|
if (unitPhaseResult.action === "break") {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
} catch (err) {
|
|
859
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
|
|
860
|
-
}
|
|
861
|
-
}
|
|
716
|
+
dispatchSettled = settleDispatchFailed(dispatchId, "unit-break", {
|
|
717
|
+
markFailed: markDispatchFailed,
|
|
718
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
719
|
+
}) || dispatchSettled;
|
|
862
720
|
finishTurn("stopped", "execution", "unit-break");
|
|
863
721
|
break;
|
|
864
722
|
}
|
|
@@ -869,84 +727,68 @@ export async function autoLoop(
|
|
|
869
727
|
try {
|
|
870
728
|
finalizeResult = await runFinalize(ic, iterData, loopState, sidecarItem);
|
|
871
729
|
} catch (err) {
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
}
|
|
881
|
-
}
|
|
730
|
+
dispatchSettled = settleDispatchFailed(
|
|
731
|
+
dispatchId,
|
|
732
|
+
formatDispatchExceptionSummary({ error: err }),
|
|
733
|
+
{
|
|
734
|
+
markFailed: markDispatchFailed,
|
|
735
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
736
|
+
},
|
|
737
|
+
) || dispatchSettled;
|
|
882
738
|
throw err;
|
|
883
739
|
}
|
|
884
|
-
|
|
740
|
+
phaseReporter.report("finalize", finalizeResult.action, {
|
|
885
741
|
unitType: iterData.unitType,
|
|
886
742
|
unitId: iterData.unitId,
|
|
887
743
|
});
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
? "
|
|
891
|
-
: "
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
}
|
|
900
|
-
finishTurn("stopped",
|
|
744
|
+
const finalizeDecision = decideFinalizeResult(
|
|
745
|
+
finalizeResult.action === "break"
|
|
746
|
+
? { action: "break", reason: finalizeResult.reason }
|
|
747
|
+
: finalizeResult.action === "continue"
|
|
748
|
+
? { action: "continue" }
|
|
749
|
+
: { action: "next" },
|
|
750
|
+
);
|
|
751
|
+
if (finalizeDecision.action === "stop") {
|
|
752
|
+
dispatchSettled = settleDispatchFailed(dispatchId, finalizeDecision.ledgerErrorSummary, {
|
|
753
|
+
markFailed: markDispatchFailed,
|
|
754
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
755
|
+
}) || dispatchSettled;
|
|
756
|
+
finishTurn("stopped", finalizeDecision.failureClass, finalizeDecision.turnError);
|
|
901
757
|
break;
|
|
902
758
|
}
|
|
903
|
-
if (
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
} catch (err) {
|
|
909
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
|
|
910
|
-
}
|
|
911
|
-
}
|
|
759
|
+
if (finalizeDecision.action === "retry") {
|
|
760
|
+
dispatchSettled = settleDispatchFailed(dispatchId, finalizeDecision.ledgerErrorSummary, {
|
|
761
|
+
markFailed: markDispatchFailed,
|
|
762
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
763
|
+
}) || dispatchSettled;
|
|
912
764
|
finishTurn("retry");
|
|
913
765
|
continue;
|
|
914
766
|
}
|
|
915
767
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
consecutiveErrors = 0; // Iteration completed successfully
|
|
925
|
-
consecutiveCooldowns = 0;
|
|
926
|
-
recentErrorMessages.length = 0;
|
|
927
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
|
|
928
|
-
saveStuckState(s, loopState); // persist across session restarts (#4382)
|
|
929
|
-
debugLog("autoLoop", { phase: "iteration-complete", iteration });
|
|
768
|
+
dispatchSettled = settleDispatchCompleted(dispatchId, {
|
|
769
|
+
markCompleted: markDispatchCompleted,
|
|
770
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
771
|
+
}) || dispatchSettled;
|
|
772
|
+
completeIteration();
|
|
930
773
|
finishTurn("completed");
|
|
931
774
|
} catch (loopErr) {
|
|
932
775
|
// ── Blanket catch: absorb unexpected exceptions, apply graduated recovery ──
|
|
933
776
|
const msg = loopErr instanceof Error ? loopErr.message : String(loopErr);
|
|
934
777
|
if (dispatchId !== null && !dispatchSettled && !(loopErr instanceof ModelPolicyDispatchBlockedError)) {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}
|
|
778
|
+
dispatchSettled = settleDispatchFailed(
|
|
779
|
+
dispatchId,
|
|
780
|
+
formatUnhandledDispatchErrorSummary({ error: loopErr }),
|
|
781
|
+
{
|
|
782
|
+
markFailed: markDispatchFailed,
|
|
783
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
784
|
+
},
|
|
785
|
+
) || dispatchSettled;
|
|
944
786
|
}
|
|
945
787
|
|
|
946
788
|
// Always emit iteration-end on error so the journal records iteration
|
|
947
789
|
// completion even on failure (#2344). Without this, errors in
|
|
948
790
|
// runFinalize leave the journal incomplete, making diagnosis harder.
|
|
949
|
-
|
|
791
|
+
journalReporter.emit("iteration-end", { iteration, error: msg });
|
|
950
792
|
|
|
951
793
|
// ── Pre-send model-policy block: not a retryable error (#4959 / #4850) ──
|
|
952
794
|
// The model-policy gate runs before the prompt is sent. When every
|
|
@@ -957,6 +799,12 @@ export async function autoLoop(
|
|
|
957
799
|
// instead, with the per-model deny reasons surfaced from the typed
|
|
958
800
|
// error.
|
|
959
801
|
if (loopErr instanceof ModelPolicyDispatchBlockedError) {
|
|
802
|
+
const policyDecision = decideModelPolicyBlocked({
|
|
803
|
+
unitType: loopErr.unitType,
|
|
804
|
+
unitId: loopErr.unitId,
|
|
805
|
+
errorMessage: msg,
|
|
806
|
+
reasons: loopErr.reasons,
|
|
807
|
+
});
|
|
960
808
|
debugLog("autoLoop", {
|
|
961
809
|
phase: "model-policy-blocked",
|
|
962
810
|
iteration,
|
|
@@ -964,23 +812,8 @@ export async function autoLoop(
|
|
|
964
812
|
unitId: loopErr.unitId,
|
|
965
813
|
reasons: loopErr.reasons,
|
|
966
814
|
});
|
|
967
|
-
ctx.ui.notify(
|
|
968
|
-
|
|
969
|
-
"error",
|
|
970
|
-
);
|
|
971
|
-
deps.emitJournalEvent({
|
|
972
|
-
ts: new Date().toISOString(),
|
|
973
|
-
flowId,
|
|
974
|
-
seq: nextSeq(),
|
|
975
|
-
eventType: "unit-end",
|
|
976
|
-
data: {
|
|
977
|
-
unitType: loopErr.unitType,
|
|
978
|
-
unitId: loopErr.unitId,
|
|
979
|
-
status: "blocked",
|
|
980
|
-
reason: "model-policy-dispatch-blocked",
|
|
981
|
-
reasons: loopErr.reasons,
|
|
982
|
-
},
|
|
983
|
-
});
|
|
815
|
+
ctx.ui.notify(policyDecision.notifyMessage, "error");
|
|
816
|
+
journalReporter.emit("unit-end", policyDecision.journalData);
|
|
984
817
|
// Carry the blocked unit identity into the turn-result observer:
|
|
985
818
|
// the throw originated inside dispatch, so observedUnitType/Id were
|
|
986
819
|
// not assigned by the success path at lines 453/631/647 — but the
|
|
@@ -988,7 +821,7 @@ export async function autoLoop(
|
|
|
988
821
|
observedUnitType = loopErr.unitType;
|
|
989
822
|
observedUnitId = loopErr.unitId;
|
|
990
823
|
await deps.pauseAuto(ctx, pi);
|
|
991
|
-
finishTurn(
|
|
824
|
+
finishTurn(policyDecision.turnStatus, policyDecision.failureClass, msg);
|
|
992
825
|
// Do NOT increment consecutiveErrors — the failure is configuration,
|
|
993
826
|
// not a transient runtime fault.
|
|
994
827
|
break;
|
|
@@ -999,22 +832,19 @@ export async function autoLoop(
|
|
|
999
832
|
// LLM budget on guaranteed failures.
|
|
1000
833
|
const infraCode = isInfrastructureError(loopErr);
|
|
1001
834
|
if (infraCode) {
|
|
835
|
+
const infraDecision = decideInfrastructureError({
|
|
836
|
+
code: infraCode,
|
|
837
|
+
errorMessage: msg,
|
|
838
|
+
});
|
|
1002
839
|
debugLog("autoLoop", {
|
|
1003
840
|
phase: "infrastructure-error",
|
|
1004
841
|
iteration,
|
|
1005
842
|
code: infraCode,
|
|
1006
843
|
error: msg,
|
|
1007
844
|
});
|
|
1008
|
-
ctx.ui.notify(
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
);
|
|
1012
|
-
await deps.stopAuto(
|
|
1013
|
-
ctx,
|
|
1014
|
-
pi,
|
|
1015
|
-
`Infrastructure error (${infraCode}): not recoverable by retry`,
|
|
1016
|
-
);
|
|
1017
|
-
finishTurn("failed", "execution", msg);
|
|
845
|
+
ctx.ui.notify(infraDecision.notifyMessage, "error");
|
|
846
|
+
await deps.stopAuto(ctx, pi, infraDecision.stopMessage);
|
|
847
|
+
finishTurn(infraDecision.turnStatus, infraDecision.failureClass, msg);
|
|
1018
848
|
break;
|
|
1019
849
|
}
|
|
1020
850
|
|
|
@@ -1027,6 +857,12 @@ export async function autoLoop(
|
|
|
1027
857
|
if (isTransientCooldownError(loopErr)) {
|
|
1028
858
|
consecutiveCooldowns++;
|
|
1029
859
|
const retryAfterMs = getCooldownRetryAfterMs(loopErr);
|
|
860
|
+
const cooldownDecision = decideCooldownRecovery({
|
|
861
|
+
consecutiveCooldowns,
|
|
862
|
+
maxCooldownRetries: MAX_COOLDOWN_RETRIES,
|
|
863
|
+
retryAfterMs,
|
|
864
|
+
fallbackWaitMs: COOLDOWN_FALLBACK_WAIT_MS,
|
|
865
|
+
});
|
|
1030
866
|
debugLog("autoLoop", {
|
|
1031
867
|
phase: "cooldown-wait",
|
|
1032
868
|
iteration,
|
|
@@ -1035,27 +871,14 @@ export async function autoLoop(
|
|
|
1035
871
|
error: msg,
|
|
1036
872
|
});
|
|
1037
873
|
|
|
1038
|
-
if (
|
|
1039
|
-
ctx.ui.notify(
|
|
1040
|
-
|
|
1041
|
-
"error",
|
|
1042
|
-
);
|
|
1043
|
-
await deps.stopAuto(
|
|
1044
|
-
ctx,
|
|
1045
|
-
pi,
|
|
1046
|
-
`${consecutiveCooldowns} consecutive credential cooldowns exceeded retry budget`,
|
|
1047
|
-
);
|
|
874
|
+
if (cooldownDecision.action === "stop") {
|
|
875
|
+
ctx.ui.notify(cooldownDecision.notifyMessage, "error");
|
|
876
|
+
await deps.stopAuto(ctx, pi, cooldownDecision.stopMessage);
|
|
1048
877
|
break;
|
|
1049
878
|
}
|
|
1050
879
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
: COOLDOWN_FALLBACK_WAIT_MS;
|
|
1054
|
-
ctx.ui.notify(
|
|
1055
|
-
`Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`,
|
|
1056
|
-
"warning",
|
|
1057
|
-
);
|
|
1058
|
-
await new Promise(resolve => setTimeout(resolve, waitMs));
|
|
880
|
+
ctx.ui.notify(cooldownDecision.notifyMessage, "warning");
|
|
881
|
+
await new Promise(resolve => setTimeout(resolve, cooldownDecision.waitMs));
|
|
1059
882
|
finishTurn("retry", "timeout", msg);
|
|
1060
883
|
continue; // Retry iteration without incrementing consecutiveErrors
|
|
1061
884
|
}
|
|
@@ -1069,34 +892,24 @@ export async function autoLoop(
|
|
|
1069
892
|
error: msg,
|
|
1070
893
|
});
|
|
1071
894
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
);
|
|
1081
|
-
await deps.stopAuto(
|
|
1082
|
-
ctx,
|
|
1083
|
-
pi,
|
|
1084
|
-
`${consecutiveErrors} consecutive iteration failures`,
|
|
1085
|
-
);
|
|
1086
|
-
finishTurn("failed", "execution", msg);
|
|
895
|
+
const errorDecision = decideIterationErrorRecovery({
|
|
896
|
+
consecutiveErrors,
|
|
897
|
+
recentErrorMessages,
|
|
898
|
+
currentErrorMessage: msg,
|
|
899
|
+
});
|
|
900
|
+
if (errorDecision.action === "stop") {
|
|
901
|
+
ctx.ui.notify(errorDecision.notifyMessage, "error");
|
|
902
|
+
await deps.stopAuto(ctx, pi, errorDecision.stopMessage);
|
|
903
|
+
finishTurn(errorDecision.turnStatus, "execution", msg);
|
|
1087
904
|
break;
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
ctx.ui.notify(
|
|
1091
|
-
`Iteration error (attempt ${consecutiveErrors}): ${msg}. Invalidating caches and retrying.`,
|
|
1092
|
-
"warning",
|
|
1093
|
-
);
|
|
905
|
+
}
|
|
906
|
+
if (errorDecision.action === "invalidate-and-retry") {
|
|
907
|
+
ctx.ui.notify(errorDecision.notifyMessage, "warning");
|
|
1094
908
|
deps.invalidateAllCaches();
|
|
1095
909
|
} else {
|
|
1096
|
-
|
|
1097
|
-
ctx.ui.notify(`Iteration error: ${msg}. Retrying.`, "warning");
|
|
910
|
+
ctx.ui.notify(errorDecision.notifyMessage, "warning");
|
|
1098
911
|
}
|
|
1099
|
-
finishTurn(
|
|
912
|
+
finishTurn(errorDecision.turnStatus, "execution", msg);
|
|
1100
913
|
}
|
|
1101
914
|
}
|
|
1102
915
|
|