tumwater 0.2.0 → 0.3.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 (446) hide show
  1. package/README.md +27 -13
  2. package/dist/build-info.json +2 -2
  3. package/dist/src/agent/agent-args.js +8 -9
  4. package/dist/src/agent/agent-backend.js +8 -6
  5. package/dist/src/agent/backend-traits.js +42 -25
  6. package/dist/src/agent/claude/claude-account.js +71 -204
  7. package/dist/src/agent/claude/claude-args.js +9 -6
  8. package/dist/src/agent/claude/claude-backend.js +10 -10
  9. package/dist/src/agent/claude/claude-env.js +1 -1
  10. package/dist/src/agent/claude/claude-stream.js +4 -3
  11. package/dist/src/agent/claude/claude-write-guard.js +49 -0
  12. package/dist/src/agent/claude/write-guard-hook.js +13 -0
  13. package/dist/src/agent/codex/codex-account.js +119 -0
  14. package/dist/src/agent/codex/codex-args.js +181 -0
  15. package/dist/src/agent/codex/codex-backend.js +279 -0
  16. package/dist/src/agent/codex/codex-catalog.js +97 -0
  17. package/dist/src/agent/codex/codex-env.js +18 -0
  18. package/dist/src/agent/codex/codex-hook-trust.js +246 -0
  19. package/dist/src/agent/codex/codex-patch-paths.js +36 -0
  20. package/dist/src/agent/codex/codex-rollout.js +179 -0
  21. package/dist/src/agent/codex/codex-stream.js +402 -0
  22. package/dist/src/agent/codex/codex-write-guard.js +86 -0
  23. package/dist/src/agent/codex/write-guard-hook.js +12 -0
  24. package/dist/src/agent/image-input.js +29 -24
  25. package/dist/src/agent/notes-shim.js +11 -12
  26. package/dist/src/agent/opencode/opencode-args.js +0 -1
  27. package/dist/src/agent/opencode/opencode-backend.js +12 -9
  28. package/dist/src/agent/opencode/opencode-catalog.js +55 -29
  29. package/dist/src/agent/opencode/opencode-config.js +19 -14
  30. package/dist/src/agent/opencode/opencode-env.js +0 -1
  31. package/dist/src/agent/opencode/opencode-session-id.js +1 -2
  32. package/dist/src/agent/opencode/opencode-stream.js +1 -1
  33. package/dist/src/agent/opencode/write-guard-plugin/index.js +48 -0
  34. package/dist/src/agent/role-notes-write.js +5 -6
  35. package/dist/src/agent/run-agent.js +465 -448
  36. package/dist/src/agent/run-settle.js +214 -0
  37. package/dist/src/agent/session-ledger.js +86 -16
  38. package/dist/src/agent/subscription-account.js +220 -0
  39. package/dist/src/agent/write-guard.js +148 -0
  40. package/dist/src/backlog/backlog-archive.js +246 -55
  41. package/dist/src/backlog/backlog-cli-view.js +280 -0
  42. package/dist/src/backlog/backlog-cli.js +85 -274
  43. package/dist/src/backlog/backlog-commit.js +4 -5
  44. package/dist/src/backlog/backlog-eligibility.js +175 -242
  45. package/dist/src/backlog/backlog-index.js +149 -0
  46. package/dist/src/backlog/backlog-md.js +54 -6
  47. package/dist/src/backlog/backlog-parts.js +254 -0
  48. package/dist/src/backlog/backlog-release.js +117 -0
  49. package/dist/src/backlog/backlog-render.js +27 -0
  50. package/dist/src/backlog/backlog-structure.js +99 -156
  51. package/dist/src/backlog/backlog-write.js +40 -127
  52. package/dist/src/backlog/backlog.js +21 -6
  53. package/dist/src/backlog/question-answer.js +21 -15
  54. package/dist/src/baseline/main-baseline.js +89 -20
  55. package/dist/src/baseline/main-culprit.js +94 -0
  56. package/dist/src/baseline/main-guardrails.js +209 -0
  57. package/dist/src/baseline/main-red.js +139 -32
  58. package/dist/src/baseline/main-revert.js +133 -0
  59. package/dist/src/baseline/main-watch.js +184 -0
  60. package/dist/src/brief/brief-edit.js +9 -11
  61. package/dist/src/brief/brief.js +31 -51
  62. package/dist/src/budget/budget.js +30 -20
  63. package/dist/src/budget/fallback-breaker.js +26 -27
  64. package/dist/src/build/build-check-detect.js +23 -15
  65. package/dist/src/build/build-check-events.js +25 -6
  66. package/dist/src/build/build-check-report.js +49 -9
  67. package/dist/src/build/build-check-scoped.js +18 -11
  68. package/dist/src/build/build-check.js +2 -1
  69. package/dist/src/build/build-info.js +2 -3
  70. package/dist/src/build/build-stage.js +9 -14
  71. package/dist/src/build/dep-install.js +1 -2
  72. package/dist/src/change/change-data.js +123 -31
  73. package/dist/src/change/change-render.js +46 -5
  74. package/dist/src/cli/brief-command.js +3 -4
  75. package/dist/src/cli/cli-args.js +118 -33
  76. package/dist/src/cli/cli-command-args.js +46 -18
  77. package/dist/src/cli/cli-editor.js +2 -1
  78. package/dist/src/cli/cli-flag-specs.js +150 -45
  79. package/dist/src/cli/cli-init.js +51 -0
  80. package/dist/src/cli/cli-marker-commands.js +4 -4
  81. package/dist/src/cli/cli-query-commands.js +308 -590
  82. package/dist/src/cli/cli-repo-gate.js +11 -1
  83. package/dist/src/cli/cli-role-command.js +420 -0
  84. package/dist/src/cli/cli-start-summary.js +160 -0
  85. package/dist/src/cli/{cli-run.js → cli-start.js} +165 -237
  86. package/dist/src/cli/completion.js +149 -22
  87. package/dist/src/cli/config-commands.js +41 -18
  88. package/dist/src/cli/follow-view.js +75 -0
  89. package/dist/src/cli/help.js +189 -73
  90. package/dist/src/cli/log-commands.js +148 -82
  91. package/dist/src/cli/question-commands.js +205 -10
  92. package/dist/src/cli.js +106 -43
  93. package/dist/src/collections.js +26 -10
  94. package/dist/src/concurrency/check-permit.js +20 -3
  95. package/dist/src/concurrency/lock.js +17 -13
  96. package/dist/src/concurrency/provider-lease.js +44 -8
  97. package/dist/src/concurrency/semaphore.js +102 -26
  98. package/dist/src/config/config-aliases.js +0 -1
  99. package/dist/src/config/config-editable-keys.js +13 -1
  100. package/dist/src/config/config-fallbacks.js +93 -56
  101. package/dist/src/config/config-field-checks.js +40 -10
  102. package/dist/src/config/config-keys.js +30 -8
  103. package/dist/src/config/config-live.js +63 -24
  104. package/dist/src/config/config-request.js +137 -0
  105. package/dist/src/config/config-schema.js +31 -24
  106. package/dist/src/config/config-selector-checks.js +123 -0
  107. package/dist/src/config/config-validation-agents.js +80 -0
  108. package/dist/src/config/config-validation-model.js +116 -0
  109. package/dist/src/config/config-validation.js +141 -199
  110. package/dist/src/config/config-views.js +127 -53
  111. package/dist/src/config/config-write-core.js +135 -0
  112. package/dist/src/config/config-write.js +131 -264
  113. package/dist/src/config/config.js +48 -38
  114. package/dist/src/config/model-selector.js +34 -34
  115. package/dist/src/doctor/doctor-backlog-bugs.js +287 -0
  116. package/dist/src/doctor/doctor-backlog-plans.js +263 -0
  117. package/dist/src/doctor/doctor-backlog.js +100 -496
  118. package/dist/src/doctor/doctor-check-names.js +81 -0
  119. package/dist/src/doctor/doctor-checks.js +52 -579
  120. package/dist/src/doctor/doctor-claude-checks.js +145 -0
  121. package/dist/src/doctor/doctor-codex-checks.js +279 -0
  122. package/dist/src/doctor/doctor-contention-checks.js +380 -0
  123. package/dist/src/doctor/doctor-holds.js +82 -66
  124. package/dist/src/doctor/doctor-install.js +2 -1
  125. package/dist/src/doctor/doctor-model-checks.js +236 -402
  126. package/dist/src/doctor/doctor-notify.js +3 -4
  127. package/dist/src/doctor/doctor-opencode-checks.js +162 -0
  128. package/dist/src/doctor/doctor-orphans.js +182 -63
  129. package/dist/src/doctor/doctor-project-checks.js +303 -0
  130. package/dist/src/doctor/doctor.js +121 -77
  131. package/dist/src/doctor/image-probe.js +21 -8
  132. package/dist/src/doctor/outcome.js +3 -2
  133. package/dist/src/doctor/probe.js +7 -11
  134. package/dist/src/events/event-format.js +181 -86
  135. package/dist/src/events/event-labels.js +12 -5
  136. package/dist/src/events/event-legacy.js +39 -15
  137. package/dist/src/events/event-read.js +39 -39
  138. package/dist/src/events/event-tally.js +16 -0
  139. package/dist/src/events/event-window.js +60 -24
  140. package/dist/src/events/events.js +30 -13
  141. package/dist/src/events/notify.js +7 -7
  142. package/dist/src/failure/failure-cluster.js +12 -12
  143. package/dist/src/failure/failure-data.js +56 -56
  144. package/dist/src/failure/failure-render.js +31 -23
  145. package/dist/src/failure/failure-state-change.js +17 -12
  146. package/dist/src/failure/time-spend.js +99 -35
  147. package/dist/src/files/files.js +111 -35
  148. package/dist/src/files/json-files.js +3 -3
  149. package/dist/src/files/json-object.js +28 -7
  150. package/dist/src/files/stat-cache.js +2 -2
  151. package/dist/src/files/tail.js +1 -1
  152. package/dist/src/gates/bootstrap-gates.js +4 -5
  153. package/dist/src/gates/budget-gates.js +177 -84
  154. package/dist/src/gates/disk-gate.js +1 -1
  155. package/dist/src/gates/gate-polls.js +108 -58
  156. package/dist/src/gates/maintenance-quota.js +10 -13
  157. package/dist/src/gates/pause-gates.js +28 -10
  158. package/dist/src/gates/readiness.js +7 -3
  159. package/dist/src/gates/role-cap-gates.js +8 -8
  160. package/dist/src/gates/startup-gate.js +94 -32
  161. package/dist/src/gates/streak-gate.js +54 -30
  162. package/dist/src/git/commit-message.js +77 -46
  163. package/dist/src/git/git-diff.js +16 -10
  164. package/dist/src/git/git-run.js +79 -38
  165. package/dist/src/git/git.js +36 -34
  166. package/dist/src/git/slot-salvage.js +253 -0
  167. package/dist/src/git/slots-state.js +6 -6
  168. package/dist/src/git/worktree-pool.js +132 -38
  169. package/dist/src/git/worktree-use.js +4 -11
  170. package/dist/src/git/worktree.js +94 -37
  171. package/dist/src/gui/gui-admin-endpoints.js +96 -0
  172. package/dist/src/gui/gui-args.js +79 -8
  173. package/dist/src/gui/gui-backlog-commands.js +42 -18
  174. package/dist/src/gui/gui-backlog-endpoints.js +155 -0
  175. package/dist/src/gui/gui-command.js +8 -13
  176. package/dist/src/gui/gui-config-commands.js +94 -72
  177. package/dist/src/gui/gui-endpoint-commands.js +4 -3
  178. package/dist/src/gui/gui-endpoint-common.js +4 -4
  179. package/dist/src/gui/gui-endpoints.js +11 -380
  180. package/dist/src/gui/gui-history-endpoints.js +301 -0
  181. package/dist/src/gui/gui-operator-commands.js +108 -13
  182. package/dist/src/gui/gui-prompt-commands.js +11 -14
  183. package/dist/src/gui/gui-report-endpoints.js +90 -0
  184. package/dist/src/gui/gui-server.js +11 -4
  185. package/dist/src/gui/gui-team-commands.js +7 -7
  186. package/dist/src/gui/http-body.js +1 -1
  187. package/dist/src/history/history-data.js +122 -234
  188. package/dist/src/history/history-queued.js +147 -0
  189. package/dist/src/history/history-render.js +42 -22
  190. package/dist/src/history/history.js +193 -49
  191. package/dist/src/inbox/inbox-attachments.js +29 -30
  192. package/dist/src/inbox/inbox-cancel.js +10 -11
  193. package/dist/src/inbox/inbox-edit.js +9 -9
  194. package/dist/src/inbox/inbox-submit.js +18 -18
  195. package/dist/src/inbox/inbox-top.js +25 -9
  196. package/dist/src/inbox/inbox.js +42 -43
  197. package/dist/src/inbox/pending-prompt.js +26 -26
  198. package/dist/src/inbox/prompt-commands.js +62 -49
  199. package/dist/src/inbox/prompt-not-before.js +2 -2
  200. package/dist/src/init/init-templates.js +1 -2
  201. package/dist/src/init/init.js +28 -23
  202. package/dist/src/merge/backlog-conflicts.js +215 -35
  203. package/dist/src/merge/merge-batch.js +14 -8
  204. package/dist/src/merge/merge-cancel.js +53 -0
  205. package/dist/src/merge/merge-check-failures.js +44 -22
  206. package/dist/src/merge/merge-core.js +81 -32
  207. package/dist/src/merge/merge-diff.js +5 -4
  208. package/dist/src/merge/merge-drain.js +150 -11
  209. package/dist/src/merge/merge-git.js +177 -38
  210. package/dist/src/merge/merge-pipeline.js +15 -3
  211. package/dist/src/merge/merge-post-review.js +90 -0
  212. package/dist/src/merge/merge-queue-render.js +49 -11
  213. package/dist/src/merge/merge-queue.js +31 -15
  214. package/dist/src/merge/merge-requeue.js +102 -0
  215. package/dist/src/merge/merge-slot.js +61 -16
  216. package/dist/src/merge/merge-stack.js +33 -11
  217. package/dist/src/merge/merge-to-main.js +86 -27
  218. package/dist/src/merge/merge-top.js +69 -0
  219. package/dist/src/merge/merge-verify.js +12 -10
  220. package/dist/src/notes-cli.js +30 -15
  221. package/dist/src/operator/operator-commands.js +192 -81
  222. package/dist/src/operator/operator-intent.js +69 -42
  223. package/dist/src/operator/operator-requests.js +35 -40
  224. package/dist/src/operator/retire.js +5 -6
  225. package/dist/src/operator/revert.js +142 -34
  226. package/dist/src/orchestrator/orchestrator-launch.js +60 -52
  227. package/dist/src/orchestrator/orchestrator-poll.js +320 -0
  228. package/dist/src/orchestrator/orchestrator-scheduling.js +68 -369
  229. package/dist/src/orchestrator/orchestrator.js +128 -369
  230. package/dist/src/orchestrator/retention.js +42 -8
  231. package/dist/src/orchestrator/scheduling-admit.js +116 -0
  232. package/dist/src/orchestrator/scheduling-scope.js +201 -0
  233. package/dist/src/orchestrator/scheduling-skip.js +185 -0
  234. package/dist/src/orchestrator/startup-migration-steps.js +8 -7
  235. package/dist/src/orchestrator/startup-migrations.js +11 -7
  236. package/dist/src/paths.js +116 -49
  237. package/dist/src/pi/command-shape.js +12 -1
  238. package/dist/src/pi/pi-args.js +6 -4
  239. package/dist/src/pi/pi-backend.js +6 -6
  240. package/dist/src/pi/pi-bin.js +54 -63
  241. package/dist/src/pi/pi-listed-models.js +53 -0
  242. package/dist/src/pi/pi-models.js +63 -30
  243. package/dist/src/pi/pi-run-result.js +1 -1
  244. package/dist/src/pi/pi-settings.js +1 -1
  245. package/dist/src/pi/pi-stream.js +6 -6
  246. package/dist/src/pi/pi-watchdogs.js +18 -19
  247. package/dist/src/pi-extension/bounded-output.js +5 -3
  248. package/dist/src/pi-extension/context-budget.js +2 -2
  249. package/dist/src/pi-extension/context-shake.js +1 -1
  250. package/dist/src/pi-extension/context-window.js +0 -1
  251. package/dist/src/pi-extension/full-output.js +3 -10
  252. package/dist/src/pi-extension/strip-thinking.js +0 -1
  253. package/dist/src/pi-extension/trim-system-prompt.js +3 -4
  254. package/dist/src/pi-extension/write-guard.js +37 -0
  255. package/dist/src/process/launch-services.js +1 -2
  256. package/dist/src/process/node-bin.js +16 -0
  257. package/dist/src/process/process-group.js +8 -18
  258. package/dist/src/process/process.js +41 -2
  259. package/dist/src/process/run-marker.js +18 -6
  260. package/dist/src/process/supervisor.js +22 -21
  261. package/dist/src/prompt/dialect.js +17 -2
  262. package/dist/src/prompt/gate-notes.js +203 -0
  263. package/dist/src/prompt/gate-prompts.js +121 -211
  264. package/dist/src/prompt/notes-backlog.js +181 -0
  265. package/dist/src/prompt/principles.js +1 -2
  266. package/dist/src/prompt/prompt-followup.js +19 -14
  267. package/dist/src/prompt/prompt.js +129 -204
  268. package/dist/src/redeploy/redeploy-policy.js +24 -19
  269. package/dist/src/redeploy/redeploy-probes.js +1 -1
  270. package/dist/src/redeploy/redeploy.js +2 -3
  271. package/dist/src/redeploy/redeployer.js +20 -20
  272. package/dist/src/redeploy/self-reload.js +2 -1
  273. package/dist/src/report/report-data.js +161 -77
  274. package/dist/src/report/report-fold.js +129 -52
  275. package/dist/src/report/report-main-red.js +55 -0
  276. package/dist/src/report/report-render.js +133 -64
  277. package/dist/src/report/report-types.js +1 -0
  278. package/dist/src/report/report.js +26 -9
  279. package/dist/src/request-timeouts.js +2 -2
  280. package/dist/src/review/known-flakes.js +100 -1
  281. package/dist/src/review/post-merge-review.js +106 -0
  282. package/dist/src/review/protected-edits.js +4 -5
  283. package/dist/src/review/review-followup.js +8 -8
  284. package/dist/src/review/review-precheck.js +66 -23
  285. package/dist/src/review/review-run.js +395 -0
  286. package/dist/src/review/review-verdict.js +2 -2
  287. package/dist/src/review/review.js +155 -360
  288. package/dist/src/review/secret-leaks.js +36 -16
  289. package/dist/src/review/suite-rerun.js +0 -1
  290. package/dist/src/roles/legacy-role-migration.js +80 -7
  291. package/dist/src/roles/role-catalog.js +69 -12
  292. package/dist/src/roles/role-guidance.js +55 -20
  293. package/dist/src/roles/role-labels.js +1 -2
  294. package/dist/src/roles/role-render.js +67 -50
  295. package/dist/src/roles/role-view.js +59 -47
  296. package/dist/src/roles/roles.js +31 -31
  297. package/dist/src/roles/runner-ids.js +97 -0
  298. package/dist/src/run/acceptance-greps.js +119 -0
  299. package/dist/src/run/feedback-filings.js +51 -0
  300. package/dist/src/{tick → run}/qa-coverage.js +9 -27
  301. package/dist/src/{tick/tick-apply.js → run/run-apply.js} +95 -94
  302. package/dist/src/run/run-detail-data.js +179 -0
  303. package/dist/src/run/run-detail-render.js +98 -0
  304. package/dist/src/run/run-detail.js +168 -0
  305. package/dist/src/{tick/tick-finalize.js → run/run-finalize.js} +72 -60
  306. package/dist/src/{tick/tick-outcome.js → run/run-outcome.js} +6 -7
  307. package/dist/src/{tick/tick-prompt.js → run/run-prompt.js} +108 -73
  308. package/dist/src/{tick/tick-resume.js → run/run-resume.js} +55 -26
  309. package/dist/src/{tick/tick-stage.js → run/run-stage.js} +108 -50
  310. package/dist/src/{tick/tick-timing.js → run/run-timing.js} +43 -41
  311. package/dist/src/{tick/tick-usage.js → run/run-usage.js} +45 -37
  312. package/dist/src/{tick/tick-verdict.js → run/run-verdict.js} +91 -56
  313. package/dist/src/run/selfcheck-digest.js +40 -0
  314. package/dist/src/run/stage-backlog-checks.js +249 -0
  315. package/dist/src/run/stage-check.js +172 -0
  316. package/dist/src/run/stage-path-checks.js +730 -0
  317. package/dist/src/{loop → runner}/leftover.js +80 -25
  318. package/dist/src/{loop → runner}/model-fallback.js +12 -12
  319. package/dist/src/runner/revision.js +202 -0
  320. package/dist/src/{loop/loop-fallback.js → runner/runner-fallback.js} +8 -8
  321. package/dist/src/runner/runner-outcome.js +107 -0
  322. package/dist/src/{loop/loop-pi.js → runner/runner-pi.js} +140 -131
  323. package/dist/src/{loop/loop-recovery.js → runner/runner-recovery.js} +21 -15
  324. package/dist/src/{loop/loop-tick.js → runner/runner-run.js} +218 -240
  325. package/dist/src/{loop/loop-state.js → runner/runner-state-load.js} +61 -114
  326. package/dist/src/runner/runner-state.js +102 -0
  327. package/dist/src/{loop/loop.js → runner/runner.js} +123 -120
  328. package/dist/src/scheduling/backoff.js +38 -38
  329. package/dist/src/scheduling/claims.js +35 -22
  330. package/dist/src/scheduling/once-round.js +22 -22
  331. package/dist/src/scheduling/quiet-hours.js +5 -6
  332. package/dist/src/scheduling/scheduling.js +74 -64
  333. package/dist/src/scheduling/work-merged-cache.js +2 -2
  334. package/dist/src/status/status-budget.js +55 -47
  335. package/dist/src/status/status-data.js +43 -16
  336. package/dist/src/status/status-inbox.js +2 -2
  337. package/dist/src/status/status-install.js +0 -1
  338. package/dist/src/status/status-polls.js +28 -28
  339. package/dist/src/status/status-roles.js +39 -13
  340. package/dist/src/team/error-storm.js +8 -8
  341. package/dist/src/team/failure-spread.js +2 -2
  342. package/dist/src/team/orchestrator-info.js +15 -9
  343. package/dist/src/team/reclaim.js +5 -6
  344. package/dist/src/team/team-hold.js +7 -7
  345. package/dist/src/team/team-polls.js +91 -50
  346. package/dist/src/team/team-state.js +8 -2
  347. package/dist/src/text/datetime.js +63 -17
  348. package/dist/src/text/format.js +48 -11
  349. package/dist/src/text/markdown.js +8 -5
  350. package/dist/src/text/phrases.js +57 -23
  351. package/dist/src/text/suggest.js +1 -1
  352. package/dist/src/text/text.js +67 -13
  353. package/dist/src/ui/badges.js +65 -37
  354. package/dist/src/ui/gui/gui-client-backlog.js +292 -0
  355. package/dist/src/ui/gui/gui-client-boot.js +32 -26
  356. package/dist/src/ui/gui/gui-client-composer.js +8 -9
  357. package/dist/src/ui/gui/gui-client-drawer-config.js +212 -0
  358. package/dist/src/ui/gui/gui-client-drawer.js +126 -285
  359. package/dist/src/ui/gui/gui-client-feed.js +271 -0
  360. package/dist/src/ui/gui/gui-client-history.js +434 -67
  361. package/dist/src/ui/gui/gui-client-labels.js +1 -2
  362. package/dist/src/ui/gui/gui-client-markdown.js +1 -2
  363. package/dist/src/ui/gui/gui-client-model.js +27 -36
  364. package/dist/src/ui/gui/gui-client-operator.js +55 -51
  365. package/dist/src/ui/gui/gui-client-pending.js +227 -23
  366. package/dist/src/ui/gui/gui-client-report-chart.js +464 -0
  367. package/dist/src/ui/gui/gui-client-report.js +87 -427
  368. package/dist/src/ui/gui/{gui-client-loops.js → gui-client-roles.js} +43 -44
  369. package/dist/src/ui/gui/gui-client-settings.js +56 -4
  370. package/dist/src/ui/gui/gui-client-team.js +25 -465
  371. package/dist/src/ui/gui/gui-client.js +27 -25
  372. package/dist/src/ui/gui/gui-icons.js +0 -2
  373. package/dist/src/ui/gui/gui-page.js +9 -7
  374. package/dist/src/ui/gui/gui-styles.js +34 -34
  375. package/dist/src/ui/progress-data.js +9 -11
  376. package/dist/src/ui/{tick-progress-model.js → run-progress-model.js} +31 -31
  377. package/dist/src/ui/status-model.js +133 -125
  378. package/dist/src/ui/status-payload.js +136 -49
  379. package/dist/src/ui/status-render.js +101 -82
  380. package/dist/src/ui/team-alerts.js +248 -57
  381. package/dist/src/ui/tone.js +5 -6
  382. package/dist/src/ui/transcript-run.js +58 -0
  383. package/dist/src/ui/transcript-tail.js +28 -20
  384. package/dist/src/ui/transcript.js +63 -23
  385. package/dist/src/ui/tui/tui-app.js +0 -1
  386. package/dist/src/ui/tui/tui-backlog.js +51 -14
  387. package/dist/src/ui/tui/tui-editor-answer.js +27 -31
  388. package/dist/src/ui/tui/tui-editor-attach.js +3 -5
  389. package/dist/src/ui/tui/tui-editor-backends.js +132 -0
  390. package/dist/src/ui/tui/tui-editor-brief.js +10 -12
  391. package/dist/src/ui/tui/tui-editor-budget.js +35 -31
  392. package/dist/src/ui/tui/tui-editor-claude-reserve.js +24 -0
  393. package/dist/src/ui/tui/tui-editor-concurrency.js +24 -0
  394. package/dist/src/ui/tui/tui-editor-config.js +86 -0
  395. package/dist/src/ui/tui/tui-editor-entry.js +36 -47
  396. package/dist/src/ui/tui/tui-editor-fallback.js +31 -0
  397. package/dist/src/ui/tui/tui-editor-instances.js +37 -0
  398. package/dist/src/ui/tui/tui-editor-instructions.js +136 -0
  399. package/dist/src/ui/tui/tui-editor-interval.js +11 -9
  400. package/dist/src/ui/tui/tui-editor-model.js +29 -0
  401. package/dist/src/ui/tui/tui-editor-notes.js +3 -5
  402. package/dist/src/ui/tui/tui-editor-notify.js +25 -0
  403. package/dist/src/ui/tui/tui-editor-pause.js +48 -59
  404. package/dist/src/ui/tui/tui-editor-prompt.js +11 -16
  405. package/dist/src/ui/tui/tui-editor-provider-caps.js +27 -0
  406. package/dist/src/ui/tui/tui-editor-queued.js +5 -9
  407. package/dist/src/ui/tui/tui-editor-quiet.js +99 -35
  408. package/dist/src/ui/tui/tui-editor-retire.js +4 -6
  409. package/dist/src/ui/tui/tui-editor-role-key.js +76 -0
  410. package/dist/src/ui/tui/tui-editor-role-model.js +28 -0
  411. package/dist/src/ui/tui/tui-editor-search.js +45 -33
  412. package/dist/src/ui/tui/tui-editor-session.js +60 -34
  413. package/dist/src/ui/tui/tui-editor-slots.js +23 -0
  414. package/dist/src/ui/tui/tui-editors.js +35 -2
  415. package/dist/src/ui/tui/tui-frame.js +56 -11
  416. package/dist/src/ui/tui/tui-history.js +8 -9
  417. package/dist/src/ui/tui/tui-input.js +13 -11
  418. package/dist/src/ui/tui/tui-keymap.js +0 -1
  419. package/dist/src/ui/tui/tui-keys.js +24 -9
  420. package/dist/src/ui/tui/tui-pane-activity.js +14 -11
  421. package/dist/src/ui/tui/tui-pane-backlog.js +171 -126
  422. package/dist/src/ui/tui/tui-pane-brief.js +0 -1
  423. package/dist/src/ui/tui/tui-pane-ctx.js +2 -2
  424. package/dist/src/ui/tui/tui-pane-health.js +58 -8
  425. package/dist/src/ui/tui/tui-pane-history.js +402 -82
  426. package/dist/src/ui/tui/tui-pane-pending.js +308 -13
  427. package/dist/src/ui/tui/tui-pane-queued.js +71 -55
  428. package/dist/src/ui/tui/tui-pane-report.js +46 -14
  429. package/dist/src/ui/tui/tui-pane-session.js +25 -6
  430. package/dist/src/ui/tui/tui-pane-transcript.js +111 -37
  431. package/dist/src/ui/tui/tui-pane.js +80 -23
  432. package/dist/src/ui/tui/tui-panes.js +100 -30
  433. package/dist/src/ui/tui/tui.js +14 -14
  434. package/dist/src/verdict/fix-claim.js +82 -32
  435. package/dist/src/verdict/no-change.js +4 -4
  436. package/dist/src/verdict/refusal.js +40 -16
  437. package/dist/src/verdict/reply-contract.js +42 -31
  438. package/dist/src/version.js +0 -1
  439. package/package.json +2 -1
  440. package/dist/src/loop/revision.js +0 -70
  441. package/dist/src/roles/loop-ids.js +0 -77
  442. package/dist/src/tick/stage-check.js +0 -419
  443. package/dist/src/tick/telemetry-digest.js +0 -25
  444. package/dist/src/tick/tick-detail-data.js +0 -108
  445. package/dist/src/tick/tick-detail.js +0 -163
  446. package/dist/src/ui/gui/gui-client-sound.js +0 -53
