tumwater 0.2.0 → 0.4.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 (464) 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 +55 -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 +6 -4
  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 +404 -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 +281 -55
  41. package/dist/src/backlog/backlog-cli-view.js +255 -0
  42. package/dist/src/backlog/backlog-cli.js +91 -335
  43. package/dist/src/backlog/backlog-commit.js +20 -13
  44. package/dist/src/backlog/backlog-eligibility.js +193 -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 +264 -0
  48. package/dist/src/backlog/backlog-release.js +134 -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-guardrails.js +136 -0
  56. package/dist/src/baseline/main-red.js +153 -36
  57. package/dist/src/baseline/main-watch.js +232 -0
  58. package/dist/src/brief/brief-edit.js +12 -12
  59. package/dist/src/brief/brief.js +31 -51
  60. package/dist/src/budget/budget-fallback-view.js +288 -0
  61. package/dist/src/budget/budget-wiring.js +158 -0
  62. package/dist/src/budget/budget.js +31 -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 +65 -3
  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 +181 -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 +183 -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 +291 -598
  82. package/dist/src/cli/cli-repo-gate.js +11 -1
  83. package/dist/src/cli/cli-review-commands.js +113 -0
  84. package/dist/src/cli/cli-role-command.js +525 -0
  85. package/dist/src/cli/cli-start-summary.js +167 -0
  86. package/dist/src/cli/{cli-run.js → cli-start.js} +193 -237
  87. package/dist/src/cli/completion.js +169 -22
  88. package/dist/src/cli/config-commands.js +58 -26
  89. package/dist/src/cli/follow-view.js +75 -0
  90. package/dist/src/cli/help.js +258 -82
  91. package/dist/src/cli/log-commands.js +164 -85
  92. package/dist/src/cli/question-commands.js +211 -10
  93. package/dist/src/cli.js +173 -45
  94. package/dist/src/collections.js +56 -13
  95. package/dist/src/concurrency/check-permit.js +20 -3
  96. package/dist/src/concurrency/lock.js +17 -13
  97. package/dist/src/concurrency/provider-lease.js +44 -8
  98. package/dist/src/concurrency/semaphore.js +102 -26
  99. package/dist/src/config/config-aliases.js +0 -1
  100. package/dist/src/config/config-editable-keys.js +16 -1
  101. package/dist/src/config/config-fallbacks.js +94 -56
  102. package/dist/src/config/config-field-checks.js +40 -10
  103. package/dist/src/config/config-keys.js +30 -8
  104. package/dist/src/config/config-live.js +63 -24
  105. package/dist/src/config/config-request.js +137 -0
  106. package/dist/src/config/config-schema.js +31 -24
  107. package/dist/src/config/config-selector-checks.js +123 -0
  108. package/dist/src/config/config-validation-agents.js +80 -0
  109. package/dist/src/config/config-validation-model.js +116 -0
  110. package/dist/src/config/config-validation.js +169 -222
  111. package/dist/src/config/config-views.js +136 -54
  112. package/dist/src/config/config-write-core.js +135 -0
  113. package/dist/src/config/config-write.js +164 -265
  114. package/dist/src/config/config.js +53 -38
  115. package/dist/src/config/model-selector.js +34 -34
  116. package/dist/src/doctor/doctor-backlog-bugs.js +330 -0
  117. package/dist/src/doctor/doctor-backlog-plans.js +398 -0
  118. package/dist/src/doctor/doctor-backlog.js +249 -512
  119. package/dist/src/doctor/doctor-check-names.js +85 -0
  120. package/dist/src/doctor/doctor-checks.js +61 -593
  121. package/dist/src/doctor/doctor-claude-checks.js +142 -0
  122. package/dist/src/doctor/doctor-codex-checks.js +276 -0
  123. package/dist/src/doctor/doctor-contention-checks.js +506 -0
  124. package/dist/src/doctor/doctor-fallback-checks.js +130 -0
  125. package/dist/src/doctor/doctor-holds.js +80 -66
  126. package/dist/src/doctor/doctor-install.js +2 -1
  127. package/dist/src/doctor/doctor-model-checks.js +216 -537
  128. package/dist/src/doctor/doctor-notify.js +9 -5
  129. package/dist/src/doctor/doctor-opencode-checks.js +164 -0
  130. package/dist/src/doctor/doctor-orphans.js +182 -63
  131. package/dist/src/doctor/doctor-pi-checks.js +62 -0
  132. package/dist/src/doctor/doctor-project-checks.js +397 -0
  133. package/dist/src/doctor/doctor.js +126 -77
  134. package/dist/src/doctor/image-probe.js +21 -8
  135. package/dist/src/doctor/outcome.js +3 -2
  136. package/dist/src/doctor/probe.js +21 -12
  137. package/dist/src/events/event-format.js +185 -89
  138. package/dist/src/events/event-labels.js +11 -5
  139. package/dist/src/events/event-legacy.js +39 -15
  140. package/dist/src/events/event-read.js +52 -39
  141. package/dist/src/events/event-tally.js +16 -0
  142. package/dist/src/events/event-window.js +80 -26
  143. package/dist/src/events/events.js +30 -13
  144. package/dist/src/events/notify.js +7 -7
  145. package/dist/src/failure/failure-cluster.js +12 -12
  146. package/dist/src/failure/failure-data.js +65 -60
  147. package/dist/src/failure/failure-render.js +29 -21
  148. package/dist/src/failure/failure-state-change.js +17 -12
  149. package/dist/src/failure/time-spend.js +35 -35
  150. package/dist/src/files/file-queue.js +17 -0
  151. package/dist/src/files/files.js +111 -35
  152. package/dist/src/files/json-files.js +3 -3
  153. package/dist/src/files/json-object.js +28 -7
  154. package/dist/src/files/stat-cache.js +2 -2
  155. package/dist/src/files/tail.js +1 -1
  156. package/dist/src/gates/bootstrap-gates.js +4 -5
  157. package/dist/src/gates/budget-gates.js +88 -225
  158. package/dist/src/gates/disk-gate.js +1 -1
  159. package/dist/src/gates/gate-polls.js +101 -143
  160. package/dist/src/gates/maintenance-quota.js +37 -30
  161. package/dist/src/gates/pause-gates.js +28 -10
  162. package/dist/src/gates/readiness.js +7 -3
  163. package/dist/src/gates/role-cap-gates.js +8 -8
  164. package/dist/src/gates/startup-gate.js +94 -32
  165. package/dist/src/gates/streak-gate.js +54 -30
  166. package/dist/src/git/commit-message.js +89 -46
  167. package/dist/src/git/git-diff.js +16 -10
  168. package/dist/src/git/git-run.js +79 -38
  169. package/dist/src/git/git.js +54 -34
  170. package/dist/src/git/slot-salvage.js +253 -0
  171. package/dist/src/git/slots-state.js +6 -6
  172. package/dist/src/git/worktree-pool.js +132 -38
  173. package/dist/src/git/worktree-use.js +4 -11
  174. package/dist/src/git/worktree.js +94 -37
  175. package/dist/src/gui/gui-admin-endpoints.js +96 -0
  176. package/dist/src/gui/gui-args.js +79 -8
  177. package/dist/src/gui/gui-backlog-commands.js +43 -19
  178. package/dist/src/gui/gui-backlog-endpoints.js +156 -0
  179. package/dist/src/gui/gui-command.js +26 -13
  180. package/dist/src/gui/gui-config-commands.js +168 -80
  181. package/dist/src/gui/gui-endpoint-commands.js +5 -4
  182. package/dist/src/gui/gui-endpoint-common.js +4 -4
  183. package/dist/src/gui/gui-endpoints.js +11 -380
  184. package/dist/src/gui/gui-history-endpoints.js +301 -0
  185. package/dist/src/gui/gui-operator-commands.js +235 -13
  186. package/dist/src/gui/gui-prompt-commands.js +26 -20
  187. package/dist/src/gui/gui-report-endpoints.js +97 -0
  188. package/dist/src/gui/gui-server.js +26 -5
  189. package/dist/src/gui/gui-team-commands.js +7 -7
  190. package/dist/src/gui/http-body.js +1 -1
  191. package/dist/src/history/history-data.js +122 -234
  192. package/dist/src/history/history-queued.js +155 -0
  193. package/dist/src/history/history-render.js +42 -22
  194. package/dist/src/history/history.js +190 -49
  195. package/dist/src/inbox/inbox-attachments.js +29 -30
  196. package/dist/src/inbox/inbox-cancel.js +10 -11
  197. package/dist/src/inbox/inbox-edit.js +9 -9
  198. package/dist/src/inbox/inbox-submit.js +18 -18
  199. package/dist/src/inbox/inbox-top.js +28 -17
  200. package/dist/src/inbox/inbox.js +42 -43
  201. package/dist/src/inbox/pending-prompt.js +26 -26
  202. package/dist/src/inbox/prompt-commands.js +62 -49
  203. package/dist/src/inbox/prompt-not-before.js +2 -2
  204. package/dist/src/init/init-templates.js +1 -2
  205. package/dist/src/init/init.js +28 -23
  206. package/dist/src/merge/backlog-conflicts.js +215 -35
  207. package/dist/src/merge/merge-batch.js +14 -8
  208. package/dist/src/merge/merge-cancel.js +53 -0
  209. package/dist/src/merge/merge-check-failures.js +44 -22
  210. package/dist/src/merge/merge-core.js +58 -32
  211. package/dist/src/merge/merge-diff.js +5 -4
  212. package/dist/src/merge/merge-drain.js +45 -19
  213. package/dist/src/merge/merge-git.js +177 -38
  214. package/dist/src/merge/merge-pipeline.js +15 -3
  215. package/dist/src/merge/merge-post-review.js +214 -0
  216. package/dist/src/merge/merge-queue-render.js +48 -11
  217. package/dist/src/merge/merge-queue.js +52 -15
  218. package/dist/src/merge/merge-requeue.js +103 -0
  219. package/dist/src/merge/merge-slot.js +61 -16
  220. package/dist/src/merge/merge-stack.js +27 -11
  221. package/dist/src/merge/merge-to-main.js +77 -26
  222. package/dist/src/merge/merge-top.js +83 -0
  223. package/dist/src/merge/merge-verify.js +75 -18
  224. package/dist/src/notes-cli.js +35 -15
  225. package/dist/src/operator/operator-commands.js +192 -81
  226. package/dist/src/operator/operator-intent.js +69 -42
  227. package/dist/src/operator/operator-requests.js +35 -40
  228. package/dist/src/operator/retire.js +5 -6
  229. package/dist/src/operator/revert.js +142 -34
  230. package/dist/src/orchestrator/orchestrator-launch.js +60 -52
  231. package/dist/src/orchestrator/orchestrator-poll.js +352 -0
  232. package/dist/src/orchestrator/orchestrator-scheduling.js +71 -370
  233. package/dist/src/orchestrator/orchestrator.js +129 -369
  234. package/dist/src/orchestrator/retention.js +42 -8
  235. package/dist/src/orchestrator/scheduling-admit.js +116 -0
  236. package/dist/src/orchestrator/scheduling-scope.js +245 -0
  237. package/dist/src/orchestrator/scheduling-skip.js +195 -0
  238. package/dist/src/orchestrator/startup-migration-steps.js +8 -7
  239. package/dist/src/orchestrator/startup-migrations.js +11 -7
  240. package/dist/src/paths.js +126 -49
  241. package/dist/src/pi/command-shape.js +12 -1
  242. package/dist/src/pi/pi-args.js +6 -4
  243. package/dist/src/pi/pi-backend.js +6 -6
  244. package/dist/src/pi/pi-bin.js +54 -63
  245. package/dist/src/pi/pi-listed-models.js +53 -0
  246. package/dist/src/pi/pi-models.js +63 -30
  247. package/dist/src/pi/pi-run-result.js +1 -1
  248. package/dist/src/pi/pi-settings.js +1 -1
  249. package/dist/src/pi/pi-stream.js +6 -6
  250. package/dist/src/pi/pi-watchdogs.js +18 -19
  251. package/dist/src/pi-extension/bounded-output.js +5 -3
  252. package/dist/src/pi-extension/context-budget.js +2 -2
  253. package/dist/src/pi-extension/context-shake.js +1 -1
  254. package/dist/src/pi-extension/context-window.js +0 -1
  255. package/dist/src/pi-extension/full-output.js +3 -10
  256. package/dist/src/pi-extension/strip-thinking.js +0 -1
  257. package/dist/src/pi-extension/trim-system-prompt.js +3 -4
  258. package/dist/src/pi-extension/write-guard.js +37 -0
  259. package/dist/src/process/launch-services.js +1 -2
  260. package/dist/src/process/node-bin.js +16 -0
  261. package/dist/src/process/process-group.js +8 -18
  262. package/dist/src/process/process.js +41 -2
  263. package/dist/src/process/run-marker.js +26 -6
  264. package/dist/src/process/supervisor.js +22 -21
  265. package/dist/src/prompt/dialect.js +17 -2
  266. package/dist/src/prompt/gate-notes.js +203 -0
  267. package/dist/src/prompt/gate-prompts.js +150 -217
  268. package/dist/src/prompt/notes-backlog.js +184 -0
  269. package/dist/src/prompt/principles.js +1 -2
  270. package/dist/src/prompt/prompt-followup.js +19 -14
  271. package/dist/src/prompt/prompt.js +131 -204
  272. package/dist/src/redeploy/redeploy-policy.js +24 -19
  273. package/dist/src/redeploy/redeploy-probes.js +1 -1
  274. package/dist/src/redeploy/redeploy.js +2 -3
  275. package/dist/src/redeploy/redeployer.js +20 -20
  276. package/dist/src/redeploy/self-reload.js +2 -1
  277. package/dist/src/report/report-data.js +188 -124
  278. package/dist/src/report/report-fold.js +130 -54
  279. package/dist/src/report/report-main-red.js +55 -0
  280. package/dist/src/report/report-render.js +136 -65
  281. package/dist/src/report/report-types.js +1 -0
  282. package/dist/src/report/report.js +23 -9
  283. package/dist/src/request-timeouts.js +2 -2
  284. package/dist/src/review/diff-rules.js +53 -0
  285. package/dist/src/review/known-flakes.js +112 -1
  286. package/dist/src/review/post-merge-review-accept.js +51 -0
  287. package/dist/src/review/post-merge-review-render.js +112 -0
  288. package/dist/src/review/post-merge-review.js +239 -0
  289. package/dist/src/review/protected-edits.js +24 -10
  290. package/dist/src/review/quarantine-render.js +65 -0
  291. package/dist/src/review/review-followup.js +8 -8
  292. package/dist/src/review/review-precheck.js +66 -23
  293. package/dist/src/review/review-run.js +395 -0
  294. package/dist/src/review/review-verdict.js +2 -2
  295. package/dist/src/review/review.js +180 -401
  296. package/dist/src/review/secret-leaks.js +36 -16
  297. package/dist/src/review/suite-rerun.js +0 -1
  298. package/dist/src/roles/legacy-role-migration.js +80 -7
  299. package/dist/src/roles/role-catalog.js +127 -12
  300. package/dist/src/roles/role-guidance.js +65 -20
  301. package/dist/src/roles/role-labels.js +7 -5
  302. package/dist/src/roles/role-render.js +108 -56
  303. package/dist/src/roles/role-view.js +95 -56
  304. package/dist/src/roles/roles.js +33 -33
  305. package/dist/src/roles/runner-ids.js +97 -0
  306. package/dist/src/run/acceptance-greps.js +119 -0
  307. package/dist/src/run/ci-parity.js +121 -0
  308. package/dist/src/run/feedback-filings.js +51 -0
  309. package/dist/src/run/qa-coverage.js +125 -0
  310. package/dist/src/{tick/tick-apply.js → run/run-apply.js} +95 -94
  311. package/dist/src/run/run-detail-data.js +175 -0
  312. package/dist/src/run/run-detail-render.js +91 -0
  313. package/dist/src/run/run-detail.js +168 -0
  314. package/dist/src/{tick/tick-finalize.js → run/run-finalize.js} +73 -60
  315. package/dist/src/{tick/tick-outcome.js → run/run-outcome.js} +6 -7
  316. package/dist/src/{tick/tick-prompt.js → run/run-prompt.js} +122 -73
  317. package/dist/src/{tick/tick-resume.js → run/run-resume.js} +55 -26
  318. package/dist/src/{tick/tick-stage.js → run/run-stage.js} +170 -83
  319. package/dist/src/{tick/tick-timing.js → run/run-timing.js} +43 -41
  320. package/dist/src/{tick/tick-usage.js → run/run-usage.js} +45 -37
  321. package/dist/src/{tick/tick-verdict.js → run/run-verdict.js} +105 -57
  322. package/dist/src/run/selfcheck-digest.js +40 -0
  323. package/dist/src/run/stage-backlog-checks.js +249 -0
  324. package/dist/src/run/stage-check.js +178 -0
  325. package/dist/src/run/stage-checks-shared.js +65 -0
  326. package/dist/src/run/stage-name-checks.js +204 -0
  327. package/dist/src/run/stage-path-checks.js +231 -0
  328. package/dist/src/run/stage-prose-checks.js +261 -0
  329. package/dist/src/runner/leftover.js +216 -0
  330. package/dist/src/{loop → runner}/model-fallback.js +12 -12
  331. package/dist/src/runner/revision.js +191 -0
  332. package/dist/src/{loop/loop-fallback.js → runner/runner-fallback.js} +8 -8
  333. package/dist/src/runner/runner-outcome.js +109 -0
  334. package/dist/src/{loop/loop-pi.js → runner/runner-pi.js} +140 -131
  335. package/dist/src/{loop/loop-recovery.js → runner/runner-recovery.js} +39 -18
  336. package/dist/src/{loop/loop-tick.js → runner/runner-run.js} +236 -245
  337. package/dist/src/{loop/loop-state.js → runner/runner-state-load.js} +61 -114
  338. package/dist/src/runner/runner-state.js +103 -0
  339. package/dist/src/{loop/loop.js → runner/runner.js} +123 -120
  340. package/dist/src/scheduling/backoff.js +38 -38
  341. package/dist/src/scheduling/claim-entries.js +49 -0
  342. package/dist/src/scheduling/claims.js +35 -22
  343. package/dist/src/scheduling/once-round.js +22 -22
  344. package/dist/src/scheduling/quiet-hours.js +5 -6
  345. package/dist/src/scheduling/scheduling.js +74 -64
  346. package/dist/src/scheduling/work-merged-cache.js +2 -2
  347. package/dist/src/status/status-budget.js +55 -47
  348. package/dist/src/status/status-data.js +49 -17
  349. package/dist/src/status/status-inbox.js +2 -2
  350. package/dist/src/status/status-install.js +0 -1
  351. package/dist/src/status/status-polls.js +43 -28
  352. package/dist/src/status/status-roles.js +50 -13
  353. package/dist/src/team/error-storm.js +8 -8
  354. package/dist/src/team/failure-spread.js +2 -2
  355. package/dist/src/team/orchestrator-info.js +15 -9
  356. package/dist/src/team/reclaim.js +7 -8
  357. package/dist/src/team/team-hold.js +7 -7
  358. package/dist/src/team/team-polls.js +91 -50
  359. package/dist/src/team/team-state.js +8 -2
  360. package/dist/src/text/datetime.js +65 -18
  361. package/dist/src/text/format.js +48 -11
  362. package/dist/src/text/markdown.js +8 -5
  363. package/dist/src/text/phrases.js +60 -23
  364. package/dist/src/text/suggest.js +1 -1
  365. package/dist/src/text/text.js +78 -13
  366. package/dist/src/ui/badges.js +99 -38
  367. package/dist/src/ui/gui/gui-client-backlog.js +314 -0
  368. package/dist/src/ui/gui/gui-client-boot.js +89 -61
  369. package/dist/src/ui/gui/gui-client-composer.js +8 -9
  370. package/dist/src/ui/gui/gui-client-drawer-config.js +254 -0
  371. package/dist/src/ui/gui/gui-client-drawer.js +155 -289
  372. package/dist/src/ui/gui/gui-client-feed.js +271 -0
  373. package/dist/src/ui/gui/gui-client-history.js +437 -68
  374. package/dist/src/ui/gui/gui-client-labels.js +6 -3
  375. package/dist/src/ui/gui/gui-client-markdown.js +1 -2
  376. package/dist/src/ui/gui/gui-client-model.js +27 -36
  377. package/dist/src/ui/gui/gui-client-operator.js +60 -52
  378. package/dist/src/ui/gui/gui-client-pending.js +405 -24
  379. package/dist/src/ui/gui/gui-client-report-chart.js +492 -0
  380. package/dist/src/ui/gui/gui-client-report.js +105 -430
  381. package/dist/src/ui/gui/{gui-client-loops.js → gui-client-roles.js} +43 -44
  382. package/dist/src/ui/gui/gui-client-settings.js +163 -5
  383. package/dist/src/ui/gui/gui-client-team.js +36 -465
  384. package/dist/src/ui/gui/gui-client.js +38 -26
  385. package/dist/src/ui/gui/gui-icons.js +0 -2
  386. package/dist/src/ui/gui/gui-page.js +10 -7
  387. package/dist/src/ui/gui/gui-styles.js +38 -34
  388. package/dist/src/ui/progress-data.js +9 -11
  389. package/dist/src/ui/{tick-progress-model.js → run-progress-model.js} +33 -32
  390. package/dist/src/ui/status-model.js +133 -125
  391. package/dist/src/ui/status-payload.js +364 -49
  392. package/dist/src/ui/status-render.js +109 -82
  393. package/dist/src/ui/team-alerts.js +728 -62
  394. package/dist/src/ui/tone.js +12 -6
  395. package/dist/src/ui/transcript-run.js +58 -0
  396. package/dist/src/ui/transcript-tail.js +28 -20
  397. package/dist/src/ui/transcript.js +63 -23
  398. package/dist/src/ui/tui/tui-app.js +0 -1
  399. package/dist/src/ui/tui/tui-backlog.js +53 -14
  400. package/dist/src/ui/tui/tui-editor-answer.js +27 -31
  401. package/dist/src/ui/tui/tui-editor-attach.js +4 -12
  402. package/dist/src/ui/tui/tui-editor-backends.js +127 -0
  403. package/dist/src/ui/tui/tui-editor-brief.js +14 -36
  404. package/dist/src/ui/tui/tui-editor-budget.js +36 -39
  405. package/dist/src/ui/tui/tui-editor-check.js +29 -0
  406. package/dist/src/ui/tui/tui-editor-checks.js +28 -0
  407. package/dist/src/ui/tui/tui-editor-claude-reserve.js +24 -0
  408. package/dist/src/ui/tui/tui-editor-concurrency.js +25 -0
  409. package/dist/src/ui/tui/tui-editor-config.js +99 -0
  410. package/dist/src/ui/tui/tui-editor-entry.js +39 -64
  411. package/dist/src/ui/tui/tui-editor-fallback.js +31 -0
  412. package/dist/src/ui/tui/tui-editor-instances.js +46 -0
  413. package/dist/src/ui/tui/tui-editor-instructions.js +117 -0
  414. package/dist/src/ui/tui/tui-editor-interval.js +29 -16
  415. package/dist/src/ui/tui/tui-editor-model.js +29 -0
  416. package/dist/src/ui/tui/tui-editor-notes.js +9 -29
  417. package/dist/src/ui/tui/tui-editor-notify.js +25 -0
  418. package/dist/src/ui/tui/tui-editor-pause.js +48 -59
  419. package/dist/src/ui/tui/tui-editor-prompt.js +11 -16
  420. package/dist/src/ui/tui/tui-editor-provider-caps.js +27 -0
  421. package/dist/src/ui/tui/tui-editor-queued.js +5 -9
  422. package/dist/src/ui/tui/tui-editor-quiet.js +95 -41
  423. package/dist/src/ui/tui/tui-editor-retire.js +5 -13
  424. package/dist/src/ui/tui/tui-editor-role-enabled.js +126 -0
  425. package/dist/src/ui/tui/tui-editor-role-key.js +71 -0
  426. package/dist/src/ui/tui/tui-editor-role-model.js +28 -0
  427. package/dist/src/ui/tui/tui-editor-search.js +45 -33
  428. package/dist/src/ui/tui/tui-editor-session.js +101 -34
  429. package/dist/src/ui/tui/tui-editor-slots.js +24 -0
  430. package/dist/src/ui/tui/tui-editors.js +44 -2
  431. package/dist/src/ui/tui/tui-frame.js +68 -11
  432. package/dist/src/ui/tui/tui-history.js +8 -9
  433. package/dist/src/ui/tui/tui-input.js +13 -11
  434. package/dist/src/ui/tui/tui-keymap.js +0 -1
  435. package/dist/src/ui/tui/tui-keys.js +33 -9
  436. package/dist/src/ui/tui/tui-pane-activity.js +35 -19
  437. package/dist/src/ui/tui/tui-pane-backlog.js +198 -126
  438. package/dist/src/ui/tui/tui-pane-brief.js +0 -1
  439. package/dist/src/ui/tui/tui-pane-ctx.js +2 -2
  440. package/dist/src/ui/tui/tui-pane-health.js +168 -8
  441. package/dist/src/ui/tui/tui-pane-history.js +446 -82
  442. package/dist/src/ui/tui/tui-pane-pending.js +539 -15
  443. package/dist/src/ui/tui/tui-pane-queued.js +78 -57
  444. package/dist/src/ui/tui/tui-pane-report.js +54 -16
  445. package/dist/src/ui/tui/tui-pane-session.js +34 -6
  446. package/dist/src/ui/tui/tui-pane-transcript.js +111 -37
  447. package/dist/src/ui/tui/tui-pane.js +91 -28
  448. package/dist/src/ui/tui/tui-panes.js +153 -34
  449. package/dist/src/ui/tui/tui.js +18 -15
  450. package/dist/src/verdict/fix-claim.js +129 -33
  451. package/dist/src/verdict/no-change.js +4 -4
  452. package/dist/src/verdict/refusal.js +40 -16
  453. package/dist/src/verdict/reply-contract.js +77 -31
  454. package/dist/src/version.js +0 -1
  455. package/package.json +2 -1
  456. package/dist/src/loop/leftover.js +0 -130
  457. package/dist/src/loop/revision.js +0 -70
  458. package/dist/src/roles/loop-ids.js +0 -77
  459. package/dist/src/tick/qa-coverage.js +0 -108
  460. package/dist/src/tick/stage-check.js +0 -419
  461. package/dist/src/tick/telemetry-digest.js +0 -25
  462. package/dist/src/tick/tick-detail-data.js +0 -108
  463. package/dist/src/tick/tick-detail.js +0 -163
  464. package/dist/src/ui/gui/gui-client-sound.js +0 -53
