pi-crew 0.9.16 → 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 +81 -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 +145 -47
  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 +44 -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
@@ -1,41 +1,59 @@
1
1
  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
+ import { resolveToolPolicy } from "../agents/agent-config.ts";
4
5
  import type { CrewRuntimeConfig } from "../config/config.ts";
5
- import type { TeamRunManifest, TeamTaskState, UsageState } from "../state/types.ts";
6
+ import { loadConfig } from "../config/config.ts";
7
+ import { DEFAULT_LIVE_SESSION } from "../config/defaults.ts";
6
8
  import { appendEvent } from "../state/event-log.ts";
7
- import { trackTaskUsage } from "./usage-tracker.ts";
8
- // NOTE: buildMemoryBlock is intentionally NOT imported here. The agent memory
9
- // block is injected via renderTaskPrompt().full (the USER prompt), which is
10
- // shared by both the child-pi path (no system prompt) and the live-session
11
- // path. Adding it to liveSystemPrompt() too duplicated the entire memory
12
- // block (up to 200 lines) in both the user and system prompts. Keep memory
13
- // in a single place: the shared user prompt. See G3 fix.
14
- import { createStreamingOutput, type StreamingOutputHandle } from "./streaming-output.ts";
15
- import { registerLiveAgent, disposeLiveAgentSession, terminateLiveAgent, updateLiveAgentStatus, trackLiveAgentToolStart, trackLiveAgentToolEnd, trackLiveAgentTurnEnd, trackLiveAgentResponseText, markLiveAgentCompleted } from "./live-agent-manager.ts";
9
+ import type { TeamRunManifest, TeamTaskState, UsageState } from "../state/types.ts";
10
+ import { logInternalError } from "../utils/internal-error.ts";
11
+ import { redactSecrets } from "../utils/redaction.ts";
12
+ import type { WorkflowStep } from "../workflows/workflow-config.ts";
13
+ import { createIrcTool } from "./custom-tools/irc-tool.ts";
14
+ import { createSubmitResultTool } from "./custom-tools/submit-result-tool.ts";
16
15
  import { applyLiveAgentControlRequest, applyLiveAgentControlRequests, type LiveAgentControlCursor } from "./live-agent-control.ts";
16
+ import {
17
+ disposeLiveAgentSession,
18
+ listLiveAgents,
19
+ markLiveAgentCompleted,
20
+ registerLiveAgent,
21
+ terminateLiveAgent,
22
+ trackLiveAgentResponseText,
23
+ trackLiveAgentToolEnd,
24
+ trackLiveAgentToolStart,
25
+ trackLiveAgentTurnEnd,
26
+ updateLiveAgentStatus,
27
+ } from "./live-agent-manager.ts";
17
28
  import { subscribeLiveControlRealtime } from "./live-control-realtime.ts";
18
- import { eventToSidechainType, sidechainOutputPath, writeSidechainEntry } from "./sidechain-output.ts";
19
- import type { WorkflowStep } from "../workflows/workflow-config.ts";
20
- import { isLiveSessionRuntimeAvailable } from "./runtime-resolver.ts";
21
- import { redactSecrets } from "../utils/redaction.ts";
29
+ import { buildExtensionBridge } from "./live-extension-bridge.ts";
30
+ import { collectLiveSessionHealth, formatLiveSessionDiagnostics, type LiveSessionHealth } from "./live-session-health.ts";
31
+ import { buildMcpProxyFromSession } from "./mcp-proxy.ts";
22
32
  import { buildConfiguredModelRouting } from "./model-fallback.ts";
23
33
  import { readEnabledModelsPatterns } from "./model-scope.ts";
24
- import { resolveToolPolicy } from "../agents/agent-config.ts";
25
- import { loadConfig } from "../config/config.ts";
34
+ import { isLiveSessionRuntimeAvailable } from "./runtime-resolver.ts";
26
35
  import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
27
- import { DEFAULT_LIVE_SESSION } from "../config/defaults.ts";
28
- import { buildYieldReminder, hasYieldInOutput, isYieldEvent, extractYieldResult, validateYieldData, DEFAULT_YIELD_CONFIG, type YieldResult } from "./yield-handler.ts";
29
- import { buildMcpProxyFromSession } from "./mcp-proxy.ts";
30
- import { createSubmitResultTool } from "./custom-tools/submit-result-tool.ts";
31
- import { createIrcTool } from "./custom-tools/irc-tool.ts";
32
- import { buildExtensionBridge } from "./live-extension-bridge.ts";
33
- import { logInternalError } from "../utils/internal-error.ts";
34
36
  // prose-compressor imported for custom tool descriptions below;
35
37
  // tool description compression for SDK-managed tools awaits SDK support.
36
38
  import { buildSensitivePathConstraint } from "./sensitive-paths.ts";
37
- import { collectLiveSessionHealth, formatLiveSessionDiagnostics, type LiveSessionHealth } from "./live-session-health.ts";
38
- import { listLiveAgents } from "./live-agent-manager.ts";
39
+ import { eventToSidechainType, sidechainOutputPath, writeSidechainEntry } from "./sidechain-output.ts";
40
+ // NOTE: buildMemoryBlock is intentionally NOT imported here. The agent memory
41
+ // block is injected via renderTaskPrompt().full (the USER prompt), which is
42
+ // shared by both the child-pi path (no system prompt) and the live-session
43
+ // path. Adding it to liveSystemPrompt() too duplicated the entire memory
44
+ // block (up to 200 lines) in both the user and system prompts. Keep memory
45
+ // in a single place: the shared user prompt. See G3 fix.
46
+ import { createStreamingOutput, type StreamingOutputHandle } from "./streaming-output.ts";
47
+ import { trackTaskUsage } from "./usage-tracker.ts";
48
+ import {
49
+ buildYieldReminder,
50
+ DEFAULT_YIELD_CONFIG,
51
+ extractYieldResult,
52
+ hasYieldInOutput,
53
+ isYieldEvent,
54
+ validateYieldData,
55
+ type YieldResult,
56
+ } from "./yield-handler.ts";
39
57
 
