tumwater 0.4.2 → 0.4.3

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 (305) hide show
  1. package/README.md +6 -6
  2. package/dist/build-info.json +2 -2
  3. package/dist/src/agent/agent-backend.js +6 -6
  4. package/dist/src/agent/{run-agent.js → agent-run.js} +25 -12
  5. package/dist/src/agent/{run-settle.js → agent-settle.js} +48 -24
  6. package/dist/src/agent/{run-spawn.js → agent-spawn.js} +21 -12
  7. package/dist/src/agent/{run-stream.js → agent-stream.js} +4 -4
  8. package/dist/src/agent/backend-traits.js +2 -2
  9. package/dist/src/agent/claude/claude-account.js +1 -8
  10. package/dist/src/agent/claude/claude-backend.js +3 -3
  11. package/dist/src/agent/claude/claude-env.js +27 -31
  12. package/dist/src/agent/claude/claude-stream.js +111 -54
  13. package/dist/src/agent/codex/codex-account.js +9 -0
  14. package/dist/src/agent/codex/codex-backend.js +2 -2
  15. package/dist/src/agent/codex/codex-env.js +28 -15
  16. package/dist/src/agent/codex/codex-hook-trust.js +39 -20
  17. package/dist/src/agent/codex/codex-rollout.js +93 -56
  18. package/dist/src/agent/codex/codex-stream.js +1 -1
  19. package/dist/src/agent/env-scrub.js +18 -0
  20. package/dist/src/agent/image-input.js +68 -11
  21. package/dist/src/agent/notes-shim.js +2 -2
  22. package/dist/src/agent/opencode/opencode-backend.js +2 -2
  23. package/dist/src/agent/opencode/opencode-catalog.js +50 -27
  24. package/dist/src/agent/opencode/opencode-config.js +32 -14
  25. package/dist/src/agent/opencode/opencode-env.js +12 -13
  26. package/dist/src/agent/opencode/opencode-stream.js +47 -25
  27. package/dist/src/agent/session-ledger.js +1 -1
  28. package/dist/src/agent/subscription-account.js +3 -3
  29. package/dist/src/backlog/backlog-cli-view.js +81 -41
  30. package/dist/src/backlog/backlog-cli.js +57 -26
  31. package/dist/src/backlog/backlog-eligibility.js +58 -102
  32. package/dist/src/backlog/backlog-md.js +5 -5
  33. package/dist/src/backlog/backlog-parts.js +65 -27
  34. package/dist/src/backlog/backlog-release.js +12 -12
  35. package/dist/src/backlog/backlog-structure.js +114 -61
  36. package/dist/src/backlog/backlog.js +1 -1
  37. package/dist/src/baseline/main-baseline.js +148 -84
  38. package/dist/src/budget/budget-fallback-view.js +100 -243
  39. package/dist/src/budget/budget-wiring.js +29 -65
  40. package/dist/src/budget/fallback-breaker.js +2 -2
  41. package/dist/src/build/build-check-detect.js +43 -14
  42. package/dist/src/build/build-check-events.js +2 -2
  43. package/dist/src/build/build-check-scoped.js +40 -16
  44. package/dist/src/build/build-check.js +13 -5
  45. package/dist/src/cli/cli-command-args.js +89 -52
  46. package/dist/src/cli/cli-flag-specs.js +42 -22
  47. package/dist/src/cli/cli-init.js +34 -12
  48. package/dist/src/cli/cli-query-commands.js +1 -1
  49. package/dist/src/cli/cli-repo-gate.js +2 -2
  50. package/dist/src/cli/cli-start.js +91 -58
  51. package/dist/src/cli/completion.js +82 -46
  52. package/dist/src/cli/config-commands.js +82 -71
  53. package/dist/src/cli/help.js +4 -6
  54. package/dist/src/cli/log-commands.js +43 -23
  55. package/dist/src/cli/notify-command.js +2 -2
  56. package/dist/src/cli/question-commands.js +86 -60
  57. package/dist/src/cli.js +181 -135
  58. package/dist/src/collections.js +31 -16
  59. package/dist/src/concurrency/check-slots.js +70 -0
  60. package/dist/src/concurrency/lock.js +22 -0
  61. package/dist/src/concurrency/run-permit.js +49 -0
  62. package/dist/src/concurrency/semaphore.js +46 -250
  63. package/dist/src/config/config-editable-keys.js +4 -7
  64. package/dist/src/config/config-fallbacks.js +81 -101
  65. package/dist/src/config/config-field-checks.js +66 -37
  66. package/dist/src/config/config-keys.js +5 -20
  67. package/dist/src/config/config-live.js +4 -28
  68. package/dist/src/config/{model-selector.js → config-model-selector.js} +4 -4
  69. package/dist/src/config/config-request.js +153 -102
  70. package/dist/src/config/config-schema.js +9 -11
  71. package/dist/src/config/config-selector-checks.js +1 -1
  72. package/dist/src/config/config-validation-agents.js +2 -2
  73. package/dist/src/config/config-validation-roles.js +4 -52
  74. package/dist/src/config/config-validation.js +4 -38
  75. package/dist/src/config/config-views.js +9 -34
  76. package/dist/src/config/config-write.js +6 -23
  77. package/dist/src/config/config.js +4 -5
  78. package/dist/src/doctor/doctor-backlog-bugs.js +7 -6
  79. package/dist/src/doctor/doctor-backlog-plans.js +24 -24
  80. package/dist/src/doctor/doctor-backlog.js +7 -5
  81. package/dist/src/doctor/doctor-check-names.js +3 -6
  82. package/dist/src/doctor/doctor-checks.js +5 -5
  83. package/dist/src/doctor/doctor-claude-checks.js +44 -28
  84. package/dist/src/doctor/doctor-codex-checks.js +6 -6
  85. package/dist/src/doctor/doctor-contention-checks.js +44 -112
  86. package/dist/src/doctor/doctor-fallback-checks.js +2 -2
  87. package/dist/src/doctor/doctor-holds.js +6 -45
  88. package/dist/src/doctor/doctor-install.js +1 -1
  89. package/dist/src/doctor/doctor-launch-services.js +1 -1
  90. package/dist/src/doctor/doctor-model-checks.js +178 -94
  91. package/dist/src/doctor/doctor-notify.js +2 -2
  92. package/dist/src/doctor/doctor-opencode-checks.js +5 -4
  93. package/dist/src/doctor/doctor-orphans.js +120 -20
  94. package/dist/src/doctor/{outcome.js → doctor-outcome.js} +7 -0
  95. package/dist/src/doctor/doctor-pi-checks.js +2 -2
  96. package/dist/src/doctor/doctor-principles.js +3 -3
  97. package/dist/src/doctor/doctor-project-checks.js +3 -3
  98. package/dist/src/doctor/doctor-role-notes.js +1 -1
  99. package/dist/src/doctor/doctor.js +8 -11
  100. package/dist/src/events/event-format.js +30 -54
  101. package/dist/src/events/event-labels.js +1 -5
  102. package/dist/src/events/event-legacy.js +1 -3
  103. package/dist/src/events/{notify.js → event-notify.js} +2 -2
  104. package/dist/src/events/event-read.js +1 -1
  105. package/dist/src/failure/failure-cluster.js +6 -6
  106. package/dist/src/failure/failure-data.js +8 -4
  107. package/dist/src/failure/failure-render.js +44 -34
  108. package/dist/src/failure/failure-state-change.js +4 -34
  109. package/dist/src/failure/{time-spend.js → failure-time-spend.js} +117 -84
  110. package/dist/src/files/files.js +30 -0
  111. package/dist/src/files/json-object.js +8 -8
  112. package/dist/src/files/stat-cache.js +12 -8
  113. package/dist/src/gates/budget-gates.js +85 -84
  114. package/dist/src/gates/gate-polls.js +27 -68
  115. package/dist/src/gates/pause-gates.js +16 -2
  116. package/dist/src/gates/readiness.js +1 -1
  117. package/dist/src/gates/role-cap-gates.js +44 -35
  118. package/dist/src/gates/{startup-gate.js → startup-gates.js} +7 -7
  119. package/dist/src/gates/{streak-gate.js → streak-gates.js} +75 -52
  120. package/dist/src/git/git.js +75 -45
  121. package/dist/src/git/worktree-pool.js +3 -6
  122. package/dist/src/gui/gui-admin-endpoints.js +3 -3
  123. package/dist/src/gui/gui-backlog-commands.js +4 -4
  124. package/dist/src/gui/gui-backlog-endpoints.js +61 -41
  125. package/dist/src/gui/gui-command.js +43 -24
  126. package/dist/src/gui/gui-history-endpoints.js +100 -52
  127. package/dist/src/gui/gui-operator-commands.js +22 -23
  128. package/dist/src/gui/gui-prompt-commands.js +23 -23
  129. package/dist/src/gui/gui-report-endpoints.js +1 -1
  130. package/dist/src/history/history-data.js +71 -44
  131. package/dist/src/history/history-queued.js +49 -27
  132. package/dist/src/history/history.js +51 -33
  133. package/dist/src/inbox/prompt-commands.js +59 -42
  134. package/dist/src/init/init.js +88 -40
  135. package/dist/src/merge/merge-backlog-conflicts.js +1 -1
  136. package/dist/src/merge/merge-core.js +1 -1
  137. package/dist/src/merge/merge-drain.js +8 -11
  138. package/dist/src/merge/merge-pipeline.js +6 -7
  139. package/dist/src/merge/merge-post-review-drain.js +10 -13
  140. package/dist/src/merge/merge-requeue.js +1 -1
  141. package/dist/src/merge/merge-slot.js +0 -8
  142. package/dist/src/merge/merge-verify.js +8 -18
  143. package/dist/src/notes-cli.js +52 -42
  144. package/dist/src/operator/operator-commands.js +76 -44
  145. package/dist/src/operator/operator-intent.js +3 -3
  146. package/dist/src/orchestrator/orchestrator-launch.js +31 -63
  147. package/dist/src/orchestrator/orchestrator-poll.js +27 -32
  148. package/dist/src/orchestrator/orchestrator.js +8 -21
  149. package/dist/src/orchestrator/scheduling-admit.js +101 -68
  150. package/dist/src/orchestrator/scheduling-scope.js +1 -1
  151. package/dist/src/orchestrator/scheduling-skip.js +1 -1
  152. package/dist/src/orchestrator/startup-migrations.js +1 -1
  153. package/dist/src/paths.js +8 -7
  154. package/dist/src/pi/pi-args.js +5 -2
  155. package/dist/src/pi/pi-backend.js +2 -2
  156. package/dist/src/pi/pi-bin.js +3 -3
  157. package/dist/src/pi/pi-event-line.js +1 -1
  158. package/dist/src/pi/pi-models.js +43 -29
  159. package/dist/src/pi/pi-settings.js +43 -20
  160. package/dist/src/pi/pi-stream.js +32 -6
  161. package/dist/src/pi/pi-watchdogs.js +12 -5
  162. package/dist/src/pi/pi.js +2 -2
  163. package/dist/src/pi-extension/context-shake.js +32 -20
  164. package/dist/src/pi-extension/kill-guard.js +69 -0
  165. package/dist/src/process/process-group.js +49 -5
  166. package/dist/src/process/process.js +8 -8
  167. package/dist/src/process/run-marker.js +31 -13
  168. package/dist/src/process/supervisor.js +40 -28
  169. package/dist/src/prompt/dialect.js +1 -1
  170. package/dist/src/prompt/gate-notes.js +2 -2
  171. package/dist/src/prompt/notes-backlog.js +66 -37
  172. package/dist/src/prompt/principles.js +6 -4
  173. package/dist/src/prompt/prompt-followup.js +12 -4
  174. package/dist/src/prompt/prompt.js +88 -38
  175. package/dist/src/report/report-data.js +53 -37
  176. package/dist/src/report/report-fold.js +16 -9
  177. package/dist/src/report/report-render.js +21 -194
  178. package/dist/src/report/report-since-data.js +4 -3
  179. package/dist/src/report/report-since-render.js +173 -0
  180. package/dist/src/report/report-usage-fold.js +8 -8
  181. package/dist/src/report/report.js +46 -22
  182. package/dist/src/review/post-merge-review-render.js +9 -3
  183. package/dist/src/review/post-merge-review.js +1 -1
  184. package/dist/src/review/review-precheck.js +11 -1
  185. package/dist/src/review/review.js +40 -153
  186. package/dist/src/review/secret-leaks.js +26 -16
  187. package/dist/src/roles/role-catalog.js +11 -3
  188. package/dist/src/roles/role-guidance.js +16 -12
  189. package/dist/src/roles/role-render.js +1 -14
  190. package/dist/src/roles/role-view.js +9 -21
  191. package/dist/src/run/acceptance-greps.js +88 -45
  192. package/dist/src/run/run-apply.js +12 -6
  193. package/dist/src/run/run-detail-data.js +121 -68
  194. package/dist/src/run/run-detail-render.js +92 -35
  195. package/dist/src/run/run-detail.js +72 -41
  196. package/dist/src/run/run-prompt.js +63 -50
  197. package/dist/src/run/run-resume.js +76 -29
  198. package/dist/src/run/run-stage.js +135 -84
  199. package/dist/src/run/run-timing.js +8 -2
  200. package/dist/src/run/run-usage.js +31 -1
  201. package/dist/src/run/run-verdict.js +119 -50
  202. package/dist/src/run/stage-check.js +49 -32
  203. package/dist/src/run/stage-checks-shared.js +28 -0
  204. package/dist/src/run/stage-name-checks.js +111 -92
  205. package/dist/src/run/stage-path-checks.js +69 -42
  206. package/dist/src/run/stage-prose-checks.js +55 -40
  207. package/dist/src/runner/runner-outcome.js +6 -1
  208. package/dist/src/runner/runner-pi.js +3 -10
  209. package/dist/src/runner/runner-recovery.js +1 -1
  210. package/dist/src/runner/{revision.js → runner-revision.js} +1 -1
  211. package/dist/src/runner/runner-run.js +97 -35
  212. package/dist/src/runner/runner-state-load.js +12 -9
  213. package/dist/src/runner/runner.js +41 -25
  214. package/dist/src/scheduling/claims.js +0 -4
  215. package/dist/src/scheduling/scheduling.js +53 -66
  216. package/dist/src/status/status-data.js +2 -2
  217. package/dist/src/status/status-role-notes.js +2 -2
  218. package/dist/src/status/status-roles.js +9 -17
  219. package/dist/src/team/{error-storm.js → team-error-storm.js} +1 -1
  220. package/dist/src/team/{failure-spread.js → team-failure-spread.js} +5 -5
  221. package/dist/src/team/team-hold.js +98 -65
  222. package/dist/src/team/{orchestrator-info.js → team-orchestrator-info.js} +2 -15
  223. package/dist/src/team/team-polls.js +28 -126
  224. package/dist/src/team/{reclaim.js → team-reclaim.js} +61 -31
  225. package/dist/src/team/team-state.js +4 -13
  226. package/dist/src/text/markdown.js +1 -1
  227. package/dist/src/text/phrases.js +20 -15
  228. package/dist/src/text/text.js +3 -3
  229. package/dist/src/ui/alert-feeds.js +49 -73
  230. package/dist/src/ui/badges.js +3 -13
  231. package/dist/src/ui/gui/gui-client-boot.js +2 -2
  232. package/dist/src/ui/gui/gui-client-composer.js +1 -1
  233. package/dist/src/ui/gui/gui-client-drawer-config.js +7 -17
  234. package/dist/src/ui/gui/gui-client-drawer.js +1 -1
  235. package/dist/src/ui/gui/gui-client-history.js +28 -14
  236. package/dist/src/ui/gui/gui-client-model.js +0 -12
  237. package/dist/src/ui/gui/gui-client-pending.js +7 -6
  238. package/dist/src/ui/gui/gui-client-report-chart.js +5 -5
  239. package/dist/src/ui/gui/gui-client-report.js +1 -1
  240. package/dist/src/ui/gui/gui-client-roles.js +0 -1
  241. package/dist/src/ui/gui/gui-client-settings.js +43 -84
  242. package/dist/src/ui/gui/gui-client-team.js +4 -4
  243. package/dist/src/ui/gui/gui-client.js +7 -1
  244. package/dist/src/ui/progress-data.js +53 -40
  245. package/dist/src/ui/run-progress-model.js +9 -2
  246. package/dist/src/ui/status-model.js +2 -24
  247. package/dist/src/ui/status-payload.js +3 -7
  248. package/dist/src/ui/status-render.js +5 -9
  249. package/dist/src/ui/team-alert-backlog.js +6 -6
  250. package/dist/src/ui/team-alert-status.js +9 -170
  251. package/dist/src/ui/team-alert-tail.js +19 -215
  252. package/dist/src/ui/team-alerts.js +7 -8
  253. package/dist/src/ui/transcript-run.js +27 -16
  254. package/dist/src/ui/tui/tui-editor-answer.js +12 -10
  255. package/dist/src/ui/tui/tui-editor-attach.js +4 -3
  256. package/dist/src/ui/tui/tui-editor-backends.js +4 -3
  257. package/dist/src/ui/tui/tui-editor-brief.js +6 -9
  258. package/dist/src/ui/tui/tui-editor-budget.js +4 -3
  259. package/dist/src/ui/tui/tui-editor-config.js +80 -68
  260. package/dist/src/ui/tui/tui-editor-entry.js +12 -20
  261. package/dist/src/ui/tui/tui-editor-pause.js +51 -57
  262. package/dist/src/ui/tui/tui-editor-prompt.js +9 -13
  263. package/dist/src/ui/tui/tui-editor-queued.js +11 -14
  264. package/dist/src/ui/tui/tui-editor-quiet.js +4 -3
  265. package/dist/src/ui/tui/tui-editor-release.js +4 -3
  266. package/dist/src/ui/tui/tui-editor-retire.js +7 -7
  267. package/dist/src/ui/tui/tui-editor-role-enabled.js +4 -3
  268. package/dist/src/ui/tui/tui-editor-role-file.js +4 -4
  269. package/dist/src/ui/tui/tui-editor-role-key.js +4 -3
  270. package/dist/src/ui/tui/tui-editor-role-model.js +97 -15
  271. package/dist/src/ui/tui/tui-editor-search.js +4 -3
  272. package/dist/src/ui/tui/tui-editor-session.js +17 -4
  273. package/dist/src/ui/tui/tui-editors.js +1 -7
  274. package/dist/src/ui/tui/tui-frame.js +182 -134
  275. package/dist/src/ui/tui/tui-guard.js +20 -0
  276. package/dist/src/ui/tui/tui-input.js +159 -92
  277. package/dist/src/ui/tui/tui-keymap.js +51 -29
  278. package/dist/src/ui/tui/tui-keys.js +1 -1
  279. package/dist/src/ui/tui/tui-pane-activity.js +3 -3
  280. package/dist/src/ui/tui/tui-pane-backlog.js +74 -36
  281. package/dist/src/ui/tui/tui-pane-ctx.js +1 -1
  282. package/dist/src/ui/tui/tui-pane-health.js +252 -228
  283. package/dist/src/ui/tui/tui-pane-history.js +61 -70
  284. package/dist/src/ui/tui/tui-pane-pending.js +284 -247
  285. package/dist/src/ui/tui/tui-pane-queued.js +25 -27
  286. package/dist/src/ui/tui/tui-pane-report.js +2 -1
  287. package/dist/src/ui/tui/tui-pane-session.js +11 -7
  288. package/dist/src/ui/tui/tui-pane-transcript.js +19 -31
  289. package/dist/src/ui/tui/tui-pane.js +14 -11
  290. package/dist/src/ui/tui/tui-panes.js +29 -32
  291. package/dist/src/ui/tui/tui.js +3 -4
  292. package/dist/src/verdict/fix-claim.js +76 -54
  293. package/dist/src/verdict/refusal.js +1 -1
  294. package/package.json +5 -5
  295. package/dist/src/concurrency/provider-lease.js +0 -105
  296. package/dist/src/runner/model-fallback.js +0 -76
  297. package/dist/src/runner/runner-fallback.js +0 -66
  298. package/dist/src/ui/tui/tui-editor-claude-reserve.js +0 -24
  299. package/dist/src/ui/tui/tui-editor-provider-caps.js +0 -27
  300. /package/dist/src/backlog/{question-answer.js → backlog-question-answer.js} +0 -0
  301. /package/dist/src/doctor/{probe.js → doctor-probe.js} +0 -0
  302. /package/dist/src/gates/{disk-gate.js → disk-gates.js} +0 -0
  303. /package/dist/src/operator/{retire.js → operator-retire.js} +0 -0
  304. /package/dist/src/operator/{revert.js → operator-revert.js} +0 -0
  305. /package/dist/src/runner/{leftover.js → runner-leftover.js} +0 -0