@@ -1,20 +1,18 @@
1
- // vocabulary: plain
2
- import fs from "node:fs";
3
1
  import path from "node:path";
4
- import { ensureParentDir, readTextIfExists, writeTextAtomic } from "../files/files.js";
2
+ import { dirEntryNames, ensureParentDir, readTextIfExists, writeTextAtomic } from "../files/files.js";
5
3
  import { listQueueFiles, queueFileName, queueFileStamp, removeQueueFile } from "../files/file-queue.js";
6
4
  import { cachedByStat } from "../files/stat-cache.js";
7
5
  import { roleInboxDir } from "../paths.js";
8
6
  import { DIRECTOR_ROLE } from "../roles/roles.js";
9
7
  import { knownRoleIdsCached } from "../config/config.js";
10
- import { humanSeconds, secondsSince, secondsUntil } from "../text/datetime.js";
8
+ import { humanAgo, humanSeconds, secondsUntil } from "../text/datetime.js";
11
9
  import { errorMessage, truncate } from "../text/text.js";
12
10
  import { warnEvent } from "../events/events.js";
13
11
  import { isPromptImageSibling } from "./inbox-attachments.js";
14
12
  /** File-based queues of user prompts. Any process can enqueue; the orchestrator pops. Ordering
15
13
  * comes from the timestamped filenames. The director's queue is the historical one at the inbox
16
- * root; every other loop has its own subdirectory (roleInboxDir), so `tumwater prompt --role <id>`
17
- * queues a request only that loop's next tick sees.
14
+ * root; every other role has its own subdirectory (roleInboxDir), so `tumwater prompt --role <id>`
15
+ * queues a request only that role's next run sees.
18
16
  *
19
17
  * This module is the store: enqueueing, listing, peeking, and dequeuing, plus the shared
20
18
  * takeQueuedFile race policy. The cancel half — position-, list-, and file-addressed removal
@@ -41,14 +39,14 @@ export function promptPreview(text) {
41
39
  return truncate(stripNotBeforeMarker(text), PROMPT_PREVIEW_MAX);
42
40
  }
43
41
  let seq = 0;
44
- /** Append a prompt to a loop's queue as one timestamped file (creating the queue dir if needed)
42
+ /** Append a prompt to a role's queue as one timestamped file (creating the queue dir if needed)
45
43
  * and return its path. The filename orders prompts across processes by wall-clock time; the
46
44
  * per-process counter and pid break ties within one process. No event is logged —
47
45
  * inbox-submit.ts's submitPrompt and submitRolePrompt are the user-facing wrappers that add the
48
46
  * prompt_enqueued line, and PendingPrompt's re-queue of an unfulfilled prompt calls this directly.
49
47
  * The write is atomic (writeTextAtomic) because the queue's readers — the dashboards' 1 s poll,
50
- * `tumwater prompt --list`, and the dequeuing loop — run in other processes, and a read that
51
- * raced a plain writeFileSync could see a truncated prompt and run a tick on a half user request.
48
+ * `tumwater prompt --list`, and the dequeuing role — run in other processes, and a read that
49
+ * raced a plain writeFileSync could see a truncated prompt and run a run on a half user request.
52
50
  * The optional decorate hook runs before that one write with the file's path and may return the
53
51
  * final text instead — submitPromptWithImages uses it to save the prompt's images beside the
54
52
  * queue file and append their reference lines, so the queue file is born complete and no
@@ -69,15 +67,15 @@ export function enqueueRolePrompt(root, role, prompt, notBeforeMs, decorate) {
69
67
  writeTextAtomic(file, text);
70
68
  return file;
71
69
  }
72
- /** Every queued prompt file for one loop as a path joined onto the loop's inbox dir, oldest
73
- * first (listQueueFiles over the loop's inbox dir, .md entries only). Prompts still deferred by
70
+ /** Every queued prompt file for one role as a path joined onto the role's inbox dir, oldest
71
+ * first (listQueueFiles over the role's inbox dir, .md entries only). Prompts still deferred by
74
72
  * a not-before marker are included — deliverability filtering is the callers' job
75
73
  * (deliverablePredicate, deliverablePromptCount) — and a missing inbox dir reads as an empty
76
74
  * queue. */
