pi-crew 0.9.15 → 0.9.17

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 (432) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/README.md +19 -0
  3. package/dist/build-meta.json +21790 -0
  4. package/dist/index.mjs +83070 -0
  5. package/dist/index.mjs.map +7 -0
  6. package/docs/A +358 -0
  7. package/docs/M-A +357 -0
  8. package/docs/REVIEW-FINDINGS-2026-06 +357 -0
  9. package/docs/Y +357 -0
  10. package/docs/a +357 -0
  11. package/docs/aA +358 -0
  12. package/docs/archive/README.md +91 -0
  13. package/docs/patterns/command-agent-skill.md +1 -1
  14. package/docs/skills/REFERENCE.md +0 -17
  15. package/docs//303/242mmaAAA/303/242 +357 -0
  16. package/index.bundle.ts +25 -0
  17. package/index.ts +95 -4
  18. package/package.json +15 -4
  19. package/skills/iterative-audit/SKILL.md +0 -1
  20. package/skills/widget-rendering/SKILL.md +17 -0
  21. package/src/adapters/claude-adapter.ts +1 -3
  22. package/src/adapters/export-util.ts +16 -16
  23. package/src/adapters/index.ts +5 -5
  24. package/src/agents/agent-config.ts +20 -14
  25. package/src/agents/agent-serializer.ts +1 -1
  26. package/src/agents/discover-agents.ts +83 -39
  27. package/src/benchmark/benchmark-runner.ts +51 -51
  28. package/src/benchmark/feedback-loop.ts +1 -1
  29. package/src/config/config.ts +166 -590
  30. package/src/config/defaults.ts +28 -2
  31. package/src/config/drift-detector.ts +11 -14
  32. package/src/config/markers.ts +201 -203
  33. package/src/config/resilient-parser.ts +14 -6
  34. package/src/config/role-tools.ts +3 -3
  35. package/src/config/suggestions.ts +5 -12
  36. package/src/config/types.ts +9 -25
  37. package/src/errors.ts +151 -157
  38. package/src/extension/action-suggestions.ts +54 -9
  39. package/src/extension/async-notifier.ts +43 -13
  40. package/src/extension/autonomous-policy.ts +77 -37
  41. package/src/extension/command-completions.ts +9 -8
  42. package/src/extension/context-status-injection.ts +14 -12
  43. package/src/extension/crew-autocomplete.ts +8 -16
  44. package/src/extension/crew-cleanup.ts +2 -1
  45. package/src/extension/crew-shortcuts.ts +9 -6
  46. package/src/extension/cross-extension-rpc.ts +136 -42
  47. package/src/extension/help.ts +1 -1
  48. package/src/extension/import-index.ts +10 -5
  49. package/src/extension/knowledge-injection.ts +88 -15
  50. package/src/extension/management.ts +89 -349
  51. package/src/extension/message-renderers.ts +3 -4
  52. package/src/extension/notification-router.ts +22 -5
  53. package/src/extension/notification-sink.ts +6 -3
  54. package/src/extension/pi-api.ts +17 -8
  55. package/src/extension/plan-orchestrate.ts +8 -27
  56. package/src/extension/project-init.ts +21 -6
  57. package/src/extension/register.ts +329 -975
  58. package/src/extension/registration/artifact-cleanup.ts +9 -4
  59. package/src/extension/registration/command-utils.ts +5 -1
  60. package/src/extension/registration/commands.ts +806 -314
  61. package/src/extension/registration/compaction-guard.ts +15 -15
  62. package/src/extension/registration/lifecycle.ts +259 -0
  63. package/src/extension/registration/observability.ts +293 -0
  64. package/src/extension/registration/subagent-helpers.ts +29 -7
  65. package/src/extension/registration/subagent-tools.ts +253 -44
  66. package/src/extension/registration/team-tool.ts +19 -84
  67. package/src/extension/registration/ui.ts +168 -0
  68. package/src/extension/registration/viewers.ts +64 -24
  69. package/src/extension/result-watcher.ts +18 -7
  70. package/src/extension/run-bundle-schema.ts +21 -6
  71. package/src/extension/run-export.ts +15 -6
  72. package/src/extension/run-import.ts +64 -29
  73. package/src/extension/run-index.ts +28 -9
  74. package/src/extension/run-maintenance.ts +32 -12
  75. package/src/extension/session-summary.ts +1 -1
  76. package/src/extension/team-manager-command.ts +64 -7
  77. package/src/extension/team-onboard.ts +151 -150
  78. package/src/extension/team-recommendation.ts +121 -21
  79. package/src/extension/team-tool/anchor.ts +31 -64
  80. package/src/extension/team-tool/api.ts +929 -141
  81. package/src/extension/team-tool/auto-summarize.ts +14 -26
  82. package/src/extension/team-tool/cache-control.ts +1 -5
  83. package/src/extension/team-tool/cancel.ts +138 -38
  84. package/src/extension/team-tool/chain-dispatch.ts +5 -13
  85. package/src/extension/team-tool/chain-executor.ts +29 -51
  86. package/src/extension/team-tool/config-patch.ts +1 -1
  87. package/src/extension/team-tool/context.ts +40 -20
  88. package/src/extension/team-tool/destructive-gate.ts +10 -5
  89. package/src/extension/team-tool/doctor.ts +170 -51
  90. package/src/extension/team-tool/explain.ts +228 -214
  91. package/src/extension/team-tool/failure-patterns.ts +3 -9
  92. package/src/extension/team-tool/goal-wrap.ts +71 -29
  93. package/src/extension/team-tool/goal.ts +185 -35
  94. package/src/extension/team-tool/handle-schedule.ts +34 -15
  95. package/src/extension/team-tool/handle-settings.ts +94 -56
  96. package/src/extension/team-tool/health-monitor.ts +27 -108
  97. package/src/extension/team-tool/inspect.ts +42 -9
  98. package/src/extension/team-tool/intent-policy.ts +4 -1
  99. package/src/extension/team-tool/lifecycle-actions.ts +244 -48
  100. package/src/extension/team-tool/orchestrate.ts +7 -18
  101. package/src/extension/team-tool/parallel-dispatch.ts +51 -29
  102. package/src/extension/team-tool/plan.ts +29 -5
  103. package/src/extension/team-tool/respond.ts +49 -16
  104. package/src/extension/team-tool/run-not-found.ts +3 -8
  105. package/src/extension/team-tool/run.ts +80 -317
  106. package/src/extension/team-tool/status.ts +135 -43
  107. package/src/extension/team-tool/workflow-manage.ts +92 -25
  108. package/src/extension/team-tool-types.ts +8 -1
  109. package/src/extension/team-tool.ts +142 -551
  110. package/src/extension/validate-resources.ts +39 -8
  111. package/src/hooks/registry.ts +66 -17
  112. package/src/hooks/types.ts +1 -1
  113. package/src/i18n.ts +25 -11
  114. package/src/observability/correlation.ts +17 -3
  115. package/src/observability/event-bus.ts +51 -56
  116. package/src/observability/event-to-metric.ts +117 -15
  117. package/src/observability/exporters/otlp-exporter.ts +56 -17
  118. package/src/observability/exporters/prometheus-exporter.ts +1 -1
  119. package/src/observability/metric-registry.ts +16 -4
  120. package/src/observability/metric-retention.ts +8 -2
  121. package/src/observability/metric-sink.ts +11 -3
  122. package/src/observability/metrics-primitives.ts +42 -9
  123. package/src/plugins/plugin-define.ts +2 -2
  124. package/src/plugins/plugin-registry.ts +25 -25
  125. package/src/plugins/plugins/index.ts +1 -1
  126. package/src/plugins/plugins/nextjs.ts +16 -16
  127. package/src/plugins/plugins/vite.ts +7 -11
  128. package/src/plugins/plugins/vitest.ts +6 -11
  129. package/src/runtime/adaptive-plan.ts +225 -40
  130. package/src/runtime/agent-control.ts +58 -15
  131. package/src/runtime/agent-memory.ts +15 -9
  132. package/src/runtime/agent-observability.ts +10 -2
  133. package/src/runtime/anchor-manager.ts +27 -25
  134. package/src/runtime/async-marker.ts +7 -1
  135. package/src/runtime/async-runner.ts +27 -23
  136. package/src/runtime/auto-summarize.ts +7 -13
  137. package/src/runtime/background-runner.ts +189 -251
  138. package/src/runtime/batch-barrier.ts +18 -16
  139. package/src/runtime/cancellation-token.ts +16 -6
  140. package/src/runtime/cancellation.ts +46 -8
  141. package/src/runtime/capability-inventory.ts +6 -4
  142. package/src/runtime/chain-parser.ts +44 -11
  143. package/src/runtime/chain-runner.ts +63 -69
  144. package/src/runtime/checkpoint.ts +12 -56
  145. package/src/runtime/child-pi.ts +343 -78
  146. package/src/runtime/coalesce-tasks.ts +268 -0
  147. package/src/runtime/code-summary.ts +71 -26
  148. package/src/runtime/compact-stages/index.ts +15 -5
  149. package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
  150. package/src/runtime/compact-stages/truncation-stage.ts +4 -1
  151. package/src/runtime/compaction-summary.ts +17 -10
  152. package/src/runtime/completion-guard.ts +33 -16
  153. package/src/runtime/crash-classification.ts +28 -7
  154. package/src/runtime/crash-recovery.ts +177 -37
  155. package/src/runtime/crew-agent-records.ts +193 -40
  156. package/src/runtime/crew-hooks.ts +9 -24
  157. package/src/runtime/cross-extension-rpc.ts +25 -23
  158. package/src/runtime/custom-tools/irc-tool.ts +43 -15
  159. package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
  160. package/src/runtime/delivery-coordinator.ts +34 -7
  161. package/src/runtime/delta-conflict.ts +9 -21
  162. package/src/runtime/deterministic-ast.ts +1 -1
  163. package/src/runtime/diagnostic-export.ts +53 -20
  164. package/src/runtime/direct-run.ts +12 -2
  165. package/src/runtime/dwf-state-store.ts +1 -1
  166. package/src/runtime/dynamic-workflow-context.ts +186 -58
  167. package/src/runtime/dynamic-workflow-runner.ts +42 -20
  168. package/src/runtime/effectiveness.ts +16 -8
  169. package/src/runtime/errors/crew-errors.ts +7 -11
  170. package/src/runtime/event-stream-bridge.ts +9 -3
  171. package/src/runtime/foreground-control.ts +54 -14
  172. package/src/runtime/foreground-watchdog.ts +9 -6
  173. package/src/runtime/goal-achievement.ts +27 -10
  174. package/src/runtime/goal-evaluator.ts +54 -19
  175. package/src/runtime/goal-loop-runner.ts +280 -99
  176. package/src/runtime/goal-state-store.ts +27 -17
  177. package/src/runtime/green-contract.ts +11 -2
  178. package/src/runtime/group-join.ts +64 -31
  179. package/src/runtime/handoff-manager.ts +37 -42
  180. package/src/runtime/heartbeat-gradient.ts +10 -2
  181. package/src/runtime/heartbeat-watcher.ts +32 -6
  182. package/src/runtime/hidden-handoff.ts +12 -30
  183. package/src/runtime/important-line-classifier.ts +12 -2
  184. package/src/runtime/iteration-hooks.ts +25 -15
  185. package/src/runtime/live-agent-control.ts +55 -7
  186. package/src/runtime/live-agent-manager.ts +130 -27
  187. package/src/runtime/live-control-realtime.ts +23 -3
  188. package/src/runtime/live-irc.ts +4 -1
  189. package/src/runtime/live-session-health.ts +12 -4
  190. package/src/runtime/live-session-runtime.ts +379 -117
  191. package/src/runtime/manifest-cache.ts +28 -12
  192. package/src/runtime/mcp-proxy.ts +8 -16
  193. package/src/runtime/metric-parser.ts +1 -5
  194. package/src/runtime/model-fallback.ts +55 -18
  195. package/src/runtime/model-resolver.ts +2 -6
  196. package/src/runtime/model-scope.ts +19 -3
  197. package/src/runtime/notebook-helpers.ts +60 -62
  198. package/src/runtime/orphan-worker-registry.ts +37 -26
  199. package/src/runtime/output-validator.ts +18 -3
  200. package/src/runtime/overflow-recovery.ts +5 -4
  201. package/src/runtime/parallel-research.ts +29 -5
  202. package/src/runtime/parallel-utils.ts +9 -11
  203. package/src/runtime/path-overlap.ts +150 -0
  204. package/src/runtime/peer-dep.ts +12 -17
  205. package/src/runtime/per-write-validator.ts +1 -3
  206. package/src/runtime/phase-tracker.ts +342 -330
  207. package/src/runtime/pi-args.ts +26 -8
  208. package/src/runtime/pi-json-output.ts +1 -1
  209. package/src/runtime/pi-spawn.ts +30 -19
  210. package/src/runtime/pipeline-runner.ts +56 -55
  211. package/src/runtime/plan-templates.ts +5 -6
  212. package/src/runtime/policy-engine.ts +43 -7
  213. package/src/runtime/post-checks.ts +12 -4
  214. package/src/runtime/post-exit-stdio-guard.ts +2 -2
  215. package/src/runtime/process-lifecycle.ts +20 -10
  216. package/src/runtime/process-status.ts +16 -5
  217. package/src/runtime/progress-event-coalescer.ts +2 -1
  218. package/src/runtime/progress-tracker.ts +103 -103
  219. package/src/runtime/prose-compressor.ts +9 -11
  220. package/src/runtime/recovery-recipes.ts +118 -24
  221. package/src/runtime/replace.ts +25 -10
  222. package/src/runtime/resilient-edit.ts +10 -25
  223. package/src/runtime/result-extractor.ts +1 -2
  224. package/src/runtime/retry-executor.ts +20 -4
  225. package/src/runtime/retry-runner.ts +26 -50
  226. package/src/runtime/role-permission.ts +6 -1
  227. package/src/runtime/run-coalesced-task-group.ts +256 -0
  228. package/src/runtime/run-drift.ts +14 -15
  229. package/src/runtime/run-tracker.ts +6 -28
  230. package/src/runtime/runtime-policy.ts +1 -6
  231. package/src/runtime/runtime-resolver.ts +80 -15
  232. package/src/runtime/scheduler.ts +47 -18
  233. package/src/runtime/semaphore.ts +5 -7
  234. package/src/runtime/sensitive-paths.ts +2 -1
  235. package/src/runtime/session-usage.ts +1 -1
  236. package/src/runtime/settings-store.ts +16 -12
  237. package/src/runtime/sidechain-output.ts +6 -2
  238. package/src/runtime/single-agent-compose.ts +1 -4
  239. package/src/runtime/skill-effectiveness.ts +29 -97
  240. package/src/runtime/skill-instructions.ts +40 -83
  241. package/src/runtime/stale-reconciler.ts +73 -197
  242. package/src/runtime/stream-preview.ts +1 -1
  243. package/src/runtime/streaming-output.ts +1 -1
  244. package/src/runtime/subagent-manager.ts +86 -169
  245. package/src/runtime/subprocess-tool-registry.ts +4 -1
  246. package/src/runtime/supervisor-contact.ts +10 -5
  247. package/src/runtime/task-display.ts +19 -5
  248. package/src/runtime/task-graph-scheduler.ts +95 -21
  249. package/src/runtime/task-graph.ts +5 -11
  250. package/src/runtime/task-health.ts +54 -47
  251. package/src/runtime/task-id.ts +11 -18
  252. package/src/runtime/task-output-context.ts +265 -81
  253. package/src/runtime/task-packet.ts +12 -20
  254. package/src/runtime/task-quality.ts +6 -14
  255. package/src/runtime/task-runner/context-retrieval.ts +4 -13
  256. package/src/runtime/task-runner/live-executor.ts +114 -36
  257. package/src/runtime/task-runner/output-splitter.ts +152 -0
  258. package/src/runtime/task-runner/progress.ts +50 -12
  259. package/src/runtime/task-runner/prompt-builder.ts +31 -7
  260. package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
  261. package/src/runtime/task-runner/result-utils.ts +3 -1
  262. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  263. package/src/runtime/task-runner/run-projection.ts +27 -8
  264. package/src/runtime/task-runner/state-helpers.ts +29 -8
  265. package/src/runtime/task-runner/tail-read.ts +2 -6
  266. package/src/runtime/task-runner.ts +180 -326
  267. package/src/runtime/team-runner-artifacts.ts +13 -0
  268. package/src/runtime/team-runner.ts +456 -974
  269. package/src/runtime/tool-output-pruner.ts +6 -9
  270. package/src/runtime/tool-progress.ts +11 -21
  271. package/src/runtime/verification-gates.ts +33 -24
  272. package/src/runtime/verification-integrity.ts +1 -4
  273. package/src/runtime/verification-worktree.ts +62 -12
  274. package/src/runtime/worker-heartbeat.ts +5 -1
  275. package/src/runtime/worker-startup.ts +29 -5
  276. package/src/runtime/workflow-state.ts +17 -9
  277. package/src/runtime/workspace-lock.ts +30 -35
  278. package/src/runtime/workspace-tree.ts +20 -32
  279. package/src/runtime/yield-handler.ts +43 -9
  280. package/src/runtime/zombie-scanner.ts +5 -4
  281. package/src/schema/config-schema.ts +266 -172
  282. package/src/schema/team-tool-schema.ts +29 -74
  283. package/src/schema/validation-types.ts +25 -17
  284. package/src/skills/discover-skills.ts +35 -10
  285. package/src/skills/skill-templates.ts +109 -27
  286. package/src/skills/validate.ts +26 -8
  287. package/src/state/active-run-registry.ts +87 -28
  288. package/src/state/artifact-store.ts +9 -5
  289. package/src/state/atomic-write-v2.ts +85 -63
  290. package/src/state/atomic-write.ts +105 -26
  291. package/src/state/blob-store.ts +47 -20
  292. package/src/state/contracts.ts +20 -5
  293. package/src/state/crew-init.ts +5 -22
  294. package/src/state/decision-ledger.ts +19 -73
  295. package/src/state/event-log-rotation.ts +41 -15
  296. package/src/state/event-log.ts +168 -53
  297. package/src/state/event-reconstructor.ts +11 -1
  298. package/src/state/gitignore-manager.ts +2 -8
  299. package/src/state/health-store.ts +57 -57
  300. package/src/state/hook-instinct-bridge.ts +1 -1
  301. package/src/state/hook-integrations.ts +1 -1
  302. package/src/state/instinct-store.ts +17 -5
  303. package/src/state/jsonl-writer.ts +1 -1
  304. package/src/state/locks.ts +23 -9
  305. package/src/state/mailbox.ts +151 -28
  306. package/src/state/observation-store.ts +20 -14
  307. package/src/state/run-cache.ts +142 -135
  308. package/src/state/run-graph.ts +6 -15
  309. package/src/state/run-metrics.ts +5 -18
  310. package/src/state/schedule.ts +15 -9
  311. package/src/state/state-store.ts +129 -45
  312. package/src/state/task-claims.ts +12 -2
  313. package/src/state/tiered-eval.ts +52 -43
  314. package/src/state/types-eval.ts +2 -2
  315. package/src/state/types.ts +24 -20
  316. package/src/state/usage.ts +20 -4
  317. package/src/state/worker-atomic-writer.ts +6 -3
  318. package/src/subagents/index.ts +2 -2
  319. package/src/teams/discover-teams.ts +21 -6
  320. package/src/tools/safe-bash-extension.ts +5 -6
  321. package/src/tools/safe-bash.ts +10 -11
  322. package/src/types/new-api-types.ts +6 -10
  323. package/src/ui/agent-management-overlay.ts +52 -40
  324. package/src/ui/card-colors.ts +13 -4
  325. package/src/ui/crew-footer.ts +8 -7
  326. package/src/ui/crew-select-list.ts +1 -1
  327. package/src/ui/dashboard-panes/agents-pane.ts +41 -25
  328. package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
  329. package/src/ui/dashboard-panes/capability-pane.ts +32 -15
  330. package/src/ui/dashboard-panes/health-pane.ts +2 -1
  331. package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
  332. package/src/ui/dashboard-panes/progress-pane.ts +12 -9
  333. package/src/ui/heartbeat-aggregator.ts +15 -4
  334. package/src/ui/keybinding-map.ts +40 -7
  335. package/src/ui/live-conversation-overlay.ts +36 -20
  336. package/src/ui/live-duration.ts +1 -4
  337. package/src/ui/live-run-sidebar.ts +88 -25
  338. package/src/ui/loaders.ts +2 -8
  339. package/src/ui/mascot.ts +20 -36
  340. package/src/ui/overlays/agent-picker-overlay.ts +11 -3
  341. package/src/ui/overlays/confirm-overlay.ts +4 -2
  342. package/src/ui/overlays/help-overlay.ts +25 -14
  343. package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
  344. package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
  345. package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
  346. package/src/ui/pi-ui-compat.ts +7 -7
  347. package/src/ui/powerbar-publisher.ts +120 -42
  348. package/src/ui/render-diff.ts +10 -3
  349. package/src/ui/render-scheduler.ts +12 -4
  350. package/src/ui/run-action-dispatcher.ts +81 -18
  351. package/src/ui/run-dashboard.ts +172 -76
  352. package/src/ui/run-event-bus.ts +59 -37
  353. package/src/ui/run-snapshot-cache.ts +276 -86
  354. package/src/ui/settings-overlay.ts +361 -74
  355. package/src/ui/status-colors.ts +12 -1
  356. package/src/ui/syntax-highlight.ts +1 -1
  357. package/src/ui/theme-adapter.ts +16 -14
  358. package/src/ui/theme-discovery.ts +13 -2
  359. package/src/ui/tool-progress-formatter.ts +7 -7
  360. package/src/ui/tool-render.ts +128 -56
  361. package/src/ui/tool-renderers/brief-mode.ts +45 -27
  362. package/src/ui/tool-renderers/index.ts +109 -43
  363. package/src/ui/transcript-cache.ts +32 -6
  364. package/src/ui/transcript-entries.ts +25 -23
  365. package/src/ui/transcript-viewer.ts +78 -29
  366. package/src/ui/widget/index.ts +99 -40
  367. package/src/ui/widget/widget-formatters.ts +13 -6
  368. package/src/ui/widget/widget-model.ts +19 -8
  369. package/src/ui/widget/widget-renderer.ts +23 -13
  370. package/src/ui/widget/widget-types.ts +1 -1
  371. package/src/utils/bm25-search.ts +199 -199
  372. package/src/utils/conflict-detect.ts +22 -21
  373. package/src/utils/env-filter.ts +14 -7
  374. package/src/utils/file-coalescer.ts +5 -1
  375. package/src/utils/fingerprint.ts +3 -6
  376. package/src/utils/frontmatter.ts +3 -1
  377. package/src/utils/fs-watch.ts +2 -6
  378. package/src/utils/gh-protocol.ts +119 -44
  379. package/src/utils/git.ts +13 -15
  380. package/src/utils/guards.ts +2 -5
  381. package/src/utils/ids.ts +9 -2
  382. package/src/utils/incremental-reader.ts +14 -3
  383. package/src/utils/internal-error.ts +2 -1
  384. package/src/utils/names.ts +12 -3
  385. package/src/utils/paths.ts +49 -5
  386. package/src/utils/project-detector.ts +2 -2
  387. package/src/utils/redaction.ts +29 -19
  388. package/src/utils/resolve-shell.ts +9 -7
  389. package/src/utils/run-watcher-registry.ts +19 -31
  390. package/src/utils/safe-paths.ts +45 -24
  391. package/src/utils/scan-cache.ts +9 -2
  392. package/src/utils/session-utils.ts +2 -4
  393. package/src/utils/sleep.ts +12 -5
  394. package/src/utils/sse-parser.ts +5 -17
  395. package/src/utils/visual.ts +52 -32
  396. package/src/workflows/discover-workflows.ts +41 -109
  397. package/src/workflows/intermediate-store.ts +5 -21
  398. package/src/workflows/preflight-validator.ts +6 -33
  399. package/src/workflows/topology-analyzer.ts +5 -21
  400. package/src/workflows/workflow-config.ts +7 -6
  401. package/src/worktree/branch-freshness.ts +66 -8
  402. package/src/worktree/cleanup.ts +130 -20
  403. package/src/worktree/worktree-manager.ts +212 -69
  404. package/skills/artifact-analysis-loop/SKILL.md +0 -303
  405. package/skills/detection-pipeline-design/SKILL.md +0 -286
  406. package/skills/hunting-investigation-loop/SKILL.md +0 -402
  407. package/skills/incident-playbook-construction/SKILL.md +0 -384
  408. package/skills/security-review/SKILL.md +0 -561
  409. package/skills/threat-hypothesis-framework/SKILL.md +0 -176
  410. package/skills/ui-render-performance/SKILL.md +0 -58
  411. /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
  412. /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
  413. /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
  414. /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
  415. /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
  416. /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
  417. /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
  418. /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
  419. /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
  420. /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
  421. /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
  422. /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
  423. /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
  424. /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
  425. /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
  426. /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
  427. /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
  428. /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
  429. /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
  430. /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
  431. /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
  432. /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