@@ -1,4 +1,3 @@
1
- // vocabulary: plain
2
1
  /**
3
2
  * The dashboard's POST prompt-queueing command handlers (barrelled into
4
3
  * gui/gui-endpoint-commands.ts, which routes to them from src/gui/gui-server.ts): prompt,
@@ -19,7 +18,7 @@ import { PAUSE_FOR_MAX_MS, submitRolePromptAndWake } from "../operator/operator-
19
18
  import { DIRECTOR_ROLE } from "../roles/roles.js";
20
19
  import { rejectBadQueueFileName, rejectBadRole, requirePromptText } from "./gui-args.js";
21
20
  import { badRequest, OK_GONE, sendJson } from "./http-body.js";
22
- import { errorMessage, gotSuffix } from "../text/text.js";
21
+ import { errorMessage, gotSuffix, joinParts } from "../text/text.js";
23
22
  import { readPostBody, readRoleBody } from "./gui-endpoint-common.js";
24
23
  /** Handle POST /api/prompt: queue a director prompt. An over-long prompt
25
24
  * (DIRECTOR_PROMPT_MAX_CHARS) is a user-input error, not a server fault: the shared length
@@ -93,10 +92,10 @@ function checkedPromptFields(res, body, role = DIRECTOR_ROLE) {
93
92
  return null;
94
93
  return { text, images, notBeforeMs };
95
94
  }
96
- /** Handle POST /api/prompt-role: queue a prompt for one loop — the dashboard's per-row
95
+ /** Handle POST /api/prompt-role: queue a prompt for one role — the dashboard's per-row
97
96
  * prompt affordance submits here, calling the same path `tumwater prompt --role <id>` uses
98
- * (submitRolePrompt enqueues into that loop's own queue and logs under it, then a single-role
99
- * wake brings the live loop in within one poll; the wake message rides back for the flash).
97
+ * (submitRolePrompt enqueues into that role's own queue and logs under it, then a single-role
98
+ * wake brings the live role in within one poll; the wake message rides back for the flash).
100
99
  * The role validates exactly like /api/transcript (the shared rejectBadRole wording), and the
101
100
  * body discipline is /api/prompt's: readJsonObject → 400 malformed/non-object, 413 oversized,
102
101
  * text a non-empty string within the shared length rule → 400 otherwise — plus the same
@@ -110,9 +109,9 @@ export async function handlePromptRole(req, res, root) {
110
109
  if (!fields)
111
110
  return;
112
111
  // Image-input submit gate (plans/image-input.md "Attachments", part 5/5): an attachment the
113
- // target loop cannot read (and that no tier reroutes) answers 400 naming the fix before
112
+ // target role cannot read (and that no tier reroutes) answers 400 naming the fix before
114
113
  // anything is queued — the same gate submitRolePrompt enforces, surfaced as a user-input
115
- // error rather than the server's 500. A loop that reroutes a blind read is not refused; its
114
+ // error rather than the server's 500. A role that reroutes a blind read is not refused; its
116
115
  // notice rides in the confirmation the composer flashes.
117
116
  let notice = "";
118
117
  if (fields.images && fields.images.length > 0) {
@@ -123,29 +122,36 @@ export async function handlePromptRole(req, res, root) {
123
122
  }
124
123
  notice = guidance.notice ?? "";
125
124
  }
126
- const message = [
125
+ const message = joinParts([
127
126
  submitRolePromptAndWake(root, role, fields.text, fields.images, fields.notBeforeMs),
128
127
  notice,
129
- ]
130
- .filter(Boolean)
131
- .join("\n");
128
+ ], "\n");
132
129
  sendJson(res, 200, { ok: true, message });
133
130
  }
131
+ /** The file-addressed prompt handlers' shared role prologue: validate the optional role
132
+ * (400 sent on a present-but-invalid one and null returned, so the caller stops) and default
133
+ * an absent role to the director's queue. The same optional-role rule handlePromptCancel,
134
+ * handlePromptEdit and handlePromptTop state once instead of a guard-plus-default pair. */
135
+ function promptFileRole(body, res, root) {
136
+ if (body.role !== undefined && rejectBadRole(root, res, body.role))
137
+ return null;
138
+ return body.role === undefined ? DIRECTOR_ROLE : body.role;
139
+ }
134
140
  /** Handle POST /api/prompt-cancel: retract one queued prompt addressed by its queue file —
135
141
  * the dashboard's per-row cancel affordance, the file-addressed twin of the CLI's
136
142
  * position-addressed `prompt --cancel`. The role is optional (absent cancels from the
137
143
  * director's queue) and validates exactly like /api/transcript; a file name failing the
138
144
  * shared rejectBadQueueFileName guard is a user-input error answered 400 with
139
- * nothing touched on disk. A vanished file answers 200 { status: "gone" } — the loop already
145
+ * nothing touched on disk. A vanished file answers 200 { status: "gone" } — the role already
140
146
  * dequeued the prompt, which is data for the flash line, not a server fault. Same body
141
147
  * discipline as /api/prompt (readJsonObject → 400 malformed/non-object, 413 oversized). */
