pi-crew 0.9.53 → 0.9.55

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 (493) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/package.json +6 -3
  3. package/scripts/clean-strip-types.mjs +60 -0
  4. package/src/adapters/claude-adapter.ts +23 -0
  5. package/src/adapters/codex-adapter.ts +21 -0
  6. package/src/adapters/cursor-adapter.ts +17 -0
  7. package/src/adapters/export-util.ts +143 -0
  8. package/src/adapters/index.ts +15 -0
  9. package/src/adapters/registry.ts +18 -0
  10. package/src/adapters/types.ts +23 -0
  11. package/src/agents/agent-config.ts +194 -0
  12. package/src/agents/agent-search.ts +98 -0
  13. package/src/agents/agent-serializer.ts +38 -0
  14. package/src/agents/discover-agents.ts +623 -0
  15. package/src/benchmark/benchmark-runner.ts +313 -0
  16. package/src/benchmark/feedback-loop.ts +73 -0
  17. package/src/config/config.ts +1270 -0
  18. package/src/config/defaults.ts +193 -0
  19. package/src/config/drift-detector.ts +290 -0
  20. package/src/config/markers.ts +330 -0
  21. package/src/config/resilient-parser.ts +117 -0
  22. package/src/config/role-tools.ts +118 -0
  23. package/src/config/suggestions.ts +75 -0
  24. package/src/config/types.ts +280 -0
  25. package/src/errors.ts +194 -0
  26. package/src/extension/action-suggestions.ts +117 -0
  27. package/src/extension/async-notifier.ts +179 -0
  28. package/src/extension/autonomous-policy.ts +209 -0
  29. package/src/extension/command-completions.ts +120 -0
  30. package/src/extension/context-status-injection.ts +185 -0
  31. package/src/extension/crew-autocomplete.ts +131 -0
  32. package/src/extension/crew-cleanup.ts +168 -0
  33. package/src/extension/crew-input-router.ts +93 -0
  34. package/src/extension/crew-shortcuts.ts +87 -0
  35. package/src/extension/crew-vibes/cat-frames.ts +18 -0
  36. package/src/extension/crew-vibes/config.ts +195 -0
  37. package/src/extension/crew-vibes/figures.ts +101 -0
  38. package/src/extension/crew-vibes/font-detect.ts +71 -0
  39. package/src/extension/crew-vibes/footer.ts +292 -0
  40. package/src/extension/crew-vibes/index.ts +432 -0
  41. package/src/extension/crew-vibes/provider-usage.ts +396 -0
  42. package/src/extension/crew-vibes/render.ts +206 -0
  43. package/src/extension/crew-vibes/speed.ts +286 -0
  44. package/src/extension/cross-extension-rpc.ts +350 -0
  45. package/src/extension/help.ts +62 -0
  46. package/src/extension/import-index.ts +74 -0
  47. package/src/extension/knowledge-injection.ts +402 -0
  48. package/src/extension/management.ts +571 -0
  49. package/src/extension/message-renderers.ts +108 -0
  50. package/src/extension/notification-router.ts +152 -0
  51. package/src/extension/notification-sink.ts +54 -0
  52. package/src/extension/pi-api.ts +56 -0
  53. package/src/extension/plan-orchestrate.ts +302 -0
  54. package/src/extension/project-init.ts +170 -0
  55. package/src/extension/register.ts +113 -0
  56. package/src/extension/registration/artifact-cleanup.ts +20 -0
  57. package/src/extension/registration/command-registration.ts +58 -0
  58. package/src/extension/registration/command-utils.ts +58 -0
  59. package/src/extension/registration/commands.ts +1228 -0
  60. package/src/extension/registration/compaction-guard.ts +333 -0
  61. package/src/extension/registration/context-builder.ts +135 -0
  62. package/src/extension/registration/crash-recovery-cache.ts +54 -0
  63. package/src/extension/registration/foreground-run-controller.ts +238 -0
  64. package/src/extension/registration/hook-registration.ts +119 -0
  65. package/src/extension/registration/lazy-configurers.ts +124 -0
  66. package/src/extension/registration/lifecycle-handlers.ts +923 -0
  67. package/src/extension/registration/lifecycle.ts +259 -0
  68. package/src/extension/registration/observability.ts +322 -0
  69. package/src/extension/registration/registration-types.ts +158 -0
  70. package/src/extension/registration/runtime-cleanup.ts +230 -0
  71. package/src/extension/registration/subagent-helpers.ts +125 -0
  72. package/src/extension/registration/subagent-manager-setup.ts +330 -0
  73. package/src/extension/registration/subagent-tools.ts +456 -0
  74. package/src/extension/registration/team-tool.ts +225 -0
  75. package/src/extension/registration/tool-registration.ts +50 -0
  76. package/src/extension/registration/ui.ts +172 -0
  77. package/src/extension/registration/viewers.ts +121 -0
  78. package/src/extension/registration/wire-cross-extension.ts +37 -0
  79. package/src/extension/result-watcher.ts +139 -0
  80. package/src/extension/rpc-hmac.ts +256 -0
  81. package/src/extension/run-bundle-schema.ts +104 -0
  82. package/src/extension/run-export.ts +97 -0
  83. package/src/extension/run-import.ts +168 -0
  84. package/src/extension/run-index.ts +131 -0
  85. package/src/extension/run-maintenance.ts +190 -0
  86. package/src/extension/session-summary.ts +18 -0
  87. package/src/extension/team-manager-command.ts +153 -0
  88. package/src/extension/team-onboard.ts +180 -0
  89. package/src/extension/team-recommendation.ts +288 -0
  90. package/src/extension/team-tool/anchor.ts +172 -0
  91. package/src/extension/team-tool/api.ts +1244 -0
  92. package/src/extension/team-tool/auto-summarize.ts +142 -0
  93. package/src/extension/team-tool/cache-control.ts +19 -0
  94. package/src/extension/team-tool/cancel.ts +337 -0
  95. package/src/extension/team-tool/chain-dispatch.ts +95 -0
  96. package/src/extension/team-tool/chain-executor.ts +379 -0
  97. package/src/extension/team-tool/config-patch.ts +50 -0
  98. package/src/extension/team-tool/context.ts +149 -0
  99. package/src/extension/team-tool/destructive-gate.ts +52 -0
  100. package/src/extension/team-tool/dispatch/automate.ts +80 -0
  101. package/src/extension/team-tool/dispatch/control.ts +42 -0
  102. package/src/extension/team-tool/dispatch/index.ts +95 -0
  103. package/src/extension/team-tool/dispatch/manage.ts +161 -0
  104. package/src/extension/team-tool/dispatch/run.ts +53 -0
  105. package/src/extension/team-tool/dispatch/status.ts +187 -0
  106. package/src/extension/team-tool/doctor.ts +431 -0
  107. package/src/extension/team-tool/explain.ts +282 -0
  108. package/src/extension/team-tool/failure-patterns.ts +118 -0
  109. package/src/extension/team-tool/goal-wrap.ts +330 -0
  110. package/src/extension/team-tool/goal.ts +556 -0
  111. package/src/extension/team-tool/handle-schedule.ts +332 -0
  112. package/src/extension/team-tool/handle-settings.ts +520 -0
  113. package/src/extension/team-tool/health-monitor.ts +481 -0
  114. package/src/extension/team-tool/inspect.ts +88 -0
  115. package/src/extension/team-tool/intent-policy.ts +45 -0
  116. package/src/extension/team-tool/lifecycle-actions.ts +615 -0
  117. package/src/extension/team-tool/orchestrate.ts +98 -0
  118. package/src/extension/team-tool/parallel-dispatch.ts +183 -0
  119. package/src/extension/team-tool/plan.ts +50 -0
  120. package/src/extension/team-tool/respond.ts +150 -0
  121. package/src/extension/team-tool/run-deadline.ts +66 -0
  122. package/src/extension/team-tool/run-not-found.ts +49 -0
  123. package/src/extension/team-tool/run.ts +1051 -0
  124. package/src/extension/team-tool/status.ts +260 -0
  125. package/src/extension/team-tool/workflow-manage.ts +261 -0
  126. package/src/extension/team-tool-types.ts +26 -0
  127. package/src/extension/team-tool.ts +750 -0
  128. package/src/extension/tool-result.ts +16 -0
  129. package/src/extension/validate-resources.ts +108 -0
  130. package/src/hooks/registry.ts +200 -0
  131. package/src/hooks/types.ts +69 -0
  132. package/src/i18n.ts +212 -0
  133. package/src/observability/correlation.ts +50 -0
  134. package/src/observability/event-bus.ts +86 -0
  135. package/src/observability/event-to-metric.ts +170 -0
  136. package/src/observability/exporters/adapter.ts +27 -0
  137. package/src/observability/exporters/otlp-exporter.ts +356 -0
  138. package/src/observability/exporters/prometheus-exporter.ts +54 -0
  139. package/src/observability/metric-registry.ts +100 -0
  140. package/src/observability/metric-retention.ts +64 -0
  141. package/src/observability/metric-sink.ts +99 -0
  142. package/src/observability/metrics-primitives.ts +219 -0
  143. package/src/plugins/plugin-define.ts +6 -0
  144. package/src/plugins/plugin-registry.ts +32 -0
  145. package/src/plugins/plugins/index.ts +3 -0
  146. package/src/plugins/plugins/nextjs.ts +19 -0
  147. package/src/plugins/plugins/vite.ts +10 -0
  148. package/src/plugins/plugins/vitest.ts +9 -0
  149. package/src/prompt/prompt-runtime.ts +380 -0
  150. package/src/runtime/adaptive-plan.ts +563 -0
  151. package/src/runtime/agent-control.ts +215 -0
  152. package/src/runtime/agent-memory.ts +81 -0
  153. package/src/runtime/agent-observability.ts +122 -0
  154. package/src/runtime/anchor-manager.ts +475 -0
  155. package/src/runtime/async-marker.ts +32 -0
  156. package/src/runtime/async-runner.ts +381 -0
  157. package/src/runtime/attention-events.ts +28 -0
  158. package/src/runtime/auto-summarize.ts +344 -0
  159. package/src/runtime/background-runner.ts +840 -0
  160. package/src/runtime/batch-barrier.ts +147 -0
  161. package/src/runtime/broker-issuer.ts +39 -0
  162. package/src/runtime/cancellation-token.ts +99 -0
  163. package/src/runtime/cancellation.ts +99 -0
  164. package/src/runtime/capability-inventory.ts +137 -0
  165. package/src/runtime/chain-parser.ts +237 -0
  166. package/src/runtime/chain-runner.ts +606 -0
  167. package/src/runtime/checkpoint.ts +291 -0
  168. package/src/runtime/child-pi-constants.ts +42 -0
  169. package/src/runtime/child-pi-kill.ts +180 -0
  170. package/src/runtime/child-pi-pool.ts +68 -0
  171. package/src/runtime/child-pi-spawn.ts +287 -0
  172. package/src/runtime/child-pi-steering.ts +128 -0
  173. package/src/runtime/child-pi-streams.ts +296 -0
  174. package/src/runtime/child-pi-transcript.ts +169 -0
  175. package/src/runtime/child-pi.ts +1105 -0
  176. package/src/runtime/coalesce-tasks.ts +268 -0
  177. package/src/runtime/code-summary.ts +292 -0
  178. package/src/runtime/command-trace.ts +105 -0
  179. package/src/runtime/compact-pipeline.ts +56 -0
  180. package/src/runtime/compact-stages/ansi-strip-stage.ts +25 -0
  181. package/src/runtime/compact-stages/blank-collapse-stage.ts +31 -0
  182. package/src/runtime/compact-stages/deduplicate-stage.ts +34 -0
  183. package/src/runtime/compact-stages/head-snap-stage.ts +57 -0
  184. package/src/runtime/compact-stages/index.ts +23 -0
  185. package/src/runtime/compact-stages/tail-capture-stage.ts +77 -0
  186. package/src/runtime/compact-stages/truncation-stage.ts +74 -0
  187. package/src/runtime/compaction-summary.ts +278 -0
  188. package/src/runtime/completion-guard.ts +207 -0
  189. package/src/runtime/concurrency.ts +58 -0
  190. package/src/runtime/crash-classification.ts +229 -0
  191. package/src/runtime/crash-recovery.ts +594 -0
  192. package/src/runtime/crew-agent-records.ts +595 -0
  193. package/src/runtime/crew-agent-runtime.ts +62 -0
  194. package/src/runtime/crew-broker-child.ts +88 -0
  195. package/src/runtime/crew-broker-client.ts +673 -0
  196. package/src/runtime/crew-broker-tokens.ts +159 -0
  197. package/src/runtime/crew-broker.ts +1304 -0
  198. package/src/runtime/crew-hooks.ts +227 -0
  199. package/src/runtime/cross-extension-rpc.ts +143 -0
  200. package/src/runtime/custom-tools/irc-tool.ts +282 -0
  201. package/src/runtime/custom-tools/submit-result-tool.ts +102 -0
  202. package/src/runtime/deadletter.ts +47 -0
  203. package/src/runtime/delivery-coordinator.ts +211 -0
  204. package/src/runtime/delta-conflict.ts +348 -0
  205. package/src/runtime/deterministic-ast.ts +161 -0
  206. package/src/runtime/diagnostic-export.ts +171 -0
  207. package/src/runtime/direct-run.ts +45 -0
  208. package/src/runtime/dwf-state-store.ts +102 -0
  209. package/src/runtime/dynamic-workflow-context.ts +1013 -0
  210. package/src/runtime/dynamic-workflow-runner.ts +325 -0
  211. package/src/runtime/effectiveness.ts +90 -0
  212. package/src/runtime/errors/crew-errors.ts +162 -0
  213. package/src/runtime/event-stream-bridge.ts +98 -0
  214. package/src/runtime/foreground-control.ts +193 -0
  215. package/src/runtime/foreground-watchdog.ts +132 -0
  216. package/src/runtime/global-worker-cap.ts +96 -0
  217. package/src/runtime/goal-achievement.ts +148 -0
  218. package/src/runtime/goal-evaluator.ts +365 -0
  219. package/src/runtime/goal-loop-runner.ts +825 -0
  220. package/src/runtime/goal-state-store.ts +219 -0
  221. package/src/runtime/green-contract.ts +55 -0
  222. package/src/runtime/group-join.ts +267 -0
  223. package/src/runtime/handoff-manager.ts +598 -0
  224. package/src/runtime/heartbeat-gradient.ts +36 -0
  225. package/src/runtime/heartbeat-watcher.ts +239 -0
  226. package/src/runtime/hidden-handoff.ts +407 -0
  227. package/src/runtime/important-line-classifier.ts +140 -0
  228. package/src/runtime/intercom-bridge.ts +187 -0
  229. package/src/runtime/iteration-hooks.ts +305 -0
  230. package/src/runtime/live-agent-control.ts +136 -0
  231. package/src/runtime/live-agent-manager.ts +704 -0
  232. package/src/runtime/live-control-realtime.ts +56 -0
  233. package/src/runtime/live-extension-bridge.ts +148 -0
  234. package/src/runtime/live-irc.ts +97 -0
  235. package/src/runtime/live-session-health.ts +108 -0
  236. package/src/runtime/live-session-runtime.ts +1146 -0
  237. package/src/runtime/loop-gates.ts +128 -0
  238. package/src/runtime/manifest-cache.ts +375 -0
  239. package/src/runtime/mcp-proxy.ts +105 -0
  240. package/src/runtime/metric-parser.ts +36 -0
  241. package/src/runtime/model-fallback.ts +409 -0
  242. package/src/runtime/model-resolver.ts +126 -0
  243. package/src/runtime/model-scope.ts +158 -0
  244. package/src/runtime/orphan-worker-registry.ts +465 -0
  245. package/src/runtime/output-validator.ts +202 -0
  246. package/src/runtime/overflow-recovery.ts +206 -0
  247. package/src/runtime/parallel-research.ts +68 -0
  248. package/src/runtime/parallel-utils.ts +160 -0
  249. package/src/runtime/parent-guard.ts +134 -0
  250. package/src/runtime/path-overlap.ts +150 -0
  251. package/src/runtime/peer-dep.ts +292 -0
  252. package/src/runtime/per-write-validator.ts +181 -0
  253. package/src/runtime/phase-progress.ts +217 -0
  254. package/src/runtime/phase-tracker.ts +385 -0
  255. package/src/runtime/pi-args.ts +655 -0
  256. package/src/runtime/pi-json-output.ts +170 -0
  257. package/src/runtime/pi-spawn.ts +273 -0
  258. package/src/runtime/pipeline-runner.ts +523 -0
  259. package/src/runtime/plan-templates.ts +201 -0
  260. package/src/runtime/policy-engine.ts +115 -0
  261. package/src/runtime/post-checks.ts +142 -0
  262. package/src/runtime/post-exit-stdio-guard.ts +109 -0
  263. package/src/runtime/process-lifecycle.ts +491 -0
  264. package/src/runtime/process-status.ts +154 -0
  265. package/src/runtime/progress-event-coalescer.ts +44 -0
  266. package/src/runtime/progress-tracker.ts +124 -0
  267. package/src/runtime/prose-compressor.ts +162 -0
  268. package/src/runtime/recovery-recipes.ts +203 -0
  269. package/src/runtime/replace.ts +570 -0
  270. package/src/runtime/resilient-edit.ts +153 -0
  271. package/src/runtime/result-extractor.ts +217 -0
  272. package/src/runtime/retry-executor.ts +109 -0
  273. package/src/runtime/retry-runner.ts +336 -0
  274. package/src/runtime/role-permission.ts +59 -0
  275. package/src/runtime/run-coalesced-task-group.ts +308 -0
  276. package/src/runtime/run-drift.ts +219 -0
  277. package/src/runtime/run-tracker.ts +116 -0
  278. package/src/runtime/run-worker.ts +78 -0
  279. package/src/runtime/runtime-policy.ts +29 -0
  280. package/src/runtime/runtime-resolver.ts +172 -0
  281. package/src/runtime/runtime-warmup.ts +160 -0
  282. package/src/runtime/scheduler.ts +353 -0
  283. package/src/runtime/semaphore.ts +141 -0
  284. package/src/runtime/sensitive-paths.ts +93 -0
  285. package/src/runtime/session-resources.ts +25 -0
  286. package/src/runtime/session-snapshot.ts +59 -0
  287. package/src/runtime/session-usage.ts +79 -0
  288. package/src/runtime/settings-store.ts +155 -0
  289. package/src/runtime/sidechain-output.ts +35 -0
  290. package/src/runtime/single-agent-compose.ts +84 -0
  291. package/src/runtime/skill-effectiveness.ts +524 -0
  292. package/src/runtime/skill-instructions.ts +394 -0
  293. package/src/runtime/stale-reconciler.ts +680 -0
  294. package/src/runtime/stream-preview.ts +184 -0
  295. package/src/runtime/streaming-output.ts +50 -0
  296. package/src/runtime/subagent-manager.ts +561 -0
  297. package/src/runtime/subprocess-tool-registry.ts +70 -0
  298. package/src/runtime/supervisor-contact.ts +64 -0
  299. package/src/runtime/task-display.ts +52 -0
  300. package/src/runtime/task-graph-scheduler.ts +227 -0
  301. package/src/runtime/task-graph.ts +290 -0
  302. package/src/runtime/task-health.ts +83 -0
  303. package/src/runtime/task-id.ts +161 -0
  304. package/src/runtime/task-output-context.ts +602 -0
  305. package/src/runtime/task-packet.ts +268 -0
  306. package/src/runtime/task-quality.ts +199 -0
  307. package/src/runtime/task-runner/capabilities.ts +78 -0
  308. package/src/runtime/task-runner/child-executor.ts +790 -0
  309. package/src/runtime/task-runner/context-retrieval.ts +163 -0
  310. package/src/runtime/task-runner/live-executor.ts +227 -0
  311. package/src/runtime/task-runner/output-splitter.ts +152 -0
  312. package/src/runtime/task-runner/post-execution.ts +480 -0
  313. package/src/runtime/task-runner/pre-execution.ts +365 -0
  314. package/src/runtime/task-runner/progress.ts +157 -0
  315. package/src/runtime/task-runner/prompt-builder.ts +278 -0
  316. package/src/runtime/task-runner/prompt-pipeline.ts +88 -0
  317. package/src/runtime/task-runner/result-utils.ts +16 -0
  318. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  319. package/src/runtime/task-runner/run-projection.ts +125 -0
  320. package/src/runtime/task-runner/scaffold-executor.ts +25 -0
  321. package/src/runtime/task-runner/state-helpers.ts +176 -0
  322. package/src/runtime/task-runner/tail-read.ts +34 -0
  323. package/src/runtime/task-runner.ts +216 -0
  324. package/src/runtime/team-runner-artifacts.ts +13 -0
  325. package/src/runtime/team-runner.ts +2396 -0
  326. package/src/runtime/tool-output-pruner.ts +333 -0
  327. package/src/runtime/tool-progress.ts +278 -0
  328. package/src/runtime/usage-tracker.ts +73 -0
  329. package/src/runtime/verification-gates.ts +579 -0
  330. package/src/runtime/verification-integrity.ts +108 -0
  331. package/src/runtime/verification-worktree.ts +186 -0
  332. package/src/runtime/worker-heartbeat.ts +25 -0
  333. package/src/runtime/worker-startup.ts +83 -0
  334. package/src/runtime/workflow-state.ts +195 -0
  335. package/src/runtime/workspace-lock.ts +443 -0
  336. package/src/runtime/workspace-tree.ts +312 -0
  337. package/src/runtime/yield-handler.ts +224 -0
  338. package/src/runtime/zombie-scanner.ts +298 -0
  339. package/src/schema/config-schema.ts +327 -0
  340. package/src/schema/team-tool-schema.ts +492 -0
  341. package/src/schema/validation-types.ts +159 -0
  342. package/src/skills/discover-skills.ts +203 -0
  343. package/src/skills/skill-templates.ts +456 -0
  344. package/src/skills/validate.ts +285 -0
  345. package/src/state/active-run-registry.ts +439 -0
  346. package/src/state/artifact-store.ts +176 -0
  347. package/src/state/atomic-write.ts +970 -0
  348. package/src/state/blob-store.ts +308 -0
  349. package/src/state/contracts.ts +160 -0
  350. package/src/state/crew-init.ts +269 -0
  351. package/src/state/decision-ledger.ts +372 -0
  352. package/src/state/event-log-rotation.ts +399 -0
  353. package/src/state/event-log.ts +1465 -0
  354. package/src/state/event-reconstructor.ts +229 -0
  355. package/src/state/gitignore-manager.ts +46 -0
  356. package/src/state/health-store.ts +79 -0
  357. package/src/state/hook-instinct-bridge.ts +94 -0
  358. package/src/state/hook-integrations.ts +51 -0
  359. package/src/state/instinct-store.ts +275 -0
  360. package/src/state/jsonl-writer.ts +107 -0
  361. package/src/state/locks.ts +562 -0
  362. package/src/state/mailbox.ts +916 -0
  363. package/src/state/observation-store.ts +176 -0
  364. package/src/state/run-cache.ts +193 -0
  365. package/src/state/run-graph.ts +183 -0
  366. package/src/state/run-metrics.ts +165 -0
  367. package/src/state/schedule.ts +166 -0
  368. package/src/state/session-state-map.ts +51 -0
  369. package/src/state/state-store.ts +973 -0
  370. package/src/state/task-claims.ts +61 -0
  371. package/src/state/tiered-eval.ts +480 -0
  372. package/src/state/types-eval.ts +58 -0
  373. package/src/state/types.ts +447 -0
  374. package/src/state/usage.ts +138 -0
  375. package/src/state/worker-atomic-writer.ts +198 -0
  376. package/src/subagents/async-entry.ts +1 -0
  377. package/src/subagents/index.ts +3 -0
  378. package/src/subagents/live/control.ts +1 -0
  379. package/src/subagents/live/manager.ts +1 -0
  380. package/src/subagents/live/realtime.ts +1 -0
  381. package/src/subagents/live/session-runtime.ts +1 -0
  382. package/src/subagents/manager.ts +1 -0
  383. package/src/subagents/spawn.ts +1 -0
  384. package/src/teams/discover-teams.ts +187 -0
  385. package/src/teams/team-config.ts +27 -0
  386. package/src/teams/team-serializer.ts +38 -0
  387. package/src/tools/safe-bash-extension.ts +54 -0
  388. package/src/tools/safe-bash.ts +505 -0
  389. package/src/types/diff.d.ts +18 -0
  390. package/src/types/new-api-types.ts +35 -0
  391. package/src/ui/agent-management-overlay.ts +160 -0
  392. package/src/ui/card-colors.ts +139 -0
  393. package/src/ui/crew-footer.ts +102 -0
  394. package/src/ui/crew-select-list.ts +112 -0
  395. package/src/ui/dashboard-panes/agents-pane.ts +164 -0
  396. package/src/ui/dashboard-panes/cancellation-pane.ts +66 -0
  397. package/src/ui/dashboard-panes/capability-pane.ts +77 -0
  398. package/src/ui/dashboard-panes/health-pane.ts +31 -0
  399. package/src/ui/dashboard-panes/mailbox-pane.ts +35 -0
  400. package/src/ui/dashboard-panes/metrics-pane.ts +37 -0
  401. package/src/ui/dashboard-panes/progress-pane.ts +38 -0
  402. package/src/ui/dashboard-panes/transcript-pane.ts +10 -0
  403. package/src/ui/deploy-bundled-themes.ts +71 -0
  404. package/src/ui/dwf-phase-display.ts +151 -0
  405. package/src/ui/dynamic-border.ts +35 -0
  406. package/src/ui/format-helpers.ts +31 -0
  407. package/src/ui/heartbeat-aggregator.ts +74 -0
  408. package/src/ui/key-utils.ts +42 -0
  409. package/src/ui/keybinding-map.ts +248 -0
  410. package/src/ui/layout-primitives.ts +106 -0
  411. package/src/ui/live-conversation-overlay.ts +183 -0
  412. package/src/ui/live-duration.ts +55 -0
  413. package/src/ui/live-run-sidebar.ts +293 -0
  414. package/src/ui/loaders.ts +6 -0
  415. package/src/ui/mascot.ts +449 -0
  416. package/src/ui/overlays/agent-picker-overlay.ts +66 -0
  417. package/src/ui/overlays/confirm-overlay.ts +60 -0
  418. package/src/ui/overlays/help-overlay.ts +177 -0
  419. package/src/ui/overlays/mailbox-compose-overlay.ts +181 -0
  420. package/src/ui/overlays/mailbox-compose-preview.ts +78 -0
  421. package/src/ui/overlays/mailbox-detail-overlay.ts +155 -0
  422. package/src/ui/pi-ui-compat.ts +68 -0
  423. package/src/ui/powerbar-publisher.ts +459 -0
  424. package/src/ui/render-coalescer.ts +101 -0
  425. package/src/ui/render-diff.ts +160 -0
  426. package/src/ui/render-scheduler.ts +278 -0
  427. package/src/ui/run-action-dispatcher.ts +182 -0
  428. package/src/ui/run-dashboard.ts +910 -0
  429. package/src/ui/run-event-bus.ts +381 -0
  430. package/src/ui/run-snapshot-cache.ts +1057 -0
  431. package/src/ui/settings-overlay.ts +1067 -0
  432. package/src/ui/shared-overlay-scheduler.ts +96 -0
  433. package/src/ui/snapshot-types.ts +90 -0
  434. package/src/ui/spinner.ts +17 -0
  435. package/src/ui/status-colors.ts +143 -0
  436. package/src/ui/syntax-highlight.ts +136 -0
  437. package/src/ui/terminal-status.ts +269 -0
  438. package/src/ui/theme-adapter.ts +271 -0
  439. package/src/ui/theme-discovery.ts +199 -0
  440. package/src/ui/tool-progress-formatter.ts +93 -0
  441. package/src/ui/tool-renderers/brief-mode.ts +225 -0
  442. package/src/ui/tool-renderers/index.ts +726 -0
  443. package/src/ui/transcript-cache.ts +128 -0
  444. package/src/ui/transcript-entries.ts +256 -0
  445. package/src/ui/transcript-viewer.ts +424 -0
  446. package/src/ui/widget/index.ts +418 -0
  447. package/src/ui/widget/widget-formatters.ts +182 -0
  448. package/src/ui/widget/widget-model.ts +110 -0
  449. package/src/ui/widget/widget-renderer.ts +182 -0
  450. package/src/ui/widget/widget-types.ts +36 -0
  451. package/src/utils/bm25-search.ts +235 -0
  452. package/src/utils/completion-dedupe.ts +63 -0
  453. package/src/utils/conflict-detect.ts +668 -0
  454. package/src/utils/env-allowlist.ts +30 -0
  455. package/src/utils/env-filter.ts +155 -0
  456. package/src/utils/file-coalescer.ts +98 -0
  457. package/src/utils/fingerprint.ts +180 -0
  458. package/src/utils/frontmatter.ts +70 -0
  459. package/src/utils/fs-watch.ts +37 -0
  460. package/src/utils/gh-protocol.ts +556 -0
  461. package/src/utils/git.ts +260 -0
  462. package/src/utils/guards.ts +107 -0
  463. package/src/utils/ids.ts +24 -0
  464. package/src/utils/incremental-reader.ts +220 -0
  465. package/src/utils/internal-error.ts +10 -0
  466. package/src/utils/names.ts +36 -0
  467. package/src/utils/ndjson.ts +115 -0
  468. package/src/utils/paths.ts +227 -0
  469. package/src/utils/project-detector.ts +160 -0
  470. package/src/utils/redaction.ts +370 -0
  471. package/src/utils/resolve-shell.ts +36 -0
  472. package/src/utils/run-watcher-registry.ts +152 -0
  473. package/src/utils/safe-paths.ts +393 -0
  474. package/src/utils/scan-cache.ts +144 -0
  475. package/src/utils/session-utils.ts +110 -0
  476. package/src/utils/sleep.ts +54 -0
  477. package/src/utils/socket-path.ts +164 -0
  478. package/src/utils/sse-parser.ts +131 -0
  479. package/src/utils/task-name-generator.ts +337 -0
  480. package/src/utils/timings.ts +33 -0
  481. package/src/utils/token-counter.ts +200 -0
  482. package/src/utils/visual.ts +207 -0
  483. package/src/workflows/cost-estimator.ts +34 -0
  484. package/src/workflows/discover-workflows.ts +308 -0
  485. package/src/workflows/intermediate-store.ts +166 -0
  486. package/src/workflows/preflight-validator.ts +168 -0
  487. package/src/workflows/topology-analyzer.ts +203 -0
  488. package/src/workflows/validate-workflow.ts +50 -0
  489. package/src/workflows/workflow-config.ts +75 -0
  490. package/src/workflows/workflow-serializer.ts +32 -0
  491. package/src/worktree/branch-freshness.ts +112 -0
  492. package/src/worktree/cleanup.ts +341 -0
  493. package/src/worktree/worktree-manager.ts +1204 -0
