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
@@ -0,0 +1,320 @@
1
+ import { publishInfoFields } from "../team/orchestrator-info.js";
2
+ import { runnerEnabled } from "../roles/runner-ids.js";
3
+ import { DIRECTOR_ROLE } from "../roles/roles.js";
4
+ import { reviewHoldKey, pollDeferralInputs, pollRunnerReasons } from "./orchestrator-scheduling.js";
5
+ import { seamConcurrencyKey } from "../config/config-views.js";
6
+ import { launchDueRuns } from "./orchestrator-launch.js";
7
+ import { branchHead, currentBranch } from "../git/git.js";
8
+ import { queuedMergeFiles, queuedMergeRoles } from "../merge/merge-queue.js";
9
+ import { requeueMainRedPin } from "../merge/merge-requeue.js";
10
+ import { drainMergeQueue, settleAbortedApproved } from "../merge/merge-drain.js";
11
+ import { abortableMerges, mergeTasks } from "../merge/merge-pipeline.js";
12
+ import { TUMWATER_SOURCE } from "../events/events.js";
13
+ import { consumeAbortRequests, consumeReclaimRequest, consumeRestartRequest, consumeResetRequest, consumeWakeRequest, } from "../operator/operator-requests.js";
14
+ import { checkPermitSnapshot } from "../concurrency/check-permit.js";
15
+ import { slotPoolSnapshot } from "../git/worktree-pool.js";
16
+ import { redeployTarget } from "../baseline/main-baseline.js";
17
+ import { p75RunDurationMs } from "../run/run-timing.js";
18
+ import { pollTeamGates } from "../gates/gate-polls.js";
19
+ import { heldProviders, windowHeldProviders } from "../team/team-hold.js";
20
+ import { workReserveCount } from "../scheduling/claims.js";
21
+ export function newPollState() {
22
+ return { restart: false, holdForRestart: false, diskHeld: false, warnedBranchDivergence: false, lastReserve: 0 };
23
+ }
24
+ /** The start gate every reserved run passes the moment its permit is granted
25
+ * (runTimedRoleRun's `held`): closed while a restart is pending, and after one is decided so
26
+ * no waiter the shutdown hands a permit to starts on the build being replaced. One predicate,
27
+ * so another team-wide hold on new runs can close the same gate point. */
28
+ function runStartHeld(state) {
29
+ return state.holdForRestart || state.restart || state.diskHeld;
30
+ }
31
+ /** Live-reload, notify/retention/launchservices, CLI request markers, abort settling and the
32
+ * branch-divergence watch. Writes state.warnedBranchDivergence. */
33
+ export async function pollRequestsAndWatch(ctx, state) {
34
+ const { root, mainBranch, runners } = ctx;
35
+ // Live-reload tumwater.json — the single reload point shared by all roles.
36
+ // src/config/config-live.ts owns the last-known-good retention and the edge-triggered
37
+ // warnings/events around it.
38
+ const liveConfig = ctx.liveReload.poll();
39
+ // The notify command rides the same last-known-good reload (src/events/notify.ts): a live
40
+ // `config set notify` edit takes effect on the next poll, no restart.
41
+ ctx.notifier.update(liveConfig);
42
+ // Live session retention (the last restart-only setting): the edge-triggered
43
+ // retention_changed event, the once-per-day gate, and the prune itself live in
44
+ // src/orchestrator/retention.ts. The live config (last-known-good while the file is broken or
45
+ // missing) drives the check, like the budget gate.
46
+ ctx.retentionPruner.poll(root, liveConfig.sessionRetentionDays);
47
+ // A missing or stale opencode catalog is refetched at most once an hour while opencode is routed.
48
+ ctx.opencodeCatalogRefresh.poll(liveConfig);
49
+ // launchservicesd's Mach-port budget (src/process/launch-services.ts owns it):
50
+ // a background sample at most every 15 minutes, and a warning days before the kernel
51
+ // kills the daemon and wedges the Mac's GUI session. Never awaited — a poll does not
52
+ // wait on `top`.
53
+ void ctx.launchServicesWatch?.poll();
54
+ // Consume CLI request markers: a reset-counters request, a wake request, a forced-restart
55
+ // request, and per-role abort requests.
56
+ consumeResetRequest(root, runners);
57
+ consumeWakeRequest(root, runners);
58
+ consumeRestartRequest(root, ctx.redeploy);
59
+ consumeReclaimRequest(root, ctx.reclaim);
60
+ consumeAbortRequests(root, runners, abortableMerges(ctx.merges));
61
+ await settleAbortedApproved(root, ctx.merges);
62
+ // branchHead reads the ref files first (microsecond-scale; this runs every poll) and
63
+ // spawns `git rev-parse` only when they cannot resolve it. "" means main does not exist
64
+ // yet — isEligible treats an empty head as "no wake".
65
+ const mainHead = (await branchHead(root, mainBranch)) ?? "";
66
+ // Branch-divergence watch, once per poll: the team keeps fast-forwarding the branch it
67
+ // resolved at startup — the safe behavior, since role worktrees are based on it — and one
68
+ // warning names the divergence instead of leaving it mysterious. Back on the target branch
69
+ // re-arms the check.
70
+ const liveBranch = await currentBranch(root);
71
+ if (liveBranch !== null && liveBranch !== mainBranch) {
72
+ if (!state.warnedBranchDivergence) {
73
+ state.warnedBranchDivergence = true;
74
+ ctx.warn(`your checkout moved to ${liveBranch} — the team keeps merging into ${mainBranch}`);
75
+ }
76
+ }
77
+ else {
78
+ state.warnedBranchDivergence = false;
79
+ }
80
+ return { liveConfig, mainHead, now: Date.now() };
81
+ }
82
+ /** The team's gates and alarms, one poll of the family (src/gates/gate-polls.ts): the daily
83
+ * budget gate — with its derived-state publish and the fallback handback to the primary — the
84
+ * operator and per-role pause gates, quiet hours, the team-wide failure hold, and the two
85
+ * observational storm alarms. The family's cross-poll memory lives in gateStates, advanced in
86
+ * place. The failure hold is deliberately not among the returned verdicts — the start gate and
87
+ * the merges' startHeld read the LATEST poll's verdict at permit time from gateStates.teamHold,
88
+ * so a waiter granted its permit after later polls ran meets the hold as it stands then.
89
+ * Writes state.diskHeld. */
90
+ export function pollGatesAndHolds(ctx, state, { liveConfig, now }) {
91
+ const { root, runners, gateStates } = ctx;
92
+ const gates = pollTeamGates(gateStates, {
93
+ root,
94
+ runners,
95
+ liveConfig,
96
+ modelsPath: ctx.modelsPath,
97
+ now,
98
+ info: ctx.info,
99
+ reclaim: ctx.reclaim,
100
+ });
101
+ // The latest poll's disk verdict, hoisted for runStartHeld's permit-time reads
102
+ // (plans/disk-floor.md, part 1/4).
103
+ state.diskHeld = gates.diskHeld;
104
+ // Publish the permit pool's live state (plans/provider-concurrency.md §8): observers
105
+ // (status, TUI, GUI) read one file instead of coupling to this Semaphore, and the team
106
+ // line shows per-provider counts only while a cap map is configured. Written only when
107
+ // it changes, like budget and disk; a map-less team publishes `byKey` empty, which
108
+ // renders exactly as before. The check-permit pool rides along, so status can show checks
109
+ // running and waiting while merges stall. The workspace pool's live state rides along too:
110
+ // one small slots.json read per poll, and publishInfoFields rewrites the info file only
111
+ // when a value changed.
112
+ publishInfoFields(root, ctx.info, [
113
+ ["permits", ctx.semaphore.snapshot()],
114
+ ["checkPermits", checkPermitSnapshot()],
115
+ ["slotPool", slotPoolSnapshot(root)],
116
+ ]);
117
+ // The failure hold, keyed per provider (PLANS.md 2026-10-05): a role is held when ITS
118
+ // run model's provider stands under a hold, and every role is held when the
119
+ // reviewer's provider is (with the review gate on, nothing could merge — and the merge
120
+ // queue reads the same reviewHeld verdict). Key presence in the map is relapse
121
+ // memory, not a hold: heldProviders() reads only standing holds (`until` non-null),
122
+ // so a lifted hold never keeps blocking.
123
+ const teamHeldProviders = heldProviders(gateStates.teamHold);
124
+ const teamHeldNow = () => heldProviders(gateStates.teamHold);
125
+ // The reviewer's seam is read from the config merges actually review under — the poll's
126
+ // roleConfig, which a used-up claude window or the cap has already moved to a fallback —
127
+ // so a reviewer that left claude no longer holds the whole team on the claude hold.
128
+ const reviewSeamKey = reviewHoldKey(gates.roleConfig);
129
+ return {
130
+ ...gates,
131
+ teamHeldProviders,
132
+ teamHeldNow,
133
+ reviewHeldNow: () => liveConfig.review.enabled && teamHeldNow().has(reviewSeamKey),
134
+ reviewHeld: liveConfig.review.enabled && teamHeldProviders.has(reviewSeamKey),
135
+ roleProviders: new Map(runners.map((r) => [r.role, r.runProvider(now)])),
136
+ };
137
+ }
138
+ /** Self-redeploy (src/redeploy/redeployer.ts): with main's head in hand, let the state
139
+ * machine observe it. `hold` starts no new runs at all — director included; a restart
140
+ * takes effect within the drain's window plus a bounded merge hand-off, and its prompt waits
141
+ * in the inbox for the new build — while the green check/compile/drain run in the
142
+ * background. That covers runs reserved before the hold too: a waiter parked in the
143
+ * semaphore queue that is granted a permit mid-drain meets the closed start gate
144
+ * (runStartHeld), releases the permit, and hands its reservation back so it re-schedules
145
+ * once the hold lifts or on the new build. `restart` means dist/ already holds the new
146
+ * build: stop scheduling, abort whatever role runs the drain gave up waiting for — the
147
+ * permit holders; they resume on the new build — and return true. A director run can never
148
+ * be in flight here — poll only returns `restart` once it has finished. (holdForRestart keeps
149
+ * the previous poll's verdict until this one's is in: resetting it before the await
150
+ * would open the gate for a waiter granted a permit while poll runs.)
151
+ * Main watch (src/baseline/main-watch.ts): records the full check's verdict on main's new
152
+ * tip in the background; nothing here waits for it. Writes state.restart and
153
+ * state.holdForRestart; returns whether the loop should stop. */
154
+ export async function pollRedeploy(ctx, state, { liveConfig, mainHead, now }) {
155
+ const { redeploy } = ctx;
156
+ if (!ctx.onceMode)
157
+ ctx.mainWatch.poll(mainHead, state.holdForRestart || state.diskHeld, liveConfig);
158
+ if (!redeploy)
159
+ return false;
160
+ const action = await redeploy.poll(await redeployTarget(ctx.root, mainHead, redeploy.build.sha), {
161
+ roleInFlight: ctx.rolePermitHolders.size,
162
+ directorInFlight: ctx.directorInFlight.size,
163
+ roleRunP75Ms: p75RunDurationMs(ctx.roleRunDurationsMs),
164
+ }, liveConfig.autoRestart, now);
165
+ publishInfoFields(ctx.root, ctx.info, [["build", redeploy.status(now)]]);
166
+ if (action === "restart") {
167
+ state.restart = true;
168
+ // Only permit holders have a pi run to cut off (the director is guaranteed finished by
169
+ // then): a parked waiter meets the closed start gate whenever the shutdown hands it a
170
+ // permit, so it needs no abort — and aborting for it alone would also cut off an
171
+ // in-flight merge that no permit-holding run put at stake. The role-only controller
172
+ // keeps that promise: the merge, wired to the full signal, runs on into the hand-off
173
+ // window the wait announces (BUGS.md 2026-09-30).
174
+ if (ctx.rolePermitHolders.size > 0)
175
+ ctx.internalRoleStop.abort();
176
+ return true;
177
+ }
178
+ state.holdForRestart = action === "hold";
179
+ return false;
180
+ }
181
+ /** Merge queue 3/5 — drain the durable merge queue while neither a restart nor a failure
182
+ * hold is pending (the scheduler's WHEN; merge-drain.ts owns the HOW — the verification
183
+ * stage, its merge slot, and the dedupe against main). A held poll starts no verify and no
184
+ * merge, exactly as it starts no run; what is already in flight carries on, and a verify
185
+ * parked for its permit meets the same start gate as a parked run when the permit comes. */
186
+ export async function pollMergeDrain(ctx, state, { liveConfig, mainHead }, gates) {
187
+ if (state.holdForRestart || gates.reviewHeld || state.diskHeld)
188
+ return;
189
+ const { root, mainBranch } = ctx;
190
+ // A `main_red` pin the pipeline kept goes back on the queue once main's head has moved.
191
+ for (const r of ctx.runners)
192
+ await requeueMainRedPin(root, mainBranch, r.state, mainHead);
193
+ await drainMergeQueue({
194
+ root,
195
+ mainBranch,
196
+ signal: ctx.signal,
197
+ semaphore: ctx.semaphore,
198
+ runners: ctx.runners,
199
+ liveConfig,
200
+ roleConfig: gates.roleConfig,
201
+ directorConfig: gates.directorConfig,
202
+ piDefault: ctx.piDefault,
203
+ startHeld: () => runStartHeld(state) || gates.reviewHeldNow(),
204
+ }, ctx.merges);
205
+ }
206
+ /** The scheduling pass: the deferral inputs feed pollRunnerReasons, whose reasons map
207
+ * launchDueRuns starts runs from. */
208
+ export async function pollSchedule(ctx, state, { liveConfig, mainHead, now }, gates) {
209
+ const { root, runners, gateStates } = ctx;
210
+ const inputs = pollDeferralInputs(root, runners, liveConfig, gateStates, gates, ctx.breakerNow());
211
+ const reasons = await pollRunnerReasons({
212
+ root,
213
+ runners,
214
+ once: ctx.once,
215
+ now,
216
+ mainHead,
217
+ userPaused: gates.userPaused,
218
+ quietNow: gates.quietNow,
219
+ pausedRoles: gates.pausedRoles,
220
+ capPaused: gates.capPaused,
221
+ maintenanceQuota: gates.maintenanceQuota,
222
+ bootstrapHeld: gates.bootstrapHeld,
223
+ budgetPausedRoles: gates.budgetPausedRoles,
224
+ probeRoles: inputs.probeRoles,
225
+ reviewStrongPaused: inputs.reviewStrongPaused,
226
+ roleQuietHeld: gates.roleQuietHeld,
227
+ holdForRestart: state.holdForRestart,
228
+ diskHeld: state.diskHeld,
229
+ heldProviders: gates.teamHeldProviders,
230
+ windowHeldProviders: windowHeldProviders(gateStates.teamHold),
231
+ reviewHeld: gates.reviewHeld,
232
+ roleProviders: gates.roleProviders,
233
+ openBugsNow: inputs.openBugsNow,
234
+ workBacklogOpen: inputs.workBacklogOpen,
235
+ planBacklogFull: inputs.plansFull,
236
+ deferredDue: ctx.deferredDue,
237
+ workMergedSince: ctx.workMergedSince,
238
+ });
239
+ launchDueRuns({
240
+ root,
241
+ reasons,
242
+ // roleSignal, not signal: the timed run wrapper watches the full signal PLUS the
243
+ // role-only stop, exactly as the pre-extraction inline pass did — the restart drain's
244
+ // give-up abort must also turn away a waiter granted its permit at that moment.
245
+ signal: ctx.roleSignal,
246
+ gateStates,
247
+ breakerPolicy: ctx.breakerPolicy,
248
+ breakerNow: ctx.breakerNow,
249
+ probePair: inputs.probePair,
250
+ probeRoles: inputs.probeRoles,
251
+ budgetActive: gates.budgetActive,
252
+ windowMovedRoles: gates.windowMovedRoles,
253
+ semaphore: ctx.semaphore,
254
+ piDefault: ctx.piDefault,
255
+ rolePermitHolders: ctx.rolePermitHolders,
256
+ roleInFlight: ctx.roleInFlight,
257
+ directorInFlight: ctx.directorInFlight,
258
+ roleRunDurationsMs: ctx.roleRunDurationsMs,
259
+ startHeld: (role) => runStartHeld(state) ||
260
+ (role !== DIRECTOR_ROLE
261
+ ? gates.reviewHeldNow() || gates.teamHeldNow().has(gates.roleProviders.get(role))
262
+ : windowHeldProviders(gateStates.teamHold).has(gates.roleProviders.get(role))),
263
+ });
264
+ }
265
+ /** Priority headroom, then once mode's exit; returns whether the loop should stop. Writes
266
+ * state.lastReserve and, in once mode, fires internalStop. */
267
+ export function pollReserveAndExit(ctx, state, { liveConfig, now }) {
268
+ const { root, runners, semaphore } = ctx;
269
+ // Priority headroom (plans/parallel-work-instances.md part 7/7): withhold a few permits
270
+ // from maintenance while a work role has work to take, so a due work run never waits out
271
+ // a whole maintenance run. Sized after the launch pass, so a runner launched this poll
272
+ // already reads as running and reserves nothing for itself.
273
+ const poolSnapshot = semaphore.snapshot();
274
+ // The provider-headroom predicate receives the structural ClaimRunner; the config that
275
+ // names the provider lives on the real RoleRunners, so look the runner up by role.
276
+ const runnerByRole = new Map(runners.map((r) => [r.role, r]));
277
+ const reserve = workReserveCount(root, runners, {
278
+ maxConcurrent: liveConfig.maxConcurrent,
279
+ enabled: new Set(runners.filter((r) => runnerEnabled(r.config, r.role)).map((r) => r.role)),
280
+ queuedMergeRoles: queuedMergeRoles(root),
281
+ instancesOf: (base) => liveConfig.roles[base]?.instances ?? 1,
282
+ // Per-provider headroom (plans/provider-concurrency.md §6): an idle work role reserves a
283
+ // permit only when its own provider could use it — capped and full, it would only idle
284
+ // the slot another provider's maintenance run could take. Read from the pool's live
285
+ // snapshot; an uncapped key (or the team-total-only case) always has headroom.
286
+ providerHasHeadroom: (r) => {
287
+ const runner = runnerByRole.get(r.role);
288
+ const cfg = runner && runner.role !== DIRECTOR_ROLE ? runner.runConfig(now) : null;
289
+ const key = cfg ? seamConcurrencyKey(cfg, ctx.piDefault) : undefined;
290
+ if (key === undefined)
291
+ return true;
292
+ const k = poolSnapshot.byKey[key];
293
+ if (k?.limit === undefined)
294
+ return true;
295
+ return k.inUse < k.limit;
296
+ },
297
+ });
298
+ semaphore.setReserve(reserve);
299
+ if ((state.lastReserve === 0) !== (reserve === 0)) {
300
+ ctx.emit({ source: TUMWATER_SOURCE, type: "permit_reserve", reserve });
301
+ }
302
+ state.lastReserve = reserve;
303
+ // Once mode's exit: every enabled role settled, no run in flight, and the merge queue
304
+ // empty with no merge in flight for one full poll cycle — then fire the internal
305
+ // stop, the same graceful shutdown the restart drain uses (the `finally` awaits
306
+ // in-flight merge tasks to the end). The one-poll-cycle requirement is the guard
307
+ // against dropping a queued-but-not-yet-started merge: a stop that arrives during the
308
+ // shutdown drain drops the queue entry, so the slot gets its poll to pick the entry up
309
+ // before the stop is trusted.
310
+ if (ctx.once.exitReady({
311
+ roleRuns: ctx.roleInFlight.size,
312
+ directorRuns: ctx.directorInFlight.size,
313
+ merges: mergeTasks(ctx.merges).length,
314
+ queuedMerges: queuedMergeFiles(root).length,
315
+ })) {
316
+ ctx.internalStop.abort();
317
+ return true;
318
+ }
319
+ return false;
320
+ }