toolroll 0.9.92 → 0.9.94

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 (341) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/dist/activity-line.d.ts +7 -4
  3. package/dist/activity-line.js +9 -7
  4. package/dist/agent-fence.d.ts +4 -0
  5. package/dist/agent-fence.js +4 -1
  6. package/dist/approval-authority.d.ts +7 -1
  7. package/dist/approval-authority.js +11 -2
  8. package/dist/approval-password.d.ts +31 -0
  9. package/dist/approval-password.js +26 -0
  10. package/dist/assignment-status.d.ts +1 -1
  11. package/dist/assignment-ui.js +3 -3
  12. package/dist/assignment.js +16 -3
  13. package/dist/boot-identity.d.ts +2 -1
  14. package/dist/boot-identity.js +6 -4
  15. package/dist/bounded-spawn.d.ts +57 -0
  16. package/dist/bounded-spawn.js +220 -0
  17. package/dist/browser/terminal.js +42 -42
  18. package/dist/browser/workspace.css +2 -2
  19. package/dist/browser/workspace.js +26 -26
  20. package/dist/browser-crew.js +2 -2
  21. package/dist/browser-shell.d.ts +1 -1
  22. package/dist/browser-shell.js +2 -2
  23. package/dist/browser-workspace.d.ts +48 -7
  24. package/dist/browser-workspace.js +3 -3
  25. package/dist/builder-restart.d.ts +21 -0
  26. package/dist/builder-restart.js +50 -0
  27. package/dist/builder.d.ts +4 -0
  28. package/dist/builder.js +73 -25
  29. package/dist/chat-acceptance.js +1 -1
  30. package/dist/chat-actions.d.ts +12 -2
  31. package/dist/chat-actions.js +25 -2
  32. package/dist/chat-channel.js +11 -0
  33. package/dist/chat-decide.d.ts +7 -2
  34. package/dist/chat-decide.js +37 -9
  35. package/dist/chat-quiet.js +3 -3
  36. package/dist/chat-voice.d.ts +1 -1
  37. package/dist/chat-voice.js +2 -2
  38. package/dist/check-facts.d.ts +126 -0
  39. package/dist/check-facts.js +318 -0
  40. package/dist/check-failure.d.ts +22 -3
  41. package/dist/check-failure.js +57 -13
  42. package/dist/check-levels-ui.d.ts +4 -0
  43. package/dist/check-levels-ui.js +10 -1
  44. package/dist/check-load.d.ts +85 -0
  45. package/dist/check-load.js +147 -0
  46. package/dist/check-only-standing.d.ts +36 -0
  47. package/dist/check-only-standing.js +39 -0
  48. package/dist/check-only.d.ts +15 -0
  49. package/dist/check-only.js +99 -0
  50. package/dist/check-report.d.ts +7 -0
  51. package/dist/check-report.js +4 -3
  52. package/dist/check-stamp.d.ts +46 -0
  53. package/dist/check-stamp.js +93 -0
  54. package/dist/checkout-cleanup.d.ts +36 -5
  55. package/dist/checkout-cleanup.js +166 -14
  56. package/dist/cli-help.d.ts +4 -1
  57. package/dist/cli-help.js +47 -30
  58. package/dist/cli.js +16 -1
  59. package/dist/code-extract.d.ts +44 -0
  60. package/dist/code-extract.js +88 -0
  61. package/dist/code-map-acts.d.ts +24 -0
  62. package/dist/code-map-acts.js +53 -0
  63. package/dist/code-map-admission.d.ts +52 -0
  64. package/dist/code-map-admission.js +295 -0
  65. package/dist/code-map-build.d.ts +63 -0
  66. package/dist/code-map-build.js +415 -0
  67. package/dist/code-map-cli.d.ts +153 -0
  68. package/dist/code-map-cli.js +103 -0
  69. package/dist/code-map-main.d.ts +1 -0
  70. package/dist/code-map-main.js +48 -0
  71. package/dist/code-map-read.d.ts +106 -0
  72. package/dist/code-map-read.js +171 -0
  73. package/dist/code-map-report.d.ts +37 -0
  74. package/dist/code-map-report.js +95 -0
  75. package/dist/code-map-shape.d.ts +172 -0
  76. package/dist/code-map-shape.js +327 -0
  77. package/dist/code-map-store.d.ts +136 -0
  78. package/dist/code-map-store.js +233 -0
  79. package/dist/coding-provider.d.ts +2 -0
  80. package/dist/coding-provider.js +3 -2
  81. package/dist/coding-update.js +3 -2
  82. package/dist/coding-workspace.js +4 -4
  83. package/dist/console-chrome.js +2 -2
  84. package/dist/containment.d.ts +5 -0
  85. package/dist/containment.js +14 -1
  86. package/dist/contracts/chat-actions.d.ts +9 -0
  87. package/dist/contracts/chat-actions.js +2 -0
  88. package/dist/contracts/cli.d.ts +52 -0
  89. package/dist/contracts/cli.js +4 -0
  90. package/dist/contracts/console-api.d.ts +12 -5
  91. package/dist/contracts/console-api.js +12 -5
  92. package/dist/contracts/gateway-tools.d.ts +17 -0
  93. package/dist/contracts/gateway-tools.js +3 -1
  94. package/dist/contracts/lead-tools.d.ts +61 -0
  95. package/dist/contracts/lead-tools.js +10 -1
  96. package/dist/contracts/project-knowledge.d.ts +38 -5
  97. package/dist/contracts/project-knowledge.js +11 -5
  98. package/dist/contracts/project-memory.d.ts +3 -1
  99. package/dist/contracts/project-memory.js +3 -2
  100. package/dist/contracts/release-check.d.ts +25 -1
  101. package/dist/contracts/release-check.js +19 -0
  102. package/dist/contracts/storage.d.ts +14 -0
  103. package/dist/contracts/storage.js +3 -1
  104. package/dist/contracts/store-json.d.ts +2 -0
  105. package/dist/contracts/youiyoux-request.d.ts +1 -1
  106. package/dist/contracts/youiyoux-request.js +1 -1
  107. package/dist/desktop-access.js +6 -2
  108. package/dist/desktop-update.d.ts +2 -2
  109. package/dist/desktop-update.js +13 -9
  110. package/dist/dispatch.js +18 -15
  111. package/dist/dispose.js +8 -2
  112. package/dist/easy-start.js +2 -3
  113. package/dist/eval-hooks.d.ts +55 -0
  114. package/dist/eval-hooks.js +227 -4
  115. package/dist/evals.js +2 -1
  116. package/dist/fast-start.d.ts +136 -0
  117. package/dist/fast-start.js +431 -0
  118. package/dist/fast-terms.d.ts +9 -0
  119. package/dist/fast-terms.js +23 -0
  120. package/dist/fenced-check-coverage.d.ts +62 -0
  121. package/dist/fenced-check-coverage.js +54 -0
  122. package/dist/first-run.js +1 -1
  123. package/dist/flaky-ci.d.ts +31 -0
  124. package/dist/flaky-ci.js +149 -0
  125. package/dist/flaky-cli.d.ts +60 -0
  126. package/dist/flaky-cli.js +60 -0
  127. package/dist/flaky.d.ts +83 -0
  128. package/dist/flaky.js +264 -0
  129. package/dist/flow-card-task.js +3 -0
  130. package/dist/flow-triggers.d.ts +1 -1
  131. package/dist/flow-triggers.js +1 -1
  132. package/dist/github-import.d.ts +62 -0
  133. package/dist/github-import.js +146 -0
  134. package/dist/guides.js +15 -10
  135. package/dist/invoke.d.ts +5 -1
  136. package/dist/invoke.js +49 -14
  137. package/dist/job-object-helper.ps1 +10 -3
  138. package/dist/keymap.d.ts +41 -0
  139. package/dist/keymap.js +51 -0
  140. package/dist/knowledge-cli.js +1 -1
  141. package/dist/knowledge-ui.d.ts +21 -4
  142. package/dist/knowledge-ui.js +75 -7
  143. package/dist/laptop-background.d.ts +16 -0
  144. package/dist/laptop-background.js +108 -2
  145. package/dist/lead-context.js +1 -1
  146. package/dist/lead-contract.d.ts +1 -1
  147. package/dist/lead-contract.js +2 -2
  148. package/dist/lead-progress.js +3 -0
  149. package/dist/lead-status.d.ts +2 -0
  150. package/dist/lead-status.js +6 -2
  151. package/dist/lead-tools.js +51 -2
  152. package/dist/lead.js +1 -1
  153. package/dist/lesson-notes.d.ts +81 -0
  154. package/dist/lesson-notes.js +336 -0
  155. package/dist/limits-ui.js +1 -1
  156. package/dist/local-owner.d.ts +1 -1
  157. package/dist/local-owner.js +11 -0
  158. package/dist/machine-check.d.ts +16 -0
  159. package/dist/machine-check.js +26 -0
  160. package/dist/machine-identity.d.ts +75 -0
  161. package/dist/machine-identity.js +170 -0
  162. package/dist/mcp-core.js +11 -1
  163. package/dist/memory-cli.d.ts +300 -1
  164. package/dist/memory-cli.js +62 -9
  165. package/dist/memory-pass.d.ts +16 -0
  166. package/dist/memory-pass.js +67 -3
  167. package/dist/memory-tidy.d.ts +181 -0
  168. package/dist/memory-tidy.js +523 -0
  169. package/dist/memory-use.d.ts +35 -0
  170. package/dist/memory-use.js +109 -0
  171. package/dist/merge-checklist.d.ts +55 -0
  172. package/dist/merge-checklist.js +182 -0
  173. package/dist/needs-you.d.ts +32 -13
  174. package/dist/needs-you.js +108 -49
  175. package/dist/nightly-github.d.ts +2 -0
  176. package/dist/nightly-github.js +4 -4
  177. package/dist/operate-remote-arguments.js +6 -1
  178. package/dist/operate-remote.js +3 -1
  179. package/dist/operate.d.ts +6 -1
  180. package/dist/operate.js +540 -70
  181. package/dist/phase-routing.js +2 -2
  182. package/dist/plain-schema.d.ts +23 -0
  183. package/dist/plain-schema.js +94 -0
  184. package/dist/plain-words.d.ts +20 -0
  185. package/dist/plain-words.js +66 -0
  186. package/dist/planner.js +2 -1
  187. package/dist/process-liveness.d.ts +2 -0
  188. package/dist/process-liveness.js +61 -17
  189. package/dist/project-delete-ui.d.ts +7 -2
  190. package/dist/project-delete-ui.js +12 -1
  191. package/dist/project-delete.js +13 -2
  192. package/dist/project-knowledge.d.ts +18 -11
  193. package/dist/project-knowledge.js +39 -9
  194. package/dist/project-learning.d.ts +2 -1
  195. package/dist/project-learning.js +15 -45
  196. package/dist/project-memory.d.ts +5 -0
  197. package/dist/project-memory.js +22 -2
  198. package/dist/proof.js +30 -5
  199. package/dist/provider-auth.js +1 -1
  200. package/dist/publish.js +9 -1
  201. package/dist/pull-request-flow.js +5 -0
  202. package/dist/push.d.ts +26 -3
  203. package/dist/push.js +55 -15
  204. package/dist/release-adapters.d.ts +9 -0
  205. package/dist/release-adapters.js +87 -1
  206. package/dist/release-approval.d.ts +191 -0
  207. package/dist/release-approval.js +382 -0
  208. package/dist/release-auto.js +26 -17
  209. package/dist/release-card.d.ts +74 -6
  210. package/dist/release-card.js +179 -23
  211. package/dist/release-carry.d.ts +7 -2
  212. package/dist/release-carry.js +39 -9
  213. package/dist/release-cli.d.ts +4 -0
  214. package/dist/release-cli.js +38 -23
  215. package/dist/release-coverage.js +1 -1
  216. package/dist/release-next.d.ts +48 -0
  217. package/dist/release-next.js +161 -0
  218. package/dist/release.d.ts +50 -1
  219. package/dist/release.js +118 -11
  220. package/dist/remote-destination.d.ts +36 -0
  221. package/dist/remote-destination.js +217 -0
  222. package/dist/remote-main.d.ts +48 -0
  223. package/dist/remote-main.js +84 -5
  224. package/dist/repository-context.d.ts +3 -2
  225. package/dist/repository-context.js +112 -70
  226. package/dist/restart-certification.d.ts +1 -0
  227. package/dist/restart-certification.js +8 -6
  228. package/dist/result-acts.d.ts +29 -21
  229. package/dist/result-acts.js +36 -25
  230. package/dist/result-follow-ups.d.ts +2 -2
  231. package/dist/result-follow-ups.js +18 -4
  232. package/dist/result-review.d.ts +1 -1
  233. package/dist/route-change-check.d.ts +4 -0
  234. package/dist/route-change-check.js +13 -0
  235. package/dist/route-change.d.ts +22 -0
  236. package/dist/route-change.js +89 -0
  237. package/dist/route-hooks.js +3 -2
  238. package/dist/route-results.d.ts +6 -1
  239. package/dist/route-results.js +14 -5
  240. package/dist/run-closeout.d.ts +1 -1
  241. package/dist/run-closeout.js +7 -5
  242. package/dist/runner-process.js +3 -2
  243. package/dist/runner.js +2 -1
  244. package/dist/scope.d.ts +6 -1
  245. package/dist/scope.js +22 -9
  246. package/dist/serve.d.ts +1 -1
  247. package/dist/serve.js +24 -18
  248. package/dist/server/chat.js +14 -12
  249. package/dist/server/chrome.d.ts +1 -1
  250. package/dist/server/chrome.js +26 -35
  251. package/dist/server/console.css +23 -0
  252. package/dist/server/guards.js +4 -0
  253. package/dist/server/home.d.ts +6 -0
  254. package/dist/server/home.js +21 -13
  255. package/dist/server/http.js +1 -1
  256. package/dist/server/kit.js +1 -1
  257. package/dist/server/merge-ready-view.d.ts +10 -0
  258. package/dist/server/merge-ready-view.js +30 -0
  259. package/dist/server/pages-assets.d.ts +1 -0
  260. package/dist/server/pages-assets.js +8 -5
  261. package/dist/server/pages.js +103 -82
  262. package/dist/server/render-chat.js +2 -2
  263. package/dist/server/render-code-map.d.ts +30 -0
  264. package/dist/server/render-code-map.js +137 -0
  265. package/dist/server/render-flaky.d.ts +20 -0
  266. package/dist/server/render-flaky.js +59 -0
  267. package/dist/server/render-history.js +1 -1
  268. package/dist/server/render-new-task.d.ts +26 -1
  269. package/dist/server/render-new-task.js +30 -5
  270. package/dist/server/render-pages.d.ts +1 -175
  271. package/dist/server/render-pages.js +38 -313
  272. package/dist/server/render-projects.d.ts +2 -1
  273. package/dist/server/render-projects.js +9 -7
  274. package/dist/server/render-release.d.ts +19 -0
  275. package/dist/server/render-release.js +84 -0
  276. package/dist/server/render-results.d.ts +2 -2
  277. package/dist/server/render-results.js +71 -73
  278. package/dist/server/render-tasks.d.ts +13 -2
  279. package/dist/server/render-tasks.js +156 -139
  280. package/dist/server/retired-routes.d.ts +17 -0
  281. package/dist/server/retired-routes.js +53 -0
  282. package/dist/server/route-table.d.ts +4 -1
  283. package/dist/server/route-table.js +52 -13
  284. package/dist/server/settings.js +129 -22
  285. package/dist/server/task-views.js +61 -26
  286. package/dist/server/tasks.d.ts +17 -6
  287. package/dist/server/tasks.js +273 -338
  288. package/dist/server/welcome.js +1 -1
  289. package/dist/settings-groups-ui.js +1 -1
  290. package/dist/setup-guide.d.ts +2 -2
  291. package/dist/stop-proof.d.ts +67 -0
  292. package/dist/stop-proof.js +295 -0
  293. package/dist/storage-sweep-process.js +1 -1
  294. package/dist/storage-sweep.d.ts +5 -3
  295. package/dist/storage-sweep.js +30 -9
  296. package/dist/storage-ui.js +28 -17
  297. package/dist/storage.d.ts +27 -2
  298. package/dist/storage.js +39 -2
  299. package/dist/store.d.ts +148 -34
  300. package/dist/store.js +626 -177
  301. package/dist/surface.js +46 -5
  302. package/dist/sweep-quarantine.d.ts +1 -0
  303. package/dist/sweep-quarantine.js +6 -4
  304. package/dist/tamper-scan.d.ts +4 -0
  305. package/dist/tamper-scan.js +90 -0
  306. package/dist/task-aliases.d.ts +5 -0
  307. package/dist/task-aliases.js +9 -0
  308. package/dist/task-control.js +4 -1
  309. package/dist/task-outcome-cli.d.ts +2 -0
  310. package/dist/task-outcome-cli.js +36 -17
  311. package/dist/task-sizing.d.ts +5 -0
  312. package/dist/task-sizing.js +2 -0
  313. package/dist/task-source.d.ts +7 -0
  314. package/dist/task-source.js +14 -0
  315. package/dist/task-status.d.ts +9 -0
  316. package/dist/task-status.js +40 -49
  317. package/dist/teardown-git.d.ts +16 -0
  318. package/dist/teardown-git.js +63 -5
  319. package/dist/telegram-progress.js +5 -3
  320. package/dist/telegram-status.js +6 -4
  321. package/dist/test-infra.d.ts +8 -0
  322. package/dist/test-infra.js +18 -0
  323. package/dist/tidy.js +1 -1
  324. package/dist/toolroll-update-ui.js +2 -2
  325. package/dist/toolroll-update.js +18 -5
  326. package/dist/tui-contract.d.ts +24 -0
  327. package/dist/tui-source.js +67 -8
  328. package/dist/tui.js +51 -51
  329. package/dist/vanished-retry.d.ts +30 -0
  330. package/dist/vanished-retry.js +174 -0
  331. package/dist/work-index.d.ts +2 -0
  332. package/dist/work-index.js +82 -70
  333. package/dist/work-summary.d.ts +2 -2
  334. package/dist/work-summary.js +2 -0
  335. package/dist/workspace-ui.d.ts +4 -2
  336. package/dist/workspace-ui.js +28 -22
  337. package/dist/worktree.d.ts +12 -3
  338. package/dist/worktree.js +68 -13
  339. package/package.json +1 -1
  340. package/dist/server/render-next.d.ts +0 -63
  341. package/dist/server/render-next.js +0 -109
