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
|
@@ -9,24 +9,39 @@
|
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
10
10
|
import { MAX_LOOP_ITERATIONS, } from "./types.js";
|
|
11
11
|
import { _clearCurrentResolve } from "./resolve.js";
|
|
12
|
-
import { runPreDispatch, runDispatch, runGuards,
|
|
12
|
+
import { runPreDispatch, runDispatch, runGuards, runFinalize, } from "./phases.js";
|
|
13
13
|
import { debugLog } from "../debug-logger.js";
|
|
14
14
|
import { isInfrastructureError, isTransientCooldownError, getCooldownRetryAfterMs, COOLDOWN_FALLBACK_WAIT_MS, MAX_COOLDOWN_RETRIES } from "./infra-errors.js";
|
|
15
15
|
import { ModelPolicyDispatchBlockedError } from "../auto-model-selection.js";
|
|
16
16
|
import { resolveEngine } from "../engine-resolver.js";
|
|
17
17
|
import { logWarning } from "../workflow-logger.js";
|
|
18
|
-
import { gsdRoot } from "../paths.js";
|
|
19
|
-
import { heartbeatAutoWorker } from "../db/auto-workers.js";
|
|
20
18
|
import { recordDispatchClaim, markRunning as markDispatchRunning, markCompleted as markDispatchCompleted, markFailed as markDispatchFailed, getRecentForUnit as getRecentDispatchesForUnit, getRecentUnitKeysForProjectRoot, } from "../db/unit-dispatches.js";
|
|
21
19
|
import { refreshMilestoneLease } from "../db/milestone-leases.js";
|
|
20
|
+
import { heartbeatAutoWorker } from "../db/auto-workers.js";
|
|
22
21
|
import { getRuntimeKv, setRuntimeKv } from "../db/runtime-kv.js";
|
|
23
|
-
import { atomicWriteSync } from "../atomic-write.js";
|
|
24
22
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
25
23
|
import { scheduleSidecarQueue } from "../uok/execution-graph.js";
|
|
26
|
-
import { ExecutionGraphScheduler } from "../uok/execution-graph.js";
|
|
27
|
-
import { readFileSync, mkdirSync, unlinkSync } from "node:fs";
|
|
28
|
-
import { join } from "node:path";
|
|
29
24
|
import { normalizeRealPath } from "../paths.js";
|
|
25
|
+
import { decideCooldownRecovery, decideDispatchClaim, decideEngineDispatch, decideFinalizeResult, decideInfrastructureError, decideIterationErrorRecovery, decideMemoryPressure, decideModelPolicyBlocked, decideMinRequestInterval, decideWorkflowLoop, formatDispatchExceptionSummary, formatUnhandledDispatchErrorSummary, resolveUnitRequestTimestamp, shouldUseCustomEnginePath, } from "./workflow-kernel.js";
|
|
26
|
+
import { hydrateCustomVerifyRetryCounts, saveCustomVerifyRetryCounts, } from "./custom-verify-retry-store.js";
|
|
27
|
+
import { settleDispatchCompleted, settleDispatchFailed, } from "./workflow-dispatch-ledger.js";
|
|
28
|
+
import { openDispatchClaim } from "./workflow-dispatch-claim.js";
|
|
29
|
+
import { completeWorkflowIteration } from "./workflow-iteration-completion.js";
|
|
30
|
+
import { createWorkflowJournalReporter } from "./workflow-journal-reporter.js";
|
|
31
|
+
import { createWorkflowPhaseReporter } from "./workflow-phase-reporter.js";
|
|
32
|
+
import { createWorkflowTurnReporter } from "./workflow-turn-reporter.js";
|
|
33
|
+
import { validateWorkflowSessionLock } from "./workflow-session-lock.js";
|
|
34
|
+
import { dequeueSidecarItem } from "./workflow-sidecar-queue.js";
|
|
35
|
+
import { maintainWorkerHeartbeat } from "./workflow-worker-heartbeat.js";
|
|
36
|
+
import { measureMemoryPressure } from "./workflow-memory-pressure.js";
|
|
37
|
+
import { buildSidecarIterationData } from "./workflow-sidecar-iteration.js";
|
|
38
|
+
import { createExecutionGraphUnitDispatchDeps, runUnitPhaseViaContract, } from "./workflow-unit-dispatch.js";
|
|
39
|
+
import { handleCustomEngineDispatchOutcome } from "./workflow-custom-engine-dispatch-outcome.js";
|
|
40
|
+
import { buildCustomEngineIterationData } from "./workflow-custom-engine-iteration.js";
|
|
41
|
+
import { handleCustomEngineVerifyRetry } from "./workflow-custom-engine-retry.js";
|
|
42
|
+
import { handleCustomEngineVerifyPause, handleCustomEngineVerifyRetryOutcome, } from "./workflow-custom-engine-verify-outcome.js";
|
|
43
|
+
import { handleCustomEngineReconcile } from "./workflow-custom-engine-reconcile.js";
|
|
44
|
+
import { handleCustomEngineReconcileOutcome } from "./workflow-custom-engine-reconcile-outcome.js";
|
|
30
45
|
// ── Stuck detection persistence (#3704) ──────────────────────────────────
|
|
31
46
|
// Phase C migration: stuck-state.json deleted in favor of DB-backed
|
|
32
47
|
// equivalents. recentUnits is rebuilt from unit_dispatches (Phase B
|
|
@@ -70,200 +85,54 @@ function saveStuckState(s, state) {
|
|
|
70
85
|
debugLog("autoLoop", { phase: "save-stuck-state-failed", error: err instanceof Error ? err.message : String(err) });
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return s.activeRunDir ? join(s.activeRunDir, "runtime") : join(gsdRoot(s.basePath), "runtime");
|
|
88
|
+
function logDispatchLedgerWriteFailure(err) {
|
|
89
|
+
debugLog("autoLoop", {
|
|
90
|
+
phase: "dispatch-ledger-write-failed",
|
|
91
|
+
error: err instanceof Error ? err.message : String(err),
|
|
92
|
+
});
|
|
79
93
|
}
|
|
80
|
-
function
|
|
81
|
-
|
|
94
|
+
function logDispatchClaimRejected(details) {
|
|
95
|
+
debugLog("autoLoop", {
|
|
96
|
+
phase: "dispatch-claim-rejected",
|
|
97
|
+
...details,
|
|
98
|
+
});
|
|
82
99
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const raw = JSON.parse(readFileSync(customVerifyRetryStatePath(s), "utf-8"));
|
|
89
|
-
const counts = raw && typeof raw === "object" && raw.counts && typeof raw.counts === "object"
|
|
90
|
-
? raw.counts
|
|
91
|
-
: {};
|
|
92
|
-
for (const [key, value] of Object.entries(counts)) {
|
|
93
|
-
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
94
|
-
s.verificationRetryCount.set(key, Math.floor(value));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
debugLog("autoLoop", { phase: "load-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
|
|
100
|
-
}
|
|
101
|
-
return s.verificationRetryCount;
|
|
100
|
+
function logDispatchClaimFailed(err) {
|
|
101
|
+
debugLog("autoLoop", {
|
|
102
|
+
phase: "dispatch-claim-failed",
|
|
103
|
+
error: err instanceof Error ? err.message : String(err),
|
|
104
|
+
});
|
|
102
105
|
}
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
unlinkSync(filePath);
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
mkdirSync(customVerifyRetryStateDir(s), { recursive: true });
|
|
112
|
-
atomicWriteSync(filePath, JSON.stringify({
|
|
113
|
-
counts: Object.fromEntries(retryCounts),
|
|
114
|
-
updatedAt: new Date().toISOString(),
|
|
115
|
-
}) + "\n");
|
|
116
|
-
}
|
|
117
|
-
catch (err) {
|
|
118
|
-
const code = err && typeof err === "object" && "code" in err ? err.code : undefined;
|
|
119
|
-
if (code !== "ENOENT") {
|
|
120
|
-
debugLog("autoLoop", { phase: "save-custom-verify-retries-failed", error: err instanceof Error ? err.message : String(err) });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
106
|
+
function logCustomVerifyRetryLoadFailure(err) {
|
|
107
|
+
debugLog("autoLoop", {
|
|
108
|
+
phase: "load-custom-verify-retries-failed",
|
|
109
|
+
error: err instanceof Error ? err.message : String(err),
|
|
110
|
+
});
|
|
123
111
|
}
|
|
124
|
-
function
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return { kind: "degraded" };
|
|
130
|
-
const recent = getRecentDispatchesForUnit(iterData.unitId, 1);
|
|
131
|
-
const attemptN = (recent[0]?.attempt_n ?? 0) + 1;
|
|
132
|
-
let claim;
|
|
133
|
-
try {
|
|
134
|
-
claim = recordDispatchClaim({
|
|
135
|
-
traceId: flowId,
|
|
136
|
-
turnId,
|
|
137
|
-
workerId: s.workerId,
|
|
138
|
-
milestoneLeaseToken: s.milestoneLeaseToken,
|
|
139
|
-
milestoneId: mid,
|
|
140
|
-
sliceId: iterData.state.activeSlice?.id ?? null,
|
|
141
|
-
taskId: iterData.state.activeTask?.id ?? null,
|
|
142
|
-
unitType: iterData.unitType,
|
|
143
|
-
unitId: iterData.unitId,
|
|
144
|
-
attemptN,
|
|
145
|
-
});
|
|
146
|
-
if (!claim.ok) {
|
|
147
|
-
debugLog("autoLoop", {
|
|
148
|
-
phase: "dispatch-claim-rejected",
|
|
149
|
-
unitId: iterData.unitId,
|
|
150
|
-
reason: claim.error,
|
|
151
|
-
existingId: "existingId" in claim ? claim.existingId : undefined,
|
|
152
|
-
existingWorker: "existingWorker" in claim ? claim.existingWorker : undefined,
|
|
153
|
-
});
|
|
154
|
-
if (claim.error === "already_active") {
|
|
155
|
-
return {
|
|
156
|
-
kind: "skip",
|
|
157
|
-
reason: "already-active",
|
|
158
|
-
existingId: claim.existingId,
|
|
159
|
-
existingWorker: claim.existingWorker,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
return { kind: "skip", reason: "stale-lease" };
|
|
163
|
-
}
|
|
164
|
-
markDispatchRunning(claim.dispatchId);
|
|
165
|
-
return { kind: "opened", dispatchId: claim.dispatchId };
|
|
166
|
-
}
|
|
167
|
-
catch (err) {
|
|
168
|
-
debugLog("autoLoop", {
|
|
169
|
-
phase: "dispatch-claim-failed",
|
|
170
|
-
error: err instanceof Error ? err.message : String(err),
|
|
171
|
-
});
|
|
172
|
-
return { kind: "degraded" };
|
|
173
|
-
}
|
|
112
|
+
function logCustomVerifyRetrySaveFailure(err) {
|
|
113
|
+
debugLog("autoLoop", {
|
|
114
|
+
phase: "save-custom-verify-retries-failed",
|
|
115
|
+
error: err instanceof Error ? err.message : String(err),
|
|
116
|
+
});
|
|
174
117
|
}
|
|
175
118
|
// ── Memory pressure monitoring (#3331) ──────────────────────────────────
|
|
176
119
|
// Check heap usage every N iterations and trigger graceful shutdown before
|
|
177
120
|
// the OS OOM killer sends SIGKILL. The threshold is 90% of the V8 heap
|
|
178
121
|
// limit (--max-old-space-size or default ~1.5-4GB depending on platform).
|
|
179
122
|
const MEMORY_CHECK_INTERVAL = 5; // check every 5 iterations
|
|
180
|
-
const MEMORY_PRESSURE_THRESHOLD = 0.85; // 85% of heap limit
|
|
181
123
|
const MAX_CUSTOM_ENGINE_VERIFY_RETRIES = 3;
|
|
182
|
-
function checkMemoryPressure() {
|
|
183
|
-
const mem = process.memoryUsage();
|
|
184
|
-
// v8.getHeapStatistics() gives heap_size_limit but requires import
|
|
185
|
-
// Use a conservative estimate: RSS > 3GB is danger zone on most systems
|
|
186
|
-
const heapMB = Math.round(mem.heapUsed / 1024 / 1024);
|
|
187
|
-
const rssMB = Math.round(mem.rss / 1024 / 1024);
|
|
188
|
-
// Try to get the actual V8 heap limit
|
|
189
|
-
let limitMB = 4096; // conservative default
|
|
190
|
-
try {
|
|
191
|
-
const v8 = require("node:v8");
|
|
192
|
-
const stats = v8.getHeapStatistics();
|
|
193
|
-
limitMB = Math.round(stats.heap_size_limit / 1024 / 1024);
|
|
194
|
-
}
|
|
195
|
-
catch {
|
|
196
|
-
limitMB = 4096; /* v8 stats unavailable — use conservative default */
|
|
197
|
-
}
|
|
198
|
-
const pct = heapMB / limitMB;
|
|
199
|
-
return { pressured: pct > MEMORY_PRESSURE_THRESHOLD, heapMB, limitMB, pct };
|
|
200
|
-
}
|
|
201
|
-
function resolveDispatchNodeKind(unitType, sidecarItem) {
|
|
202
|
-
if (sidecarItem?.kind === "hook")
|
|
203
|
-
return "hook";
|
|
204
|
-
if (sidecarItem?.kind === "triage")
|
|
205
|
-
return "verification";
|
|
206
|
-
if (sidecarItem?.kind === "quick-task")
|
|
207
|
-
return "team-worker";
|
|
208
|
-
if (unitType.startsWith("hook/"))
|
|
209
|
-
return "hook";
|
|
210
|
-
if (unitType === "reactive-execute")
|
|
211
|
-
return "subagent";
|
|
212
|
-
if (unitType === "gate-evaluate"
|
|
213
|
-
|| unitType === "validate-milestone"
|
|
214
|
-
|| unitType === "run-uat"
|
|
215
|
-
|| unitType === "complete-slice") {
|
|
216
|
-
return "verification";
|
|
217
|
-
}
|
|
218
|
-
if (unitType === "replan-slice" || unitType === "reassess-roadmap") {
|
|
219
|
-
return "reprocess";
|
|
220
|
-
}
|
|
221
|
-
return "unit";
|
|
222
|
-
}
|
|
223
124
|
async function enforceMinRequestInterval(s, prefs) {
|
|
224
125
|
const minInterval = prefs?.min_request_interval_ms ?? 0;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
126
|
+
const decision = decideMinRequestInterval({
|
|
127
|
+
minIntervalMs: minInterval,
|
|
128
|
+
lastRequestTimestamp: s.lastRequestTimestamp,
|
|
129
|
+
nowMs: Date.now(),
|
|
130
|
+
});
|
|
131
|
+
if (decision.action === "wait") {
|
|
132
|
+
debugLog("autoLoop", { phase: "rate-limit-wait", waitMs: decision.waitMs });
|
|
133
|
+
await new Promise(r => setTimeout(r, decision.waitMs));
|
|
232
134
|
}
|
|
233
135
|
}
|
|
234
|
-
async function runUnitPhaseViaContract(dispatchContract, ic, iterData, loopState, sidecarItem) {
|
|
235
|
-
if (dispatchContract === "legacy-direct") {
|
|
236
|
-
return runUnitPhase(ic, iterData, loopState, sidecarItem);
|
|
237
|
-
}
|
|
238
|
-
const scheduler = new ExecutionGraphScheduler();
|
|
239
|
-
let outcome = null;
|
|
240
|
-
const executeNode = async () => {
|
|
241
|
-
outcome = await runUnitPhase(ic, iterData, loopState, sidecarItem);
|
|
242
|
-
};
|
|
243
|
-
const kinds = [
|
|
244
|
-
"unit",
|
|
245
|
-
"hook",
|
|
246
|
-
"subagent",
|
|
247
|
-
"team-worker",
|
|
248
|
-
"verification",
|
|
249
|
-
"reprocess",
|
|
250
|
-
];
|
|
251
|
-
for (const kind of kinds)
|
|
252
|
-
scheduler.registerHandler(kind, executeNode);
|
|
253
|
-
const nodeId = `dispatch:${ic.iteration}:${iterData.unitType}:${iterData.unitId}`;
|
|
254
|
-
await scheduler.run([
|
|
255
|
-
{
|
|
256
|
-
id: nodeId,
|
|
257
|
-
kind: resolveDispatchNodeKind(iterData.unitType, sidecarItem),
|
|
258
|
-
dependsOn: [],
|
|
259
|
-
metadata: {
|
|
260
|
-
unitType: iterData.unitType,
|
|
261
|
-
unitId: iterData.unitId,
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
|
-
], { parallel: false, maxWorkers: 1 });
|
|
265
|
-
return outcome ?? { action: "break", reason: "scheduler-dispatch-missing-result" };
|
|
266
|
-
}
|
|
267
136
|
/**
|
|
268
137
|
* Main auto-mode execution loop. Iterates: derive → dispatch → guards →
|
|
269
138
|
* runUnit → finalize → repeat. Exits when s.active becomes false or a
|
|
@@ -276,6 +145,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
276
145
|
debugLog("autoLoop", { phase: "enter" });
|
|
277
146
|
let iteration = 0;
|
|
278
147
|
const dispatchContract = options?.dispatchContract ?? "legacy-direct";
|
|
148
|
+
const unitDispatchDeps = createExecutionGraphUnitDispatchDeps();
|
|
279
149
|
// Load persisted stuck state so counters survive session restarts (#3704)
|
|
280
150
|
const persisted = loadStuckState(s);
|
|
281
151
|
const loopState = {
|
|
@@ -289,65 +159,65 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
289
159
|
while (s.active) {
|
|
290
160
|
iteration++;
|
|
291
161
|
debugLog("autoLoop", { phase: "loop-top", iteration });
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
catch (err) {
|
|
303
|
-
debugLog("autoLoop", {
|
|
304
|
-
phase: "heartbeat-failed",
|
|
305
|
-
error: err instanceof Error ? err.message : String(err),
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
}
|
|
162
|
+
maintainWorkerHeartbeat(s, {
|
|
163
|
+
heartbeatAutoWorker,
|
|
164
|
+
refreshMilestoneLease,
|
|
165
|
+
logHeartbeatFailure: err => debugLog("autoLoop", {
|
|
166
|
+
phase: "heartbeat-failed",
|
|
167
|
+
error: err instanceof Error ? err.message : String(err),
|
|
168
|
+
}),
|
|
169
|
+
});
|
|
309
170
|
// ── Journal: per-iteration flow grouping ──
|
|
310
171
|
const flowId = randomUUID();
|
|
311
172
|
let seqCounter = 0;
|
|
312
173
|
const nextSeq = () => ++seqCounter;
|
|
174
|
+
const journalReporter = createWorkflowJournalReporter({
|
|
175
|
+
emitJournalEvent: deps.emitJournalEvent,
|
|
176
|
+
flowId,
|
|
177
|
+
nextSeq,
|
|
178
|
+
});
|
|
313
179
|
const turnId = randomUUID();
|
|
314
180
|
s.currentTraceId = flowId;
|
|
315
181
|
s.currentTurnId = turnId;
|
|
316
182
|
const turnStartedAt = new Date().toISOString();
|
|
317
183
|
let observedUnitType;
|
|
318
184
|
let observedUnitId;
|
|
319
|
-
|
|
185
|
+
const phaseReporter = createWorkflowPhaseReporter({
|
|
186
|
+
observer: deps.uokObserver,
|
|
187
|
+
});
|
|
188
|
+
const turnReporter = createWorkflowTurnReporter({
|
|
189
|
+
observer: deps.uokObserver,
|
|
190
|
+
traceId: flowId,
|
|
191
|
+
turnId,
|
|
192
|
+
iteration,
|
|
193
|
+
basePath: s.basePath,
|
|
194
|
+
startedAt: turnStartedAt,
|
|
195
|
+
clearCurrentTurn: () => {
|
|
196
|
+
s.currentTraceId = null;
|
|
197
|
+
s.currentTurnId = null;
|
|
198
|
+
},
|
|
199
|
+
});
|
|
320
200
|
const finishTurn = (status, failureClass = "none", error) => {
|
|
321
|
-
|
|
322
|
-
return;
|
|
323
|
-
turnFinished = true;
|
|
324
|
-
deps.uokObserver?.onTurnResult({
|
|
325
|
-
traceId: flowId,
|
|
326
|
-
turnId,
|
|
327
|
-
iteration,
|
|
201
|
+
turnReporter.finish({
|
|
328
202
|
unitType: observedUnitType,
|
|
329
203
|
unitId: observedUnitId,
|
|
330
204
|
status,
|
|
331
205
|
failureClass,
|
|
332
|
-
phaseResults: [],
|
|
333
206
|
error,
|
|
334
|
-
startedAt: turnStartedAt,
|
|
335
|
-
finishedAt: new Date().toISOString(),
|
|
336
207
|
});
|
|
337
|
-
s.currentTraceId = null;
|
|
338
|
-
s.currentTurnId = null;
|
|
339
208
|
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
209
|
+
turnReporter.start();
|
|
210
|
+
const iterationDecision = decideWorkflowLoop({
|
|
211
|
+
active: s.active,
|
|
343
212
|
iteration,
|
|
344
|
-
|
|
345
|
-
|
|
213
|
+
maxIterations: MAX_LOOP_ITERATIONS,
|
|
214
|
+
hasCommandContext: true,
|
|
215
|
+
sessionLockValid: true,
|
|
346
216
|
});
|
|
347
|
-
if (
|
|
217
|
+
if (iterationDecision.action === "stop" && iterationDecision.reason === "max-iterations") {
|
|
348
218
|
debugLog("autoLoop", {
|
|
349
219
|
phase: "exit",
|
|
350
|
-
reason:
|
|
220
|
+
reason: iterationDecision.reason,
|
|
351
221
|
iteration,
|
|
352
222
|
});
|
|
353
223
|
await deps.stopAuto(ctx, pi, `Safety: loop exceeded ${MAX_LOOP_ITERATIONS} iterations — possible runaway`);
|
|
@@ -357,69 +227,79 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
357
227
|
// ── Memory pressure check (#3331) ──
|
|
358
228
|
// Graceful shutdown before OOM killer sends SIGKILL.
|
|
359
229
|
if (iteration % MEMORY_CHECK_INTERVAL === 0) {
|
|
360
|
-
const mem =
|
|
230
|
+
const mem = measureMemoryPressure();
|
|
361
231
|
debugLog("autoLoop", { phase: "memory-check", ...mem });
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
finishTurn("stopped", "timeout", "memory-pressure");
|
|
232
|
+
const memoryDecision = decideMemoryPressure({ ...mem, iteration });
|
|
233
|
+
if (memoryDecision.action === "stop") {
|
|
234
|
+
logWarning("dispatch", memoryDecision.warningMessage);
|
|
235
|
+
await deps.stopAuto(ctx, pi, memoryDecision.stopMessage);
|
|
236
|
+
finishTurn("stopped", "timeout", memoryDecision.turnError);
|
|
368
237
|
break;
|
|
369
238
|
}
|
|
370
239
|
}
|
|
371
|
-
|
|
240
|
+
const commandContextDecision = decideWorkflowLoop({
|
|
241
|
+
active: s.active,
|
|
242
|
+
iteration,
|
|
243
|
+
maxIterations: MAX_LOOP_ITERATIONS,
|
|
244
|
+
hasCommandContext: Boolean(s.cmdCtx),
|
|
245
|
+
sessionLockValid: true,
|
|
246
|
+
});
|
|
247
|
+
if (commandContextDecision.action === "stop" && commandContextDecision.reason === "missing-command-context") {
|
|
372
248
|
debugLog("autoLoop", { phase: "exit", reason: "no-cmdCtx" });
|
|
373
|
-
finishTurn("stopped", "manual-attention",
|
|
249
|
+
finishTurn("stopped", "manual-attention", commandContextDecision.reason);
|
|
374
250
|
break;
|
|
375
251
|
}
|
|
376
252
|
let dispatchId = null;
|
|
377
253
|
let dispatchSettled = false;
|
|
254
|
+
const completeIteration = () => {
|
|
255
|
+
completeWorkflowIteration({
|
|
256
|
+
get consecutiveErrors() { return consecutiveErrors; },
|
|
257
|
+
set consecutiveErrors(value) { consecutiveErrors = value; },
|
|
258
|
+
get consecutiveCooldowns() { return consecutiveCooldowns; },
|
|
259
|
+
set consecutiveCooldowns(value) { consecutiveCooldowns = value; },
|
|
260
|
+
recentErrorMessages,
|
|
261
|
+
}, {
|
|
262
|
+
emitIterationEnd: () => journalReporter.emit("iteration-end", { iteration }),
|
|
263
|
+
saveStuckState: () => saveStuckState(s, loopState),
|
|
264
|
+
logIterationComplete: () => debugLog("autoLoop", { phase: "iteration-complete", iteration }),
|
|
265
|
+
});
|
|
266
|
+
};
|
|
378
267
|
try {
|
|
379
268
|
// ── Blanket try/catch: one bad iteration must not kill the session
|
|
380
269
|
const prefs = deps.loadEffectiveGSDPreferences()?.preferences;
|
|
381
270
|
const uokFlags = resolveUokFlags(prefs);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
sidecarItem = s.sidecarQueue.shift();
|
|
394
|
-
debugLog("autoLoop", {
|
|
395
|
-
phase: "sidecar-dequeue",
|
|
396
|
-
kind: sidecarItem.kind,
|
|
397
|
-
unitType: sidecarItem.unitType,
|
|
398
|
-
unitId: sidecarItem.unitId,
|
|
399
|
-
});
|
|
400
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "sidecar-dequeue", data: { kind: sidecarItem.kind, unitType: sidecarItem.unitType, unitId: sidecarItem.unitId } });
|
|
401
|
-
}
|
|
402
|
-
const sessionLockBase = deps.lockBase();
|
|
403
|
-
if (sessionLockBase) {
|
|
404
|
-
const lockStatus = deps.validateSessionLock(sessionLockBase);
|
|
405
|
-
if (!lockStatus.valid) {
|
|
406
|
-
debugLog("autoLoop", {
|
|
271
|
+
const sessionLockOutcome = validateWorkflowSessionLock({
|
|
272
|
+
active: s.active,
|
|
273
|
+
iteration,
|
|
274
|
+
maxIterations: MAX_LOOP_ITERATIONS,
|
|
275
|
+
deps: {
|
|
276
|
+
lockBase: deps.lockBase,
|
|
277
|
+
validateSessionLock: deps.validateSessionLock,
|
|
278
|
+
handleLostSessionLock: lockStatus => deps.handleLostSessionLock(ctx, lockStatus),
|
|
279
|
+
logInvalidSessionLock: details => debugLog("autoLoop", {
|
|
407
280
|
phase: "session-lock-invalid",
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
});
|
|
412
|
-
deps.handleLostSessionLock(ctx, lockStatus);
|
|
413
|
-
debugLog("autoLoop", {
|
|
281
|
+
...details,
|
|
282
|
+
}),
|
|
283
|
+
logSessionLockExit: details => debugLog("autoLoop", {
|
|
414
284
|
phase: "exit",
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
285
|
+
...details,
|
|
286
|
+
}),
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
if (sessionLockOutcome.action === "stop" && sessionLockOutcome.reason === "session-lock-lost") {
|
|
290
|
+
break;
|
|
420
291
|
}
|
|
292
|
+
// ── Check sidecar queue before deriveState ──
|
|
293
|
+
const sidecarItem = await dequeueSidecarItem({
|
|
294
|
+
queue: s.sidecarQueue,
|
|
295
|
+
executionGraphEnabled: uokFlags.executionGraph,
|
|
296
|
+
scheduleQueue: scheduleSidecarQueue,
|
|
297
|
+
warnSchedulingFailure: message => logWarning("dispatch", `sidecar queue scheduling failed: ${message}`),
|
|
298
|
+
logDequeue: payload => debugLog("autoLoop", { phase: "sidecar-dequeue", ...payload }),
|
|
299
|
+
emitDequeue: payload => journalReporter.emit("sidecar-dequeue", payload),
|
|
300
|
+
});
|
|
421
301
|
const ic = { ctx, pi, s, deps, prefs, iteration, flowId, nextSeq };
|
|
422
|
-
|
|
302
|
+
journalReporter.emit("iteration-start", { iteration });
|
|
423
303
|
let iterData;
|
|
424
304
|
// ── Custom engine path ──────────────────────────────────────────────
|
|
425
305
|
// When activeEngineId is a non-dev value, bypass runPreDispatch and
|
|
@@ -429,7 +309,11 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
429
309
|
//
|
|
430
310
|
// GSD_ENGINE_BYPASS=1 skips the engine layer entirely — falls through
|
|
431
311
|
// to the dev path below.
|
|
432
|
-
if (
|
|
312
|
+
if (shouldUseCustomEnginePath({
|
|
313
|
+
activeEngineId: s.activeEngineId,
|
|
314
|
+
hasSidecarItem: Boolean(sidecarItem),
|
|
315
|
+
engineBypass: process.env.GSD_ENGINE_BYPASS === "1",
|
|
316
|
+
})) {
|
|
433
317
|
debugLog("autoLoop", { phase: "custom-engine-derive", iteration, engineId: s.activeEngineId });
|
|
434
318
|
const { engine, policy } = resolveEngine({
|
|
435
319
|
activeEngineId: s.activeEngineId,
|
|
@@ -452,43 +336,47 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
452
336
|
}
|
|
453
337
|
debugLog("autoLoop", { phase: "custom-engine-dispatch", iteration });
|
|
454
338
|
const dispatch = await engine.resolveDispatch(engineState, { basePath: s.basePath });
|
|
455
|
-
|
|
456
|
-
|
|
339
|
+
const engineDispatchDecision = decideEngineDispatch(dispatch.action === "stop"
|
|
340
|
+
? { action: "stop", reason: dispatch.reason }
|
|
341
|
+
: { action: dispatch.action });
|
|
342
|
+
const dispatchFlow = await handleCustomEngineDispatchOutcome({
|
|
343
|
+
decision: engineDispatchDecision,
|
|
344
|
+
deps: {
|
|
345
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
if (dispatchFlow.action === "break") {
|
|
349
|
+
finishTurn("stopped", "manual-attention", "custom-engine-dispatch-stop");
|
|
457
350
|
break;
|
|
458
351
|
}
|
|
459
|
-
if (
|
|
352
|
+
if (dispatchFlow.action === "continue") {
|
|
353
|
+
finishTurn("skipped");
|
|
460
354
|
continue;
|
|
461
355
|
}
|
|
462
356
|
// dispatch.action === "dispatch"
|
|
357
|
+
if (dispatch.action !== "dispatch") {
|
|
358
|
+
finishTurn("skipped");
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
463
361
|
const step = dispatch.step;
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
phase: "post-derive",
|
|
467
|
-
site: "custom-engine-gsd-state",
|
|
362
|
+
iterData = await buildCustomEngineIterationData({
|
|
363
|
+
step,
|
|
468
364
|
basePath: s.basePath,
|
|
469
365
|
canonicalProjectRoot: s.canonicalProjectRoot,
|
|
470
|
-
|
|
471
|
-
|
|
366
|
+
currentMilestoneId: s.currentMilestoneId,
|
|
367
|
+
deriveState: deps.deriveState,
|
|
368
|
+
logPostDerive: details => debugLog("autoLoop", {
|
|
369
|
+
phase: "post-derive",
|
|
370
|
+
...details,
|
|
371
|
+
}),
|
|
472
372
|
});
|
|
473
|
-
iterData = {
|
|
474
|
-
unitType: step.unitType,
|
|
475
|
-
unitId: step.unitId,
|
|
476
|
-
prompt: step.prompt,
|
|
477
|
-
finalPrompt: step.prompt,
|
|
478
|
-
pauseAfterUatDispatch: false,
|
|
479
|
-
state: gsdState,
|
|
480
|
-
mid: s.currentMilestoneId ?? "workflow",
|
|
481
|
-
midTitle: "Workflow",
|
|
482
|
-
isRetry: false,
|
|
483
|
-
previousTier: undefined,
|
|
484
|
-
};
|
|
485
373
|
observedUnitType = iterData.unitType;
|
|
486
374
|
observedUnitId = iterData.unitId;
|
|
487
375
|
// ── Progress widget (mirrors dev path in runDispatch) ──
|
|
488
376
|
deps.updateProgressWidget(ctx, iterData.unitType, iterData.unitId, iterData.state);
|
|
489
377
|
// ── Guards (shared with dev path) ──
|
|
490
378
|
const guardsResult = await runGuards(ic, s.currentMilestoneId ?? "workflow");
|
|
491
|
-
|
|
379
|
+
phaseReporter.report("guard", guardsResult.action, {
|
|
492
380
|
unitType: iterData.unitType,
|
|
493
381
|
unitId: iterData.unitId,
|
|
494
382
|
});
|
|
@@ -498,13 +386,13 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
498
386
|
}
|
|
499
387
|
// ── Unit execution (shared with dev path) ──
|
|
500
388
|
await enforceMinRequestInterval(s, prefs);
|
|
501
|
-
const unitPhaseResult = await runUnitPhaseViaContract(dispatchContract, ic, iterData, loopState);
|
|
389
|
+
const unitPhaseResult = await runUnitPhaseViaContract(dispatchContract, ic, iterData, loopState, undefined, unitDispatchDeps);
|
|
502
390
|
if (unitPhaseResult.action === "next") {
|
|
503
|
-
const requestTimestamp = unitPhaseResult.data
|
|
504
|
-
if (
|
|
391
|
+
const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
|
|
392
|
+
if (requestTimestamp !== undefined)
|
|
505
393
|
s.lastRequestTimestamp = requestTimestamp;
|
|
506
394
|
}
|
|
507
|
-
|
|
395
|
+
phaseReporter.report("unit", unitPhaseResult.action, {
|
|
508
396
|
unitType: iterData.unitType,
|
|
509
397
|
unitId: iterData.unitId,
|
|
510
398
|
});
|
|
@@ -516,103 +404,94 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
516
404
|
debugLog("autoLoop", { phase: "custom-engine-verify", iteration, unitId: iterData.unitId });
|
|
517
405
|
const verifyResult = await policy.verify(iterData.unitType, iterData.unitId, { basePath: s.basePath });
|
|
518
406
|
if (verifyResult === "pause") {
|
|
519
|
-
await
|
|
520
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "pause", {
|
|
407
|
+
const verifyFlow = await handleCustomEngineVerifyPause({
|
|
521
408
|
unitType: iterData.unitType,
|
|
522
409
|
unitId: iterData.unitId,
|
|
410
|
+
deps: {
|
|
411
|
+
pauseAuto: () => deps.pauseAuto(ctx, pi),
|
|
412
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
413
|
+
reportPause: details => phaseReporter.report("custom-engine", "pause", details),
|
|
414
|
+
finishTurn,
|
|
415
|
+
},
|
|
523
416
|
});
|
|
524
|
-
|
|
525
|
-
|
|
417
|
+
if (verifyFlow.action === "break")
|
|
418
|
+
break;
|
|
526
419
|
}
|
|
527
420
|
if (verifyResult === "retry") {
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
const attempts = (retryCounts.get(recoveryKey) ?? 0) + 1;
|
|
531
|
-
retryCounts.set(recoveryKey, attempts);
|
|
532
|
-
saveCustomVerifyRetryCounts(s);
|
|
533
|
-
debugLog("autoLoop", { phase: "custom-engine-verify-retry", iteration, unitId: iterData.unitId, attempts });
|
|
534
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "retry", {
|
|
421
|
+
const retryOutcome = await handleCustomEngineVerifyRetry({
|
|
422
|
+
session: s,
|
|
535
423
|
unitType: iterData.unitType,
|
|
536
424
|
unitId: iterData.unitId,
|
|
537
|
-
|
|
425
|
+
basePath: s.basePath,
|
|
426
|
+
iteration,
|
|
427
|
+
maxRetries: MAX_CUSTOM_ENGINE_VERIFY_RETRIES,
|
|
428
|
+
deps: {
|
|
429
|
+
hydrateRetryCounts: () => hydrateCustomVerifyRetryCounts(s, {
|
|
430
|
+
logFailure: logCustomVerifyRetryLoadFailure,
|
|
431
|
+
}),
|
|
432
|
+
saveRetryCounts: () => saveCustomVerifyRetryCounts(s, {
|
|
433
|
+
logFailure: logCustomVerifyRetrySaveFailure,
|
|
434
|
+
}),
|
|
435
|
+
recover: (unitType, unitId, options) => policy.recover(unitType, unitId, options),
|
|
436
|
+
logRetry: details => debugLog("autoLoop", {
|
|
437
|
+
phase: "custom-engine-verify-retry",
|
|
438
|
+
...details,
|
|
439
|
+
}),
|
|
440
|
+
reportRetry: details => phaseReporter.report("custom-engine", "retry", details),
|
|
441
|
+
},
|
|
538
442
|
});
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
|
|
550
|
-
break;
|
|
551
|
-
}
|
|
552
|
-
const exhaustedReason = `Custom workflow verification for ${iterData.unitId} requested retry ${attempts} times without passing.`;
|
|
553
|
-
await deps.stopAuto(ctx, pi, recovery.outcome === "stop" && recovery.reason ? recovery.reason : exhaustedReason);
|
|
554
|
-
finishTurn("stopped", "manual-attention", "custom-engine-verify-retry-exhausted");
|
|
443
|
+
const retryFlow = await handleCustomEngineVerifyRetryOutcome({
|
|
444
|
+
outcome: retryOutcome,
|
|
445
|
+
deps: {
|
|
446
|
+
pauseAuto: () => deps.pauseAuto(ctx, pi),
|
|
447
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
448
|
+
reportPause: details => phaseReporter.report("custom-engine", "pause", details),
|
|
449
|
+
finishTurn,
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
if (retryFlow.action === "break")
|
|
555
453
|
break;
|
|
556
|
-
}
|
|
557
|
-
finishTurn("retry");
|
|
558
454
|
continue;
|
|
559
455
|
}
|
|
560
456
|
// Verification passed — mark step complete
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
457
|
+
const reconcileOutcome = await handleCustomEngineReconcile({
|
|
458
|
+
session: s,
|
|
459
|
+
engineState,
|
|
460
|
+
iterData,
|
|
461
|
+
iteration,
|
|
462
|
+
deps: {
|
|
463
|
+
saveRetryCounts: () => saveCustomVerifyRetryCounts(s, {
|
|
464
|
+
logFailure: logCustomVerifyRetrySaveFailure,
|
|
465
|
+
}),
|
|
466
|
+
logReconcile: details => debugLog("autoLoop", {
|
|
467
|
+
phase: "custom-engine-reconcile",
|
|
468
|
+
...details,
|
|
469
|
+
}),
|
|
470
|
+
reconcile: (state, completedStep) => engine.reconcile(state, completedStep),
|
|
471
|
+
now: () => Date.now(),
|
|
472
|
+
clearUnitTimeout: deps.clearUnitTimeout,
|
|
473
|
+
completeIteration,
|
|
474
|
+
},
|
|
569
475
|
});
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
consecutiveCooldowns = 0;
|
|
573
|
-
recentErrorMessages.length = 0;
|
|
574
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
|
|
575
|
-
saveStuckState(s, loopState); // persist across session restarts (#3704)
|
|
576
|
-
debugLog("autoLoop", { phase: "iteration-complete", iteration });
|
|
577
|
-
if (reconcileResult.outcome === "milestone-complete") {
|
|
578
|
-
await deps.stopAuto(ctx, pi, "Workflow complete");
|
|
579
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "milestone-complete", {
|
|
580
|
-
unitType: iterData.unitType,
|
|
581
|
-
unitId: iterData.unitId,
|
|
582
|
-
});
|
|
583
|
-
finishTurn("completed");
|
|
584
|
-
break;
|
|
585
|
-
}
|
|
586
|
-
if (reconcileResult.outcome === "pause") {
|
|
587
|
-
await deps.pauseAuto(ctx, pi);
|
|
588
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "pause", {
|
|
589
|
-
unitType: iterData.unitType,
|
|
590
|
-
unitId: iterData.unitId,
|
|
591
|
-
});
|
|
592
|
-
finishTurn("paused", "manual-attention");
|
|
593
|
-
break;
|
|
594
|
-
}
|
|
595
|
-
if (reconcileResult.outcome === "stop") {
|
|
596
|
-
await deps.stopAuto(ctx, pi, reconcileResult.reason ?? "Engine stopped");
|
|
597
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "stop", {
|
|
598
|
-
unitType: iterData.unitType,
|
|
599
|
-
unitId: iterData.unitId,
|
|
600
|
-
reason: reconcileResult.reason,
|
|
601
|
-
});
|
|
602
|
-
finishTurn("stopped", "manual-attention", reconcileResult.reason);
|
|
603
|
-
break;
|
|
604
|
-
}
|
|
605
|
-
deps.uokObserver?.onPhaseResult("custom-engine", "continue", {
|
|
476
|
+
const reconcileFlow = await handleCustomEngineReconcileOutcome({
|
|
477
|
+
outcome: reconcileOutcome,
|
|
606
478
|
unitType: iterData.unitType,
|
|
607
479
|
unitId: iterData.unitId,
|
|
480
|
+
deps: {
|
|
481
|
+
stopAuto: reason => deps.stopAuto(ctx, pi, reason),
|
|
482
|
+
pauseAuto: () => deps.pauseAuto(ctx, pi),
|
|
483
|
+
report: (action, details) => phaseReporter.report("custom-engine", action, details),
|
|
484
|
+
finishTurn,
|
|
485
|
+
},
|
|
608
486
|
});
|
|
609
|
-
|
|
487
|
+
if (reconcileFlow.action === "break")
|
|
488
|
+
break;
|
|
610
489
|
continue;
|
|
611
490
|
}
|
|
612
491
|
if (!sidecarItem) {
|
|
613
492
|
// ── Phase 1: Pre-dispatch ─────────────────────────────────────────
|
|
614
493
|
const preDispatchResult = await runPreDispatch(ic, loopState);
|
|
615
|
-
|
|
494
|
+
phaseReporter.report("pre-dispatch", preDispatchResult.action);
|
|
616
495
|
if (preDispatchResult.action === "break") {
|
|
617
496
|
finishTurn("stopped", "manual-attention", "pre-dispatch-break");
|
|
618
497
|
break;
|
|
@@ -624,14 +503,14 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
624
503
|
const preData = preDispatchResult.data;
|
|
625
504
|
// ── Phase 2: Guards ───────────────────────────────────────────────
|
|
626
505
|
const guardsResult = await runGuards(ic, preData.mid);
|
|
627
|
-
|
|
506
|
+
phaseReporter.report("guard", guardsResult.action);
|
|
628
507
|
if (guardsResult.action === "break") {
|
|
629
508
|
finishTurn("stopped", "manual-attention", "guard-break");
|
|
630
509
|
break;
|
|
631
510
|
}
|
|
632
511
|
// ── Phase 3: Dispatch ─────────────────────────────────────────────
|
|
633
512
|
const dispatchResult = await runDispatch(ic, preData, loopState);
|
|
634
|
-
|
|
513
|
+
phaseReporter.report("dispatch", dispatchResult.action);
|
|
635
514
|
if (dispatchResult.action === "break") {
|
|
636
515
|
finishTurn("stopped", "manual-attention", "dispatch-break");
|
|
637
516
|
break;
|
|
@@ -645,30 +524,19 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
645
524
|
observedUnitId = iterData.unitId;
|
|
646
525
|
}
|
|
647
526
|
else {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
debugLog("autoLoop", {
|
|
651
|
-
phase: "post-derive",
|
|
652
|
-
site: "sidecar",
|
|
527
|
+
iterData = await buildSidecarIterationData({
|
|
528
|
+
sidecarItem,
|
|
653
529
|
basePath: s.basePath,
|
|
654
530
|
canonicalProjectRoot: s.canonicalProjectRoot,
|
|
655
|
-
|
|
656
|
-
|
|
531
|
+
deriveState: deps.deriveState,
|
|
532
|
+
logPostDerive: details => debugLog("autoLoop", {
|
|
533
|
+
phase: "post-derive",
|
|
534
|
+
...details,
|
|
535
|
+
}),
|
|
657
536
|
});
|
|
658
|
-
iterData = {
|
|
659
|
-
unitType: sidecarItem.unitType,
|
|
660
|
-
unitId: sidecarItem.unitId,
|
|
661
|
-
prompt: sidecarItem.prompt,
|
|
662
|
-
finalPrompt: sidecarItem.prompt,
|
|
663
|
-
pauseAfterUatDispatch: false,
|
|
664
|
-
state: sidecarState,
|
|
665
|
-
mid: sidecarState.activeMilestone?.id,
|
|
666
|
-
midTitle: sidecarState.activeMilestone?.title,
|
|
667
|
-
isRetry: false, previousTier: undefined,
|
|
668
|
-
};
|
|
669
537
|
observedUnitType = iterData.unitType;
|
|
670
538
|
observedUnitId = iterData.unitId;
|
|
671
|
-
|
|
539
|
+
phaseReporter.report("dispatch", "sidecar", {
|
|
672
540
|
unitType: iterData.unitType,
|
|
673
541
|
unitId: iterData.unitId,
|
|
674
542
|
sidecarKind: sidecarItem.kind,
|
|
@@ -681,52 +549,51 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
681
549
|
// null when DB unavailable, no worker registered, or no active lease
|
|
682
550
|
// — those degraded paths fall through to the existing single-worker
|
|
683
551
|
// semantics with no ledger entry, preserving back-compat.
|
|
684
|
-
const dispatchClaim = openDispatchClaim(s, flowId, turnId, iterData
|
|
685
|
-
|
|
686
|
-
|
|
552
|
+
const dispatchClaim = openDispatchClaim(s, flowId, turnId, iterData, {
|
|
553
|
+
getRecentDispatchesForUnit,
|
|
554
|
+
recordDispatchClaim,
|
|
555
|
+
markDispatchRunning,
|
|
556
|
+
logClaimRejected: logDispatchClaimRejected,
|
|
557
|
+
logClaimFailed: logDispatchClaimFailed,
|
|
558
|
+
});
|
|
559
|
+
const dispatchDecision = decideDispatchClaim(dispatchClaim.kind === "opened"
|
|
560
|
+
? { kind: "opened", dispatchId: dispatchClaim.dispatchId }
|
|
561
|
+
: dispatchClaim.kind === "skip"
|
|
562
|
+
? { kind: "skip", reason: dispatchClaim.reason }
|
|
563
|
+
: { kind: "degraded" });
|
|
564
|
+
if (dispatchDecision.action === "skip") {
|
|
565
|
+
finishTurn("skipped", "execution", dispatchDecision.reason);
|
|
687
566
|
continue;
|
|
688
567
|
}
|
|
689
|
-
dispatchId =
|
|
568
|
+
dispatchId = dispatchDecision.dispatchId;
|
|
690
569
|
let unitPhaseResult;
|
|
691
570
|
try {
|
|
692
|
-
unitPhaseResult = await runUnitPhaseViaContract(dispatchContract, ic, iterData, loopState, sidecarItem);
|
|
571
|
+
unitPhaseResult = await runUnitPhaseViaContract(dispatchContract, ic, iterData, loopState, sidecarItem, unitDispatchDeps);
|
|
693
572
|
}
|
|
694
573
|
catch (err) {
|
|
695
574
|
if (err instanceof ModelPolicyDispatchBlockedError) {
|
|
696
575
|
throw err;
|
|
697
576
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
});
|
|
703
|
-
dispatchSettled = true;
|
|
704
|
-
}
|
|
705
|
-
catch (ledgerErr) {
|
|
706
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: ledgerErr instanceof Error ? ledgerErr.message : String(ledgerErr) });
|
|
707
|
-
}
|
|
708
|
-
}
|
|
577
|
+
dispatchSettled = settleDispatchFailed(dispatchId, formatDispatchExceptionSummary({ error: err }), {
|
|
578
|
+
markFailed: markDispatchFailed,
|
|
579
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
580
|
+
}) || dispatchSettled;
|
|
709
581
|
throw err;
|
|
710
582
|
}
|
|
711
583
|
if (unitPhaseResult.action === "next") {
|
|
712
|
-
const requestTimestamp = unitPhaseResult.data
|
|
713
|
-
if (
|
|
584
|
+
const requestTimestamp = resolveUnitRequestTimestamp(unitPhaseResult.data);
|
|
585
|
+
if (requestTimestamp !== undefined)
|
|
714
586
|
s.lastRequestTimestamp = requestTimestamp;
|
|
715
587
|
}
|
|
716
|
-
|
|
588
|
+
phaseReporter.report("unit", unitPhaseResult.action, {
|
|
717
589
|
unitType: iterData.unitType,
|
|
718
590
|
unitId: iterData.unitId,
|
|
719
591
|
});
|
|
720
592
|
if (unitPhaseResult.action === "break") {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
}
|
|
726
|
-
catch (err) {
|
|
727
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
|
|
728
|
-
}
|
|
729
|
-
}
|
|
593
|
+
dispatchSettled = settleDispatchFailed(dispatchId, "unit-break", {
|
|
594
|
+
markFailed: markDispatchFailed,
|
|
595
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
596
|
+
}) || dispatchSettled;
|
|
730
597
|
finishTurn("stopped", "execution", "unit-break");
|
|
731
598
|
break;
|
|
732
599
|
}
|
|
@@ -736,88 +603,57 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
736
603
|
finalizeResult = await runFinalize(ic, iterData, loopState, sidecarItem);
|
|
737
604
|
}
|
|
738
605
|
catch (err) {
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
});
|
|
744
|
-
dispatchSettled = true;
|
|
745
|
-
}
|
|
746
|
-
catch (ledgerErr) {
|
|
747
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: ledgerErr instanceof Error ? ledgerErr.message : String(ledgerErr) });
|
|
748
|
-
}
|
|
749
|
-
}
|
|
606
|
+
dispatchSettled = settleDispatchFailed(dispatchId, formatDispatchExceptionSummary({ error: err }), {
|
|
607
|
+
markFailed: markDispatchFailed,
|
|
608
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
609
|
+
}) || dispatchSettled;
|
|
750
610
|
throw err;
|
|
751
611
|
}
|
|
752
|
-
|
|
612
|
+
phaseReporter.report("finalize", finalizeResult.action, {
|
|
753
613
|
unitType: iterData.unitType,
|
|
754
614
|
unitId: iterData.unitId,
|
|
755
615
|
});
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
: "
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
finishTurn("stopped", finalizeFailureClass, "finalize-break");
|
|
616
|
+
const finalizeDecision = decideFinalizeResult(finalizeResult.action === "break"
|
|
617
|
+
? { action: "break", reason: finalizeResult.reason }
|
|
618
|
+
: finalizeResult.action === "continue"
|
|
619
|
+
? { action: "continue" }
|
|
620
|
+
: { action: "next" });
|
|
621
|
+
if (finalizeDecision.action === "stop") {
|
|
622
|
+
dispatchSettled = settleDispatchFailed(dispatchId, finalizeDecision.ledgerErrorSummary, {
|
|
623
|
+
markFailed: markDispatchFailed,
|
|
624
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
625
|
+
}) || dispatchSettled;
|
|
626
|
+
finishTurn("stopped", finalizeDecision.failureClass, finalizeDecision.turnError);
|
|
770
627
|
break;
|
|
771
628
|
}
|
|
772
|
-
if (
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
778
|
-
catch (err) {
|
|
779
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
|
|
780
|
-
}
|
|
781
|
-
}
|
|
629
|
+
if (finalizeDecision.action === "retry") {
|
|
630
|
+
dispatchSettled = settleDispatchFailed(dispatchId, finalizeDecision.ledgerErrorSummary, {
|
|
631
|
+
markFailed: markDispatchFailed,
|
|
632
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
633
|
+
}) || dispatchSettled;
|
|
782
634
|
finishTurn("retry");
|
|
783
635
|
continue;
|
|
784
636
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
catch (err) {
|
|
791
|
-
debugLog("autoLoop", { phase: "dispatch-ledger-write-failed", error: err instanceof Error ? err.message : String(err) });
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
consecutiveErrors = 0; // Iteration completed successfully
|
|
795
|
-
consecutiveCooldowns = 0;
|
|
796
|
-
recentErrorMessages.length = 0;
|
|
797
|
-
deps.emitJournalEvent({ ts: new Date().toISOString(), flowId, seq: nextSeq(), eventType: "iteration-end", data: { iteration } });
|
|
798
|
-
saveStuckState(s, loopState); // persist across session restarts (#4382)
|
|
799
|
-
debugLog("autoLoop", { phase: "iteration-complete", iteration });
|
|
637
|
+
dispatchSettled = settleDispatchCompleted(dispatchId, {
|
|
638
|
+
markCompleted: markDispatchCompleted,
|
|
639
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
640
|
+
}) || dispatchSettled;
|
|
641
|
+
completeIteration();
|
|
800
642
|
finishTurn("completed");
|
|
801
643
|
}
|
|
802
644
|
catch (loopErr) {
|
|
803
645
|
// ── Blanket catch: absorb unexpected exceptions, apply graduated recovery ──
|
|
804
646
|
const msg = loopErr instanceof Error ? loopErr.message : String(loopErr);
|
|
805
647
|
if (dispatchId !== null && !dispatchSettled && !(loopErr instanceof ModelPolicyDispatchBlockedError)) {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
}
|
|
810
|
-
catch (err) {
|
|
811
|
-
debugLog("autoLoop", {
|
|
812
|
-
phase: "dispatch-ledger-write-failed",
|
|
813
|
-
error: err instanceof Error ? err.message : String(err),
|
|
814
|
-
});
|
|
815
|
-
}
|
|
648
|
+
dispatchSettled = settleDispatchFailed(dispatchId, formatUnhandledDispatchErrorSummary({ error: loopErr }), {
|
|
649
|
+
markFailed: markDispatchFailed,
|
|
650
|
+
logWriteFailure: logDispatchLedgerWriteFailure,
|
|
651
|
+
}) || dispatchSettled;
|
|
816
652
|
}
|
|
817
653
|
// Always emit iteration-end on error so the journal records iteration
|
|
818
654
|
// completion even on failure (#2344). Without this, errors in
|
|
819
655
|
// runFinalize leave the journal incomplete, making diagnosis harder.
|
|
820
|
-
|
|
656
|
+
journalReporter.emit("iteration-end", { iteration, error: msg });
|
|
821
657
|
// ── Pre-send model-policy block: not a retryable error (#4959 / #4850) ──
|
|
822
658
|
// The model-policy gate runs before the prompt is sent. When every
|
|
823
659
|
// candidate model is denied (cross-provider disabled + flat-rate
|
|
@@ -827,6 +663,12 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
827
663
|
// instead, with the per-model deny reasons surfaced from the typed
|
|
828
664
|
// error.
|
|
829
665
|
if (loopErr instanceof ModelPolicyDispatchBlockedError) {
|
|
666
|
+
const policyDecision = decideModelPolicyBlocked({
|
|
667
|
+
unitType: loopErr.unitType,
|
|
668
|
+
unitId: loopErr.unitId,
|
|
669
|
+
errorMessage: msg,
|
|
670
|
+
reasons: loopErr.reasons,
|
|
671
|
+
});
|
|
830
672
|
debugLog("autoLoop", {
|
|
831
673
|
phase: "model-policy-blocked",
|
|
832
674
|
iteration,
|
|
@@ -834,20 +676,8 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
834
676
|
unitId: loopErr.unitId,
|
|
835
677
|
reasons: loopErr.reasons,
|
|
836
678
|
});
|
|
837
|
-
ctx.ui.notify(
|
|
838
|
-
|
|
839
|
-
ts: new Date().toISOString(),
|
|
840
|
-
flowId,
|
|
841
|
-
seq: nextSeq(),
|
|
842
|
-
eventType: "unit-end",
|
|
843
|
-
data: {
|
|
844
|
-
unitType: loopErr.unitType,
|
|
845
|
-
unitId: loopErr.unitId,
|
|
846
|
-
status: "blocked",
|
|
847
|
-
reason: "model-policy-dispatch-blocked",
|
|
848
|
-
reasons: loopErr.reasons,
|
|
849
|
-
},
|
|
850
|
-
});
|
|
679
|
+
ctx.ui.notify(policyDecision.notifyMessage, "error");
|
|
680
|
+
journalReporter.emit("unit-end", policyDecision.journalData);
|
|
851
681
|
// Carry the blocked unit identity into the turn-result observer:
|
|
852
682
|
// the throw originated inside dispatch, so observedUnitType/Id were
|
|
853
683
|
// not assigned by the success path at lines 453/631/647 — but the
|
|
@@ -855,7 +685,7 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
855
685
|
observedUnitType = loopErr.unitType;
|
|
856
686
|
observedUnitId = loopErr.unitId;
|
|
857
687
|
await deps.pauseAuto(ctx, pi);
|
|
858
|
-
finishTurn(
|
|
688
|
+
finishTurn(policyDecision.turnStatus, policyDecision.failureClass, msg);
|
|
859
689
|
// Do NOT increment consecutiveErrors — the failure is configuration,
|
|
860
690
|
// not a transient runtime fault.
|
|
861
691
|
break;
|
|
@@ -865,15 +695,19 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
865
695
|
// LLM budget on guaranteed failures.
|
|
866
696
|
const infraCode = isInfrastructureError(loopErr);
|
|
867
697
|
if (infraCode) {
|
|
698
|
+
const infraDecision = decideInfrastructureError({
|
|
699
|
+
code: infraCode,
|
|
700
|
+
errorMessage: msg,
|
|
701
|
+
});
|
|
868
702
|
debugLog("autoLoop", {
|
|
869
703
|
phase: "infrastructure-error",
|
|
870
704
|
iteration,
|
|
871
705
|
code: infraCode,
|
|
872
706
|
error: msg,
|
|
873
707
|
});
|
|
874
|
-
ctx.ui.notify(
|
|
875
|
-
await deps.stopAuto(ctx, pi,
|
|
876
|
-
finishTurn(
|
|
708
|
+
ctx.ui.notify(infraDecision.notifyMessage, "error");
|
|
709
|
+
await deps.stopAuto(ctx, pi, infraDecision.stopMessage);
|
|
710
|
+
finishTurn(infraDecision.turnStatus, infraDecision.failureClass, msg);
|
|
877
711
|
break;
|
|
878
712
|
}
|
|
879
713
|
// ── Credential cooldown: wait and retry with bounded budget ──
|
|
@@ -885,6 +719,12 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
885
719
|
if (isTransientCooldownError(loopErr)) {
|
|
886
720
|
consecutiveCooldowns++;
|
|
887
721
|
const retryAfterMs = getCooldownRetryAfterMs(loopErr);
|
|
722
|
+
const cooldownDecision = decideCooldownRecovery({
|
|
723
|
+
consecutiveCooldowns,
|
|
724
|
+
maxCooldownRetries: MAX_COOLDOWN_RETRIES,
|
|
725
|
+
retryAfterMs,
|
|
726
|
+
fallbackWaitMs: COOLDOWN_FALLBACK_WAIT_MS,
|
|
727
|
+
});
|
|
888
728
|
debugLog("autoLoop", {
|
|
889
729
|
phase: "cooldown-wait",
|
|
890
730
|
iteration,
|
|
@@ -892,16 +732,13 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
892
732
|
retryAfterMs,
|
|
893
733
|
error: msg,
|
|
894
734
|
});
|
|
895
|
-
if (
|
|
896
|
-
ctx.ui.notify(
|
|
897
|
-
await deps.stopAuto(ctx, pi,
|
|
735
|
+
if (cooldownDecision.action === "stop") {
|
|
736
|
+
ctx.ui.notify(cooldownDecision.notifyMessage, "error");
|
|
737
|
+
await deps.stopAuto(ctx, pi, cooldownDecision.stopMessage);
|
|
898
738
|
break;
|
|
899
739
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
: COOLDOWN_FALLBACK_WAIT_MS;
|
|
903
|
-
ctx.ui.notify(`Credentials in cooldown (${consecutiveCooldowns}/${MAX_COOLDOWN_RETRIES}) — waiting ${Math.round(waitMs / 1000)}s before retrying.`, "warning");
|
|
904
|
-
await new Promise(resolve => setTimeout(resolve, waitMs));
|
|
740
|
+
ctx.ui.notify(cooldownDecision.notifyMessage, "warning");
|
|
741
|
+
await new Promise(resolve => setTimeout(resolve, cooldownDecision.waitMs));
|
|
905
742
|
finishTurn("retry", "timeout", msg);
|
|
906
743
|
continue; // Retry iteration without incrementing consecutiveErrors
|
|
907
744
|
}
|
|
@@ -913,26 +750,25 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
913
750
|
consecutiveErrors,
|
|
914
751
|
error: msg,
|
|
915
752
|
});
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
753
|
+
const errorDecision = decideIterationErrorRecovery({
|
|
754
|
+
consecutiveErrors,
|
|
755
|
+
recentErrorMessages,
|
|
756
|
+
currentErrorMessage: msg,
|
|
757
|
+
});
|
|
758
|
+
if (errorDecision.action === "stop") {
|
|
759
|
+
ctx.ui.notify(errorDecision.notifyMessage, "error");
|
|
760
|
+
await deps.stopAuto(ctx, pi, errorDecision.stopMessage);
|
|
761
|
+
finishTurn(errorDecision.turnStatus, "execution", msg);
|
|
924
762
|
break;
|
|
925
763
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
ctx.ui.notify(`Iteration error (attempt ${consecutiveErrors}): ${msg}. Invalidating caches and retrying.`, "warning");
|
|
764
|
+
if (errorDecision.action === "invalidate-and-retry") {
|
|
765
|
+
ctx.ui.notify(errorDecision.notifyMessage, "warning");
|
|
929
766
|
deps.invalidateAllCaches();
|
|
930
767
|
}
|
|
931
768
|
else {
|
|
932
|
-
|
|
933
|
-
ctx.ui.notify(`Iteration error: ${msg}. Retrying.`, "warning");
|
|
769
|
+
ctx.ui.notify(errorDecision.notifyMessage, "warning");
|
|
934
770
|
}
|
|
935
|
-
finishTurn(
|
|
771
|
+
finishTurn(errorDecision.turnStatus, "execution", msg);
|
|
936
772
|
}
|
|
937
773
|
}
|
|
938
774
|
_clearCurrentResolve();
|