pi-crew 0.9.53 → 0.9.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/package.json +6 -3
  3. package/scripts/clean-strip-types.mjs +60 -0
  4. package/src/adapters/claude-adapter.ts +23 -0
  5. package/src/adapters/codex-adapter.ts +21 -0
  6. package/src/adapters/cursor-adapter.ts +17 -0
  7. package/src/adapters/export-util.ts +143 -0
  8. package/src/adapters/index.ts +15 -0
  9. package/src/adapters/registry.ts +18 -0
  10. package/src/adapters/types.ts +23 -0
  11. package/src/agents/agent-config.ts +194 -0
  12. package/src/agents/agent-search.ts +98 -0
  13. package/src/agents/agent-serializer.ts +38 -0
  14. package/src/agents/discover-agents.ts +623 -0
  15. package/src/benchmark/benchmark-runner.ts +313 -0
  16. package/src/benchmark/feedback-loop.ts +73 -0
  17. package/src/config/config.ts +1270 -0
  18. package/src/config/defaults.ts +193 -0
  19. package/src/config/drift-detector.ts +290 -0
  20. package/src/config/markers.ts +330 -0
  21. package/src/config/resilient-parser.ts +117 -0
  22. package/src/config/role-tools.ts +118 -0
  23. package/src/config/suggestions.ts +75 -0
  24. package/src/config/types.ts +280 -0
  25. package/src/errors.ts +194 -0
  26. package/src/extension/action-suggestions.ts +117 -0
  27. package/src/extension/async-notifier.ts +179 -0
  28. package/src/extension/autonomous-policy.ts +209 -0
  29. package/src/extension/command-completions.ts +120 -0
  30. package/src/extension/context-status-injection.ts +185 -0
  31. package/src/extension/crew-autocomplete.ts +131 -0
  32. package/src/extension/crew-cleanup.ts +168 -0
  33. package/src/extension/crew-input-router.ts +93 -0
  34. package/src/extension/crew-shortcuts.ts +87 -0
  35. package/src/extension/crew-vibes/cat-frames.ts +18 -0
  36. package/src/extension/crew-vibes/config.ts +195 -0
  37. package/src/extension/crew-vibes/figures.ts +101 -0
  38. package/src/extension/crew-vibes/font-detect.ts +71 -0
  39. package/src/extension/crew-vibes/footer.ts +292 -0
  40. package/src/extension/crew-vibes/index.ts +432 -0
  41. package/src/extension/crew-vibes/provider-usage.ts +396 -0
  42. package/src/extension/crew-vibes/render.ts +206 -0
  43. package/src/extension/crew-vibes/speed.ts +286 -0
  44. package/src/extension/cross-extension-rpc.ts +350 -0
  45. package/src/extension/help.ts +62 -0
  46. package/src/extension/import-index.ts +74 -0
  47. package/src/extension/knowledge-injection.ts +402 -0
  48. package/src/extension/management.ts +571 -0
  49. package/src/extension/message-renderers.ts +108 -0
  50. package/src/extension/notification-router.ts +152 -0
  51. package/src/extension/notification-sink.ts +54 -0
  52. package/src/extension/pi-api.ts +56 -0
  53. package/src/extension/plan-orchestrate.ts +302 -0
  54. package/src/extension/project-init.ts +170 -0
  55. package/src/extension/register.ts +113 -0
  56. package/src/extension/registration/artifact-cleanup.ts +20 -0
  57. package/src/extension/registration/command-registration.ts +58 -0
  58. package/src/extension/registration/command-utils.ts +58 -0
  59. package/src/extension/registration/commands.ts +1228 -0
  60. package/src/extension/registration/compaction-guard.ts +333 -0
  61. package/src/extension/registration/context-builder.ts +135 -0
  62. package/src/extension/registration/crash-recovery-cache.ts +54 -0
  63. package/src/extension/registration/foreground-run-controller.ts +238 -0
  64. package/src/extension/registration/hook-registration.ts +119 -0
  65. package/src/extension/registration/lazy-configurers.ts +124 -0
  66. package/src/extension/registration/lifecycle-handlers.ts +923 -0
  67. package/src/extension/registration/lifecycle.ts +259 -0
  68. package/src/extension/registration/observability.ts +322 -0
  69. package/src/extension/registration/registration-types.ts +158 -0
  70. package/src/extension/registration/runtime-cleanup.ts +230 -0
  71. package/src/extension/registration/subagent-helpers.ts +125 -0
  72. package/src/extension/registration/subagent-manager-setup.ts +330 -0
  73. package/src/extension/registration/subagent-tools.ts +456 -0
  74. package/src/extension/registration/team-tool.ts +225 -0
  75. package/src/extension/registration/tool-registration.ts +50 -0
  76. package/src/extension/registration/ui.ts +172 -0
  77. package/src/extension/registration/viewers.ts +121 -0
  78. package/src/extension/registration/wire-cross-extension.ts +37 -0
  79. package/src/extension/result-watcher.ts +139 -0
  80. package/src/extension/rpc-hmac.ts +256 -0
  81. package/src/extension/run-bundle-schema.ts +104 -0
  82. package/src/extension/run-export.ts +97 -0
  83. package/src/extension/run-import.ts +168 -0
  84. package/src/extension/run-index.ts +131 -0
  85. package/src/extension/run-maintenance.ts +190 -0
  86. package/src/extension/session-summary.ts +18 -0
  87. package/src/extension/team-manager-command.ts +153 -0
  88. package/src/extension/team-onboard.ts +180 -0
  89. package/src/extension/team-recommendation.ts +288 -0
  90. package/src/extension/team-tool/anchor.ts +172 -0
  91. package/src/extension/team-tool/api.ts +1244 -0
  92. package/src/extension/team-tool/auto-summarize.ts +142 -0
  93. package/src/extension/team-tool/cache-control.ts +19 -0
  94. package/src/extension/team-tool/cancel.ts +337 -0
  95. package/src/extension/team-tool/chain-dispatch.ts +95 -0
  96. package/src/extension/team-tool/chain-executor.ts +379 -0
  97. package/src/extension/team-tool/config-patch.ts +50 -0
  98. package/src/extension/team-tool/context.ts +149 -0
  99. package/src/extension/team-tool/destructive-gate.ts +52 -0
  100. package/src/extension/team-tool/dispatch/automate.ts +80 -0
  101. package/src/extension/team-tool/dispatch/control.ts +42 -0
  102. package/src/extension/team-tool/dispatch/index.ts +95 -0
  103. package/src/extension/team-tool/dispatch/manage.ts +161 -0
  104. package/src/extension/team-tool/dispatch/run.ts +53 -0
  105. package/src/extension/team-tool/dispatch/status.ts +187 -0
  106. package/src/extension/team-tool/doctor.ts +431 -0
  107. package/src/extension/team-tool/explain.ts +282 -0
  108. package/src/extension/team-tool/failure-patterns.ts +118 -0
  109. package/src/extension/team-tool/goal-wrap.ts +330 -0
  110. package/src/extension/team-tool/goal.ts +556 -0
  111. package/src/extension/team-tool/handle-schedule.ts +332 -0
  112. package/src/extension/team-tool/handle-settings.ts +520 -0
  113. package/src/extension/team-tool/health-monitor.ts +481 -0
  114. package/src/extension/team-tool/inspect.ts +88 -0
  115. package/src/extension/team-tool/intent-policy.ts +45 -0
  116. package/src/extension/team-tool/lifecycle-actions.ts +615 -0
  117. package/src/extension/team-tool/orchestrate.ts +98 -0
  118. package/src/extension/team-tool/parallel-dispatch.ts +183 -0
  119. package/src/extension/team-tool/plan.ts +50 -0
  120. package/src/extension/team-tool/respond.ts +150 -0
  121. package/src/extension/team-tool/run-deadline.ts +66 -0
  122. package/src/extension/team-tool/run-not-found.ts +49 -0
  123. package/src/extension/team-tool/run.ts +1051 -0
  124. package/src/extension/team-tool/status.ts +260 -0
  125. package/src/extension/team-tool/workflow-manage.ts +261 -0
  126. package/src/extension/team-tool-types.ts +26 -0
  127. package/src/extension/team-tool.ts +750 -0
  128. package/src/extension/tool-result.ts +16 -0
  129. package/src/extension/validate-resources.ts +108 -0
  130. package/src/hooks/registry.ts +200 -0
  131. package/src/hooks/types.ts +69 -0
  132. package/src/i18n.ts +212 -0
  133. package/src/observability/correlation.ts +50 -0
  134. package/src/observability/event-bus.ts +86 -0
  135. package/src/observability/event-to-metric.ts +170 -0
  136. package/src/observability/exporters/adapter.ts +27 -0
  137. package/src/observability/exporters/otlp-exporter.ts +356 -0
  138. package/src/observability/exporters/prometheus-exporter.ts +54 -0
  139. package/src/observability/metric-registry.ts +100 -0
  140. package/src/observability/metric-retention.ts +64 -0
  141. package/src/observability/metric-sink.ts +99 -0
  142. package/src/observability/metrics-primitives.ts +219 -0
  143. package/src/plugins/plugin-define.ts +6 -0
  144. package/src/plugins/plugin-registry.ts +32 -0
  145. package/src/plugins/plugins/index.ts +3 -0
  146. package/src/plugins/plugins/nextjs.ts +19 -0
  147. package/src/plugins/plugins/vite.ts +10 -0
  148. package/src/plugins/plugins/vitest.ts +9 -0
  149. package/src/prompt/prompt-runtime.ts +380 -0
  150. package/src/runtime/adaptive-plan.ts +563 -0
  151. package/src/runtime/agent-control.ts +215 -0
  152. package/src/runtime/agent-memory.ts +81 -0
  153. package/src/runtime/agent-observability.ts +122 -0
  154. package/src/runtime/anchor-manager.ts +475 -0
  155. package/src/runtime/async-marker.ts +32 -0
  156. package/src/runtime/async-runner.ts +381 -0
  157. package/src/runtime/attention-events.ts +28 -0
  158. package/src/runtime/auto-summarize.ts +344 -0
  159. package/src/runtime/background-runner.ts +840 -0
  160. package/src/runtime/batch-barrier.ts +147 -0
  161. package/src/runtime/broker-issuer.ts +39 -0
  162. package/src/runtime/cancellation-token.ts +99 -0
  163. package/src/runtime/cancellation.ts +99 -0
  164. package/src/runtime/capability-inventory.ts +137 -0
  165. package/src/runtime/chain-parser.ts +237 -0
  166. package/src/runtime/chain-runner.ts +606 -0
  167. package/src/runtime/checkpoint.ts +291 -0
  168. package/src/runtime/child-pi-constants.ts +42 -0
  169. package/src/runtime/child-pi-kill.ts +180 -0
  170. package/src/runtime/child-pi-pool.ts +68 -0
  171. package/src/runtime/child-pi-spawn.ts +287 -0
  172. package/src/runtime/child-pi-steering.ts +128 -0
  173. package/src/runtime/child-pi-streams.ts +296 -0
  174. package/src/runtime/child-pi-transcript.ts +169 -0
  175. package/src/runtime/child-pi.ts +1105 -0
  176. package/src/runtime/coalesce-tasks.ts +268 -0
  177. package/src/runtime/code-summary.ts +292 -0
  178. package/src/runtime/command-trace.ts +105 -0
  179. package/src/runtime/compact-pipeline.ts +56 -0
  180. package/src/runtime/compact-stages/ansi-strip-stage.ts +25 -0
  181. package/src/runtime/compact-stages/blank-collapse-stage.ts +31 -0
  182. package/src/runtime/compact-stages/deduplicate-stage.ts +34 -0
  183. package/src/runtime/compact-stages/head-snap-stage.ts +57 -0
  184. package/src/runtime/compact-stages/index.ts +23 -0
  185. package/src/runtime/compact-stages/tail-capture-stage.ts +77 -0
  186. package/src/runtime/compact-stages/truncation-stage.ts +74 -0
  187. package/src/runtime/compaction-summary.ts +278 -0
  188. package/src/runtime/completion-guard.ts +207 -0
  189. package/src/runtime/concurrency.ts +58 -0
  190. package/src/runtime/crash-classification.ts +229 -0
  191. package/src/runtime/crash-recovery.ts +594 -0
  192. package/src/runtime/crew-agent-records.ts +595 -0
  193. package/src/runtime/crew-agent-runtime.ts +62 -0
  194. package/src/runtime/crew-broker-child.ts +88 -0
  195. package/src/runtime/crew-broker-client.ts +673 -0
  196. package/src/runtime/crew-broker-tokens.ts +159 -0
  197. package/src/runtime/crew-broker.ts +1304 -0
  198. package/src/runtime/crew-hooks.ts +227 -0
  199. package/src/runtime/cross-extension-rpc.ts +143 -0
  200. package/src/runtime/custom-tools/irc-tool.ts +282 -0
  201. package/src/runtime/custom-tools/submit-result-tool.ts +102 -0
  202. package/src/runtime/deadletter.ts +47 -0
  203. package/src/runtime/delivery-coordinator.ts +211 -0
  204. package/src/runtime/delta-conflict.ts +348 -0
  205. package/src/runtime/deterministic-ast.ts +161 -0
  206. package/src/runtime/diagnostic-export.ts +171 -0
  207. package/src/runtime/direct-run.ts +45 -0
  208. package/src/runtime/dwf-state-store.ts +102 -0
  209. package/src/runtime/dynamic-workflow-context.ts +1013 -0
  210. package/src/runtime/dynamic-workflow-runner.ts +325 -0
  211. package/src/runtime/effectiveness.ts +90 -0
  212. package/src/runtime/errors/crew-errors.ts +162 -0
  213. package/src/runtime/event-stream-bridge.ts +98 -0
  214. package/src/runtime/foreground-control.ts +193 -0
  215. package/src/runtime/foreground-watchdog.ts +132 -0
  216. package/src/runtime/global-worker-cap.ts +96 -0
  217. package/src/runtime/goal-achievement.ts +148 -0
  218. package/src/runtime/goal-evaluator.ts +365 -0
  219. package/src/runtime/goal-loop-runner.ts +825 -0
  220. package/src/runtime/goal-state-store.ts +219 -0
  221. package/src/runtime/green-contract.ts +55 -0
  222. package/src/runtime/group-join.ts +267 -0
  223. package/src/runtime/handoff-manager.ts +598 -0
  224. package/src/runtime/heartbeat-gradient.ts +36 -0
  225. package/src/runtime/heartbeat-watcher.ts +239 -0
  226. package/src/runtime/hidden-handoff.ts +407 -0
  227. package/src/runtime/important-line-classifier.ts +140 -0
  228. package/src/runtime/intercom-bridge.ts +187 -0
  229. package/src/runtime/iteration-hooks.ts +305 -0
  230. package/src/runtime/live-agent-control.ts +136 -0
  231. package/src/runtime/live-agent-manager.ts +704 -0
  232. package/src/runtime/live-control-realtime.ts +56 -0
  233. package/src/runtime/live-extension-bridge.ts +148 -0
  234. package/src/runtime/live-irc.ts +97 -0
  235. package/src/runtime/live-session-health.ts +108 -0
  236. package/src/runtime/live-session-runtime.ts +1146 -0
  237. package/src/runtime/loop-gates.ts +128 -0
  238. package/src/runtime/manifest-cache.ts +375 -0
  239. package/src/runtime/mcp-proxy.ts +105 -0
  240. package/src/runtime/metric-parser.ts +36 -0
  241. package/src/runtime/model-fallback.ts +409 -0
  242. package/src/runtime/model-resolver.ts +126 -0
  243. package/src/runtime/model-scope.ts +158 -0
  244. package/src/runtime/orphan-worker-registry.ts +465 -0
  245. package/src/runtime/output-validator.ts +202 -0
  246. package/src/runtime/overflow-recovery.ts +206 -0
  247. package/src/runtime/parallel-research.ts +68 -0
  248. package/src/runtime/parallel-utils.ts +160 -0
  249. package/src/runtime/parent-guard.ts +134 -0
  250. package/src/runtime/path-overlap.ts +150 -0
  251. package/src/runtime/peer-dep.ts +292 -0
  252. package/src/runtime/per-write-validator.ts +181 -0
  253. package/src/runtime/phase-progress.ts +217 -0
  254. package/src/runtime/phase-tracker.ts +385 -0
  255. package/src/runtime/pi-args.ts +655 -0
  256. package/src/runtime/pi-json-output.ts +170 -0
  257. package/src/runtime/pi-spawn.ts +273 -0
  258. package/src/runtime/pipeline-runner.ts +523 -0
  259. package/src/runtime/plan-templates.ts +201 -0
  260. package/src/runtime/policy-engine.ts +115 -0
  261. package/src/runtime/post-checks.ts +142 -0
  262. package/src/runtime/post-exit-stdio-guard.ts +109 -0
  263. package/src/runtime/process-lifecycle.ts +491 -0
  264. package/src/runtime/process-status.ts +154 -0
  265. package/src/runtime/progress-event-coalescer.ts +44 -0
  266. package/src/runtime/progress-tracker.ts +124 -0
  267. package/src/runtime/prose-compressor.ts +162 -0
  268. package/src/runtime/recovery-recipes.ts +203 -0
  269. package/src/runtime/replace.ts +570 -0
  270. package/src/runtime/resilient-edit.ts +153 -0
  271. package/src/runtime/result-extractor.ts +217 -0
  272. package/src/runtime/retry-executor.ts +109 -0
  273. package/src/runtime/retry-runner.ts +336 -0
  274. package/src/runtime/role-permission.ts +59 -0
  275. package/src/runtime/run-coalesced-task-group.ts +308 -0
  276. package/src/runtime/run-drift.ts +219 -0
  277. package/src/runtime/run-tracker.ts +116 -0
  278. package/src/runtime/run-worker.ts +78 -0
  279. package/src/runtime/runtime-policy.ts +29 -0
  280. package/src/runtime/runtime-resolver.ts +172 -0
  281. package/src/runtime/runtime-warmup.ts +160 -0
  282. package/src/runtime/scheduler.ts +353 -0
  283. package/src/runtime/semaphore.ts +141 -0
  284. package/src/runtime/sensitive-paths.ts +93 -0
  285. package/src/runtime/session-resources.ts +25 -0
  286. package/src/runtime/session-snapshot.ts +59 -0
  287. package/src/runtime/session-usage.ts +79 -0
  288. package/src/runtime/settings-store.ts +155 -0
  289. package/src/runtime/sidechain-output.ts +35 -0
  290. package/src/runtime/single-agent-compose.ts +84 -0
  291. package/src/runtime/skill-effectiveness.ts +524 -0
  292. package/src/runtime/skill-instructions.ts +394 -0
  293. package/src/runtime/stale-reconciler.ts +680 -0
  294. package/src/runtime/stream-preview.ts +184 -0
  295. package/src/runtime/streaming-output.ts +50 -0
  296. package/src/runtime/subagent-manager.ts +561 -0
  297. package/src/runtime/subprocess-tool-registry.ts +70 -0
  298. package/src/runtime/supervisor-contact.ts +64 -0
  299. package/src/runtime/task-display.ts +52 -0
  300. package/src/runtime/task-graph-scheduler.ts +227 -0
  301. package/src/runtime/task-graph.ts +290 -0
  302. package/src/runtime/task-health.ts +83 -0
  303. package/src/runtime/task-id.ts +161 -0
  304. package/src/runtime/task-output-context.ts +602 -0
  305. package/src/runtime/task-packet.ts +268 -0
  306. package/src/runtime/task-quality.ts +199 -0
  307. package/src/runtime/task-runner/capabilities.ts +78 -0
  308. package/src/runtime/task-runner/child-executor.ts +790 -0
  309. package/src/runtime/task-runner/context-retrieval.ts +163 -0
  310. package/src/runtime/task-runner/live-executor.ts +227 -0
  311. package/src/runtime/task-runner/output-splitter.ts +152 -0
  312. package/src/runtime/task-runner/post-execution.ts +480 -0
  313. package/src/runtime/task-runner/pre-execution.ts +365 -0
  314. package/src/runtime/task-runner/progress.ts +157 -0
  315. package/src/runtime/task-runner/prompt-builder.ts +278 -0
  316. package/src/runtime/task-runner/prompt-pipeline.ts +88 -0
  317. package/src/runtime/task-runner/result-utils.ts +16 -0
  318. package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
  319. package/src/runtime/task-runner/run-projection.ts +125 -0
  320. package/src/runtime/task-runner/scaffold-executor.ts +25 -0
  321. package/src/runtime/task-runner/state-helpers.ts +176 -0
  322. package/src/runtime/task-runner/tail-read.ts +34 -0
  323. package/src/runtime/task-runner.ts +216 -0
  324. package/src/runtime/team-runner-artifacts.ts +13 -0
  325. package/src/runtime/team-runner.ts +2396 -0
  326. package/src/runtime/tool-output-pruner.ts +333 -0
  327. package/src/runtime/tool-progress.ts +278 -0
  328. package/src/runtime/usage-tracker.ts +73 -0
  329. package/src/runtime/verification-gates.ts +579 -0
  330. package/src/runtime/verification-integrity.ts +108 -0
  331. package/src/runtime/verification-worktree.ts +186 -0
  332. package/src/runtime/worker-heartbeat.ts +25 -0
  333. package/src/runtime/worker-startup.ts +83 -0
  334. package/src/runtime/workflow-state.ts +195 -0
  335. package/src/runtime/workspace-lock.ts +443 -0
  336. package/src/runtime/workspace-tree.ts +312 -0
  337. package/src/runtime/yield-handler.ts +224 -0
  338. package/src/runtime/zombie-scanner.ts +298 -0
  339. package/src/schema/config-schema.ts +327 -0
  340. package/src/schema/team-tool-schema.ts +492 -0
  341. package/src/schema/validation-types.ts +159 -0
  342. package/src/skills/discover-skills.ts +203 -0
  343. package/src/skills/skill-templates.ts +456 -0
  344. package/src/skills/validate.ts +285 -0
  345. package/src/state/active-run-registry.ts +439 -0
  346. package/src/state/artifact-store.ts +176 -0
  347. package/src/state/atomic-write.ts +970 -0
  348. package/src/state/blob-store.ts +308 -0
  349. package/src/state/contracts.ts +160 -0
  350. package/src/state/crew-init.ts +269 -0
  351. package/src/state/decision-ledger.ts +372 -0
  352. package/src/state/event-log-rotation.ts +399 -0
  353. package/src/state/event-log.ts +1465 -0
  354. package/src/state/event-reconstructor.ts +229 -0
  355. package/src/state/gitignore-manager.ts +46 -0
  356. package/src/state/health-store.ts +79 -0
  357. package/src/state/hook-instinct-bridge.ts +94 -0
  358. package/src/state/hook-integrations.ts +51 -0
  359. package/src/state/instinct-store.ts +275 -0
  360. package/src/state/jsonl-writer.ts +107 -0
  361. package/src/state/locks.ts +562 -0
  362. package/src/state/mailbox.ts +916 -0
  363. package/src/state/observation-store.ts +176 -0
  364. package/src/state/run-cache.ts +193 -0
  365. package/src/state/run-graph.ts +183 -0
  366. package/src/state/run-metrics.ts +165 -0
  367. package/src/state/schedule.ts +166 -0
  368. package/src/state/session-state-map.ts +51 -0
  369. package/src/state/state-store.ts +973 -0
  370. package/src/state/task-claims.ts +61 -0
  371. package/src/state/tiered-eval.ts +480 -0
  372. package/src/state/types-eval.ts +58 -0
  373. package/src/state/types.ts +447 -0
  374. package/src/state/usage.ts +138 -0
  375. package/src/state/worker-atomic-writer.ts +198 -0
  376. package/src/subagents/async-entry.ts +1 -0
  377. package/src/subagents/index.ts +3 -0
  378. package/src/subagents/live/control.ts +1 -0
  379. package/src/subagents/live/manager.ts +1 -0
  380. package/src/subagents/live/realtime.ts +1 -0
  381. package/src/subagents/live/session-runtime.ts +1 -0
  382. package/src/subagents/manager.ts +1 -0
  383. package/src/subagents/spawn.ts +1 -0
  384. package/src/teams/discover-teams.ts +187 -0
  385. package/src/teams/team-config.ts +27 -0
  386. package/src/teams/team-serializer.ts +38 -0
  387. package/src/tools/safe-bash-extension.ts +54 -0
  388. package/src/tools/safe-bash.ts +505 -0
  389. package/src/types/diff.d.ts +18 -0
  390. package/src/types/new-api-types.ts +35 -0
  391. package/src/ui/agent-management-overlay.ts +160 -0
  392. package/src/ui/card-colors.ts +139 -0
  393. package/src/ui/crew-footer.ts +102 -0
  394. package/src/ui/crew-select-list.ts +112 -0
  395. package/src/ui/dashboard-panes/agents-pane.ts +164 -0
  396. package/src/ui/dashboard-panes/cancellation-pane.ts +66 -0
  397. package/src/ui/dashboard-panes/capability-pane.ts +77 -0
  398. package/src/ui/dashboard-panes/health-pane.ts +31 -0
  399. package/src/ui/dashboard-panes/mailbox-pane.ts +35 -0
  400. package/src/ui/dashboard-panes/metrics-pane.ts +37 -0
  401. package/src/ui/dashboard-panes/progress-pane.ts +38 -0
  402. package/src/ui/dashboard-panes/transcript-pane.ts +10 -0
  403. package/src/ui/deploy-bundled-themes.ts +71 -0
  404. package/src/ui/dwf-phase-display.ts +151 -0
  405. package/src/ui/dynamic-border.ts +35 -0
  406. package/src/ui/format-helpers.ts +31 -0
  407. package/src/ui/heartbeat-aggregator.ts +74 -0
  408. package/src/ui/key-utils.ts +42 -0
  409. package/src/ui/keybinding-map.ts +248 -0
  410. package/src/ui/layout-primitives.ts +106 -0
  411. package/src/ui/live-conversation-overlay.ts +183 -0
  412. package/src/ui/live-duration.ts +55 -0
  413. package/src/ui/live-run-sidebar.ts +293 -0
  414. package/src/ui/loaders.ts +6 -0
  415. package/src/ui/mascot.ts +449 -0
  416. package/src/ui/overlays/agent-picker-overlay.ts +66 -0
  417. package/src/ui/overlays/confirm-overlay.ts +60 -0
  418. package/src/ui/overlays/help-overlay.ts +177 -0
  419. package/src/ui/overlays/mailbox-compose-overlay.ts +181 -0
  420. package/src/ui/overlays/mailbox-compose-preview.ts +78 -0
  421. package/src/ui/overlays/mailbox-detail-overlay.ts +155 -0
  422. package/src/ui/pi-ui-compat.ts +68 -0
  423. package/src/ui/powerbar-publisher.ts +459 -0
  424. package/src/ui/render-coalescer.ts +101 -0
  425. package/src/ui/render-diff.ts +160 -0
  426. package/src/ui/render-scheduler.ts +278 -0
  427. package/src/ui/run-action-dispatcher.ts +182 -0
  428. package/src/ui/run-dashboard.ts +910 -0
  429. package/src/ui/run-event-bus.ts +381 -0
  430. package/src/ui/run-snapshot-cache.ts +1057 -0
  431. package/src/ui/settings-overlay.ts +1067 -0
  432. package/src/ui/shared-overlay-scheduler.ts +96 -0
  433. package/src/ui/snapshot-types.ts +90 -0
  434. package/src/ui/spinner.ts +17 -0
  435. package/src/ui/status-colors.ts +143 -0
  436. package/src/ui/syntax-highlight.ts +136 -0
  437. package/src/ui/terminal-status.ts +269 -0
  438. package/src/ui/theme-adapter.ts +271 -0
  439. package/src/ui/theme-discovery.ts +199 -0
  440. package/src/ui/tool-progress-formatter.ts +93 -0
  441. package/src/ui/tool-renderers/brief-mode.ts +225 -0
  442. package/src/ui/tool-renderers/index.ts +726 -0
  443. package/src/ui/transcript-cache.ts +128 -0
  444. package/src/ui/transcript-entries.ts +256 -0
  445. package/src/ui/transcript-viewer.ts +424 -0
  446. package/src/ui/widget/index.ts +418 -0
  447. package/src/ui/widget/widget-formatters.ts +182 -0
  448. package/src/ui/widget/widget-model.ts +110 -0
  449. package/src/ui/widget/widget-renderer.ts +182 -0
  450. package/src/ui/widget/widget-types.ts +36 -0
  451. package/src/utils/bm25-search.ts +235 -0
  452. package/src/utils/completion-dedupe.ts +63 -0
  453. package/src/utils/conflict-detect.ts +668 -0
  454. package/src/utils/env-allowlist.ts +30 -0
  455. package/src/utils/env-filter.ts +155 -0
  456. package/src/utils/file-coalescer.ts +98 -0
  457. package/src/utils/fingerprint.ts +180 -0
  458. package/src/utils/frontmatter.ts +70 -0
  459. package/src/utils/fs-watch.ts +37 -0
  460. package/src/utils/gh-protocol.ts +556 -0
  461. package/src/utils/git.ts +260 -0
  462. package/src/utils/guards.ts +107 -0
  463. package/src/utils/ids.ts +24 -0
  464. package/src/utils/incremental-reader.ts +220 -0
  465. package/src/utils/internal-error.ts +10 -0
  466. package/src/utils/names.ts +36 -0
  467. package/src/utils/ndjson.ts +115 -0
  468. package/src/utils/paths.ts +227 -0
  469. package/src/utils/project-detector.ts +160 -0
  470. package/src/utils/redaction.ts +370 -0
  471. package/src/utils/resolve-shell.ts +36 -0
  472. package/src/utils/run-watcher-registry.ts +152 -0
  473. package/src/utils/safe-paths.ts +393 -0
  474. package/src/utils/scan-cache.ts +144 -0
  475. package/src/utils/session-utils.ts +110 -0
  476. package/src/utils/sleep.ts +54 -0
  477. package/src/utils/socket-path.ts +164 -0
  478. package/src/utils/sse-parser.ts +131 -0
  479. package/src/utils/task-name-generator.ts +337 -0
  480. package/src/utils/timings.ts +33 -0
  481. package/src/utils/token-counter.ts +200 -0
  482. package/src/utils/visual.ts +207 -0
  483. package/src/workflows/cost-estimator.ts +34 -0
  484. package/src/workflows/discover-workflows.ts +308 -0
  485. package/src/workflows/intermediate-store.ts +166 -0
  486. package/src/workflows/preflight-validator.ts +168 -0
  487. package/src/workflows/topology-analyzer.ts +203 -0
  488. package/src/workflows/validate-workflow.ts +50 -0
  489. package/src/workflows/workflow-config.ts +75 -0
  490. package/src/workflows/workflow-serializer.ts +32 -0
  491. package/src/worktree/branch-freshness.ts +112 -0
  492. package/src/worktree/cleanup.ts +341 -0
  493. package/src/worktree/worktree-manager.ts +1204 -0