40
58
  /**
41
59
  * Module-scoped latch for the optional peer dependency import. When N
@@ -110,13 +128,16 @@ export interface LiveSessionPlannedResult {
110
128
  type LiveSessionModule = Record<string, unknown> & {
111
129
  createAgentSession?: (options?: Record<string, unknown>) => Promise<{ session: LiveSessionLike; modelFallbackMessage?: string }>;
112
130
  DefaultResourceLoader?: new (options: Record<string, unknown>) => { reload?: () => Promise<void> };
113
- SessionManager?: { inMemory?: (cwd?: string) => unknown; create?: (cwd?: string, sessionDir?: string) => unknown };
131
+ SessionManager?: {
132
+ inMemory?: (cwd?: string) => unknown;
133
+ create?: (cwd?: string, sessionDir?: string) => unknown;
134
+ };
114
135
  SettingsManager?: { create?: (cwd?: string, agentDir?: string) => unknown };
115
136
  getAgentDir?: () => string;
116
137
  };
117
138
 
118
139
  type LiveSessionLike = {
119
- subscribe?: (listener: (event: unknown) => void) => (() => void);
140
+ subscribe?: (listener: (event: unknown) => void) => () => void;
120
141
  prompt?: (text: string, options?: Record<string, unknown>) => Promise<void>;
121
142
  steer?: (text: string) => Promise<void>;
122
143
  abort?: () => Promise<void> | void;
@@ -135,7 +156,7 @@ function appendTranscript(filePath: string | undefined, event: unknown): void {
135
156
  }
136
157
 
137
158
  function asRecord(value: unknown): Record<string, unknown> | undefined {
138
- return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
159
+ return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;
139
160
  }
140
161
 
141
162
  function isString(value: unknown): value is string {
@@ -157,7 +178,7 @@ function extractMessageRole(obj: Record<string, unknown> | undefined): string |
157
178
  */
158
179
  function extractMessageUsage(obj: Record<string, unknown> | undefined): Record<string, unknown> | undefined {
159
180
  const message = obj?.message ? asRecord(obj.message) : undefined;
160
- return message?.usage && typeof message.usage === "object" ? message.usage as Record<string, unknown> : undefined;
181
+ return message?.usage && typeof message.usage === "object" ? (message.usage as Record<string, unknown>) : undefined;
161
182
  }
162
183
 
163
184
  /**
@@ -260,21 +281,18 @@ function modelFromRegistry(modelRegistry: unknown, modelId: string | undefined):
260
281
  * model (e.g. minimax/MiniMax-M3, zai/glm-5.2); otherwise returns the
261
282
  * raw `parentModel` unchanged so the caller surfaces E008.
262
283
  */
263
- export function resolveParentModelFromRegistry(
264
- modelRegistry: unknown,
265
- rawParentModel: unknown,
266
- ): string | undefined {
284
+ export function resolveParentModelFromRegistry(modelRegistry: unknown, rawParentModel: unknown): string | undefined {
267
285
  const raw = typeof rawParentModel === "string" ? rawParentModel.trim() : undefined;
268
286
  if (raw) {
269
287
  const candidate = raw.includes("/")
270
288
  ? raw
271
289
  : (() => {
272
- const m = modelFromRegistry(modelRegistry, raw);
273
- if (m && typeof m === "object" && "fullId" in m) {
274
- return String((m as { fullId?: unknown }).fullId ?? raw);
275
- }
276
- return undefined;
277
- })();
290
+ const m = modelFromRegistry(modelRegistry, raw);
291
+ if (m && typeof m === "object" && "fullId" in m) {
292
+ return String((m as { fullId?: unknown }).fullId ?? raw);
293
+ }
294
+ return undefined;
295
+ })();
278
296
  if (candidate && modelFromRegistry(modelRegistry, candidate)) return candidate;
279
297
  }
280
298
  const registry = modelRegistry as { getAvailable?: () => unknown[] } | undefined;