@@ -1,3 +1,4 @@
1
+ import { existsSync } from "node:fs";
1
2
  import { resultRecordWordsOf } from "../route-results.js";
2
3
  import { selectionEvidenceWords } from "../route-rules.js";
3
4
  import { feedbackImageProblem } from "../result-actions.js";
@@ -7,8 +8,10 @@ import { RELEASE_STEPS } from "../release.js";
7
8
  import { releaseProgressFor, shipChecksForTask } from "../store.js";
8
9
  import { releaseCiRunningOf } from "../release-ci-hold.js";
9
10
  import { releaseObligationsOf } from "../release-recheck.js";
10
- import { approvalProofOf, freshlyApprovable, freshnessFor, localApprovalEligible, withFreshness } from "../scope.js";
11
- import { localOwnerRefusal } from "../local-owner.js";
11
+ import { approvalProofOf, freshnessFor, withFreshness } from "../scope.js";
12
+ import { approvalPasswordField } from "../approval-password.js";
13
+ import { fastChangeProblem, fastStarted } from "../fast-start.js";
14
+ import { routeChangeOf } from "../route-change.js";
12
15
  import { liveAttemptOf, steerControlsFor } from "../steer-controls.js";
13
16
  import { originOf } from "../task-source.js";
14
17
  import { recentGitReads, taskBaseOf } from "../task-base.js";
