tumwater 0.1.2 → 0.2.0

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 (361) hide show
  1. package/README.md +74 -108
  2. package/dist/build-info.json +2 -2
  3. package/dist/src/agent/agent-args.js +24 -0
  4. package/dist/src/agent/agent-backend.js +2 -2
  5. package/dist/src/agent/backend-traits.js +60 -0
  6. package/dist/src/agent/claude/claude-account.js +61 -8
  7. package/dist/src/agent/claude/claude-args.js +12 -15
  8. package/dist/src/agent/claude/claude-backend.js +51 -41
  9. package/dist/src/agent/claude/claude-env.js +7 -3
  10. package/dist/src/agent/claude/claude-stream.js +7 -16
  11. package/dist/src/agent/image-input.js +107 -0
  12. package/dist/src/agent/notes-shim.js +41 -0
  13. package/dist/src/agent/opencode/opencode-args.js +61 -0
  14. package/dist/src/agent/opencode/opencode-backend.js +255 -0
  15. package/dist/src/agent/opencode/opencode-catalog.js +184 -0
  16. package/dist/src/agent/opencode/opencode-config.js +188 -0
  17. package/dist/src/agent/opencode/opencode-env.js +36 -0
  18. package/dist/src/agent/opencode/opencode-session-id.js +37 -0
  19. package/dist/src/agent/opencode/opencode-stream.js +278 -0
  20. package/dist/src/agent/role-notes-write.js +16 -32
  21. package/dist/src/agent/run-agent.js +95 -18
  22. package/dist/src/agent/session-ledger.js +57 -1
  23. package/dist/src/backlog/backlog-archive.js +296 -0
  24. package/dist/src/backlog/backlog-cli.js +573 -0
  25. package/dist/src/backlog/backlog-commit.js +31 -0
  26. package/dist/src/backlog/backlog-eligibility.js +357 -33
  27. package/dist/src/backlog/backlog-md.js +98 -18
  28. package/dist/src/backlog/backlog-render.js +62 -11
  29. package/dist/src/backlog/backlog-structure.js +261 -58
  30. package/dist/src/backlog/backlog-write.js +197 -319
  31. package/dist/src/backlog/backlog.js +113 -16
  32. package/dist/src/backlog/question-answer.js +339 -0
  33. package/dist/src/baseline/main-baseline.js +75 -88
  34. package/dist/src/baseline/main-red.js +38 -30
  35. package/dist/src/brief/brief-edit.js +43 -0
  36. package/dist/src/{brief.js → brief/brief.js} +66 -10
  37. package/dist/src/budget/budget.js +32 -15
  38. package/dist/src/budget/fallback-breaker.js +8 -7
  39. package/dist/src/build/build-check-detect.js +8 -7
  40. package/dist/src/build/build-check-events.js +68 -22
  41. package/dist/src/build/build-check-report.js +22 -23
  42. package/dist/src/build/build-check-scoped.js +51 -62
  43. package/dist/src/build/build-check.js +15 -14
  44. package/dist/src/build/build-info.js +2 -1
  45. package/dist/src/build/build-stage.js +23 -22
  46. package/dist/src/build/dep-install.js +22 -21
  47. package/dist/src/build/host-sleep.js +1 -1
  48. package/dist/src/change/change-data.js +25 -14
  49. package/dist/src/change/change-render.js +11 -10
  50. package/dist/src/cli/brief-command.js +58 -0
  51. package/dist/src/cli/cli-args.js +25 -5
  52. package/dist/src/cli/cli-command-args.js +46 -14
  53. package/dist/src/cli/cli-editor.js +64 -0
  54. package/dist/src/cli/cli-flag-specs.js +54 -16
  55. package/dist/src/cli/cli-marker-commands.js +13 -10
  56. package/dist/src/cli/cli-output.js +9 -0
  57. package/dist/src/cli/cli-query-commands.js +458 -49
  58. package/dist/src/cli/cli-repo-gate.js +1 -1
  59. package/dist/src/cli/cli-run.js +208 -59
  60. package/dist/src/cli/completion.js +207 -0
  61. package/dist/src/cli/config-commands.js +14 -11
  62. package/dist/src/cli/help.js +305 -110
  63. package/dist/src/cli/log-commands.js +127 -21
  64. package/dist/src/cli/notify-command.js +33 -18
  65. package/dist/src/cli/question-commands.js +29 -224
  66. package/dist/src/cli.js +121 -40
  67. package/dist/src/collections.js +66 -16
  68. package/dist/src/concurrency/check-permit.js +16 -17
  69. package/dist/src/concurrency/lock.js +6 -5
  70. package/dist/src/concurrency/provider-lease.js +69 -0
  71. package/dist/src/concurrency/semaphore.js +258 -36
  72. package/dist/src/config/config-aliases.js +106 -0
  73. package/dist/src/config/config-editable-keys.js +3 -3
  74. package/dist/src/config/config-fallbacks.js +379 -0
  75. package/dist/src/config/config-field-checks.js +19 -10
  76. package/dist/src/config/config-keys.js +160 -0
  77. package/dist/src/config/config-live.js +64 -12
  78. package/dist/src/config/config-schema.js +34 -22
  79. package/dist/src/config/config-validation.js +132 -48
  80. package/dist/src/config/config-views.js +119 -337
  81. package/dist/src/config/config-write.js +138 -177
  82. package/dist/src/config/config.js +60 -49
  83. package/dist/src/config/model-selector.js +28 -2
  84. package/dist/src/doctor/doctor-backlog.js +546 -49
  85. package/dist/src/doctor/doctor-checks.js +534 -56
  86. package/dist/src/doctor/doctor-holds.js +193 -53
  87. package/dist/src/doctor/doctor-install.js +30 -0
  88. package/dist/src/doctor/doctor-launch-services.js +2 -2
  89. package/dist/src/doctor/doctor-model-checks.js +549 -157
  90. package/dist/src/doctor/doctor-notify.js +27 -0
  91. package/dist/src/doctor/doctor-orphans.js +10 -9
  92. package/dist/src/doctor/doctor-render.js +36 -9
  93. package/dist/src/doctor/doctor.js +80 -22
  94. package/dist/src/doctor/image-probe.js +244 -0
  95. package/dist/src/doctor/probe.js +64 -0
  96. package/dist/src/events/event-format.js +226 -102
  97. package/dist/src/events/event-labels.js +116 -0
  98. package/dist/src/events/event-legacy.js +140 -0
  99. package/dist/src/events/event-read.js +58 -22
  100. package/dist/src/events/event-window.js +27 -7
  101. package/dist/src/events/events.js +18 -14
  102. package/dist/src/events/notify.js +137 -38
  103. package/dist/src/failure/failure-cluster.js +12 -9
  104. package/dist/src/failure/failure-data.js +96 -48
  105. package/dist/src/failure/failure-render.js +69 -58
  106. package/dist/src/failure/failure-state-change.js +33 -26
  107. package/dist/src/failure/time-spend.js +79 -59
  108. package/dist/src/files/file-queue.js +16 -4
  109. package/dist/src/files/files.js +18 -6
  110. package/dist/src/files/json-object.js +18 -3
  111. package/dist/src/files/tail.js +1 -1
  112. package/dist/src/gates/bootstrap-gates.js +5 -4
  113. package/dist/src/gates/budget-gates.js +250 -34
  114. package/dist/src/gates/disk-gate.js +18 -18
  115. package/dist/src/gates/gate-polls.js +117 -69
  116. package/dist/src/gates/maintenance-quota.js +29 -29
  117. package/dist/src/gates/pause-gates.js +11 -11
  118. package/dist/src/gates/readiness.js +2 -1
  119. package/dist/src/gates/role-cap-gates.js +16 -21
  120. package/dist/src/gates/startup-gate.js +75 -31
  121. package/dist/src/gates/streak-gate.js +18 -16
  122. package/dist/src/git/commit-message.js +12 -5
  123. package/dist/src/git/git-diff.js +16 -16
  124. package/dist/src/git/git-run.js +8 -8
  125. package/dist/src/git/git.js +86 -55
  126. package/dist/src/git/slots-state.js +14 -5
  127. package/dist/src/git/worktree-pool.js +25 -18
  128. package/dist/src/git/worktree-use.js +15 -14
  129. package/dist/src/git/worktree.js +18 -18
  130. package/dist/src/gui/gui-args.js +10 -14
  131. package/dist/src/gui/gui-backlog-commands.js +273 -0
  132. package/dist/src/gui/gui-command.js +1 -1
  133. package/dist/src/gui/gui-config-commands.js +440 -0
  134. package/dist/src/gui/gui-endpoint-commands.js +16 -669
  135. package/dist/src/gui/gui-endpoint-common.js +49 -0
  136. package/dist/src/gui/gui-endpoints.js +116 -56
  137. package/dist/src/gui/gui-operator-commands.js +145 -0
  138. package/dist/src/gui/gui-prompt-commands.js +234 -0
  139. package/dist/src/gui/gui-server.js +28 -8
  140. package/dist/src/gui/gui-team-commands.js +164 -0
  141. package/dist/src/gui/http-body.js +17 -1
  142. package/dist/src/history/history-data.js +194 -98
  143. package/dist/src/history/history-render.js +76 -0
  144. package/dist/src/history/history.js +37 -58
  145. package/dist/src/inbox/inbox-attachments.js +75 -14
  146. package/dist/src/inbox/inbox-cancel.js +7 -5
  147. package/dist/src/inbox/inbox-edit.js +1 -1
  148. package/dist/src/inbox/inbox-submit.js +44 -4
  149. package/dist/src/inbox/inbox-top.js +83 -0
  150. package/dist/src/inbox/inbox.js +8 -2
  151. package/dist/src/inbox/pending-prompt.js +1 -1
  152. package/dist/src/inbox/prompt-commands.js +170 -80
  153. package/dist/src/init/init-templates.js +16 -14
  154. package/dist/src/init/init.js +12 -11
  155. package/dist/src/loop/leftover.js +28 -27
  156. package/dist/src/loop/loop-fallback.js +2 -2
  157. package/dist/src/loop/loop-pi.js +106 -52
  158. package/dist/src/loop/loop-recovery.js +15 -15
  159. package/dist/src/loop/loop-state.js +139 -13
  160. package/dist/src/loop/loop-tick.js +194 -86
  161. package/dist/src/loop/loop.js +72 -36
  162. package/dist/src/loop/model-fallback.js +3 -2
  163. package/dist/src/loop/revision.js +16 -7
  164. package/dist/src/merge/backlog-conflicts.js +155 -0
  165. package/dist/src/{landing/landing-batch.js → merge/merge-batch.js} +90 -89
  166. package/dist/src/{landing/landing-check-failures.js → merge/merge-check-failures.js} +87 -41
  167. package/dist/src/{landing/landing-core.js → merge/merge-core.js} +119 -95
  168. package/dist/src/{landing/landing-diff.js → merge/merge-diff.js} +1 -1
  169. package/dist/src/merge/merge-drain.js +212 -0
  170. package/dist/src/{landing/landing-git.js → merge/merge-git.js} +94 -21
  171. package/dist/src/merge/merge-pipeline.js +99 -0
  172. package/dist/src/{landing/landing-questions.js → merge/merge-questions.js} +9 -6
  173. package/dist/src/merge/merge-queue-render.js +75 -0
  174. package/dist/src/{landing/landing-queue.js → merge/merge-queue.js} +95 -36
  175. package/dist/src/merge/merge-slot.js +340 -0
  176. package/dist/src/{landing/landing-stack.js → merge/merge-stack.js} +66 -62
  177. package/dist/src/{landing/landing-merge.js → merge/merge-to-main.js} +72 -62
  178. package/dist/src/merge/merge-verify.js +212 -0
  179. package/dist/src/notes-cli.js +97 -0
  180. package/dist/src/operator/operator-commands.js +154 -47
  181. package/dist/src/operator/operator-intent.js +87 -49
  182. package/dist/src/operator/operator-requests.js +52 -52
  183. package/dist/src/operator/retire.js +62 -27
  184. package/dist/src/operator/revert.js +71 -0
  185. package/dist/src/orchestrator/orchestrator-launch.js +74 -14
  186. package/dist/src/orchestrator/orchestrator-scheduling.js +129 -44
  187. package/dist/src/orchestrator/orchestrator.js +158 -100
  188. package/dist/src/orchestrator/retention.js +29 -12
  189. package/dist/src/orchestrator/startup-migration-steps.js +51 -0
  190. package/dist/src/orchestrator/startup-migrations.js +40 -0
  191. package/dist/src/paths.js +128 -37
  192. package/dist/src/pi/pi-args.js +26 -3
  193. package/dist/src/pi/pi-backend.js +15 -23
  194. package/dist/src/pi/pi-bin.js +18 -12
  195. package/dist/src/pi/pi-event-line.js +17 -1
  196. package/dist/src/pi/pi-failure.js +87 -0
  197. package/dist/src/pi/pi-models.js +126 -38
  198. package/dist/src/pi/pi-run-result.js +1 -1
  199. package/dist/src/pi/pi-settings.js +86 -0
  200. package/dist/src/pi/pi-stream.js +131 -107
  201. package/dist/src/pi/pi-watchdogs.js +47 -43
  202. package/dist/src/pi-extension/bounded-output.js +20 -5
  203. package/dist/src/pi-extension/context-budget.js +3 -1
  204. package/dist/src/pi-extension/context-shake.js +54 -21
  205. package/dist/src/pi-extension/context-window.js +37 -0
  206. package/dist/src/pi-extension/full-output.js +2 -2
  207. package/dist/src/pi-extension/strip-thinking.js +80 -0
  208. package/dist/src/pi-extension/trim-system-prompt.js +38 -0
  209. package/dist/src/process/launch-services.js +11 -10
  210. package/dist/src/process/process-table.js +1 -1
  211. package/dist/src/process/process.js +7 -7
  212. package/dist/src/process/run-marker.js +29 -6
  213. package/dist/src/process/supervisor.js +47 -25
  214. package/dist/src/prompt/dialect.js +30 -10
  215. package/dist/src/prompt/gate-prompts.js +170 -67
  216. package/dist/src/prompt/principles.js +1 -0
  217. package/dist/src/prompt/prompt-followup.js +35 -20
  218. package/dist/src/prompt/prompt.js +249 -91
  219. package/dist/src/redeploy/redeploy-policy.js +10 -10
  220. package/dist/src/redeploy/redeploy.js +6 -4
  221. package/dist/src/redeploy/redeployer.js +63 -55
  222. package/dist/src/redeploy/self-reload.js +1 -1
  223. package/dist/src/report/report-data.js +264 -255
  224. package/dist/src/report/report-fold.js +353 -0
  225. package/dist/src/report/report-render.js +270 -33
  226. package/dist/src/request-timeouts.js +1 -1
  227. package/dist/src/review/known-flakes.js +34 -14
  228. package/dist/src/review/protected-edits.js +33 -0
  229. package/dist/src/review/review-followup.js +16 -4
  230. package/dist/src/review/review-precheck.js +14 -13
  231. package/dist/src/review/review-verdict.js +14 -0
  232. package/dist/src/review/review.js +81 -39
  233. package/dist/src/review/secret-leaks.js +127 -0
  234. package/dist/src/review/suite-rerun.js +4 -3
  235. package/dist/src/roles/legacy-role-ids.js +21 -0
  236. package/dist/src/roles/legacy-role-migration.js +62 -0
  237. package/dist/src/roles/loop-ids.js +19 -2
  238. package/dist/src/roles/role-catalog.js +125 -135
  239. package/dist/src/roles/role-guidance.js +64 -31
  240. package/dist/src/roles/role-labels.js +10 -0
  241. package/dist/src/roles/role-render.js +194 -18
  242. package/dist/src/roles/role-view.js +216 -17
  243. package/dist/src/roles/roles.js +18 -15
  244. package/dist/src/scheduling/backoff.js +29 -19
  245. package/dist/src/scheduling/claims.js +25 -9
  246. package/dist/src/scheduling/once-round.js +11 -11
  247. package/dist/src/scheduling/quiet-hours.js +25 -32
  248. package/dist/src/scheduling/scheduling.js +43 -24
  249. package/dist/src/scheduling/{work-landed-cache.js → work-merged-cache.js} +14 -14
  250. package/dist/src/status/status-budget.js +115 -0
  251. package/dist/src/status/status-data.js +77 -184
  252. package/dist/src/status/status-inbox.js +47 -0
  253. package/dist/src/status/status-install.js +27 -0
  254. package/dist/src/status/status-polls.js +68 -33
  255. package/dist/src/status/status-roles.js +105 -0
  256. package/dist/src/{fleet → team}/error-storm.js +10 -10
  257. package/dist/src/{fleet → team}/failure-spread.js +8 -8
  258. package/dist/src/{fleet → team}/orchestrator-info.js +86 -18
  259. package/dist/src/{fleet → team}/reclaim.js +5 -4
  260. package/dist/src/{fleet/fleet-hold.js → team/team-hold.js} +55 -21
  261. package/dist/src/{fleet/fleet-polls.js → team/team-polls.js} +116 -65
  262. package/dist/src/{fleet/fleet-state.js → team/team-state.js} +62 -37
  263. package/dist/src/text/datetime.js +42 -2
  264. package/dist/src/text/format.js +10 -1
  265. package/dist/src/text/markdown.js +1 -1
  266. package/dist/src/text/phrases.js +35 -34
  267. package/dist/src/text/suggest.js +3 -2
  268. package/dist/src/text/text.js +2 -2
  269. package/dist/src/tick/qa-coverage.js +2 -1
  270. package/dist/src/tick/stage-check.js +147 -26
  271. package/dist/src/tick/telemetry-digest.js +10 -9
  272. package/dist/src/tick/tick-apply.js +101 -72
  273. package/dist/src/tick/tick-detail-data.js +32 -18
  274. package/dist/src/tick/tick-detail.js +62 -21
  275. package/dist/src/tick/tick-finalize.js +29 -22
  276. package/dist/src/tick/tick-outcome.js +2 -1
  277. package/dist/src/tick/tick-prompt.js +94 -26
  278. package/dist/src/tick/tick-resume.js +29 -13
  279. package/dist/src/tick/tick-stage.js +91 -47
  280. package/dist/src/tick/tick-timing.js +60 -59
  281. package/dist/src/tick/tick-usage.js +53 -23
  282. package/dist/src/tick/tick-verdict.js +76 -10
  283. package/dist/src/ui/badges.js +118 -67
  284. package/dist/src/ui/gui/gui-client-boot.js +209 -30
  285. package/dist/src/ui/gui/gui-client-composer.js +102 -23
  286. package/dist/src/ui/gui/gui-client-drawer.js +330 -75
  287. package/dist/src/ui/gui/gui-client-history.js +96 -38
  288. package/dist/src/ui/gui/gui-client-labels.js +24 -0
  289. package/dist/src/ui/gui/gui-client-loops.js +94 -52
  290. package/dist/src/ui/gui/gui-client-markdown.js +1 -0
  291. package/dist/src/ui/gui/gui-client-model.js +63 -43
  292. package/dist/src/ui/gui/gui-client-operator.js +129 -39
  293. package/dist/src/ui/gui/gui-client-pending.js +36 -32
  294. package/dist/src/ui/gui/gui-client-report.js +339 -46
  295. package/dist/src/ui/gui/gui-client-settings.js +148 -14
  296. package/dist/src/ui/gui/gui-client-sound.js +2 -1
  297. package/dist/src/ui/gui/{gui-client-fleet.js → gui-client-team.js} +196 -72
  298. package/dist/src/ui/gui/gui-client.js +26 -20
  299. package/dist/src/ui/gui/gui-page.js +19 -19
  300. package/dist/src/ui/gui/gui-styles.js +12 -4
  301. package/dist/src/ui/progress-data.js +5 -3
  302. package/dist/src/ui/status-model.js +184 -122
  303. package/dist/src/ui/status-payload.js +119 -32
  304. package/dist/src/ui/status-render.js +122 -52
  305. package/dist/src/ui/team-alerts.js +341 -0
  306. package/dist/src/ui/tick-progress-model.js +14 -14
  307. package/dist/src/ui/tone.js +11 -8
  308. package/dist/src/ui/transcript-tail.js +1 -0
  309. package/dist/src/ui/transcript.js +23 -16
  310. package/dist/src/ui/tui/tui-app.js +1 -0
  311. package/dist/src/ui/tui/tui-backlog.js +85 -11
  312. package/dist/src/ui/tui/tui-editor-answer.js +97 -0
  313. package/dist/src/ui/tui/tui-editor-attach.js +107 -0
  314. package/dist/src/ui/tui/tui-editor-brief.js +107 -0
  315. package/dist/src/ui/tui/tui-editor-budget.js +155 -0
  316. package/dist/src/ui/tui/tui-editor-ctx.js +1 -0
  317. package/dist/src/ui/tui/tui-editor-entry.js +230 -0
  318. package/dist/src/ui/tui/tui-editor-interval.js +122 -0
  319. package/dist/src/ui/tui/tui-editor-notes.js +114 -0
  320. package/dist/src/ui/tui/tui-editor-pause.js +266 -0
  321. package/dist/src/ui/tui/tui-editor-prompt.js +95 -0
  322. package/dist/src/ui/tui/tui-editor-queued.js +98 -0
  323. package/dist/src/ui/tui/tui-editor-quiet.js +106 -0
  324. package/dist/src/ui/tui/tui-editor-retire.js +83 -0
  325. package/dist/src/ui/tui/tui-editor-search.js +73 -0
  326. package/dist/src/ui/tui/tui-editor-session.js +97 -0
  327. package/dist/src/ui/tui/tui-editors.js +152 -0
  328. package/dist/src/ui/tui/tui-frame.js +67 -55
  329. package/dist/src/ui/tui/tui-history.js +12 -7
  330. package/dist/src/ui/tui/tui-input.js +49 -44
  331. package/dist/src/ui/tui/tui-keymap.js +1 -0
  332. package/dist/src/ui/tui/tui-keys.js +91 -1704
  333. package/dist/src/ui/tui/tui-pane-activity.js +99 -0
  334. package/dist/src/ui/tui/tui-pane-backlog.js +224 -0
  335. package/dist/src/ui/tui/tui-pane-brief.js +30 -0
  336. package/dist/src/ui/tui/tui-pane-ctx.js +11 -0
  337. package/dist/src/ui/tui/tui-pane-health.js +124 -0
  338. package/dist/src/ui/tui/tui-pane-history.js +316 -0
  339. package/dist/src/ui/tui/tui-pane-pending.js +74 -0
  340. package/dist/src/ui/tui/tui-pane-queued.js +143 -0
  341. package/dist/src/ui/tui/tui-pane-report.js +122 -0
  342. package/dist/src/ui/tui/tui-pane-session.js +101 -0
  343. package/dist/src/ui/tui/tui-pane-transcript.js +150 -0
  344. package/dist/src/ui/tui/tui-pane.js +66 -28
  345. package/dist/src/ui/tui/tui-panes.js +294 -0
  346. package/dist/src/ui/tui/tui.js +45 -25
  347. package/dist/src/verdict/fix-claim.js +141 -38
  348. package/dist/src/verdict/no-change.js +19 -0
  349. package/dist/src/verdict/refusal.js +92 -8
  350. package/dist/src/verdict/reply-contract.js +17 -5
  351. package/dist/src/version.js +3 -2
  352. package/package.json +4 -2
  353. package/dist/src/agent/mcp/role-notes-server.js +0 -160
  354. package/dist/src/landing/backlog-conflicts.js +0 -116
  355. package/dist/src/landing/landing-drain.js +0 -204
  356. package/dist/src/landing/landing-pipeline.js +0 -96
  357. package/dist/src/landing/landing-queue-render.js +0 -31
  358. package/dist/src/landing/landing-slot.js +0 -246
  359. package/dist/src/landing/landing-vetting.js +0 -196
  360. package/dist/src/pi-extension/role-notes.js +0 -40
  361. package/dist/src/ui/fleet-alerts.js +0 -174