@@ -311,15 +329,16 @@ const ROLE_INTENSITY: Record<string, "lite" | "full" | "ultra"> = {
311
329
  function buildCommunicationStyle(role: string): string {
312
330
  const intensity = ROLE_INTENSITY[role] ?? "full";
313
331
  if (intensity === "lite") return "## Communication\nProfessional concise. No filler/hedging. Full sentences OK.";
314
- if (intensity === "ultra") return [
315
- "## Communication (ultra-compressed)",
316
- "Drop: articles, filler, hedging, pleasantries. Fragments OK.",
317
- "Pattern: [thing] [action] [reason].",
318
- "Code/paths/symbols: exact, never abbreviated. Errors quoted exact.",
319
- "Abbreviate prose words: DB/auth/config/req/res/fn/impl.",
320
- "Arrows for causality: X → Y. One word when one word enough.",
321
- "Security/destructive: write normal English. Resume compressed after.",
322
- ].join("\n");
332
+ if (intensity === "ultra")
333
+ return [
334
+ "## Communication (ultra-compressed)",
335
+ "Drop: articles, filler, hedging, pleasantries. Fragments OK.",
336
+ "Pattern: [thing] [action] [reason].",
337
+ "Code/paths/symbols: exact, never abbreviated. Errors quoted exact.",
338
+ "Abbreviate prose words: DB/auth/config/req/res/fn/impl.",
339
+ "Arrows for causality: X Y. One word when one word enough.",
340
+ "Security/destructive: write normal English. Resume compressed after.",
341
+ ].join("\n");
323
342
  return [
324
343
  "## Communication (compressed)",
325
344
  "Drop: articles (a/an/the), filler (just/really/basically/actually/simply), hedging, pleasantries.",
@@ -330,32 +349,36 @@ function buildCommunicationStyle(role: string): string {
330
349
  }
331
350
 
332
351
  function buildOutputContract(role: string): string {
333
- if (role === "explorer") return [
334
- "## Output Contract",
335
- "<path>:<line> `<symbol>` — <≤6 word note>",
336
- "Group: Defs: / Refs: / Callers: / Tests: / Sites:",
337
- "Zero hits \"No match.\"",
338
- "Last linetotals: N defs, M refs.",
339
- ].join("\n");
340
- if (role === "executor") return [
341
- "## Output Contract",
342
- "<path>:<line-range> — <change ≤10 words>.",
343
- "verified: <re-read OK | mismatch @ path:line>.",
344
- "Refusal tokens: too-big. / needs-confirm. / ambiguous. / regressed.",
345
- ].join("\n");
346
- if (role === "reviewer" || role === "security-reviewer") return [
347
- "## Output Contract",
348
- "<path>:<line>: <emoji> <severity>: <problem>. <fix>.",
349
- "Severity: 🔴 bug, 🟡 risk, 🔵 nit, ❓ question.",
350
- "Zero findings → \"No issues.\"",
351
- "Sorted: file order ascending line numbers.",
352
- ].join("\n");
353
- if (role === "verifier") return [
354
- "## Output Contract",
355
- "PASS: <what verified> — <evidence ≤20 words>.",
356
- "FAIL: <what failed> — <reason>. <expected vs actual>.",
357
- "Evidence: file paths, test output, or diffs.",
358
- ].join("\n");
352
+ if (role === "explorer")
353
+ return [
354
+ "## Output Contract",
355
+ "<path>:<line> `<symbol>` <≤6 word note>",
356
+ "Group: Defs: / Refs: / Callers: / Tests: / Sites:",
357
+ 'Zero hits"No match."',
358
+ "Last line → totals: N defs, M refs.",
359
+ ].join("\n");
360
+ if (role === "executor")
361
+ return [
362
+ "## Output Contract",
363
+ "<path>:<line-range> <change ≤10 words>.",
364
+ "verified: <re-read OK | mismatch @ path:line>.",
365
+ "Refusal tokens: too-big. / needs-confirm. / ambiguous. / regressed.",
366
+ ].join("\n");
367
+ if (role === "reviewer" || role === "security-reviewer")
368
+ return [
369
+ "## Output Contract",
370
+ "<path>:<line>: <emoji> <severity>: <problem>. <fix>.",
371
+ "Severity: 🔴 bug, 🟡 risk, 🔵 nit, ❓ question.",
372
+ 'Zero findings "No issues."',
373
+ "Sorted: file order → ascending line numbers.",
374
+ ].join("\n");
375
+ if (role === "verifier")
376
+ return [
377
+ "## Output Contract",
378
+ "PASS: <what verified> — <evidence ≤20 words>.",
379
+ "FAIL: <what failed> — <reason>. <expected vs actual>.",
380
+ "Evidence: file paths, test output, or diffs.",
381
+ ].join("\n");
359
382
  if (role === "writer") return "## Output Contract\nWrite clear documentation. Full sentences. No compression.";
360
383
  return ""; // planner, critic, analyst, test-engineer: no strict format
361
384
  }
@@ -397,7 +420,9 @@ export function liveSystemPrompt(input: LiveSessionSpawnInput): string {
397
420
  sensitiveConstraint,
398
421
  "",
399
422
  input.agent.systemPrompt || "Follow the user task exactly and report verification evidence.",
400
- ].filter(Boolean).join("\n");
423
+ ]
424
+ .filter(Boolean)
425
+ .join("\n");
401
426
  }
402
427
 
403
428
  function filterActiveTools(session: LiveSessionLike, agent: AgentConfig, role?: string): void {
@@ -411,7 +436,9 @@ function filterActiveTools(session: LiveSessionLike, agent: AgentConfig, role?:
411
436
  const policy = resolveToolPolicy(agent, role);
412
437
  const disallowed = policy.excludeTools?.length ? new Set(policy.excludeTools) : undefined;
413
438
  const allowed = policy.tools?.length ? new Set(policy.tools) : undefined;
414
- const active = session.getActiveToolNames().filter((name) => !recursiveTools.has(name) && (!disallowed || !disallowed.has(name)) && (!allowed || allowed.has(name)));
439
+ const active = session
440
+ .getActiveToolNames()
441
+ .filter((name) => !recursiveTools.has(name) && (!disallowed || !disallowed.has(name)) && (!allowed || allowed.has(name)));
415
442
  session.setActiveToolsByName(active);
416
443
  }
417
444
 
@@ -424,11 +451,16 @@ function usageFromStats(stats: unknown): UsageState | undefined {
424
451
  const cacheWrite = numberField(obj, ["cacheWrite", "cache_write"]);
425
452
  const cost = numberField(obj, ["cost"]);
426
453
  const turns = numberField(obj, ["turns", "turnCount", "turn_count"]);
427
- return [input, output, cacheRead, cacheWrite, cost, turns].some((value) => value !== undefined) ? { input, output, cacheRead, cacheWrite, cost, turns } : undefined;
454
+ return [input, output, cacheRead, cacheWrite, cost, turns].some((value) => value !== undefined)
455
+ ? { input, output, cacheRead, cacheWrite, cost, turns }
456
+ : undefined;
428
457
  }
429
458
 
430
459
  async function promptWithTimeout(session: LiveSessionLike, text: string, timeoutMs: number, label: string): Promise<boolean> {
431
- const promptPromise = session.prompt?.(text, { source: "api", expandPromptTemplates: false });
460
+ const promptPromise = session.prompt?.(text, {
461
+ source: "api",
462
+ expandPromptTemplates: false,
463
+ });
432
464
  if (!promptPromise) return false;
433
465
  let timer: ReturnType<typeof setTimeout> | undefined;
434
466
  try {
@@ -447,8 +479,15 @@ async function promptWithTimeout(session: LiveSessionLike, text: string, timeout
447
479
 
448
480
  export async function probeLiveSessionRuntime(): Promise<LiveSessionUnavailableResult | LiveSessionPlannedResult> {
449
481
  const availability = await isLiveSessionRuntimeAvailable();
450
- if (!availability.available) return { available: false, reason: availability.reason ?? "Live-session runtime is unavailable." };
451
- return { available: true, reason: "Live-session SDK exports are available. pi-crew can run in-process live agents when runtime.mode=live-session." };
482
+ if (!availability.available)
483
+ return {
484
+ available: false,
485
+ reason: availability.reason ?? "Live-session runtime is unavailable.",
486
+ };
487
+ return {
488
+ available: true,
489
+ reason: "Live-session SDK exports are available. pi-crew can run in-process live agents when runtime.mode=live-session.",
490
+ };
452
491
  }
453
492
 
454
493
  export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<LiveSessionRunResult> {
@@ -464,29 +503,91 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
464
503
  let customToolYieldResolved = false;
465
504
  if (process.env.PI_CREW_MOCK_LIVE_SESSION === "success") {
466
505
  const agentId = `${input.manifest.runId}:${input.task.id}`;
467
- const inherited = input.runtimeConfig?.inheritContext === true && input.parentContext ? ` with inherited context: ${input.parentContext}` : "";
468
- const event = { type: "message_end", message: { role: "assistant", content: [{ type: "text", text: `Mock live-session success for ${input.agent.name}${inherited}` }] } };
469
- const mockSession = { steer: async () => {}, prompt: async () => {}, abort: async () => {} };
470
- registerLiveAgent({ agentId, runId: input.manifest.runId, taskId: input.task.id, role: input.task.role, agent: input.agent?.name ?? "mock", description: "mock", session: mockSession, status: "running", workspaceId: input.workspaceId }, appendEvent, input.manifest.eventsPath);
506
+ const inherited =
507
+ input.runtimeConfig?.inheritContext === true && input.parentContext ? ` with inherited context: ${input.parentContext}` : "";
508
+ const event = {
509
+ type: "message_end",
510
+ message: {
511
+ role: "assistant",
512
+ content: [
513
+ {
514
+ type: "text",
515
+ text: `Mock live-session success for ${input.agent.name}${inherited}`,
516
+ },
517
+ ],
518
+ },
519
+ };
520
+ const mockSession = {
521
+ steer: async () => {},
522
+ prompt: async () => {},
523
+ abort: async () => {},
524
+ };
525
+ registerLiveAgent(
526
+ {
527
+ agentId,
528
+ runId: input.manifest.runId,
529
+ taskId: input.task.id,
530
+ role: input.task.role,
531
+ agent: input.agent?.name ?? "mock",
532
+ description: "mock",
533
+ session: mockSession,
534
+ status: "running",
535
+ workspaceId: input.workspaceId,
536
+ },
537
+ appendEvent,
538
+ input.manifest.eventsPath,
539
+ );
471
540
  appendTranscript(input.transcriptPath, event);
472
541
  const sidechainPath = sidechainOutputPath(input.manifest.stateRoot, input.task.id);
473
- writeSidechainEntry(sidechainPath, { agentId, type: "user", message: { role: "user", content: input.prompt }, cwd: input.task.cwd });
474
- writeSidechainEntry(sidechainPath, { agentId, type: "message", message: event, cwd: input.task.cwd });
542
+ writeSidechainEntry(sidechainPath, {
543
+ agentId,
544
+ type: "user",
545
+ message: { role: "user", content: input.prompt },
546
+ cwd: input.task.cwd,
547
+ });
548
+ writeSidechainEntry(sidechainPath, {
549
+ agentId,
550
+ type: "message",
551
+ message: event,
552
+ cwd: input.task.cwd,
553
+ });
475
554
  if (isCurrent()) input.onEvent?.(event);
476
555
  const stdout = `Mock live-session success for ${input.agent.name}${inherited}`;
477
556
  if (isCurrent()) input.onOutput?.(stdout);
478
557
  updateLiveAgentStatus(agentId, "completed");
479
558
  markLiveAgentCompleted(agentId);
480
- return { available: true, exitCode: 0, stdout, stderr: "", jsonEvents: 1 };
559
+ return {
560
+ available: true,
561
+ exitCode: 0,
562
+ stdout,
563
+ stderr: "",
564
+ jsonEvents: 1,
565
+ };
481
566
  }
482
567
  const availability = await isLiveSessionRuntimeAvailable();
483
- if (!availability.available) return { available: true, exitCode: 1, stdout: "", stderr: availability.reason ?? "Live-session runtime unavailable.", jsonEvents: 0, error: availability.reason };
568
+ if (!availability.available)
569
+ return {
570
+ available: true,
571
+ exitCode: 1,
572
+ stdout: "",
573
+ stderr: availability.reason ?? "Live-session runtime unavailable.",
574
+ jsonEvents: 0,
575
+ error: availability.reason,
576
+ };
484
577
  // LAZY: optional peer dependency — only loaded when live-session runtime is
485
578
  // chosen. Goes through the module-scoped latch (loadLiveSessionModule) so
486
579
  // concurrent first-imports share ONE in-flight promise instead of racing
487
580
  // module-record instantiation under the tsx loader.
488
581
  const mod = await loadLiveSessionModule();
489
- if (typeof mod.createAgentSession !== "function") return { available: true, exitCode: 1, stdout: "", stderr: "createAgentSession export is unavailable.", jsonEvents: 0, error: "createAgentSession export is unavailable." };
582
+ if (typeof mod.createAgentSession !== "function")
583
+ return {
584
+ available: true,
585
+ exitCode: 1,
586
+ stdout: "",
587
+ stderr: "createAgentSession export is unavailable.",
588
+ jsonEvents: 0,
589
+ error: "createAgentSession export is unavailable.",
590
+ };
490
591
  let session: LiveSessionLike | undefined;
491
592
  let unsubscribe: (() => void) | undefined;
492
593
  let unsubscribeControlRealtime: (() => void) | undefined;
@@ -528,8 +629,19 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
528
629
  await (resourceLoader as { reload?: () => Promise<void> }).reload?.();
529
630
  }
530
631
  const effectiveParentModel = resolveParentModelFromRegistry(input.modelRegistry, input.parentModel);
531
- const modelRouting = buildConfiguredModelRouting({ overrideModel: input.modelOverride, stepModel: input.step.model, teamRoleModel: input.teamRoleModel, agentModel: input.agent.model, fallbackModels: input.agent.fallbackModels, parentModel: effectiveParentModel, modelRegistry: input.modelRegistry, cwd: input.manifest.cwd, scopeModelsPatterns: await resolveScopeModelsPatterns(input.manifest.cwd) });
532
- const resolvedModel = modelFromRegistry(input.modelRegistry, modelRouting.candidates[0] ?? modelRouting.requested) ?? input.parentModel;
632
+ const modelRouting = buildConfiguredModelRouting({
633
+ overrideModel: input.modelOverride,
634
+ stepModel: input.step.model,
635
+ teamRoleModel: input.teamRoleModel,
636
+ agentModel: input.agent.model,
637
+ fallbackModels: input.agent.fallbackModels,
638
+ parentModel: effectiveParentModel,
639
+ modelRegistry: input.modelRegistry,
640
+ cwd: input.manifest.cwd,
641
+ scopeModelsPatterns: await resolveScopeModelsPatterns(input.manifest.cwd),
642
+ });
643
+ const resolvedModel =
644
+ modelFromRegistry(input.modelRegistry, modelRouting.candidates[0] ?? modelRouting.requested) ?? input.parentModel;
533
645
  // Phase 4: MCP proxy — will be determined after session creation
534
646
  // (we check parent's MCP tools and share connections when available)
535
647
  const mcpProxy = buildMcpProxyFromSession([], { shareMcp: true });
@@ -547,8 +659,16 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
547
659
  cwd: input.task.cwd,
548
660
  ...(agentDir ? { agentDir } : {}),
549
661
  ...(resourceLoader ? { resourceLoader } : {}),
550
- ...(mod.SessionManager?.inMemory ? { sessionManager: mod.SessionManager.inMemory(input.task.cwd) } : {}),
551
- ...(mod.SettingsManager?.create && agentDir ? { settingsManager: mod.SettingsManager.create(input.task.cwd, agentDir) } : {}),
662
+ ...(mod.SessionManager?.inMemory
663
+ ? {
664
+ sessionManager: mod.SessionManager.inMemory(input.task.cwd),
665
+ }
666
+ : {}),
667
+ ...(mod.SettingsManager?.create && agentDir
668
+ ? {
669
+ settingsManager: mod.SettingsManager.create(input.task.cwd, agentDir),
670
+ }
671
+ : {}),
552
672
  ...(input.modelRegistry ? { modelRegistry: input.modelRegistry } : {}),
553
673
  ...(resolvedModel ? { model: resolvedModel } : {}),
554
674
  ...(input.agent.thinking ? { thinkingLevel: input.agent.thinking } : {}),
@@ -556,7 +676,15 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
556
676
  customTools,
557
677
  });
558
678
  session = created.session;
559
- appendEvent(input.manifest.eventsPath, { type: "live-session.session_created", runId: input.manifest.runId, taskId: input.task.id, data: { elapsedMs: Date.now() - sessionCreateStart, modelFallbackMessage: created.modelFallbackMessage } });
679
+ appendEvent(input.manifest.eventsPath, {
680
+ type: "live-session.session_created",
681
+ runId: input.manifest.runId,
682
+ taskId: input.task.id,
683
+ data: {
684
+ elapsedMs: Date.now() - sessionCreateStart,
685
+ modelFallbackMessage: created.modelFallbackMessage,
686
+ },
687
+ });
560
688
  filterActiveTools(session, input.agent, input.task.role);
561
689
 
562
690
  // Diagnostic: log before bindExtensions so we can identify extension-loading hangs
@@ -568,7 +696,15 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
568
696
  ]);
569
697
  } catch (bindError) {
570
698
  const msg = bindError instanceof Error ? bindError.message : String(bindError);
571
- appendEvent(input.manifest.eventsPath, { type: "live-session.bind_extensions_error", runId: input.manifest.runId, taskId: input.task.id, data: { elapsedMs: Date.now() - bindExtensionsStart, error: msg } });
699
+ appendEvent(input.manifest.eventsPath, {
700
+ type: "live-session.bind_extensions_error",
701
+ runId: input.manifest.runId,
702
+ taskId: input.task.id,
703
+ data: {
704
+ elapsedMs: Date.now() - bindExtensionsStart,
705
+ error: msg,
706
+ },
707
+ });
572
708
  // Continue without extensions — they should not block the session
573
709
  }