@@ -0,0 +1,203 @@
1
+ // src/workflows/topology-analyzer.ts
2
+ //
3
+ // Workflow topology classifier. Given a WorkflowConfig, returns a TopologyAnalysis
4
+ // describing the structural shape (single / sequential / concurrent / complex-dag
5
+ // / dynamic). The shape is used by the preflight validator to enforce the
6
+ // "don't use pi-crew for sequential independent agents" rule from .crew/knowledge.md.
7
+ //
8
+ // Algorithm (high level):
9
+ // 1. runtime === "dynamic" → DYNAMIC (chain/script workflows decide at runtime)
10
+ // 2. stepCount === 1 → SINGLE (one step: no concurrency, no DAG)
11
+ // 3. parallelGroupCount >= 1 AND max-fanout >= 3 → CONCURRENT
12
+ // 4. stepCount >= 4 AND has-multi-deps → COMPLEX_DAG
13
+ // 5. else → SEQUENTIAL
14
+ //
15
+ // "Has-multi-deps" = at least one step lists 2+ dependsOn. This is the
16
+ // unambiguous signal of a branching DAG (diamond patterns, fan-in joins).
17
+ // Plain linear chains with high depth are still SEQUENTIAL — Run #3 fast-fix
18
+ // (3 steps linear, depth 3) and the default workflow (4 steps linear, depth 4)
19
+ // are both sequential by this rule; raw Agent calls are faster for both.
20
+
21
+ import type { WorkflowConfig, WorkflowStep } from "./workflow-config.ts";
22
+
23
+ export type WorkflowTopology = "single" | "sequential" | "concurrent" | "complex-dag" | "dynamic";
24
+
25
+ export type TopologyRecommendation = "raw_agent" | "fast_fix" | "parallel_research" | "implementation_adaptive" | "any";
26
+
27
+ export interface TopologyAnalysis {
28
+ topology: WorkflowTopology;
29
+ stepCount: number;
30
+ parallelGroupCount: number;
31
+ fanOutDegree: number;
32
+ dagDepth: number;
33
+ recommendation: TopologyRecommendation;
34
+ reason: string;
35
+ }
36
+
37
+ /** Distinct parallelGroup values across all steps. Empty if no step sets a group. */
38
+ export function parallelGroupsFromSteps(steps: WorkflowStep[]): Set<string> {
39
+ const out = new Set<string>();
40
+ for (const step of steps) {
41
+ if (step.parallelGroup !== undefined) out.add(step.parallelGroup);
42
+ }
43
+ return out;
44
+ }
45
+
46
+ /** Max group size across all parallelGroup values. 0 if no step sets a group. */
47
+ export function fanOutDegreeFromSteps(steps: WorkflowStep[]): number {
48
+ const counts = new Map<string, number>();
49
+ for (const step of steps) {
50
+ if (step.parallelGroup === undefined) continue;
51
+ counts.set(step.parallelGroup, (counts.get(step.parallelGroup) ?? 0) + 1);
52
+ }
53
+ let max = 0;
54
+ for (const count of counts.values()) if (count > max) max = count;
55
+ return max;
56
+ }
57
+
58
+ /**
59
+ * Longest-path DAG depth from roots. A root is a step with no dependsOn.
60
+ * Returns 0 for an empty list, 1 for a list of roots only with no inter-step deps.
61
+ *
62
+ * Defensive: a step depending on an unknown id is treated as a root
63
+ * (validate-workflow.ts catches real cycles before this runs; this is
64
+ * belt-and-suspenders against malformed inputs).
65
+ */
66
+ export function dagDepthFromSteps(steps: WorkflowStep[]): number {
67
+ if (steps.length === 0) return 0;
68
+ const ids = new Set(steps.map((s) => s.id));
69
+ // Build adjacency and indegree. Unknown deps are dropped to avoid phantom edges.
70
+ const indeg = new Map<string, number>();
71
+ const adj = new Map<string, string[]>();
72
+ for (const step of steps) {
73
+ const deps = (step.dependsOn ?? []).filter((d) => ids.has(d));
74
+ indeg.set(step.id, deps.length);
75
+ // step.id's parents are deps; deps's children include step.id.
76
+ adj.set(step.id, adj.get(step.id) ?? []);
77
+ for (const dep of deps) {
78
+ const children = adj.get(dep) ?? [];
79
+ children.push(step.id);
80
+ adj.set(dep, children);
81
+ }
82
+ }
83
+ // Kahn-style BFS. depth[v] = max(depth[parent]) + 1, roots = 1.
84
+ const depth = new Map<string, number>();
85
+ const queue: string[] = [];
86
+ for (const [id, n] of indeg) {
87
+ if (n === 0) {
88
+ depth.set(id, 1);
89
+ queue.push(id);
90
+ }
91
+ }
92
+ let maxDepth = 0;
93
+ while (queue.length > 0) {
94
+ const v = queue.shift()!;
95
+ const dv = depth.get(v) ?? 0;
96
+ if (dv > maxDepth) maxDepth = dv;
97
+ for (const child of adj.get(v) ?? []) {
98
+ const cand = dv + 1;
99
+ if (cand > (depth.get(child) ?? 0)) depth.set(child, cand);
100
+ indeg.set(child, (indeg.get(child) ?? 0) - 1);
101
+ if ((indeg.get(child) ?? 0) === 0) queue.push(child);
102
+ }
103
+ }
104
+ return maxDepth;
105
+ }
106
+
107
+ /** True if at least one step lists 2+ dependsOn entries. */
108
+ function hasMultiDeps(steps: WorkflowStep[]): boolean {
109
+ for (const step of steps) {
110
+ if ((step.dependsOn?.length ?? 0) >= 2) return true;
111
+ }
112
+ return false;
113
+ }
114
+
115
+ /**
116
+ * Classify a workflow's topology. See file header for the rule order.
117
+ * Pure function — no I/O, no side effects, no exceptions.
118
+ */
119
+ export function analyzeWorkflowTopology(workflow: WorkflowConfig): TopologyAnalysis {
120
+ // Chain/dynamic workflows: runtime decides the topology at execution time.
121
+ // Don't try to classify the empty `steps: []` (DynamicWorkflowConfig forces
122
+ // it to be empty).
123
+ if (workflow.runtime === "dynamic") {
124
+ return {
125
+ topology: "dynamic",
126
+ stepCount: 0,
127
+ parallelGroupCount: 0,
128
+ fanOutDegree: 0,
129
+ dagDepth: 0,
130
+ recommendation: "any",
131
+ reason: "Chain/dynamic workflow — runtime decides topology",
132
+ };
133
+ }
134
+
135
+ const steps = workflow.steps;
136
+ const stepCount = steps.length;
137
+ const parallelGroupCount = parallelGroupsFromSteps(steps).size;
138
+ const fanOutDegree = fanOutDegreeFromSteps(steps);
139
+ const dagDepth = dagDepthFromSteps(steps);
140
+
141
+ // Explicit topology override from frontmatter `topology:` field.
142
+ // When set, the author has already classified the workflow — respect that.
143
+ // We still compute structural metrics so telemetry can show the delta.
144
+ if (workflow.topology !== undefined && workflow.topology !== "dynamic") {
145
+ const recommendation: TopologyRecommendation =
146
+ workflow.topology === "single" || workflow.topology === "sequential"
147
+ ? "raw_agent"
148
+ : workflow.topology === "concurrent"
149
+ ? "parallel_research"
150
+ : workflow.topology === "complex-dag"
151
+ ? "implementation_adaptive"
152
+ : "any";
153
+ return {
154
+ topology: workflow.topology,
155
+ stepCount,
156
+ parallelGroupCount,
157
+ fanOutDegree,
158
+ dagDepth,
159
+ recommendation,
160
+ reason: `Explicit topology from frontmatter: '${workflow.topology}'`,
161
+ };
162
+ }
163
+
164
+ let topology: WorkflowTopology;
165
+ let recommendation: TopologyRecommendation;
166
+ let reason: string;
167
+
168
+ // Note: explicit `workflow.topology` override is handled BEFORE the variable
169
+ // declarations below (in the block above). If we reach here, auto-classify.
170
+
171
+ if (stepCount === 1) {
172
+ topology = "single";
173
+ recommendation = "raw_agent";
174
+ reason = "Single-task workflow: no concurrency or DAG structure to justify pi-crew overhead.";
175
+ } else if (parallelGroupCount >= 1 && fanOutDegree >= 3) {
176
+ topology = "concurrent";
177
+ recommendation = "parallel_research";
178
+ reason = `Concurrent fan-out: ${fanOutDegree} steps in parallel group(s) of size ≥3.`;
179
+ } else if (stepCount >= 4 && hasMultiDeps(steps)) {
180
+ topology = "complex-dag";
181
+ recommendation = "implementation_adaptive";
182
+ reason = `Complex DAG: ${stepCount} steps with branching (≥2 deps on ≥1 node), depth ${dagDepth}.`;
183
+ } else {
184
+ topology = "sequential";
185
+ if (stepCount <= 3) {
186
+ recommendation = "raw_agent";
187
+ reason = `Sequential chain of ${stepCount} steps — raw Agent calls are faster.`;
188
+ } else {
189
+ recommendation = "fast_fix";
190
+ reason = `Sequential chain of ${stepCount} steps — audit-trail-justified, but raw calls remain faster.`;
191
+ }
192
+ }
193
+
194
+ return {
195
+ topology,
196
+ stepCount,
197
+ parallelGroupCount,
198
+ fanOutDegree,
199
+ dagDepth,
200
+ recommendation,
201
+ reason,
202
+ };
203
+ }
@@ -0,0 +1,50 @@
1
+ import type { TeamConfig } from "../teams/team-config.ts";
2
+ import type { WorkflowConfig } from "./workflow-config.ts";
3
+
4
+ export function validateWorkflowForTeam(workflow: WorkflowConfig, team: TeamConfig): string[] {
5
+ const errors: string[] = [];
6
+ const roles = new Set(team.roles.map((role) => role.name));
7
+ const stepIds = new Set<string>();
8
+
9
+ for (const step of workflow.steps) {
10
+ if (stepIds.has(step.id)) errors.push(`Duplicate workflow step id '${step.id}'.`);
11
+ stepIds.add(step.id);
12
+ if (!roles.has(step.role)) errors.push(`Step '${step.id}' references unknown team role '${step.role}'.`);
13
+ }
14
+
15
+ for (const step of workflow.steps) {
16
+ for (const dep of step.dependsOn ?? []) {
17
+ if (!stepIds.has(dep)) errors.push(`Step '${step.id}' depends on unknown step '${dep}'.`);
18
+ }
19
+ }
20
+
21
+ // Validate output field types
22
+ for (const step of workflow.steps) {
23
+ if (step.output !== undefined && step.output !== false && typeof step.output !== "string") {
24
+ errors.push(`Step '${step.id}' has invalid 'output' field: expected string or false, got ${typeof step.output}.`);
25
+ }
26
+ if (typeof step.output === "string" && step.output.trim() === "") {
27
+ errors.push(`Step '${step.id}' has empty 'output' string.`);
28
+ }
29
+ }
30
+
31
+ const visiting = new Set<string>();
32
+ const visited = new Set<string>();
33
+ const byId = new Map(workflow.steps.map((step) => [step.id, step]));
34
+
35
+ function visit(id: string, trail: string[]): void {
36
+ if (visited.has(id)) return;
37
+ if (visiting.has(id)) {
38
+ errors.push(`Workflow dependency cycle detected: ${[...trail, id].join(" -> ")}.`);
39
+ return;
40
+ }
41
+ visiting.add(id);
42
+ const step = byId.get(id);
43
+ for (const dep of step?.dependsOn ?? []) visit(dep, [...trail, id]);
44
+ visiting.delete(id);
45
+ visited.add(id);
46
+ }
47
+
48
+ for (const step of workflow.steps) visit(step.id, []);
49
+ return [...new Set(errors)];
50
+ }
@@ -0,0 +1,75 @@
1
+ import type { ResourceSource } from "../agents/agent-config.ts";
2
+
3
+ export interface WorkflowStep {
4
+ id: string;
5
+ role: string;
6
+ task: string;
7
+ /** Security (F-02): provenance of the workflow file that declared this step.
8
+ * Populated during discovery by discover-workflows.ts. Used by task-runner.ts
9
+ * to gate preStepScript execution — project-sourced workflows may NOT run
10
+ * pre-step scripts (RCE prevention). Undefined for manually-constructed steps. */
11
+ source?: ResourceSource;
12
+ dependsOn?: string[];
13
+ parallelGroup?: string;
14
+ output?: string | false;
15
+ reads?: string[] | false;
16
+ model?: string;
17
+ /** Additional skills for this step; false disables role-default injected skills for this step. */
18
+ skills?: string[] | false;
19
+ progress?: boolean;
20
+ worktree?: boolean;
21
+ verify?: boolean;
22
+ /** Per-step files to overlay into the worktree (in addition to global worktree.seedPaths).
23
+ * Useful when only certain steps need access to local drafts or scripts. */
24
+ seedPaths?: string[];
25
+ /** Path to a deterministic script to run before dispatching the LLM worker.
26
+ * Script stdout is injected into the worker's prompt as context.
27
+ * Pattern origin: Understand-Anything deterministic pre-step pattern. */
28
+ preStepScript?: string;
29
+ /** Arguments for preStepScript. Passed as positional args. */
30
+ preStepArgs?: string[];
31
+ /** Timeout in ms for preStepScript. Default: 30000. */
32
+ preStepTimeout?: number;
33
+ /** Round 21 (E4): if true, a failing preStepScript does NOT abort the task.
34
+ * The failure is logged as a warning and the task proceeds without the
35
+ * pre-step output. Use for advisory hooks (e.g. optional test runs) whose
36
+ * failure shouldn't block the workflow. Default: false (fail-fast). */
37
+ preStepOptional?: boolean;
38
+ }
39
+
40
+ export interface WorkflowConfig {
41
+ name: string;
42
+ description: string;
43
+ source: ResourceSource;
44
+ filePath: string;
45
+ steps: WorkflowStep[];
46
+ maxConcurrency?: number;
47
+ /** P2 dynamic-workflow discriminator. Default "static" (the .workflow.md step-list model).
48
+ * "dynamic" = the workflow is a JS/TS script (.dwf.ts) run via dynamic-workflow-runner.
49
+ * Backward-compatible: absent = "static". */
50
+ runtime?: "static" | "dynamic";
51
+ /** For runtime:"dynamic" — relative/absolute path to the .dwf.ts script. Unused for static. */
52
+ dynamicScript?: string;
53
+ /** For runtime:"dynamic" — per-workflow token budget. When set, ctx.agent() auto-rejects with
54
+ * ok:false once exhausted. Accumulated from each agent run's reported usage. */
55
+ maxTokenBudget?: number;
56
+ /** Explicit topology classification from frontmatter `topology:` field.
57
+ * When set, overrides the auto-classified topology in analyzeWorkflowTopology().
58
+ * Used by preflight-validator to enforce "don't use pi-crew for sequential chains".
59
+ * Valid values: 'single' | 'sequential' | 'concurrent' | 'complex-dag' | 'dynamic'.
60
+ * Absent = auto-classify from step structure (default). */
61
+ topology?: "single" | "sequential" | "concurrent" | "complex-dag" | "dynamic";
62
+ /** Round 25 (M6): coalesce micro-tasks. Default false (off). When true,
63
+ * multiple ready tasks sharing role + cwd are grouped into a single
64
+ * multi-task worker prompt to reduce per-task cold-start cost. Disabled
65
+ * in v0.9.17 unless the workflow author opts in. See
66
+ * src/runtime/coalesce-tasks.ts. */
67
+ coalesceMicroTasks?: boolean;
68
+ }
69
+
70
+ /** A dynamic workflow (runtime === "dynamic"). steps is empty — the script is the source of truth. */
71
+ export interface DynamicWorkflowConfig extends WorkflowConfig {
72
+ runtime: "dynamic";
73
+ dynamicScript: string;
74
+ steps: [];
75
+ }
@@ -0,0 +1,32 @@
1
+ import type { WorkflowConfig, WorkflowStep } from "./workflow-config.ts";
2
+
3
+ function serializeStep(step: WorkflowStep): string[] {
4
+ const lines = [`## ${step.id}`, `role: ${step.role}`];
5
+ if (step.dependsOn?.length) lines.push(`dependsOn: ${step.dependsOn.join(", ")}`);
6
+ if (step.parallelGroup) lines.push(`parallelGroup: ${step.parallelGroup}`);
7
+ if (step.output === false) lines.push("output: false");
8
+ else if (step.output) lines.push(`output: ${step.output}`);
9
+ if (step.reads === false) lines.push("reads: false");
10
+ else if (Array.isArray(step.reads) && step.reads.length > 0) lines.push(`reads: ${step.reads.join(", ")}`);
11
+ if (step.model) lines.push(`model: ${step.model}`);
12
+ if (step.skills === false) lines.push("skills: false");
13
+ else if (Array.isArray(step.skills) && step.skills.length > 0) lines.push(`skills: ${step.skills.join(", ")}`);
14
+ if (step.progress !== undefined) lines.push(`progress: ${step.progress ? "true" : "false"}`);
15
+ if (step.worktree !== undefined) lines.push(`worktree: ${step.worktree ? "true" : "false"}`);
16
+ if (step.verify !== undefined) lines.push(`verify: ${step.verify ? "true" : "false"}`);
17
+ lines.push("", step.task.trim(), "");
18
+ return lines;
19
+ }
20
+
21
+ export function serializeWorkflow(workflow: WorkflowConfig): string {
22
+ const lines = [
23
+ "---",
24
+ `name: ${workflow.name}`,
25
+ `description: ${workflow.description}`,
26
+ ...(workflow.maxConcurrency !== undefined ? [`maxConcurrency: ${workflow.maxConcurrency}`] : []),
27
+ "---",
28
+ "",
29
+ ...workflow.steps.flatMap(serializeStep),
30
+ ];
31
+ return lines.join("\n");
32
+ }
@@ -0,0 +1,112 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { WINDOWS_ESSENTIAL_ENV_VARS } from "../utils/env-allowlist.ts";
3
+ import { sanitizeEnvSecrets } from "../utils/env-filter.ts";
4
+
5
+ // Read-only git operations only (rev-list, rev-parse, log). Sanitize env to
6
+ // avoid leaking API keys/tokens to any git hook/alias/credential-helper.
7
+ // C-1 fix (code-review 2026-06-23): previously inherited the full parent env.
8
+ const GIT_SAFE_ENV = sanitizeEnvSecrets(process.env, {
9
+ allowList: [
10
+ "PATH",
11
+ "HOME",
12
+ "USER",
13
+ ...WINDOWS_ESSENTIAL_ENV_VARS,
14
+ "SHELL",
15
+ "TERM",
16
+ "LANG",
17
+ "LC_ALL",
18
+ "GIT_CONFIG_GLOBAL",
19
+ "GIT_CONFIG_SYSTEM",
20
+ "GIT_EXEC_PATH",
21
+ ],
22
+ });
23
+
24
+ export type BranchFreshnessStatus = "fresh" | "stale" | "diverged" | "unknown";
25
+ export type StaleBranchPolicy = "warn" | "block" | "auto_rebase" | "auto_merge_forward";
26
+
27
+ export interface BranchFreshness {
28
+ status: BranchFreshnessStatus;
29
+ branch?: string;
30
+ mainRef: string;
31
+ ahead: number;
32
+ behind: number;
33
+ missingFixes: string[];
34
+ message: string;
35
+ error?: string;
36
+ }
37
+
38
+ function git(cwd: string, args: string[]): string {
39
+ return execFileSync("git", args, {
40
+ cwd,
41
+ encoding: "utf-8",
42
+ stdio: ["ignore", "pipe", "pipe"],
43
+ env: GIT_SAFE_ENV,
44
+ windowsHide: true,
45
+ }).trim();
46
+ }
47
+
48
+ function count(cwd: string, range: string): number {
49
+ const raw = git(cwd, ["rev-list", "--count", range]);
50
+ const parsed = Number.parseInt(raw, 10);
51
+ return Number.isFinite(parsed) ? parsed : 0;
52
+ }
53
+
54
+ export function checkBranchFreshness(cwd: string, mainRef = "main"): BranchFreshness {
55
+ try {
56
+ git(cwd, ["rev-parse", "--is-inside-work-tree"]);
57
+ const branch = git(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
58
+ const behind = count(cwd, `${branch}..${mainRef}`);
59
+ const ahead = count(cwd, `${mainRef}..${branch}`);
60
+ const missingFixes =
61
+ behind > 0
62
+ ? git(cwd, ["log", "--format=%s", `${branch}..${mainRef}`])
63
+ .split("\n")
64
+ .map((line) => line.trim())
65
+ .filter(Boolean)
66
+ : [];
67
+ if (behind === 0)
68
+ return {
69
+ status: "fresh",
70
+ branch,
71
+ mainRef,
72
+ ahead,
73
+ behind,
74
+ missingFixes,
75
+ message: `Branch '${branch}' is fresh against ${mainRef}.`,
76
+ };
77
+ if (ahead > 0)
78
+ return {
79
+ status: "diverged",
80
+ branch,
81
+ mainRef,
82
+ ahead,
83
+ behind,
84
+ missingFixes,
85
+ message: `Branch '${branch}' diverged from ${mainRef}: ahead=${ahead}, behind=${behind}.`,
86
+ };
87
+ return {
88
+ status: "stale",
89
+ branch,
90
+ mainRef,
91
+ ahead,
92
+ behind,
93
+ missingFixes,
94
+ message: `Branch '${branch}' is ${behind} commit(s) behind ${mainRef}.`,
95
+ };
96
+ } catch (error) {
97
+ const message = error instanceof Error ? error.message : String(error);
98
+ return {
99
+ status: "unknown",
100
+ mainRef,
101
+ ahead: 0,
102
+ behind: 0,
103
+ missingFixes: [],
104
+ message: "Branch freshness could not be determined.",
105
+ error: message,
106
+ };
107
+ }
108
+ }
109
+
110
+ export function shouldBlockForBranchFreshness(freshness: BranchFreshness, policy: StaleBranchPolicy = "warn"): boolean {
111
+ return policy === "block" && (freshness.status === "stale" || freshness.status === "diverged");
112
+ }