pi-crew 0.9.16 → 0.9.18

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 (435) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +19 -0
  3. package/dist/build-meta.json +21784 -0
  4. package/dist/index.mjs +83169 -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/migration/atomic-write-v2-migration.md +297 -0
  14. package/docs/patterns/command-agent-skill.md +1 -1
  15. package/docs/perf/performance-review-2026-07.md +287 -0
  16. package/docs/skills/REFERENCE.md +0 -17
  17. package/docs//303/242mmaAAA/303/242 +357 -0
  18. package/index.bundle.ts +25 -0
  19. package/index.ts +95 -4
  20. package/package.json +15 -4
  21. package/skills/iterative-audit/SKILL.md +0 -1
  22. package/skills/widget-rendering/SKILL.md +17 -0
  23. package/src/adapters/claude-adapter.ts +1 -3
  24. package/src/adapters/export-util.ts +16 -16
  25. package/src/adapters/index.ts +5 -5
  26. package/src/agents/agent-config.ts +20 -14
  27. package/src/agents/agent-serializer.ts +1 -1
  28. package/src/agents/discover-agents.ts +83 -39
  29. package/src/benchmark/benchmark-runner.ts +51 -51
  30. package/src/benchmark/feedback-loop.ts +1 -1
  31. package/src/config/config.ts +303 -591
  32. package/src/config/defaults.ts +28 -2
  33. package/src/config/drift-detector.ts +11 -14
  34. package/src/config/markers.ts +201 -203
  35. package/src/config/resilient-parser.ts +14 -6
  36. package/src/config/role-tools.ts +3 -3
  37. package/src/config/suggestions.ts +5 -12
  38. package/src/config/types.ts +9 -25
  39. package/src/errors.ts +151 -157
  40. package/src/extension/action-suggestions.ts +54 -9
  41. package/src/extension/async-notifier.ts +43 -13
  42. package/src/extension/autonomous-policy.ts +77 -37
  43. package/src/extension/command-completions.ts +9 -8
  44. package/src/extension/context-status-injection.ts +14 -12
  45. package/src/extension/crew-autocomplete.ts +8 -16
  46. package/src/extension/crew-cleanup.ts +2 -1
  47. package/src/extension/crew-shortcuts.ts +9 -6
  48. package/src/extension/cross-extension-rpc.ts +136 -42
  49. package/src/extension/help.ts +1 -1
  50. package/src/extension/import-index.ts +10 -5
  51. package/src/extension/knowledge-injection.ts +88 -15
  52. package/src/extension/management.ts +89 -349
  53. package/src/extension/message-renderers.ts +3 -4
  54. package/src/extension/notification-router.ts +22 -5
  55. package/src/extension/notification-sink.ts +6 -3
  56. package/src/extension/pi-api.ts +17 -8
  57. package/src/extension/plan-orchestrate.ts +8 -27
  58. package/src/extension/project-init.ts +21 -6
  59. package/src/extension/register.ts +329 -975
  60. package/src/extension/registration/artifact-cleanup.ts +9 -4
  61. package/src/extension/registration/command-utils.ts +5 -1
  62. package/src/extension/registration/commands.ts +806 -314
  63. package/src/extension/registration/compaction-guard.ts +15 -15
  64. package/src/extension/registration/lifecycle.ts +259 -0
  65. package/src/extension/registration/observability.ts +293 -0
  66. package/src/extension/registration/subagent-helpers.ts +29 -7
  67. package/src/extension/registration/subagent-tools.ts +253 -44
  68. package/src/extension/registration/team-tool.ts +19 -84
  69. package/src/extension/registration/ui.ts +168 -0
  70. package/src/extension/registration/viewers.ts +64 -24
  71. package/src/extension/result-watcher.ts +18 -7
  72. package/src/extension/run-bundle-schema.ts +21 -6
  73. package/src/extension/run-export.ts +15 -6
  74. package/src/extension/run-import.ts +64 -29
  75. package/src/extension/run-index.ts +28 -9
  76. package/src/extension/run-maintenance.ts +32 -12
  77. package/src/extension/session-summary.ts +1 -1
  78. package/src/extension/team-manager-command.ts +64 -7
  79. package/src/extension/team-onboard.ts +149 -150
  80. package/src/extension/team-recommendation.ts +121 -21
  81. package/src/extension/team-tool/anchor.ts +31 -64
  82. package/src/extension/team-tool/api.ts +929 -141
  83. package/src/extension/team-tool/auto-summarize.ts +14 -26
  84. package/src/extension/team-tool/cache-control.ts +1 -5
  85. package/src/extension/team-tool/cancel.ts +138 -38
  86. package/src/extension/team-tool/chain-dispatch.ts +5 -13
  87. package/src/extension/team-tool/chain-executor.ts +29 -51
  88. package/src/extension/team-tool/config-patch.ts +1 -1
  89. package/src/extension/team-tool/context.ts +40 -20
  90. package/src/extension/team-tool/destructive-gate.ts +10 -5
  91. package/src/extension/team-tool/doctor.ts +170 -51
  92. package/src/extension/team-tool/explain.ts +228 -214
  93. package/src/extension/team-tool/failure-patterns.ts +3 -9
  94. package/src/extension/team-tool/goal-wrap.ts +71 -29
  95. package/src/extension/team-tool/goal.ts +185 -35
  96. package/src/extension/team-tool/handle-schedule.ts +34 -15
  97. package/src/extension/team-tool/handle-settings.ts +94 -56
  98. package/src/extension/team-tool/health-monitor.ts +27 -108
  99. package/src/extension/team-tool/inspect.ts +42 -9
  100. package/src/extension/team-tool/intent-policy.ts +4 -1
  101. package/src/extension/team-tool/lifecycle-actions.ts +244 -48
  102. package/src/extension/team-tool/orchestrate.ts +7 -18
  103. package/src/extension/team-tool/parallel-dispatch.ts +51 -29
  104. package/src/extension/team-tool/plan.ts +29 -5
  105. package/src/extension/team-tool/respond.ts +49 -16
  106. package/src/extension/team-tool/run-not-found.ts +3 -8
  107. package/src/extension/team-tool/run.ts +80 -317
  108. package/src/extension/team-tool/status.ts +135 -43
  109. package/src/extension/team-tool/workflow-manage.ts +92 -25
  110. package/src/extension/team-tool-types.ts +8 -1
  111. package/src/extension/team-tool.ts +142 -551
  112. package/src/extension/validate-resources.ts +39 -8
  113. package/src/hooks/registry.ts +66 -17
  114. package/src/hooks/types.ts +1 -1
  115. package/src/i18n.ts +25 -11
  116. package/src/observability/correlation.ts +17 -3
  117. package/src/observability/event-bus.ts +51 -56
  118. package/src/observability/event-to-metric.ts +117 -15
  119. package/src/observability/exporters/otlp-exporter.ts +56 -17
  120. package/src/observability/exporters/prometheus-exporter.ts +1 -1
  121. package/src/observability/metric-registry.ts +16 -4
  122. package/src/observability/metric-retention.ts +8 -2
  123. package/src/observability/metric-sink.ts +11 -3
  124. package/src/observability/metrics-primitives.ts +42 -9
  125. package/src/plugins/plugin-define.ts +2 -2
  126. package/src/plugins/plugin-registry.ts +25 -25
  127. package/src/plugins/plugins/index.ts +1 -1
  128. package/src/plugins/plugins/nextjs.ts +16 -16
  129. package/src/plugins/plugins/vite.ts +7 -11
  130. package/src/plugins/plugins/vitest.ts +6 -11
  131. package/src/runtime/adaptive-plan.ts +225 -40
  132. package/src/runtime/agent-control.ts +58 -15
  133. package/src/runtime/agent-memory.ts +15 -9
  134. package/src/runtime/agent-observability.ts +10 -2
  135. package/src/runtime/anchor-manager.ts +27 -25
  136. package/src/runtime/async-marker.ts +7 -1
  137. package/src/runtime/async-runner.ts +39 -24
  138. package/src/runtime/auto-summarize.ts +7 -13
  139. package/src/runtime/background-runner.ts +189 -251
  140. package/src/runtime/batch-barrier.ts +18 -16
  141. package/src/runtime/cancellation-token.ts +16 -6
  142. package/src/runtime/cancellation.ts +46 -8
  143. package/src/runtime/capability-inventory.ts +6 -4
  144. package/src/runtime/chain-parser.ts +44 -11
  145. package/src/runtime/chain-runner.ts +63 -69
  146. package/src/runtime/checkpoint.ts +12 -56
  147. package/src/runtime/child-pi.ts +344 -79
  148. package/src/runtime/coalesce-tasks.ts +268 -0
  149. package/src/runtime/code-summary.ts +71 -26
  150. package/src/runtime/compact-stages/index.ts +15 -5
  151. package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
  152. package/src/runtime/compact-stages/truncation-stage.ts +4 -1
  153. package/src/runtime/compaction-summary.ts +17 -10
  154. package/src/runtime/completion-guard.ts +33 -16
  155. package/src/runtime/crash-classification.ts +28 -7
  156. package/src/runtime/crash-recovery.ts +177 -37
  157. package/src/runtime/crew-agent-records.ts +145 -47
  158. package/src/runtime/crew-hooks.ts +9 -24
  159. package/src/runtime/cross-extension-rpc.ts +25 -23
  160. package/src/runtime/custom-tools/irc-tool.ts +43 -15
  161. package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
  162. package/src/runtime/delivery-coordinator.ts +34 -7
  163. package/src/runtime/delta-conflict.ts +9 -21
  164. package/src/runtime/deterministic-ast.ts +1 -1
  165. package/src/runtime/diagnostic-export.ts +53 -20
  166. package/src/runtime/direct-run.ts +12 -2
  167. package/src/runtime/dwf-state-store.ts +1 -1
  168. package/src/runtime/dynamic-workflow-context.ts +187 -59
  169. package/src/runtime/dynamic-workflow-runner.ts +42 -20
  170. package/src/runtime/effectiveness.ts +16 -8
  171. package/src/runtime/errors/crew-errors.ts +7 -11
  172. package/src/runtime/event-stream-bridge.ts +9 -3
  173. package/src/runtime/foreground-control.ts +54 -14
  174. package/src/runtime/foreground-watchdog.ts +9 -6
  175. package/src/runtime/goal-achievement.ts +27 -10
  176. package/src/runtime/goal-evaluator.ts +54 -19
  177. package/src/runtime/goal-loop-runner.ts +280 -99
  178. package/src/runtime/goal-state-store.ts +27 -17
  179. package/src/runtime/green-contract.ts +11 -2
  180. package/src/runtime/group-join.ts +64 -31
  181. package/src/runtime/handoff-manager.ts +37 -42
  182. package/src/runtime/heartbeat-gradient.ts +10 -2
  183. package/src/runtime/heartbeat-watcher.ts +32 -6
  184. package/src/runtime/hidden-handoff.ts +13 -31
  185. package/src/runtime/important-line-classifier.ts +12 -2
  186. package/src/runtime/iteration-hooks.ts +25 -15
  187. package/src/runtime/live-agent-control.ts +55 -7
  188. package/src/runtime/live-agent-manager.ts +130 -27
  189. package/src/runtime/live-control-realtime.ts +23 -3
  190. package/src/runtime/live-irc.ts +4 -1
  191. package/src/runtime/live-session-health.ts +12 -4
  192. package/src/runtime/live-session-runtime.ts +379 -117
  193. package/src/runtime/manifest-cache.ts +28 -12
  194. package/src/runtime/mcp-proxy.ts +10 -18
  195. package/src/runtime/metric-parser.ts +1 -5
  196. package/src/runtime/model-fallback.ts +55 -18
  197. package/src/runtime/model-resolver.ts +2 -6
  198. package/src/runtime/model-scope.ts +19 -3
  199. package/src/runtime/notebook-helpers.ts +60 -62
  200. package/src/runtime/orphan-worker-registry.ts +37 -26
  201. package/src/runtime/output-validator.ts +18 -3
  202. package/src/runtime/overflow-recovery.ts +5 -4
  203. package/src/runtime/parallel-research.ts +29 -5
  204. package/src/runtime/parallel-utils.ts +9 -11
  205. package/src/runtime/path-overlap.ts +150 -0
  206. package/src/runtime/peer-dep.ts +12 -17
  207. package/src/runtime/per-write-validator.ts +1 -3
  208. package/src/runtime/phase-tracker.ts +342 -330
  209. package/src/runtime/pi-args.ts +26 -8
  210. package/src/runtime/pi-json-output.ts +1 -1
  211. package/src/runtime/pi-spawn.ts +30 -19
  212. package/src/runtime/pipeline-runner.ts +56 -55
  213. package/src/runtime/plan-templates.ts +5 -6
  214. package/src/runtime/policy-engine.ts +43 -7
  215. package/src/runtime/post-checks.ts +12 -4
  216. package/src/runtime/post-exit-stdio-guard.ts +2 -2
  217. package/src/runtime/process-lifecycle.ts +20 -10
  218. package/src/runtime/process-status.ts +16 -5
  219. package/src/runtime/progress-event-coalescer.ts +2 -1
  220. package/src/runtime/progress-tracker.ts +103 -103
  221. package/src/runtime/prose-compressor.ts +9 -11
  222. package/src/runtime/recovery-recipes.ts +118 -24
  223. package/src/runtime/replace.ts +25 -10
  224. package/src/runtime/resilient-edit.ts +10 -25
  225. package/src/runtime/result-extractor.ts +2 -6
  226. package/src/runtime/retry-executor.ts +20 -4
  227. package/src/runtime/retry-runner.ts +27 -51
  228. package/src/runtime/role-permission.ts +6 -1
  229. package/src/runtime/run-coalesced-task-group.ts +256 -0
  230. package/src/runtime/run-drift.ts +14 -15
  231. package/src/runtime/run-tracker.ts +6 -28
  232. package/src/runtime/runtime-policy.ts +1 -6
  233. package/src/runtime/runtime-resolver.ts +80 -15
  234. package/src/runtime/scheduler.ts +47 -18
  235. package/src/runtime/semaphore.ts +5 -7
  236. package/src/runtime/sensitive-paths.ts +2 -1
  237. package/src/runtime/session-usage.ts +1 -1
  238. package/src/runtime/settings-store.ts +16 -12
  239. package/src/runtime/sidechain-output.ts +6 -2
  240. package/src/runtime/single-agent-compose.ts +1 -4
  241. package/src/runtime/skill-effectiveness.ts +29 -97
  242. package/src/runtime/skill-instructions.ts +40 -83
  243. package/src/runtime/stale-reconciler.ts +73 -197
  244. package/src/runtime/stream-preview.ts +1 -1
  245. package/src/runtime/streaming-output.ts +1 -1
  246. package/src/runtime/subagent-manager.ts +44 -169
  247. package/src/runtime/subprocess-tool-registry.ts +4 -1
  248. package/src/runtime/supervisor-contact.ts +10 -5
  249. package/src/runtime/task-display.ts +19 -5
  250. package/src/runtime/task-graph-scheduler.ts +95 -21
  251. package/src/runtime/task-graph.ts +5 -11
  252. package/src/runtime/task-health.ts +54 -47
  253. package/src/runtime/task-id.ts +12 -19
  254. package/src/runtime/task-output-context.ts +265 -81
  255. package/src/runtime/task-packet.ts +12 -20
  256. package/src/runtime/task-quality.ts +6 -14
  257. package/src/runtime/task-runner/context-retrieval.ts +4 -13
  258. package/src/runtime/task-runner/live-executor.ts +114 -36
  259. package/src/runtime/task-runner/output-splitter.ts +152 -0
  260. package/src/runtime/task-runner/progress.ts +50 -12
  261. package/src/runtime/task-runner/prompt-builder.ts +31 -7
  262. package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
  263. package/src/runtime/task-runner/result-utils.ts +3 -1
  264. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  265. package/src/runtime/task-runner/run-projection.ts +27 -8
  266. package/src/runtime/task-runner/state-helpers.ts +50 -14
  267. package/src/runtime/task-runner/tail-read.ts +2 -6
  268. package/src/runtime/task-runner.ts +180 -326
  269. package/src/runtime/team-runner-artifacts.ts +13 -0
  270. package/src/runtime/team-runner.ts +456 -974
  271. package/src/runtime/tool-output-pruner.ts +6 -9
  272. package/src/runtime/tool-progress.ts +11 -21
  273. package/src/runtime/verification-gates.ts +33 -24
  274. package/src/runtime/verification-integrity.ts +2 -7
  275. package/src/runtime/verification-worktree.ts +62 -12
  276. package/src/runtime/worker-heartbeat.ts +5 -1
  277. package/src/runtime/worker-startup.ts +29 -5
  278. package/src/runtime/workflow-state.ts +17 -9
  279. package/src/runtime/workspace-lock.ts +30 -35
  280. package/src/runtime/workspace-tree.ts +20 -32
  281. package/src/runtime/yield-handler.ts +43 -9
  282. package/src/runtime/zombie-scanner.ts +5 -4
  283. package/src/schema/config-schema.ts +266 -172
  284. package/src/schema/team-tool-schema.ts +29 -74
  285. package/src/schema/validation-types.ts +25 -17
  286. package/src/skills/discover-skills.ts +35 -10
  287. package/src/skills/skill-templates.ts +109 -27
  288. package/src/skills/validate.ts +26 -8
  289. package/src/state/active-run-registry.ts +87 -28
  290. package/src/state/artifact-store.ts +9 -5
  291. package/src/state/atomic-write-v2.ts +85 -63
  292. package/src/state/atomic-write.ts +106 -27
  293. package/src/state/blob-store.ts +47 -20
  294. package/src/state/contracts.ts +20 -5
  295. package/src/state/crew-init.ts +5 -22
  296. package/src/state/decision-ledger.ts +19 -73
  297. package/src/state/event-log-rotation.ts +41 -15
  298. package/src/state/event-log.ts +168 -53
  299. package/src/state/event-reconstructor.ts +11 -1
  300. package/src/state/gitignore-manager.ts +2 -8
  301. package/src/state/health-store.ts +57 -57
  302. package/src/state/hook-instinct-bridge.ts +1 -1
  303. package/src/state/hook-integrations.ts +1 -1
  304. package/src/state/instinct-store.ts +17 -5
  305. package/src/state/jsonl-writer.ts +1 -1
  306. package/src/state/locks.ts +23 -9
  307. package/src/state/mailbox.ts +151 -28
  308. package/src/state/observation-store.ts +20 -14
  309. package/src/state/run-cache.ts +142 -135
  310. package/src/state/run-graph.ts +6 -15
  311. package/src/state/run-metrics.ts +5 -18
  312. package/src/state/schedule.ts +15 -9
  313. package/src/state/state-store.ts +137 -47
  314. package/src/state/task-claims.ts +12 -2
  315. package/src/state/tiered-eval.ts +52 -43
  316. package/src/state/types-eval.ts +2 -2
  317. package/src/state/types.ts +24 -20
  318. package/src/state/usage.ts +20 -4
  319. package/src/state/worker-atomic-writer.ts +6 -3
  320. package/src/subagents/index.ts +2 -2
  321. package/src/teams/discover-teams.ts +21 -6
  322. package/src/tools/safe-bash-extension.ts +5 -6
  323. package/src/tools/safe-bash.ts +10 -11
  324. package/src/types/new-api-types.ts +6 -10
  325. package/src/ui/agent-management-overlay.ts +52 -40
  326. package/src/ui/card-colors.ts +13 -4
  327. package/src/ui/crew-footer.ts +8 -7
  328. package/src/ui/crew-select-list.ts +1 -1
  329. package/src/ui/dashboard-panes/agents-pane.ts +41 -25
  330. package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
  331. package/src/ui/dashboard-panes/capability-pane.ts +32 -15
  332. package/src/ui/dashboard-panes/health-pane.ts +2 -1
  333. package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
  334. package/src/ui/dashboard-panes/progress-pane.ts +12 -9
  335. package/src/ui/heartbeat-aggregator.ts +15 -4
  336. package/src/ui/keybinding-map.ts +40 -7
  337. package/src/ui/live-conversation-overlay.ts +36 -20
  338. package/src/ui/live-duration.ts +1 -4
  339. package/src/ui/live-run-sidebar.ts +88 -25
  340. package/src/ui/loaders.ts +2 -8
  341. package/src/ui/mascot.ts +20 -36
  342. package/src/ui/overlays/agent-picker-overlay.ts +11 -3
  343. package/src/ui/overlays/confirm-overlay.ts +4 -2
  344. package/src/ui/overlays/help-overlay.ts +25 -14
  345. package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
  346. package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
  347. package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
  348. package/src/ui/pi-ui-compat.ts +7 -7
  349. package/src/ui/powerbar-publisher.ts +120 -42
  350. package/src/ui/render-diff.ts +10 -3
  351. package/src/ui/render-scheduler.ts +12 -4
  352. package/src/ui/run-action-dispatcher.ts +81 -18
  353. package/src/ui/run-dashboard.ts +172 -76
  354. package/src/ui/run-event-bus.ts +59 -37
  355. package/src/ui/run-snapshot-cache.ts +276 -86
  356. package/src/ui/settings-overlay.ts +361 -74
  357. package/src/ui/status-colors.ts +12 -1
  358. package/src/ui/syntax-highlight.ts +1 -1
  359. package/src/ui/terminal-status.ts +1 -3
  360. package/src/ui/theme-adapter.ts +16 -14
  361. package/src/ui/theme-discovery.ts +13 -2
  362. package/src/ui/tool-progress-formatter.ts +7 -7
  363. package/src/ui/tool-render.ts +128 -56
  364. package/src/ui/tool-renderers/brief-mode.ts +45 -27
  365. package/src/ui/tool-renderers/index.ts +109 -43
  366. package/src/ui/transcript-cache.ts +32 -6
  367. package/src/ui/transcript-entries.ts +25 -23
  368. package/src/ui/transcript-viewer.ts +78 -29
  369. package/src/ui/widget/index.ts +99 -40
  370. package/src/ui/widget/widget-formatters.ts +13 -6
  371. package/src/ui/widget/widget-model.ts +19 -8
  372. package/src/ui/widget/widget-renderer.ts +23 -13
  373. package/src/ui/widget/widget-types.ts +1 -1
  374. package/src/utils/bm25-search.ts +199 -199
  375. package/src/utils/conflict-detect.ts +22 -21
  376. package/src/utils/env-filter.ts +14 -7
  377. package/src/utils/file-coalescer.ts +5 -1
  378. package/src/utils/fingerprint.ts +3 -6
  379. package/src/utils/frontmatter.ts +3 -1
  380. package/src/utils/fs-watch.ts +2 -6
  381. package/src/utils/gh-protocol.ts +119 -44
  382. package/src/utils/git.ts +13 -15
  383. package/src/utils/guards.ts +2 -5
  384. package/src/utils/ids.ts +9 -2
  385. package/src/utils/incremental-reader.ts +14 -3
  386. package/src/utils/internal-error.ts +2 -1
  387. package/src/utils/names.ts +12 -3
  388. package/src/utils/paths.ts +49 -5
  389. package/src/utils/project-detector.ts +2 -2
  390. package/src/utils/redaction.ts +29 -19
  391. package/src/utils/resolve-shell.ts +9 -7
  392. package/src/utils/run-watcher-registry.ts +19 -31
  393. package/src/utils/safe-paths.ts +46 -29
  394. package/src/utils/scan-cache.ts +9 -2
  395. package/src/utils/session-utils.ts +2 -4
  396. package/src/utils/sleep.ts +12 -5
  397. package/src/utils/sse-parser.ts +5 -17
  398. package/src/utils/visual.ts +52 -32
  399. package/src/workflows/discover-workflows.ts +41 -109
  400. package/src/workflows/intermediate-store.ts +5 -21
  401. package/src/workflows/preflight-validator.ts +6 -33
  402. package/src/workflows/topology-analyzer.ts +5 -21
  403. package/src/workflows/workflow-config.ts +7 -6
  404. package/src/worktree/branch-freshness.ts +66 -8
  405. package/src/worktree/cleanup.ts +130 -20
  406. package/src/worktree/worktree-manager.ts +212 -69
  407. package/skills/artifact-analysis-loop/SKILL.md +0 -303
  408. package/skills/detection-pipeline-design/SKILL.md +0 -286
  409. package/skills/hunting-investigation-loop/SKILL.md +0 -402
  410. package/skills/incident-playbook-construction/SKILL.md +0 -384
  411. package/skills/security-review/SKILL.md +0 -561
  412. package/skills/threat-hypothesis-framework/SKILL.md +0 -176
  413. package/skills/ui-render-performance/SKILL.md +0 -58
  414. /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
  415. /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
  416. /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
  417. /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
  418. /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
  419. /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
  420. /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
  421. /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
  422. /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
  423. /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
  424. /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
  425. /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
  426. /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
  427. /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
  428. /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
  429. /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
  430. /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
  431. /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
  432. /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
  433. /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
  434. /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
  435. /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