574
710
 
@@ -583,9 +719,17 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
583
719
  const extRunner = (session as Record<string, unknown>).extensionRunner;
584
720
  if (extRunner && typeof (extRunner as Record<string, unknown>).initialize === "function") {
585
721
  try {
586
- (extRunner as { initialize: (apis: unknown, host: unknown) => void }).initialize(extensionBridge.apis, extensionBridge.host);
722
+ (
723
+ extRunner as {
724
+ initialize: (apis: unknown, host: unknown) => void;
725
+ }
726
+ ).initialize(extensionBridge.apis, extensionBridge.host);
587
727
  if (typeof (extRunner as Record<string, unknown>).emit === "function") {
588
- await (extRunner as { emit: (event: unknown) => Promise<void> }).emit({ type: "session_start" });
728
+ await (
729
+ extRunner as {
730
+ emit: (event: unknown) => Promise<void>;
731
+ }
732
+ ).emit({ type: "session_start" });
589
733
  }
590
734
  } catch {
591
735
  // Extension runner initialization failure should not block the session
@@ -593,7 +737,22 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
593
737
  }
594
738
  }
595
739
 
596
- registerLiveAgent({ agentId, runId: input.manifest.runId, taskId: input.task.id, role: input.task.role, agent: input.agent?.name ?? "unknown", description: input.task.adaptive?.task ?? input.step?.task ?? "", modelName: (resolvedModel as { name?: string })?.name, session, status: "running", workspaceId: input.workspaceId }, appendEvent, input.manifest.eventsPath);
740
+ registerLiveAgent(
741
+ {
742
+ agentId,
743
+ runId: input.manifest.runId,
744
+ taskId: input.task.id,
745
+ role: input.task.role,
746
+ agent: input.agent?.name ?? "unknown",
747
+ description: input.task.adaptive?.task ?? input.step?.task ?? "",
748
+ modelName: (resolvedModel as { name?: string })?.name,
749
+ session,
750
+ status: "running",
751
+ workspaceId: input.workspaceId,
752
+ },
753
+ appendEvent,
754
+ input.manifest.eventsPath,
755
+ );
597
756
  streamOut = createStreamingOutput(input.manifest, input.task.id);