@@ -3,15 +3,17 @@ import { betweenWindow } from "../../cli/cli-args.js";
3
3
  import { HISTORY_DEFAULT_RUNS, HISTORY_MAX_RUNS, historyClass, readRunRows, readRunRowsSince, summarizeRunRows, summarizeRunRowsByModel, runRowsMatchingGrep, runRowsOnModels, } from "../../history/history-data.js";
4
4
  import { renderModelSummary, renderSummary } from "../../history/history-render.js";
5
5
  import { historyPaneText } from "./tui-history.js";
6
+ import { guardError } from "./tui-guard.js";
6
7
  import { readRunDetail } from "../../run/run-detail-data.js";
7
8
  import { renderRunDetail, runTranscriptLines } from "../../run/run-detail-render.js";
8
- import { revertFollowUp, runRevertSha } from "../../operator/revert.js";
9
+ import { revertFollowUp, runRevertSha } from "../../operator/operator-revert.js";
9
10
  import { shortSha } from "../../text/format.js";
10
11
  import { plural } from "../../text/phrases.js";
11
12
  import { pageMarkdownBody } from "./tui-backlog.js";
12
13
  import { pageDir } from "./tui-keymap.js";
13
14
  import { promptLineFree } from "./tui-pane-ctx.js";
14
- import { nextInCycle, cycleLabel, HISTORY_WINDOWS, HISTORY_RESULTS } from "./tui-pane-session.js";
15
+ import { flashReject } from "./tui-guard.js";
16
+ import { paneAtHead, nextInCycle, cycleLabel, HISTORY_WINDOWS, HISTORY_RESULTS } from "./tui-pane-session.js";
15
17
  /** The bounds `readRunRowsSince` reads for a trailing window of `windowMs` stepped `step` window
16
18
  * lengths back: step 0 (or no window) is the trailing window, step k the window (k+1)*len to k*len
17
19
  * ago, the `history --since --until` pair. */
