pi-crew 0.9.56 → 0.9.57

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.
Files changed (307) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +29 -0
  3. package/README.md +53 -5
  4. package/dist/index.mjs +5350 -4350
  5. package/docs/README.md +54 -0
  6. package/package.json +12 -12
  7. package/skills/real-test-pi-crew/SKILL.md +93 -3
  8. package/src/agents/discover-agents.ts +68 -10
  9. package/src/benchmark/feedback-loop.ts +1 -1
  10. package/src/config/config.ts +2 -1
  11. package/src/config/types.ts +12 -0
  12. package/src/extension/action-suggestions.ts +16 -63
  13. package/src/extension/async-notifier.ts +3 -3
  14. package/src/extension/command-completions.ts +2 -2
  15. package/src/extension/crew-cleanup.ts +3 -3
  16. package/src/extension/crew-vibes/footer.ts +4 -2
  17. package/src/extension/cross-extension-rpc.ts +10 -5
  18. package/src/extension/knowledge-injection.ts +57 -10
  19. package/src/extension/register.ts +2 -2
  20. package/src/extension/registration/artifact-cleanup.ts +41 -3
  21. package/src/extension/registration/commands.ts +4 -4
  22. package/src/extension/registration/context-builder.ts +10 -10
  23. package/src/extension/registration/crash-recovery-cache.ts +3 -3
  24. package/src/extension/registration/foreground-run-controller.ts +1 -1
  25. package/src/extension/registration/lazy-configurers.ts +2 -2
  26. package/src/extension/registration/lifecycle-handlers.ts +12 -12
  27. package/src/extension/registration/lifecycle.ts +2 -2
  28. package/src/extension/registration/observability.ts +2 -2
  29. package/src/extension/registration/registration-types.ts +3 -3
  30. package/src/extension/registration/runtime-cleanup.ts +1 -1
  31. package/src/extension/registration/subagent-helpers.ts +2 -2
  32. package/src/extension/registration/subagent-manager-setup.ts +2 -2
  33. package/src/extension/registration/subagent-tools.ts +21 -16
  34. package/src/extension/registration/team-tool.ts +108 -17
  35. package/src/extension/registration/viewers.ts +3 -4
  36. package/src/extension/registration/wire-cross-extension.ts +7 -7
  37. package/src/extension/rpc-hmac.ts +3 -2
  38. package/src/extension/run-bundle-schema.ts +13 -4
  39. package/src/extension/run-export.ts +2 -2
  40. package/src/extension/run-index.ts +2 -3
  41. package/src/extension/run-maintenance.ts +57 -1
  42. package/src/extension/team-manager-command.ts +3 -1
  43. package/src/extension/team-tool/anchor.ts +8 -2
  44. package/src/extension/team-tool/api.ts +117 -39
  45. package/src/extension/team-tool/cancel.ts +23 -8
  46. package/src/extension/team-tool/chain-executor.ts +1 -1
  47. package/src/extension/team-tool/dispatch/automate.ts +17 -2
  48. package/src/extension/team-tool/dispatch/control.ts +17 -2
  49. package/src/extension/team-tool/dispatch/manage.ts +34 -2
  50. package/src/extension/team-tool/dispatch/run.ts +17 -2
  51. package/src/extension/team-tool/dispatch/status.ts +37 -5
  52. package/src/extension/team-tool/doctor.ts +2 -2
  53. package/src/extension/team-tool/explain.ts +1 -1
  54. package/src/extension/team-tool/goal-wrap.ts +5 -5
  55. package/src/extension/team-tool/goal.ts +30 -9
  56. package/src/extension/team-tool/handle-schedule.ts +37 -19
  57. package/src/extension/team-tool/inspect.ts +21 -5
  58. package/src/extension/team-tool/lifecycle-actions.ts +53 -10
  59. package/src/extension/team-tool/parallel-dispatch.ts +14 -5
  60. package/src/extension/team-tool/param-error.ts +24 -0
  61. package/src/extension/team-tool/respond.ts +20 -6
  62. package/src/extension/team-tool/run.ts +27 -17
  63. package/src/extension/team-tool/status.ts +11 -5
  64. package/src/extension/team-tool.ts +26 -19
  65. package/src/hooks/registry.ts +1 -1
  66. package/src/i18n.ts +22 -0
  67. package/src/observability/event-bus.ts +1 -1
  68. package/src/prompt/prompt-runtime.ts +2 -2
  69. package/src/runtime/README.md +35 -0
  70. package/src/runtime/agent-control.ts +1 -1
  71. package/src/runtime/anchor-manager.ts +0 -2
  72. package/src/runtime/async-runner.ts +1 -1
  73. package/src/runtime/attention-events.ts +1 -1
  74. package/src/runtime/auto-summarize.ts +0 -2
  75. package/src/runtime/background-runner.ts +103 -30
  76. package/src/runtime/{crew-broker-child.ts → broker/crew-broker-child.ts} +2 -2
  77. package/src/runtime/{crew-broker-client.ts → broker/crew-broker-client.ts} +4 -7
  78. package/src/runtime/{crew-broker.ts → broker/crew-broker.ts} +13 -21
  79. package/src/runtime/chain-runner.ts +50 -5
  80. package/src/runtime/{child-pi-constants.ts → child-pi/child-pi-constants.ts} +1 -1
  81. package/src/runtime/{child-pi-kill.ts → child-pi/child-pi-kill.ts} +3 -3
  82. package/src/runtime/{child-pi-spawn.ts → child-pi/child-pi-spawn.ts} +28 -12
  83. package/src/runtime/{child-pi-steering.ts → child-pi/child-pi-steering.ts} +1 -1
  84. package/src/runtime/{child-pi-streams.ts → child-pi/child-pi-streams.ts} +11 -4
  85. package/src/runtime/{child-pi-transcript.ts → child-pi/child-pi-transcript.ts} +6 -6
  86. package/src/runtime/{child-pi.ts → child-pi/child-pi.ts} +28 -72
  87. package/src/runtime/{compact-stages → compaction/compact-stages}/bounded-tail.ts +1 -1
  88. package/src/runtime/{compact-stages → compaction/compact-stages}/index.ts +2 -2
  89. package/src/runtime/{compaction-summary.ts → compaction/compaction-summary.ts} +3 -3
  90. package/src/runtime/{tool-output-pruner.ts → compaction/tool-output-pruner.ts} +1 -1
  91. package/src/runtime/custom-tools/irc-tool.ts +2 -2
  92. package/src/runtime/delivery-coordinator.ts +0 -3
  93. package/src/runtime/diagnostic-export.ts +3 -3
  94. package/src/runtime/foreground-control.ts +1 -1
  95. package/src/runtime/foreground-watchdog.ts +1 -1
  96. package/src/runtime/{adaptive-plan.ts → goal-workflow/adaptive-plan.ts} +8 -8
  97. package/src/runtime/{dynamic-workflow-context.ts → goal-workflow/dynamic-workflow-context.ts} +16 -16
  98. package/src/runtime/{dynamic-workflow-runner.ts → goal-workflow/dynamic-workflow-runner.ts} +10 -10
  99. package/src/runtime/{goal-achievement.ts → goal-workflow/goal-achievement.ts} +3 -3
  100. package/src/runtime/{goal-evaluator.ts → goal-workflow/goal-evaluator.ts} +8 -8
  101. package/src/runtime/{goal-loop-runner.ts → goal-workflow/goal-loop-runner.ts} +27 -25
  102. package/src/runtime/{goal-state-store.ts → goal-workflow/goal-state-store.ts} +8 -8
  103. package/src/runtime/{plan-templates.ts → goal-workflow/plan-templates.ts} +1 -1
  104. package/src/runtime/group-join.ts +3 -3
  105. package/src/runtime/handoff-manager.ts +0 -2
  106. package/src/runtime/{heartbeat-watcher.ts → heartbeat/heartbeat-watcher.ts} +7 -7
  107. package/src/runtime/iteration-hooks.ts +1 -1
  108. package/src/runtime/{live-agent-control.ts → live-session/live-agent-control.ts} +2 -2
  109. package/src/runtime/{live-agent-manager.ts → live-session/live-agent-manager.ts} +4 -4
  110. package/src/runtime/{live-session-runtime.ts → live-session/live-session-runtime.ts} +39 -41
  111. package/src/runtime/manifest-cache.ts +1 -1
  112. package/src/runtime/{model-fallback.ts → model/model-fallback.ts} +1 -1
  113. package/src/runtime/{pi-args.ts → model/pi-args.ts} +20 -5
  114. package/src/runtime/model/provider-extensions.ts +116 -0
  115. package/src/runtime/{runtime-policy.ts → model/runtime-policy.ts} +2 -2
  116. package/src/runtime/{runtime-resolver.ts → model/runtime-resolver.ts} +3 -3
  117. package/src/runtime/{runtime-warmup.ts → model/runtime-warmup.ts} +8 -8
  118. package/src/runtime/orphan-worker-registry.ts +1 -1
  119. package/src/runtime/{progress-tracker.ts → output/progress-tracker.ts} +1 -1
  120. package/src/runtime/{result-extractor.ts → output/result-extractor.ts} +4 -4
  121. package/src/runtime/{sidechain-output.ts → output/sidechain-output.ts} +2 -2
  122. package/src/runtime/{stream-preview.ts → output/stream-preview.ts} +1 -1
  123. package/src/runtime/{streaming-output.ts → output/streaming-output.ts} +2 -2
  124. package/src/runtime/{tool-progress.ts → output/tool-progress.ts} +1 -1
  125. package/src/runtime/parent-guard.ts +30 -10
  126. package/src/runtime/pipeline-runner.ts +2 -2
  127. package/src/runtime/policy-engine.ts +2 -2
  128. package/src/runtime/{cancellation.ts → process/cancellation.ts} +1 -1
  129. package/src/runtime/{post-exit-stdio-guard.ts → process/post-exit-stdio-guard.ts} +1 -1
  130. package/src/runtime/{process-lifecycle.ts → process/process-lifecycle.ts} +3 -3
  131. package/src/runtime/{checkpoint.ts → recovery/checkpoint.ts} +4 -4
  132. package/src/runtime/{crash-recovery.ts → recovery/crash-recovery.ts} +93 -21
  133. package/src/runtime/{overflow-recovery.ts → recovery/overflow-recovery.ts} +1 -1
  134. package/src/runtime/{recovery-recipes.ts → recovery/recovery-recipes.ts} +1 -1
  135. package/src/runtime/{retry-executor.ts → recovery/retry-executor.ts} +2 -2
  136. package/src/runtime/{retry-runner.ts → recovery/retry-runner.ts} +2 -8
  137. package/src/runtime/run-tracker.ts +1 -1
  138. package/src/runtime/run-worker.ts +3 -3
  139. package/src/runtime/{coalesce-tasks.ts → scheduling/coalesce-tasks.ts} +3 -3
  140. package/src/runtime/{concurrency.ts → scheduling/concurrency.ts} +1 -1
  141. package/src/runtime/{parallel-research.ts → scheduling/parallel-research.ts} +4 -2
  142. package/src/runtime/{run-coalesced-task-group.ts → scheduling/run-coalesced-task-group.ts} +95 -36
  143. package/src/runtime/{task-graph-scheduler.ts → scheduling/task-graph-scheduler.ts} +1 -1
  144. package/src/runtime/session-resources.ts +1 -1
  145. package/src/runtime/settings-store.ts +1 -1
  146. package/src/runtime/single-agent-compose.ts +1 -0
  147. package/src/runtime/stale-reconciler.ts +1 -1
  148. package/src/runtime/subagent-manager.ts +1 -1
  149. package/src/runtime/supervisor-contact.ts +1 -1
  150. package/src/runtime/task-output-context.ts +7 -5
  151. package/src/runtime/task-runner/child-executor.ts +62 -22
  152. package/src/runtime/task-runner/live-executor.ts +8 -8
  153. package/src/runtime/task-runner/post-execution.ts +12 -12
  154. package/src/runtime/task-runner/pre-execution.ts +6 -6
  155. package/src/runtime/task-runner/progress.ts +1 -1
  156. package/src/runtime/task-runner/run-projection.ts +1 -1
  157. package/src/runtime/task-runner/scaffold-executor.ts +1 -1
  158. package/src/runtime/task-runner/state-helpers.ts +2 -2
  159. package/src/runtime/task-runner.ts +4 -4
  160. package/src/runtime/team-runner.ts +380 -139
  161. package/src/runtime/{completion-guard.ts → verification/completion-guard.ts} +1 -1
  162. package/src/runtime/{green-contract.ts → verification/green-contract.ts} +1 -1
  163. package/src/runtime/{post-checks.ts → verification/post-checks.ts} +4 -4
  164. package/src/runtime/{verification-gates.ts → verification/verification-gates.ts} +5 -5
  165. package/src/runtime/{verification-integrity.ts → verification/verification-integrity.ts} +1 -1
  166. package/src/schema/config-schema.ts +1 -0
  167. package/src/schema/team-tool-schema.ts +133 -177
  168. package/src/state/README.md +44 -0
  169. package/src/state/atomic-write.ts +24 -3
  170. package/src/state/{locks.ts → coordination/locks.ts} +118 -38
  171. package/src/state/{mailbox.ts → coordination/mailbox.ts} +14 -8
  172. package/src/state/{schedule.ts → coordination/schedule.ts} +3 -3
  173. package/src/state/{task-claims.ts → coordination/task-claims.ts} +1 -1
  174. package/src/state/decision-ledger.ts +1 -1
  175. package/src/state/{event-log-rotation.ts → event-log/event-log-rotation.ts} +161 -31
  176. package/src/state/{event-log.ts → event-log/event-log.ts} +38 -26
  177. package/src/state/{jsonl-writer.ts → event-log/jsonl-writer.ts} +14 -6
  178. package/src/state/hook-instinct-bridge.ts +2 -2
  179. package/src/state/{active-run-registry.ts → stores/active-run-registry.ts} +7 -7
  180. package/src/state/{artifact-store.ts → stores/artifact-store.ts} +62 -4
  181. package/src/state/{blob-store.ts → stores/blob-store.ts} +3 -3
  182. package/src/state/{health-store.ts → stores/health-store.ts} +3 -3
  183. package/src/state/{instinct-store.ts → stores/instinct-store.ts} +3 -3
  184. package/src/state/{observation-store.ts → stores/observation-store.ts} +2 -2
  185. package/src/state/{run-cache.ts → stores/run-cache.ts} +4 -4
  186. package/src/state/{run-graph.ts → stores/run-graph.ts} +4 -4
  187. package/src/state/{run-metrics.ts → stores/run-metrics.ts} +3 -3
  188. package/src/state/{state-store.ts → stores/state-store.ts} +236 -17
  189. package/src/state/types.ts +27 -3
  190. package/src/ui/component.ts +55 -0
  191. package/src/ui/crew-select-list.ts +3 -1
  192. package/src/ui/dashboard-panes/agents-pane.ts +1 -1
  193. package/src/ui/dwf-phase-display.ts +1 -1
  194. package/src/ui/heartbeat-aggregator.ts +1 -1
  195. package/src/ui/keybinding-map.ts +179 -6
  196. package/src/ui/layout-primitives.ts +9 -5
  197. package/src/ui/live-conversation-overlay.ts +1 -1
  198. package/src/ui/live-run-sidebar.ts +1 -1
  199. package/src/ui/overlay-stack.ts +148 -0
  200. package/src/ui/overlays/agent-picker-overlay.ts +1 -1
  201. package/src/ui/overlays/mailbox-compose-overlay.ts +1 -1
  202. package/src/ui/overlays/mailbox-detail-overlay.ts +2 -2
  203. package/src/ui/powerbar-publisher.ts +1 -1
  204. package/src/ui/render-scheduler.ts +1 -1
  205. package/src/ui/run-action-dispatcher.ts +3 -3
  206. package/src/ui/run-dashboard.ts +5 -33
  207. package/src/ui/run-event-bus.ts +3 -3
  208. package/src/ui/run-snapshot-cache.ts +37 -18
  209. package/src/ui/settings-overlay.ts +13 -21
  210. package/src/ui/snapshot-types.ts +1 -1
  211. package/src/ui/status-colors.ts +0 -2
  212. package/src/ui/terminal-status.ts +1 -1
  213. package/src/ui/theme-adapter.ts +33 -13
  214. package/src/ui/tool-renderers/index.ts +8 -0
  215. package/src/ui/transcript-viewer.ts +37 -13
  216. package/src/ui/widget/index.ts +32 -9
  217. package/src/ui/widget/widget-formatters.ts +62 -4
  218. package/src/ui/widget/widget-model.ts +2 -2
  219. package/src/ui/widget/widget-renderer.ts +1 -1
  220. package/src/utils/conflict-detect.ts +58 -5
  221. package/src/utils/ndjson.ts +2 -2
  222. package/src/utils/socket-path.ts +1 -1
  223. package/src/workflows/workflow-config.ts +1 -1
  224. package/src/worktree/cleanup.ts +1 -1
  225. package/src/worktree/worktree-manager.ts +88 -39
  226. package/workflows/chain.workflow.md +2 -2
  227. package/index.bundle.ts +0 -25
  228. package/scripts/bench-check.mjs +0 -96
  229. package/scripts/bench-cold-start.mjs +0 -216
  230. package/scripts/build-bundle.mjs +0 -92
  231. package/scripts/check-all-skills.ts +0 -294
  232. package/scripts/check-bundle-size.mjs +0 -38
  233. package/scripts/check-bundle-staleness.mjs +0 -97
  234. package/scripts/check-conflict-markers.mjs +0 -91
  235. package/scripts/check-lazy-imports.mjs +0 -28
  236. package/scripts/dev-runner.mjs +0 -106
  237. package/scripts/profile-startup.mjs +0 -125
  238. package/scripts/release-smoke.mjs +0 -74
  239. package/scripts/run-bench.mjs +0 -47
  240. package/scripts/run-real-chain.ts +0 -41
  241. package/scripts/smoke-team-perf.ts +0 -43
  242. package/scripts/test-issue-29-crash.ts +0 -111
  243. package/scripts/test-issue-29-e2e.ts +0 -183
  244. package/scripts/test-issue-29-real-runtime.ts +0 -330
  245. package/scripts/test-issue-29-real-tasks.ts +0 -387
  246. package/scripts/test-issue-29-team-tool.ts +0 -105
  247. package/scripts/test-runner.mjs +0 -84
  248. package/scripts/verify-flicker-fix.ts +0 -109
  249. package/scripts/verify-skill.ts +0 -550
  250. package/scripts/watch-bundle.mjs +0 -259
  251. package/scripts/watchdog-harness.ts +0 -119
  252. package/src/adapters/claude-adapter.ts +0 -23
  253. package/src/adapters/codex-adapter.ts +0 -21
  254. package/src/adapters/cursor-adapter.ts +0 -17
  255. package/src/adapters/export-util.ts +0 -143
  256. package/src/adapters/index.ts +0 -15
  257. package/src/adapters/registry.ts +0 -18
  258. package/src/adapters/types.ts +0 -23
  259. package/src/runtime/code-summary.ts +0 -292
  260. package/src/runtime/cross-extension-rpc.ts +0 -143
  261. package/src/runtime/hidden-handoff.ts +0 -407
  262. package/src/runtime/prose-compressor.ts +0 -162
  263. package/src/subagents/async-entry.ts +0 -1
  264. package/src/subagents/index.ts +0 -3
  265. package/src/subagents/live/control.ts +0 -1
  266. package/src/subagents/live/manager.ts +0 -1
  267. package/src/subagents/live/realtime.ts +0 -1
  268. package/src/subagents/live/session-runtime.ts +0 -1
  269. package/src/subagents/manager.ts +0 -1
  270. package/src/subagents/spawn.ts +0 -1
  271. package/test-integration-check.ts +0 -118
  272. /package/src/runtime/{broker-issuer.ts → broker/broker-issuer.ts} +0 -0
  273. /package/src/runtime/{crew-broker-tokens.ts → broker/crew-broker-tokens.ts} +0 -0
  274. /package/src/runtime/{child-pi-pool.ts → child-pi/child-pi-pool.ts} +0 -0
  275. /package/src/runtime/{compact-pipeline.ts → compaction/compact-pipeline.ts} +0 -0
  276. /package/src/runtime/{compact-stages → compaction/compact-stages}/ansi-strip-stage.ts +0 -0
  277. /package/src/runtime/{compact-stages → compaction/compact-stages}/blank-collapse-stage.ts +0 -0
  278. /package/src/runtime/{compact-stages → compaction/compact-stages}/deduplicate-stage.ts +0 -0
  279. /package/src/runtime/{compact-stages → compaction/compact-stages}/head-snap-stage.ts +0 -0
  280. /package/src/runtime/{compact-stages → compaction/compact-stages}/tail-capture-stage.ts +0 -0
  281. /package/src/runtime/{compact-stages → compaction/compact-stages}/truncation-stage.ts +0 -0
  282. /package/src/runtime/{important-line-classifier.ts → compaction/important-line-classifier.ts} +0 -0
  283. /package/src/runtime/{heartbeat-gradient.ts → heartbeat/heartbeat-gradient.ts} +0 -0
  284. /package/src/runtime/{worker-heartbeat.ts → heartbeat/worker-heartbeat.ts} +0 -0
  285. /package/src/runtime/{worker-startup.ts → heartbeat/worker-startup.ts} +0 -0
  286. /package/src/runtime/{intercom-bridge.ts → live-session/intercom-bridge.ts} +0 -0
  287. /package/src/runtime/{live-control-realtime.ts → live-session/live-control-realtime.ts} +0 -0
  288. /package/src/runtime/{live-extension-bridge.ts → live-session/live-extension-bridge.ts} +0 -0
  289. /package/src/runtime/{live-irc.ts → live-session/live-irc.ts} +0 -0
  290. /package/src/runtime/{live-session-health.ts → live-session/live-session-health.ts} +0 -0
  291. /package/src/runtime/{model-resolver.ts → model/model-resolver.ts} +0 -0
  292. /package/src/runtime/{model-scope.ts → model/model-scope.ts} +0 -0
  293. /package/src/runtime/{output-validator.ts → output/output-validator.ts} +0 -0
  294. /package/src/runtime/{pi-json-output.ts → output/pi-json-output.ts} +0 -0
  295. /package/src/runtime/{progress-event-coalescer.ts → output/progress-event-coalescer.ts} +0 -0
  296. /package/src/runtime/{cancellation-token.ts → process/cancellation-token.ts} +0 -0
  297. /package/src/runtime/{zombie-scanner.ts → process/zombie-scanner.ts} +0 -0
  298. /package/src/runtime/{crash-classification.ts → recovery/crash-classification.ts} +0 -0
  299. /package/src/runtime/{batch-barrier.ts → scheduling/batch-barrier.ts} +0 -0
  300. /package/src/runtime/{global-worker-cap.ts → scheduling/global-worker-cap.ts} +0 -0
  301. /package/src/runtime/{parallel-utils.ts → scheduling/parallel-utils.ts} +0 -0
  302. /package/src/runtime/{scheduler.ts → scheduling/scheduler.ts} +0 -0
  303. /package/src/runtime/{semaphore.ts → scheduling/semaphore.ts} +0 -0
  304. /package/src/runtime/{task-graph.ts → scheduling/task-graph.ts} +0 -0
  305. /package/src/runtime/{verification-worktree.ts → verification/verification-worktree.ts} +0 -0
  306. /package/src/state/{event-reconstructor.ts → event-log/event-reconstructor.ts} +0 -0
  307. /package/src/state/{worker-atomic-writer.ts → event-log/worker-atomic-writer.ts} +0 -0