598
757
  let controlCursor: LiveAgentControlCursor = { offset: 0 };
599
758
  const seenControlRequestIds = new Set<string>();
@@ -602,14 +761,27 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
602
761
  if (!isCurrent() || controlBusy || !session) return;
603
762
  controlBusy = true;
604
763
  try {
605
- controlCursor = await applyLiveAgentControlRequests({ manifest: input.manifest, taskId: input.task.id, agentId, session, cursor: controlCursor, seenRequestIds: seenControlRequestIds });
764
+ controlCursor = await applyLiveAgentControlRequests({
765
+ manifest: input.manifest,
766
+ taskId: input.task.id,
767
+ agentId,
768
+ session,
769
+ cursor: controlCursor,
770
+ seenRequestIds: seenControlRequestIds,
771
+ });
606
772
  } finally {
607
773
  controlBusy = false;
608
774
  }
609
775
  };
610
776
  unsubscribeControlRealtime = subscribeLiveControlRealtime((request) => {
611
777
  if (!isCurrent() || request.runId !== input.manifest.runId || request.taskId !== input.task.id || !session) return;
612
- void applyLiveAgentControlRequest({ request, taskId: input.task.id, agentId, session, seenRequestIds: seenControlRequestIds });
778
+ void applyLiveAgentControlRequest({
779
+ request,
780
+ taskId: input.task.id,
781
+ agentId,
782
+ session,
783
+ seenRequestIds: seenControlRequestIds,
784
+ });
613
785
  });