77
75
  export function queuedFiles(root, role) {
78
76
  return listQueueFiles(roleInboxDir(root, role), ".md");
79
77
  }
80
- /** Resolve the 1-based position `tumwater prompt --list`'s per-loop numbering shows into one
78
+ /** Resolve the 1-based position `tumwater prompt --list`'s per-role numbering shows into one
81
79
  * queue file — the shared range-check-and-pick half of cancelRolePrompt (inbox-cancel.ts)
82
80
  * and editRolePrompt (inbox-edit.ts), so the two cannot drift on the error or the numbering.
83
81
  * Throws for out-of-range positions with no side effects. The undefined-pick check folds into
@@ -94,12 +92,12 @@ export function queuedFileAtPosition(root, role, position) {
94
92
  }
95
93
  return file;
96
94
  }
97
- /** Number of prompts currently queued for one loop and deliverable now — a directory listing
95
+ /** Number of prompts currently queued for one role and deliverable now — a directory listing
98
96
  * plus, per file, one stat-cached content read (the prompt cache below; an unchanged file
99
- * costs one stat). Defaults to the director's queue; a role argument counts that loop's own
100
- * per-role queue (scheduling passes it so a queued prompt makes its loop due by itself).
97
+ * costs one stat). Defaults to the director's queue; a role argument counts that role's own
98
+ * per-role queue (scheduling passes it so a queued prompt makes its role due by itself).
101
99
  * A prompt deferred by the not-before marker (its time still in the future) stays excluded,
102
- * so a deferred prompt alone never makes its loop due; once due, the marker falls out of the
100
+ * so a deferred prompt alone never makes its role due; once due, the marker falls out of the
103
101
  * count naturally. A missing inbox dir reads as 0, like queuedPrompts and dequeuePrompt. */