@@ -55,6 +58,8 @@ import {} from "./render-pages.js";
55
58
  import { completionReceiptView, diffFileAnchor, evidenceLinksFor, followUpsFor, orderChangedFiles, parseReviewDiff, proofBundleView, receiptStatusOf, withinSignedTouches } from "./render-results.js";
56
59
  import { approvalFormDigest, consentDoorOf, nonceHashOf, publicationFactsOf, resumeCeremonyPage, resumeDigestOf, taskBody, taskPage } from "./render-tasks.js";
57
60
  import {} from "./session.js";
61
+ import { mergeReadyViewOf } from "./merge-ready-view.js";
62
+ import { machineChecked, machineCheckWords } from "../machine-check.js";
58
63
  import { RESULT_REVIEW_SCRIPT } from "../result-review.js";
59
64
  import { reviewEvidenceScript } from "./render-results.js";
60
65
  import { budgetHoldWords, budgetLabel, monthOf } from "../spend.js";
@@ -162,6 +167,7 @@ export function createTaskViews(runtime) {
162
167
  },
163
168
  publication: latest === null ? null : publicationFactsOf(runtime.store.publicationForRun(latest.id)),
164
169
  liveRunId: live === null ? null : live.id,
170
+ ...(machineChecked(runtime.store, task.id) ? { machine: true } : {}),
165
171
  openDecision: ref === null ? null : openWorkDecisionOf(runtime.store, ref.id, now),
