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,20 +1,20 @@
1
1
  import * as fs from "node:fs";
2
2
  import type { CrewUiConfig } from "../config/config.ts";
3
- import { readCrewAgents } from "../runtime/crew-agent-records.ts";
4
3
  import { applyAttentionState, resolveCrewControlConfig } from "../runtime/agent-control.ts";
4
+ import { readCrewAgents } from "../runtime/crew-agent-records.ts";
5
5
  import { formatTaskGraphLines, waitingReason } from "../runtime/task-display.ts";
6
6
  import { loadRunManifestById } from "../state/state-store.ts";
7
- import { aggregateUsage, formatUsage } from "../state/usage.ts";
8
7
  import type { TeamTaskState } from "../state/types.ts";
8
+ import { aggregateUsage, formatUsage } from "../state/usage.ts";
9
9
  import { readJsonFileCoalesced } from "../utils/file-coalescer.ts";
10
10
  import { pad, truncate } from "../utils/visual.ts";
11
- import { colorizeStatusGlyphs, iconForStatus } from "./status-colors.ts";
12
- import type { CrewTheme } from "./theme-adapter.ts";
13
- import { asCrewTheme, subscribeThemeChange } from "./theme-adapter.ts";
14
11
  import { Box, Text } from "./layout-primitives.ts";
12
+ import { runEventBus } from "./run-event-bus.ts";
15
13
  import type { RunSnapshotCache, RunUiSnapshot } from "./snapshot-types.ts";
16
14
  import { spinnerBucket, spinnerFrame } from "./spinner.ts";
17
- import { runEventBus } from "./run-event-bus.ts";
15
+ import { colorizeStatusGlyphs, iconForStatus } from "./status-colors.ts";
16
+ import type { CrewTheme } from "./theme-adapter.ts";
17
+ import { asCrewTheme, subscribeThemeChange } from "./theme-adapter.ts";
18
18
 
19
19
  const TASK_READ_TTL_MS = 200;
20
20
 