@@ -0,0 +1,381 @@
1
+ import { spawn } from "node:child_process";
2
+ import * as fs from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import * as path from "node:path";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
+ import { appendEventAsync } from "../state/event-log.ts";
7
+ import type { TeamRunManifest } from "../state/types.ts";
8
+ import { WINDOWS_ESSENTIAL_ENV_VARS } from "../utils/env-allowlist.ts";
9
+ import { sanitizeEnvSecrets } from "../utils/env-filter.ts";
10
+ import { logInternalError } from "../utils/internal-error.ts";
11
+ import { packageRoot } from "../utils/paths.ts";
12
+ import { redactSecretString } from "../utils/redaction.ts";
13
+ import { registerWorker, unregisterWorker } from "./orphan-worker-registry.ts";
14
+ import { PEER_DEP_DIR_ENV, resolvePeerDepDir } from "./peer-dep.ts";
15
+
16
+ export type FileExists = (filePath: string) => boolean;
17
+
18
+ const requireFromHere = createRequire(import.meta.url);
19
+
20
+ // Node introduced --experimental-strip-types in v22.6.0
21
+ const STRIP_TYPES_MIN_MAJOR = 22;
22
+ const STRIP_TYPES_MIN_MINOR = 6;
23
+
24
+ export type LoaderSpec = { kind: "jiti"; path: string } | { kind: "strip-types" };
25
+
26
+ type LoaderInput = LoaderSpec | string | false | undefined;
27
+
28
+ function packageRootFromRuntime(): string {
29
+ return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
30
+ }
31
+
32
+ function jitiRegisterPathFromPackageJson(packageJsonPath: string): string {
33
+ return path.join(path.dirname(packageJsonPath), "lib", "jiti-register.mjs");
34
+ }
35
+
36
+ export function resolveJitiRegisterPath(packageRoot = packageRootFromRuntime(), exists: FileExists = fs.existsSync): string | undefined {
37
+ // Walk upward from packageRoot looking for node_modules/jiti/lib/jiti-register.mjs
38
+ let current = path.resolve(packageRoot);
39
+ const root = path.parse(current).root;
40
+ while (true) {
41
+ const candidate = path.join(current, "node_modules", "jiti", "lib", "jiti-register.mjs");
42
+ if (exists(candidate)) return candidate;
43
+ if (current === root) break;
44
+ const parent = path.dirname(current);
45
+ if (parent === current) break;
46
+ current = parent;
47
+ }
48
+ // Fallback: require resolution (handles global installs or isolated stores)
49
+ try {
50
+ const pkgPath = requireFromHere.resolve("jiti/package.json");
51
+ const candidates = [
52
+ jitiRegisterPathFromPackageJson(pkgPath),
53
+ path.join(path.dirname(pkgPath), "register.mjs"),
54
+ path.join(path.dirname(pkgPath), "dist", "register.mjs"),
55
+ ];
56
+ for (const c of candidates) if (exists(c)) return c;
57
+ } catch {
58
+ // Fall through.
59
+ }
60
+ return undefined;
61
+ }
62
+
63
+ export function nodeSupportsStripTypes(version = process.version): boolean {
64
+ const match = /^v?(\d+)\.(\d+)/.exec(version);
65
+ if (!match) return false;
66
+ const major = Number(match[1]);
67
+ const minor = Number(match[2]);
68
+ if (major > STRIP_TYPES_MIN_MAJOR) return true;
69
+ if (major === STRIP_TYPES_MIN_MAJOR && minor >= STRIP_TYPES_MIN_MINOR) return true;
70
+ return false;
71
+ }
72
+
73
+ export interface ResolveLoaderOptions {
74
+ packageRoot?: string;
75
+ exists?: FileExists;
76
+ nodeVersion?: string;
77
+ }
78
+
79
+ export function resolveTypeScriptLoader(opts: ResolveLoaderOptions = {}): LoaderSpec | undefined {
80
+ const jitiPath = resolveJitiRegisterPath(opts.packageRoot, opts.exists);
81
+ if (jitiPath) return { kind: "jiti", path: jitiPath };
82
+ if (nodeSupportsStripTypes(opts.nodeVersion)) return { kind: "strip-types" };
83
+ return undefined;
84
+ }
85
+
86
+ function normalizeLoaderInput(input: LoaderInput): LoaderSpec | undefined {
87
+ if (input === undefined || input === null || input === false || input === "") return undefined;
88
+ if (typeof input === "string") return { kind: "jiti", path: input };
89
+ return input;
90
+ }
91
+
92
+ function buildLoaderUnavailableMessage(searchedFrom: string): string {
93
+ return [
94
+ "pi-crew background runner cannot start: jiti loader not found and Node --experimental-strip-types fallback unavailable.",
95
+ ` - Searched for node_modules/jiti walking upward from: ${searchedFrom}`,
96
+ ` - Node --experimental-strip-types requires >= 22.6 (current: ${process.version})`,
97
+ " - Fix: run 'npm install' in the pi-crew directory, reinstall via 'pi install npm:pi-crew', or upgrade Node.js to >= 22.6.",
98
+ ].join("\n");
99
+ }
100
+
101
+ export function getBackgroundRunnerCommand(
102
+ runnerPath: string,
103
+ cwd: string,
104
+ runId: string,
105
+ loaderInput: LoaderInput = resolveTypeScriptLoader(),
106
+ /**
107
+ * Directory to write the V8 fatal-error report into. Defaults to
108
+ * path.dirname(runnerPath). Pass the run stateRoot so the report lands
109
+ * next to background.log for easy diagnosis.
110
+ */
111
+ reportDirectory?: string,
112
+ ): { args: string[]; loader: "jiti" | "strip-types" } {
113
+ const loader = normalizeLoaderInput(loaderInput);
114
+ if (!loader) throw new Error(buildLoaderUnavailableMessage(packageRootFromRuntime()));
115
+ // Limit V8 heap to 512MB for the background runner to avoid triggering the
116
+ // Linux OOM killer. The runner itself is lightweight — it delegates work to
117
+ // child Pi processes — so 512MB is generous. Without this limit, Node.js
118
+ // defaults to ~1.5GB on 64-bit systems, which combined with jiti compilation
119
+ // and child processes can exhaust system memory.
120
+ const memoryLimit = "--max-old-space-size=512";
121
+ // V8 diagnostic report on fatal error. A native heap-OOM abort or segfault
122
+ // bypasses the JS process.on('exit') handler and console overrides
123
+ // entirely — only a V8 report file survives such crashes. This is ON by
124
+ // default precisely so silent runner deaths (like the explore→code-review
125
+ // transition crash) leave a native stack/heap/environment trace. Users who
126
+ // don't want report files can opt out with PI_CREW_BG_REPORT_ON_FATAL=0.
127
+ const reportOn = !(process.env.PI_CREW_BG_REPORT_ON_FATAL === "0" || process.env.PI_TEAMS_BG_REPORT_ON_FATAL === "0");
128
+ const reportDir = reportDirectory ?? path.dirname(runnerPath);
129
+ const reportFlags = reportOn ? ["--report-on-fatalerror", "--report-compact", `--report-directory=${reportDir}`] : [];
130
+ if (loader.kind === "jiti") {
131
+ return {
132
+ args: [
133
+ memoryLimit,
134
+ ...reportFlags,
135
+ "--trace-uncaught",
136
+ "--import",
137
+ pathToFileURL(loader.path).href,
138
+ runnerPath,
139
+ "--cwd",
140
+ cwd,
141
+ "--run-id",
142
+ runId,
143
+ ],
144
+ loader: "jiti",
145
+ };
146
+ }
147
+ return {
148
+ args: [memoryLimit, ...reportFlags, "--experimental-strip-types", runnerPath, "--cwd", cwd, "--run-id", runId],
149
+ loader: "strip-types",
150
+ };
151
+ }
152
+
153
+ export interface SpawnBackgroundTeamRunResult {
154
+ pid?: number;
155
+ logPath: string;
156
+ }
157
+
158
+ /**
159
+ * Env vars explicitly forwarded to the detached background runner.
160
+ *
161
+ * Provider API keys (MINIMAX/OPENAI/ANTHROPIC/...) are INTENTIONALLY OMITTED
162
+ * (security review M1): the background runner only spawns child Pi workers,
163
+ * which read keys from the Pi config file (not env). Passing keys via env
164
+ * leaks them into V8 fatal-error reports (--report-on-fatalerror writes the
165
+ * `environmentVariables` section unredacted). Matches child-pi.ts policy.
166
+ * Exported so the invariant is unit-testable (test/unit/async-runner.test.ts).
167
+ */
168
+ export const BACKGROUND_RUNNER_ENV_ALLOWLIST: string[] = [
169
+ // Essential non-secret vars
170
+ "PATH",
171
+ "HOME",
172
+ "USER",
173
+ "SHELL",
174
+ "TERM",
175
+ "LANG",
176
+ "LC_ALL",
177
+ "LC_COLLATE",
178
+ "LC_CTYPE",
179
+ "LC_MESSAGES",
180
+ "LC_MONETARY",
181
+ "LC_NUMERIC",
182
+ "LC_TIME",
183
+ "XDG_CONFIG_HOME",
184
+ "XDG_DATA_HOME",
185
+ "XDG_CACHE_HOME",
186
+ "XDG_RUNTIME_DIR",
187
+ // Windows essentials — see WINDOWS_ESSENTIAL_ENV_VARS (src/utils/env-allowlist.ts).
188
+ ...WINDOWS_ESSENTIAL_ENV_VARS,
189
+ "NVM_BIN",
190
+ "NVM_DIR",
191
+ "NVM_INC",
192
+ "NODE_PATH",
193
+ "NODE_DISABLE_COLORS",
194
+ "NODE_EXTRA_CA_CERTS",
195
+ "NPM_CONFIG_REGISTRY",
196
+ "NPM_CONFIG_USERCONFIG",
197
+ "NPM_CONFIG_GLOBALCONFIG",
198
+ // PI_CREW_PARENT_PID is needed for parent-guard (liveness check).
199
+ "PI_CREW_DEPTH",
200
+ "PI_CREW_MAX_DEPTH",
201
+ "PI_CREW_INHERIT_PROJECT_CONTEXT",
202
+ "PI_CREW_INHERIT_SKILLS",
203
+ "PI_CREW_PARENT_PID",
204
+ "PI_TEAMS_DEPTH",
205
+ "PI_TEAMS_MAX_DEPTH",
206
+ "PI_TEAMS_INHERIT_PROJECT_CONTEXT",
207
+ "PI_TEAMS_INHERIT_SKILLS",
208
+ "PI_TEAMS_PI_BIN",
209
+ "PI_TEAMS_MOCK_CHILD_PI",
210
+ "PI_CREW_ALLOW_MOCK",
211
+ // Phase 1.5: worker-thread atomic writer opt-in (RFC 15).
212
+ "PI_CREW_WORKER_ATOMIC_WRITER",
213
+ "PI_TEAMS_WORKER_ATOMIC_WRITER",
214
+ // Phase 1.5 #1: verification env sanitization opt-out (RFC 13 §6).
215
+ "PI_CREW_VERIFICATION_SANITIZE_ENV",
216
+ "PI_TEAMS_VERIFICATION_SANITIZE_ENV",
217
+ "PI_CREW_VERIFICATION_PRESERVE_ENV",
218
+ "PI_TEAMS_VERIFICATION_PRESERVE_ENV",
219
+ // Phase 1.5 #2: verification git-worktree sandbox opt-in (RFC 16).
220
+ "PI_CREW_VERIFICATION_WORKTREE",
221
+ "PI_TEAMS_VERIFICATION_WORKTREE",
222
+ // Phase 1.5 #3: V8 diagnostic report on fatal error (RFC 17 — investigation).
223
+ "PI_CREW_BG_REPORT_ON_FATAL",
224
+ "PI_TEAMS_BG_REPORT_ON_FATAL",
225
+ ];
226
+
227
+ export async function spawnBackgroundTeamRun(manifest: TeamRunManifest): Promise<SpawnBackgroundTeamRunResult> {
228
+ // FIX (2026-07-02, perf review F-critical): use packageRoot() instead of
229
+ // import.meta.url-relative path. The previous path.resolve walks
230
+ // <bundleDir>/background-runner.ts, which is correct in src/ but BROKEN
231
+ // in the bundle: esbuild's __esm helper does not preserve per-module
232
+ // import.meta.url, so the resolve lands at <pi-crew>/background-runner.ts
233
+ // (missing `src/runtime/`). The background-runner then ENOENTs at spawn
234
+ // and 3 explorer agents failed during the verification run. packageRoot()
235
+ // walks up to find pi-crew's package.json and works correctly from both
236
+ // src/ and dist/ entry points. Mirrors the fix in pi-args.ts:10 (commit
237
+ // 0dd93e0).
238
+ const runnerPath = path.join(packageRoot(), "src", "runtime", "background-runner.ts");
239
+ const logPath = path.join(manifest.stateRoot, "background.log");
240
+ fs.mkdirSync(manifest.stateRoot, { recursive: true });
241
+
242
+ // SECURITY FIX: Use sanitizeEnvSecrets with same allow-list as child-pi.ts
243
+ // to prevent leaking all env vars (including secrets) to detached background runner.
244
+ // Previously, destructuring only removed PI_CREW_PARENT_PID but kept everything else.
245
+ const filteredEnv = sanitizeEnvSecrets(process.env, {
246
+ allowList: BACKGROUND_RUNNER_ENV_ALLOWLIST,
247
+ });
248
+ // FIX: removed delete workarounds — with explicit allowlist, these vars
249
+ // are no longer auto-leaked. Matches child-pi.ts.
250
+
251
+ // FIX (split-scope install): pass the resolved peer-dep dir to the child so
252
+ // it can resolve @earendil-works/pi-coding-agent WITHOUT the ~200ms
253
+ // `npm root -g` probe. No-op when pi-crew and pi are co-located. See
254
+ // src/runtime/peer-dep.ts.
255
+ const peerDepDir = resolvePeerDepDir();
256
+ const childEnv = peerDepDir ? { ...filteredEnv, [PEER_DEP_DIR_ENV]: peerDepDir } : filteredEnv;
257
+
258
+ const loader = resolveTypeScriptLoader();
259
+ if (!loader) {
260
+ const message = buildLoaderUnavailableMessage(packageRootFromRuntime());
261
+ // FIX-08: use async event append to avoid sleepSync event-loop blocking.
262
+ await appendEventAsync(manifest.eventsPath, {
263
+ type: "async.failed",
264
+ runId: manifest.runId,
265
+ message,
266
+ });
267
+ throw new Error(message);
268
+ }
269
+ // Pass manifest.stateRoot as report-directory so V8 fatal reports land
270
+ // next to background.log (same dir) for easy post-mortem diagnosis.
271
+ const command = getBackgroundRunnerCommand(runnerPath, manifest.cwd, manifest.runId, loader, manifest.stateRoot);
272
+ fs.appendFileSync(logPath, `[pi-crew] background loader=${command.loader}\n`, "utf-8");
273
+
274
+ // Spawn the background runner as a fully detached process with its own session.
275
+ // BUG #17 FIX: setsid:true + detached:true creates a process that:
276
+ // 1. Has its own session (SID = PID) — immune to terminal/SIGTERM signals
277
+ // 2. Is detached (unref'd) — parent exit doesn't affect it
278
+ // 3. Has its own process group (PGID = PID) — process group kills don't reach it
279
+ //
280
+ // IMPORTANT: session_shutdown handlers must NOT kill async runners.
281
+ // See register.ts cleanupRuntime — the kill loop was commented out.
282
+ // Type assertion for setsid is necessary because Node.js types don't include it
283
+ // in SpawnOptions on all platforms, but it's supported on Unix systems.
284
+ // Use explicit cast through unknown to satisfy TypeScript's strict type checking.
285
+ const spawnOpts = {
286
+ cwd: manifest.cwd,
287
+ detached: true,
288
+ setsid: true,
289
+ stdio: ["ignore", "pipe", "pipe"],
290
+ env: childEnv,
291
+ windowsHide: true,
292
+ } as unknown as Parameters<typeof spawn>[2];
293
+ const child = spawn(process.execPath, command.args, spawnOpts);
294
+ // Round 27 (BUG 3) history: the piped stdout/stderr were previously destroyed
295
+ // immediately to avoid a pipe-buffer deadlock (child writes >64KB with nobody
296
+ // draining → hang). BUT destroying stderr ALSO swallowed native crash
297
+ // messages: a V8 heap-OOM abort() or segfault writes its diagnostic directly
298
+ // to the process stderr fd, which was the (now-destroyed) pipe read-end, so
299
+ // the bytes vanished — making runner deaths completely silent. This caused
300
+ // the explore→code-review transition crash to leave zero trace.
301
+ //
302
+ // FIX: keep stdout destroyed (unused — runner redirects its own console to
303
+ // a file), but DRAIN stderr asynchronously into background.log with a
304
+ // "[child stderr]" prefix. Buffer is capped to avoid unbounded memory if a
305
+ // noisy child streams megabytes; excess is dropped with a truncation marker.
306
+ child.stdout?.destroy();
307
+ const STDERR_CAPTURE_LIMIT = 256 * 1024;
308
+ const stderrChunks: Buffer[] = [];
309
+ let stderrLen = 0;
310
+ let stderrTruncated = false;
311
+ const flushStderr = (): void => {
312
+ if (stderrChunks.length === 0) return;
313
+ let body: string;
314
+ try {
315
+ body = Buffer.concat(stderrChunks).toString("utf-8");
316
+ } catch {
317
+ stderrChunks.length = 0;
318
+ return;
319
+ }
320
+ stderrChunks.length = 0;
321
+ try {
322
+ // FIND-14: route child stderr through redactSecretString before writing
323
+ // to the log so API keys / bearer tokens / inline secrets emitted by the
324
+ // child are scrubbed. Without this, a child crash trace containing
325
+ // `Authorization: Bearer ...` or a stack trace with `MINIMAX_API_KEY=...`
326
+ // would land in background.log unredacted and ship to disk (and to the
327
+ // V8 fatal-error report which writes environmentVariables unredacted).
328
+ const redacted = redactSecretString(body);
329
+ fs.appendFileSync(logPath, `[child stderr] ${redacted}${redacted.endsWith("\n") ? "" : "\n"}`, "utf-8");
330
+ } catch {
331
+ /* best-effort */
332
+ }
333
+ };
334
+ child.stderr?.on("data", (chunk: Buffer) => {
335
+ if (stderrLen + chunk.length > STDERR_CAPTURE_LIMIT) {
336
+ if (!stderrTruncated) {
337
+ stderrTruncated = true;
338
+ try {
339
+ fs.appendFileSync(logPath, `[child stderr truncated at ${STDERR_CAPTURE_LIMIT} bytes]\n`, "utf-8");
340
+ } catch {
341
+ /* best-effort */
342
+ }
343
+ }
344
+ return;
345
+ }
346
+ stderrChunks.push(chunk);
347
+ stderrLen += chunk.length;
348
+ });
349
+ child.stderr?.on("end", flushStderr);
350
+ child.stderr?.on("close", flushStderr);
351
+ child.on("error", (error: Error) => {
352
+ logInternalError("async-runner.spawn", error, `pid=${child.pid ?? "unknown"}`);
353
+ });
354
+ child.unref();
355
+
356
+ // Track this worker in the orphan registry so it can be killed on
357
+ // session_start of a future session if the parent pi process is killed.
358
+ if (child.pid) {
359
+ registerWorker(
360
+ child.pid,
361
+ manifest.ownerSessionId ?? "unknown",
362
+ manifest.runId,
363
+ process.pid, // parentPid — used by cleanup to verify session is dead
364
+ );
365
+ // Best-effort: unregister when child exits. Background-runner writes
366
+ // the marker file before it dies, so we unregister on the next
367
+ // cleanup tick. The child "exit" event may fire after unref() when
368
+ // stdio is piped; register handler defensively.
369
+ if (child.pid) {
370
+ child.on("exit", () => {
371
+ try {
372
+ unregisterWorker(child.pid!);
373
+ } catch {
374
+ /* best-effort */
375
+ }
376
+ });
377
+ }
378
+ }
379
+
380
+ return { pid: child.pid, logPath };
381
+ }
@@ -0,0 +1,28 @@
1
+ import { appendEvent, readEvents } from "../state/event-log.ts";
2
+ import type { CrewAttentionEventData, TeamRunManifest } from "../state/types.ts";
3
+
4
+ export interface AppendTaskAttentionInput {
5
+ manifest: TeamRunManifest;
6
+ taskId?: string;
7
+ message: string;
8
+ data: CrewAttentionEventData;
9
+ }
10
+
11
+ export function appendTaskAttentionEvent(input: AppendTaskAttentionInput): boolean {
12
+ const recent = readEvents(input.manifest.eventsPath).slice(-200);
13
+ const dedupKey = `${input.taskId ?? ""}:${input.data.reason}:${input.data.activityState}`;
14
+ const duplicate = recent.some(
15
+ (event) =>
16
+ event.type === "task.attention" &&
17
+ `${event.taskId ?? ""}:${event.data?.reason ?? ""}:${event.data?.activityState ?? ""}` === dedupKey,
18
+ );
19
+ if (duplicate) return false;
20
+ appendEvent(input.manifest.eventsPath, {
21
+ type: "task.attention",
22
+ runId: input.manifest.runId,
23
+ taskId: input.taskId,
24
+ message: input.message,
25
+ data: { ...input.data },
26
+ });
27
+ return true;
28
+ }