104
102
  export function inboxSize(root, role = DIRECTOR_ROLE) {
105
103
  return deliverablePromptCount(root, role);
@@ -132,7 +130,7 @@ const promptCache = new Map();
132
130
  function cachedPromptText(file) {
133
131
  return cachedByStat(promptCache, file, file, () => readTextIfExists(file), (t) => t);
134
132
  }
135
- /** The one read pass over a loop's queue that serves every list-shaped consumer: each queued
133
+ /** The one read pass over a role's queue that serves every list-shaped consumer: each queued
136
134
  * file paired with its basename, full text, and the enqueue stamp parsed from the filename
137
135
  * (queueFileStamp; null for a hand-placed name). Same listing order and race policy as
138
136
  * queuedRolePrompts (a file that vanishes mid-listing is skipped, not thrown), and the same
@@ -153,10 +151,10 @@ export function queuedRolePromptRecords(root, role) {
153
151
  }
154
152
  return out;
155
153
  }
156
- /** Full text of every prompt queued for one loop, in execution order (oldest first) — the same
154
+ /** Full text of every prompt queued for one role, in execution order (oldest first) — the same
157
155
  * filename sort dequeueRolePrompt pops by. A not-yet-deliverable prompt (the not-before marker
158
156
  * still in the future) is not part of the execution order: it is skipped here, so peek and
159
- * dequeue can never hand a tick a prompt its time has not reached. A missing queue directory
157
+ * dequeue can never hand a run a prompt its time has not reached. A missing queue directory
160
158
  * reads as an empty queue, like inboxSize and dequeueRolePrompt; a file that vanishes between
161
159
  * listing and reading (a concurrent dequeue or cancel) is skipped rather than throwing, so a
162
160
  * polled snapshot can never crash on it. Unchanged files are served from the stat-keyed cache
@@ -168,7 +166,7 @@ export function queuedRolePrompts(root, role) {
168
166
  .filter((e) => deliverableAt(e.notBeforeMs, now))
169
167
  .map((e) => e.text);
170
168
  }
171
- /** Every queued prompt of one loop with the queue-file basename that addresses it and its
169
+ /** Every queued prompt of one role with the queue-file basename that addresses it and its
172
170
  * enqueue stamp, in execution order — the snapshot's cancel-addressable payload
173
171
  * (StatusSnapshot.inboxFiles and roleInboxPrompts). Same pass, order, race policy, and stat
174
172
  * cache as queuedRolePrompts. */
@@ -180,14 +178,14 @@ export function queuedRolePromptEntries(root, role) {
180
178
  notBeforeMs: e.notBeforeMs,
181
179
  }));