@@ -1,11 +1,11 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
5
4
  import { errors } from "../errors.ts";
5
+ import { saveRunManifest } from "../state/state-store.ts";
6
+ import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
6
7
  import { recordFromTask, upsertCrewAgent } from "./crew-agent-records.ts";
7
8
  import { checkProcessLiveness } from "./process-status.ts";
8
- import { saveRunManifest } from "../state/state-store.ts";
9
9
 
10
10
  /** Age threshold for orphaned temp directory cleanup: 1 hour. */
11
11
  const ORPHAN_TEMP_DIR_AGE_THRESHOLD_MS = 60 * 60 * 1000;
@@ -22,13 +22,7 @@ const ORPHAN_TEMP_SCAN_BATCH_SIZE = 50;
22
22
  export interface ReconcileResult {
23
23
  runId: string;
24
24
  /** What was found and what action was taken */
25
- verdict:
26
- | "healthy"
27
- | "blocked_awaiting_approval"
28
- | "result_exists"
29
- | "pid_dead"
30
- | "pid_alive_stale"
31
- | "no_status";
25
+ verdict: "healthy" | "blocked_awaiting_approval" | "result_exists" | "pid_dead" | "pid_alive_stale" | "no_status";
32
26
  /** Whether repair was applied */
33
27
  repaired: boolean;
34
28
  /** Human-readable detail */
@@ -47,11 +41,7 @@ export interface ReconcileResult {
47
41
  * original analysis of this failure mode.
48
42
  */
49
43
  export function isPlanApprovalPending(manifest: TeamRunManifest): boolean {
50
- return (
51
- manifest.status === "blocked" &&
52
- manifest.planApproval?.required === true &&
53
- manifest.planApproval.status === "pending"
54
- );
44
+ return manifest.status === "blocked" && manifest.planApproval?.required === true && manifest.planApproval.status === "pending";
55
45
  }
56
46
 
57
47
  const STALE_ALIVE_PID_MS = 24 * 60 * 60 * 1000; // 24 hours
@@ -63,10 +53,7 @@ const NO_PID_HEARTBEAT_STALE_MS = 5 * 60 * 1000; // 5 minutes — same as heartb
63
53
  * Phase 1: Check if a result file already exists for the run.
64
54
  * If so, the run completed but status wasn't updated — repair it.
65
55
  */
66
- function checkResultFile(
67
- manifest: TeamRunManifest,
68
- tasks: TeamTaskState[],
69
- ): { found: boolean; repaired: boolean } {
56
+ function checkResultFile(manifest: TeamRunManifest, tasks: TeamTaskState[]): { found: boolean; repaired: boolean } {
70
57
  // Check if all tasks already have terminal status (result was written but manifest wasn't updated)
71
58
  const allTerminal =
72
59
  tasks.length > 0 &&
@@ -87,10 +74,7 @@ function checkResultFile(
87
74
  // (e.g., a previous reconcile fixed tasks but crashed before updating agents)
88
75
  for (const task of tasks) {
89
76
  try {
90
- upsertCrewAgent(
91
- manifest,
92
- recordFromTask(manifest, task, "scaffold"),
93
- );
77
+ upsertCrewAgent(manifest, recordFromTask(manifest, task, "scaffold"));
94
78
  } catch {
95
79
  /* non-critical */
96
80
  }
@@ -114,7 +98,10 @@ function getProcessStartTime(pid: number): number | undefined {
114
98
  const stat = fs.readFileSync(`/proc/${pid}/stat`, "utf-8");
115
99
  const lastParen = stat.lastIndexOf(")");
116
100
  if (lastParen === -1) return undefined;
117
- const fieldsAfterComm = stat.slice(lastParen + 1).trim().split(/\s+/);
101
+ const fieldsAfterComm = stat
102
+ .slice(lastParen + 1)
103
+ .trim()
104
+ .split(/\s+/);
118
105
  // starttime is at index 19 (the 20th field after comm)
119
106
  const startTimeClockTicks = Number(fieldsAfterComm[19]);
120
107
  if (!Number.isFinite(startTimeClockTicks)) return undefined;
@@ -151,11 +138,7 @@ function checkPidLiveness(
151
138
  // Re-verify startTime after kill(0) to close the TOCTOU window.
152
139
  // If startTime changed, the PID was recycled to a different process.
153
140
  const startTimeAfter = getProcessStartTime(pid);
154
- if (
155
- startTimeBefore !== undefined &&
156
- startTimeAfter !== undefined &&
157
- startTimeBefore !== startTimeAfter
158
- ) {
141
+ if (startTimeBefore !== undefined && startTimeAfter !== undefined && startTimeBefore !== startTimeAfter) {
159
142
  // PID was recycled — treat as dead to avoid acting on wrong process.
160
143
  return { alive: false, detail: "pid_recycled" };
161
144
  }
@@ -166,9 +149,7 @@ function checkPidLiveness(
166
149
  const heartbeatPath = path.join(stateRoot, "heartbeat.json");
167
150
  try {
168
151
  if (fs.existsSync(heartbeatPath)) {
169
- const hb = JSON.parse(
170
- fs.readFileSync(heartbeatPath, "utf-8"),
171
- ) as { pid?: number; at?: number };
152
+ const hb = JSON.parse(fs.readFileSync(heartbeatPath, "utf-8")) as { pid?: number; at?: number };
172
153
  if (hb?.pid === pid && hb?.at) {
173
154
  const ageMs = Date.now() - hb.at;
174
155
  // Heartbeat written < 5 min ago → process was alive recently.
@@ -192,11 +173,7 @@ function checkPidLiveness(
192
173
  * Phase 3: For dead PIDs, repair immediately.
193
174
  * For alive PIDs, only mark stale if status hasn't updated in STALE_ALIVE_PID_MS.
194
175
  */
195
- function evaluateStaleness(
196
- manifest: TeamRunManifest,
197
- pidAlive: boolean,
198
- now: number,
199
- ): { stale: boolean; reason: string } {
176
+ function evaluateStaleness(manifest: TeamRunManifest, pidAlive: boolean, now: number): { stale: boolean; reason: string } {
200
177
  if (!pidAlive) {
201
178
  return { stale: true, reason: "pid_dead" };
202
179
  }
@@ -215,24 +192,11 @@ function evaluateStaleness(
215
192
 
216
193
  function hasRecentActiveEvidence(tasks: TeamTaskState[], now: number): boolean {
217
194
  return tasks.some((task) => {
218
- if (task.status !== "running" && task.status !== "waiting")
219
- return false;
220
- const heartbeatAt = task.heartbeat?.lastSeenAt
221
- ? new Date(task.heartbeat.lastSeenAt).getTime()
222
- : Number.NaN;
223
- if (
224
- task.heartbeat?.alive !== false &&
225
- Number.isFinite(heartbeatAt) &&
226
- now - heartbeatAt <= ACTIVE_EVIDENCE_TTL_MS
227
- )
228
- return true;
229
- const activityAt = task.agentProgress?.lastActivityAt
230
- ? new Date(task.agentProgress.lastActivityAt).getTime()
231
- : Number.NaN;
232
- return (
233
- Number.isFinite(activityAt) &&
234
- now - activityAt <= ACTIVE_EVIDENCE_TTL_MS
235
- );
195
+ if (task.status !== "running" && task.status !== "waiting") return false;
196
+ const heartbeatAt = task.heartbeat?.lastSeenAt ? new Date(task.heartbeat.lastSeenAt).getTime() : Number.NaN;
197
+ if (task.heartbeat?.alive !== false && Number.isFinite(heartbeatAt) && now - heartbeatAt <= ACTIVE_EVIDENCE_TTL_MS) return true;
198
+ const activityAt = task.agentProgress?.lastActivityAt ? new Date(task.agentProgress.lastActivityAt).getTime() : Number.NaN;
199
+ return Number.isFinite(activityAt) && now - activityAt <= ACTIVE_EVIDENCE_TTL_MS;
236
200
  });
237
201
  }
238
202
 
@@ -242,15 +206,10 @@ function hasRecentActiveEvidence(tasks: TeamTaskState[], now: number): boolean {
242
206
  * are considered NOT stale (they may be newly spawned and haven't reported yet).
243
207
  */
244
208
  function isTaskHeartbeatStale(task: TeamTaskState, now: number): boolean {
245
- const heartbeatAt = task.heartbeat?.lastSeenAt
246
- ? new Date(task.heartbeat.lastSeenAt).getTime()
247
- : Number.NaN;
248
- const activityAt = task.agentProgress?.lastActivityAt
249
- ? new Date(task.agentProgress.lastActivityAt).getTime()
250
- : Number.NaN;
209
+ const heartbeatAt = task.heartbeat?.lastSeenAt ? new Date(task.heartbeat.lastSeenAt).getTime() : Number.NaN;
210
+ const activityAt = task.agentProgress?.lastActivityAt ? new Date(task.agentProgress.lastActivityAt).getTime() : Number.NaN;
251
211
  // If no heartbeat AND no activity, we can't determine staleness — not stale
252
- if (!Number.isFinite(heartbeatAt) && !Number.isFinite(activityAt))
253
- return false;
212
+ if (!Number.isFinite(heartbeatAt) && !Number.isFinite(activityAt)) return false;
254
213
  // Compute elapsed from both sources and use the fresher (minimum) one,
255
214
  // mirroring heartbeat-watcher logic: if either source has recent activity,
256
215
  // the task is not stale even if the other is stale.
@@ -268,13 +227,8 @@ function isTaskHeartbeatStale(task: TeamTaskState, now: number): boolean {
268
227
  * Merged from the former allRunningTasksHeartbeatStale and
269
228
  * findIndividuallyStaleTaskIds to avoid redundant duplicate checks.
270
229
  */
271
- function getRunningTaskStaleness(
272
- tasks: TeamTaskState[],
273
- now: number,
274
- ): { allStale: boolean; staleTaskIds: string[] } {
275
- const runningTasks = tasks.filter(
276
- (t) => t.status === "running" || t.status === "waiting",
277
- );
230
+ function getRunningTaskStaleness(tasks: TeamTaskState[], now: number): { allStale: boolean; staleTaskIds: string[] } {
231
+ const runningTasks = tasks.filter((t) => t.status === "running" || t.status === "waiting");
278
232
  if (runningTasks.length === 0) return { allStale: false, staleTaskIds: [] };
279
233
  const staleTaskIds: string[] = [];
280
234
  for (const task of runningTasks) {
@@ -299,7 +253,9 @@ function getRunningTaskStaleness(
299
253
  * readable code + help hint; `.message` carries the same rich text as before.
300
254
  */
301
255
  function buildStaleReconcileError(task: TeamTaskState, reason: string): Error {
302
- const heartbeatAgeSeconds = task.heartbeat?.lastSeenAt ? Math.round((Date.now() - new Date(task.heartbeat.lastSeenAt).getTime()) / 1000) : undefined;
256
+ const heartbeatAgeSeconds = task.heartbeat?.lastSeenAt
257
+ ? Math.round((Date.now() - new Date(task.heartbeat.lastSeenAt).getTime()) / 1000)
258
+ : undefined;
303
259
  return errors.runStale(reason, heartbeatAgeSeconds);
304
260
  }
305
261
 
@@ -308,18 +264,10 @@ function formatStaleReconcileError(task: TeamTaskState, reason: string): string
308
264
  return buildStaleReconcileError(task, reason).message;
309
265
  }
310
266
 
311
- function repairStaleRun(
312
- manifest: TeamRunManifest,
313
- tasks: TeamTaskState[],
314
- reason: string,
315
- ): TeamTaskState[] {
267
+ function repairStaleRun(manifest: TeamRunManifest, tasks: TeamTaskState[], reason: string): TeamTaskState[] {
316
268
  const now = new Date().toISOString();
317
269
  const repairedTasks = tasks.map((task) => {
318
- if (
319
- task.status === "running" ||
320
- task.status === "queued" ||
321
- task.status === "waiting"
322
- ) {
270
+ if (task.status === "running" || task.status === "queued" || task.status === "waiting") {
323
271
  return {
324
272
  ...task,
325
273
  status: "cancelled" as const,
@@ -333,10 +281,7 @@ function repairStaleRun(
333
281
  // Update agent records so widget sees cancelled status immediately
334
282
  for (const task of repairedTasks) {
335
283
  try {
336
- upsertCrewAgent(
337
- manifest,
338
- recordFromTask(manifest, task, "scaffold"),
339
- );
284
+ upsertCrewAgent(manifest, recordFromTask(manifest, task, "scaffold"));
340
285
  } catch {
341
286
  /* non-critical */
342
287
  }
@@ -358,11 +303,7 @@ function repairStaleRun(
358
303
  * /tmp workspaces where concurrent access is a known benign race (separate
359
304
  * dirs, low consequence of redundant repair).
360
305
  */
361
- export function reconcileStaleRun(
362
- manifest: TeamRunManifest,
363
- tasks: TeamTaskState[],
364
- now = Date.now(),
365
- ): ReconcileResult {
306
+ export function reconcileStaleRun(manifest: TeamRunManifest, tasks: TeamTaskState[], now = Date.now()): ReconcileResult {
366
307
  const runId = manifest.runId;
367
308
 
368
309
  // Preserve runs intentionally blocked on human plan approval. These are not
@@ -414,11 +355,7 @@ export function reconcileStaleRun(
414
355
  // Merged with individual stale task check to avoid redundant duplicate checks.
415
356
  const { allStale, staleTaskIds } = getRunningTaskStaleness(tasks, now);
416
357
  if (allStale) {
417
- const repaired = repairStaleRun(
418
- manifest,
419
- tasks,
420
- "no_pid_heartbeat_stale",
421
- );
358
+ const repaired = repairStaleRun(manifest, tasks, "no_pid_heartbeat_stale");
422
359
  return {
423
360
  runId,
424
361
  verdict: "no_status",
@@ -449,10 +386,7 @@ export function reconcileStaleRun(
449
386
  // Fall through: no recent activity but not all tasks stale enough yet.
450
387
  // Check the longer STALE_ALIVE_PID_MS threshold for very old runs.
451
388
  const updatedAt = new Date(manifest.updatedAt).getTime();
452
- if (
453
- Number.isFinite(updatedAt) &&
454
- now - updatedAt > STALE_ALIVE_PID_MS
455
- ) {
389
+ if (Number.isFinite(updatedAt) && now - updatedAt > STALE_ALIVE_PID_MS) {
456
390
  const repaired = repairStaleRun(manifest, tasks, "no_pid_stale");
457
391
  return {
458
392
  runId,
@@ -515,7 +449,11 @@ export interface OrphanReconcileResult {
515
449
  */
516
450
  export function reconcileOrphanedTempWorkspaces(
517
451
  now = Date.now(),
518
- options?: { cleanupOrphanedTempDirs?: boolean; tmpDir?: string; scanBatchSize?: number },
452
+ options?: {
453
+ cleanupOrphanedTempDirs?: boolean;
454
+ tmpDir?: string;
455
+ scanBatchSize?: number;
456
+ },
519
457
  ): OrphanReconcileResult {
520
458
  // Injectable tmpDir + scanBatchSize for deterministic unit testing
521
459
  // (Round 19: tests must not depend on global /tmp cleanliness; the
@@ -536,8 +474,7 @@ export function reconcileOrphanedTempWorkspaces(
536
474
  .sort((a, b) => a.name.localeCompare(b.name))
537
475
  .slice(0, scanBatch);
538
476
  for (const entry of candidates) {
539
- if (!entry.isDirectory() || !entry.name.startsWith("pi-crew-"))
540
- continue;
477
+ if (!entry.isDirectory() || !entry.name.startsWith("pi-crew-")) continue;
541
478
  const workspaceDir = path.join(tmpDir, entry.name);
542
479
  const crewDir = path.join(workspaceDir, ".crew");
543
480
  if (!fs.existsSync(crewDir)) continue;
@@ -546,36 +483,17 @@ export function reconcileOrphanedTempWorkspaces(
546
483
  let hasRunning = false;
547
484
  try {
548
485
  for (const runDir of fs.readdirSync(stateRunsDir)) {
549
- const manifestPath = path.join(
550
- stateRunsDir,
551
- runDir,
552
- "manifest.json",
553
- );
554
- const tasksPath = path.join(
555
- stateRunsDir,
556
- runDir,
557
- "tasks.json",
558
- );
559
- if (
560
- !fs.existsSync(manifestPath) ||
561
- !fs.existsSync(tasksPath)
562
- )
563
- continue;
486
+ const manifestPath = path.join(stateRunsDir, runDir, "manifest.json");
487
+ const tasksPath = path.join(stateRunsDir, runDir, "tasks.json");
488
+ if (!fs.existsSync(manifestPath) || !fs.existsSync(tasksPath)) continue;
564
489
  try {
565
- const manifest: TeamRunManifest = JSON.parse(
566
- fs.readFileSync(manifestPath, "utf-8"),
567
- );
490
+ const manifest: TeamRunManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
568
491
  if (manifest.status !== "running") continue;
569
- const tasks: TeamTaskState[] = JSON.parse(
570
- fs.readFileSync(tasksPath, "utf-8"),
571
- );
492
+ const tasks: TeamTaskState[] = JSON.parse(fs.readFileSync(tasksPath, "utf-8"));
572
493
  const result = reconcileStaleRun(manifest, tasks, now);
573
494
  if (result.repaired && result.repairedTasks) {
574
495
  // Persist repaired tasks
575
- fs.writeFileSync(
576
- tasksPath,
577
- JSON.stringify(result.repairedTasks, null, 2),
578
- );
496
+ fs.writeFileSync(tasksPath, JSON.stringify(result.repairedTasks, null, 2));
579
497
  // Update manifest status
580
498
  const updated = {
581
499
  ...manifest,
@@ -583,21 +501,11 @@ export function reconcileOrphanedTempWorkspaces(
583
501
  updatedAt: new Date(now).toISOString(),
584
502
  summary: `Stale run reconciled: ${result.detail}`,
585
503
  };
586
- fs.writeFileSync(
587
- manifestPath,
588
- JSON.stringify(updated, null, 2),
589
- );
504
+ fs.writeFileSync(manifestPath, JSON.stringify(updated, null, 2));
590
505
  // Update agent records
591
506
  for (const task of result.repairedTasks) {
592
507
  try {
593
- upsertCrewAgent(
594
- updated,
595
- recordFromTask(
596
- updated,
597
- task,
598
- "scaffold",
599
- ),
600
- );
508
+ upsertCrewAgent(updated, recordFromTask(updated, task, "scaffold"));
601
509
  } catch {
602
510
  /* non-critical */
603
511
  }
@@ -605,48 +513,38 @@ export function reconcileOrphanedTempWorkspaces(
605
513
  repaired++;
606
514
  }
607
515
  // Persist result_exists manifest status update
608
- if (result.verdict === "result_exists") {
609
- // checkResultFile (called by reconcileStaleRun at line 518)
610
- // already saved manifest.status='completed' at line 66.
611
- // No additional manifest write needed here — avoids TOCTOU
612
- // window between checkResultFile save and re-write.
613
- // Sync agent records (checkResultFile also does this but
614
- // we sync here for consistency)
615
- for (const task of tasks) {
616
- try {
617
- upsertCrewAgent(
618
- manifest,
619
- recordFromTask(manifest, task, "scaffold"),
620
- );
621
- } catch {
622
- /* non-critical */
623
- }
516
+ if (result.verdict === "result_exists") {
517
+ // checkResultFile (called by reconcileStaleRun at line 518)
518
+ // already saved manifest.status='completed' at line 66.
519
+ // No additional manifest write needed here — avoids TOCTOU
520
+ // window between checkResultFile save and re-write.
521
+ // Sync agent records (checkResultFile also does this but
522
+ // we sync here for consistency)
523
+ for (const task of tasks) {
524
+ try {
525
+ upsertCrewAgent(manifest, recordFromTask(manifest, task, "scaffold"));
526
+ } catch {
527
+ /* non-critical */
624
528
  }
625
529
  }
626
- // If still running after reconciliation attempt, mark for dir-preserving
627
- if (
628
- result.verdict === "healthy" ||
629
- (result.verdict === "no_status" && !result.repaired)
630
- ) {
631
- hasRunning = true;
632
- }
530
+ }
531
+ // If still running after reconciliation attempt, mark for dir-preserving
532
+ if (result.verdict === "healthy" || (result.verdict === "no_status" && !result.repaired)) {
533
+ hasRunning = true;
534
+ }
633
535
  } catch (err) {
634
536
  // Log warning when skipping a directory due to error.
635
537
  // Note: manifestPath here refers to the variable defined in the
636
538
  // for loop at line 442 (outer scope of this catch block).
637
539
  const scanManifestPath = manifestPath;
638
- console.warn(
639
- `[stale-reconciler] Skipping manifest due to parse error: ${scanManifestPath}: ${err}`,
640
- );
540
+ console.warn(`[stale-reconciler] Skipping manifest due to parse error: ${scanManifestPath}: ${err}`);
641
541
  }
642
542
  }
643
543
  } catch (err) {
644
544
  // Cannot determine running state — treat as if running to prevent
645
545
  // premature cleanup of a potentially active workspace.
646
546
  hasRunning = true;
647
- console.warn(
648
- `[stale-reconciler] Skipping unreadable runs dir: ${stateRunsDir}: ${err}`,
649
- );
547
+ console.warn(`[stale-reconciler] Skipping unreadable runs dir: ${stateRunsDir}: ${err}`);
650
548
  }
651
549
 
652
550
  // Post-loop: check if this workspace dir can be cleaned up.
@@ -696,22 +594,14 @@ export function reconcileOrphanedTempWorkspaces(
696
594
  if (fs.existsSync(stateRunsDir)) {
697
595
  try {
698
596
  for (const runDir of fs.readdirSync(stateRunsDir)) {
699
- const manifestPath = path.join(
700
- stateRunsDir,
701
- runDir,
702
- "manifest.json",
703
- );
597
+ const manifestPath = path.join(stateRunsDir, runDir, "manifest.json");
704
598
  if (!fs.existsSync(manifestPath)) continue;
705
599
  let manifest: TeamRunManifest | undefined;
706
600
  try {
707
- manifest = JSON.parse(
708
- fs.readFileSync(manifestPath, "utf-8"),
709
- );
601
+ manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
710
602
  } catch (err) {
711
603
  // Log warning when skipping a directory due to error
712
- console.warn(
713
- `[stale-reconciler] Skipping manifest due to parse error: ${manifestPath}: ${err}`,
714
- );
604
+ console.warn(`[stale-reconciler] Skipping manifest due to parse error: ${manifestPath}: ${err}`);
715
605
  continue;
716
606
  }
717
607
  if (manifest?.status === "running") {
@@ -720,9 +610,7 @@ export function reconcileOrphanedTempWorkspaces(
720
610
  }
721
611
  }
722
612
  } catch (err) {
723
- console.warn(
724
- `[stale-reconciler] Skipping unreadable runs dir: ${stateRunsDir}: ${err}`,
725
- );
613
+ console.warn(`[stale-reconciler] Skipping unreadable runs dir: ${stateRunsDir}: ${err}`);
726
614
  }
727
615
  }
728
616
  }
@@ -733,16 +621,10 @@ export function reconcileOrphanedTempWorkspaces(
733
621
  if (fs.existsSync(stateRunsDir)) {
734
622
  try {
735
623
  for (const runDir of fs.readdirSync(stateRunsDir)) {
736
- const manifestPath = path.join(
737
- stateRunsDir,
738
- runDir,
739
- "manifest.json",
740
- );
624
+ const manifestPath = path.join(stateRunsDir, runDir, "manifest.json");
741
625
  if (!fs.existsSync(manifestPath)) continue;
742
626
  try {
743
- const manifest: TeamRunManifest = JSON.parse(
744
- fs.readFileSync(manifestPath, "utf-8"),
745
- );
627
+ const manifest: TeamRunManifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
746
628
  if (manifest.status === "running") {
747
629
  stillClean = false;
748
630
  break;
@@ -777,16 +659,10 @@ export function reconcileOrphanedTempWorkspaces(
777
659
  if (fs.existsSync(stateRunsDir)) {
778
660
  try {
779
661
  for (const runDir of fs.readdirSync(stateRunsDir)) {
780
- const manifestPath = path.join(
781
- stateRunsDir,
782
- runDir,
783
- "manifest.json",
784
- );
662
+ const manifestPath = path.join(stateRunsDir, runDir, "manifest.json");
785
663
  if (!fs.existsSync(manifestPath)) continue;
786
664
  try {
787
- const m = JSON.parse(
788
- fs.readFileSync(manifestPath, "utf-8"),
789
- ) as TeamRunManifest;
665
+ const m = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as TeamRunManifest;
790
666
  if (m.status === "running") {
791
667
  hasRunningManifest = true;
792
668
  break;
@@ -2,8 +2,8 @@
2
2
  // Captures incremental worker output during task execution for live preview.
3
3
  // Used by the UI layer to show partial results before task completion.
4
4
 
5
- import type { ParsedPiUsage } from "./pi-json-output.ts";
6
5
  import { TAIL_CAPTURE_STREAM_STAGE } from "./compact-stages/index.ts";
6
+ import type { ParsedPiUsage } from "./pi-json-output.ts";
7
7
 
8
8
  export interface ToolCallPreview {
9
9
  toolName: string;
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { isSafePathId } from "../utils/safe-paths.ts";
4
3
  import type { TeamRunManifest } from "../state/types.ts";
4
+ import { isSafePathId } from "../utils/safe-paths.ts";
5
5
 
6
6
  export interface StreamingOutputHandle {
7
7
  write(text: string): void;