@@ -68,7 +68,14 @@ export class LiveRunSidebar {
68
68
  private autoCloseTimeout?: NodeJS.Timeout;
69
69
  private hasAutoClosed = false;
70
70
 
71
- constructor(input: { cwd: string; runId: string; done: Done; theme?: unknown; config?: CrewUiConfig; snapshotCache?: RunSnapshotCache }) {
71
+ constructor(input: {
72
+ cwd: string;
73
+ runId: string;
74
+ done: Done;
75
+ theme?: unknown;
76
+ config?: CrewUiConfig;
77
+ snapshotCache?: RunSnapshotCache;
78
+ }) {
72
79
  this.cwd = input.cwd;
73
80
  this.runId = input.runId;
74
81
  this.done = input.done;
@@ -77,18 +84,49 @@ export class LiveRunSidebar {
77
84
  this.snapshotCache = input.snapshotCache;
78
85
  this.unsubscribeTheme = subscribeThemeChange(input.theme, () => this.invalidate());
79
86
  this.unsubscribeEventBus = (() => {
80
- const unsub1 = runEventBus.onChannel("run:state", () => this.invalidate());
81
- const unsub2 = runEventBus.onChannel("worker:lifecycle", () => this.invalidate());
82
- const unsub3 = runEventBus.onChannel("ui:invalidate", () => this.invalidate());
83
- return () => { unsub1(); unsub2(); unsub3(); };
84
- })();
87
+ const unsub1 = runEventBus.onChannel("run:state", () => this.invalidate());
88
+ const unsub2 = runEventBus.onChannel("worker:lifecycle", () => this.invalidate());
89
+ const unsub3 = runEventBus.onChannel("ui:invalidate", () => this.invalidate());
90
+ return () => {
91
+ unsub1();
92
+ unsub2();
93
+ unsub3();
94
+ };
95
+ })();
85
96
  }
86
97
 
87
- private buildSignature(manifestStatus: string, tasks: TeamTaskState[], agents: ReturnType<typeof readCrewAgents>, waitingCount: number, snapshot?: RunUiSnapshot): string {
98
+ private buildSignature(
99
+ manifestStatus: string,
100
+ tasks: TeamTaskState[],
101
+ agents: ReturnType<typeof readCrewAgents>,
102
+ waitingCount: number,
103
+ snapshot?: RunUiSnapshot,
104
+ ): string {
88
105
  const animation = agents.some((agent) => agent.status === "running") ? `:spin=${spinnerBucket()}` : "";
89
106
  if (snapshot) return `${snapshot.signature}:${waitingCount}${animation}`;
90
- const taskSig = tasks.map((task) => `${task.id}:${task.status}:${task.startedAt ?? ""}:${task.finishedAt ?? ""}:${task.agentProgress?.currentTool ?? ""}:${task.agentProgress?.toolCount ?? 0}:${task.agentProgress?.tokens ?? 0}:${task.usage ? JSON.stringify(task.usage) : ""}`).join("|");
91
- const agentSig = agents.map((agent) => [agent.id, agent.status, agent.startedAt, agent.completedAt ?? "", agent.progress?.currentTool ?? "", agent.progress?.toolCount ?? 0, agent.progress?.tokens ?? 0, agent.progress?.turns ?? 0, agent.progress?.lastActivityAt ?? "", agent.progress?.recentOutput?.at(-1) ?? "", agent.toolUses ?? 0].join(":")).join("|");
107
+ const taskSig = tasks
108
+ .map(
109
+ (task) =>
110
+ `${task.id}:${task.status}:${task.startedAt ?? ""}:${task.finishedAt ?? ""}:${task.agentProgress?.currentTool ?? ""}:${task.agentProgress?.toolCount ?? 0}:${task.agentProgress?.tokens ?? 0}:${task.usage ? JSON.stringify(task.usage) : ""}`,
111
+ )
112
+ .join("|");
113
+ const agentSig = agents
114
+ .map((agent) =>
115
+ [
116
+ agent.id,
117
+ agent.status,
118
+ agent.startedAt,
119
+ agent.completedAt ?? "",
120
+ agent.progress?.currentTool ?? "",
121
+ agent.progress?.toolCount ?? 0,
122
+ agent.progress?.tokens ?? 0,
123
+ agent.progress?.turns ?? 0,
124
+ agent.progress?.lastActivityAt ?? "",
125
+ agent.progress?.recentOutput?.at(-1) ?? "",
126
+ agent.toolUses ?? 0,
127
+ ].join(":"),
128
+ )
129
+ .join("|");
92
130
  return `${manifestStatus}|${agents.length}|${waitingCount}|${taskSig}|${agentSig}${animation}`;
93
131
  }
94
132
 
@@ -152,9 +190,10 @@ export class LiveRunSidebar {
152
190
  // user sees *why* a run ended without having to switch panes. The reason
153
191
  // is already computed on the consumed snapshot (cancellationReason).
154
192
  const TERMINAL_WITH_REASON = ["failed", "cancelled", "stopped"];
155
- const reasonSuffix = TERMINAL_WITH_REASON.includes(run.status) && snapshot?.cancellationReason
156
- ? ` · ${truncate(snapshot.cancellationReason, 40)}`
157
- : "";
193
+ const reasonSuffix =
194
+ TERMINAL_WITH_REASON.includes(run.status) && snapshot?.cancellationReason
195
+ ? ` · ${truncate(snapshot.cancellationReason, 40)}`
196
+ : "";
158
197
  const lines: string[] = [
159
198
  border("╭", "─", "╮", w),
160
199
  line(`${this.theme.fg("accent", "▐")} ${this.theme.bold("pi-crew live sidebar")}`, w),
@@ -164,11 +203,27 @@ export class LiveRunSidebar {
164
203
  line(`Active agents (${active.length})`, w),
165
204
  ];
166
205
  for (const agent of active.slice(0, 8)) {
167
- const status = iconForStatus(agent.status, { runningGlyph: spinnerFrame(agent.taskId) });
168
- const usage = agent.usage ? formatUsage(agent.usage) : agent.progress?.tokens ? `tokens=${agent.progress.tokens}` : "usage=pending";
206
+ const status = iconForStatus(agent.status, {
207
+ runningGlyph: spinnerFrame(agent.taskId),
208
+ });
209
+ const usage = agent.usage
210
+ ? formatUsage(agent.usage)
211
+ : agent.progress?.tokens
212
+ ? `tokens=${agent.progress.tokens}`
213
+ : "usage=pending";
169
214
  lines.push(line(`${status} ${agent.taskId} ${agent.role}->${agent.agent}`, w));
170
- lines.push(line(` ${agent.routing ? `model ${agent.routing.requested ? `${agent.routing.requested} → ` : ""}${agent.routing.resolved}` : agent.model ? `model ${agent.model}` : "model pending"}`, w));
171
- lines.push(line(` ${agent.progress?.currentTool ? `tool ${agent.progress.currentTool} · ` : ""}${agent.toolUses ?? 0} tools · ${usage}`, w));
215
+ lines.push(
216
+ line(
217
+ ` ${agent.routing ? `model ${agent.routing.requested ? `${agent.routing.requested} → ` : ""}${agent.routing.resolved}` : agent.model ? `model ${agent.model}` : "model pending"}`,
218
+ w,
219
+ ),
220
+ );
221
+ lines.push(
222
+ line(
223
+ ` ${agent.progress?.currentTool ? `tool ${agent.progress.currentTool} · ` : ""}${agent.toolUses ?? 0} tools · ${usage}`,
224
+ w,
225
+ ),
226
+ );
172
227
  }
173
228
  if (!active.length) lines.push(line("- none", w));
174
229
  lines.push(border("├", "─", "┤", w), line(`Waiting tasks (${waiting.length})`, w));
@@ -180,7 +235,12 @@ export class LiveRunSidebar {
180
235
  lines.push(border("├", "─", "┤", w), line(`Completed agents (${completed.length})`, w));
181
236
  for (const agent of completed) {
182
237
  const status = iconForStatus(agent.status === "running" ? "stopped" : agent.status);
183
- lines.push(line(`${status} ${agent.taskId} ${agent.model ? `· ${agent.model}` : ""}${agent.usage ? ` · ${formatUsage(agent.usage)}` : ""}`, w));
238
+ lines.push(
239
+ line(
240
+ `${status} ${agent.taskId} ${agent.model ? `· ${agent.model}` : ""}${agent.usage ? ` · ${formatUsage(agent.usage)}` : ""}`,
241
+ w,
242
+ ),
243
+ );
184
244
  }
185
245
  if (completed.length === 0) lines.push(line("- none", w));
186
246
  lines.push(border("├", "─", "┤", w));
@@ -192,7 +252,7 @@ export class LiveRunSidebar {
192
252
  const isTerminal = ["completed", "failed", "cancelled", "blocked"].includes(run.status);
193
253
  const hasActiveAgents = agents.some((a) => a.status === "running");
194
254
  if (isTerminal && !hasActiveAgents && !this.hasAutoClosed) {
195
- const autoCloseMs = (this.config?.autoCloseDashboardMs ?? 3000);
255
+ const autoCloseMs = this.config?.autoCloseDashboardMs ?? 3000;
196
256
  if (autoCloseMs > 0) {
197
257
  this.autoCloseTimeout = setTimeout(() => {
198
258
  this.hasAutoClosed = true;
@@ -207,7 +267,10 @@ export class LiveRunSidebar {
207
267
  this.autoCloseTimeout = undefined;
208
268
  }
209
269
  lines.push(border("╰", "─", "╯", w));
210
- this.cachedLines = renderLines(lines.map((entry) => this.colorLine(entry)), w);
270
+ this.cachedLines = renderLines(
271
+ lines.map((entry) => this.colorLine(entry)),
272
+ w,
273
+ );
211
274
  this.cachedSignature = signature;
212
275
  this.cachedWidth = w;
213
276
  }
package/src/ui/loaders.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { pad, truncate } from "../utils/visual.ts";
2
+ import { DynamicCrewBorder } from "./dynamic-border.ts";
2
3
  import type { CrewTheme } from "./theme-adapter.ts";
3
4
  import { asCrewTheme } from "./theme-adapter.ts";
4
- import { DynamicCrewBorder } from "./dynamic-border.ts";
5
5
 
6
6
  export interface BorderedLoaderOptions {
7
7
  message: string;
@@ -79,13 +79,7 @@ export class CrewBorderedLoader {
79
79
  const bottom = `${leftRightPad}${this.theme.fg("border", "└")}${border}${this.theme.fg("border", "┘")}`;
80
80
  const lineWithHint = optionsHint(this.theme, this.message, widthAwareInner);
81
81
  this.width = width;
82
- const lines = [
83
- top,
84
- line,
85
- `${leftRightPad}│ ${pad(lineWithHint, widthAwareInner)} │`,
86
- hint,
87
- bottom,
88
- ];
82
+ const lines = [top, line, `${leftRightPad}│ ${pad(lineWithHint, widthAwareInner)} │`, hint, bottom];
89
83
  this.lineCache = lines.join("\n");
90
84
  return lines;
91
85
  }
package/src/ui/mascot.ts CHANGED
@@ -1,19 +1,10 @@
1
- import type { CrewTheme } from "./theme-adapter.ts";
2
- import { asCrewTheme } from "./theme-adapter.ts";
3
1
  import { pad } from "../utils/visual.ts";
4
2
  import { DynamicCrewBorder } from "./dynamic-border.ts";
3
+ import type { CrewTheme } from "./theme-adapter.ts";
4
+ import { asCrewTheme } from "./theme-adapter.ts";
5
5
 
6
6
  export type MascotStyle = "cat" | "armin";
7
- export type MascotEffect =
8
- | "random"
9
- | "none"
10
- | "typewriter"
11
- | "scanline"
12
- | "rain"
13
- | "fade"
14
- | "crt"
15
- | "glitch"
16
- | "dissolve";
7
+ export type MascotEffect = "random" | "none" | "typewriter" | "scanline" | "rain" | "fade" | "crt" | "glitch" | "dissolve";
17
8
 
18
9
  interface AnimatedMascotOptions {
19
10
  frameIntervalMs?: number;
@@ -36,28 +27,19 @@ const CAT_FRAMES: readonly (readonly string[])[] = [
36
27
  const ARMIN_WIDTH = 31;
37
28
  const ARMIN_HEIGHT = 36;
38
29
  const ARMIN_BITS: readonly number[] = [
39
- 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf0, 0xff, 0x7f, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdb, 0xff, 0x7f, 0xff, 0xb7, 0xff,
40
- 0x7f, 0xff, 0x77, 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f, 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3,
41
- 0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f, 0xf7, 0x0f, 0xf7, 0x7f, 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7,
42
- 0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70, 0x0f, 0xff, 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53,
43
- 0xc1, 0xff, 0xef, 0x57, 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f, 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50,
44
- 0x6c, 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03, 0x9c, 0x78, 0xff, 0x07,
45
- 0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78, 0xff, 0xff, 0xdf, 0x78, 0xff,
46
- 0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f,
30
+ 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf0, 0xff, 0x7f, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdb, 0xff, 0x7f, 0xff, 0xb7, 0xff, 0x7f, 0xff, 0x77,
31
+ 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f, 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3, 0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f,
32
+ 0xf7, 0x0f, 0xf7, 0x7f, 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7, 0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70, 0x0f, 0xff,
33
+ 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53, 0xc1, 0xff, 0xef, 0x57, 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f,
34
+ 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50, 0x6c, 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03,
35
+ 0x9c, 0x78, 0xff, 0x07, 0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78, 0xff, 0xff, 0xdf, 0x78,
36
+ 0xff, 0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f,
47
37
  ];
48
38
 
49
39
  const ARMIN_BYTES_PER_ROW = Math.ceil(ARMIN_WIDTH / 8);
50
40
  const ARMIN_DISPLAY_HEIGHT = Math.ceil(ARMIN_HEIGHT / 2);
51
41
 
52
- const NON_NONE_EFFECTS: MascotEffect[] = [
53
- "typewriter",
54
- "scanline",
55
- "rain",
56
- "fade",
57
- "crt",
58
- "glitch",
59
- "dissolve",
60
- ];
42
+ const NON_NONE_EFFECTS: MascotEffect[] = ["typewriter", "scanline", "rain", "fade", "crt", "glitch", "dissolve"];
61
43
  const CAT_FRIENDLY_EFFECTS: MascotEffect[] = ["scanline", "glitch", "crt"];
62
44
 
63
45
  function getArminPixel(x: number, y: number): boolean {
@@ -379,9 +361,7 @@ export class AnimatedMascot {
379
361
  if (this.effect === "none") return [...lines];
380
362
  if (this.effect === "scanline") {
381
363
  const scanRow = this.effectPhase % (lines.length + 4);
382
- return lines.map((ln, i) =>
383
- i === scanRow ? this.theme.bold(this.theme.fg("accent", ln)) : ln,
384
- );
364
+ return lines.map((ln, i) => (i === scanRow ? this.theme.bold(this.theme.fg("accent", ln)) : ln));
385
365
  }
386
366
  if (this.effect === "glitch") {
387
367
  if (this.effectPhase % 9 !== 0) return [...lines];
@@ -399,7 +379,12 @@ export class AnimatedMascot {
399
379
  }
400
380
 
401
381
  render(width: number): string[] {
402
- if (width === this.cachedWidth && this.cachedVersion === this.gridVersion && this.cachedFrame === this.frame && this.cachedLines.length) {
382
+ if (
383
+ width === this.cachedWidth &&
384
+ this.cachedVersion === this.gridVersion &&
385
+ this.cachedFrame === this.frame &&
386
+ this.cachedLines.length
387
+ ) {
403
388
  return this.cachedLines;
404
389
  }
405
390
  const safeWidth = Math.max(20, width);
@@ -418,9 +403,8 @@ export class AnimatedMascot {
418
403
  const frameLines = this.applyCatEffect(this.currentCatFrame());
419
404
  for (const line of frameLines) result.push(this.formatLine(line, safeWidth));
420
405
  }
421
- const hint = this.style === "armin"
422
- ? `Press q or Esc to close · effect: ${this.effect}`
423
- : "Press q or Esc to close · animated preview";
406
+ const hint =
407
+ this.style === "armin" ? `Press q or Esc to close · effect: ${this.effect}` : "Press q or Esc to close · animated preview";
424
408
  result.push(this.formatLine(hint, safeWidth, "muted"));
425
409
  result.push(`${this.theme.fg("border", "╰")}${horizontal}${this.theme.fg("border", "╯")}`);
426
410
  this.cachedWidth = safeWidth;
@@ -1,5 +1,5 @@
1
- import type { CrewAgentRecord } from "../../runtime/crew-agent-runtime.ts";
2
1
  import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
2
+ import type { CrewAgentRecord } from "../../runtime/crew-agent-runtime.ts";
3
3
  import { loadRunManifestById } from "../../state/state-store.ts";
4
4
  import { pad, truncate } from "../../utils/visual.ts";
5
5
  import { asCrewTheme, type CrewTheme } from "../theme-adapter.ts";
@@ -14,7 +14,12 @@ export class AgentPickerOverlay {
14
14
  private readonly theme: CrewTheme;
15
15
  private selected = 0;
16
16
 
17
- constructor(opts: { cwd: string; runId: string; done: (selection: AgentPickerSelection | undefined) => void; theme?: unknown }) {
17
+ constructor(opts: {
18
+ cwd: string;
19
+ runId: string;
20
+ done: (selection: AgentPickerSelection | undefined) => void;
21
+ theme?: unknown;
22
+ }) {
18
23
  const loaded = loadRunManifestById(opts.cwd, opts.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency;
19
24
  this.agents = loaded ? readCrewAgents(loaded.manifest) : [];
20
25
  this.done = opts.done;
@@ -30,7 +35,10 @@ export class AgentPickerOverlay {
30
35
  const lines = [
31
36
  this.theme.bold("Select agent"),
32
37
  "↑/↓ move · Enter select · ESC cancel",
33
- ...this.agents.map((agent, index) => `${index === this.selected ? "›" : " "} ${agent.taskId} · ${agent.status} · ${agent.role}->${agent.agent}`),
38
+ ...this.agents.map(
39
+ (agent, index) =>
40
+ `${index === this.selected ? "›" : " "} ${agent.taskId} · ${agent.status} · ${agent.role}->${agent.agent}`,
41
+ ),
34
42
  ];
35
43
  if (!this.agents.length) lines.push("No agents found.");
36
44
  return lines.map((line) => pad(truncate(line, inner), inner));
@@ -1,6 +1,6 @@
1
+ import { pad, truncate } from "../../utils/visual.ts";
1
2
  import { Box, Text } from "../layout-primitives.ts";
2
3
  import { asCrewTheme, type CrewTheme } from "../theme-adapter.ts";
3
- import { pad, truncate } from "../../utils/visual.ts";
4
4
 
5
5
  export interface ConfirmOptions {
6
6
  title: string;
@@ -34,7 +34,9 @@ export class ConfirmOverlay {
34
34
  `╭${"─".repeat(innerWidth)}╮`,
35
35
  `│ ${pad(truncate(title, innerWidth - 1), innerWidth - 1)}│`,
36
36
  `├${"─".repeat(innerWidth)}┤`,
37
- ...(bodyLines.length ? bodyLines : ["Are you sure?"]).map((line) => `│ ${pad(truncate(line, innerWidth - 1), innerWidth - 1)}│`),
37
+ ...(bodyLines.length ? bodyLines : ["Are you sure?"]).map(
38
+ (line) => `│ ${pad(truncate(line, innerWidth - 1), innerWidth - 1)}│`,
39
+ ),
38
40
  `├${"─".repeat(innerWidth)}┤`,
39
41
  `│ ${pad(truncate(this.theme.fg("dim", hint), innerWidth - 1), innerWidth - 1)}│`,
40
42
  `╰${"─".repeat(innerWidth)}╯`,
@@ -14,10 +14,11 @@
14
14
  *
15
15
  * Template origin: `confirm-overlay.ts`.
16
16
  */
17
- import { Box, Text } from "../layout-primitives.ts";
18
- import { asCrewTheme, type CrewTheme } from "../theme-adapter.ts";
17
+
19
18
  import { pad, truncate } from "../../utils/visual.ts";
20
19
  import { DASHBOARD_KEYS } from "../keybinding-map.ts";
20
+ import { Box, Text } from "../layout-primitives.ts";
21
+ import { asCrewTheme, type CrewTheme } from "../theme-adapter.ts";
21
22
 
22
23
  /** Translate a raw key sequence into a readable token for the cheatsheet. */
23
24
  function keyToken(key: string): string {
@@ -89,7 +90,10 @@ function buildHelpGroups(): HelpGroup[] {
89
90
  }));
90
91
  const mailboxEntries: HelpEntry[] = Object.entries(DASHBOARD_KEYS.mailbox)
91
92
  .filter(([name]) => name !== "openDetail")
92
- .map(([name, keys]) => ({ keys: keyList(keys), label: MAILBOX_LABELS[name] ?? name }));
93
+ .map(([name, keys]) => ({
94
+ keys: keyList(keys),
95
+ label: MAILBOX_LABELS[name] ?? name,
96
+ }));
93
97
  const healthEntries: HelpEntry[] = Object.entries(DASHBOARD_KEYS.health).map(([name, keys]) => ({
94
98
  keys: keyList(keys),
95
99
  label: HEALTH_LABELS[name] ?? name,
@@ -98,15 +102,24 @@ function buildHelpGroups(): HelpGroup[] {
98
102
  {
99
103
  title: "General",
100
104
  entries: [
101
- { keys: keyList(DASHBOARD_KEYS.close), label: "close dashboard" },
102
- { keys: keyList(DASHBOARD_KEYS.select), label: "open run status" },
105
+ {
106
+ keys: keyList(DASHBOARD_KEYS.close),
107
+ label: "close dashboard",
108
+ },
109
+ {
110
+ keys: keyList(DASHBOARD_KEYS.select),
111
+ label: "open run status",
112
+ },
103
113
  { keys: "?", label: "toggle this help" },
104
114
  ],
105
115
  },
106
116
  {
107
117
  title: "Navigation",
108
118
  entries: [
109
- { keys: `${keyList(DASHBOARD_KEYS.navigation.up)}/${keyList(DASHBOARD_KEYS.navigation.down)}`, label: "move selection" },
119
+ {
120
+ keys: `${keyList(DASHBOARD_KEYS.navigation.up)}/${keyList(DASHBOARD_KEYS.navigation.down)}`,
121
+ label: "move selection",
122
+ },
110
123
  ],
111
124
  },
112
125
  { title: "Panes", entries: paneEntries },
@@ -116,7 +129,10 @@ function buildHelpGroups(): HelpGroup[] {
116
129
  title: "Health & notifications",
117
130
  entries: [
118
131
  ...healthEntries,
119
- { keys: keyList(DASHBOARD_KEYS.notification.dismissAll), label: "dismiss notifs" },
132
+ {
133
+ keys: keyList(DASHBOARD_KEYS.notification.dismissAll),
134
+ label: "dismiss notifs",
135
+ },
120
136
  ],
121
137
  },
122
138
  ];
@@ -144,17 +160,12 @@ export class HelpOverlay {
144
160
  const mid = fg("border", `├${bar}┤`);
145
161
  const bot = fg("border", `╰${bar}╯`);
146
162
  const keyCol = 9;
147
- const lines: string[] = [
148
- top,
149
- row(`${fg("accent", "pi-crew dashboard")} ${fg("dim", "— key reference (press ? to close)")}`),
150
- mid,
151
- ];
163
+ const lines: string[] = [top, row(`${fg("accent", "pi-crew dashboard")} ${fg("dim", "— key reference (press ? to close)")}`), mid];
152
164
  for (const group of buildHelpGroups()) {
153
165
  lines.push(row(fg("accent", group.title)));
154
166
  for (let i = 0; i < group.entries.length; i += 2) {
155
167
  const pair = group.entries.slice(i, i + 2);
156
- const cell = (entry: HelpEntry) =>
157
- `${this.theme.bold(pad(entry.keys, keyCol))}${fg("dim", truncate(entry.label, 16))}`;
168
+ const cell = (entry: HelpEntry) => `${this.theme.bold(pad(entry.keys, keyCol))}${fg("dim", truncate(entry.label, 16))}`;
158
169
  lines.push(row(pair.map(cell).join(" ")));
159
170
  }
160
171
  }
@@ -21,13 +21,22 @@ const FIELD_ORDER: FieldName[] = ["from", "to", "body", "taskId", "direction"];
21
21
  export class MailboxComposeOverlay {
22
22
  private readonly done: (result: MailboxComposeResult) => void;
23
23
  private readonly theme: CrewTheme;
24
- private fields: MailboxComposePayload = { from: "operator", to: "leader", body: "", direction: "inbox" };
24
+ private fields: MailboxComposePayload = {
25
+ from: "operator",
26
+ to: "leader",
27
+ body: "",
28
+ direction: "inbox",
29
+ };
25
30
  private activeField = 1;
26
31
  private error: string | undefined;
27
32
  private preview = false;
28
33
  private confirm: ConfirmOverlay | undefined;
29
34
 
30
- constructor(opts: { done: (result: MailboxComposeResult) => void; theme?: unknown; initial?: Partial<MailboxComposePayload> }) {
35
+ constructor(opts: {
36
+ done: (result: MailboxComposeResult) => void;
37
+ theme?: unknown;
38
+ initial?: Partial<MailboxComposePayload>;
39
+ }) {
31
40
  this.done = opts.done;
32
41
  this.theme = asCrewTheme(opts.theme ?? {});
33
42
  this.fields = { ...this.fields, ...opts.initial };
@@ -43,7 +52,9 @@ export class MailboxComposeOverlay {
43
52
  const formWidth = this.preview ? Math.max(24, Math.floor(inner * 0.6)) : inner;
44
53
  const lines = [
45
54
  this.theme.bold("Compose mailbox message"),
46
- this.preview ? "P close preview · Tab cycle · Enter submit · ESC discard" : "P preview · Tab cycle · Enter submit · ESC discard",
55
+ this.preview
56
+ ? "P close preview · Tab cycle · Enter submit · ESC discard"
57
+ : "P preview · Tab cycle · Enter submit · ESC discard",
47
58
  ...(this.error ? [this.theme.fg("error", this.error)] : []),
48
59
  this.fieldLine("from", formWidth),
49
60
  this.fieldLine("to", formWidth),
@@ -56,7 +67,9 @@ export class MailboxComposeOverlay {
56
67
  const max = Math.max(lines.length, previewLines.length);
57
68
  const split: string[] = [];
58
69
  for (let index = 0; index < max; index += 1) {
59
- split.push(`${pad(truncate(lines[index] ?? "", formWidth), formWidth)} │ ${truncate(previewLines[index] ?? "", inner - formWidth - 3)}`);
70
+ split.push(
71
+ `${pad(truncate(lines[index] ?? "", formWidth), formWidth)} │ ${truncate(previewLines[index] ?? "", inner - formWidth - 3)}`,
72
+ );
60
73
  }
61
74
  return split;
62
75
  }
@@ -74,14 +87,20 @@ export class MailboxComposeOverlay {
74
87
  private appendText(data: string): void {
75
88
  const field = this.activeName();
76
89
  if (field === "direction") return;
77
- this.fields = { ...this.fields, [field]: `${this.fields[field] ?? ""}${data}` };
90
+ this.fields = {
91
+ ...this.fields,
92
+ [field]: `${this.fields[field] ?? ""}${data}`,
93
+ };
78
94
  this.error = undefined;
79
95
  }
80
96
 
81
97
  private backspace(): void {
82
98
  const field = this.activeName();
83
99
  if (field === "direction") return;
84
- this.fields = { ...this.fields, [field]: (this.fields[field] ?? "").slice(0, -1) };
100
+ this.fields = {
101
+ ...this.fields,
102
+ [field]: (this.fields[field] ?? "").slice(0, -1),
103
+ };
85
104
  }
86
105
 
87
106
  private submit(): void {
@@ -94,7 +113,16 @@ export class MailboxComposeOverlay {
94
113
  this.error = "Recipient is required.";
95
114
  return;
96
115
  }
97
- this.done({ type: "submit", payload: { ...this.fields, from: this.fields.from.trim() || "operator", to: this.fields.to.trim(), body, taskId: this.fields.taskId?.trim() || undefined } });
116
+ this.done({
117
+ type: "submit",
118
+ payload: {
119
+ ...this.fields,
120
+ from: this.fields.from.trim() || "operator",
121
+ to: this.fields.to.trim(),
122
+ body,
123
+ taskId: this.fields.taskId?.trim() || undefined,
124
+ },
125
+ });
98
126
  }
99
127
 
100
128
  private cancel(): void {
@@ -102,10 +130,19 @@ export class MailboxComposeOverlay {
102
130
  this.done({ type: "cancel" });
103
131
  return;
104
132
  }
105
- this.confirm = new ConfirmOverlay({ title: "Discard draft?", body: `Body has ${this.fields.body.length} chars. Y=discard, N=continue editing`, dangerLevel: "medium", defaultAction: "cancel" }, (confirmed) => {
106
- this.confirm = undefined;
107
- if (confirmed) this.done({ type: "cancel" });
108
- }, this.theme);
133
+ this.confirm = new ConfirmOverlay(
134
+ {
135
+ title: "Discard draft?",
136
+ body: `Body has ${this.fields.body.length} chars. Y=discard, N=continue editing`,
137
+ dangerLevel: "medium",
138
+ defaultAction: "cancel",
139
+ },
140
+ (confirmed) => {
141
+ this.confirm = undefined;
142
+ if (confirmed) this.done({ type: "cancel" });
143
+ },
144
+ this.theme,
145
+ );
109
146
  }
110
147
 
111
148
  handleInput(data: string): void {
@@ -1,8 +1,12 @@
1
+ import { truncate } from "../../utils/visual.ts";
1
2
  import type { CrewTheme } from "../theme-adapter.ts";
2
3
  import { asCrewTheme } from "../theme-adapter.ts";
3
- import { truncate } from "../../utils/visual.ts";
4
4
 
5
- export type MarkdownToken = { type: "heading" | "code-block" | "list-item" | "paragraph"; level?: number; text: string };
5
+ export type MarkdownToken = {
6
+ type: "heading" | "code-block" | "list-item" | "paragraph";
7
+ level?: number;
8
+ text: string;
9
+ };
6
10
 
7
11
  function stripInlineMarkdown(text: string): string {
8
12
  return text
@@ -33,15 +37,26 @@ export function tokenizeMarkdown(body: string): MarkdownToken[] {
33
37
  }
34
38
  const heading = /^(#{1,3})\s+(.+)$/.exec(line);
35
39
  if (heading) {
36
- tokens.push({ type: "heading", level: heading[1]!.length, text: stripInlineMarkdown(heading[2]!) });
40
+ tokens.push({
41
+ type: "heading",
42
+ level: heading[1]!.length,
43
+ text: stripInlineMarkdown(heading[2]!),
44
+ });
37
45
  continue;
38
46
  }
39
47
  const list = /^\s*(?:[-*]|\d+\.)\s+(.+)$/.exec(line);
40
48
  if (list) {
41
- tokens.push({ type: "list-item", text: stripInlineMarkdown(list[1]!) });
49
+ tokens.push({
50
+ type: "list-item",
51
+ text: stripInlineMarkdown(list[1]!),
52
+ });
42
53
  continue;
43
54
  }
44
- if (line.trim()) tokens.push({ type: "paragraph", text: stripInlineMarkdown(line.trim()) });
55
+ if (line.trim())
56
+ tokens.push({
57
+ type: "paragraph",
58
+ text: stripInlineMarkdown(line.trim()),
59
+ });
45
60
  }
46
61
  if (inCode && codeLines.length) tokens.push({ type: "code-block", text: codeLines.join("\n") });
47
62
  return tokens;
@@ -1,4 +1,4 @@
1
- import { readDeliveryState, readMailbox, type MailboxMessage } from "../../state/mailbox.ts";
1
+ import { type MailboxMessage, readDeliveryState, readMailbox } from "../../state/mailbox.ts";
2
2
  import { loadRunManifestById } from "../../state/state-store.ts";
3
3
  import { pad, truncate } from "../../utils/visual.ts";
4
4
  import { asCrewTheme, type CrewTheme } from "../theme-adapter.ts";
@@ -23,7 +23,12 @@ export class MailboxDetailOverlay {
23
23
  private lastRefreshedTaskCount = 0;
24
24
  private needsRefresh = true;
25
25
 
26
- constructor(opts: { runId: string; cwd: string; done: (action: MailboxAction | undefined) => void; theme?: unknown }) {
26
+ constructor(opts: {
27
+ runId: string;
28
+ cwd: string;
29
+ done: (action: MailboxAction | undefined) => void;
30
+ theme?: unknown;
31
+ }) {
27
32
  this.runId = opts.runId;
28
33
  this.cwd = opts.cwd;
29
34
  this.done = opts.done;
@@ -41,10 +46,23 @@ export class MailboxDetailOverlay {
41
46
  this.needsRefresh = true;
42
47
  }
43
48
  const delivery = readDeliveryState(loaded.manifest).messages;
44
- const applyDelivery = (message: MailboxMessage): MailboxMessage => ({ ...message, status: delivery[message.id] ?? message.status });
49
+ const applyDelivery = (message: MailboxMessage): MailboxMessage => ({
50
+ ...message,
51
+ status: delivery[message.id] ?? message.status,
52
+ });
45
53
  const taskIds = loaded.tasks.map((task) => task.id);
46
- this.inbox = [...readMailbox(loaded.manifest, "inbox"), ...taskIds.flatMap((taskId) => readMailbox(loaded.manifest, "inbox", taskId))].map(applyDelivery).reverse();
47
- this.outbox = [...readMailbox(loaded.manifest, "outbox"), ...taskIds.flatMap((taskId) => readMailbox(loaded.manifest, "outbox", taskId))].map(applyDelivery).reverse();
54
+ this.inbox = [
55
+ ...readMailbox(loaded.manifest, "inbox"),
56
+ ...taskIds.flatMap((taskId) => readMailbox(loaded.manifest, "inbox", taskId)),
57
+ ]
58
+ .map(applyDelivery)
59
+ .reverse();
60
+ this.outbox = [
61
+ ...readMailbox(loaded.manifest, "outbox"),
62
+ ...taskIds.flatMap((taskId) => readMailbox(loaded.manifest, "outbox", taskId)),
63
+ ]
64
+ .map(applyDelivery)
65
+ .reverse();
48
66
  this.selected = Math.min(this.selected, Math.max(0, this.current().length - 1));
49
67
  }
50
68
 
@@ -121,7 +139,10 @@ export class MailboxDetailOverlay {
121
139
  return;
122
140
  }
123
141
  if (data === "N") {
124
- this.done({ type: "nudge", agentId: this.selectedMessage()?.taskId });
142
+ this.done({
143
+ type: "nudge",
144
+ agentId: this.selectedMessage()?.taskId,
145
+ });
125
146
  return;
126
147
  }
127
148
  if (data === "C") {