614
786
  await pollControl();
615
787
  controlTimer = setInterval(() => {
@@ -620,14 +792,25 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
620
792
  const maxTurns = input.runtimeConfig?.maxTurns;
621
793
  const graceTurns = input.runtimeConfig?.graceTurns ?? 5;
622
794
  const sidechainPath = sidechainOutputPath(input.manifest.stateRoot, input.task.id);
623
- writeSidechainEntry(sidechainPath, { agentId, type: "user", message: { role: "user", content: input.prompt }, cwd: input.task.cwd });
795
+ writeSidechainEntry(sidechainPath, {
796
+ agentId,
797
+ type: "user",
798
+ message: { role: "user", content: input.prompt },
799
+ cwd: input.task.cwd,
800
+ });
624
801
  if (typeof session.subscribe === "function") {
625
802
  unsubscribe = session.subscribe((event) => {
626
803
  if (!isCurrent()) return;
627
804
  jsonEvents += 1;
628
805
  appendTranscript(input.transcriptPath, event);
629
806
  const sidechainType = eventToSidechainType(event);
630
- if (sidechainType) writeSidechainEntry(sidechainPath, { agentId, type: sidechainType, message: event, cwd: input.task.cwd });
807
+ if (sidechainType)
808
+ writeSidechainEntry(sidechainPath, {
809
+ agentId,
810
+ type: sidechainType,
811
+ message: event,
812
+ cwd: input.task.cwd,
813
+ });
631
814
  const obj = asRecord(event);
632
815
  if (obj?.type === "turn_end") {
633
816
  turnCount += 1;
@@ -670,24 +853,42 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
670
853
  // Phase 1: collect events for yield detection
671
854
  if (event && typeof event === "object" && !Array.isArray(event)) {
672
855
  collectedJsonEvents.push(event as Record<string, unknown>);
673
- if (collectedJsonEvents.length > maxCollectedJsonEvents) collectedJsonEvents.splice(0, collectedJsonEvents.length - maxCollectedJsonEvents);
856
+ if (collectedJsonEvents.length > maxCollectedJsonEvents)
857
+ collectedJsonEvents.splice(0, collectedJsonEvents.length - maxCollectedJsonEvents);
674
858
  }
675
859
  });
676
860
  }
677
861
  // Round 27 (BUG 4): named abort handler (removed in finally below).
678
- onSignalAbort = (): void => { void session?.abort?.(); };
862
+ onSignalAbort = (): void => {
863
+ void session?.abort?.();
864
+ };
679
865
  if (input.signal) {
680
866
  if (input.signal.aborted) await session.abort?.();
681
867
  // Round 27 (BUG 4): named handler so the finally block can remove it.
682
868
  // The previous anonymous listener leaked on normal completion (only
683
869
  // auto-removed by { once: true } AFTER the signal fires).
684
- else input.signal.addEventListener("abort", onSignalAbort, { once: true });
870
+ else
871
+ input.signal.addEventListener("abort", onSignalAbort, {
872
+ once: true,
873
+ });
685
874
  }
686
- const effectivePrompt = input.runtimeConfig?.inheritContext === true && input.parentContext ? `${input.parentContext}\n\n---\n# Live Subagent Task\n${input.prompt}` : input.prompt;
875
+ const effectivePrompt =
876
+ input.runtimeConfig?.inheritContext === true && input.parentContext
877
+ ? `${input.parentContext}\n\n---\n# Live Subagent Task\n${input.prompt}`
878
+ : input.prompt;
687
879
 
688
880
  // Diagnostic: log prompt size and timing
689
881
  const promptStart = Date.now();
690
- appendEvent(input.manifest.eventsPath, { type: "live-session.prompt_start", runId: input.manifest.runId, taskId: input.task.id, data: { promptLength: effectivePrompt.length, agent: input.agent.name, role: input.task.role } });
882
+ appendEvent(input.manifest.eventsPath, {
883
+ type: "live-session.prompt_start",
884
+ runId: input.manifest.runId,
885
+ taskId: input.task.id,
886
+ data: {
887
+ promptLength: effectivePrompt.length,
888
+ agent: input.agent.name,
889
+ role: input.task.role,
890
+ },
891
+ });
691
892
 
692
893
  // Phase 3: Wrap session.prompt with timeout for graceful cancellation
693
894
  const sessionTimeoutMs = DEFAULT_LIVE_SESSION.responseTimeoutMs;
@@ -695,20 +896,43 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
695
896
  await promptWithTimeout(session, effectivePrompt, sessionTimeoutMs, "Live-session");
696
897
  } catch (promptError) {
697
898
  const msg = promptError instanceof Error ? promptError.message : String(promptError);
698
- appendEvent(input.manifest.eventsPath, { type: "live-session.prompt_error", runId: input.manifest.runId, taskId: input.task.id, data: { elapsedMs: Date.now() - promptStart, error: msg } });
899
+ appendEvent(input.manifest.eventsPath, {
900
+ type: "live-session.prompt_error",
901
+ runId: input.manifest.runId,
902
+ taskId: input.task.id,
903
+ data: { elapsedMs: Date.now() - promptStart, error: msg },
904
+ });
699
905
  if (msg.includes("timed out")) {
700
906
  await session.abort?.();
701
907
  updateLiveAgentStatus(agentId, "failed");
702
- return { available: true, exitCode: 1, stdout: stdout.trim(), stderr: msg, jsonEvents, error: msg };
908
+ return {
909
+ available: true,
910
+ exitCode: 1,
911
+ stdout: stdout.trim(),
912
+ stderr: msg,
913
+ jsonEvents,
914
+ error: msg,
915
+ };
703
916
  }
704
917
  throw promptError;
705
918
  }
706
- appendEvent(input.manifest.eventsPath, { type: "live-session.prompt_done", runId: input.manifest.runId, taskId: input.task.id, data: { elapsedMs: Date.now() - promptStart, jsonEvents, outputLength: stdout.length } });
919
+ appendEvent(input.manifest.eventsPath, {
920
+ type: "live-session.prompt_done",
921
+ runId: input.manifest.runId,
922
+ taskId: input.task.id,
923
+ data: {
924
+ elapsedMs: Date.now() - promptStart,
925
+ jsonEvents,
926
+ outputLength: stdout.length,
927
+ },
928
+ });
707
929
 
708
930
  // --- Phase 1: Yield enforcement loop ---
709
931
  // After the initial prompt completes, check if the worker called submit_result.
710
932
  // Priority: 1) custom tool callback (G1), 2) JSON event detection (legacy).
711
- const yieldConfig = input.runtimeConfig?.yield ?? { enabled: DEFAULT_YIELD_CONFIG.enabled };
933
+ const yieldConfig = input.runtimeConfig?.yield ?? {
934
+ enabled: DEFAULT_YIELD_CONFIG.enabled,
935
+ };
712
936
  const yieldEnabled = yieldConfig.enabled !== false;
713
937
  if (yieldEnabled && session) {
714
938
  // Check custom tool callback first (G1)
@@ -733,7 +957,12 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
733
957
  customToolYieldResolved = false;
734
958
  const schemaReminder = `Your submit_result data did not match the required schema: ${validation.error}. Please fix and call submit_result again with valid data.`;
735
959
  try {
736
- await promptWithTimeout(session, schemaReminder, Math.min(sessionTimeoutMs, DEFAULT_LIVE_SESSION.idleWaitTimeoutMs), "Live-session schema reminder");
960
+ await promptWithTimeout(
961
+ session,
962
+ schemaReminder,
963
+ Math.min(sessionTimeoutMs, DEFAULT_LIVE_SESSION.idleWaitTimeoutMs),
964
+ "Live-session schema reminder",
965
+ );
737
966
  } catch {
738
967
  /* ignore */
739
968
  }
@@ -770,7 +999,12 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
770
999
  if (typeof session.setActiveToolsByName === "function" && prevTools.length > 0) {
771
1000
  session.setActiveToolsByName(["submit_result"]);
772
1001
  }
773
- await promptWithTimeout(session, reminder, Math.min(sessionTimeoutMs, DEFAULT_LIVE_SESSION.idleWaitTimeoutMs), "Live-session yield reminder");
1002
+ await promptWithTimeout(
1003
+ session,
1004
+ reminder,
1005
+ Math.min(sessionTimeoutMs, DEFAULT_LIVE_SESSION.idleWaitTimeoutMs),
1006
+ "Live-session yield reminder",
1007
+ );
774
1008
  } catch {
775
1009
  break;
776
1010
  } finally {
@@ -794,14 +1028,32 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
794
1028
  }
795
1029
  }
796
1030
  if (!customToolYieldResolved && !yieldResult && !input.signal?.aborted && retryCount >= maxReminders) {
797
- input.onEvent?.({ type: "task.attention", runId: input.manifest.runId, taskId: input.task.id, message: "Live-session worker completed without calling submit_result tool.", data: { activityState: "needs_attention", reason: "no_yield", attempts: retryCount } });
1031
+ input.onEvent?.({
1032
+ type: "task.attention",
1033
+ runId: input.manifest.runId,
1034
+ taskId: input.task.id,
1035
+ message: "Live-session worker completed without calling submit_result tool.",
1036
+ data: {
1037
+ activityState: "needs_attention",
1038
+ reason: "no_yield",
1039
+ attempts: retryCount,
1040
+ },
1041
+ });
798
1042
  }
799
1043
  }