@@ -1,34 +1,24 @@
1
+ // vocabulary: plain
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import { loadConfigSafe } from "../config/config.js";
4
- import { configForRole, reviewConfig } from "../config/config-views.js";
5
+ import { seamsInUse } from "../config/config-fallbacks.js";
5
6
  import { findOnPath } from "../files/files.js";
6
7
  import { GIT_MISSING_MESSAGE } from "../git/git-run.js";
7
8
  import { branchesPhrase, branchExists, currentBranch, hasCommits, isGitRepo } from "../git/git.js";
8
9
  import { DETACHED_HEAD_MESSAGE, NOT_A_REPO_MESSAGE, NOT_INITIALIZED_MESSAGE, NO_COMMITS_MESSAGE, } from "./readiness.js";
9
10
  import { agentMissingMessage, findAgentBinary, resolveAgentBin } from "../pi/pi-bin.js";
10
11
  import { seedClaudeAccount } from "../agent/claude/claude-account.js";
11
- import { loopIds } from "../roles/loop-ids.js";
12
- /** The startup gate of `tumwater run` as one function: every precondition an orchestrator
13
- * generation checks before it starts. "Can a generation boot in this repo's current state?" has
14
- * three askers and they must get one answer: cmdRun (cli/cli-run.ts) fails fast on it at startup,
15
- * the self-redeploy (src/redeploy/redeployer.ts) asks it before it holds the fleet and again right
16
- * before its swap, and the supervisor (src/process/supervisor.ts) asks it to name why a generation
17
- * died. On 2026-09-22 only the first existed: a redeploy swapped onto a build whose child found
18
- * tumwater.json missing, exited "not initialized", and the supervisor exited with it — 4 h 44 m
19
- * of a dead fleet and no event (BUGS.md 2026-09-23). The operator-facing wording lives in
20
- * readiness.ts, shared with doctor's per-check report.
21
- *
22
- * The one startup check deliberately outside the gate is cmdRun's "an orchestrator is already
23
- * running": to a redeploy asking on behalf of its successor, the live orchestrator is itself —
24
- * gone by the time the successor boots. The gate is the ASKER's build's rule, so a redeploy checks
25
- * what the running build knows of startup; a precondition the new build adds is invisible to it
26
- * until that build runs. */
12
+ import { refreshOpencodeCatalog } from "../agent/opencode/opencode-catalog.js";
13
+ import { agentBackend } from "../agent/agent-backend.js";
14
+ // Register the built-in pi and claude adapters into the registry this module reads (see
15
+ // unregisteredBackendInUse) — importing run-agent.ts is the one place they register.
16
+ import "../agent/run-agent.js";
27
17
  /** The repo-level preconditions every repo-bound command shares (requireReadyRepo in
28
18
  * cli/cli-repo-gate.ts): git
29
19
  * on PATH, a repository, tumwater.json present, at least one commit. The first unmet one's
30
20
  * message, or null when the repo is ready. A missing tumwater.json is "not initialized" here,
31
- * never "use defaults": starting a fleet is the moment an operator's config must exist. */
21
+ * never "use defaults": starting a team is the moment an operator's config must exist. */
32
22
  export async function repoNotReady(root) {
33
23
  // Fail fast on a missing binary: without this, the probe below reads as "not a git
34
24
  // repository" — pointing at the wrong fix for a machine with no git installed.
@@ -49,13 +39,24 @@ export async function repoNotReady(root) {
49
39
  export async function runStartupCheck(root,
50
40
  /** The `--branch` flag of the invocation (null when absent) — the supervisor forwards it to
51
41
  * every generation, so every asker must pass the same one. */
52
- branchArg) {
42
+ branchArg,
43
+ /** The opencode-catalog seed's injectable parts — tests only; production callers omit it and
44
+ * the seed uses the real models.dev fetch (see OpenCodeSeedOptions). */
45
+ opencodeSeed = {}) {
53
46
  const notReady = await repoNotReady(root);
54
47
  if (notReady !== null)
55
48
  return { problem: notReady };
56
49
  const { config, error } = loadConfigSafe(root);
57
50
  if (config === undefined)
58
51
  return { problem: error };
52
+ // A backend an enabled seam routes to that this build has no registered adapter for cannot
53
+ // run its jobs: refuse to start rather than letting the run fall through to pi with a model
54
+ // id pi cannot serve (plans/opencode-backend.md part 2/7). Read the registry through
55
+ // run-agent.ts, whose module scope registers the built-in pi and claude adapters.
56
+ const unregistered = unregisteredBackendInUse(config);
57
+ if (unregistered !== undefined) {
58
+ return { problem: `backend ${unregistered} is configured but this build has no adapter for it` };
59
+ }
59
60
  // Fail fast instead of starting loops whose every tick dies with "spawn <bin> ENOENT". Every
60
61
  // enabled seam's agent — the top-level `agent` plus each enabled loop's resolved view and the
61
62
  // reviewer — resolves through the same resolveAgentBin the spawn uses (and doctor's pi check);
@@ -71,7 +72,7 @@ branchArg) {
71
72
  }
72
73
  // Seed the claude account state before the first run (plans/agent-backends.md part 6a):
73
74
  // `claude auth status` decides subscription vs API key, and an existing file is left alone.
74
- // Gated on a claude seam so a pi-only fleet spawns nothing, and attempted once per root per
75
+ // Gated on a claude seam so a pi-only team spawns nothing, and attempted once per root per
75
76
  // process: runStartupCheck is also the redeploy/supervisor poll's ask (runStartupProblem),
76
77
  // and a logged-out claude would otherwise spawn a bounded probe on every poll. If the seed
77
78
  // fails, the first claude run's observation fills the file in.
@@ -79,6 +80,22 @@ branchArg) {
79
80
  claudeSeedAttempted.add(root);
80
81
  seedClaudeAccount(root, config);
81
82
  }
83
+ // Seed the opencode models catalog (part 6b/7) before the first run: the poll surfaces price
84
+ // opencode seams from the cached `.tumwater/state/opencode-models.json`, and an absent cache
85
+ // reads every opencode seam NOT free (the safe direction for the budget gate). Mirroring the
86
+ // claude seed above, it runs once per root per process when a model job routes to opencode;
87
+ // a failed fetch keeps the last good cache (or an empty one) and never blocks startup.
88
+ if (!opencodeSeedAttempted.has(root) && agentsInUse(config).includes("opencode")) {
89
+ opencodeSeedAttempted.add(root);
90
+ await refreshOpencodeCatalog(root, {
91
+ providers: opencodeProviders(config),
92
+ // Probe the configured opencode binary (not a different one on PATH) for the version, so
93
+ // the freshness check compares against the binary the team actually runs.
94
+ cliBin: resolveAgentBin(config, "opencode").bin,
95
+ fetch: opencodeSeed.fetch,
96
+ now: opencodeSeed.now,
97
+ });
98
+ }
82
99
  const branch = await resolveMainBranch(root, config, branchArg);
83
100
  if ("problem" in branch)
84
101
  return branch;
@@ -88,17 +105,44 @@ branchArg) {
88
105
  * so the supervisor's and redeploy's repeated startup checks do not respawn `claude auth
89
106
  * status` on every poll when the probe fails. */
90
107
  const claudeSeedAttempted = new Set();
91
- /** Every agent backend an enabled seam resolves to: the top-level `agent` plus each enabled
92
- * loop's configForRole view and, when the review gate is on, the reviewer's view
93
- * (reviewConfig). One list the startup gate and doctor's binary check share, so a claude route
94
- * the harness would spawn is checked exactly like pi on both surfaces. */
108
+ /** Roots this process has already attempted an opencode-catalog seed for (see runStartupCheck),
109
+ * so the supervisor's and redeploy's repeated startup checks do not respawn the models.dev
110
+ * fetch on every poll when it fails. */
111
+ const opencodeSeedAttempted = new Set();
112
+ /** The models.dev providers the config routes through OpenCode beyond its own gateway, which
113
+ * the catalog parse (part 6a/7) keeps only when named here (finding 10's `opencode-go` and so
114
+ * on). A bare gateway seam (`opencode/<id>`) adds nothing — `opencode` is always kept. Each
115
+ * provider is the model id's segment before the first `/` — `opencode/anthropic/…` routes to
116
+ * models.dev's `anthropic` provider, so its catalog key is `anthropic/<id>` — read from the
117
+ * same seam enumeration the startup gate already sweeps for binaries. */
118
+ export function opencodeProviders(config) {
119
+ const providers = new Set();
120
+ for (const seam of seamsInUse(config)) {
121
+ if (seam.agent !== "opencode")
122
+ continue;
123
+ const m = seam.model;
124
+ if (m?.includes("/"))
125
+ providers.add(m.slice(0, m.indexOf("/")));
126
+ }
127
+ return [...providers];
128
+ }
129
+ /** Every agent backend an enabled seam resolves to — the distinct agents of the one
130
+ * seamsInUse list (startup-gate's consumer of it), so a claude or pi clause that exists only
131
+ * as a fallback, the resolver, or the director is checked exactly like a primary seam.
132
+ * One list the startup gate and doctor's binary check share, so a route the harness would
133
+ * spawn is checked on both surfaces. */
95
134
  export function agentsInUse(config) {
96
- const agents = new Set([config.agent ?? "pi"]);
97
- for (const id of loopIds(config))
98
- agents.add(configForRole(config, id).agent ?? "pi");
99
- if (config.review.enabled)
100
- agents.add(reviewConfig(config).agent ?? "pi");
101
- return [...agents];
135
+ return [...new Set(seamsInUse(config).map((s) => s.agent ?? "pi"))];
136
+ }
137
+ /** The first backend an enabled seam routes to that this build has no registered adapter for,
138
+ * or undefined when every seam's backend is registered. The built-in pi and claude adapters
139
+ * are registered by importing src/agent/run-agent.ts (see the import above); a seam backend
140
+ * that is not in the registry is one this build cannot run. Doctor's binary check asks the
141
+ * same question, so the startup gate and doctor cannot disagree about which backend a build
142
+ * can serve. After the opencode adapter lands (part 5/7) this stays the general rule for any
143
+ * future id. */
144
+ export function unregisteredBackendInUse(config) {
145
+ return agentsInUse(config).find((agent) => agentBackend(agent) === undefined);
102
146
  }
103
147
  /** runStartupCheck reduced to its verdict: the message a generation would fail on right now, or
104
148
  * null when one would boot — what the redeploy and the supervisor ask. */
@@ -106,7 +150,7 @@ export async function runStartupProblem(root, branchArg) {
106
150
  const check = await runStartupCheck(root, branchArg);
107
151
  return "problem" in check ? check.problem : null;
108
152
  }
109
- /** The branch the fleet targets: `--branch <name>` wins, then `baseBranch` in config, then
153
+ /** The branch the team targets: `--branch <name>` wins, then `baseBranch` in config, then
110
154
  * whatever the primary checkout has checked out — the branch-agnostic default. An explicit
111
155
  * value must exist: failing at startup with the branches that do exist beats failing at the
112
156
  * first `git worktree add`. */
@@ -1,17 +1,17 @@
1
1
  /** The error-streak circuit breaker (PLANS.md 2026-09-30): a role whose ticks keep failing
2
- * consecutively is warned at ERROR_STREAK_WARN (src/tick/tick-apply.ts) and named by the fleet-wide
3
- * storm alarms (src/fleet/error-storm.ts, src/fleet/failure-spread.ts), but both only talk — the
2
+ * consecutively is warned at ERROR_STREAK_WARN (src/tick/tick-apply.ts) and named by the team-wide
3
+ * storm alarms (src/team/error-storm.ts, src/team/failure-spread.ts), but both only talk — the
4
4
  * role keeps ticking on the error ladder's 600 s max backoff forever, burning a model slot and
5
5
  * spend on a loop that cannot succeed. Past ERROR_STREAK_BREAKER consecutive failed ticks this gate
6
6
  * pauses the role through the same per-role pause marker the operator's `tumwater pause --role
7
- * <id>` writes (src/fleet/fleet-state.ts's pauseRole — the marker, lock, and idempotence come
7
+ * <id>` writes (src/team/team-state.ts's pauseRole — the marker, lock, and idempotence come
8
8
  * free), so the scheduler's existing pausedRolesSet skip blocks new ticks with zero scheduler
9
9
  * changes. The director is NOT exempt: a failing director cannot process prompts anyway, and one
10
10
  * uniform rule needs no carve-out. `tumwater resume --role <id>` (or the dashboard's per-row
11
11
  * toggle) lifts it, as today.
12
12
  *
13
13
  * Shape, like every gate in the family (src/gates/gate-polls.ts): the pure trip bookkeeping lives
14
- * here so it is unit-testable without a fleet, and the module owns the only event emission — the
14
+ * here so it is unit-testable without a team, and the module owns the only event emission — the
15
15
  * orchestrator's poll owns only the wiring.
16
16
  *
17
17
  * Ack bookkeeping. The marker itself is the ack carrier: every poll, each role present in the
@@ -26,12 +26,13 @@
26
26
  * the ack: the next episode trips on its own fresh ERROR_STREAK_BREAKER failures.
27
27
  *
28
28
  * Accepted behavior, stated here and not fixed in this change: the dashboards' "failing tick after
29
- * tick" alert (src/ui/fleet-alerts.ts) reads consecutiveErrors regardless of pause, so it keeps
29
+ * tick" alert (src/ui/team-alerts.ts) reads consecutiveErrors regardless of pause, so it keeps
30
30
  * listing a breaker-paused role until the streak clears; the loop cell's paused badge explains why
31
31
  * it is not ticking, and the role_streak_paused event tells the operator why. */
32
32
  import { ERROR_STREAK_BREAKER } from "../tick/tick-apply.js";
33
- import { pauseRole } from "../fleet/fleet-state.js";
34
- import { logEventBestEffort } from "../events/events.js";
33
+ import { loopPaused } from "../roles/loop-ids.js";
34
+ import { pauseRole } from "../team/team-state.js";
35
+ import { logEventBestEffort, TUMWATER_SOURCE } from "../events/events.js";
35
36
  /** A fresh gate state: nothing acked, so a live streak at or past the breaker trips on the
36
37
  * first poll (the durable-cause case a restart after an operator resume relies on). */
37
38
  export function newStreakGateState() {
@@ -40,21 +41,22 @@ export function newStreakGateState() {
40
41
  /** Step the gate by one orchestrator poll. For each runner whose consecutive error streak
41
42
  * has reached ERROR_STREAK_BREAKER plus what its ack already excused, and whose role is not
42
43
  * in `pausedRoles`: write the per-role pause marker and log one `role_streak_paused` event
43
- * carrying the role, the streak, and the last error. Returns the roles this poll paused, so
44
- * the wiring can fold them into the poll's paused-roles view and the scheduler blocks them
45
- * on this very poll, not the next one.
44
+ * carrying the role, the streak, and the last error. Returns the pause keys this poll wrote
45
+ * (`pauseKey` maps a loop id to its marker key; instance 1 of a multi-instance role pauses as
46
+ * `<role>-1`), so the wiring can fold them into the poll's paused-roles view and the scheduler
47
+ * blocks them on this very poll, not the next one.
46
48
  *
47
49
  * Roles already paused are acked instead of tripped (the ack carrier is the marker itself,
48
50
  * per the module doc), a healthy streak clears its ack, and a streak below its bar leaves
49
51
  * the state untouched — so repeated polls while a breaker-paused role stays paused log
50
52
  * nothing more, and pauseRole's own idempotence backstops any race. */
51
- export function pollStreakGate(root, state, runners, pausedRoles) {
53
+ export function pollStreakGate(root, state, runners, pausedRoles, pauseKey = (r) => r) {
52
54
  const tripped = [];
53
55
  for (const { role, state: s } of runners) {
54
56
  const streak = s.consecutiveErrors ?? 0;
55
57
  // Ack while paused: the marker is the ack carrier. The streak is frozen while a role is
56
58
  // paused (no ticks run), so recording it here is exactly the level the resume excuses.
57
- if (pausedRoles.has(role)) {
59
+ if (loopPaused(pausedRoles, role)) {
58
60
  state.acked.set(role, streak);
59
61
  continue;
60
62
  }
@@ -71,15 +73,15 @@ export function pollStreakGate(root, state, runners, pausedRoles) {
71
73
  // ERROR_STREAK_BREAKER more failures from this level, whether or not any poll sees the
72
74
  // role paused in between (an operator resume racing the next poll must not re-trip).
73
75
  state.acked.set(role, streak);
74
- if (pauseRole(root, role)) {
76
+ if (pauseRole(root, pauseKey(role))) {
75
77
  logEventBestEffort(root, {
76
- loop: "harness",
78
+ source: TUMWATER_SOURCE,
77
79
  type: "role_streak_paused",
78
- role,
80
+ role: pauseKey(role),
79
81
  streak,
80
82
  ...(s.lastError ? { lastError: s.lastError } : {}),
81
83
  });
82
- tripped.push(role);
84
+ tripped.push(pauseKey(role));
83
85
  }
84
86
  }
85
87
  return tripped;
@@ -1,3 +1,4 @@
1
+ // vocabulary: plain
1
2
  import { truncate } from "../text/text.js";
2
3
  import { compactTokens } from "../text/format.js";
3
4
  import { labeledLine } from "../verdict/reply-contract.js";
@@ -12,6 +13,12 @@ import { labeledLine } from "../verdict/reply-contract.js";
12
13
  * bloat every commit subject. Truncated with an ellipsis — like the body fields below — rather
13
14
  * than silently cut mid-word, which would read as if the subject were complete. */
14
15
  const COMMIT_SUMMARY_MAX = 100;
16
+ /** The untruncated SUMMARY length when it exceeds COMMIT_SUMMARY_MAX (extractSummary would cut
17
+ * it); null when it fits or the reply has no SUMMARY line. */
18
+ export function summaryOverCap(finalText) {
19
+ const summary = labeledLine(finalText, "SUMMARY");
20
+ return summary !== null && summary.length > COMMIT_SUMMARY_MAX ? summary.length : null;
21
+ }
15
22
  /** Pull the SUMMARY: line out of a pi final reply; null when absent. Capped at
16
23
  * COMMIT_SUMMARY_MAX chars with an ellipsis (consistent with extractCommitBody's field cap). */
17
24
  export function extractSummary(finalText) {
@@ -21,11 +28,11 @@ export function extractSummary(finalText) {
21
28
  /** The subject for a changed tick whose reply — and whose follow-up request — carried no
22
29
  * SUMMARY line: named from what actually changed, so the log still says what the commit touched
23
30
  * instead of only which loop made it. Up to three repo-relative paths (worktree order), then a
24
- * count; capped like a real summary. Falls back to the bare "<role> tick N" only when nothing is
31
+ * count; capped like a real summary. Falls back to the bare "<role> run N" only when nothing is
25
32
  * known. */
26
33
  export function fallbackSummary(files, role, tick) {
27
34
  if (files.length === 0)
28
- return `${role} tick ${tick}`;
35
+ return `${role} run ${tick}`;
29
36
  const shown = files.slice(0, 3).join(", ");
30
37
  const rest = files.length > 3 ? ` and ${files.length - 3} more` : "";
31
38
  return truncate(`Update ${shown}${rest}`, COMMIT_SUMMARY_MAX);
@@ -75,11 +82,11 @@ export function formatCommitBody(body) {
75
82
  /** The harness-stamped trailer line of every tick commit — truth from the run's counters, not
76
83
  * model claims. `turns` sums this tick's pre-commit pi runs (main + transient retry); `peakCtx`
77
84
  * is their largest single-request context. A changed tick flagged high-friction (plans/
78
- * refusal-and-thrash.md) appends a sibling Friction line after the Tick line — minutes rounded,
85
+ * refusal-and-thrash.md) appends a sibling Friction line after the Run line — minutes rounded,
79
86
  * e.g. `Friction: high (41 turns / 62m)`; only changed ticks carry it, so the refusal path
80
- * never passes the argument and the Tick line's asserted format stays stable. */
87
+ * never passes the argument and the Run line's asserted format stays stable. */
81
88
  export function commitTrailer(role, tick, turns, peakCtx, highFrictionMinutes, revisionRound) {
82
- const base = `Tick: ${role} #${tick} · turns ${turns} · ctx ${compactTokens(peakCtx)}`;
89
+ const base = `Run: ${role} #${tick} · turns ${turns} · ctx ${compactTokens(peakCtx)}`;
83
90
  const friction = highFrictionMinutes === undefined
84
91
  ? ""
85
92
  : `\nFriction: high (${turns} turns / ${Math.round(highFrictionMinutes)}m)`;
@@ -28,7 +28,7 @@ const C_QUOTE_ESCAPES = {
28
28
  * Non-ASCII arrives one octal escape per UTF-8 byte, so the escapes are first collected into
29
29
  * a latin1 byte string and only then reassembled as UTF-8 (decoding each escape to a character
30
30
  * on its own yields mojibake — `héllo.md` would come back as `héllo.md`). Used by
31
- * conflictedFiles in landing-git.ts; changedFiles reads git's NUL-terminated `-z` format, which
31
+ * conflictedFiles in merge-git.ts; changedFiles reads git's NUL-terminated `-z` format, which
32
32
  * emits paths verbatim (no quoting), so it has no encoded path to decode. */
33
33
  export function unquotePorcelainPath(p) {
34
34
  if (!p.startsWith('"'))
@@ -66,9 +66,9 @@ export function unquotePorcelainPath(p) {
66
66
  }
67
67
  return Buffer.from(bytes, "latin1").toString("utf8");
68
68
  }
69
- /** Repo-relative paths of every change in the worktree — modified, untracked, and deleted,
70
- * parsed from `git status --porcelain -z` (paths only). The refusal path uses this to classify
71
- * what a refusing run left behind: markdown notes may land, everything else is discarded.
69
+ /** Repo-relative paths of every change in the worktree — modified, untracked, and deleted, parsed
70
+ * from `git status --porcelain -z` (paths only). The refusal path uses this to classify what a
71
+ * refusing run left behind: markdown notes may be kept, everything else is discarded.
72
72
  *
73
73
  * The `-z` format is what git recommends for machine parsing: records are NUL-terminated and
74
74
  * paths are emitted verbatim, never C-quoted, so a path with whitespace, a quote, a control
@@ -100,7 +100,7 @@ export async function changedFiles(wt) {
100
100
  return files;
101
101
  }
102
102
  /** Repo-relative paths changed between the branch's fork point from main and its HEAD —
103
- * everything a merge of this branch would land (the three-dot range diffs against the
103
+ * everything a merge of this branch would bring in (the three-dot range diffs against the
104
104
  * merge-base, so commits main gained during the tick are not included). */
105
105
  export async function aheadOfMainFiles(wt, mainBranch) {
106
106
  const out = await gitTry(wt, "diff", "--name-only", `${mainBranch}...HEAD`);
@@ -138,15 +138,15 @@ function splitDiffByFile(diff) {
138
138
  sections.push(cur.join("\n"));
139
139
  return sections;
140
140
  }
141
- /** The combined ahead-of-main diff — everything a merge of this branch would land. Capped:
142
- * over `maxBytes`, the result is a truncation note plus `--stat` and the largest files' full
143
- * diffs (an oversized diff is itself reviewable information, and the reviewer can read any
144
- * file in the worktree directly). The per-file sections are split out of the one full diff
145
- * already fetched — spawning a diff per file would re-diff the entire range once per file for
146
- * text we already hold in memory (measured ~0.5 s of redundant git work on a 530 KB / 39-file
147
- * tick). Section byte length ranks files at least as well as numstat's added+deleted: it is
148
- * exactly what the reviewer will see, and a binary file's short "Binary files differ" stub
149
- * naturally ranks below any real text change. */
141
+ /** The combined ahead-of-main diff — everything a merge of this branch would bring in. Capped: over
142
+ * `maxBytes`, the result is a truncation note plus `--stat` and the largest files' full diffs (an
143
+ * oversized diff is itself reviewable information, and the reviewer can read any file in the
144
+ * worktree directly). The per-file sections are split out of the one full diff already fetched —
145
+ * spawning a diff per file would re-diff the entire range once per file for text we already hold in
146
+ * memory (measured ~0.5 s of redundant git work on a 530 KB / 39-file tick). Section byte length
147
+ * ranks files at least as well as numstat's added+deleted: it is exactly what the reviewer will
148
+ * see, and a binary file's short "Binary files differ" stub naturally ranks below any real text
149
+ * change. */
150
150
  export async function aheadOfMainDiff(wt, mainBranch, maxBytes = 200_000) {
151
151
  const range = `${mainBranch}...HEAD`;
152
152
  const full = (await gitTry(wt, "diff", range)) ?? "";
@@ -157,8 +157,8 @@ export async function aheadOfMainDiff(wt, mainBranch, maxBytes = 200_000) {
157
157
  let out = `[diff truncated: the full ahead-of-main diff is ${full.length} bytes; ` +
158
158
  `showing --stat plus the largest files]\n\n` + ((await gitTry(wt, "diff", "--stat", range)) ?? "") + "\n";
159
159
  for (const d of ranked) {
160
- // Account for the surrounding newlines in the budget check so the output never exceeds
161
- // maxBytes even when a section lands exactly on the boundary.
160
+ // Account for the surrounding newlines in the budget check so the output never exceeds maxBytes
161
+ // even when a section ends exactly on the boundary.
162
162
  if (out.length + d.length + 2 > maxBytes)
163
163
  break;
164
164
  out += `\n${d}\n`;
@@ -8,12 +8,12 @@ import { realGitFromXcrun } from "./xcrun-git.js";
8
8
  import { EXEC_MAX_BUFFER, childEnv, releaseChildHandles, signalTree } from "../process/process.js";
9
9
  import { KILL_GRACE_MS, armGroupDeadline } from "../process/process-group.js";
10
10
  import { errorMessage } from "../text/text.js";
11
- /** The wall-clock bound on one git subprocess. Generous enough for a large rebase or diff on
12
- * a slow disk, but finite: a git wedged on a stuck filesystem or a dead helper otherwise
13
- * stalls its awaited landing/scheduling path with no bound at all. `runGit`'s optional
14
- * timeoutMs overrides it — tests drive the deadline down to exercise the timeout; production
15
- * callers need no override. The SIGTERM → SIGKILL escalation then runs for KILL_GRACE_MS, so
16
- * one call is bounded at timeoutMs + KILL_GRACE_MS whatever the child does. */
11
+ /** The wall-clock bound on one git subprocess. Generous enough for a large rebase or diff on a slow
12
+ * disk, but finite: a git wedged on a stuck filesystem or a dead helper otherwise stalls its
13
+ * awaited merge/scheduling path with no bound at all. `runGit`'s optional timeoutMs overrides it —
14
+ * tests drive the deadline down to exercise the timeout; production callers need no override. The
15
+ * SIGTERM → SIGKILL escalation then runs for KILL_GRACE_MS, so one call is bounded at timeoutMs +
16
+ * KILL_GRACE_MS whatever the child does. */
17
17
  export const GIT_TIMEOUT_MS = 600_000;
18
18
  /** Identity used for harness-authored commits so ticks work without global git config. */
19
19
  export const COMMIT_IDENT = [
@@ -50,7 +50,7 @@ let resolvedGit;
50
50
  /** Wall-clock bound on the one-time macOS `xcrun --find git` probe. Unlike a git command, the
51
51
  * probe is a synchronous spawnSync, so a wedged xcrun (an Xcode license prompt, a corrupt
52
52
  * developer directory) blocks the whole event loop — no timer or watchdog can run until it
53
- * returns. A short bound keeps that from freezing the fleet: on timeout the probe reads as
53
+ * returns. A short bound keeps that from freezing the team: on timeout the probe reads as
54
54
  * "no answer" and the harness spawns `git` by name, exactly as a machine without the stub
55
55
  * does. */
56
56
  const GIT_RESOLVE_TIMEOUT_MS = 10_000;
@@ -200,7 +200,7 @@ export function execGitBounded(args, opts) {
200
200
  return Object.assign(promise, { child });
201
201
  }
202
202
  /** Like git(), with extra environment variables (e.g. GIT_EDITOR for rebase --continue, which the
203
- * landing flow in landing-merge.ts needs so `rebase --continue` can never block on a commit-message
203
+ * merge flow in merge-to-main.ts needs so `rebase --continue` can never block on a commit-message
204
204
  * prompt; and the harness ident for rewritten committer identity). The subprocess is bounded by
205
205
  * GIT_TIMEOUT_MS plus the KILL_GRACE_MS escalation (an optional `timeoutMs`/`killGraceMs` override
206
206
  * both for tests), so a hung or signal-ignoring git fails loudly as a GitError instead of stalling