142
148
  export async function handlePromptCancel(req, res, root) {
143
149
  const body = await readPostBody(req, res, '{"role": "feature", "file": "<stamp>-<seq>-<pid>.md"}');
144
150
  if (!body)
145
151
  return;
146
- if (body.role !== undefined && rejectBadRole(root, res, body.role))
152
+ const role = promptFileRole(body, res, root);
153
+ if (role === null)
147
154
  return;
148
- const role = body.role === undefined ? DIRECTOR_ROLE : body.role;
149
155
  if (rejectBadQueueFileName(res, body.file))
150
156
  return;
151
157
  const outcome = cancelQueuedFile(root, role, body.file);
@@ -161,7 +167,7 @@ export async function handlePromptCancel(req, res, root) {
161
167
  * and images validate through the same checkedPromptFields /api/prompt and /api/prompt-role
162
168
  * use; editQueuedFile throws for a bad name or an over-cap text — both user-input errors
163
169
  * answered 400 (a filesystem failure reads as 400 like handleConfigSet's failed write). A
164
- * vanished file answers 200 { ok: true, status: "gone" } — the loop already dequeued the
170
+ * vanished file answers 200 { ok: true, status: "gone" } — the role already dequeued the
165
171
  * prompt, which is data for the flash line, not a server error; an edit answers 200 with the
166
172
  * old and new operator-facing text the client flashes. Same body discipline as /api/prompt
167
173
  * (readJsonObject → 400 malformed/non-object, 413 oversized). */
@@ -169,9 +175,9 @@ export async function handlePromptEdit(req, res, root) {
169
175
  const body = await readPostBody(req, res, '{"role": "qa", "file": "<stamp>.md", "text": "..."}');
170
176
  if (!body)
171
177
  return;
172
- if (body.role !== undefined && rejectBadRole(root, res, body.role))
178
+ const role = promptFileRole(body, res, root);
179
+ if (role === null)
173
180
  return;
174
- const role = body.role === undefined ? DIRECTOR_ROLE : body.role;
175
181
  if (rejectBadQueueFileName(res, body.file))
176
182
  return;
177
183
  const fields = checkedPromptFields(res, body, role);
@@ -179,7 +185,7 @@ export async function handlePromptEdit(req, res, root) {
179
185
  return;
180
186
  // Image-input gate (plans/image-input.md "Attachments", part 5/5), the edit twin of
181
187
  // handlePromptRole's: an image edited into the queued prompt answers 400 naming the fix
182
- // when the target loop cannot read it (and no tier reroutes it) — the same gate
188
+ // when the target role cannot read it (and no tier reroutes it) — the same gate
183
189
  // submitRolePrompt enforces — before anything is written.
184
190
  if (fields.images && fields.images.length > 0) {
185
191
  const guidance = imagePromptGuidance(root, role);
@@ -213,9 +219,9 @@ export async function handlePromptTop(req, res, root) {
213
219
  const body = await readPostBody(req, res, '{"role": "qa", "file": "<stamp>.md"}');
214
220
  if (!body)
215
221
  return;
216
- if (body.role !== undefined && rejectBadRole(root, res, body.role))
222
+ const role = promptFileRole(body, res, root);
223
+ if (role === null)
217
224
  return;
218
- const role = body.role === undefined ? DIRECTOR_ROLE : body.role;
219
225
  if (rejectBadQueueFileName(res, body.file))
220
226
  return;
221
227
  let outcome;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The dashboard's GET report and failures handlers (src/gui/gui-server.ts routes to them):
3
+ * report and failures. Each answers its request and touches no socket beyond its own `res`;
4
+ * the domain work lives one layer down (report/report-data.ts, failure/failure-data.ts), so
5
+ * this module only adapts HTTP onto it. Barrelled into gui/gui-endpoints.ts beside the other
6
+ * per-family GET endpoint modules.
7
+ */
8
+ import { collectReport, collectReportSince } from "../report/report-data.js";
9
+ import { collectFailureReport, collectFailureReportSince } from "../failure/failure-data.js";
10
+ import { renderFailureMarkdown } from "../failure/failure-render.js";
11
+ import { renderSinceReportMarkdown } from "../report/report-render.js";
12
+ import { loadQuarantine } from "../review/known-flakes.js";
13
+ import { quarantineRows, renderQuarantineSection } from "../review/quarantine-render.js";
14
+ import { REPORT_SINCE_MAX_MS, reportSinceMsg } from "../events/event-window.js";
15
+ import { roleListQuery, sinceMsQuery, untilMsQuery, windowDays } from "./gui-args.js";
16
+ import { badRequest, sendJson } from "./http-body.js";
17
+ /** Parse and validate the role-scoped, sinceMs-or-days query the report and failures endpoints
18
+ * both take: the `?role=` filter, a comma-separated list (each id trimmed, deduplicated, and
19
+ * validated by rejectBadRole — an unknown id or an empty list → 400 naming it) and, when
20
+ * `?sinceMs=` is present, the trailing-window length (reportSinceMs, which 400s a simultaneous
21
+ * `?days=`). Returns null once a 400 is sent. `sinceMs` is defined exactly when the caller
22
+ * should use the since shape; otherwise it falls through to the days shape with `windowDays(q)`.
23
+ * The one home of that shared scaffolding, so the two endpoints cannot drift on the role rule or
24
+ * the days-vs-sinceMs mutual exclusion (the server twin of reportEndpoint on the GUI client). */
25
+ function reportScope(q, res, root) {
26
+ const roles = roleListQuery(q, res, root);
27
+ if (roles === null)
28
+ return null;
29
+ if (q.get("sinceMs") !== null) {
30
+ const sinceMs = reportSinceMs(q, res);
31
+ if (sinceMs === null)
32
+ return null;
33
+ return { roles, sinceMs };
34
+ }
35
+ return { roles };
36
+ }
37
+ /** Parse and bound the report endpoints' `?sinceMs=` trailing-window length: a simultaneous
38
+ * `?days=` is the CLI's rival shape (whole local days vs a trailing window) → 400 naming both;
39
+ * otherwise the length rides sinceMsQuery (gui-args.ts) — positive-integer parse, then a 400
40
+ * naming the cap rather than a silent clamp (an explicit window typo must not shrink to some
41
+ * other window) — with the "must be between 1 and …" wording. Returns the parsed length, or
42
+ * null once the 400 is sent. */
43
+ function reportSinceMs(q, res) {
44
+ if (q.get("days") !== null) {
45
+ badRequest(res, "days and sinceMs are mutually exclusive; days counts whole local days, sinceMs totals a trailing window");
46
+ return null;
47
+ }
48
+ return sinceMsQuery(q, res, REPORT_SINCE_MAX_MS, reportSinceMsg);
49
+ }
50
+ /** Handle GET /api/report?days=N[&role=<id>[,<id>...]] or
51
+ * /api/report?sinceMs=<ms>[&untilMs=<ms>][&role=<id>[,<id>...]]: the
52
+ * usage report — the day series (collectReport's ReportData) as JSON the dashboard's report tab
53
+ * charts, or, when sinceMs is set, the trailing-window totals rendered through
54
+ * renderSinceReportMarkdown as { markdown } (the CLI's `report --since` shape). The day window
55
+ * follows windowDays. An absent role is the team-wide report; the listed roles, summed
56
+ * (each id validated by reportScope). Reads files directly, so it works whether or not the team
57
+ * is running. */
58
+ export function handleReport(q, res, root) {
59
+ const scope = reportScope(q, res, root);
60
+ if (scope === null)
61
+ return;
62
+ const untilMs = untilMsQuery(q, res, scope.sinceMs);
63
+ if (untilMs === null)
64
+ return;
65
+ if (scope.sinceMs !== undefined) {
66
+ sendJson(res, 200, { markdown: renderSinceReportMarkdown(collectReportSince(root, scope.sinceMs, scope.roles, untilMs)) });
67
+ return;
68
+ }
69
+ sendJson(res, 200, collectReport(root, windowDays(q), scope.roles));
70
+ }
71
+ /** Handle GET /api/failures?days=N[&role=<id>[,<id>...]] or
72
+ * /api/failures?sinceMs=<ms>[&untilMs=<ms>][&role=<id>[,<id>...]]: the
73
+ * same bounded Markdown failure digest the selfcheck role feeds on and `tumwater report
74
+ * --failures` prints, as JSON ({ markdown }) — the dashboard's failures tab renders it; with
75
+ * sinceMs it is the trailing-window digest (collectFailureReportSince) through the same render,
76
+ * the CLI's `report --failures --since` shape. The response also carries `quarantine`, the
77
+ * Markdown section (renderQuarantineSection over the current loadQuarantine list, an empty
78
+ * string when it is empty) the Failures view paints below the digest — the read twin of the
79
+ * amber quarantine alert, current rather than window- or role-scoped. The digest's `markdown`
80
+ * is unchanged. The days window follows windowDays (so it can
81
+ * never drift from /api/report's). role rides the same rule as
82
+ * handleReport: absent → the team digest, present → the validated listed roles, summed. Reads files
83
+ * directly, so it works with no team running. */
84
+ export function handleFailures(q, res, root) {
85
+ const scope = reportScope(q, res, root);
86
+ if (scope === null)
87
+ return;
88
+ const untilMs = untilMsQuery(q, res, scope.sinceMs);
89
+ if (untilMs === null)
90
+ return;
91
+ const quarantine = renderQuarantineSection(quarantineRows(loadQuarantine(root)), Date.now());
92
+ if (scope.sinceMs !== undefined) {
93
+ sendJson(res, 200, { markdown: renderFailureMarkdown(collectFailureReportSince(root, scope.sinceMs, scope.roles, untilMs)), quarantine });
94
+ return;
95
+ }
96
+ sendJson(res, 200, { markdown: renderFailureMarkdown(collectFailureReport(root, windowDays(q), scope.roles)), quarantine });
97
+ }
@@ -1,6 +1,8 @@
1
1
  /** The dashboard HTTP server: routing, the shared-token gate, the static page, /api/status, and the
2
2
  * self-reload watch. Every /api endpoint's handler lives in gui/gui-endpoints.ts (the GET data
3
- * endpoints) and gui/gui-endpoint-commands.ts (the POST operator endpoints) — this module owns
3
+ * endpoints, barrelled there from one module per family — gui-history-endpoints,
4
+ * gui-backlog-endpoints, gui-report-endpoints, gui-admin-endpoints) and
5
+ * gui/gui-endpoint-commands.ts (the POST operator endpoints) — this module owns
4
6
  * the socket, not the data. The `tumwater gui` CLI entry (cmdGui) lives in gui/gui-command.ts,
5
7
  * which imports startGui from here, so the server and the command that boots it stay adjacent. */
6
8
  import crypto from "node:crypto";
@@ -10,8 +12,8 @@ import { statusPayload } from "../ui/status-payload.js";
10
12
  import { captureStartupBuild, createReloadWatch, reexecSelf, watchReloadSupervisor, } from "../redeploy/self-reload.js";
11
13
  import { warnEvent, TUMWATER_SOURCE } from "../events/events.js";
12
14
  import { errorMessage } from "../text/text.js";
13
- import { handleBacklog, handleBrief, handleConfig, handleDiff, handleFailures, handleReport, handleHistory, handleLogs, handlePromptText, handleTick, handleRole, handleTranscript, handleDoctor, handleRetireList, } from "./gui-endpoints.js";
14
- import { handleAbort, handleBriefEdit, handleBudget, handleConfigSet, handleConfigUnset, handleRoleCap, handleRoleEnable, handleRoleDisable, handleRoleInstances, handleRoleInterval, handleRoleInstructions, handleRoleModel, handleRoleQuietHours, handleNotifyTest, handlePause, handlePauseRole, handlePrompt, handleBacklogFile, handleBacklogCancel, handleBacklogRelease, handleBacklogTop, handleBacklogEdit, handlePromptCancel, handlePromptEdit, handlePromptRole, handlePromptTop, handleQuestionAnswer, handleReclaim, handleRestart, handleStopSchedule, handleResetCounters, handleRoleNotes, handleRetire, handleWake, handleWakeCancel, } from "./gui-endpoint-commands.js";
15
+ import { handleBacklog, handleBacklogMatch, handleBrief, handleConfig, handleDiff, handleFailures, handleReport, handleHistory, handleLogs, handlePromptText, handleRun, handleRole, handleTranscript, handleDoctor, handleRetireList, } from "./gui-endpoints.js";
16
+ import { handleAbort, handleBriefEdit, handleBudget, handleConfigSet, handleConfigUnset, handleRoleCap, handleRoleReviewAfterMerge, handleRoleEnable, handleRoleDisable, handleRoleInstances, handleRoleInterval, handleRoleInstructions, handleRoleModel, handleRoleQuietHours, handleNotifyTest, handlePause, handlePauseRole, handlePrompt, handleBacklogFile, handleBacklogCancel, handleBacklogRelease, handleBacklogTop, handleBacklogEdit, handlePromptCancel, handlePromptEdit, handlePromptRole, handlePromptTop, handleQuestionAnswer, handleReclaim, handleKillOrphans, handleDropBrokenPins, handleCommitBacklog, handleResyncInstall, handleRetireLeftovers, handleDoctorReprobe, handleRestart, handleStopSchedule, handleResetCounters, handleRoleNotes, handleRetire, handleRevert, handleQueueCancel, handleQueueTop, handlePostReviewAccept, handleWake, handleWakeCancel, } from "./gui-endpoint-commands.js";
15
17
  import { sendJson } from "./http-body.js";
16
18
  /** Constant-time credential comparison for the shared-token gate: `timingSafeEqual` throws
17
19
  * on unequal lengths, so the length equality is the guard. A naive `===` string compare
@@ -148,10 +150,11 @@ export function startGui(root, port, allInterfaces = false, token = "", watch =
148
150
  "GET /api/logs": (_req, res, target) => handleLogs(target.searchParams, res, root),
149
151
  "GET /api/transcript": (_req, res, target) => handleTranscript(target.searchParams, res, root),
150
152
  "GET /api/prompt-text": (_req, res, target) => handlePromptText(target.searchParams, res, root),
151
- "GET /api/run": (_req, res, target) => handleTick(target.searchParams, res, root),
153
+ "GET /api/run": (_req, res, target) => handleRun(target.searchParams, res, root),
152
154
  "GET /api/role": (_req, res, target) => handleRole(target.searchParams, res, root),
153
155
  "GET /api/diff": (_req, res, target) => handleDiff(target.searchParams, res, root),
154
156
  "GET /api/backlog": (_req, res, target) => handleBacklog(target.searchParams, res, root),
157
+ "GET /api/backlog-match": (_req, res, target) => handleBacklogMatch(target.searchParams, res, root),
155
158
  "GET /api/config": (_req, res) => handleConfig(res, root),
156
159
  "GET /api/brief": (_req, res) => handleBrief(res, root),
157
160
  "GET /api/doctor": (_req, res) => handleDoctor(res, root),
@@ -173,6 +176,7 @@ export function startGui(root, port, allInterfaces = false, token = "", watch =
173
176
  "POST /api/question-answer": (req, res) => handleQuestionAnswer(req, res, root),
174
177
  "POST /api/budget": (req, res) => handleBudget(req, res, root),
175
178
  "POST /api/role-cap": (req, res) => handleRoleCap(req, res, root),
179
+ "POST /api/role-review-after-merge": (req, res) => handleRoleReviewAfterMerge(req, res, root),
176
180
  "POST /api/role-enable": (req, res) => handleRoleEnable(req, res, root),
177
181
  "POST /api/role-disable": (req, res) => handleRoleDisable(req, res, root),
178
182
  "POST /api/role-interval": (req, res) => handleRoleInterval(req, res, root),
@@ -186,9 +190,19 @@ export function startGui(root, port, allInterfaces = false, token = "", watch =
186
190
  "POST /api/reset-counters": (req, res) => handleResetCounters(req, res, root),
187
191
  "POST /api/role-notes": (req, res) => handleRoleNotes(req, res, root),
188
192
  "POST /api/retire": (req, res) => handleRetire(req, res, root),
193
+ "POST /api/revert": (req, res) => handleRevert(req, res, root),
194
+ "POST /api/queue-cancel": (req, res) => handleQueueCancel(req, res, root),
195
+ "POST /api/queue-top": (req, res) => handleQueueTop(req, res, root),
196
+ "POST /api/post-review-accept": (req, res) => handlePostReviewAccept(req, res, root),
189
197
  "POST /api/restart": (req, res) => handleRestart(req, res, root),
190
198
  "POST /api/stop-schedule": (req, res) => handleStopSchedule(req, res, root),
191
199
  "POST /api/reclaim": (req, res) => handleReclaim(req, res, root),
200
+ "POST /api/kill-orphans": (req, res) => handleKillOrphans(req, res, root),
201
+ "POST /api/doctor-drop-broken-pins": (req, res) => handleDropBrokenPins(req, res, root),
202
+ "POST /api/doctor-commit-backlog": (req, res) => handleCommitBacklog(req, res, root),
203
+ "POST /api/doctor-resync-install": (req, res) => handleResyncInstall(req, res, root),
204
+ "POST /api/doctor-retire-leftovers": (req, res) => handleRetireLeftovers(req, res, root),
205
+ "POST /api/doctor-reprobe": (req, res) => handleDoctorReprobe(req, res, root),
192
206
  "POST /api/abort": (req, res) => handleAbort(req, res, root),
193
207
  "POST /api/pause-role": (req, res) => handlePauseRole(req, res, root),
194
208
  };
@@ -240,8 +254,15 @@ export function startGui(root, port, allInterfaces = false, token = "", watch =
240
254
  if (route)
241
255
  await route(req, res, target);
242
256
  else {
257
+ // Unknown path: a bare "not found" hides which path failed, so name the offending
258
+ // target, JSON.stringify-quoted like every sibling error-answer (the quote-the-
259
+ // offending-value convention). Plain text, not sendJson's {error}, on purpose: this
260
+ // also answers non-/api requests (a stale /api route, a proxy's /favicon.ico), and the
261
+ // client's apiError treats a plain-text 404 body as a bare message. `pathname` is null
262
+ // only for a target the URL parser rejected, so fall back to the raw url. No "no such
263
+ // route" claim: a known path with a wrong method lands here too (GET /api/stop-schedule).
243
264
  res.writeHead(404, { "content-type": "text/plain" });
244
- res.end("not found");
265
+ res.end(`not found: ${JSON.stringify(pathname ?? req.url ?? "/")}`);
245
266
  }
246
267
  }
247
268
  catch (err) {
@@ -5,7 +5,7 @@
5
5
  * `wakeInSecondsMs` body rules they share. Each handler adapts HTTP onto the domain work one
6
6
  * layer down (team/team-state, operator-intent) and touches no socket beyond its own `res`.
7
7
  */
8
- import { baseRoleOf, INSTANCE_ROLES } from "../roles/loop-ids.js";
8
+ import { baseRoleOf, INSTANCE_ROLES } from "../roles/runner-ids.js";
9
9
  import { normalizePauseReason, pauseTeam, pauseRole, resumeTeam, resumeRole } from "../team/team-state.js";
10
10
  import { cancelWakes, PAUSE_FOR_MAX_MS, requestWake } from "../operator/operator-intent.js";
11
11
  import { requirePausedFlag, validRoleIds } from "./gui-args.js";
@@ -127,13 +127,13 @@ export async function handleWakeCancel(req, res, root) {
127
127
  const body = await readRoleBody(req, res, '{"role": "feature"}', root, true);
128
128
  if (!body)
129
129
  return;
130
- sendJson(res, 200, { ok: true, message: cancelWakes(root, body.role) });
130
+ sendJson(res, 200, { ok: true, message: cancelWakes(root, body.role === undefined ? undefined : [body.role]) });
131
131
  }
132
- /** Resume a row: lift every marker key that pauses this loop id (its own, its base role's, and
133
- * instance 1's `<role>-1`), since the row shows Resume whenever `loopPaused` holds and the key
132
+ /** Resume a row: lift every marker key that pauses this role id (its own, its base role's, and
133
+ * instance 1's `<role>-1`), since the row shows Resume whenever `runnerPaused` holds and the key
134
134
  * actually in the marker may differ from the row's id. Reports whether any key was lifted. */
135
- function resumeLoopKeys(root, loopId) {
136
- const keys = new Set([loopId, baseRoleOf(loopId), ...(INSTANCE_ROLES.has(loopId) ? [`${loopId}-1`] : [])]);
135
+ function resumeRunnerKeys(root, runnerId) {
136
+ const keys = new Set([runnerId, baseRoleOf(runnerId), ...(INSTANCE_ROLES.has(runnerId) ? [`${runnerId}-1`] : [])]);
137
137
  let changed = false;
138
138
  for (const key of keys)
139
139
  changed = resumeRole(root, key) || changed;
@@ -159,6 +159,6 @@ export async function handlePauseRole(req, res, root) {
159
159
  return;
160
160
  const changed = value
161
161
  ? pauseRole(root, body.role, untilMs)
162
- : resumeLoopKeys(root, body.role);
162
+ : resumeRunnerKeys(root, body.role);
163
163
  sendJson(res, 200, { ok: true, changed, paused: value, ...(untilMs === undefined ? {} : { until: untilMs }) });
164
164
  }
@@ -13,7 +13,7 @@ export function badRequest(res, message) {
13
13
  sendJson(res, 400, { error: message });
14
14
  }
15
15
  /** Send 200 with the {"ok":true,"status":"gone"} body every file-addressed handler that answers
16
- * for a vanished entry (the loop already dequeued it) replies with — data for the UI's flash
16
+ * for a vanished entry (the role already dequeued it) replies with — data for the UI's flash
17
17
  * line, not a server fault — so the status and the `{ ok, status }` wrapper live here instead
18
18
  * of being open-coded at each call site. */
19
19
  export function okGone(res) {