@@ -1,18 +1,20 @@
1
- import type { AgentConfig } from "../agents/agent-config.ts";
2
- import { writeArtifact } from "../state/artifact-store.ts";
3
- import { appendEventAsync } from "../state/event-log.ts";
4
- import { saveRunTasksAsync, updateRunStatus } from "../state/state-store.ts";
5
- import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
6
- import type { WorkflowStep } from "../workflows/workflow-config.ts";
7
- import { DEFAULT_RETRY_POLICY, executeWithRetry } from "./retry-executor.ts";
8
- import { permissionForRole } from "./role-permission.ts";
9
- import { runWorker } from "./run-worker.ts";
10
- import type { CrewRuntimeMode } from "./runtime-resolver.ts";
11
- import { sanitizeTaskText } from "./task-packet.ts";
12
- import { splitCoalescedOutput } from "./task-runner/output-splitter.ts";
13
- import { mergeArtifacts } from "./team-runner-artifacts.ts";
14
- import { createWorkerHeartbeat, touchWorkerHeartbeat } from "./worker-heartbeat.ts";
15
- import { buildWorkspaceTree } from "./workspace-tree.ts";
1
+ import type { AgentConfig } from "../../agents/agent-config.ts";
2
+ import type { CrewReliabilityConfig, CrewRuntimeConfig } from "../../config/types.ts";
3
+ import { appendEventAsync } from "../../state/event-log/event-log.ts";
4
+ import { writeArtifact } from "../../state/stores/artifact-store.ts";
5
+ import { saveRunTasksAsync, updateRunStatus } from "../../state/stores/state-store.ts";
6
+ import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
7
+ import type { WorkflowStep } from "../../workflows/workflow-config.ts";
8
+ import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
9
+ import type { CrewRuntimeMode } from "../model/runtime-resolver.ts";
10
+ import type { RetryPolicy } from "../recovery/retry-executor.ts";
11
+ import { DEFAULT_RETRY_POLICY, executeWithRetry } from "../recovery/retry-executor.ts";
12
+ import { permissionForRole } from "../role-permission.ts";
13
+ import { runWorker } from "../run-worker.ts";
14
+ import { sanitizeTaskText } from "../task-packet.ts";
15
+ import { splitCoalescedOutput } from "../task-runner/output-splitter.ts";
16
+ import { mergeArtifacts } from "../team-runner-artifacts.ts";
17
+ import { buildWorkspaceTree } from "../workspace-tree.ts";
16
18
 