@@ -2,6 +2,13 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import type { AgentConfig } from "../agents/agent-config.ts";
4
4
  import type { CrewLimitsConfig, CrewRuntimeConfig } from "../config/config.ts";
5
+ import { loadConfig } from "../config/config.ts";
6
+ import { errors } from "../errors.ts";
7
+ import { appendHookEvent, executeHook } from "../hooks/registry.ts";
8
+ import { writeArtifact } from "../state/artifact-store.ts";
9
+ import { appendEventAsync, appendEventBuffered, appendEventFireAndForget } from "../state/event-log.ts";
10
+ import { saveRunManifest } from "../state/state-store.ts";
11
+ import { createTaskClaim } from "../state/task-claims.ts";
5
12
  import type {
6
13
  ArtifactDescriptor,
7
14
  OperationTerminalEvidence,
@@ -12,21 +19,25 @@ import type {
12
19
  } from "../state/types.ts";
13
20
  import { logInternalError } from "../utils/internal-error.ts";
14
21
  import { resolveRealContainedPath } from "../utils/safe-paths.ts";
15
- import { errors } from "../errors.ts";
16
- import { writeArtifact } from "../state/artifact-store.ts";
17
- import { appendEventAsync, appendEventFireAndForget } from "../state/event-log.ts";
18
- import { saveRunManifest } from "../state/state-store.ts";
19
- import { createTaskClaim } from "../state/task-claims.ts";
20
- import {
21
- createWorkerHeartbeat,
22
- touchWorkerHeartbeat,
23
- } from "./worker-heartbeat.ts";
24
22
  import type { WorkflowStep } from "../workflows/workflow-config.ts";
23
+ import { captureWorktreeDiff, captureWorktreeDiffStat, prepareTaskWorkspace } from "../worktree/worktree-manager.ts";
24
+ import { reserveControlChannel } from "./agent-control.ts";
25
+ import { appendTaskAttentionEvent } from "./attention-events.ts";
26
+ import { buildSyntheticTerminalEvidence, cancellationReasonFromSignal } from "./cancellation.ts";
27
+ import { type ChildPiLifecycleEvent, runChildPi } from "./child-pi.ts";
28
+ import { extractCommandTrace } from "./command-trace.ts";
29
+ import { evaluateCompletionMutationGuard } from "./completion-guard.ts";
25
30
  import {
26
- captureWorktreeDiff,
27
- captureWorktreeDiffStat,
28
- prepareTaskWorkspace,
29
- } from "../worktree/worktree-manager.ts";
31
+ appendCrewAgentEvent,
32
+ appendCrewAgentOutput,
33
+ emptyCrewAgentProgress,
34
+ recordFromTask,
35
+ upsertCrewAgent,
36
+ } from "./crew-agent-records.ts";
37
+ import type { CrewAgentProgress, CrewRuntimeKind } from "./crew-agent-runtime.ts";
38
+ import { crewHooks } from "./crew-hooks.ts";
39
+ import { bridgeEventFromJsonEvent, registerStreamBridge } from "./event-stream-bridge.ts";
40
+ import { createVerificationEvidence } from "./green-contract.ts";
30
41
  import {
31
42
  buildConfiguredModelRouting,
32
43
  formatModelAttemptNote,
@@ -34,81 +45,31 @@ import {
34
45
  type ModelAttemptSummary,
35
46
  } from "./model-fallback.ts";
36
47
  import { readEnabledModelsPatterns } from "./model-scope.ts";
37
- import { loadConfig } from "../config/config.ts";
38
- import { tailReadWithLineSnap } from "./task-runner/tail-read.ts";
39
- import {
40
- parsePiJsonOutput,
41
- type ParsedPiJsonOutput,
42
- } from "./pi-json-output.ts";
43
- import { runChildPi, type ChildPiLifecycleEvent } from "./child-pi.ts";
44
- import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
45
- import { buildTaskPacket } from "./task-packet.ts";
46
- import { executeHook, appendHookEvent } from "../hooks/registry.ts";
47
- import { createVerificationEvidence } from "./green-contract.ts";
48
- import { executeVerificationCommands, computeGreenLevelFromResults } from "./verification-gates.ts";
49
- import { createStartupEvidence } from "./worker-startup.ts";
48
+ import { type OutputValidationResult, validateWorkerOutput } from "./output-validator.ts";
49
+ import { type ParsedPiJsonOutput, parsePiJsonOutput } from "./pi-json-output.ts";
50
+ import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "./progress-event-coalescer.ts";
50
51
  import { permissionForRole } from "./role-permission.ts";
51
- import { crewHooks } from "./crew-hooks.ts";
52
+ import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
53
+ import { parseSessionUsage } from "./session-usage.ts";
54
+ import { renderSkillInstructions } from "./skill-instructions.ts";
55
+ import { parseSupervisorContactFromLine, recordSupervisorContact } from "./supervisor-contact.ts";
52
56
  import {
53
57
  collectDependencyOutputContext,
54
58
  renderDependencyOutputContext,
55
59
  writeTaskInputsArtifact,
56
60
  writeTaskSharedOutput,
57
61
  } from "./task-output-context.ts";
58
- import {
59
- appendCrewAgentEvent,
60
- appendCrewAgentOutput,
61
- emptyCrewAgentProgress,
62
- recordFromTask,
63
- upsertCrewAgent,
64
- } from "./crew-agent-records.ts";
65
- import { reserveControlChannel } from "./agent-control.ts";
66
- import { parseSessionUsage } from "./session-usage.ts";
67
- import type {
68
- CrewAgentProgress,
69
- CrewRuntimeKind,
70
- } from "./crew-agent-runtime.ts";
71
- import {
72
- shouldAppendProgressEventUpdate,
73
- type ProgressEventSummary,
74
- } from "./progress-event-coalescer.ts";
75
- import {
76
- coordinationBridgeInstructions,
77
- renderTaskPrompt,
78
- } from "./task-runner/prompt-builder.ts";
79
- import { buildWorkerPromptPipeline } from "./task-runner/prompt-pipeline.ts";
62
+ import { buildTaskPacket } from "./task-packet.ts";
80
63
  import { buildWorkerCapabilityInventory } from "./task-runner/capabilities.ts";
81
- import {
82
- applyAgentProgressEvent,
83
- applyUsageToProgress,
84
- progressEventSummary,
85
- shouldFlushProgressEvent,
86
- } from "./task-runner/progress.ts";
87
- import { extractCommandTrace } from "./command-trace.ts";
88
- import {
89
- checkpointTask,
90
- persistSingleTaskUpdate,
91
- updateTask,
92
- } from "./task-runner/state-helpers.ts";
93
- import {
94
- cleanResultText,
95
- isFinalChildEvent,
96
- } from "./task-runner/result-utils.ts";
97
- import { evaluateCompletionMutationGuard } from "./completion-guard.ts";
98
- import {
99
- cancellationReasonFromSignal,
100
- buildSyntheticTerminalEvidence,
101
- } from "./cancellation.ts";
102
- import { appendTaskAttentionEvent } from "./attention-events.ts";
103
- import {
104
- parseSupervisorContactFromLine,
105
- recordSupervisorContact,
106
- } from "./supervisor-contact.ts";
107
- import {
108
- registerStreamBridge,
109
- bridgeEventFromJsonEvent,
110
- } from "./event-stream-bridge.ts";
111
- import { renderSkillInstructions } from "./skill-instructions.ts";
64
+ import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./task-runner/progress.ts";
65
+ import { coordinationBridgeInstructions, renderTaskPrompt } from "./task-runner/prompt-builder.ts";
66
+ import { buildWorkerPromptPipeline } from "./task-runner/prompt-pipeline.ts";
67
+ import { cleanResultText, isFinalChildEvent } from "./task-runner/result-utils.ts";
68
+ import { checkpointTask, persistSingleTaskUpdate, updateTask } from "./task-runner/state-helpers.ts";
69
+ import { tailReadWithLineSnap } from "./task-runner/tail-read.ts";
70
+ import { computeGreenLevelFromResults, executeVerificationCommands } from "./verification-gates.ts";
71
+ import { createWorkerHeartbeat, touchWorkerHeartbeat } from "./worker-heartbeat.ts";
72
+ import { createStartupEvidence } from "./worker-startup.ts";
112
73
  import {
113
74
  DEFAULT_YIELD_CONFIG,
114
75
  extractYieldResult,
@@ -117,10 +78,6 @@ import {
117
78
  registerYieldTool,
118
79
  type YieldResult,
119
80
  } from "./yield-handler.ts";
120
- import {
121
- validateWorkerOutput,
122
- type OutputValidationResult,
123
- } from "./output-validator.ts";
124
81
 
125
82
  // Register the submit_result tool handler so subprocess events can extract yield data.
126
83
  registerYieldTool();
@@ -155,9 +112,7 @@ export interface TaskRunnerInput {
155
112
  onJsonEvent?: (taskId: string, runId: string, event: unknown) => void;
156
113
  }
157
114
 
158
- export async function runTeamTask(
159
- input: TaskRunnerInput,
160
- ): Promise<{ manifest: TeamRunManifest; tasks: TeamTaskState[] }> {
115
+ export async function runTeamTask(input: TaskRunnerInput): Promise<{ manifest: TeamRunManifest; tasks: TeamTaskState[] }> {
161
116
  // Cold-start race fix: ensure the hot module graph is warm before touching
162
117
  // any module. Under tsx, concurrent first-imports race module-record
163
118
  // instantiation; awaiting the registration-time warmup eliminates the window.
@@ -183,15 +138,8 @@ export async function runTeamTask(
183
138
  cwd: workspace.cwd,
184
139
  worktreePath: worktree?.path,
185
140
  });
186
- const dependencyContext = collectDependencyOutputContext(
187
- manifest,
188
- input.tasks,
189
- input.task,
190
- input.step,
191
- );
192
- const dependencyContextText =
193
- input.dependencyContextText ??
194
- renderDependencyOutputContext(dependencyContext);
141
+ const dependencyContext = collectDependencyOutputContext(manifest, input.tasks, input.task, input.step);
142
+ const dependencyContextText = input.dependencyContextText ?? renderDependencyOutputContext(dependencyContext);
195
143
  let task: TeamTaskState = {
196
144
  ...input.task,
197
145
  cwd: workspace.cwd,
@@ -206,16 +154,10 @@ export async function runTeamTask(
206
154
  lifetimeUsage: { input: 0, output: 0, cacheWrite: 0 },
207
155
  ...(dependencyContextText ? { dependencyContextText } : {}),
208
156
  // Reserve control channel before spawn so cancel/steer can target this task immediately
209
- controlReservation: reserveControlChannel(
210
- input.task.id,
211
- manifest.runId,
212
- ),
157
+ controlReservation: reserveControlChannel(input.task.id, manifest.runId),
213
158
  } as TeamTaskState;
214
159
  let tasks = updateTask(input.tasks, task);
215
- const runtimeKind =
216
- input.taskRuntimeOverride ??
217
- input.runtimeKind ??
218
- (input.executeWorkers ? "child-process" : "scaffold");
160
+ const runtimeKind = input.taskRuntimeOverride ?? input.runtimeKind ?? (input.executeWorkers ? "child-process" : "scaffold");
219
161
  // FIX: Check signal before persisting state — if cancelled, skip the write.
220
162
  if (input.signal?.aborted) {
221
163
  const cancelReason = cancellationReasonFromSignal(input.signal);
@@ -231,13 +173,7 @@ export async function runTeamTask(
231
173
  };
232
174
  }
233
175
  tasks = persistSingleTaskUpdate(manifest, tasks, task, "started");
234
- if (runtimeKind === "child-process")
235
- ({ task, tasks } = checkpointTask(
236
- manifest,
237
- tasks,
238
- task,
239
- "started",
240
- ));
176
+ if (runtimeKind === "child-process") ({ task, tasks } = checkpointTask(manifest, tasks, task, "started"));
241
177
  upsertCrewAgent(manifest, recordFromTask(manifest, task, runtimeKind));
242
178
  await appendEventAsync(manifest.eventsPath, {
243
179
  type: "task.started",
@@ -271,7 +207,7 @@ export async function runTeamTask(
271
207
  teamRole: { skills: input.teamRoleSkills },
272
208
  step: input.step,
273
209
  override: input.skillOverride,
274
- runId: manifest.runId,
210
+ runId: manifest.runId,
275
211
  })
276
212
  : undefined;
277
213
  const skillBlock = input.skillBlock ?? renderedSkills?.block;
@@ -289,7 +225,7 @@ export async function runTeamTask(
289
225
  // follow it and execute a script outside cwd. Throws on escape.
290
226
  resolveRealContainedPath(manifest.cwd, input.step.preStepScript);
291
227
  try {
292
- // LAZY: defer dynamic import of node:child_process to its call site.
228
+ // LAZY: defer dynamic import of node:child_process to its call site.
293
229
  const { execFileSync } = await import("node:child_process");
294
230
  preStepOutput = execFileSync(input.step.preStepScript, scriptArgs, {
295
231
  timeout: scriptTimeout,
@@ -307,7 +243,20 @@ export async function runTeamTask(
307
243
  // pre-step output rather than aborting the task (advisory hooks).
308
244
  if (input.step.preStepOptional) {
309
245
  const warnMsg = `[preStepOptional] pre-step hook '${input.step.preStepScript}' failed (exit ${exitCode ?? "?"}) but preStepOptional=true; continuing without its output.`;
310
- try { appendEventFireAndForget(manifest.eventsPath, { type: "hook.pre_step_optional_failed", runId: manifest.runId, taskId: task.id, message: warnMsg, data: { script: input.step.preStepScript, exitCode: exitCode ?? null } }); } catch { /* best-effort event log */ }
246
+ try {
247
+ appendEventFireAndForget(manifest.eventsPath, {
248
+ type: "hook.pre_step_optional_failed",
249
+ runId: manifest.runId,
250
+ taskId: task.id,
251
+ message: warnMsg,
252
+ data: {
253
+ script: input.step.preStepScript,
254
+ exitCode: exitCode ?? null,
255
+ },
256
+ });
257
+ } catch {
258
+ /* best-effort event log */
259
+ }
311
260
  preStepOutput = undefined;
312
261
  } else {
313
262
  throw errors.preStepFailed(input.step.preStepScript, exitCode, msg);
@@ -315,18 +264,15 @@ export async function runTeamTask(
315
264
  }
316
265
  }
317
266
 
318
- const promptResult = await renderTaskPrompt(
319
- manifest,
320
- input.step,
321
- task,
322
- input.agent,
323
- skillBlock,
324
- );
267
+ const promptResult = await renderTaskPrompt(manifest, input.step, task, input.agent, skillBlock);
325
268
  let prompt = promptResult.full;
326
269
 
327
270
  // Inject deterministic pre-step output into prompt
328
271
  if (preStepOutput) {
329
- prompt += "\n\n---\n## Pre-Step Script Output\n\nThe following data was produced by a pre-step script. Use it as context for your task:\n\n<output>\n" + preStepOutput + "\n</output>\n";
272
+ prompt +=
273
+ "\n\n---\n## Pre-Step Script Output\n\nThe following data was produced by a pre-step script. Use it as context for your task:\n\n<output>\n" +
274
+ preStepOutput +
275
+ "\n</output>\n";
330
276
  }
331
277
  const promptArtifact = writeArtifact(manifest.artifactsRoot, {
332
278
  kind: "prompt",
@@ -342,7 +288,7 @@ export async function runTeamTask(
342
288
  let error: string | undefined;
343
289
  let modelAttempts: ModelAttemptSummary[] | undefined;
344
290
  let parsedOutput: ParsedPiJsonOutput | undefined;
345
- let rawFinalText: string | undefined;
291
+ let rawFinalText: string | undefined;
346
292
  let intermediateFindings: string | undefined;
347
293
  let finalStdout = "";
348
294
  let transcriptPath: string | undefined;
@@ -350,23 +296,14 @@ export async function runTeamTask(
350
296
  const collectedJsonEvents: Record<string, unknown>[] = [];
351
297
 
352
298
  let startupEvidence = createStartupEvidence({
353
- command:
354
- runtimeKind === "child-process"
355
- ? "pi"
356
- : runtimeKind === "live-session"
357
- ? "live-session"
358
- : "safe-scaffold",
299
+ command: runtimeKind === "child-process" ? "pi" : runtimeKind === "live-session" ? "live-session" : "safe-scaffold",
359
300
  startedAt: new Date(task.startedAt ?? new Date().toISOString()),
360
301
  finishedAt: new Date(),
361
302
  promptSentAt: new Date(task.startedAt ?? new Date().toISOString()),
362
303
  promptAccepted: true,
363
304
  exitCode: 0,
364
305
  });
365
- const inputsArtifact = writeTaskInputsArtifact(
366
- manifest,
367
- task,
368
- dependencyContext,
369
- );
306
+ const inputsArtifact = writeTaskInputsArtifact(manifest, task, dependencyContext);
370
307
  const skillArtifact = skillBlock
371
308
  ? writeArtifact(manifest.artifactsRoot, {
372
309
  kind: "metadata",
@@ -400,8 +337,7 @@ export async function runTeamTask(
400
337
  scopeModelsPatterns: await resolveTaskScopeModelsPatterns(task.cwd),
401
338
  });
402
339
  const candidates = modelRoutingPlan.candidates;
403
- const attemptModels =
404
- candidates.length > 0 ? candidates : [undefined];
340
+ const attemptModels = candidates.length > 0 ? candidates : [undefined];
405
341
  const logs: string[] = [];
406
342
  let finalStderr = "";
407
343
  modelAttempts = [];
@@ -431,26 +367,14 @@ export async function runTeamTask(
431
367
  // Now update in-memory heartbeat so it is always >= persisted state.
432
368
  task = {
433
369
  ...task,
434
- heartbeat: touchWorkerHeartbeat(
435
- task.heartbeat ?? createWorkerHeartbeat(task.id),
436
- ),
370
+ heartbeat: touchWorkerHeartbeat(task.heartbeat ?? createWorkerHeartbeat(task.id)),
437
371
  };
438
372
  lastHeartbeatPersistedAt = now;
439
373
  };
440
- const persistChildProgress = (
441
- event: unknown,
442
- force = false,
443
- ): void => {
374
+ const persistChildProgress = (event: unknown, force = false): void => {
444
375
  const now = Date.now();
445
- if (
446
- force ||
447
- shouldFlushProgressEvent(event) ||
448
- now - lastAgentRecordPersistedAt >= 500
449
- ) {
450
- upsertCrewAgent(
451
- manifest,
452
- recordFromTask(manifest, task, "child-process"),
453
- );
376
+ if (force || shouldFlushProgressEvent(event) || now - lastAgentRecordPersistedAt >= 500) {
377
+ upsertCrewAgent(manifest, recordFromTask(manifest, task, "child-process"));
454
378
  lastAgentRecordPersistedAt = now;
455
379
  }
456
380
  const summary = progressEventSummary(task, event);
@@ -464,9 +388,11 @@ export async function runTeamTask(
464
388
  });
465
389
  if (decision.shouldAppend) {
466
390
  // 2.2 caller migration: high-frequency task.progress goes through
467
- // the buffered path; loss-on-kill is acceptable because progress
391
+ // the buffered path (M7 wire); loss-on-kill is acceptable because progress
468
392
  // is informational and re-derivable from per-agent records.
469
- appendEventFireAndForget(manifest.eventsPath, {
393
+ // appendEventBuffered coalesces into a single lock acquire after bufferMs,
394
+ // reducing producer p95 from ~13µs (serial) to ~0µs (bench M7).
395
+ void appendEventBuffered(manifest.eventsPath, {
470
396
  type: "task.progress",
471
397
  runId: manifest.runId,
472
398
  taskId: task.id,
@@ -482,7 +408,9 @@ export async function runTeamTask(
482
408
  // Ensure transcripts/ subdirectory exists before child-pi appends
483
409
  // to it. appendTranscript uses O_APPEND (no mkdir) for security,
484
410
  // so the caller must create the directory.
485
- fs.mkdirSync(path.join(manifest.artifactsRoot, "transcripts"), { recursive: true });
411
+ fs.mkdirSync(path.join(manifest.artifactsRoot, "transcripts"), {
412
+ recursive: true,
413
+ });
486
414
  const model = attemptModels[i];
487
415
  const attemptStartedAt = new Date();
488
416
  const pendingAttempt: ModelAttemptSummary = {
@@ -494,11 +422,14 @@ export async function runTeamTask(
494
422
  modelAttempts: [...modelAttempts, pendingAttempt],
495
423
  };
496
424
  tasks = updateTask(tasks, task);
497
- crewHooks.emit({ type: "task_started", timestamp: new Date().toISOString(), runId: manifest.runId, taskId: task.id, data: { role: task.role, model: model ?? "default" } });
498
- upsertCrewAgent(
499
- manifest,
500
- recordFromTask(manifest, task, "child-process"),
501
- );
425
+ crewHooks.emit({
426
+ type: "task_started",
427
+ timestamp: new Date().toISOString(),
428
+ runId: manifest.runId,
429
+ taskId: task.id,
430
+ data: { role: task.role, model: model ?? "default" },
431
+ });
432
+ upsertCrewAgent(manifest, recordFromTask(manifest, task, "child-process"));
502
433
  const childResult = await runChildPi({
503
434
  cwd: task.cwd,
504
435
  task: prompt,
@@ -520,19 +451,20 @@ export async function runTeamTask(
520
451
  artifactsRoot: manifest.artifactsRoot,
521
452
  onSpawn: (pid) => {
522
453
  try {
523
- ({ task, tasks } = checkpointTask(
524
- manifest,
525
- tasks,
526
- task,
527
- "child-spawned",
528
- pid,
529
- ));
454
+ ({ task, tasks } = checkpointTask(manifest, tasks, task, "child-spawned", pid));
530
455
  if (task.pendingSteers?.length) {
531
456
  const steeringDir = `${manifest.artifactsRoot}/steering`;
532
457
  fs.mkdirSync(steeringDir, { recursive: true });
533
458
  const steeringPath = `${steeringDir}/${task.id}.jsonl`;
534
459
  for (const msg of task.pendingSteers) {
535
- fs.appendFileSync(steeringPath, JSON.stringify({ type: "steer", message: msg, ts: new Date().toISOString() }) + "\n");
460
+ fs.appendFileSync(
461
+ steeringPath,
462
+ JSON.stringify({
463
+ type: "steer",
464
+ message: msg,
465
+ ts: new Date().toISOString(),
466
+ }) + "\n",
467
+ );
536
468
  }
537
469
  task.pendingSteers = [];
538
470
  tasks = persistSingleTaskUpdate(manifest, tasks, task);
@@ -548,7 +480,9 @@ export async function runTeamTask(
548
480
  taskId: task.id,
549
481
  message: `Worker lifecycle: ${event.type}${event.error ? ` error=${event.error}` : ""}${event.exitCode != null ? ` exit=${event.exitCode}` : ""}`,
550
482
  data: { ...event },
551
- }).catch((error) => logInternalError("task-runner.lifecycle-event", error, `taskId=${task.id}, type=${event.type}`));
483
+ }).catch((error) =>
484
+ logInternalError("task-runner.lifecycle-event", error, `taskId=${task.id}, type=${event.type}`),
485
+ );
552
486
  },
553
487
  onStdoutLine: (line) => {
554
488
  appendCrewAgentOutput(manifest, task.id, line);
@@ -567,17 +501,11 @@ export async function runTeamTask(
567
501
  // Errors are logged but processing continues so subsequent events still update state.
568
502
  try {
569
503
  appendCrewAgentEvent(manifest, task.id, event);
570
- if (
571
- event &&
572
- typeof event === "object" &&
573
- !Array.isArray(event)
574
- )
575
- collectedJsonEvents.push(
576
- event as Record<string, unknown>,
577
- );
578
- if (collectedJsonEvents.length > 1000) {
579
- collectedJsonEvents.splice(0, collectedJsonEvents.length - 1000);
580
- }
504
+ if (event && typeof event === "object" && !Array.isArray(event))
505
+ collectedJsonEvents.push(event as Record<string, unknown>);
506
+ if (collectedJsonEvents.length > 1000) {
507
+ collectedJsonEvents.splice(0, collectedJsonEvents.length - 1000);
508
+ }
581
509
  // Accumulate lifetime usage via message_end events (survives compaction)
582
510
  if (event && typeof event === "object" && (event as Record<string, unknown>).type === "message_end") {
583
511
  const msg = (event as Record<string, unknown>).message as Record<string, unknown> | undefined;
@@ -597,7 +525,8 @@ export async function runTeamTask(
597
525
  // This supplements the event log so developers can see what the child Pi worker produced.
598
526
  if (process.env.PI_CREW_BACKGROUND_MODE === "1" && event) {
599
527
  const bgLogPath = `${manifest.stateRoot}/background.log`;
600
- const eventLine = typeof event === "object" && !Array.isArray(event) ? JSON.stringify(event) : String(event);
528
+ const eventLine =
529
+ typeof event === "object" && !Array.isArray(event) ? JSON.stringify(event) : String(event);
601
530
  fs.appendFileSync(bgLogPath, `${eventLine}\n`);
602
531
  }
603
532
  // Always keep in-memory agentProgress fresh (cheap) so the UI/events see
@@ -618,31 +547,15 @@ export async function runTeamTask(
618
547
  lastTaskProgressPersistedAt = progressNow;
619
548
  }
620
549
  // Bridge event to UI event bus for near-instant updates
621
- const bridgeEvent = bridgeEventFromJsonEvent(
622
- manifest.runId,
623
- task.id,
624
- event,
625
- );
550
+ const bridgeEvent = bridgeEventFromJsonEvent(manifest.runId, task.id, event);
626
551
  if (bridgeEvent) streamBridge?.handler(bridgeEvent);
627
552
  // Feed overflow recovery tracker
628
553
  if (input.onJsonEvent) {
629
- input.onJsonEvent(
630
- task.id,
631
- manifest.runId,
632
- event,
633
- );
554
+ input.onJsonEvent(task.id, manifest.runId, event);
634
555
  }
635
- if (
636
- !finalCheckpointWritten &&
637
- isFinalChildEvent(event)
638
- ) {
556
+ if (!finalCheckpointWritten && isFinalChildEvent(event)) {
639
557
  finalCheckpointWritten = true;
640
- ({ task, tasks } = checkpointTask(
641
- manifest,
642
- tasks,
643
- task,
644
- "child-stdout-final",
645
- ));
558
+ ({ task, tasks } = checkpointTask(manifest, tasks, task, "child-stdout-final"));
646
559
  }
647
560
  persistChildProgress(event);
648
561
  } catch (err) {
@@ -652,8 +565,7 @@ export async function runTeamTask(
652
565
  });
653
566
  const evidenceStatus = childResult.exitStatus?.cancelled
654
567
  ? "cancelled"
655
- : childResult.error ||
656
- (childResult.exitCode && childResult.exitCode !== 0)
568
+ : childResult.error || (childResult.exitCode && childResult.exitCode !== 0)
657
569
  ? "failed"
658
570
  : "completed";
659
571
  terminalEvidence = [
@@ -665,14 +577,10 @@ export async function runTeamTask(
665
577
  finishedAt: new Date().toISOString(),
666
578
  ...(input.signal?.aborted
667
579
  ? {
668
- reason: cancellationReasonFromSignal(
669
- input.signal,
670
- ),
580
+ reason: cancellationReasonFromSignal(input.signal),
671
581
  }
672
582
  : {}),
673
- ...(childResult.exitStatus
674
- ? { exitStatus: childResult.exitStatus }
675
- : {}),
583
+ ...(childResult.exitStatus ? { exitStatus: childResult.exitStatus } : {}),
676
584
  },
677
585
  ];
678
586
  if (evidenceStatus === "cancelled") {
@@ -682,13 +590,7 @@ export async function runTeamTask(
682
590
  code: "caller_cancelled" as const,
683
591
  message: "Worker cancelled.",
684
592
  };
685
- terminalEvidence.push(
686
- buildSyntheticTerminalEvidence(
687
- "tool",
688
- cancelReason,
689
- attemptStartedAt.toISOString(),
690
- ),
691
- );
593
+ terminalEvidence.push(buildSyntheticTerminalEvidence("tool", cancelReason, attemptStartedAt.toISOString()));
692
594
  await appendEventAsync(manifest.eventsPath, {
693
595
  type: "worker.cancelled",
694
596
  runId: manifest.runId,
@@ -702,8 +604,7 @@ export async function runTeamTask(
702
604
  startedAt: attemptStartedAt,
703
605
  finishedAt: new Date(),
704
606
  promptSentAt: attemptStartedAt,
705
- promptAccepted:
706
- childResult.exitCode === 0 && !childResult.error,
607
+ promptAccepted: childResult.exitCode === 0 && !childResult.error,
707
608
  stderr: childResult.stderr,
708
609
  error: childResult.error,
709
610
  exitCode: childResult.exitCode,
@@ -713,19 +614,14 @@ export async function runTeamTask(
713
614
  finalStderr = childResult.stderr;
714
615
  // Cap transcript read to MAX_TRANSCRIPT_BYTES to avoid OOM on huge transcripts.
715
616
  const MAX_TRANSCRIPT_PARSE_BYTES = 5 * 1024 * 1024;
716
- const transcriptText = tailReadWithLineSnap(
717
- transcriptPath,
718
- MAX_TRANSCRIPT_PARSE_BYTES,
719
- childResult.stdout,
720
- );
617
+ const transcriptText = tailReadWithLineSnap(transcriptPath, MAX_TRANSCRIPT_PARSE_BYTES, childResult.stdout);
721
618
  parsedOutput = parsePiJsonOutput(transcriptText);
722
619
  rawFinalText = childResult.rawFinalText;
723
620
  intermediateFindings = childResult.intermediateFindings;
724
621
  error =
725
622
  childResult.error ||
726
623
  (childResult.exitCode && childResult.exitCode !== 0
727
- ? childResult.stderr ||
728
- `Child Pi exited with ${childResult.exitCode}`
624
+ ? childResult.stderr || `Child Pi exited with ${childResult.exitCode}`
729
625
  : undefined);
730
626
  // E1/E7 (Round 15): when the child timed out, surface a structured
731
627
  // CrewError (E007) so users get a code + actionable help hint instead
@@ -802,31 +698,21 @@ export async function runTeamTask(
802
698
  if (error && modelAttempts.length > 1) {
803
699
  // E2/E1 (Round 15): structured CrewError (E008). Build via the factory so
804
700
  // the error carries a code + help hint; keep its .message as the task error.
805
- error = errors.modelExhausted(modelAttempts.map((a) => a.model), error).message;
701
+ error = errors.modelExhausted(
702
+ modelAttempts.map((a) => a.model),
703
+ error,
704
+ ).message;
806
705
  }
807
706
  // NEW-8 fix: register all attempt transcripts as artifacts, not just the used one.
808
707
  // Earlier failed attempts' transcripts exist on disk but were invisible to the artifact system.
809
- const successfulAttemptIndex = modelAttempts.findIndex(
810
- (attempt) => attempt.success,
811
- );
812
- const usedAttempt =
813
- successfulAttemptIndex === -1
814
- ? Math.max(0, modelAttempts.length - 1)
815
- : successfulAttemptIndex;
816
- for (
817
- let attemptIdx = 0;
818
- attemptIdx < modelAttempts.length;
819
- attemptIdx++
820
- ) {
708
+ const successfulAttemptIndex = modelAttempts.findIndex((attempt) => attempt.success);
709
+ const usedAttempt = successfulAttemptIndex === -1 ? Math.max(0, modelAttempts.length - 1) : successfulAttemptIndex;
710
+ for (let attemptIdx = 0; attemptIdx < modelAttempts.length; attemptIdx++) {
821
711
  if (attemptIdx === usedAttempt) continue;
822
712
  const tPath = `${manifest.artifactsRoot}/transcripts/${task.id}.attempt-${attemptIdx}.jsonl`;
823
713
  if (!fs.existsSync(tPath)) continue;
824
714
  const MAX_ATTEMPT_TRANSCRIPT = 5 * 1024 * 1024;
825
- const tContent = tailReadWithLineSnap(
826
- tPath,
827
- MAX_ATTEMPT_TRANSCRIPT,
828
- "",
829
- );
715
+ const tContent = tailReadWithLineSnap(tPath, MAX_ATTEMPT_TRANSCRIPT, "");
830
716
  if (tContent) {
831
717
  writeArtifact(manifest.artifactsRoot, {
832
718
  kind: "log",
@@ -862,9 +748,7 @@ export async function runTeamTask(
862
748
  ...logs,
863
749
  `finalExitCode=${exitCode ?? "null"}`,
864
750
  `jsonEvents=${parsedOutput?.jsonEvents ?? 0}`,
865
- parsedOutput?.usage
866
- ? `usage=${JSON.stringify(parsedOutput.usage)}`
867
- : "",
751
+ parsedOutput?.usage ? `usage=${JSON.stringify(parsedOutput.usage)}` : "",
868
752
  "",
869
753
  "STDOUT:",
870
754
  finalStdout,
@@ -874,12 +758,8 @@ export async function runTeamTask(
874
758
  ].join("\n"),
875
759
  producer: task.id,
876
760
  });
877
- const resolvedModel =
878
- modelAttempts[usedAttempt]?.model ?? candidates[0] ?? "default";
879
- const fallbackReason =
880
- usedAttempt > 0
881
- ? modelAttempts[usedAttempt - 1]?.error
882
- : undefined;
761
+ const resolvedModel = modelAttempts[usedAttempt]?.model ?? candidates[0] ?? "default";
762
+ const fallbackReason = usedAttempt > 0 ? modelAttempts[usedAttempt - 1]?.error : undefined;
883
763
  task = {
884
764
  ...task,
885
765
  modelRouting: {
@@ -895,9 +775,7 @@ export async function runTeamTask(
895
775
  // Safety net: transcriptPath may be undefined in edge cases (e.g., early exit before loop).
896
776
  // In practice it is always set inside the for loop above.
897
777
  const attemptFallback = `${manifest.artifactsRoot}/transcripts/${task.id}.attempt-${usedAttempt}.jsonl`;
898
- const sessionUsage = parseSessionUsage(
899
- transcriptPath ?? attemptFallback,
900
- );
778
+ const sessionUsage = parseSessionUsage(transcriptPath ?? attemptFallback);
901
779
  const effectiveUsage = parsedOutput?.usage ?? sessionUsage;
902
780
  if (effectiveUsage) {
903
781
  parsedOutput = {
@@ -907,25 +785,15 @@ export async function runTeamTask(
907
785
  task = {
908
786
  ...task,
909
787
  usage: effectiveUsage,
910
- agentProgress: applyUsageToProgress(
911
- task.agentProgress,
912
- effectiveUsage,
913
- ),
788
+ agentProgress: applyUsageToProgress(task.agentProgress, effectiveUsage),
914
789
  };
915
790
  tasks = updateTask(tasks, task);
916
- upsertCrewAgent(
917
- manifest,
918
- recordFromTask(manifest, task, "child-process"),
919
- );
791
+ upsertCrewAgent(manifest, recordFromTask(manifest, task, "child-process"));
920
792
  }
921
793
  // M2 fix: use attempt-relative path; cap content at MAX_TRANSCRIPT_ARTIFACT_BYTES.
922
794
  const MAX_TRANSCRIPT_ARTIFACT_BYTES = 5 * 1024 * 1024; // 5MB cap
923
795
  const attemptTranscriptPath = `${manifest.artifactsRoot}/transcripts/${task.id}.attempt-${usedAttempt}.jsonl`;
924
- const transcriptContent = tailReadWithLineSnap(
925
- attemptTranscriptPath,
926
- MAX_TRANSCRIPT_ARTIFACT_BYTES,
927
- "",
928
- );
796
+ const transcriptContent = tailReadWithLineSnap(attemptTranscriptPath, MAX_TRANSCRIPT_ARTIFACT_BYTES, "");
929
797
  if (transcriptContent) {
930
798
  transcriptArtifact = writeArtifact(manifest.artifactsRoot, {
931
799
  kind: "log",
@@ -941,17 +809,10 @@ export async function runTeamTask(
941
809
  ...(transcriptArtifact ? { transcriptArtifact } : {}),
942
810
  };
943
811
  tasks = updateTask(tasks, task);
944
- ({ task, tasks } = checkpointTask(
945
- manifest,
946
- tasks,
947
- task,
948
- "artifact-written",
949
- ));
812
+ ({ task, tasks } = checkpointTask(manifest, tasks, task, "artifact-written"));
950
813
  } else if (runtimeKind === "live-session") {
951
814
  // LAZY: live-executor is only needed for live-session runtime branches.
952
- const { runLiveTask } = await import(
953
- "./task-runner/live-executor.ts"
954
- );
815
+ const { runLiveTask } = await import("./task-runner/live-executor.ts");
955
816
  const live = await runLiveTask({
956
817
  manifest,
957
818
  tasks,
@@ -1016,14 +877,10 @@ export async function runTeamTask(
1016
877
  // only applies to live-session workers where submit_result is injected by the
1017
878
  // runtime. Skipping yield detection for child-process prevents every child
1018
879
  // worker from incorrectly being marked needs_attention.
1019
- const yieldEnabled =
1020
- runtimeKind !== "child-process" &&
1021
- (input.runtimeConfig?.yield?.enabled ?? DEFAULT_YIELD_CONFIG.enabled);
880
+ const yieldEnabled = runtimeKind !== "child-process" && (input.runtimeConfig?.yield?.enabled ?? DEFAULT_YIELD_CONFIG.enabled);
1022
881
  if (yieldEnabled && collectedJsonEvents.length > 0) {
1023
882
  if (hasYieldInOutput(collectedJsonEvents)) {
1024
- const yieldEvent = collectedJsonEvents.find((e) =>
1025
- isYieldEvent(e),
1026
- );
883
+ const yieldEvent = collectedJsonEvents.find((e) => isYieldEvent(e));
1027
884
  if (yieldEvent) {
1028
885
  _yieldResult = extractYieldResult(yieldEvent);
1029
886
  }
@@ -1033,8 +890,7 @@ export async function runTeamTask(
1033
890
  type: "task.needs_attention",
1034
891
  runId: manifest.runId,
1035
892
  taskId: task.id,
1036
- message:
1037
- "Worker completed without calling submit_result tool.",
893
+ message: "Worker completed without calling submit_result tool.",
1038
894
  data: {
1039
895
  activityState: "needs_attention",
1040
896
  reason: "no_yield",
@@ -1072,17 +928,13 @@ export async function runTeamTask(
1072
928
  })
1073
929
  : undefined;
1074
930
 
1075
- const mutationGuardMode =
1076
- input.runtimeConfig?.completionMutationGuard ?? "warn";
931
+ const mutationGuardMode = input.runtimeConfig?.completionMutationGuard ?? "warn";
1077
932
  const mutationGuard =
1078
933
  !error && mutationGuardMode !== "off"
1079
934
  ? evaluateCompletionMutationGuard({
1080
935
  role: task.role,
1081
936
  taskText: `${task.title}\n${input.step.task}`,
1082
- transcriptPath:
1083
- runtimeKind === "child-process"
1084
- ? transcriptPath
1085
- : transcriptArtifact?.path,
937
+ transcriptPath: runtimeKind === "child-process" ? transcriptPath : transcriptArtifact?.path,
1086
938
  stdout: finalStdout,
1087
939
  })
1088
940
  : undefined;
@@ -1090,8 +942,7 @@ export async function runTeamTask(
1090
942
  appendTaskAttentionEvent({
1091
943
  manifest,
1092
944
  taskId: task.id,
1093
- message:
1094
- "Implementation-style task completed without an observed mutation tool call.",
945
+ message: "Implementation-style task completed without an observed mutation tool call.",
1095
946
  data: {
1096
947
  activityState: "needs_attention",
1097
948
  reason: "completion_guard",
@@ -1112,14 +963,11 @@ export async function runTeamTask(
1112
963
  },
1113
964
  };
1114
965
  if (mutationGuardMode === "fail") {
1115
- error =
1116
- "Completion mutation guard failed: implementation-style task completed without an observed mutation tool call.";
966
+ error = "Completion mutation guard failed: implementation-style task completed without an observed mutation tool call.";
1117
967
  exitCode = exitCode === 0 ? 1 : exitCode;
1118
968
  if (modelAttempts?.length) {
1119
969
  modelAttempts = modelAttempts.map((attempt, index) =>
1120
- index === modelAttempts!.length - 1
1121
- ? { ...attempt, success: false, exitCode, error }
1122
- : attempt,
970
+ index === modelAttempts!.length - 1 ? { ...attempt, success: false, exitCode, error } : attempt,
1123
971
  );
1124
972
  }
1125
973
  }
@@ -1142,8 +990,7 @@ export async function runTeamTask(
1142
990
  data: {
1143
991
  valid: false,
1144
992
  formatMatch: outputValidation.formatMatch,
1145
- structurePreserved:
1146
- outputValidation.structurePreserved,
993
+ structurePreserved: outputValidation.structurePreserved,
1147
994
  issues: outputValidation.issues,
1148
995
  },
1149
996
  });
@@ -1188,22 +1035,23 @@ export async function runTeamTask(
1188
1035
  );
1189
1036
 
1190
1037
  // Compute observed green level from results
1191
- const observedGreenLevel = computeGreenLevelFromResults(
1192
- commandResults,
1193
- taskPacket.verification.requiredGreenLevel,
1194
- );
1038
+ const observedGreenLevel = computeGreenLevelFromResults(commandResults, taskPacket.verification.requiredGreenLevel);
1195
1039
 
1196
1040
  // Determine satisfaction based on green level
1197
1041
  const requiredLevel = taskPacket.verification.requiredGreenLevel;
1198
1042
  const satisfied =
1199
- observedGreenLevel === "none" ? false :
1200
- observedGreenLevel === "targeted" ? requiredLevel === "targeted" :
1201
- observedGreenLevel === "package" ? ["targeted", "package"].includes(requiredLevel) :
1202
- observedGreenLevel === "workspace" ? ["targeted", "package", "workspace"].includes(requiredLevel) :
1203
- observedGreenLevel === "merge_ready";
1043
+ observedGreenLevel === "none"
1044
+ ? false
1045
+ : observedGreenLevel === "targeted"
1046
+ ? requiredLevel === "targeted"
1047
+ : observedGreenLevel === "package"
1048
+ ? ["targeted", "package"].includes(requiredLevel)
1049
+ : observedGreenLevel === "workspace"
1050
+ ? ["targeted", "package", "workspace"].includes(requiredLevel)
1051
+ : observedGreenLevel === "merge_ready";
1204
1052
 
1205
- const allPassed = commandResults.every(r => r.status === "passed");
1206
- const failedCount = commandResults.filter(r => r.status === "failed").length;
1053
+ const allPassed = commandResults.every((r) => r.status === "passed");
1054
+ const failedCount = commandResults.filter((r) => r.status === "failed").length;
1207
1055
 
1208
1056
  verificationEvidence = {
1209
1057
  requiredGreenLevel: taskPacket.verification.requiredGreenLevel,
@@ -1242,14 +1090,9 @@ export async function runTeamTask(
1242
1090
  verification: verificationEvidence,
1243
1091
  resultArtifact,
1244
1092
  claim: undefined,
1245
- heartbeat: touchWorkerHeartbeat(
1246
- task.heartbeat ?? createWorkerHeartbeat(task.id),
1247
- { alive: false },
1248
- ),
1093
+ heartbeat: touchWorkerHeartbeat(task.heartbeat ?? createWorkerHeartbeat(task.id), { alive: false }),
1249
1094
  workerExitStatus: terminalEvidence.at(-1)?.exitStatus,
1250
- terminalEvidence: terminalEvidence.length
1251
- ? [...(task.terminalEvidence ?? []), ...terminalEvidence]
1252
- : task.terminalEvidence,
1095
+ terminalEvidence: terminalEvidence.length ? [...(task.terminalEvidence ?? []), ...terminalEvidence] : task.terminalEvidence,
1253
1096
  ...(logArtifact ? { logArtifact } : {}),
1254
1097
  ...(transcriptArtifact ? { transcriptArtifact } : {}),
1255
1098
  };
@@ -1266,7 +1109,14 @@ export async function runTeamTask(
1266
1109
  timestamp: task.finishedAt ?? new Date().toISOString(),
1267
1110
  runId: manifest.runId,
1268
1111
  taskId: task.id,
1269
- data: { status: task.status, role: task.role, error: task.error, exitCode: task.exitCode, usage: task.usage, commandTrace },
1112
+ data: {
1113
+ status: task.status,
1114
+ role: task.role,
1115
+ error: task.error,
1116
+ exitCode: task.exitCode,
1117
+ usage: task.usage,
1118
+ commandTrace,
1119
+ },
1270
1120
  });
1271
1121
 
1272
1122
  const packetArtifact = writeArtifact(manifest.artifactsRoot, {
@@ -1281,11 +1131,7 @@ export async function runTeamTask(
1281
1131
  content: `${JSON.stringify(task.verification, null, 2)}\n`,
1282
1132
  producer: task.id,
1283
1133
  });
1284
- const sharedOutputArtifact = writeTaskSharedOutput(
1285
- manifest,
1286
- input.step,
1287
- task,
1288
- );
1134
+ const sharedOutputArtifact = writeTaskSharedOutput(manifest, input.step, task);
1289
1135
  const startupArtifact = writeArtifact(manifest.artifactsRoot, {
1290
1136
  kind: "metadata",
1291
1137
  relativePath: `metadata/${task.id}.startup-evidence.json`,
@@ -1361,7 +1207,12 @@ export async function runTeamTask(
1361
1207
  });
1362
1208
 
1363
1209
  // Execute after_task_complete lifecycle hook (non-blocking)
1364
- const afterTaskReport = await executeHook("after_task_complete", { runId: manifest.runId, taskId: task.id, cwd: manifest.cwd, status: error ? "failed" : noYield ? "needs_attention" : "completed" });
1210
+ const afterTaskReport = await executeHook("after_task_complete", {
1211
+ runId: manifest.runId,
1212
+ taskId: task.id,
1213
+ cwd: manifest.cwd,
1214
+ status: error ? "failed" : noYield ? "needs_attention" : "completed",
1215
+ });
1365
1216
  appendHookEvent(manifest, afterTaskReport);
1366
1217
 
1367
1218
  return { manifest, tasks };
@@ -1443,7 +1294,10 @@ export function detectRetryableModelFailureFromOutput(parsed: ParsedPiJsonOutput
1443
1294
  if (!eventSource || eventSource.length === 0) return undefined;
1444
1295
  for (const candidate of eventSource) {
1445
1296
  if (!candidate || typeof candidate !== "object") continue;
1446
- const event = candidate as { stopReason?: unknown; errorMessage?: unknown };
1297
+ const event = candidate as {
1298
+ stopReason?: unknown;
1299
+ errorMessage?: unknown;
1300
+ };
1447
1301
  if (event.stopReason !== "error") continue;
1448
1302
  if (typeof event.errorMessage !== "string" || event.errorMessage.length === 0) continue;
1449
1303
  if (!isRetryableModelFailure(event.errorMessage)) continue;