182
180
  }
183
- /** The loop order a list-wide position (`--cancel`/`--edit` with no `--role`) resolves across:
184
- * the director first, then the remaining cached catalog ids — the per-loop sections `prompt
181
+ /** The role order a list-wide position (`--cancel`/`--edit` with no `--role`) resolves across:
182
+ * the director first, then the remaining cached catalog ids — the per-role sections `prompt
185
183
  * --list` and the TUI Queued pane print, each numbered from 1. The single home of that scope,
186
184
  * shared by the cancel and edit branches so neither can drift from what the list showed. */
187
185
  export function listWideScope(root) {
188
186
  return [DIRECTOR_ROLE, ...knownRoleIdsCached(root).filter((r) => r !== DIRECTOR_ROLE)];
189
187
  }
190
- /** One traversal of the queues behind the list-shaped queue views: with `role`, that loop's
188
+ /** One traversal of the queues behind the list-shaped queue views: with `role`, that role's
191
189
  * queue alone; otherwise the director first (its queue is the shared pre-1/2 inbox), then the
192
190
  * remaining catalog ids in order, empty queues skipped — exactly the sections the prose
193
191
  * prints. */
@@ -195,7 +193,7 @@ export function queuedListRows(root, role, validIds) {
195
193
  const prompts = [];
196
194
  const record = (r, position, e) =>
197
195
  // The marker is stripped from the text both shapes print (stripNotBeforeMarker): the
198
- // prose and --json are the operator's view of what a loop will tick, and the marker is
196
+ // prose and --json are the operator's view of what a role will run, and the marker is
199
197
  // plumbing, not content. Full verbatim prompt text minus plumbing, still not a preview.
200
198
  prompts.push({ role: r, position, file: e.file, text: stripNotBeforeMarker(e.text), queuedAtMs: e.queuedAtMs, notBeforeMs: e.notBeforeMs });
201
199
  if (role !== null) {
@@ -224,11 +222,19 @@ function queuedAgeSuffix(queuedAtMs, notBeforeMs, now) {
224
222
  }
225
223
  if (queuedAtMs === null)
226
224
  return "";
227
- const ageSeconds = secondsSince(queuedAtMs, now);
228
- return ` (queued ${humanSeconds(ageSeconds)} ago)`;
225
+ return ` (queued ${humanAgo(queuedAtMs, now)})`;
226
+ }
227
+ /** Keep the rows whose prompt text contains `grep`, case-insensitively, each row still carrying
228
+ * its unfiltered per-role `position`. A null grep keeps every row. The one filter `prompt --list
229
+ * --grep` and the TUI Inbox pane's `/` search share. */
230
+ export function queuedRowsMatching(rows, grep) {
231
+ if (grep === null)
232
+ return [...rows];
233
+ const needle = grep.toLowerCase();
234
+ return rows.filter((row) => row.text.toLowerCase().includes(needle));
229
235
  }
230
236
  /** Render the list-shaped queue view as the prose `prompt --list` prints and the TUI Queued
231
- * pane shows: consecutive rows grouped by role, one `<role>:` section per loop holding
237
+ * pane shows: consecutive rows grouped by role, one `<role>:` section per role holding
232
238
  * `"<position>. <text><queuedAgeSuffix>"` lines, sections joined by `\n`. Empty rows render
233
239
  * the empty string, so each surface keeps its own empty-state note. One renderer so the CLI
234
240
  * and the TUI cannot drift on order, numbering, or the age/countdown wording. */
@@ -249,7 +255,7 @@ export function renderQueuedList(rows, now) {
249
255
  sections.push(`${currentRole}:\n${lines.join("\n")}`);
250
256
  return sections.join("\n");
251
257
  }
252
- /** How many prompts are queued for one loop and deliverable now, without re-reading unchanged
258
+ /** How many prompts are queued for one role and deliverable now, without re-reading unchanged
253
259
  * contents — the snapshot's per-role counts poll every role
254
260
  * every second, so the count stays a listing plus one stat-cached read per file (the prompt
255
261
  * cache above keeps an unchanged file at one stat). A deferred prompt (its not-before time
@@ -283,9 +289,9 @@ export function takeQueuedFile(file) {
283
289
  * by a hyphen (`a-notes.md` beside `a.md`), and deleting it would take another prompt with
284
290
  * this one — files like that are left alone. ENOENT-tolerant through removeQueueFile, and a
285
291
  * queue directory that is already gone leaves nothing to clean. Called by the cancel paths
286
- * (inbox-cancel.ts's takeCancelledPrompt) and by a fulfilled tick's settle sweep
292
+ * (inbox-cancel.ts's takeCancelledPrompt) and by a fulfilled run's settle sweep
287
293
  * (src/inbox/pending-prompt.ts's settleImages): a cancelled or consumed prompt takes its
288
- * attachments with it. A DEQUEUE does not call this — the tick's agent still reads the
294
+ * attachments with it. A DEQUEUE does not call this — the run's agent still reads the
289
295
  * referenced files, so they must survive until the prompt is fulfilled or cancelled, and a
290
296
  * requeue first moves them to the new queue file's stem (movePromptImages) so this sweep
291
297
  * finds them under the stem the requeued file actually names.
@@ -296,14 +302,7 @@ export function takeQueuedFile(file) {
296
302
  export function removeSameStemSiblings(root, role, file) {
297
303
  const dir = path.dirname(file);
298
304
  const stem = path.basename(file, ".md");
299
- let entries;
300
- try {
301
- entries = fs.readdirSync(dir);
302
- }
303
- catch {
304
- return; // The queue directory itself is gone — nothing to clean.
305
- }
306
- for (const entry of entries) {
305
+ for (const entry of dirEntryNames(dir)) {
307
306
  if (entry === path.basename(file) || !isPromptImageSibling(stem, entry))
308
307
  continue;
309
308
  try {
@@ -324,11 +323,11 @@ export function removeSameStemSiblings(root, role, file) {
324
323
  /** Remove and return the oldest queued prompt, or null when empty — including when a
325
324
  * concurrent `tumwater prompt --cancel` removes it between listing and reading (or between
326
325
  * reading and removal): the module's race policy is that a vanished file is skipped rather
327
- * than throwing, so the director sees an empty inbox and skips its tick instead of failing
326
+ * than throwing, so the director sees an empty inbox and skips its run instead of failing
328
327
  * with a raw ENOENT. When the removal itself hits ENOENT the cancel won after our read —
329
328
  * the prompt was cancelled, so it must not be executed: null (skip), never the text we
330
329
  * already read. Non-ENOENT errors (e.g. EACCES) are rethrown — they are not a race with a
331
- * cancel. A caller that must clean the prompt's attachments afterwards (a tick's
330
+ * cancel. A caller that must clean the prompt's attachments afterwards (a run's
332
331
  * pending-prompt bookkeeping) needs the file's stem too, so dequeueRolePromptEntry also
333
332
  * returns the queue file it took. */
334
333
  export function dequeueRolePromptEntry(root, role) {
@@ -338,15 +337,15 @@ export function dequeueRolePromptEntry(root, role) {
338
337
  const text = takeQueuedFile(oldest);
339
338
  return text === null ? null : { text, file: oldest };
340
339
  }
341
- /** Remove and return the oldest prompt queued for one loop; see dequeueRolePromptEntry. */
340
+ /** Remove and return the oldest prompt queued for one role; see dequeueRolePromptEntry. */
342
341
  export function dequeueRolePrompt(root, role) {
343
342
  return dequeueRolePromptEntry(root, role)?.text ?? null;
344
343
  }
345
- /** Full text of the oldest prompt queued for one loop, read WITHOUT consuming it — the
344
+ /** Full text of the oldest prompt queued for one role, read WITHOUT consuming it — the
346
345
  * preview seam behind `tumwater role <id>`'s next-prompt view. Same reader, listing order,
347
346
  * and race policy as queuedRolePrompts (a file that vanishes mid-listing is skipped, not
348
347
  * thrown), but the queue file is never unlinked: a preview can never cost a queued prompt
349
- * its tick, which is the property test/tick-prompt.test.ts pins through the preview seam.
348
+ * its run, which is the property test/run-prompt.test.ts pins through the preview seam.
350
349
  * A missing queue directory reads as null, like dequeueRolePrompt. */
351
350
  export function peekRolePrompt(root, role) {
352
351
  return queuedRolePrompts(root, role)[0] ?? null;
@@ -3,31 +3,31 @@ import { movePromptImages, stripVanishedImageReferences } from "./inbox-attachme
3
3
  import { DIRECTOR_ROLE } from "../roles/roles.js";
4
4
  import { warnEventBestEffort } from "../events/events.js";
5
5
  /**
6
- * The raw user prompt a director tick is executing, and the requeue policy for every outcome
7
- * that leaves the request unfulfilled — extracted from LoopRunner's private methods
8
- * (src/loop/loop.ts) so the subtle fresh-vs-resume requeue semantics have one named home beside
6
+ * The raw user prompt a director run is executing, and the requeue policy for every outcome
7
+ * that leaves the request unfulfilled — extracted from RoleRunner's private methods
8
+ * (src/runner/runner.ts) so the subtle fresh-vs-resume requeue semantics have one named home beside
9
9
  * the queue mechanics they ride on (src/inbox/inbox.ts).
10
10
  */
11
11
  export class PendingPrompt {
12
12
  root;
13
13
  role;
14
14
  /** The dequeued request, memory-only: the queue file is the durable store, and every
15
- * unfulfilled outcome hands the request back to it before the tick ends. */
15
+ * unfulfilled outcome hands the request back to it before the run ends. */
16
16
  value = null;
17
- /** The queue file the recorded request was dequeued from, so a fulfilled tick sweeps the
17
+ /** The queue file the recorded request was dequeued from, so a fulfilled run sweeps the
18
18
  * request's same-stem image attachments by that file's stem (settleImages). Null when the
19
19
  * request was recorded without one (tests) or carried no file. */
20
20
  queueFile = null;
21
21
  /** Whether the current request's images were handed back to a queue (requeue*), so a
22
- * settle must keep them for the next tick instead of removing them. */
22
+ * settle must keep them for the next run instead of removing them. */
23
23
  retain = false;
24
24
  constructor(root, role) {
25
25
  this.root = root;
26
26
  this.role = role;
27
27
  }
28
- /** Record the user request a just-dequeued tick prompt carries (assembleTickPrompt's
28
+ /** Record the user request a just-dequeued run prompt carries (assembleRunPrompt's
29
29
  * userPrompt) together with the queue file it came from (userPromptFile), so an unfulfilled
30
- * tick can re-queue it instead of losing the request and a fulfilled one can clean its
30
+ * run can re-queue it instead of losing the request and a fulfilled one can clean its
31
31
  * attachments. */
32
32
  record(userPrompt, queueFile = null) {
33
33
  if (userPrompt === null)
@@ -36,23 +36,23 @@ export class PendingPrompt {
36
36
  this.queueFile = queueFile;
37
37
  this.retain = false;
38
38
  }
39
- /** The raw user prompt this tick is executing (null for role loops), so an unfulfilled
39
+ /** The raw user prompt this run is executing (null for roles), so an unfulfilled
40
40
  * outcome below can re-queue it. */
41
41
  get() {
42
42
  return this.value;
43
43
  }
44
44
  /** Drop the recorded request without re-queueing it — the explicit-stop arm of
45
- * finishAbortedTick and every fulfilled path. Leaves the image files for settleImages:
45
+ * finishAbortedRun and every fulfilled path. Leaves the image files for settleImages:
46
46
  * the same clear runs before the requeue branches, whose requeue* methods mark the images
47
47
  * retained, so only a genuinely unrequeued request loses them. */
48
48
  clear() {
49
49
  this.value = null;
50
50
  }
51
- /** The end-of-tick half of the attachment lifetime: sweep the fulfilled request's same-stem
51
+ /** The end-of-run half of the attachment lifetime: sweep the fulfilled request's same-stem
52
52
  * image files (removeSameStemSiblings, keyed on the dequeued file's stem — never on paths
53
53
  * named by prompt text) UNLESS an unfulfilled outcome handed the request back to a queue
54
54
  * (retain), then the files must survive for the requeued prompt to read. Always forgets the
55
- * request afterwards, so a fresh tick starts clean. */
55
+ * request afterwards, so a fresh run starts clean. */
56
56
  settleImages() {
57
57
  if (!this.retain && this.queueFile !== null)
58
58
  removeSameStemSiblings(this.root, this.role, this.queueFile);
@@ -60,17 +60,17 @@ export class PendingPrompt {
60
60
  this.retain = false;
61
61
  this.value = null;
62
62
  }
63
- /** Put an unfulfilled user prompt back in the queue it came from so the next tick retries it
63
+ /** Put an unfulfilled user prompt back in the queue it came from so the next run retries it
64
64
  * — the one place that policy lives, shared by every outcome that leaves the request undone
65
65
  * (abort, timeout, failure without changes, review abort, context-ceiling cut-off, red-main
66
66
  * gate). The queue is the role's own (the director's historical inbox for the director), so a
67
- * re-queued per-role request never leaks across loops. A fulfilled no_change never reaches
67
+ * re-queued per-role request never leaks across roles. A fulfilled no_change never reaches
68
68
  * here: re-queueing it would loop the prompt forever. Image attachments ride along: the
69
69
  * re-queue moves them to the new queue file's stem so a later cancel or fulfilling sweep
70
70
  * finds them, and a reference whose file is genuinely gone (removed out of band) is dropped
71
71
  * and replaced by one note naming the loss — a re-queued prompt must never send the next
72
- * tick's agent after files that are no longer there. Either way the images are marked
73
- * retained, so settleImages keeps them for the next tick. */
72
+ * run's agent after files that are no longer there. Either way the images are marked
73
+ * retained, so settleImages keeps them for the next run. */
74
74
  requeueUnfulfilled(userPrompt) {
75
75
  if (!userPrompt)
76
76
  return;
@@ -79,21 +79,21 @@ export class PendingPrompt {
79
79
  }
80
80
  /** Re-queue whatever request is still recorded and drop it from memory: an exception between
81
81
  * the dequeue/reclaim and the pi run leaves the request only in this field — memory the
82
- * failed tick is about to drop, with no outcome handler left to re-queue it (the handlers
83
- * run inside runTick, after the pi run). The queue is the durable store, so the catch
82
+ * failed run is about to drop, with no outcome handler left to re-queue it (the handlers
83
+ * run inside runOnce, after the pi run). The queue is the durable store, so the catch
84
84
  * re-queues whatever is still pending, like every unfulfilled outcome does; it is always
85
85
  * null once a pi run has been accounted for. */
86
86
  requeuePendingUnfulfilled() {
87
87
  this.requeueUnfulfilled(this.value);
88
88
  this.value = null;
89
89
  }
90
- /** Re-queue an unfulfilled prompt whose pi session the next tick will resume: the resumed
90
+ /** Re-queue an unfulfilled prompt whose pi session the next run will resume: the resumed
91
91
  * session still owns the request in its (compacted) context, so the re-queued copy is only
92
92
  * the durable store for a restart — the resume must reclaim exactly it as its own user
93
93
  * prompt (the resume's fulfillment consumes it; only its failure paths re-queue it) instead
94
- * of leaving it queued for a later fresh tick to run the same request twice. The queue file
94
+ * of leaving it queued for a later fresh run to run the same request twice. The queue file
95
95
  * is recorded so the reclaim takes that exact prompt whatever else was enqueued meanwhile.
96
- * Director ticks never resume — their re-queued prompt always reruns fresh — so they take
96
+ * Director runs never resume — their re-queued prompt always reruns fresh — so they take
97
97
  * the plain path. */
98
98
  requeueForResume(state, userPrompt) {
99
99
  if (!userPrompt)
@@ -105,13 +105,13 @@ export class PendingPrompt {
105
105
  state.resumePromptFile = this.enqueueCarryingImages(userPrompt);
106
106
  this.retain = true;
107
107
  }
108
- /** Reclaim the prompt the interrupted tick re-queued (requeueForResume): the resumed session
109
- * still owns that request in its context, so this tick's outcome bookkeeping — re-queue on
108
+ /** Reclaim the prompt the interrupted run re-queued (requeueForResume): the resumed session
109
+ * still owns that request in its context, so this run's outcome bookkeeping — re-queue on
110
110
  * unfulfilled, clear on fulfillment — must operate on the queue's copy, or a fulfilling
111
- * resume leaves it queued for a later fresh tick to run the same request twice. The exact
111
+ * resume leaves it queued for a later fresh run to run the same request twice. The exact
112
112
  * recorded file is taken, so an enqueue or cancel meanwhile cannot divert the reclaim; a
113
- * vanished file (cancelled) reclaims nothing. The flag is consumed even when this tick does
114
- * not resume: a fresh fallback re-derives its prompt from the queue like any other tick, and
113
+ * vanished file (cancelled) reclaims nothing. The flag is consumed even when this run does
114
+ * not resume: a fresh fallback re-derives its prompt from the queue like any other run, and
115
115
  * a stale record must never survive into a later resume. */
116
116
  reclaimForResume(state, resuming) {
117
117
  const reclaimFile = state.resumePromptFile;