17
19
  export interface CoalescedTaskGroupInput {
18
20
  manifest: TeamRunManifest;
@@ -27,6 +29,10 @@ export interface CoalescedTaskGroupInput {
27
29
  onJsonEvent?: (taskId: string, runId: string, event: unknown) => void;
28
30
  teamRole?: unknown;
29
31
  perTaskRuntime?: CrewRuntimeMode;
32
+ /** RT-5: runtime config for maxTurns, graceTurns, taskTimeoutMs (mirror singleton). */
33
+ runtimeConfig?: CrewRuntimeConfig;
34
+ /** RT-5: reliability config for autoRetry + retryPolicy (mirror singleton). */
35
+ reliability?: CrewReliabilityConfig;
30
36
  }
31
37
 
32
38
  export interface CoalescedTaskGroupResult {
@@ -80,6 +86,9 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
80
86
 
81
87
  let rawOutput = "";
82
88
  let success = false;
89
+ // RT-5 #1: track cancellation separately from failure so the status
90
+ // mapping can branch cancel → "cancelled" (not "failed").
91
+ let cancelled = false;
83
92
  // FIND-06: serialize heartbeat saves and retain the active save so terminal
84
93
  // results can drain it before their final write.
85
94
  let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
@@ -110,7 +119,7 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
110
119
  if (!taskIds.includes(t.id)) return t;
111
120
  // FIND-06 belt-and-suspenders: never replace terminal state or its
112
121
  // resultArtifact with a heartbeat-only snapshot.
113
- if (t.status === "completed" || t.status === "failed") return t;
122
+ if (t.status === "completed" || t.status === "failed" || t.status === "cancelled") return t;
114
123
  return {
115
124
  ...t,
116
125
  heartbeat: touchWorkerHeartbeat(t.heartbeat ?? createWorkerHeartbeat(t.id), { alive: true }),
@@ -135,26 +144,76 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
135
144
  }
136
145
  })();