166
172
  unfinishedRunId: runs.find(one => one.outcome === null && one.role !== "reviewer")?.id ?? null,
167
173
  control: ref === null ? { kind: "none" } : taskControlOf(runtime.store, ref.id, now),
@@ -521,23 +527,25 @@ export function createTaskViews(runtime) {
521
527
  })(),
522
528
  // Cockpit B2: whether this person's remembered password may approve these exact terms (the same rule approve()
523
529
  // applies), and since when.
524
- approvalFresh: (() => {
530
+ // The one password rule every approve form reads (approval-password.ts): remembered since when, or a local
531
+ // owner's no-password approval (eligible, or why not and where to go).
532
+ ...(() => {
525
533
  const scope = ref === null ? null : runtime.store.getScope(ref.externalId);
526
- if (scope === null || who?.via !== "cookie")
527
- return null;
534
+ if (scope === null || ref === null || who?.via !== "cookie")
535
+ return { approvalFresh: null, approvalLocal: null };
528
536
  const fresh = withFreshness("approve-standard", () => freshnessFor(who.name, Date.now(), true));
529
- if (fresh === null)
530
- return null;
531
- const gate = runtime.store.approvalGate(ref.externalId, who.name, "person");
532
- return freshlyApprovable(runtime.store, ref.externalId, scope, gate.verdict === "seal" && !gate.protectedWork) ? new Date(fresh.at).toISOString() : null;
537
+ const field = approvalPasswordField(runtime.store, { name: who.name, taskId: ref.externalId, scope, passwordless: false,
538
+ localOwner: who.authority === "local-owner", freshAt: fresh?.at ?? null, returnTo: taskHref(ref.externalId) });
539
+ return { approvalFresh: field.field === "remembered" ? field.since : null,
540
+ approvalLocal: field.field === "none" && field.why === "local-owner" ? { eligible: true }
541
+ : field.field === "local-refused" ? { eligible: false, message: field.message, href: field.href, action: field.action } : null };
533
542
  })(),
534
- // Easy-start C5: a laptop's local owner approves eligible work with no password (the seal applies the same rule).
535
- approvalLocal: (() => {
536
- if (ref === null || who?.via !== "cookie" || who.authority !== "local-owner")
543
+ routeChange: ref === null ? null : routeChangeOf(runtime.store, ref.externalId),
544
+ fastGrown: (() => {
545
+ if (ref === null || runtime.store.getTask(ref.externalId)?.state !== "done" || !fastStarted(runtime.store, ref.externalId))
537
546
  return null;
538
- if (localApprovalEligible(runtime.store, who.name, ref.externalId).ok)
539
- return { eligible: true };
540
- return { eligible: false, ...localOwnerRefusal(runtime.store.accountOf(who.name)?.passwordSet === true, taskHref(ref.externalId)) };
547
+ const last = runtime.store.lastBuilderRun(ref.id);
548
+ return last === null ? null : fastChangeProblem(runtime.store, ref.externalId, last.id);
541
549
  })(),
542
550
  steerRecent: ref === null ? [] : runtime.store.runsFor(ref.id).filter(one => one.outcome !== null).map(one => one.id).sort((a, b) => b - a).slice(0, 5),
543
551
  // The running attempt's composer, for an approver on a browser session (steer-controls.ts).
@@ -805,7 +813,7 @@ export function createTaskViews(runtime) {
805
813
  return runtime.sendScreen(response, status, screen(admittedFamily.root.title, html `<h1>${admittedFamily.root.title}</h1><p>${admittedFamily.current.state}</p><p class="problem" data-history-problem>${admittedFamily.problem}</p>`, { chrome: runtime.chromeFor(admittedFamily.root.repo, "tasks") }));
806
814
  const data = taskViewData(taskId, who, problem);
807
815
  if (data === null)
808
- return refuse(response, who, 404, "no such task", "/work");
816
+ return refuse(response, who, 404, "no such task", "/tasks");
809
817
  const family = runtime.familyOf(taskId);
810
818
  const presentedData = { ...data, rootId: family?.root.id ?? taskId, rootTitle: family?.root.title ?? data.task.title,
811
819
  ...(family === null || data.assignment != null ? {} : { history: familyHistory(family) }),
@@ -858,7 +866,21 @@ export function createTaskViews(runtime) {
858
866
  // Ship (its pull request's checks, each on one time axis) and a release's own steps, read from the store now.
859
867
  const rootId = family?.root.id ?? taskId;
860
868
  const oneTaskView = onePage?.kind === "task" ? { ...onePage, ship: shipViewOf(shipChecksForTask(runtime.store, rootId), runtime.clock()),
861
- release: releaseStepsViewOf(releaseProgressFor(runtime.store, rootId), runtime.clock()) } : onePage;
869
+ release: releaseStepsViewOf(releaseProgressFor(runtime.store, rootId), runtime.clock()),
870
+ // "Can I merge?" (P1.6): the checklist from the same assignment this page read, each blocker with its own form.
871
+ mergeReady: mergeReadyViewOf(runtime.store, taskId, data.assignment, who, presentedData.runChecks ?? null, taskHref(taskId)) } : onePage;
872
+ // A check the machine runs (a prepared candidate: a release's check) is said as the check it is, with no agent's
873
+ // activity, no notes to read, and for a release its own steps instead of the generic Plan → Build stepper.
874
+ if (oneTaskView?.kind === "task" && machineChecked(runtime.store, taskId)) {
875
+ const words = machineCheckWords(runtime.store, taskId, data.liveRunId ?? null, oneTaskView.release ?? null, runtime.clock());
876
+ const card = oneTaskView.status;
877
+ if (words !== null && card !== null && card.status.headline === "Building")
878
+ oneTaskView.status = { ...card, status: { ...card.status, sentence: words } };
879
+ oneTaskView.activity = null;
880
+ oneTaskView.steering = null;
881
+ if (oneTaskView.release != null)
882
+ oneTaskView.journey = null;
883
+ }
862
884
  // The Result tab's no-script page, under the task's own (the same HTML its result page serves), and its script.
863
885
  if (extras.result != null) {
864
886
  page.body = html `${page.body}<section class="task-result-tab" id="task-result" aria-label="Result">${extras.result.html}</section>`;
@@ -895,14 +917,14 @@ export function createTaskViews(runtime) {
895
917
  const stop = runtime.store.stopOf(runId);
896
918
  const run = runtime.store.getRun(runId);
897
919
  if (stop === null || run === null || stop.taskRef !== ref.id)
898
- return taskScreen(response, who, taskId, `run #${runId} is not a stopped attempt of this task`, 409);
920
+ return taskScreen(response, who, taskId, `build #${runId} is not a stopped attempt of this task`, 409);
899
921
  if (run.role === "reviewer")
900
- return taskScreen(response, who, taskId, `run #${runId} is a historical review run — nothing reruns it; open the saved result instead`, 409);
922
+ return taskScreen(response, who, taskId, `build #${runId} was an old review. Nothing reruns it; open the saved result instead`, 409);
901
923
  if (stop.resumedAt !== null)
902
- return taskScreen(response, who, taskId, `run #${runId} was already resumed by ${stop.resumedBy ?? "?"}`, 409);
924
+ return taskScreen(response, who, taskId, `build #${runId} was already resumed by ${stop.resumedBy ?? "?"}`, 409);
903
925
  const control = taskControlOf(runtime.store, ref.id, now);
904
926
  if (control.kind !== "paused" || control.run !== runId) {
905
- return taskScreen(response, who, taskId, control.kind === "stopping" ? `run #${runId} is still stopping — its processes are not yet established gone` : `run #${runId} is no longer the attempt a resume can name — reload and decide against the current state`, 409);
927
+ return taskScreen(response, who, taskId, control.kind === "stopping" ? `build #${runId} is still stopping. Toolroll is making sure it has ended` : `build #${runId} is no longer the one to resume. Reload and decide again`, 409);
906
928
  }
907
929
  const digest = resumeDigestOf(taskId, runId, stop.settledAt ?? "", runtime.store.getScope(taskId));
908
930
  const nonceValue = randomBytes(18).toString("base64url");
@@ -1168,7 +1190,7 @@ export function createTaskViews(runtime) {
1168
1190
  // Editor links (arc 6): the deployment capability, THIS machine's
1169
1191
  // runner owning the run, the session's own device-side yes, and a
1170
1192
  // checkout to open — or nothing renders.
1171
- editor: runtime.options.editorLinks !== undefined && runtime.options.localRunner !== undefined && run.runner === runtime.options.localRunner && who.via === "cookie" && who.session.editorLinks === true && run.worktree !== null
1193
+ editor: runtime.options.editorLinks !== undefined && runtime.options.localRunner !== undefined && run.runner === runtime.options.localRunner && who.via === "cookie" && who.session.editorLinks === true && run.worktree !== null && existsSync(run.worktree)
1172
1194
  ? { worktree: run.worktree }
1173
1195
  : null,
1174
1196
  signedCriteria: scope?.acceptance.length ?? 0,
@@ -1231,18 +1253,28 @@ export function releaseStepsViewOf(progress, now) {
1231
1253
  const all = RELEASE_STEPS.filter(step => step !== "done");
1232
1254
  // A release that started part way (one carried under an earlier approval, or resumed from an older journal) shows
1233
1255
  // the steps from where its own record starts; a step missing between two recorded ones is a write that was lost.
1234
- const firstAt = all.findIndex(step => recorded.has(step));
1256
+ // A build running since the stop is the release's check, wherever the release last stopped; what follows it is to come.
1257
+ const building = progress.building, checkAt = all.indexOf("check");
1258
+ const firstAt = building === null ? all.findIndex(step => recorded.has(step)) : Math.min(all.findIndex(step => recorded.has(step)), checkAt);
1235
1259
  const lastAt = all.reduce((at, step, index) => recorded.has(step) ? index : at, -1);
1236
1260
  const steps = firstAt <= 0 ? all : all.slice(firstAt);
1237
1261
  const rows = steps.map(step => {
1238
1262
  const one = recorded.get(step);
1263
+ if (building !== null && step === "check") {
1264
+ const start = Date.parse(building.startedAt);
1265
+ return { name: RELEASE_STEP_WORDS[step] ?? step, st: "run", start: Number.isFinite(start) && Number.isFinite(origin) ? Math.max(0, (start - origin) / 1000) : 0, dur: Number.isFinite(start) ? Math.max(0, (now.getTime() - start) / 1000) : 0 };
1266
+ }
1267
+ if (building !== null && all.indexOf(step) > checkAt)
1268
+ return { name: RELEASE_STEP_WORDS[step] ?? step, st: "q", start: 0, dur: 0 };
1239
1269
  // A step with no record is never painted as done: between recorded ones it says so, after them it is queued.
1240
1270
  if (one === undefined)
1241
1271
  return all.indexOf(step) < lastAt ? { name: RELEASE_STEP_WORDS[step] ?? step, sub: "not recorded", st: "q", start: 0, dur: 0 }
1242
1272
  : { name: RELEASE_STEP_WORDS[step] ?? step, st: "q", start: 0, dur: 0 };
1243
1273
  const start = Date.parse(one.startedAt), end = one.endedAt === null ? now.getTime() : Date.parse(one.endedAt);
1244
- const st = one.state === "done" ? "ok" : one.state === "failed" ? "bad" : one.state === "waiting" ? "wait" : "run";
1245
- return { name: RELEASE_STEP_WORDS[step] ?? step, ...(one.detail === null || one.state === "done" ? {} : { sub: one.detail.slice(0, 160) }), st,
1274
+ // A failure the release has gone on from (resumed past it, or a build since) is history, not where it stands.
1275
+ const passed = one.state === "failed" && progress.stopped === null;
1276
+ const st = one.state === "done" || passed ? "ok" : one.state === "failed" ? "bad" : one.state === "waiting" ? "wait" : "run";
1277
+ return { name: RELEASE_STEP_WORDS[step] ?? step, ...(passed ? { sub: "Stopped here, then went on" } : one.detail === null || one.state === "done" ? {} : { sub: one.detail.slice(0, 160) }), st,
1246
1278
  start: Number.isFinite(start) && Number.isFinite(origin) ? Math.max(0, (start - origin) / 1000) : 0, dur: Number.isFinite(start) && Number.isFinite(end) ? Math.max(0, (end - start) / 1000) : 0 };
1247
1279
  });
1248
1280
  const current = rows.findIndex(row => row.st === "run" || row.st === "wait" || row.st === "bad");
@@ -1254,7 +1286,10 @@ export function releaseStepsViewOf(progress, now) {
1254
1286
  return {
1255
1287
  tag: progress.tag, version: progress.version, pr: progress.pr,
1256
1288
  rows,
1257
- state: progress.stopped !== null ? "failed" : done ? "done" : at?.st === "wait" ? "waiting" : "running",
1289
+ // Waiting is a person's act only at Approval; a step waiting on a machine (its check, GitHub's checks, quiet) is the
1290
+ // release running, never "Needs you".
1291
+ state: progress.stopped !== null ? "failed" : done ? "done" : at?.st === "wait" && steps[current] === "approval" ? "waiting" : "running",
1292
+ at: current === -1 ? null : { step: steps[current], name: at.name, index: current + 1, of: rows.length },
1258
1293
  headline: done ? `Released ${progress.version}` : progress.stopped !== null ? `Stopped at ${RELEASE_STEP_WORDS[progress.stopped.step] ?? progress.stopped.step}`
1259
1294
  : at !== null ? `${at.name} · Step ${current + 1} of ${rows.length}` : last === null ? "Starting" : `${last} done · the next step starts on its own`,
1260
1295
  stopped: progress.stopped === null ? null : { step: RELEASE_STEP_WORDS[progress.stopped.step] ?? progress.stopped.step, message: progress.stopped.message, at: progress.stopped.at },
@@ -41,17 +41,12 @@ export declare function createTasksHandlers(runtime: ServerRuntime): {
41
41
  * putting away many is an approver's step-up bound to the digest of exactly what the preview showed. Each write
42
42
  * re-proves the person's standing inside its own transaction. */
43
43
  export declare function createTidyHandlers(runtime: ServerRuntime): {
44
+ "tasks.archive": (ctx: HandlerContext) => Promise<void>;
44
45
  "work.put-away": (ctx: HandlerContext) => Promise<void>;
45
46
  "work.put-away.apply": (ctx: HandlerContext) => Promise<void>;
46
47
  "task.act.archive": (ctx: HandlerContext) => Promise<void>;
47
48
  "task.act.restore": (ctx: HandlerContext) => Promise<void>;
48
49
  };
49
- /**
50
- * Where a retired Tasks address goes now (wave A, src/design/KIT.md): Done is Finished. `board` names where the old
51
- * Board's state view goes once it is retired (Tasks' Board view; its Order view and its live fragment stay). Null: this
52
- * address still answers itself.
53
- */
54
- export declare function retiredTasksAddress(route: "board" | "done", url: URL): string | null;
55
50
  /** How many cards a Board column shows; the column's count covers them all and its "View all" opens the list. */
56
51
  export declare const BOARD_COLUMN_LIMIT = 40;
57
52
  /**
@@ -64,3 +59,19 @@ export declare function createAgentSignalHandlers(runtime: ServerRuntime): {
64
59
  "agents.seen": (ctx: HandlerContext) => Promise<void>;
65
60
  "agents.watch": (ctx: HandlerContext) => Promise<void>;
66
61
  };
62
+ /**
63
+ * One-tap release approval (docs/plans/trusted-release-reports.md, slice A): the sheet (`/t/<id>/release`), the push's
64
+ * opaque locator (`/approve/<task ref>`, a GET that only redirects to the sheet) and the sheet's approval, which the
65
+ * task approval POST hands here once its shared checks (cookie session, CSRF and the browser key at admission, the
66
+ * single-use nonce, a password or a standing proof) passed. The approval itself is the shared card wrapper around the
67
+ * unchanged approve() (release-approval.ts approveReleaseCard).
68
+ */
69
+ export declare function createReleaseSheetHandlers(runtime: ServerRuntime): {
70
+ routes: {
71
+ "task.release": (ctx: HandlerContext) => Promise<void>;
72
+ "task.release.go-on": (ctx: HandlerContext) => Promise<void>;
73
+ "release.locate": (ctx: HandlerContext) => Promise<void>;
74
+ };
75
+ sheetScreen: (ctx: Pick<HandlerContext, "who" | "response" | "project">, taskId: string, problem: string | null, status: number) => void;
76
+ approveFromSheet: (ctx: Pick<HandlerContext, "who" | "response" | "project">, taskId: string, cardDigest: string, token: string) => void;
77
+ };