800
1044
 
801
1045
  const usage = usageFromStats(typeof session.getStats === "function" ? session.getStats() : session.stats);
802
1046
  updateLiveAgentStatus(agentId, "completed");
803
1047
  markLiveAgentCompleted(agentId);
804
- return { available: true, exitCode: 0, stdout: stdout.trim(), stderr: created.modelFallbackMessage ?? "", jsonEvents, usage, yieldResult };
1048
+ return {
1049
+ available: true,
1050
+ exitCode: 0,
1051
+ stdout: stdout.trim(),
1052
+ stderr: created.modelFallbackMessage ?? "",
1053
+ jsonEvents,
1054
+ usage,
1055
+ yieldResult,
1056
+ };
805
1057
  } catch (error) {
806
1058
  const message = error instanceof Error ? error.message : String(error);
807
1059
 
@@ -810,13 +1062,23 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
810
1062
  const agents = listLiveAgents();
811
1063
  const health = collectLiveSessionHealth(agents, () => undefined);
812
1064
  const diagnostics = formatLiveSessionDiagnostics(health);
813
- input.onEvent?.({ type: "live-session.diagnostics", data: diagnostics });
1065
+ input.onEvent?.({
1066
+ type: "live-session.diagnostics",
1067
+ data: diagnostics,
1068
+ });
814
1069
  } catch (diagError) {
815
1070
  logInternalError("live-session.diagnostics", diagError);
816
1071
  }
817
1072
 
818
1073
  updateLiveAgentStatus(`${input.manifest.runId}:${input.task.id}`, "failed");
819
- return { available: true, exitCode: 1, stdout: stdout.trim(), stderr: message, jsonEvents, error: message };
1074
+ return {
1075
+ available: true,
1076
+ exitCode: 1,
1077
+ stdout: stdout.trim(),
1078
+ stderr: message,
1079
+ jsonEvents,
1080
+ error: message,
1081
+ };
820
1082
  } finally {
821
1083
  // H6: Unsubscribe listeners FIRST before clearing timer to prevent race
822
1084
  unsubscribe?.();