@@ -21,13 +23,14 @@ export function historyWindowBounds(windowMs, step) {
21
23
  return { sinceMs: (step + 1) * windowMs, untilMs: step * windowMs };
22
24
  }
23
25
  /** The History pane (view roleIds.length + 4) of the TUI (src/ui/tui/tui.tsx): the session
24
- * window (Ctrl+S), outcome filter (Ctrl+O), exact-role scope (Ctrl+G), free-text search (`/`),
25
- * and the Ctrl+N completed-run trail (Ctrl+P steps it to older runs, Ctrl+W shows its commit
26
- * patch, Ctrl+V twice reverts the shown run's merged change), each with its cache and
27
- * body window. With the trail off, Ctrl+P steps the window back by its own length (the
28
- * `history --since --until` window) and Ctrl+S returns to the trailing window. Split out of the
29
- * pane-navigation monolith; it owns the pane's window/result/scope/search/trail state and the
30
- * arms that touch them. */
26
+ * window (Ctrl+S), outcome filter (Ctrl+O), model filter (Ctrl+X), summary toggle (Ctrl+Y),
27
+ * exact-role scope (Ctrl+G), free-text search (`/`), the one-press newest-failure jump
28
+ * (Ctrl+L), and the Ctrl+N completed-run trail (Ctrl+P steps it to older runs, Ctrl+R cycles
29
+ * its agent transcript, Ctrl+W shows its commit patch, Ctrl+V twice reverts the shown run's
30
+ * merged change), each with its cache and body window. With the trail off, Ctrl+P steps the
31
+ * window back by its own length (the `history --since --until` window) and Ctrl+S returns to
32
+ * the trailing window. Split out of the pane-navigation monolith; it owns the pane's
33
+ * window/result/model/summary/scope/search/trail state and the arms that touch them. */
31
34
  export function createHistoryPane(session) {
32
35
  // The History pane's session trailing window (Ctrl+S), a HISTORY_WINDOWS length or null for
33
36
  // the default newest-N read. Session-only like the view/scroll state; the next Ctrl+T into
@@ -82,6 +85,20 @@ export function createHistoryPane(session) {
82
85
  let trailRun = null;
83
86
  let reverting = false; // a revert preview or commit is in flight; a held Ctrl+V starts no second
84
87
  let trailGen = 0; // bumped at every trail read or reset; a stat resolution applies only to its own gen
88
+ /** Drop the on-screen run trail and its snapshot: the shared teardown the pane's three
89
+ * History-only exits run — the Ctrl+N toggle-off arm, the Ctrl+L newest-failure jump, and
90
+ * the pane's reset on a view cycle. It bumps trailGen so an in-flight stat resolution from
91
+ * the closed trail cannot repaint the pane. */
92
+ const dropTrail = () => {
93
+ trailGen++;
94
+ trailMode = false;
95
+ trailCache = null;
96
+ trailIndex = 0;
97
+ trailTranscript = "off";
98
+ trailPatch = false;
99
+ trailPatchText = null;
100
+ trailGrep = null;
101
+ };
85
102
  /** The pane's row selection: scope, then window, then search, then outcome class — the order
86
103
  * `tumwater history` applies them. Returns the raw read's coverage flag, the count after the
87
104
  * search (so an empty body can blame the filter that emptied the set: `afterGrep > 0` means
@@ -179,18 +196,16 @@ export function createHistoryPane(session) {
179
196
  // or on a throw, which is flashed): the two outputs `tumwater history --transcript` prints.
180
197
  const loadTranscript = () => {
181
198
  trailTranscriptText = null;
182
- if (trailTranscript === "off" || trailRun === null)
199
+ const run = trailRun;
200
+ if (run === null || trailTranscript === "off")
183
201
  return;
184
- try {
185
- const { found, note } = runTranscriptLines(session.root, trailRun.role, trailRun.run, trailRun.detail, {
202
+ guardError(session, () => {
203
+ const { found, note } = runTranscriptLines(session.root, run.role, run.run, run.detail, {
186
204
  includePrompts: trailTranscript === "prompts",
187
205
  grep: trailGrep ?? undefined,
188
206
  });
189
207
  trailTranscriptText = found.length > 0 ? found.join("\n") : note;
190
- }
191
- catch (err) {
192
- session.flashError(err);
193
- }
208
+ });
194
209
  };
195
210
  // Resolve one async trail part (the run commit's stat or patch) through the session, and, if
196
211
  // the trail is still current (`trailMode`, not superseded by a newer `trailGen`, and `keep`
@@ -310,7 +325,7 @@ export function createHistoryPane(session) {
310
325
  }
311
326
  const followUp = revertFollowUp(r.subject);
312
327
  session.flashMessage(`reverted ${shortSha(sha)}: main is now ${shortSha(r.headSha)}${followUp === null ? "" : `; ${followUp}`}`);
313
- }, (err) => session.flashError(err)).finally(() => {
328
+ }, flashReject(session)).finally(() => {
314
329
  reverting = false;
315
330
  session.armedRevert = null;
316
331
  session.requestRender();
@@ -335,7 +350,7 @@ export function createHistoryPane(session) {
335
350
  session.revertArmed = p.sha;
336
351
  session.flashMessage(`press Ctrl+V again to revert ${shortSha(p.sha)} ${p.subject} (${plural(p.paths.length, "file")}) on ${p.primary} — any other key cancels`);
337
352
  }
338
- }, (err) => session.flashError(err)).finally(() => {
353
+ }, flashReject(session)).finally(() => {
339
354
  reverting = false;
340
355
  session.requestRender();
341
356
  });
@@ -357,14 +372,7 @@ export function createHistoryPane(session) {
357
372
  if (trailMode) {
358
373
  // Toggle the trail off (Ctrl+N on the trail view): drop the trail snapshot. The
359
374
  // trailGen bump keeps an in-flight stat from the old trail from repainting.
360
- trailGen++;
361
- trailMode = false;
362
- trailCache = null;
363
- trailIndex = 0;
364
- trailTranscript = "off";
365
- trailPatch = false;
366
- trailPatchText = null;
367
- trailGrep = null;
375
+ dropTrail();
368
376
  }
369
377
  else {
370
378
  // Toggle the trail on: read the pane-scoped newest completed run. A scope holding
@@ -375,8 +383,7 @@ export function createHistoryPane(session) {
375
383
  if (loadTrail(() => session.flashMessage(empty)))
376
384
  trailMode = true;
377
385
  }
378
- session.paneScroll = 0; // either way the pane starts at its head
379
- session.requestRender();
386
+ paneAtHead(session);
380
387
  return true;
381
388
  };
382
389
  const historyNewestFailure = (ctx) => {
@@ -405,22 +412,14 @@ export function createHistoryPane(session) {
405
412
  historySummary = null;
406
413
  // Drop any on-screen trail the way Ctrl+N's toggle-off arm does (the gen bump keeps an
407
414
  // in-flight stat from the old trail from repainting).
408
- trailGen++;
409
- trailMode = false;
410
- trailCache = null;
411
- trailIndex = 0;
412
- trailTranscript = "off";
413
- trailPatch = false;
414
- trailPatchText = null;
415
- trailGrep = null;
415
+ dropTrail();
416
416
  recompute();
417
417
  // historyWindow null + historyResult "problems": loadTrail reads
418
418
  // readRunRows(root, HISTORY_MAX_RUNS, null) and takes .filtered[0] — the newest failing
419
419
  // run of any role, exactly what the dashboard's Newest failure button and the CLI open.
420
420
  if (loadTrail(() => session.flashMessage("no failing run in the scanned window")))
421
421
  trailMode = true;
422
- session.paneScroll = 0;
423
- session.requestRender();
422
+ paneAtHead(session);
424
423
  return true;
425
424
  };
426
425
  const historyStepBack = (ctx) => {
@@ -504,8 +503,7 @@ export function createHistoryPane(session) {
504
503
  loadTrailStat(trailRun.detail);
505
504
  composeTrail();
506
505
  }
507
- session.paneScroll = 0;
508
- session.requestRender();
506
+ paneAtHead(session);
509
507
  return true;
510
508
  };
511
509
  const historyRevertArm = (ctx) => {
@@ -633,29 +631,29 @@ export function createHistoryPane(session) {
633
631
  }
634
632
  return false;
635
633
  };
634
+ const ctrlRoutes = {
635
+ n: historyTrailToggle,
636
+ l: historyNewestFailure,
637
+ p: historyStepBack,
638
+ r: historyTranscriptCycle,
639
+ w: historyPatchToggle,
640
+ v: historyRevertArm,
641
+ g: historyScopeCycle,
642
+ s: historyWindowCycle,
643
+ o: historyResultCycle,
644
+ x: historyModelCycle,
645
+ y: historySummaryCycle,
646
+ };
647
+ const ctrlRoute = (key, ctx) => {
648
+ if (!key.ctrl || key.name === undefined)
649
+ return null;
650
+ const route = ctrlRoutes[key.name];
651
+ return route === undefined ? null : route(ctx);
652
+ };
636
653
  const handleKey = (key, ctx) => {
637
- if (key.ctrl && key.name === "n")
638
- return historyTrailToggle(ctx);
639
- if (key.ctrl && key.name === "l")
640
- return historyNewestFailure(ctx);
641
- if (key.ctrl && key.name === "p")
642
- return historyStepBack(ctx);
643
- if (key.ctrl && key.name === "r")
644
- return historyTranscriptCycle(ctx);
645
- if (key.ctrl && key.name === "w")
646
- return historyPatchToggle(ctx);
647
- if (key.ctrl && key.name === "v")
648
- return historyRevertArm(ctx);
649
- if (key.ctrl && key.name === "g")
650
- return historyScopeCycle(ctx);
651
- if (key.ctrl && key.name === "s")
652
- return historyWindowCycle(ctx);
653
- if (key.ctrl && key.name === "o")
654
- return historyResultCycle(ctx);
655
- if (key.ctrl && key.name === "x")
656
- return historyModelCycle(ctx);
657
- if (key.ctrl && key.name === "y")
658
- return historySummaryCycle(ctx);
654
+ const ctrl = ctrlRoute(key, ctx);
655
+ if (ctrl !== null)
656
+ return ctrl;
659
657
  const page = pageDir(key.name);
660
658
  if (page !== null)
661
659
  return historyTrailPage(page);
@@ -666,14 +664,7 @@ export function createHistoryPane(session) {
666
664
  enter: recompute,
667
665
  reset() {
668
666
  // A cycle away leaves the run trail (which is History-only) and drops its snapshot too.
669
- trailGen++;
670
- trailMode = false;
671
- trailCache = null;
672
- trailIndex = 0;
673
- trailTranscript = "off";
674
- trailPatch = false;
675
- trailPatchText = null;
676
- trailGrep = null;
667
+ dropTrail();
677
668
  session.revertArmed = null;
678
669
  session.armedRevert = null;
679
670
  },