137
146
  }, 15_000);
147
+ // RT-5 #3/#4/#5: compute maxTurns, wall-clock timeout, and retry policy
148
+ // from config instead of hardcoding — mirrors the singleton path
149
+ // (team-runner.ts:1548-1578 + child-executor.ts:395-430).
150
+ const taskTimeoutMs = input.runtimeConfig?.taskTimeoutMs ?? 0;
151
+ const useRetry = input.reliability?.autoRetry !== false;
152
+ const policy: RetryPolicy = {
153
+ ...DEFAULT_RETRY_POLICY,
154
+ ...(input.reliability?.retryPolicy ?? {}),
155
+ };
156
+ // RT-5 #3: pass maxTurns from config instead of hardcoded 5.
157
+ // RT-5 #4: arm a per-attempt wall-clock timeout mirroring the singleton's
158
+ // AbortController+setTimeout pattern (child-executor.ts:395-430). The
159
+ // timeoutController is linked to the run-level signal so an external
160
+ // abort also aborts the worker. Its signal is passed to runWorker; the
161
+ // existing SIGTERM→SIGKILL escalation in child-pi.ts handles cleanup.
162
+ const runOnce = async () => {
163
+ const timeoutController = new AbortController();
164
+ let externalAbortListener: (() => void) | undefined;
165
+ if (signal) {
166
+ if (signal.aborted) {
167
+ timeoutController.abort(signal.reason);
168
+ } else {
169
+ externalAbortListener = () => timeoutController.abort(signal!.reason);
170
+ signal.addEventListener("abort", externalAbortListener, { once: true });
171
+ }
172
+ }
173
+ let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
174
+ if (taskTimeoutMs > 0 && !timeoutController.signal.aborted) {
175
+ timeoutHandle = setTimeout(() => {
176
+ if (!timeoutController.signal.aborted) {
177
+ timeoutController.abort(new Error(`Task exceeded wall-clock timeout of ${taskTimeoutMs}ms`));
178
+ }
179
+ }, taskTimeoutMs);
180
+ timeoutHandle.unref?.();
181
+ }
182
+ try {
183
+ return await runWorker({
184
+ cwd: firstTask.cwd,
185
+ task: combinedPrompt,
186
+ agent,
187
+ signal: timeoutController.signal,
188
+ excludeContextBash: true,
189
+ maxTurns: input.runtimeConfig?.maxTurns,
190
+ graceTurns: input.runtimeConfig?.graceTurns,
191
+ onJsonEvent: (e) => input.onJsonEvent?.(firstTask.id, manifest.runId, e),
192
+ });
193
+ } finally {
194
+ if (timeoutHandle) clearTimeout(timeoutHandle);
195
+ if (externalAbortListener && signal) {
196
+ signal.removeEventListener("abort", externalAbortListener);
197
+ }
198
+ }
199
+ };
138
200
  try {
139
- const result = await executeWithRetry(
140
- async () => {
141
- return await runWorker({
142
- cwd: firstTask.cwd,
143
- task: combinedPrompt,
144
- agent,
145
- signal,
146
- excludeContextBash: true,
147
- maxTurns: 5,
148
- onJsonEvent: (e) => input.onJsonEvent?.(firstTask.id, manifest.runId, e),
149
- });
150
- },
151
- DEFAULT_RETRY_POLICY,
152
- { signal },
153
- );
201
+ const result = useRetry ? await executeWithRetry(runOnce, policy, { signal }) : await runOnce();
154
202
  rawOutput = result.rawFinalText ?? result.stdout ?? "";
155
- success = result.exitStatus?.exitCode === 0;
203
+ // RT-5 #1/#2: distinguish cancel from failure. Cancel = run-level
204
+ // signal aborted OR the child reports cooperative cancellation.
205
+ // success requires exitCode===0 AND no error AND not cancelled
206
+ // (previously success = exitCode===0 only, which misreported
207
+ // depth-guard exitCode:1 and ignored the error field).
208
+ cancelled = signal?.aborted === true || result.exitStatus?.cancelled === true;
209
+ success = !cancelled && result.exitCode === 0 && !result.error;
156
210
  } catch (err) {
157
- rawOutput = `Worker dispatch failed: ${err instanceof Error ? err.message : String(err)}`;
211
+ // RT-5 #1: detect cancel in the throw path (e.g. executeWithRetry's
212
+ // throwIfCancelled when the run-level signal is already aborted).
213
+ cancelled = signal?.aborted === true;
214
+ rawOutput = cancelled
215
+ ? `Worker dispatch cancelled: ${err instanceof Error ? err.message : String(err)}`
216
+ : `Worker dispatch failed: ${err instanceof Error ? err.message : String(err)}`;
158
217
  success = false;
159
218
  } finally {
160
219
  if (heartbeatTimer !== null) clearInterval(heartbeatTimer);
@@ -186,7 +245,7 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
186
245
  newArtifacts.push(resultArtifact);
187
246
  return {
188
247
  ...t,
189
- status: ok ? ("completed" as const) : ("failed" as const),
248
+ status: ok ? ("completed" as const) : cancelled ? ("cancelled" as const) : ("failed" as const),
190
249
  finishedAt,
191
250
  result: {
192
251
  text,
@@ -232,8 +291,8 @@ export async function runCoalescedTaskGroup(input: CoalescedTaskGroupInput): Pro
232
291
  await appendEventAsync(updatedManifest.eventsPath, {
233
292
  type: "task.coalesced_dispatch_end",
234
293
  runId: manifest.runId,
235
- message: `Coalesced dispatch ${success ? "completed" : "failed"} (${taskIds.length} tasks, ${split[0]?.strategy ?? "broadcast"} split)`,
236
- data: { groupId, taskIds, success, strategy: split[0]?.strategy },
294
+ message: `Coalesced dispatch ${success ? "completed" : cancelled ? "cancelled" : "failed"} (${taskIds.length} tasks, ${split[0]?.strategy ?? "broadcast"} split)`,
295
+ data: { groupId, taskIds, success, cancelled, strategy: split[0]?.strategy },
237
296
  });
238
297
 
239
298
  return { manifest: updatedManifest, tasks: updatedTasks, taskIds, rawOutput, success };
@@ -1,4 +1,4 @@
1
- import type { TeamTaskState } from "../state/types.ts";
1
+ import type { TeamTaskState } from "../../state/types.ts";
2
2
 
3
3
  export interface TaskGraphSchedulerSnapshot {
4
4
  ready: string[];
@@ -12,7 +12,7 @@ export function tryRegisterSessionCleanup(pi: ExtensionAPI, cleanup: () => void)
12
12
  const registerFn = api.registerSessionResourceCleanup;
13
13
  if (typeof registerFn === "function") {
14
14
  try {
15
- const unregister = (registerFn as (fn: () => void) => (() => void) | void)(cleanup);
15
+ const unregister = (registerFn as (fn: () => void) => (() => void) | undefined)(cleanup);
16
16
  if (typeof unregister === "function") return unregister;
17
17
  // API returned void — cleanup is registered but cannot be unregistered
18
18
  return undefined;
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import * as path from "node:path";
4
4
  import { atomicWriteJson } from "../state/atomic-write.ts";
5
- import { withFileLockSync } from "../state/locks.ts";
5
+ import { withFileLockSync } from "../state/coordination/locks.ts";
6
6
  import { logInternalError } from "../utils/internal-error.ts";
7
7
  import type { JoinMode } from "./group-join.ts";
8
8
 
@@ -72,6 +72,7 @@ export function composeSingleAgentPrompt(workflow: WorkflowConfig, goal: string)
72
72
  if (step.output) {
73
73
  lines.push(`Output: write your result to \`${step.output}\``);
74
74
  }
75
+ // biome-ignore lint/complexity/useOptionalChain: reads is `string[] | false | undefined` — optional chain doesn't narrow out `false` (no .length on boolean)
75
76
  if (step.reads && step.reads.length) {
76
77
  lines.push(`Read first: ${step.reads.join(", ")}`);
77
78
  }
@@ -3,7 +3,7 @@ import * as os from "node:os";
3
3
  import * as path from "node:path";
4
4
  import { errors } from "../errors.ts";
5
5
  import { atomicWriteFile, atomicWriteJson } from "../state/atomic-write.ts";
6
- import { saveRunManifest } from "../state/state-store.ts";
6
+ import { saveRunManifest } from "../state/stores/state-store.ts";
7
7
  import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
8
8
  import { recordFromTask, upsertCrewAgent } from "./crew-agent-records.ts";
9
9
  import { checkProcessLiveness } from "./process-status.ts";
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { DEFAULT_PATHS, DEFAULT_SUBAGENT } from "../config/defaults.ts";
4
4
  import type { PiTeamsToolResult } from "../extension/tool-result.ts";
5
- import { loadRunManifestById } from "../state/state-store.ts";
5
+ import { loadRunManifestById } from "../state/stores/state-store.ts";
6
6
  import { logInternalError } from "../utils/internal-error.ts";
7
7
  import { projectCrewRoot } from "../utils/paths.ts";
8
8
  import { redactSecrets } from "../utils/redaction.ts";
@@ -1,4 +1,4 @@
1
- import { appendEvent } from "../state/event-log.ts";
1
+ import { appendEvent } from "../state/event-log/event-log.ts";
2
2
  import type { TeamRunManifest } from "../state/types.ts";
3
3
  import { logInternalError } from "../utils/internal-error.ts";
4
4
 
@@ -1,14 +1,14 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { DEFAULT_OUTPUT_CONTEXT } from "../config/defaults.ts";
4
- import { writeArtifact } from "../state/artifact-store.ts";
5
4
  import { atomicWriteFile } from "../state/atomic-write.ts";
5
+ import { writeArtifact } from "../state/stores/artifact-store.ts";
6
6
  import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../state/types.ts";
7
7
  import { resolveRealContainedPath } from "../utils/safe-paths.ts";
8
8
  import type { WorkflowStep } from "../workflows/workflow-config.ts";
9
- import { applyCompactPipeline } from "./compact-pipeline.ts";
10
- import { ANSI_STRIP_STAGE, BLANK_COLLAPSE_STAGE, TruncationStage } from "./compact-stages/index.ts";
11
- import { DEFAULT_PRUNE_CONFIG, type FileEditEvent, pruneToolOutputs, type ToolResultEntry } from "./tool-output-pruner.ts";
9
+ import { applyCompactPipeline } from "./compaction/compact-pipeline.ts";
10
+ import { ANSI_STRIP_STAGE, BLANK_COLLAPSE_STAGE, TruncationStage } from "./compaction/compact-stages/index.ts";
11
+ import { DEFAULT_PRUNE_CONFIG, type FileEditEvent, pruneToolOutputs, type ToolResultEntry } from "./compaction/tool-output-pruner.ts";
12
12
 
13
13
  export interface DependencyContextEntry {
14
14
  taskId: string;
@@ -410,7 +410,9 @@ export function collectDependencyOutputContext(
410
410
  // (used for recency sort in the trim step). Both are looked up against
411
411
  // `task.dependsOn` (the declared order) and `tasks` (finished timestamps).
412
412
  const declaredOrder = new Map<string, number>();
413
- task.dependsOn.forEach((depId, index) => declaredOrder.set(depId, index));
413
+ task.dependsOn.forEach((depId, index) => {
414
+ declaredOrder.set(depId, index);
415
+ });
414
416
  const recencyByTaskId = new Map<string, number>();
415
417
  for (const item of tasks) {
416
418
  if (!item.finishedAt) continue;
@@ -29,13 +29,12 @@ import * as fs from "node:fs";
29
29
  import * as path from "node:path";
30
30
  import { loadConfig } from "../../config/config.ts";
31
31
  import { errors } from "../../errors.ts";
32
- import { writeArtifact } from "../../state/artifact-store.ts";
33
- import { appendEventAsync, appendEventBuffered } from "../../state/event-log.ts";
32
+ import { appendEventAsync, appendEventBuffered } from "../../state/event-log/event-log.ts";
33
+ import { writeArtifact } from "../../state/stores/artifact-store.ts";
34
34
  import type { ArtifactDescriptor, OperationTerminalEvidence, TeamRunManifest } from "../../state/types.ts";
35
35
  import { logInternalError } from "../../utils/internal-error.ts";
36
36
  import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
37
- import { buildSyntheticTerminalEvidence, cancellationReasonFromSignal } from "../cancellation.ts";
38
- import type { ChildPiLifecycleEvent } from "../child-pi.ts";
37
+ import type { ChildPiLifecycleEvent, ChildPiRunResult } from "../child-pi/child-pi.ts";
39
38
  import {
40
39
  appendCrewAgentEvent,
41
40
  appendCrewAgentOutput,
@@ -45,21 +44,22 @@ import {
45
44
  } from "../crew-agent-records.ts";
46
45
  import { crewHooks } from "../crew-hooks.ts";
47
46
  import { bridgeEventFromJsonEvent } from "../event-stream-bridge.ts";
47
+ import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
48
+ import { createStartupEvidence } from "../heartbeat/worker-startup.ts";
48
49
  import {
49
50
  buildConfiguredModelRouting,
50
51
  formatModelAttemptNote,
51
52
  isRetryableModelFailure,
52
53
  type ModelAttemptSummary,
53
- } from "../model-fallback.ts";
54
- import { readEnabledModelsPatterns } from "../model-scope.ts";
55
- import { type ParsedPiJsonOutput, parsePiJsonOutput } from "../pi-json-output.ts";
56
- import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../progress-event-coalescer.ts";
57
- import { DEFAULT_RETRY_POLICY } from "../retry-executor.ts";
54
+ } from "../model/model-fallback.ts";
55
+ import { readEnabledModelsPatterns } from "../model/model-scope.ts";
56
+ import { type ParsedPiJsonOutput, parsePiJsonOutput } from "../output/pi-json-output.ts";
57
+ import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../output/progress-event-coalescer.ts";
58
+ import { buildSyntheticTerminalEvidence, cancellationReasonFromSignal } from "../process/cancellation.ts";
59
+ import { DEFAULT_RETRY_POLICY } from "../recovery/retry-executor.ts";
58
60
  import { runWorker } from "../run-worker.ts";
59
61
  import { parseSessionUsage } from "../session-usage.ts";
60
62
  import { recordSupervisorContact, supervisorContactFromEvent } from "../supervisor-contact.ts";
61
- import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../worker-heartbeat.ts";
62
- import { createStartupEvidence } from "../worker-startup.ts";
63
63
  import type { TaskExecutionResult } from "./post-execution.ts";
64
64
  import type { StreamBridgeHandle, TaskExecutionContext } from "./pre-execution.ts";
65
65
  import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./progress.ts";
@@ -115,6 +115,35 @@ async function resolveTaskScopeModelsPatterns(cwd: string): Promise<string[]> {
115
115
  return readEnabledModelsPatterns(cwd);
116
116
  }
117
117
 
118
+ /**
119
+ * RT-6: resolve the configured retry policy's maxAttempts from the project
120
+ * reliability config (`reliability.retryPolicy.maxAttempts`), falling back to
121
+ * {@link DEFAULT_RETRY_POLICY}.maxAttempts when config is unavailable or the
122
+ * field is unset. Mirrors `retryPolicyFromConfig` in team-runner.ts so the
123
+ * spawn-budget math and the actual retry loop (executeWithRetry) agree on the
124
+ * same ceiling. Best-effort: any config read failure silently falls back to
125
+ * the default so a misconfiguration never blocks the spawn.
126
+ */
127
+ export function resolveConfiguredMaxAttempts(cwd: string): number {
128
+ try {
129
+ return loadConfig(cwd).config.reliability?.retryPolicy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts;
130
+ } catch {
131
+ return DEFAULT_RETRY_POLICY.maxAttempts;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * RT-6: pure spawn-budget max formula. `attemptModelsCount × (maxAttempts + 1)`
137
+ * — always ≥ 1 full attempt above the theoretical max of
138
+ * `maxAttempts × attemptModelsCount`. Exported for direct unit testing so the
139
+ * configured-vs-default maxAttempts distinction is locked independently of
140
+ * the retry loop (previously hard-coded DEFAULT_RETRY_POLICY.maxAttempts = 3,
141
+ * silently halving retries when a higher maxAttempts — up to 10 — was set).
142
+ */
143
+ export function computeSpawnBudgetMax(attemptModelsCount: number, configuredMaxAttempts: number): number {
144
+ return attemptModelsCount * (configuredMaxAttempts + 1);
145
+ }
146
+
118
147
  /**
119
148
  * 429/rate-limit detection (PI_CREW_TOOLING_429_NOTE.md).
120
149
  *
@@ -215,8 +244,6 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
215
244
  const collectedJsonEvents = ctx.collectedJsonEvents;
216
245
  const streamBridge: StreamBridgeHandle | undefined = ctx.streamBridge;
217
246
 
218
- let resultArtifact: ArtifactDescriptor;
219
- let logArtifact: ArtifactDescriptor | undefined;
220
247
  let transcriptArtifact: ArtifactDescriptor | undefined;
221
248
  let exitCode: number | null = 0;
222
249
  let error: string | undefined;
@@ -246,8 +273,13 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
246
273
  // Budget = attemptModels.length × (maxAttempts + 1) — always one
247
274
  // full attempt-worth above the theoretical maximum of
248
275
  // maxAttempts × attemptModels.length. Only computes once (max=0 guard).
276
+ // RT-6: use the configured retry policy's maxAttempts (from project
277
+ // reliability config), NOT DEFAULT_RETRY_POLICY (3). The retry loop in
278
+ // team-runner.ts wraps runTeamTask in executeWithRetry with the same
279
+ // configured maxAttempts (up to 10); hard-coding the default here silently
280
+ // halved the spawn budget relative to the real retry ceiling.
249
281
  if (input.spawnBudget && input.spawnBudget.max === 0) {
250
- input.spawnBudget.max = attemptModels.length * (DEFAULT_RETRY_POLICY.maxAttempts + 1);
282
+ input.spawnBudget.max = computeSpawnBudgetMax(attemptModels.length, resolveConfiguredMaxAttempts(task.cwd));
251
283
  }
252
284
  const logs: string[] = [];
253
285
  let finalStderr = "";
@@ -390,7 +422,7 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
390
422
  }, taskTimeoutMs);
391
423
  timeoutHandle.unref?.();
392
424
  }
393
- let childResult;
425
+ let childResult: ChildPiRunResult;
394
426
  try {
395
427
  childResult = await runWorker({
396
428
  cwd: task.cwd,
@@ -419,7 +451,10 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
419
451
  const steeringDir = `${manifest.artifactsRoot}/steering`;
420
452
  // Fire-and-forget async write for steering events
421
453
  void appendSteeringAsync(steeringDir, task.id, task.pendingSteers);
422
- task.pendingSteers = [];
454
+ // RT-8: spread before clearing pendingSteers instead of mutating
455
+ // in place — preserves the immutable-snapshot invariant (the same
456
+ // object may already be referenced by the tasks array / snapshots).
457
+ task = { ...task, pendingSteers: [] };
423
458
  tasks = persistSingleTaskUpdate(manifest, tasks, task);
424
459
  }
425
460
  } catch (err) {
@@ -459,10 +494,15 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
459
494
  if (msg?.role === "assistant") {
460
495
  const usage = msg.usage as Record<string, number> | undefined;
461
496
  if (usage) {
462
- task.lifetimeUsage = {
463
- input: (task.lifetimeUsage?.input ?? 0) + (usage.input ?? 0),
464
- output: (task.lifetimeUsage?.output ?? 0) + (usage.output ?? 0),
465
- cacheWrite: (task.lifetimeUsage?.cacheWrite ?? 0) + (usage.cacheWrite ?? 0),
497
+ // RT-8: spread before accumulating lifetimeUsage instead of
498
+ // mutating in place — preserves the immutable-snapshot invariant.
499
+ task = {
500
+ ...task,
501
+ lifetimeUsage: {
502
+ input: (task.lifetimeUsage?.input ?? 0) + (usage.input ?? 0),
503
+ output: (task.lifetimeUsage?.output ?? 0) + (usage.output ?? 0),
504
+ cacheWrite: (task.lifetimeUsage?.cacheWrite ?? 0) + (usage.cacheWrite ?? 0),
505
+ },
466
506
  };
467
507
  }
468
508
  }
@@ -676,7 +716,7 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
676
716
  });
677
717
  }
678
718
  }
679
- resultArtifact = writeArtifact(manifest.artifactsRoot, {
719
+ const resultArtifact = writeArtifact(manifest.artifactsRoot, {
680
720
  kind: "result",
681
721
  relativePath: `results/${task.id}.txt`,
682
722
  content:
@@ -695,7 +735,7 @@ export async function runChildProcessTask(ctx: TaskExecutionContext): Promise<Ta
695
735
  "(no output)",
696
736
  producer: task.id,
697
737
  });
698
- logArtifact = writeArtifact(manifest.artifactsRoot, {
738
+ const logArtifact = writeArtifact(manifest.artifactsRoot, {
699
739
  kind: "log",
700
740
  relativePath: `logs/${task.id}.log`,
701
741
  content: [
@@ -1,9 +1,9 @@
1
1
  import * as fs from "node:fs";
2
2
  import type { AgentConfig } from "../../agents/agent-config.ts";
3
3
  import type { CrewRuntimeConfig } from "../../config/config.ts";
4
- import { writeArtifact } from "../../state/artifact-store.ts";
5
- import { appendEventFireAndForget } from "../../state/event-log.ts";
6
- import { loadRunManifestById } from "../../state/state-store.ts";
4
+ import { appendEventFireAndForget } from "../../state/event-log/event-log.ts";
5
+ import { writeArtifact } from "../../state/stores/artifact-store.ts";
6
+ import { loadRunManifestById } from "../../state/stores/state-store.ts";
7
7
  import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
8
8
  import type { WorkflowStep } from "../../workflows/workflow-config.ts";
9
9
  import {
@@ -13,11 +13,11 @@ import {
13
13
  recordFromTask,
14
14
  upsertCrewAgent,
15
15
  } from "../crew-agent-records.ts";
16
- import { runLiveSessionTask } from "../live-session-runtime.ts";
17
- import type { ParsedPiJsonOutput } from "../pi-json-output.ts";
18
- import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../progress-event-coalescer.ts";
19
- import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../worker-heartbeat.ts";
20
- import { createStartupEvidence, type WorkerStartupEvidence } from "../worker-startup.ts";
16
+ import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
17
+ import { createStartupEvidence, type WorkerStartupEvidence } from "../heartbeat/worker-startup.ts";
18
+ import { runLiveSessionTask } from "../live-session/live-session-runtime.ts";
19
+ import type { ParsedPiJsonOutput } from "../output/pi-json-output.ts";
20
+ import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../output/progress-event-coalescer.ts";
21
21
  import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./progress.ts";
22
22
  import { persistSingleTaskUpdate } from "./state-helpers.ts";
23
23
 
@@ -15,10 +15,10 @@
15
15
  * exactly (char scenarios 5-7, 9, 10 cover them).
16
16
  */
17
17
  import { appendHookEvent, executeHook } from "../../hooks/registry.ts";
18
- import { writeArtifact } from "../../state/artifact-store.ts";
19
- import { appendEventAsync } from "../../state/event-log.ts";
20
- import { withRunLock } from "../../state/locks.ts";
21
- import { saveRunManifestAsync } from "../../state/state-store.ts";
18
+ import { withRunLock } from "../../state/coordination/locks.ts";
19
+ import { appendEventAsync } from "../../state/event-log/event-log.ts";
20
+ import { writeArtifact } from "../../state/stores/artifact-store.ts";
21
+ import { saveRunManifestAsync } from "../../state/stores/state-store.ts";
22
22
  import type {
23
23
  ArtifactDescriptor,
24
24
  OperationTerminalEvidence,
@@ -29,16 +29,16 @@ import type {
29
29
  import { captureWorktreeDiffAsync, captureWorktreeDiffStatAsync } from "../../worktree/worktree-manager.ts";
30
30
  import { appendTaskAttentionEvent } from "../attention-events.ts";
31
31
  import { extractCommandTrace } from "../command-trace.ts";
32
- import { evaluateCompletionMutationGuard } from "../completion-guard.ts";
33
32
  import { emptyCrewAgentProgress, recordFromTask, upsertCrewAgent } from "../crew-agent-records.ts";
34
33
  import { crewHooks } from "../crew-hooks.ts";
35
- import { createVerificationEvidence } from "../green-contract.ts";
36
- import type { ModelAttemptSummary } from "../model-fallback.ts";
37
- import { type OutputValidationResult, validateWorkerOutput } from "../output-validator.ts";
38
- import type { ParsedPiJsonOutput } from "../pi-json-output.ts";
34
+ import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
35
+ import type { ModelAttemptSummary } from "../model/model-fallback.ts";
36
+ import { type OutputValidationResult, validateWorkerOutput } from "../output/output-validator.ts";
37
+ import type { ParsedPiJsonOutput } from "../output/pi-json-output.ts";
39
38
  import { writeTaskSharedOutput } from "../task-output-context.ts";
40
- import { computeGreenLevelFromResults, executeVerificationCommands } from "../verification-gates.ts";
41
- import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../worker-heartbeat.ts";
39
+ import { evaluateCompletionMutationGuard } from "../verification/completion-guard.ts";
40
+ import { createVerificationEvidence } from "../verification/green-contract.ts";
41
+ import { computeGreenLevelFromResults, executeVerificationCommands } from "../verification/verification-gates.ts";
42
42
  import { extractYieldResult, hasYieldInOutput, isYieldEvent, type YieldResult } from "../yield-handler.ts";
43
43
  import { buildWorkerCapabilityInventory } from "./capabilities.ts";
44
44
  import type { TaskExecutionContext } from "./pre-execution.ts";
@@ -64,7 +64,7 @@ export interface TaskExecutionResult {
64
64
  finalStdout: string;
65
65
  transcriptPath: string | undefined;
66
66
  terminalEvidence: OperationTerminalEvidence[];
67
- startupEvidence: import("../worker-startup.ts").WorkerStartupEvidence;
67
+ startupEvidence: import("../heartbeat/worker-startup.ts").WorkerStartupEvidence;
68
68
  }
69
69
 
70
70
  /** Final persisted task state returned by finalizeTaskResult. */
@@ -14,18 +14,20 @@
14
14
  * Extracted verbatim from `runTeamTask` — no behavioral changes.
15
15
  */
16
16
  import { errors } from "../../errors.ts";
17
- import { writeArtifact } from "../../state/artifact-store.ts";
18
- import { appendEventAsync, appendEventFireAndForget } from "../../state/event-log.ts";
19
- import { createTaskClaim } from "../../state/task-claims.ts";
17
+ import { createTaskClaim } from "../../state/coordination/task-claims.ts";
18
+ import { appendEventAsync, appendEventFireAndForget } from "../../state/event-log/event-log.ts";
19
+ import { writeArtifact } from "../../state/stores/artifact-store.ts";
20
20
  import type { ArtifactDescriptor, TaskPacket, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
21
21
  import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
22
22
  import type { PreparedTaskWorkspace } from "../../worktree/worktree-manager.ts";
23
23
  import { prepareTaskWorkspaceAsync } from "../../worktree/worktree-manager.ts";
24
24
  import { reserveControlChannel } from "../agent-control.ts";
25
- import { cancellationReasonFromSignal } from "../cancellation.ts";
26
25
  import { emptyCrewAgentProgress, recordFromTask, upsertCrewAgent } from "../crew-agent-records.ts";
27
26
  import type { CrewRuntimeKind } from "../crew-agent-runtime.ts";
28
27
  import type { registerStreamBridge } from "../event-stream-bridge.ts";
28
+ import { createWorkerHeartbeat } from "../heartbeat/worker-heartbeat.ts";
29
+ import { createStartupEvidence, type WorkerStartupEvidence } from "../heartbeat/worker-startup.ts";
30
+ import { cancellationReasonFromSignal } from "../process/cancellation.ts";
29
31
  import { permissionForRole, type RolePermissionMode } from "../role-permission.ts";
30
32
  import { renderSkillInstructions } from "../skill-instructions.ts";
31
33
  import { collectDependencyOutputContext, renderDependencyOutputContext, writeTaskInputsArtifact } from "../task-output-context.ts";
@@ -33,8 +35,6 @@ import { buildTaskPacket } from "../task-packet.ts";
33
35
  // Type-only import avoids runtime circular dependency (task-runner.ts imports
34
36
  // this module at runtime; we only need the TaskRunnerInput type here).
35
37
  import type { TaskRunnerInput } from "../task-runner.ts";
36
- import { createWorkerHeartbeat } from "../worker-heartbeat.ts";
37
- import { createStartupEvidence, type WorkerStartupEvidence } from "../worker-startup.ts";
38
38
  import { DEFAULT_YIELD_CONFIG } from "../yield-handler.ts";
39
39
  import { coordinationBridgeInstructions, renderTaskPrompt } from "./prompt-builder.ts";
40
40
  import { checkpointTask, persistSingleTaskUpdate, updateTask } from "./state-helpers.ts";
@@ -1,7 +1,7 @@
1
1
  import type { TeamTaskState, UsageState } from "../../state/types.ts";
2
2
  import { emptyCrewAgentProgress } from "../crew-agent-records.ts";
3
3
  import type { CrewAgentProgress } from "../crew-agent-runtime.ts";
4
- import type { ProgressEventSummary } from "../progress-event-coalescer.ts";
4
+ import type { ProgressEventSummary } from "../output/progress-event-coalescer.ts";
5
5
 
6
6
  function asRecord(value: unknown): Record<string, unknown> | undefined {
7
7
  return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;
@@ -1,4 +1,4 @@
1
- import type { MailboxMessage } from "../../state/mailbox.ts";
1
+ import type { MailboxMessage } from "../../state/coordination/mailbox.ts";
2
2
  import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
3
3
  import { sanitizeTaskText } from "../task-packet.ts";
4
4
 
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Extracted verbatim from the `else` (scaffold) branch of `runTeamTask`.
9
9
  */
10
- import { writeArtifact } from "../../state/artifact-store.ts";
10
+ import { writeArtifact } from "../../state/stores/artifact-store.ts";
11
11
  import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
12
12
 
13
13
  export function runScaffoldTask(manifest: TeamRunManifest, task: TeamTaskState): ArtifactDescriptor {
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import { flushPendingAtomicWrites } from "../../state/atomic-write.ts";
3
- import { withRunLockSync } from "../../state/locks.ts";
4
- import { loadRunManifestById, saveRunTasksCoalesced } from "../../state/state-store.ts";
3
+ import { withRunLockSync } from "../../state/coordination/locks.ts";
4
+ import { loadRunManifestById, saveRunTasksCoalesced } from "../../state/stores/state-store.ts";
5
5
  import type { TaskCheckpointState, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
6
6
  import { logInternalError } from "../../utils/internal-error.ts";
7
7
  import { recordFromTask, upsertCrewAgent } from "../crew-agent-records.ts";
@@ -1,13 +1,13 @@
1
1
  import type { AgentConfig } from "../agents/agent-config.ts";
2
2
  import type { CrewLimitsConfig, CrewRuntimeConfig } from "../config/config.ts";
3
- import { writeArtifact } from "../state/artifact-store.ts";
3
+ import { writeArtifact } from "../state/stores/artifact-store.ts";
4
4
  import type { ArtifactDescriptor, OperationTerminalEvidence, TeamRunManifest, TeamTaskState } from "../state/types.ts";
5
5
  import type { WorkflowStep } from "../workflows/workflow-config.ts";
6
6
  import type { CrewRuntimeKind } from "./crew-agent-runtime.ts";
7
7
  import { registerStreamBridge } from "./event-stream-bridge.ts";
8
- import type { ModelAttemptSummary } from "./model-fallback.ts";
9
- import type { ParsedPiJsonOutput } from "./pi-json-output.ts";
10
- import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
8
+ import type { ModelAttemptSummary } from "./model/model-fallback.ts";
9
+ import { awaitRuntimeWarmup } from "./model/runtime-warmup.ts";
10
+ import type { ParsedPiJsonOutput } from "./output/pi-json-output.ts";
11
11
  import { runChildProcessTask } from "./task-runner/child-executor.ts";
12
12
  import { finalizeTaskResult, type TaskExecutionResult } from "./task-runner/post-execution.ts";
13
13
  import { prepareTaskExecutionContext } from "./task-runner/pre-execution.ts";