toolroll 0.9.103 → 0.9.105

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 (1518) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +27 -27
  3. package/dist/accent-colors.js +0 -29
  4. package/dist/acp-agents.js +0 -3
  5. package/dist/acp-attest.js +0 -30
  6. package/dist/acp-check.js +3 -70
  7. package/dist/acp-client.js +3 -94
  8. package/dist/acp-inspect.js +1 -20
  9. package/dist/action-ledger.js +0 -8
  10. package/dist/activity-line.js +0 -14
  11. package/dist/actor.js +0 -15
  12. package/dist/advanced-schema.js +12 -0
  13. package/dist/advanced-view.js +26 -0
  14. package/dist/advanced.js +61 -0
  15. package/dist/agent-board.js +0 -117
  16. package/dist/agent-fence.js +11 -367
  17. package/dist/agent-onboard.js +12 -50
  18. package/dist/agent-pulse.js +5 -38
  19. package/dist/agent-state-words.js +0 -8
  20. package/dist/agent-state.js +1 -45
  21. package/dist/agent-turns.js +3 -17
  22. package/dist/agentconfig.js +1 -99
  23. package/dist/agents-board.js +0 -60
  24. package/dist/agents-live.js +1 -8
  25. package/dist/api-tokens.js +0 -27
  26. package/dist/approval-authority.js +0 -59
  27. package/dist/approval-password.js +0 -10
  28. package/dist/approval-policy.js +0 -29
  29. package/dist/approval-rules-ui.js +0 -9
  30. package/dist/assignment-adapters.js +0 -14
  31. package/dist/assignment-brief.js +1 -17
  32. package/dist/assignment-delivery.js +0 -22
  33. package/dist/assignment-presentation.js +0 -14
  34. package/dist/assignment-status.js +1 -30
  35. package/dist/assignment-ui.js +0 -12
  36. package/dist/assignment.js +117 -103
  37. package/dist/attest.js +0 -38
  38. package/dist/audit-cli.js +0 -9
  39. package/dist/backend.js +0 -59
  40. package/dist/backup-ui.js +0 -12
  41. package/dist/backup.js +8 -61
  42. package/dist/batch-checks.js +0 -20
  43. package/dist/batch-policy.js +0 -4
  44. package/dist/beads.js +0 -48
  45. package/dist/bin.js +0 -8
  46. package/dist/board.js +1 -36
  47. package/dist/boot-identity.js +0 -42
  48. package/dist/bounded-spawn.js +4 -28
  49. package/dist/brand-mark.js +0 -21
  50. package/dist/brief-fence.js +0 -16
  51. package/dist/browser/terminal.css +1 -1
  52. package/dist/browser/terminal.js +16 -16
  53. package/dist/browser/workspace.css +2 -2
  54. package/dist/browser/workspace.js +26 -26
  55. package/dist/browser-crew.js +0 -8
  56. package/dist/browser-shell.js +2 -15
  57. package/dist/browser-workspace.js +6 -30
  58. package/dist/budget-alerts.js +1 -4
  59. package/dist/build-review.js +2 -50
  60. package/dist/builder-restart.js +0 -13
  61. package/dist/builder.js +21 -1035
  62. package/dist/canonical-json.js +0 -12
  63. package/dist/capscan.js +1 -32
  64. package/dist/card-catalog.js +0 -12
  65. package/dist/card-cli.js +0 -1
  66. package/dist/card-render.js +0 -25
  67. package/dist/card-sources.js +0 -10
  68. package/dist/chat-acceptance.js +0 -7
  69. package/dist/chat-actions.js +5 -190
  70. package/dist/chat-admission.js +0 -7
  71. package/dist/chat-approval.js +0 -25
  72. package/dist/chat-ask.js +0 -17
  73. package/dist/chat-card-part.js +0 -3
  74. package/dist/chat-card.js +0 -6
  75. package/dist/chat-channel.js +2 -83
  76. package/dist/chat-continuity.js +0 -31
  77. package/dist/chat-controls.js +0 -7
  78. package/dist/chat-core.js +0 -55
  79. package/dist/chat-decide.js +2 -153
  80. package/dist/chat-delivery-state.js +0 -49
  81. package/dist/chat-delivery.js +2 -143
  82. package/dist/chat-display.js +0 -2
  83. package/dist/chat-evidence.js +0 -65
  84. package/dist/chat-flow.js +0 -72
  85. package/dist/chat-follow.js +0 -13
  86. package/dist/chat-inbox.js +0 -34
  87. package/dist/chat-live-schema.js +0 -14
  88. package/dist/chat-live.js +2 -87
  89. package/dist/chat-message-states.js +13 -40
  90. package/dist/chat-messages.js +0 -153
  91. package/dist/chat-migration.js +0 -57
  92. package/dist/chat-polish.js +0 -7
  93. package/dist/chat-quiet.js +0 -37
  94. package/dist/chat-review.js +0 -4
  95. package/dist/chat-rooms.js +0 -22
  96. package/dist/chat-settings-page.js +0 -4
  97. package/dist/chat-task-actions.js +0 -7
  98. package/dist/chat-terms.js +0 -21
  99. package/dist/chat-voice.js +0 -38
  100. package/dist/chat-warmth.js +1 -3
  101. package/dist/check-access.js +0 -30
  102. package/dist/check-facts.js +2 -62
  103. package/dist/check-failure.js +0 -98
  104. package/dist/check-levels-ui.js +4 -10
  105. package/dist/check-levels.js +3 -35
  106. package/dist/check-load.js +1 -49
  107. package/dist/check-only-standing.js +0 -6
  108. package/dist/check-only.js +0 -22
  109. package/dist/check-progress.js +0 -32
  110. package/dist/check-repair.js +2 -35
  111. package/dist/check-report.js +1 -108
  112. package/dist/check-stamp.js +0 -20
  113. package/dist/checkout-cleanup.js +0 -84
  114. package/dist/checkout-proof.js +1 -13
  115. package/dist/child-database.js +0 -3
  116. package/dist/claim.js +4 -508
  117. package/dist/claude-print.js +0 -10
  118. package/dist/cli-fast.js +0 -8
  119. package/dist/cli-help.js +90 -78
  120. package/dist/cli-http.js +0 -10
  121. package/dist/cli.js +26 -241
  122. package/dist/code-extract.js +0 -6
  123. package/dist/code-map-acts.js +0 -7
  124. package/dist/code-map-admission.js +2 -26
  125. package/dist/code-map-build.js +3 -24
  126. package/dist/code-map-cli.js +0 -4
  127. package/dist/code-map-main.js +0 -6
  128. package/dist/code-map-read.js +0 -12
  129. package/dist/code-map-report.js +0 -9
  130. package/dist/code-map-shape.js +0 -19
  131. package/dist/code-map-store.js +0 -26
  132. package/dist/codex-limits.js +1 -17
  133. package/dist/coding-context.js +0 -10
  134. package/dist/coding-handoff.js +0 -14
  135. package/dist/coding-provider.js +0 -39
  136. package/dist/coding-shipping-ui.js +0 -1
  137. package/dist/coding-ui.js +0 -1
  138. package/dist/coding-update.js +1 -18
  139. package/dist/coding-workspace.js +0 -27
  140. package/dist/commit-extract.js +0 -83
  141. package/dist/connect-cli.js +0 -19
  142. package/dist/console-chrome.js +1 -34
  143. package/dist/console-instance.js +2 -91
  144. package/dist/container-state.js +0 -4
  145. package/dist/containment.js +2 -105
  146. package/dist/contract-changes.js +0 -6
  147. package/dist/contracts/acceptance-terms.js +0 -7
  148. package/dist/contracts/chat-actions.js +0 -46
  149. package/dist/contracts/chat-callback-rows.js +0 -8
  150. package/dist/contracts/chat-card.js +0 -14
  151. package/dist/contracts/chat-content.js +0 -55
  152. package/dist/contracts/chat-tables.js +0 -7
  153. package/dist/contracts/cli.js +0 -59
  154. package/dist/contracts/coding-activity.js +0 -15
  155. package/dist/contracts/coding-context.js +0 -15
  156. package/dist/contracts/coding-handoff.js +0 -11
  157. package/dist/contracts/coding-workspace.js +0 -14
  158. package/dist/contracts/console-api.js +3 -54
  159. package/dist/contracts/contract-test.js +0 -14
  160. package/dist/contracts/contract.js +0 -48
  161. package/dist/contracts/decision.js +0 -20
  162. package/dist/contracts/diff-stat.js +0 -16
  163. package/dist/contracts/discord-callback.js +0 -9
  164. package/dist/contracts/flow-card.js +0 -18
  165. package/dist/contracts/flow-propose.js +0 -8
  166. package/dist/contracts/flow-send.js +0 -31
  167. package/dist/contracts/flow.js +0 -112
  168. package/dist/contracts/gateway-tools.js +0 -22
  169. package/dist/contracts/handoff.js +0 -22
  170. package/dist/contracts/integration-metadata.js +0 -39
  171. package/dist/contracts/lead-context.js +0 -14
  172. package/dist/contracts/lead-tools.js +0 -49
  173. package/dist/contracts/mcp-oauth.js +0 -12
  174. package/dist/contracts/memory-pass.js +0 -21
  175. package/dist/contracts/model-catalog.js +0 -9
  176. package/dist/contracts/observation-request.js +0 -11
  177. package/dist/contracts/plan.js +0 -16
  178. package/dist/contracts/project-knowledge.js +0 -26
  179. package/dist/contracts/project-memory.js +0 -16
  180. package/dist/contracts/project-skills.js +0 -31
  181. package/dist/contracts/proof.js +0 -23
  182. package/dist/contracts/provider.js +0 -9
  183. package/dist/contracts/recipes.js +0 -16
  184. package/dist/contracts/release-check.js +0 -61
  185. package/dist/contracts/release-terms.js +0 -27
  186. package/dist/contracts/retention.js +0 -12
  187. package/dist/contracts/review-findings.js +0 -13
  188. package/dist/contracts/route-results.js +0 -15
  189. package/dist/contracts/route.js +0 -33
  190. package/dist/contracts/scope.js +0 -29
  191. package/dist/contracts/scout-report.js +0 -34
  192. package/dist/contracts/slack-callback.js +0 -11
  193. package/dist/contracts/sort-answer.js +0 -24
  194. package/dist/contracts/stage-output.js +0 -46
  195. package/dist/contracts/storage.js +0 -8
  196. package/dist/contracts/store-json.js +0 -41
  197. package/dist/contracts/subagent-turn.js +0 -23
  198. package/dist/contracts/task-sizing.js +0 -10
  199. package/dist/contracts/teams-callback.js +0 -7
  200. package/dist/contracts/telegram-callback.js +0 -27
  201. package/dist/contracts/trigger-payloads.js +0 -41
  202. package/dist/contracts/update-journal.js +0 -47
  203. package/dist/contracts/verification-receipt.js +0 -36
  204. package/dist/contracts/verification-view.js +0 -15
  205. package/dist/contracts/youiyoux-request.js +0 -26
  206. package/dist/control-setup.js +0 -7
  207. package/dist/control-ui.js +0 -3
  208. package/dist/controller-service.js +0 -4
  209. package/dist/controller-supervisor.js +0 -15
  210. package/dist/converse.js +3 -129
  211. package/dist/coordinator-proposals.js +1 -6
  212. package/dist/coordinator.js +0 -65
  213. package/dist/credentials-ui.js +0 -6
  214. package/dist/daemon.js +0 -137
  215. package/dist/database-reclaim.js +0 -3
  216. package/dist/decision.js +0 -78
  217. package/dist/demo-chat.js +4 -15
  218. package/dist/demo-sign-in.js +77 -0
  219. package/dist/demo.js +5 -194
  220. package/dist/deploy-gate.js +0 -20
  221. package/dist/deploy-lock.js +0 -4
  222. package/dist/deploy-phase.js +0 -22
  223. package/dist/deploy-rescue.js +0 -21
  224. package/dist/deprecations.js +0 -12
  225. package/dist/design/kit.css +9 -6
  226. package/dist/design/kit.js +2 -33
  227. package/dist/desktop-access.js +0 -9
  228. package/dist/desktop-bundle.js +1 -3
  229. package/dist/desktop-host.js +0 -34
  230. package/dist/desktop-update-gate.js +0 -8
  231. package/dist/desktop-update-recovery.js +1 -18
  232. package/dist/desktop-update.js +2 -48
  233. package/dist/digest-times.js +0 -2
  234. package/dist/disclosure.js +0 -5
  235. package/dist/discord-api.js +0 -6
  236. package/dist/discord-chat.js +0 -31
  237. package/dist/discord.js +0 -7
  238. package/dist/discover.js +0 -50
  239. package/dist/dispatch.js +61 -60
  240. package/dist/dispose.js +0 -208
  241. package/dist/doctor.js +0 -48
  242. package/dist/easy-start-args.js +7 -7
  243. package/dist/easy-start.js +32 -45
  244. package/dist/egress.js +1 -63
  245. package/dist/email-settings.js +0 -8
  246. package/dist/envelope.js +50 -86
  247. package/dist/eval-gate.js +1 -37
  248. package/dist/eval-hooks.js +0 -120
  249. package/dist/eval-oracle-main.js +0 -7
  250. package/dist/eval-oracle.js +3 -42
  251. package/dist/eval-world.js +1 -23
  252. package/dist/evals.js +6 -134
  253. package/dist/evidence-pack.js +0 -29
  254. package/dist/evidence-pair.js +0 -17
  255. package/dist/evidence.js +4 -280
  256. package/dist/exec.js +19 -404
  257. package/dist/exhaustion.js +0 -30
  258. package/dist/export-ui.js +0 -7
  259. package/dist/export.js +1 -38
  260. package/dist/failing-first.js +0 -6
  261. package/dist/fallback-schema.js +0 -5
  262. package/dist/fallback.js +0 -81
  263. package/dist/fast-start.js +0 -97
  264. package/dist/fast-terms.js +0 -3
  265. package/dist/fenced-check-coverage.js +0 -11
  266. package/dist/findings.js +1 -63
  267. package/dist/first-run.js +4 -57
  268. package/dist/first-tasks-child.js +0 -5
  269. package/dist/flaky-ci.js +1 -24
  270. package/dist/flaky-cli.js +0 -4
  271. package/dist/flaky.js +0 -43
  272. package/dist/fleet-schema.js +0 -11
  273. package/dist/flow-actions.js +0 -31
  274. package/dist/flow-browser.js +0 -42
  275. package/dist/flow-cadence.js +1 -24
  276. package/dist/flow-card-task.js +0 -11
  277. package/dist/flow-changed.js +0 -16
  278. package/dist/flow-code.js +1 -45
  279. package/dist/flow-draft.js +0 -17
  280. package/dist/flow-engine.js +2 -76
  281. package/dist/flow-gallery-ui.js +0 -28
  282. package/dist/flow-gallery.js +0 -54
  283. package/dist/flow-insights.js +0 -12
  284. package/dist/flow-items.js +0 -27
  285. package/dist/flow-live.js +0 -31
  286. package/dist/flow-people.js +0 -14
  287. package/dist/flow-pull-request.js +0 -32
  288. package/dist/flow-replies.js +0 -9
  289. package/dist/flow-result-card.js +0 -8
  290. package/dist/flow-schedule.js +0 -74
  291. package/dist/flow-scripts.js +0 -13
  292. package/dist/flow-secrets.js +0 -10
  293. package/dist/flow-send.js +0 -45
  294. package/dist/flow-share.js +0 -60
  295. package/dist/flow-sort.js +1 -24
  296. package/dist/flow-starters-ui.js +0 -2
  297. package/dist/flow-starters.js +0 -13
  298. package/dist/flow-steps.js +0 -80
  299. package/dist/flow-triggers.js +2 -256
  300. package/dist/flow-unattended-words.js +0 -13
  301. package/dist/flow-unattended.js +2 -115
  302. package/dist/flows-cli.js +2 -36
  303. package/dist/flows-ui.js +0 -51
  304. package/dist/flows.js +0 -158
  305. package/dist/folder-gate.js +0 -21
  306. package/dist/folder-look.js +0 -42
  307. package/dist/follow-through-brief.js +0 -6
  308. package/dist/follow-through-cli.js +0 -5
  309. package/dist/fonts.js +0 -13
  310. package/dist/gaps.js +0 -20
  311. package/dist/gate-failure.js +0 -7
  312. package/dist/git-floor.js +0 -12
  313. package/dist/git-incident.js +2 -38
  314. package/dist/git-views.js +0 -24
  315. package/dist/git.js +0 -31
  316. package/dist/github-import.js +0 -22
  317. package/dist/github-jobs.js +0 -12
  318. package/dist/google-mail.js +2 -27
  319. package/dist/grant.js +0 -110
  320. package/dist/graph.js +0 -108
  321. package/dist/guides.js +4 -15
  322. package/dist/handover-note.js +0 -12
  323. package/dist/health-cli.js +0 -2
  324. package/dist/home-groups.js +0 -15
  325. package/dist/html.js +0 -54
  326. package/dist/install-method.js +0 -12
  327. package/dist/integrations-ui.js +0 -15
  328. package/dist/integrations.js +7 -50
  329. package/dist/invoke.js +1 -381
  330. package/dist/is-record.js +0 -1
  331. package/dist/issues.js +0 -48
  332. package/dist/jsonl-discriminants.js +0 -6
  333. package/dist/keymap.js +2 -16
  334. package/dist/keys.js +0 -56
  335. package/dist/kits-ui.js +0 -3
  336. package/dist/kits.js +1 -24
  337. package/dist/knowledge-cli.js +0 -4
  338. package/dist/knowledge-ui.js +0 -8
  339. package/dist/landed-cleanup.js +0 -119
  340. package/dist/laptop-background.js +0 -85
  341. package/dist/laptop-service.js +0 -67
  342. package/dist/latency-timeline.js +2 -23
  343. package/dist/lead-about.js +0 -7
  344. package/dist/lead-answer-eval.js +0 -39
  345. package/dist/lead-capabilities.js +0 -19
  346. package/dist/lead-cli-live.js +0 -22
  347. package/dist/lead-cli.js +0 -27
  348. package/dist/lead-commitments.js +1 -27
  349. package/dist/lead-context.js +2 -42
  350. package/dist/lead-contract.js +0 -8
  351. package/dist/lead-doors.js +0 -105
  352. package/dist/lead-follow.js +0 -41
  353. package/dist/lead-identity.js +1 -4
  354. package/dist/lead-latency-schema.js +0 -13
  355. package/dist/lead-people.js +3 -18
  356. package/dist/lead-progress.js +0 -12
  357. package/dist/lead-queue-runtime.js +0 -26
  358. package/dist/lead-queue.js +0 -35
  359. package/dist/lead-route.js +0 -33
  360. package/dist/lead-status.js +0 -37
  361. package/dist/lead-sweep.js +0 -18
  362. package/dist/lead-tools.js +0 -160
  363. package/dist/lead-voice.js +0 -54
  364. package/dist/lead.js +2 -105
  365. package/dist/learning-child.js +0 -6
  366. package/dist/learning-look.js +0 -14
  367. package/dist/ledger-chain.js +0 -34
  368. package/dist/ledger-csv.js +0 -2
  369. package/dist/ledger-view.js +0 -3
  370. package/dist/lesson-notes.js +0 -56
  371. package/dist/limits-ui.js +0 -14
  372. package/dist/link.js +0 -79
  373. package/dist/live-backup.js +3 -33
  374. package/dist/live-bus.js +7 -81
  375. package/dist/live-children-read.js +4 -47
  376. package/dist/live-children.js +4 -44
  377. package/dist/live-detail.js +0 -17
  378. package/dist/live-input.js +5 -68
  379. package/dist/live-main-read.js +1 -14
  380. package/dist/live-notes.js +0 -12
  381. package/dist/live-open.js +1 -23
  382. package/dist/live-records.js +4 -151
  383. package/dist/live-reply.js +1 -51
  384. package/dist/live-terminal.js +12 -111
  385. package/dist/live.js +4 -130
  386. package/dist/local-owner-acts.js +168 -0
  387. package/dist/local-owner.js +15 -80
  388. package/dist/log.js +0 -8
  389. package/dist/login-secrets.js +2 -38
  390. package/dist/machine-check.js +0 -2
  391. package/dist/machine-identity.js +1 -46
  392. package/dist/mailbox.js +0 -30
  393. package/dist/maintenance.js +1 -3
  394. package/dist/mcp-connect.js +0 -88
  395. package/dist/mcp-core.js +0 -45
  396. package/dist/mcp-http.js +0 -13
  397. package/dist/mcp-oauth.js +0 -37
  398. package/dist/mcp-person.js +0 -11
  399. package/dist/mcp.js +3 -73
  400. package/dist/memory-cli.js +0 -3
  401. package/dist/memory-pass.js +0 -53
  402. package/dist/memory-tidy.js +0 -55
  403. package/dist/memory-use.js +2 -24
  404. package/dist/merge-checklist.js +21 -29
  405. package/dist/metrics.js +0 -10
  406. package/dist/mobile-viewport.js +0 -6
  407. package/dist/model-catalog.js +1 -33
  408. package/dist/model-choices.js +9 -84
  409. package/dist/model-names.js +0 -9
  410. package/dist/models-cli.js +0 -13
  411. package/dist/models-ui.js +0 -17
  412. package/dist/modes.js +0 -35
  413. package/dist/monitoring-settings.js +2 -27
  414. package/dist/monitoring-ui.js +2 -14
  415. package/dist/monitoring.js +2 -38
  416. package/dist/names.js +0 -39
  417. package/dist/needs-you.js +7 -70
  418. package/dist/never-index.js +0 -9
  419. package/dist/nightly-check.js +0 -74
  420. package/dist/nightly-github.js +0 -168
  421. package/dist/notification-delivery.js +0 -3
  422. package/dist/notification-rows.js +0 -17
  423. package/dist/oauth-run-token.js +1 -37
  424. package/dist/observations.js +0 -16
  425. package/dist/oidc.js +1 -20
  426. package/dist/onboard.js +4 -57
  427. package/dist/one-step-chat-schema.js +0 -15
  428. package/dist/openrouter-models.js +0 -6
  429. package/dist/operate-remote-arguments.js +2 -17
  430. package/dist/operate-remote.js +0 -33
  431. package/dist/operate.js +280 -2304
  432. package/dist/orphan-sweep.js +3 -37
  433. package/dist/page-work-contract.js +0 -3
  434. package/dist/password-bearer.js +1 -11
  435. package/dist/passwordless.js +0 -3
  436. package/dist/peek-cli.js +0 -46
  437. package/dist/peek.js +2 -61
  438. package/dist/people-audit-ui.js +0 -6
  439. package/dist/person-proof.js +0 -6
  440. package/dist/phase-routing.js +8 -183
  441. package/dist/plain-schema.js +0 -14
  442. package/dist/plain-words.js +18 -12
  443. package/dist/plan-auto.js +3 -18
  444. package/dist/plan-login.js +0 -16
  445. package/dist/plan.js +0 -68
  446. package/dist/plane-review.js +0 -56
  447. package/dist/planner-source.js +0 -96
  448. package/dist/planner.js +0 -117
  449. package/dist/policy-ui.js +0 -8
  450. package/dist/policy.js +0 -47
  451. package/dist/prepared-evidence.js +0 -5
  452. package/dist/principal.js +0 -29
  453. package/dist/probe.js +0 -30
  454. package/dist/process-custody.js +0 -15
  455. package/dist/process-liveness.js +0 -32
  456. package/dist/process-tree.js +3 -29
  457. package/dist/project-access.js +0 -10
  458. package/dist/project-admission.js +1 -41
  459. package/dist/project-cli.js +0 -6
  460. package/dist/project-concurrency.js +0 -35
  461. package/dist/project-delete-ui.js +4 -29
  462. package/dist/project-delete.js +1 -73
  463. package/dist/project-demo.js +0 -13
  464. package/dist/project-file.js +0 -2
  465. package/dist/project-identity.js +0 -41
  466. package/dist/project-knowledge.js +0 -39
  467. package/dist/project-learning.js +3 -55
  468. package/dist/project-memory.js +2 -45
  469. package/dist/project-outcomes.js +0 -6
  470. package/dist/project-sandbox.js +0 -23
  471. package/dist/project-skills.js +0 -12
  472. package/dist/project-tools.js +6 -184
  473. package/dist/project.js +0 -48
  474. package/dist/prompt.js +0 -31
  475. package/dist/proof.js +0 -220
  476. package/dist/proposal.js +0 -50
  477. package/dist/protected-storage-look.js +0 -6
  478. package/dist/protected-storage.js +1 -84
  479. package/dist/provider-auth.js +3 -69
  480. package/dist/provider-capture.js +1 -15
  481. package/dist/provider-connection.js +0 -8
  482. package/dist/provider-home.js +0 -25
  483. package/dist/provider-limits.js +0 -14
  484. package/dist/provider.js +0 -324
  485. package/dist/public-access.js +11 -30
  486. package/dist/public-check.js +0 -16
  487. package/dist/publish.js +1 -150
  488. package/dist/pull-request-flow.js +6 -74
  489. package/dist/pull-request-schema.js +0 -4
  490. package/dist/pull-request-ui.js +0 -5
  491. package/dist/pulls.js +0 -80
  492. package/dist/push.js +5 -89
  493. package/dist/quick-start.js +1 -23
  494. package/dist/read-executor-worker.js +0 -1
  495. package/dist/read-executor.js +0 -10
  496. package/dist/read-only-request.js +0 -7
  497. package/dist/recipe-ui.js +0 -6
  498. package/dist/recipes.js +0 -13
  499. package/dist/release-adapters.js +6 -214
  500. package/dist/release-approval.js +0 -74
  501. package/dist/release-authority.js +0 -42
  502. package/dist/release-auto.js +0 -142
  503. package/dist/release-card.js +26 -103
  504. package/dist/release-carry.js +0 -132
  505. package/dist/release-ci-hold.js +0 -20
  506. package/dist/release-cli.js +0 -46
  507. package/dist/release-coverage.js +0 -16
  508. package/dist/release-gate.js +0 -30
  509. package/dist/release-git.js +0 -24
  510. package/dist/release-links.js +0 -17
  511. package/dist/release-net.js +0 -42
  512. package/dist/release-next.js +0 -25
  513. package/dist/release-recheck.js +0 -89
  514. package/dist/release-refusal.js +0 -18
  515. package/dist/release-view.js +0 -5
  516. package/dist/release.js +7 -341
  517. package/dist/releases.js +0 -49
  518. package/dist/remote-audit.js +0 -25
  519. package/dist/remote-command.js +0 -16
  520. package/dist/remote-destination.js +5 -26
  521. package/dist/remote-exec.js +1 -27
  522. package/dist/remote-main.js +1 -53
  523. package/dist/remote-run.js +0 -5
  524. package/dist/remote.js +0 -49
  525. package/dist/render.js +0 -133
  526. package/dist/reply-shape.js +0 -85
  527. package/dist/reply-voice.js +0 -7
  528. package/dist/report-summary.js +0 -5
  529. package/dist/reported-usage.js +0 -30
  530. package/dist/repos.js +9 -62
  531. package/dist/repository-context.js +1 -24
  532. package/dist/request-budget-ui.js +0 -4
  533. package/dist/request-budget.js +0 -23
  534. package/dist/restart-certification.js +0 -37
  535. package/dist/result-actions.js +0 -62
  536. package/dist/result-acts.js +0 -34
  537. package/dist/result-completion.js +9 -28
  538. package/dist/result-evidence-readers.js +0 -3
  539. package/dist/result-follow-ups.js +1 -39
  540. package/dist/result-review.js +0 -86
  541. package/dist/result-shots.js +0 -39
  542. package/dist/retention-ui.js +0 -7
  543. package/dist/retention.js +2 -46
  544. package/dist/review-context.js +0 -129
  545. package/dist/review-evidence.js +0 -4
  546. package/dist/review-switch.js +1 -7
  547. package/dist/reviewer.js +0 -35
  548. package/dist/route-change-check.js +0 -2
  549. package/dist/route-change.js +0 -16
  550. package/dist/route-hooks.js +0 -27
  551. package/dist/route-results.js +2 -58
  552. package/dist/route-rules.js +1 -106
  553. package/dist/route-savings.js +0 -36
  554. package/dist/route-store.js +1 -133
  555. package/dist/run-closeout.js +2 -50
  556. package/dist/run-efficiency.js +2 -44
  557. package/dist/run-ending.js +0 -13
  558. package/dist/runner-process.js +0 -33
  559. package/dist/runner.js +17 -189
  560. package/dist/sample-project.js +2 -27
  561. package/dist/sandbox-launch.js +4 -25
  562. package/dist/sandbox-runtime.js +1 -88
  563. package/dist/scan.js +0 -27
  564. package/dist/scope.js +88 -566
  565. package/dist/scout-browser-lock.js +0 -6
  566. package/dist/scout-browser.js +2 -68
  567. package/dist/scout-net.js +1 -32
  568. package/dist/scout-report.js +0 -22
  569. package/dist/scout.js +1 -116
  570. package/dist/secret-mint.js +0 -6
  571. package/dist/serve.js +29 -564
  572. package/dist/server/agents-computers.js +0 -10
  573. package/dist/server/agents-live-filed.js +0 -13
  574. package/dist/server/agents-live-lead.js +0 -19
  575. package/dist/server/agents-live-room.js +0 -19
  576. package/dist/server/chat.js +2 -194
  577. package/dist/server/chrome.js +17 -263
  578. package/dist/server/console.css +4 -4
  579. package/dist/server/edge-refusal.js +0 -3
  580. package/dist/server/flows.js +5 -74
  581. package/dist/server/guards.js +9 -86
  582. package/dist/server/handler-registry.js +0 -2
  583. package/dist/server/home-asks.js +1 -22
  584. package/dist/server/home.js +1 -30
  585. package/dist/server/http.js +0 -82
  586. package/dist/server/in-place.js +0 -15
  587. package/dist/server/kit-standalone.js +0 -20
  588. package/dist/server/kit.js +2 -114
  589. package/dist/server/last-checks.js +0 -2
  590. package/dist/server/live.js +1 -36
  591. package/dist/server/merge-ready-view.js +0 -6
  592. package/dist/server/mutation-key.js +3 -40
  593. package/dist/server/pages-assets.js +0 -16
  594. package/dist/server/pages.js +7 -195
  595. package/dist/server/people-tokens.js +3 -101
  596. package/dist/server/remote-hooks.js +0 -13
  597. package/dist/server/remote.js +0 -28
  598. package/dist/server/render-chat.js +8 -144
  599. package/dist/server/render-code-map.js +0 -5
  600. package/dist/server/render-flaky.js +0 -8
  601. package/dist/server/render-follow-through.js +2 -5
  602. package/dist/server/render-history.js +2 -34
  603. package/dist/server/render-new-task.js +2 -29
  604. package/dist/server/render-pages.js +1 -111
  605. package/dist/server/render-people.js +2 -46
  606. package/dist/server/render-projects.js +15 -32
  607. package/dist/server/render-release.js +1 -14
  608. package/dist/server/render-results.js +4 -355
  609. package/dist/server/render-settings.js +0 -15
  610. package/dist/server/render-tasks.js +17 -497
  611. package/dist/server/request-context.js +2 -9
  612. package/dist/server/retired-routes.js +0 -11
  613. package/dist/server/route-policy.js +0 -3
  614. package/dist/server/route-table.js +8 -133
  615. package/dist/server/runtime.js +0 -1
  616. package/dist/server/session.js +0 -28
  617. package/dist/server/settings.js +40 -246
  618. package/dist/server/signup-gate.js +0 -11
  619. package/dist/server/sweeps.js +0 -6
  620. package/dist/server/task-views.js +12 -227
  621. package/dist/server/tasks.js +37 -531
  622. package/dist/server/terminals.js +2 -46
  623. package/dist/server/welcome.js +2 -22
  624. package/dist/server-telemetry.js +0 -9
  625. package/dist/settings-groups-ui.js +50 -63
  626. package/dist/settings-kit-script.js +0 -19
  627. package/dist/settings-kit.js +0 -63
  628. package/dist/settings-proofs.js +0 -23
  629. package/dist/setup-guide.js +1 -9
  630. package/dist/shared-deps.js +9 -84
  631. package/dist/sign-in-guard.js +0 -27
  632. package/dist/skills-ui.js +0 -2
  633. package/dist/skills.js +2 -54
  634. package/dist/slack-api.js +0 -3
  635. package/dist/slack-chat.js +0 -25
  636. package/dist/slack-settings.js +0 -1
  637. package/dist/slack-socket.js +0 -5
  638. package/dist/slack.js +0 -4
  639. package/dist/sleep.js +0 -1
  640. package/dist/source-key.js +0 -10
  641. package/dist/spend-report.js +0 -29
  642. package/dist/spend-ui.js +0 -26
  643. package/dist/spend.js +0 -40
  644. package/dist/sqlite-runtime.js +0 -2
  645. package/dist/sqlite-telemetry.js +0 -9
  646. package/dist/sso-settings.js +0 -13
  647. package/dist/sso-ui.js +0 -2
  648. package/dist/staged-runtimes.js +5 -39
  649. package/dist/steer-capabilities.js +1 -7
  650. package/dist/steer-controls.js +0 -10
  651. package/dist/steer-live.js +0 -31
  652. package/dist/steer-mailbox.js +4 -65
  653. package/dist/steer-status.js +0 -7
  654. package/dist/stop-proof.js +5 -62
  655. package/dist/storage-sweep-child.js +1 -5
  656. package/dist/storage-sweep-process.js +2 -20
  657. package/dist/storage-sweep-schedule.js +0 -32
  658. package/dist/storage-sweep.js +2 -51
  659. package/dist/storage-ui.js +0 -18
  660. package/dist/storage.js +0 -31
  661. package/dist/store-baseline.js +0 -14
  662. package/dist/store.js +109 -4763
  663. package/dist/stream-scope.js +0 -16
  664. package/dist/structured-output.js +0 -39
  665. package/dist/style-asset.js +0 -2
  666. package/dist/subagent-admin.js +0 -9
  667. package/dist/subagent-desk.js +0 -29
  668. package/dist/subagent-memory.js +0 -38
  669. package/dist/subagent-question.js +0 -29
  670. package/dist/subagent-tools.js +1 -60
  671. package/dist/subagent-week.js +0 -28
  672. package/dist/subagent-work.js +1 -39
  673. package/dist/subagents-ui.js +1 -13
  674. package/dist/subagents.js +0 -40
  675. package/dist/subscription-chat.js +1 -42
  676. package/dist/summary.js +0 -19
  677. package/dist/surface.js +8 -73
  678. package/dist/sweep-gate.js +0 -2
  679. package/dist/sweep-quarantine.js +2 -13
  680. package/dist/sync.js +0 -47
  681. package/dist/tailnet.js +0 -9
  682. package/dist/tamper-scan.js +0 -15
  683. package/dist/task-activity.js +1 -16
  684. package/dist/task-aliases.js +0 -3
  685. package/dist/task-archive.js +0 -7
  686. package/dist/task-base.js +0 -18
  687. package/dist/task-composer.js +0 -2
  688. package/dist/task-control.js +0 -74
  689. package/dist/task-live.js +0 -23
  690. package/dist/task-moves.js +0 -28
  691. package/dist/task-outcome-cli.js +66 -19
  692. package/dist/task-review-brief.js +0 -7
  693. package/dist/task-sizing.js +0 -47
  694. package/dist/task-source.js +0 -23
  695. package/dist/task-status.js +0 -106
  696. package/dist/task-text.js +0 -12
  697. package/dist/team-chat-authorization.js +0 -3
  698. package/dist/team-contract.js +0 -2
  699. package/dist/team-http.js +0 -4
  700. package/dist/team-leads.js +1 -16
  701. package/dist/team-runtime.js +0 -13
  702. package/dist/team-ui.js +0 -1
  703. package/dist/team-updates.js +0 -4
  704. package/dist/teams-api.js +0 -12
  705. package/dist/teams-chat.js +0 -28
  706. package/dist/teams.js +0 -12
  707. package/dist/teardown-git.js +6 -294
  708. package/dist/telegram-flow.js +0 -51
  709. package/dist/telegram-lead.js +2 -203
  710. package/dist/telegram-live.js +1 -42
  711. package/dist/telegram-progress.js +0 -18
  712. package/dist/telegram-settings.js +0 -7
  713. package/dist/telegram-status.js +0 -46
  714. package/dist/telegram-team.js +1 -33
  715. package/dist/telegram.js +6 -454
  716. package/dist/templates.js +0 -24
  717. package/dist/terminal-catalog.js +2 -20
  718. package/dist/terminal-text.js +0 -12
  719. package/dist/test-infra.js +0 -50
  720. package/dist/test-temp.js +3 -26
  721. package/dist/text-limits.js +0 -92
  722. package/dist/tidy.js +0 -76
  723. package/dist/tier-report.js +0 -2
  724. package/dist/token-notices.js +1 -9
  725. package/dist/tokens-cli.js +0 -13
  726. package/dist/tool-broker.js +2 -53
  727. package/dist/tool-launcher.js +0 -14
  728. package/dist/tool-secret-store.js +3 -125
  729. package/dist/toolroll-update-cli.js +0 -9
  730. package/dist/toolroll-update-ui.js +0 -14
  731. package/dist/toolroll-update.js +13 -252
  732. package/dist/tools-ui.js +0 -17
  733. package/dist/transitions-recipes.js +0 -2
  734. package/dist/tree-proof.js +0 -23
  735. package/dist/tui-contract.js +0 -8
  736. package/dist/tui-source.js +91 -40
  737. package/dist/tui.js +54 -54
  738. package/dist/typed-start.js +0 -27
  739. package/dist/unfenced-test-support.js +0 -5
  740. package/dist/up-processes.js +1 -40
  741. package/dist/up-role-child.js +1 -13
  742. package/dist/update-notice.js +0 -1
  743. package/dist/vanished-retry.js +0 -40
  744. package/dist/verification-evidence.js +0 -39
  745. package/dist/version.js +0 -1
  746. package/dist/wake-hub.js +0 -28
  747. package/dist/webhook-limits.js +0 -7
  748. package/dist/webhook-readers.js +0 -30
  749. package/dist/webhook-signing.js +0 -14
  750. package/dist/webhooks.js +0 -54
  751. package/dist/welcome-facts.js +2 -14
  752. package/dist/when-html.js +0 -27
  753. package/dist/work-index.js +26 -98
  754. package/dist/work-summary.js +2 -17
  755. package/dist/workspace-motion.js +0 -2
  756. package/dist/workspace-revision.js +1 -21
  757. package/dist/workspace-ui.js +15 -135
  758. package/dist/worktree-notices.js +0 -3
  759. package/dist/worktree.js +0 -308
  760. package/dist/writes-mode.js +0 -1
  761. package/dist/youiyoux-intake.js +4 -159
  762. package/package.json +5 -4
  763. package/dist/accent-colors.d.ts +0 -51
  764. package/dist/acp-agents.d.ts +0 -43
  765. package/dist/acp-attest.d.ts +0 -44
  766. package/dist/acp-check.d.ts +0 -37
  767. package/dist/acp-client.d.ts +0 -163
  768. package/dist/acp-inspect.d.ts +0 -23
  769. package/dist/action-ledger.d.ts +0 -27
  770. package/dist/activity-line.d.ts +0 -29
  771. package/dist/actor.d.ts +0 -11
  772. package/dist/agent-board.d.ts +0 -229
  773. package/dist/agent-fence.d.ts +0 -479
  774. package/dist/agent-onboard.d.ts +0 -158
  775. package/dist/agent-pulse.d.ts +0 -43
  776. package/dist/agent-state-words.d.ts +0 -19
  777. package/dist/agent-state.d.ts +0 -65
  778. package/dist/agent-turns.d.ts +0 -52
  779. package/dist/agentconfig.d.ts +0 -191
  780. package/dist/agents-board.d.ts +0 -145
  781. package/dist/agents-live.d.ts +0 -31
  782. package/dist/api-tokens.d.ts +0 -80
  783. package/dist/approval-authority.d.ts +0 -51
  784. package/dist/approval-password.d.ts +0 -31
  785. package/dist/approval-policy.d.ts +0 -69
  786. package/dist/approval-rules-ui.d.ts +0 -40
  787. package/dist/assignment-adapters.d.ts +0 -152
  788. package/dist/assignment-brief.d.ts +0 -83
  789. package/dist/assignment-delivery.d.ts +0 -86
  790. package/dist/assignment-presentation.d.ts +0 -37
  791. package/dist/assignment-status.d.ts +0 -71
  792. package/dist/assignment-ui.d.ts +0 -68
  793. package/dist/assignment.d.ts +0 -318
  794. package/dist/attest.d.ts +0 -59
  795. package/dist/audit-cli.d.ts +0 -17
  796. package/dist/backend.d.ts +0 -97
  797. package/dist/backup-ui.d.ts +0 -32
  798. package/dist/backup.d.ts +0 -92
  799. package/dist/batch-checks.d.ts +0 -15
  800. package/dist/batch-policy.d.ts +0 -23
  801. package/dist/beads.d.ts +0 -34
  802. package/dist/bin.d.ts +0 -2
  803. package/dist/board.d.ts +0 -134
  804. package/dist/boot-identity.d.ts +0 -64
  805. package/dist/bounded-spawn.d.ts +0 -57
  806. package/dist/brand-icons.d.ts +0 -168
  807. package/dist/brand-mark.d.ts +0 -28
  808. package/dist/brief-fence.d.ts +0 -9
  809. package/dist/browser-crew.d.ts +0 -12
  810. package/dist/browser-shell.d.ts +0 -9
  811. package/dist/browser-workspace.d.ts +0 -1972
  812. package/dist/budget-alerts.d.ts +0 -19
  813. package/dist/build-review.d.ts +0 -38
  814. package/dist/builder-restart.d.ts +0 -21
  815. package/dist/builder.d.ts +0 -409
  816. package/dist/canonical-json.d.ts +0 -14
  817. package/dist/capscan.d.ts +0 -35
  818. package/dist/card-catalog.d.ts +0 -209
  819. package/dist/card-cli.d.ts +0 -43
  820. package/dist/card-render.d.ts +0 -43
  821. package/dist/card-sources.d.ts +0 -68
  822. package/dist/chat-acceptance.d.ts +0 -74
  823. package/dist/chat-actions.d.ts +0 -460
  824. package/dist/chat-admission.d.ts +0 -19
  825. package/dist/chat-approval.d.ts +0 -58
  826. package/dist/chat-ask.d.ts +0 -32
  827. package/dist/chat-card-part.d.ts +0 -11
  828. package/dist/chat-card.d.ts +0 -46
  829. package/dist/chat-channel.d.ts +0 -126
  830. package/dist/chat-continuity.d.ts +0 -32
  831. package/dist/chat-controls.d.ts +0 -117
  832. package/dist/chat-core.d.ts +0 -177
  833. package/dist/chat-decide.d.ts +0 -269
  834. package/dist/chat-delivery-state.d.ts +0 -132
  835. package/dist/chat-delivery.d.ts +0 -71
  836. package/dist/chat-display.d.ts +0 -1
  837. package/dist/chat-evidence.d.ts +0 -123
  838. package/dist/chat-flow.d.ts +0 -70
  839. package/dist/chat-follow.d.ts +0 -20
  840. package/dist/chat-inbox.d.ts +0 -57
  841. package/dist/chat-live-schema.d.ts +0 -17
  842. package/dist/chat-live.d.ts +0 -161
  843. package/dist/chat-message-states.d.ts +0 -75
  844. package/dist/chat-messages.d.ts +0 -338
  845. package/dist/chat-migration.d.ts +0 -30
  846. package/dist/chat-polish.d.ts +0 -17
  847. package/dist/chat-quiet.d.ts +0 -40
  848. package/dist/chat-review.d.ts +0 -51
  849. package/dist/chat-rooms.d.ts +0 -123
  850. package/dist/chat-settings-page.d.ts +0 -43
  851. package/dist/chat-task-actions.d.ts +0 -59
  852. package/dist/chat-terms.d.ts +0 -29
  853. package/dist/chat-voice.d.ts +0 -69
  854. package/dist/chat-warmth.d.ts +0 -21
  855. package/dist/check-access.d.ts +0 -54
  856. package/dist/check-facts.d.ts +0 -126
  857. package/dist/check-failure.d.ts +0 -113
  858. package/dist/check-levels-ui.d.ts +0 -36
  859. package/dist/check-levels.d.ts +0 -70
  860. package/dist/check-load.d.ts +0 -85
  861. package/dist/check-only-standing.d.ts +0 -36
  862. package/dist/check-only.d.ts +0 -15
  863. package/dist/check-progress.d.ts +0 -78
  864. package/dist/check-repair.d.ts +0 -47
  865. package/dist/check-report.d.ts +0 -177
  866. package/dist/check-stamp.d.ts +0 -46
  867. package/dist/checkout-cleanup.d.ts +0 -157
  868. package/dist/checkout-proof.d.ts +0 -28
  869. package/dist/child-database.d.ts +0 -12
  870. package/dist/claim.d.ts +0 -627
  871. package/dist/claude-print.d.ts +0 -12
  872. package/dist/cli-fast.d.ts +0 -8
  873. package/dist/cli-help.d.ts +0 -8
  874. package/dist/cli-http.d.ts +0 -58
  875. package/dist/cli.d.ts +0 -149
  876. package/dist/code-extract.d.ts +0 -44
  877. package/dist/code-map-acts.d.ts +0 -24
  878. package/dist/code-map-admission.d.ts +0 -52
  879. package/dist/code-map-build.d.ts +0 -63
  880. package/dist/code-map-cli.d.ts +0 -153
  881. package/dist/code-map-main.d.ts +0 -1
  882. package/dist/code-map-read.d.ts +0 -106
  883. package/dist/code-map-report.d.ts +0 -37
  884. package/dist/code-map-shape.d.ts +0 -172
  885. package/dist/code-map-store.d.ts +0 -136
  886. package/dist/codex-limits.d.ts +0 -15
  887. package/dist/coding-context.d.ts +0 -18
  888. package/dist/coding-handoff.d.ts +0 -39
  889. package/dist/coding-provider.d.ts +0 -88
  890. package/dist/coding-shipping-ui.d.ts +0 -5
  891. package/dist/coding-types.d.ts +0 -16
  892. package/dist/coding-ui.d.ts +0 -19
  893. package/dist/coding-update.d.ts +0 -28
  894. package/dist/coding-workspace.d.ts +0 -141
  895. package/dist/commit-extract.d.ts +0 -135
  896. package/dist/connect-cli.d.ts +0 -34
  897. package/dist/console-chrome.d.ts +0 -41
  898. package/dist/console-instance.d.ts +0 -157
  899. package/dist/container-state.d.ts +0 -5
  900. package/dist/containment.d.ts +0 -205
  901. package/dist/contract-changes.d.ts +0 -52
  902. package/dist/contracts/acceptance-terms.d.ts +0 -14
  903. package/dist/contracts/chat-actions.d.ts +0 -465
  904. package/dist/contracts/chat-callback-rows.d.ts +0 -59
  905. package/dist/contracts/chat-card.d.ts +0 -91
  906. package/dist/contracts/chat-content.d.ts +0 -551
  907. package/dist/contracts/chat-tables.d.ts +0 -12
  908. package/dist/contracts/cli.d.ts +0 -987
  909. package/dist/contracts/coding-activity.d.ts +0 -64
  910. package/dist/contracts/coding-context.d.ts +0 -97
  911. package/dist/contracts/coding-handoff.d.ts +0 -44
  912. package/dist/contracts/coding-workspace.d.ts +0 -165
  913. package/dist/contracts/console-api.d.ts +0 -539
  914. package/dist/contracts/contract-test.d.ts +0 -45
  915. package/dist/contracts/contract.d.ts +0 -92
  916. package/dist/contracts/decision.d.ts +0 -45
  917. package/dist/contracts/diff-stat.d.ts +0 -58
  918. package/dist/contracts/discord-callback.d.ts +0 -45
  919. package/dist/contracts/flow-card.d.ts +0 -53
  920. package/dist/contracts/flow-propose.d.ts +0 -334
  921. package/dist/contracts/flow-send.d.ts +0 -245
  922. package/dist/contracts/flow.d.ts +0 -19565
  923. package/dist/contracts/gateway-tools.d.ts +0 -472
  924. package/dist/contracts/handoff.d.ts +0 -91
  925. package/dist/contracts/health.d.ts +0 -82
  926. package/dist/contracts/integration-metadata.d.ts +0 -100
  927. package/dist/contracts/lead-context.d.ts +0 -165
  928. package/dist/contracts/lead-tools.d.ts +0 -2312
  929. package/dist/contracts/mcp-oauth.d.ts +0 -53
  930. package/dist/contracts/memory-pass.d.ts +0 -157
  931. package/dist/contracts/model-catalog.d.ts +0 -21
  932. package/dist/contracts/observation-request.d.ts +0 -37
  933. package/dist/contracts/plan.d.ts +0 -58
  934. package/dist/contracts/project-knowledge.d.ts +0 -159
  935. package/dist/contracts/project-memory.d.ts +0 -119
  936. package/dist/contracts/project-skills.d.ts +0 -120
  937. package/dist/contracts/proof.d.ts +0 -136
  938. package/dist/contracts/provider.d.ts +0 -40
  939. package/dist/contracts/recipes.d.ts +0 -166
  940. package/dist/contracts/release-check.d.ts +0 -371
  941. package/dist/contracts/release-terms.d.ts +0 -107
  942. package/dist/contracts/retention.d.ts +0 -42
  943. package/dist/contracts/review-findings.d.ts +0 -46
  944. package/dist/contracts/route-results.d.ts +0 -121
  945. package/dist/contracts/route.d.ts +0 -897
  946. package/dist/contracts/scope.d.ts +0 -105
  947. package/dist/contracts/scout-report.d.ts +0 -234
  948. package/dist/contracts/slack-callback.d.ts +0 -43
  949. package/dist/contracts/sort-answer.d.ts +0 -83
  950. package/dist/contracts/stage-output.d.ts +0 -127
  951. package/dist/contracts/storage.d.ts +0 -37
  952. package/dist/contracts/store-json.d.ts +0 -313
  953. package/dist/contracts/subagent-turn.d.ts +0 -43
  954. package/dist/contracts/task-sizing.d.ts +0 -24
  955. package/dist/contracts/teams-callback.d.ts +0 -13
  956. package/dist/contracts/telegram-callback.d.ts +0 -120
  957. package/dist/contracts/trigger-payloads.d.ts +0 -389
  958. package/dist/contracts/update-journal.d.ts +0 -254
  959. package/dist/contracts/verification-receipt.d.ts +0 -200
  960. package/dist/contracts/verification-view.d.ts +0 -102
  961. package/dist/contracts/youiyoux-request.d.ts +0 -248
  962. package/dist/control-setup.d.ts +0 -44
  963. package/dist/control-ui.d.ts +0 -37
  964. package/dist/controller-service.d.ts +0 -1
  965. package/dist/controller-supervisor.d.ts +0 -38
  966. package/dist/converse.d.ts +0 -316
  967. package/dist/coordinator-proposals.d.ts +0 -29
  968. package/dist/coordinator.d.ts +0 -186
  969. package/dist/credentials-ui.d.ts +0 -33
  970. package/dist/daemon.d.ts +0 -226
  971. package/dist/database-reclaim.d.ts +0 -4
  972. package/dist/decision.d.ts +0 -119
  973. package/dist/demo-chat.d.ts +0 -32
  974. package/dist/demo.d.ts +0 -153
  975. package/dist/deploy-gate.d.ts +0 -20
  976. package/dist/deploy-lock.d.ts +0 -8
  977. package/dist/deploy-phase.d.ts +0 -37
  978. package/dist/deploy-rescue.d.ts +0 -42
  979. package/dist/deprecations.d.ts +0 -20
  980. package/dist/design/kit.d.ts +0 -216
  981. package/dist/desktop-access.d.ts +0 -28
  982. package/dist/desktop-bundle.d.ts +0 -16
  983. package/dist/desktop-host.d.ts +0 -54
  984. package/dist/desktop-update-gate.d.ts +0 -12
  985. package/dist/desktop-update-recovery.d.ts +0 -14
  986. package/dist/desktop-update.d.ts +0 -147
  987. package/dist/digest-times.d.ts +0 -3
  988. package/dist/disclosure.d.ts +0 -6
  989. package/dist/discord-api.d.ts +0 -24
  990. package/dist/discord-chat.d.ts +0 -27
  991. package/dist/discord-settings.d.ts +0 -4
  992. package/dist/discord.d.ts +0 -10
  993. package/dist/discover.d.ts +0 -75
  994. package/dist/dispatch.d.ts +0 -123
  995. package/dist/dispose.d.ts +0 -194
  996. package/dist/doctor.d.ts +0 -67
  997. package/dist/easy-start-args.d.ts +0 -13
  998. package/dist/easy-start.d.ts +0 -77
  999. package/dist/egress.d.ts +0 -121
  1000. package/dist/email-settings.d.ts +0 -34
  1001. package/dist/envelope.d.ts +0 -47
  1002. package/dist/eval-gate.d.ts +0 -51
  1003. package/dist/eval-hooks.d.ts +0 -94
  1004. package/dist/eval-oracle-main.d.ts +0 -1
  1005. package/dist/eval-oracle.d.ts +0 -60
  1006. package/dist/eval-world.d.ts +0 -17
  1007. package/dist/evals.d.ts +0 -299
  1008. package/dist/evidence-pack.d.ts +0 -186
  1009. package/dist/evidence-pair.d.ts +0 -53
  1010. package/dist/evidence.d.ts +0 -371
  1011. package/dist/exec.d.ts +0 -355
  1012. package/dist/exhaustion.d.ts +0 -58
  1013. package/dist/export-ui.d.ts +0 -11
  1014. package/dist/export.d.ts +0 -48
  1015. package/dist/failing-first.d.ts +0 -31
  1016. package/dist/fallback-schema.d.ts +0 -8
  1017. package/dist/fallback.d.ts +0 -138
  1018. package/dist/fast-start.d.ts +0 -213
  1019. package/dist/fast-terms.d.ts +0 -9
  1020. package/dist/fenced-check-coverage.d.ts +0 -62
  1021. package/dist/findings.d.ts +0 -224
  1022. package/dist/first-run.d.ts +0 -197
  1023. package/dist/first-tasks-child.d.ts +0 -1
  1024. package/dist/flaky-ci.d.ts +0 -31
  1025. package/dist/flaky-cli.d.ts +0 -60
  1026. package/dist/flaky.d.ts +0 -83
  1027. package/dist/fleet-schema.d.ts +0 -17
  1028. package/dist/flow-actions.d.ts +0 -79
  1029. package/dist/flow-browser.d.ts +0 -103
  1030. package/dist/flow-cadence.d.ts +0 -48
  1031. package/dist/flow-card-task.d.ts +0 -11
  1032. package/dist/flow-changed.d.ts +0 -14
  1033. package/dist/flow-code.d.ts +0 -84
  1034. package/dist/flow-draft.d.ts +0 -42
  1035. package/dist/flow-engine.d.ts +0 -82
  1036. package/dist/flow-gallery-ui.d.ts +0 -73
  1037. package/dist/flow-gallery.d.ts +0 -147
  1038. package/dist/flow-insights.d.ts +0 -104
  1039. package/dist/flow-items.d.ts +0 -37
  1040. package/dist/flow-live.d.ts +0 -16
  1041. package/dist/flow-people.d.ts +0 -23
  1042. package/dist/flow-pull-request.d.ts +0 -14
  1043. package/dist/flow-replies.d.ts +0 -48
  1044. package/dist/flow-result-card.d.ts +0 -22
  1045. package/dist/flow-schedule.d.ts +0 -154
  1046. package/dist/flow-scripts.d.ts +0 -31
  1047. package/dist/flow-secrets.d.ts +0 -13
  1048. package/dist/flow-send.d.ts +0 -54
  1049. package/dist/flow-share.d.ts +0 -78
  1050. package/dist/flow-sort.d.ts +0 -63
  1051. package/dist/flow-starters-ui.d.ts +0 -15
  1052. package/dist/flow-starters.d.ts +0 -63
  1053. package/dist/flow-steps.d.ts +0 -52
  1054. package/dist/flow-triggers.d.ts +0 -303
  1055. package/dist/flow-unattended-words.d.ts +0 -48
  1056. package/dist/flow-unattended.d.ts +0 -259
  1057. package/dist/flows-cli.d.ts +0 -358
  1058. package/dist/flows-ui.d.ts +0 -70
  1059. package/dist/flows.d.ts +0 -136
  1060. package/dist/folder-gate.d.ts +0 -32
  1061. package/dist/folder-look.d.ts +0 -110
  1062. package/dist/follow-through-brief.d.ts +0 -12
  1063. package/dist/follow-through-cli.d.ts +0 -23
  1064. package/dist/fonts.d.ts +0 -19
  1065. package/dist/gaps.d.ts +0 -35
  1066. package/dist/gate-failure.d.ts +0 -40
  1067. package/dist/git-floor.d.ts +0 -16
  1068. package/dist/git-incident.d.ts +0 -65
  1069. package/dist/git-views.d.ts +0 -20
  1070. package/dist/git.d.ts +0 -54
  1071. package/dist/github-import.d.ts +0 -62
  1072. package/dist/github-jobs.d.ts +0 -25
  1073. package/dist/google-mail.d.ts +0 -59
  1074. package/dist/grant.d.ts +0 -136
  1075. package/dist/graph.d.ts +0 -164
  1076. package/dist/guides.d.ts +0 -22
  1077. package/dist/handover-note.d.ts +0 -33
  1078. package/dist/health-cli.d.ts +0 -3
  1079. package/dist/home-groups.d.ts +0 -39
  1080. package/dist/html.d.ts +0 -85
  1081. package/dist/install-method.d.ts +0 -17
  1082. package/dist/integrations-ui.d.ts +0 -17
  1083. package/dist/integrations.d.ts +0 -138
  1084. package/dist/invoke.d.ts +0 -228
  1085. package/dist/is-record.d.ts +0 -2
  1086. package/dist/issues.d.ts +0 -41
  1087. package/dist/jsonl-discriminants.d.ts +0 -11
  1088. package/dist/keymap.d.ts +0 -41
  1089. package/dist/keys.d.ts +0 -108
  1090. package/dist/kits-ui.d.ts +0 -16
  1091. package/dist/kits.d.ts +0 -88
  1092. package/dist/knowledge-cli.d.ts +0 -132
  1093. package/dist/knowledge-ui.d.ts +0 -45
  1094. package/dist/landed-cleanup.d.ts +0 -175
  1095. package/dist/laptop-background.d.ts +0 -187
  1096. package/dist/laptop-service.d.ts +0 -111
  1097. package/dist/latency-timeline.d.ts +0 -46
  1098. package/dist/lead-about.d.ts +0 -35
  1099. package/dist/lead-answer-eval.d.ts +0 -93
  1100. package/dist/lead-capabilities.d.ts +0 -57
  1101. package/dist/lead-cli-live.d.ts +0 -56
  1102. package/dist/lead-cli.d.ts +0 -58
  1103. package/dist/lead-commitments.d.ts +0 -84
  1104. package/dist/lead-context.d.ts +0 -45
  1105. package/dist/lead-contract.d.ts +0 -10
  1106. package/dist/lead-doors.d.ts +0 -122
  1107. package/dist/lead-follow.d.ts +0 -26
  1108. package/dist/lead-identity.d.ts +0 -23
  1109. package/dist/lead-latency-schema.d.ts +0 -24
  1110. package/dist/lead-people.d.ts +0 -55
  1111. package/dist/lead-progress.d.ts +0 -67
  1112. package/dist/lead-queue-runtime.d.ts +0 -46
  1113. package/dist/lead-queue.d.ts +0 -104
  1114. package/dist/lead-route.d.ts +0 -56
  1115. package/dist/lead-status.d.ts +0 -116
  1116. package/dist/lead-sweep.d.ts +0 -67
  1117. package/dist/lead-tools.d.ts +0 -167
  1118. package/dist/lead-voice.d.ts +0 -85
  1119. package/dist/lead.d.ts +0 -142
  1120. package/dist/learning-child.d.ts +0 -1
  1121. package/dist/learning-look.d.ts +0 -25
  1122. package/dist/ledger-chain.d.ts +0 -46
  1123. package/dist/ledger-csv.d.ts +0 -4
  1124. package/dist/ledger-view.d.ts +0 -27
  1125. package/dist/lesson-notes.d.ts +0 -81
  1126. package/dist/limits-ui.d.ts +0 -34
  1127. package/dist/link.d.ts +0 -72
  1128. package/dist/live-backup.d.ts +0 -39
  1129. package/dist/live-bus.d.ts +0 -141
  1130. package/dist/live-children-read.d.ts +0 -52
  1131. package/dist/live-children.d.ts +0 -73
  1132. package/dist/live-detail.d.ts +0 -27
  1133. package/dist/live-input.d.ts +0 -68
  1134. package/dist/live-main-read.d.ts +0 -19
  1135. package/dist/live-notes.d.ts +0 -20
  1136. package/dist/live-open.d.ts +0 -28
  1137. package/dist/live-records.d.ts +0 -149
  1138. package/dist/live-reply.d.ts +0 -83
  1139. package/dist/live-terminal.d.ts +0 -273
  1140. package/dist/live.d.ts +0 -152
  1141. package/dist/local-owner.d.ts +0 -124
  1142. package/dist/log.d.ts +0 -7
  1143. package/dist/login-secrets.d.ts +0 -60
  1144. package/dist/machine-check.d.ts +0 -16
  1145. package/dist/machine-identity.d.ts +0 -75
  1146. package/dist/mailbox.d.ts +0 -57
  1147. package/dist/maintenance.d.ts +0 -13
  1148. package/dist/mcp-connect.d.ts +0 -181
  1149. package/dist/mcp-core.d.ts +0 -110
  1150. package/dist/mcp-http.d.ts +0 -32
  1151. package/dist/mcp-oauth.d.ts +0 -92
  1152. package/dist/mcp-person.d.ts +0 -22
  1153. package/dist/mcp.d.ts +0 -20
  1154. package/dist/memory-cli.d.ts +0 -768
  1155. package/dist/memory-pass.d.ts +0 -151
  1156. package/dist/memory-tidy.d.ts +0 -181
  1157. package/dist/memory-use.d.ts +0 -35
  1158. package/dist/merge-checklist.d.ts +0 -55
  1159. package/dist/metrics.d.ts +0 -6
  1160. package/dist/mobile-viewport.d.ts +0 -7
  1161. package/dist/model-catalog.d.ts +0 -123
  1162. package/dist/model-choices.d.ts +0 -235
  1163. package/dist/model-names.d.ts +0 -6
  1164. package/dist/models-cli.d.ts +0 -307
  1165. package/dist/models-ui.d.ts +0 -161
  1166. package/dist/modes.d.ts +0 -99
  1167. package/dist/monitoring-settings.d.ts +0 -44
  1168. package/dist/monitoring-ui.d.ts +0 -23
  1169. package/dist/monitoring.d.ts +0 -34
  1170. package/dist/names.d.ts +0 -67
  1171. package/dist/needs-you.d.ts +0 -164
  1172. package/dist/never-index.d.ts +0 -3
  1173. package/dist/nightly-check.d.ts +0 -107
  1174. package/dist/nightly-github.d.ts +0 -318
  1175. package/dist/notification-delivery.d.ts +0 -19
  1176. package/dist/notification-rows.d.ts +0 -30
  1177. package/dist/oauth-run-token.d.ts +0 -51
  1178. package/dist/observations.d.ts +0 -36
  1179. package/dist/oidc.d.ts +0 -71
  1180. package/dist/onboard.d.ts +0 -108
  1181. package/dist/one-step-chat-schema.d.ts +0 -22
  1182. package/dist/openrouter-models.d.ts +0 -34
  1183. package/dist/operate-remote-arguments.d.ts +0 -36
  1184. package/dist/operate-remote.d.ts +0 -98
  1185. package/dist/operate.d.ts +0 -401
  1186. package/dist/orphan-sweep.d.ts +0 -65
  1187. package/dist/page-work-contract.d.ts +0 -21
  1188. package/dist/password-bearer.d.ts +0 -25
  1189. package/dist/passwordless.d.ts +0 -23
  1190. package/dist/peek-cli.d.ts +0 -112
  1191. package/dist/peek.d.ts +0 -110
  1192. package/dist/people-audit-ui.d.ts +0 -16
  1193. package/dist/person-proof.d.ts +0 -2
  1194. package/dist/phase-routing.d.ts +0 -401
  1195. package/dist/plain-schema.d.ts +0 -23
  1196. package/dist/plain-words.d.ts +0 -20
  1197. package/dist/plan-auto.d.ts +0 -25
  1198. package/dist/plan-login.d.ts +0 -14
  1199. package/dist/plan.d.ts +0 -188
  1200. package/dist/plane-review.d.ts +0 -54
  1201. package/dist/planner-source.d.ts +0 -225
  1202. package/dist/planner.d.ts +0 -76
  1203. package/dist/policy-ui.d.ts +0 -22
  1204. package/dist/policy.d.ts +0 -92
  1205. package/dist/prepared-evidence.d.ts +0 -17
  1206. package/dist/principal.d.ts +0 -42
  1207. package/dist/probe.d.ts +0 -46
  1208. package/dist/process-custody.d.ts +0 -17
  1209. package/dist/process-liveness.d.ts +0 -13
  1210. package/dist/process-tree.d.ts +0 -39
  1211. package/dist/project-access.d.ts +0 -17
  1212. package/dist/project-activity.d.ts +0 -20
  1213. package/dist/project-admission.d.ts +0 -105
  1214. package/dist/project-cli.d.ts +0 -19
  1215. package/dist/project-concurrency.d.ts +0 -62
  1216. package/dist/project-delete-ui.d.ts +0 -96
  1217. package/dist/project-delete.d.ts +0 -59
  1218. package/dist/project-demo.d.ts +0 -12
  1219. package/dist/project-file.d.ts +0 -3
  1220. package/dist/project-identity.d.ts +0 -52
  1221. package/dist/project-knowledge.d.ts +0 -124
  1222. package/dist/project-learning.d.ts +0 -120
  1223. package/dist/project-memory.d.ts +0 -70
  1224. package/dist/project-outcomes.d.ts +0 -119
  1225. package/dist/project-sandbox.d.ts +0 -59
  1226. package/dist/project-skills.d.ts +0 -139
  1227. package/dist/project-tools.d.ts +0 -318
  1228. package/dist/project.d.ts +0 -65
  1229. package/dist/prompt.d.ts +0 -33
  1230. package/dist/proof.d.ts +0 -457
  1231. package/dist/proposal.d.ts +0 -70
  1232. package/dist/protected-storage-look.d.ts +0 -1
  1233. package/dist/protected-storage.d.ts +0 -98
  1234. package/dist/provider-auth.d.ts +0 -143
  1235. package/dist/provider-capture.d.ts +0 -34
  1236. package/dist/provider-connection.d.ts +0 -23
  1237. package/dist/provider-home.d.ts +0 -22
  1238. package/dist/provider-limits.d.ts +0 -37
  1239. package/dist/provider.d.ts +0 -369
  1240. package/dist/public-access.d.ts +0 -52
  1241. package/dist/public-check.d.ts +0 -37
  1242. package/dist/publish.d.ts +0 -146
  1243. package/dist/pull-request-flow.d.ts +0 -189
  1244. package/dist/pull-request-schema.d.ts +0 -5
  1245. package/dist/pull-request-ui.d.ts +0 -25
  1246. package/dist/pulls.d.ts +0 -121
  1247. package/dist/push.d.ts +0 -120
  1248. package/dist/quality.d.ts +0 -8
  1249. package/dist/quick-start.d.ts +0 -26
  1250. package/dist/read-executor-worker.d.ts +0 -1
  1251. package/dist/read-executor.d.ts +0 -66
  1252. package/dist/read-only-request.d.ts +0 -4
  1253. package/dist/recipe-ui.d.ts +0 -21
  1254. package/dist/recipes.d.ts +0 -56
  1255. package/dist/release-adapters.d.ts +0 -205
  1256. package/dist/release-approval.d.ts +0 -180
  1257. package/dist/release-authority.d.ts +0 -173
  1258. package/dist/release-auto.d.ts +0 -184
  1259. package/dist/release-card.d.ts +0 -156
  1260. package/dist/release-carry.d.ts +0 -261
  1261. package/dist/release-ci-hold.d.ts +0 -41
  1262. package/dist/release-cli.d.ts +0 -34
  1263. package/dist/release-coverage.d.ts +0 -16
  1264. package/dist/release-gate.d.ts +0 -84
  1265. package/dist/release-git.d.ts +0 -43
  1266. package/dist/release-links.d.ts +0 -29
  1267. package/dist/release-net.d.ts +0 -90
  1268. package/dist/release-next.d.ts +0 -48
  1269. package/dist/release-recheck.d.ts +0 -146
  1270. package/dist/release-refusal.d.ts +0 -32
  1271. package/dist/release-view.d.ts +0 -37
  1272. package/dist/release.d.ts +0 -806
  1273. package/dist/releases.d.ts +0 -94
  1274. package/dist/remote-audit.d.ts +0 -79
  1275. package/dist/remote-command.d.ts +0 -45
  1276. package/dist/remote-destination.d.ts +0 -36
  1277. package/dist/remote-exec.d.ts +0 -38
  1278. package/dist/remote-main.d.ts +0 -111
  1279. package/dist/remote-run.d.ts +0 -20
  1280. package/dist/remote.d.ts +0 -67
  1281. package/dist/render.d.ts +0 -64
  1282. package/dist/reply-shape.d.ts +0 -106
  1283. package/dist/reply-voice.d.ts +0 -23
  1284. package/dist/report-summary.d.ts +0 -22
  1285. package/dist/reported-usage.d.ts +0 -69
  1286. package/dist/repos.d.ts +0 -67
  1287. package/dist/repository-context-ui.d.ts +0 -3
  1288. package/dist/repository-context.d.ts +0 -66
  1289. package/dist/request-budget-ui.d.ts +0 -14
  1290. package/dist/request-budget.d.ts +0 -127
  1291. package/dist/restart-certification.d.ts +0 -133
  1292. package/dist/result-actions.d.ts +0 -36
  1293. package/dist/result-acts.d.ts +0 -112
  1294. package/dist/result-completion.d.ts +0 -35
  1295. package/dist/result-evidence-readers.d.ts +0 -42
  1296. package/dist/result-follow-ups.d.ts +0 -118
  1297. package/dist/result-review.d.ts +0 -220
  1298. package/dist/result-shots.d.ts +0 -59
  1299. package/dist/retention-ui.d.ts +0 -21
  1300. package/dist/retention.d.ts +0 -77
  1301. package/dist/review-context.d.ts +0 -245
  1302. package/dist/review-evidence.d.ts +0 -33
  1303. package/dist/review-switch.d.ts +0 -36
  1304. package/dist/reviewer.d.ts +0 -99
  1305. package/dist/route-change-check.d.ts +0 -4
  1306. package/dist/route-change.d.ts +0 -22
  1307. package/dist/route-hooks.d.ts +0 -54
  1308. package/dist/route-results.d.ts +0 -75
  1309. package/dist/route-rules.d.ts +0 -324
  1310. package/dist/route-savings.d.ts +0 -136
  1311. package/dist/route-store.d.ts +0 -300
  1312. package/dist/run-closeout.d.ts +0 -89
  1313. package/dist/run-efficiency.d.ts +0 -74
  1314. package/dist/run-ending.d.ts +0 -21
  1315. package/dist/runner-process.d.ts +0 -76
  1316. package/dist/runner.d.ts +0 -324
  1317. package/dist/sample-project.d.ts +0 -31
  1318. package/dist/sandbox-launch.d.ts +0 -1
  1319. package/dist/sandbox-runtime.d.ts +0 -128
  1320. package/dist/scan.d.ts +0 -32
  1321. package/dist/scope.d.ts +0 -1067
  1322. package/dist/scout-browser-lock.d.ts +0 -69
  1323. package/dist/scout-browser.d.ts +0 -107
  1324. package/dist/scout-net.d.ts +0 -25
  1325. package/dist/scout-report.d.ts +0 -23
  1326. package/dist/scout.d.ts +0 -142
  1327. package/dist/secret-mint.d.ts +0 -1
  1328. package/dist/serve.d.ts +0 -11
  1329. package/dist/server/agents-computers.d.ts +0 -9
  1330. package/dist/server/agents-live-filed.d.ts +0 -17
  1331. package/dist/server/agents-live-lead.d.ts +0 -47
  1332. package/dist/server/agents-live-room.d.ts +0 -23
  1333. package/dist/server/chat.d.ts +0 -39
  1334. package/dist/server/chrome.d.ts +0 -328
  1335. package/dist/server/edge-refusal.d.ts +0 -7
  1336. package/dist/server/flows.d.ts +0 -8
  1337. package/dist/server/guards.d.ts +0 -80
  1338. package/dist/server/handler-context.d.ts +0 -22
  1339. package/dist/server/handler-registry.d.ts +0 -23
  1340. package/dist/server/home-asks.d.ts +0 -45
  1341. package/dist/server/home.d.ts +0 -65
  1342. package/dist/server/http.d.ts +0 -337
  1343. package/dist/server/in-place.d.ts +0 -15
  1344. package/dist/server/kit-standalone.d.ts +0 -22
  1345. package/dist/server/kit.d.ts +0 -452
  1346. package/dist/server/last-checks.d.ts +0 -17
  1347. package/dist/server/live.d.ts +0 -74
  1348. package/dist/server/merge-ready-view.d.ts +0 -10
  1349. package/dist/server/mutation-key.d.ts +0 -70
  1350. package/dist/server/pages-assets.d.ts +0 -11
  1351. package/dist/server/pages.d.ts +0 -8
  1352. package/dist/server/people-tokens.d.ts +0 -18
  1353. package/dist/server/remote-hooks.d.ts +0 -29
  1354. package/dist/server/remote.d.ts +0 -59
  1355. package/dist/server/render-chat.d.ts +0 -439
  1356. package/dist/server/render-code-map.d.ts +0 -30
  1357. package/dist/server/render-flaky.d.ts +0 -20
  1358. package/dist/server/render-follow-through.d.ts +0 -11
  1359. package/dist/server/render-history.d.ts +0 -51
  1360. package/dist/server/render-new-task.d.ts +0 -54
  1361. package/dist/server/render-pages.d.ts +0 -236
  1362. package/dist/server/render-people.d.ts +0 -102
  1363. package/dist/server/render-projects.d.ts +0 -104
  1364. package/dist/server/render-release.d.ts +0 -19
  1365. package/dist/server/render-results.d.ts +0 -754
  1366. package/dist/server/render-settings.d.ts +0 -93
  1367. package/dist/server/render-tasks.d.ts +0 -774
  1368. package/dist/server/request-context.d.ts +0 -78
  1369. package/dist/server/retired-routes.d.ts +0 -17
  1370. package/dist/server/route-policy.d.ts +0 -18
  1371. package/dist/server/route-table.d.ts +0 -114
  1372. package/dist/server/runtime.d.ts +0 -342
  1373. package/dist/server/session.d.ts +0 -192
  1374. package/dist/server/settings.d.ts +0 -76
  1375. package/dist/server/signup-gate.d.ts +0 -9
  1376. package/dist/server/sweeps.d.ts +0 -4
  1377. package/dist/server/task-views.d.ts +0 -98
  1378. package/dist/server/tasks.d.ts +0 -83
  1379. package/dist/server/terminals.d.ts +0 -31
  1380. package/dist/server/welcome.d.ts +0 -28
  1381. package/dist/server-telemetry.d.ts +0 -87
  1382. package/dist/settings-groups-ui.d.ts +0 -286
  1383. package/dist/settings-kit-script.d.ts +0 -21
  1384. package/dist/settings-kit.d.ts +0 -173
  1385. package/dist/settings-proofs.d.ts +0 -64
  1386. package/dist/setup-guide.d.ts +0 -39
  1387. package/dist/shared-deps.d.ts +0 -115
  1388. package/dist/sign-in-guard.d.ts +0 -70
  1389. package/dist/skills-ui.d.ts +0 -12
  1390. package/dist/skills.d.ts +0 -99
  1391. package/dist/slack-api.d.ts +0 -59
  1392. package/dist/slack-chat.d.ts +0 -37
  1393. package/dist/slack-settings.d.ts +0 -4
  1394. package/dist/slack-socket.d.ts +0 -12
  1395. package/dist/slack.d.ts +0 -6
  1396. package/dist/sleep.d.ts +0 -2
  1397. package/dist/source-key.d.ts +0 -2
  1398. package/dist/spend-report.d.ts +0 -87
  1399. package/dist/spend-ui.d.ts +0 -80
  1400. package/dist/spend.d.ts +0 -142
  1401. package/dist/sqlite-runtime.d.ts +0 -3
  1402. package/dist/sqlite-telemetry.d.ts +0 -9
  1403. package/dist/sso-settings.d.ts +0 -33
  1404. package/dist/sso-ui.d.ts +0 -26
  1405. package/dist/staged-runtimes.d.ts +0 -54
  1406. package/dist/steer-capabilities.d.ts +0 -32
  1407. package/dist/steer-controls.d.ts +0 -14
  1408. package/dist/steer-live.d.ts +0 -19
  1409. package/dist/steer-mailbox.d.ts +0 -46
  1410. package/dist/steer-status.d.ts +0 -25
  1411. package/dist/stop-proof.d.ts +0 -67
  1412. package/dist/storage-sweep-child.d.ts +0 -1
  1413. package/dist/storage-sweep-process.d.ts +0 -55
  1414. package/dist/storage-sweep-schedule.d.ts +0 -30
  1415. package/dist/storage-sweep.d.ts +0 -77
  1416. package/dist/storage-ui.d.ts +0 -23
  1417. package/dist/storage.d.ts +0 -68
  1418. package/dist/store-baseline.d.ts +0 -19
  1419. package/dist/store.d.ts +0 -8613
  1420. package/dist/stream-scope.d.ts +0 -18
  1421. package/dist/structured-output.d.ts +0 -57
  1422. package/dist/style-asset.d.ts +0 -7
  1423. package/dist/subagent-admin.d.ts +0 -53
  1424. package/dist/subagent-desk.d.ts +0 -59
  1425. package/dist/subagent-memory.d.ts +0 -65
  1426. package/dist/subagent-question.d.ts +0 -59
  1427. package/dist/subagent-tools.d.ts +0 -125
  1428. package/dist/subagent-week.d.ts +0 -68
  1429. package/dist/subagent-work.d.ts +0 -76
  1430. package/dist/subagents-ui.d.ts +0 -22
  1431. package/dist/subagents.d.ts +0 -146
  1432. package/dist/subscription-chat.d.ts +0 -54
  1433. package/dist/summary.d.ts +0 -33
  1434. package/dist/surface.d.ts +0 -49
  1435. package/dist/sweep-gate.d.ts +0 -10
  1436. package/dist/sweep-quarantine.d.ts +0 -29
  1437. package/dist/sync.d.ts +0 -94
  1438. package/dist/tailnet.d.ts +0 -11
  1439. package/dist/tamper-scan.d.ts +0 -4
  1440. package/dist/task-activity.d.ts +0 -27
  1441. package/dist/task-aliases.d.ts +0 -5
  1442. package/dist/task-archive.d.ts +0 -13
  1443. package/dist/task-base.d.ts +0 -39
  1444. package/dist/task-composer.d.ts +0 -14
  1445. package/dist/task-control.d.ts +0 -159
  1446. package/dist/task-live.d.ts +0 -8
  1447. package/dist/task-moves.d.ts +0 -90
  1448. package/dist/task-outcome-cli.d.ts +0 -30
  1449. package/dist/task-review-brief.d.ts +0 -69
  1450. package/dist/task-sizing.d.ts +0 -58
  1451. package/dist/task-source.d.ts +0 -77
  1452. package/dist/task-status.d.ts +0 -324
  1453. package/dist/task-text.d.ts +0 -31
  1454. package/dist/team-chat-authorization.d.ts +0 -11
  1455. package/dist/team-contract.d.ts +0 -103
  1456. package/dist/team-http.d.ts +0 -25
  1457. package/dist/team-leads.d.ts +0 -85
  1458. package/dist/team-runtime.d.ts +0 -25
  1459. package/dist/team-ui.d.ts +0 -4
  1460. package/dist/team-updates.d.ts +0 -8
  1461. package/dist/teams-api.d.ts +0 -33
  1462. package/dist/teams-chat.d.ts +0 -36
  1463. package/dist/teams-settings.d.ts +0 -14
  1464. package/dist/teams.d.ts +0 -24
  1465. package/dist/teardown-git.d.ts +0 -164
  1466. package/dist/telegram-flow.d.ts +0 -112
  1467. package/dist/telegram-lead.d.ts +0 -151
  1468. package/dist/telegram-live.d.ts +0 -116
  1469. package/dist/telegram-progress.d.ts +0 -20
  1470. package/dist/telegram-settings.d.ts +0 -9
  1471. package/dist/telegram-status.d.ts +0 -83
  1472. package/dist/telegram-team.d.ts +0 -68
  1473. package/dist/telegram.d.ts +0 -271
  1474. package/dist/templates.d.ts +0 -69
  1475. package/dist/terminal-catalog.d.ts +0 -11
  1476. package/dist/terminal-text.d.ts +0 -11
  1477. package/dist/test-infra.d.ts +0 -34
  1478. package/dist/test-temp.d.ts +0 -40
  1479. package/dist/text-limits.d.ts +0 -297
  1480. package/dist/tidy.d.ts +0 -130
  1481. package/dist/tier-report.d.ts +0 -44
  1482. package/dist/token-notices.d.ts +0 -11
  1483. package/dist/tokens-cli.d.ts +0 -21
  1484. package/dist/tool-broker.d.ts +0 -52
  1485. package/dist/tool-launcher.d.ts +0 -1
  1486. package/dist/tool-secret-store.d.ts +0 -167
  1487. package/dist/toolroll-update-cli.d.ts +0 -15
  1488. package/dist/toolroll-update-ui.d.ts +0 -47
  1489. package/dist/toolroll-update.d.ts +0 -265
  1490. package/dist/tools-ui.d.ts +0 -51
  1491. package/dist/transitions-recipes.d.ts +0 -1
  1492. package/dist/tree-proof.d.ts +0 -34
  1493. package/dist/tui-contract.d.ts +0 -144
  1494. package/dist/tui-source.d.ts +0 -14
  1495. package/dist/typed-start.d.ts +0 -51
  1496. package/dist/unfenced-test-support.d.ts +0 -2
  1497. package/dist/up-processes.d.ts +0 -162
  1498. package/dist/up-role-child.d.ts +0 -1
  1499. package/dist/update-notice.d.ts +0 -5
  1500. package/dist/vanished-retry.d.ts +0 -30
  1501. package/dist/verification-evidence.d.ts +0 -68
  1502. package/dist/version.d.ts +0 -2
  1503. package/dist/wake-hub.d.ts +0 -72
  1504. package/dist/webhook-limits.d.ts +0 -23
  1505. package/dist/webhook-readers.d.ts +0 -56
  1506. package/dist/webhook-signing.d.ts +0 -27
  1507. package/dist/webhooks.d.ts +0 -84
  1508. package/dist/welcome-facts.d.ts +0 -18
  1509. package/dist/when-html.d.ts +0 -40
  1510. package/dist/work-index.d.ts +0 -175
  1511. package/dist/work-summary.d.ts +0 -61
  1512. package/dist/workspace-motion.d.ts +0 -4
  1513. package/dist/workspace-revision.d.ts +0 -48
  1514. package/dist/workspace-ui.d.ts +0 -385
  1515. package/dist/worktree-notices.d.ts +0 -13
  1516. package/dist/worktree.d.ts +0 -365
  1517. package/dist/writes-mode.d.ts +0 -9
  1518. package/dist/youiyoux-intake.d.ts +0 -234
package/dist/serve.js CHANGED
@@ -20,10 +20,6 @@ import { html, htmlString, jsonScript, textHtml } from "./html.js";
20
20
  import { browserAssetsAvailable, browserWorkspaceDocument } from './browser-shell.js';
21
21
  import { accessKey, countsKey, indexKey, projectSummaryOf, RevisionCache, summaryKey } from './console-chrome.js';
22
22
  import { usageChipOf } from './limits-ui.js';
23
- /** Any header a proxy adds: a request carrying one is never "from this computer" (password freshness, one-time links). */
24
- const PROXY_HEADER = /^(forwarded|via|x-forwarded-.+|x-real-ip|x-client-ip|x-original-.+|x-cluster-client-ip|true-client-ip|cf-connecting-ip|fastly-client-ip|x-proxyuser-ip)$/i;
25
- /** How often the background checks look at what is due (docs/plans/get-side-effects.md), and how often this
26
- * computer's agent sign-ins are asked again. */
27
23
  const BACKGROUND_CHECKS_MS = 30_000;
28
24
  const LOCAL_AGENTS_EVERY_MS = 2 * 60_000;
29
25
  import { browserCrewFromIndex, browserCrewOf, browserNavigationOf, browserProjectsOf, needsYouLabelOf } from './browser-workspace.js';
@@ -63,48 +59,6 @@ import {} from "./tools-ui.js";
63
59
  import { WORK_INDEX_MAX_LIMIT, workCountsByProject, workIndexPage } from "./work-index.js";
64
60
  import { WORKSPACE_MOTION_SCRIPT } from "./workspace-motion.js";
65
61
  import { prepareWorkspaceRevision, WorkspaceValidatorCache } from "./workspace-revision.js";
66
- /**
67
- * The web console (§7, grown per the console review): the whole built-in
68
- * queue, visible and operable from a phone. `toolroll serve` — node:http,
69
- * no dependencies, no JavaScript in the page. TLS is a proxy's job and the
70
- * docs say so; what is not delegated is everything else:
71
- *
72
- * **Authentication is required on every bind, localhost included.** The
73
- * credential is the approver's — the same name-and-token that approves a
74
- * scope and answers in the CLI — because `answered_by` must be an identity
75
- * somebody proved, not a string a request asserted. A browser logs in once
76
- * (POST /login) and carries an HttpOnly SameSite=Strict session cookie; an
77
- * API caller sends `Authorization: Bearer <name>:<token>` per request. The
78
- * token never travels in a URL, where it would land in history and logs.
79
- *
80
- * **Every request proves its Host** against the names this server was told
81
- * it answers as. Cookie-authenticated mutations additionally pass one
82
- * centralized gate — `authorizeMutation` — that proves content type, an
83
- * allowed Origin, and the per-session CSRF nonce, and refuses duplicated
84
- * security fields; a mutation route cannot forget a check it never wrote.
85
- * Bearer mutations carry no cookie for a hostile page to ride, so they skip CSRF.
86
- * Step-up ceremonies still require a cookie session; repeating a bearer password cannot approve.
87
- *
88
- * **Approval is step-up.** A session alone never approves a scope: the
89
- * approval form restates the goal, the exclusions, and the touches — the
90
- * three fields the digest binds — and requires the approver token typed
91
- * again, plus (for browsers) a single-use nonce minted when the form was
92
- * rendered, bound server-side to who saw which digest of which task. A
93
- * stolen cookie can read; it cannot agree to work.
94
- *
95
- * **GET never mutates.** Overdue-ness is derived at render time from the
96
- * deadline on the row; the durable expiry sweep belongs to the CLI's
97
- * surfaces and the loop, not to a crawler hitting a page.
98
- *
99
- * **Everything rendered is escaped at the sink**, and every identifier in an
100
- * href is URL-encoded first — HTML escaping does not make `a/b?x=1` a valid
101
- * path segment. The CSP is belt to those suspenders.
102
- *
103
- * **Evidence goes through one verified reader** (`readVerifiedArtifact`) and
104
- * membership is enforced by the lookup — a decision serves only its linked
105
- * artifacts, a run only its own rows, and when this server was scoped to a
106
- * repo, only runs whose task belongs to that repo (or to no repo yet).
107
- */
108
62
  import { createHash, randomBytes } from "node:crypto";
109
63
  import { keepSlowRequest, Timeline } from "./latency-timeline.js";
110
64
  import { readFileSync } from "node:fs";
@@ -137,7 +91,7 @@ import { canonicalProject, projectName, resolveCeiling, rowVisible } from "./pro
137
91
  import { noteSignInProbe, signInNotices } from "./provider-auth.js";
138
92
  import { createConnectionChecker } from "./provider-connection.js";
139
93
  import { ALL_CREDENTIAL_ENV } from "./provider.js";
140
- import { hstsFor, LOOPBACK_PEERS, plainHttpRefusal, transportOf } from "./public-access.js";
94
+ import { hstsFor, LOOPBACK_PEERS, plainHttpRefusal, requestFromThisComputer, transportOf } from "./public-access.js";
141
95
  import { attachReadExecutor, defaultReadWorkers, ReadExecutor } from "./read-executor.js";
142
96
  import { cachedRelease, isNewer, runnerVersions, updateChecksOff } from "./releases.js";
143
97
  import { limitWords, FLUSH_MS as REQUEST_BUDGET_FLUSH_MS, RequestBudget, SOURCE_BUDGET_DEFAULTS, SourceAdmission } from "./request-budget.js";
@@ -158,8 +112,9 @@ import { createPeopleHandlers } from './server/people-tokens.js';
158
112
  import { createSettingsHandlers } from './server/settings.js';
159
113
  import { readPurpose, requestContext } from "./server/request-context.js";
160
114
  import { inPlaceRoute, prefetchRoute } from "./server/in-place.js";
161
- import { asLocalOwner, localModeOn, localOwnerRefusal, localOwnerStandsNow } from "./local-owner.js";
162
- import { defaultAgentOf, fillDefaultRouting } from "./model-choices.js";
115
+ import { advancedShownFor } from "./advanced.js";
116
+ import { LOCAL_OWNER_ELSEWHERE, asLocalOwner, localModeOn, localOwnerRefusal, localOwnerStandsNow } from "./local-owner.js";
117
+ import { defaultAgentOf, fillDefaultRouting, fillRoutingOnSignIn } from "./model-choices.js";
163
118
  import { chromeScript, DEMO_BANNER, DEMO_BANNER_SHORT, focusDocument, KBD_HELP, pinnedTheme, QUEUE_VIEW, refuse, screen, SENSITIVE_INPUT, shell, sidebarScript } from "./server/chrome.js";
164
119
  import { BODY_CAP, form, loginHref, passwordSetNext, refusalNext, matchTaskPath, page, projectChatHref, redactedPath, redirect, respond, safeReturn, SHUTDOWN_WAIT_MS, taskChatHref } from "./server/http.js";
165
120
  import { decisionsFor, LEAD_BY_DEFAULT_FACT, leadBrowserMessages, leadChatVersion, NOT_STARTED_SESSION, TASK_COMPOSER_MODES, teamProposalCardParts } from "./server/render-chat.js";
@@ -180,8 +135,6 @@ import { loadConsoleUrl } from "./webhooks.js";
180
135
  import { reviewFactsOf } from "./workspace-ui.js";
181
136
  import { WorktreePool } from "./worktree.js";
182
137
  export function createDecisionServer(options) {
183
- // Identities come from what the console's start resolved off its thread (startConsole); a path that didn't answer
184
- // stays unresolved, kept restrictive. Without them (embedders, tests) the old synchronous reads apply.
185
138
  const identities = options.identities ?? syncProjectIdentities();
186
139
  const { projectFamilyPeek, familiesInView, familyTasksInView, revisionDestination, runIsLive, runIsTaskResult, revisionViewOf, taskViewData, routeViewOf, taskChatFocus, pullRequestTargetOf, failureOf, explainAttempt, taskScreen, armTaskResume, planViewOf, planContractViewOf, revisionDocOf, revisionLedgerOf, resultDetailOf } = createTaskViews({
187
140
  get store() { return store; },
@@ -234,18 +187,14 @@ export function createDecisionServer(options) {
234
187
  }
235
188
  }
236
189
  }
237
- // Live terminals (docs/plans/live-terminal.md): on a machine that runs agents, when this install has a pty library.
238
190
  const terminals = terminalHostFor(store, options);
239
191
  const clock = options.clock ?? (() => new Date());
240
- // Heavy reads (the work index behind `task list`) run on read-only worker connections, off the request loop.
241
192
  const readFile = store.isDemo() ? null : store.databaseFile();
242
193
  const readWorkers = options.readWorkers ?? (process.env["VITEST"] !== undefined ? 0 : defaultReadWorkers());
243
194
  const reads = readFile === null || readWorkers < 1 ? null : new ReadExecutor(readFile, readWorkers);
244
195
  const detachReads = reads === null ? () => { } : attachReadExecutor(store, reads);
245
- /** Task checkouts, for Settings → Storage: the pool's own root, or the folder beside the database. */
246
196
  const storagePool = (databaseFile) => new WorktreePool(store, { root: options.poolRoot ?? join(dirname(databaseFile), "worktrees") });
247
197
  const install = installMethod(options.installBin);
248
- /** What the last daily check found (the cache only, never the network), or nothing while checks are off. */
249
198
  const updateFacts = () => {
250
199
  if (options.configDir === undefined)
251
200
  return null;
@@ -253,7 +202,6 @@ export function createDecisionServer(options) {
253
202
  const release = switched.off ? null : cachedRelease(options.configDir);
254
203
  return { release, newer: release !== null && isNewer(release.version, PACKAGE_VERSION), on: !switched.off, byEnv: switched.byEnv };
255
204
  };
256
- /** Settings → Updates, for everyone who can open Settings; only an operator may flip the switch. */
257
205
  const settingsUpdates = (actor, csrf) => {
258
206
  const facts = updateFacts();
259
207
  if (facts === null)
@@ -271,29 +219,20 @@ export function createDecisionServer(options) {
271
219
  };
272
220
  };
273
221
  const workspaceRevision = prepareWorkspaceRevision(store);
274
- // The sidebar, the Tasks count and the crew: read at most once per workspace revision per reader's exact access
275
- // (console-chrome.ts), and filled from a read worker before a page renders when one is attached.
276
222
  const chromeReads = new RevisionCache(workspaceRevision, clock);
277
223
  const workspaceIncarnation = randomBytes(16).toString('hex');
278
224
  const workspaceValidators = new WorkspaceValidatorCache();
279
225
  const providerHome = options.connectionHome ?? homedir();
280
226
  const checkConnection = createConnectionChecker({ home: providerHome, clock, ...(options.connectionProbe === undefined ? {} : { probe: options.connectionProbe }) });
281
- // Every sign-in check the console makes also answers a sign-in pause.
282
- // Whether this computer can fence agents: asked once as the console starts (a sandbox running /usr/bin/true), so
283
- // Settings → Project never starts a process (docs/plans/get-side-effects.md).
284
227
  const fenceHere = options.fenceAvailable === undefined ? macosFenceAvailable() || linuxFenceAvailable() : false;
285
- // Phone notifications' signing pair, made once as the console starts so /push/key only reads it.
286
228
  if (options.telegramTokenFile !== undefined) {
287
229
  try {
288
230
  loadOrCreateVapidKeys(dirname(options.telegramTokenFile));
289
231
  }
290
- catch { /* /push/key says push is not set up */ }
232
+ catch { }
291
233
  }
292
- // The last answer of every other check a page shows (docs/plans/get-side-effects.md).
293
234
  const lastChecks = new LastChecks();
294
- /** The newest release, asked of npm (Settings → Updates shows the last answer). */
295
235
  const checkRelease = () => lastChecks.run("release", () => latestReleaseFor(options.updates?.latest));
296
- // What each sign-in check said last: what a page shows (docs/plans/get-side-effects.md). A page never checks.
297
236
  const knownConnections = new Map();
298
237
  const connectionKnown = (provider) => knownConnections.get(provider) ?? null;
299
238
  const connectionCheck = async (provider, fresh) => {
@@ -302,10 +241,9 @@ export function createDecisionServer(options) {
302
241
  try {
303
242
  noteSignInProbe(store, provider, value.state, clock());
304
243
  }
305
- catch { /* the pause keeps its own state */ }
244
+ catch { }
306
245
  return value;
307
246
  };
308
- // Settings → Integrations: checked in the background with a short cache, as the first-run suggestions are.
309
247
  const integrations = createIntegrationMonitor(() => ({
310
248
  store,
311
249
  dir: options.configDir ?? null,
@@ -326,24 +264,10 @@ export function createDecisionServer(options) {
326
264
  ...(options.modelPath === undefined ? {} : { path: options.modelPath }),
327
265
  };
328
266
  const sessions = new PersistentSessions(store);
329
- // Sessions from before a restart that ran out, or whose account changed since, go now.
330
267
  store.sweepWebSessions(Date.now(), SESSION_IDLE_MS, SESSION_ABSOLUTE_MS);
331
- /** Where a new session signs in from: the browser (its user agent, short) and the address. */
332
268
  const arrival = (request) => ({ agent: (request.headers["user-agent"] ?? "").slice(0, 300) || null, address: forwardedSourceOf(request).replace(/^fwd:/, "") });
333
- /** Wrong setup codes left before the first-account road closes. */
334
269
  let setupAttemptsLeft = 5;
335
- // The /join road's limiter (D6; Codex people round 1, finding 4):
336
- // PER-SOURCE buckets so one stranger cannot drain sign-up capacity for
337
- // everyone, under a global ceiling that bounds total KDF work. Spent
338
- // only by WELL-FORMED submissions — malformed requests are refused by
339
- // the shape guards for free. The per-invite attempt counter remains the
340
- // durable meter; these buckets only price the trying.
341
270
  const joinBySource = new Map();
342
- /** The per-source key (round 2, finding 4): the direct peer — except
343
- * behind the documented same-host TLS proxy, where every client would
344
- * share the proxy's one bucket. A LOOPBACK peer is that proxy, and only
345
- * then is the forwarded chain believed, taking the LAST hop (the one
346
- * the trusted proxy itself appended; earlier entries are client-typed). */
347
271
  function forwardedSourceOf(request) {
348
272
  const peer = request.socket.remoteAddress ?? "unknown";
349
273
  const loopback = LOOPBACK_PEERS.has(peer);
@@ -354,52 +278,27 @@ export function createDecisionServer(options) {
354
278
  const lastHop = chain.split(",").pop()?.trim() ?? "";
355
279
  return lastHop === "" ? peer : `fwd:${lastHop.slice(0, 64)}`;
356
280
  }
357
- /** That source as every per-source budget counts it: a native IPv6 caller by its /64 (source-key.ts). */
358
281
  function joinSourceOf(request) { return sourceKey(forwardedSourceOf(request)); }
359
282
  const signInBudget = new SourceBudget();
360
- // A re-check or a link is the session that started it: its kept hash and credential generation ride the visit and the
361
- // hand-off, and finish refuses any other session (a sign-out and a new sign-in in between never inherit it).
362
283
  const ssoVisits = new Map();
363
284
  const ssoHandoffs = new Map();
364
285
  let ssoProvider = null;
365
286
  const ssoSettings = () => readSsoSettings(options.configDir);
366
287
  const ssoOffer = () => { const settings = ssoSettings(); return settings === null ? null : { label: settings.label, operatorsOnly: settings.passwords === "operators" }; };
367
- /** A step-up within this long of the provider checking someone needs no password. */
368
- // The one-time sign-in link `up` opens in the browser: single use, ten minutes, from this computer only. Only a hash
369
- // of the code is kept, in memory; the code itself is never written to a log or the ledger.
370
288
  const signInLinks = new Map();
371
289
  const linkKey = (code) => createHash("sha256").update(code).digest("hex");
372
290
  function mintSignInLink(account) {
373
291
  const known = store.accountOf(account);
374
- // A full link is for an account with a password: a local owner without one gets only mintLocalLink's.
375
292
  if (known === null || known.role !== "approver" || known.revokedAt !== null || !known.passwordSet)
376
293
  return null;
377
294
  return holdSignInLink({ kind: "full", account, expires: Date.now() + SIGN_IN_LINK_MS });
378
295
  }
379
- /** v147: this console start's key epoch (easy-start C2): the browser-key wave binds each session's mutation key to it. */
380
296
  const keyEpoch = options.keyEpoch ?? randomBytes(16).toString("hex");
381
- /** This computer, and nothing in front of it: a loopback peer that names a loopback address, with no sign of a proxy —
382
- * any forwarding header at all (Forwarded, X-Forwarded-*, X-Real-IP, Via, …) disqualifies the request. */
383
- const fromThisComputer = (request) => {
384
- const peer = request.socket.remoteAddress ?? "";
385
- if (!LOOPBACK_PEERS.has(peer))
386
- return false;
387
- for (const name of Object.keys(request.headers))
388
- if (PROXY_HEADER.test(name))
389
- return false;
390
- return /^(localhost|127\.0\.0\.1|\[::1\]):[0-9]{1,5}$/.test(request.headers.host ?? "");
391
- };
392
- /**
393
- * Cockpit B2: a request's password-freshness facts — the one place they are made (scope.ts honours them). Every
394
- * reader looks at the session as it is at the moment of the act, never a snapshot taken before the body arrived:
395
- * still signed in here, under the account's current credential generation, after any Forget.
396
- */
297
+ const fromThisComputer = (request) => requestFromThisComputer(request);
397
298
  function freshFactsOf(request, who, allowlisted = false) {
398
299
  if (who?.via !== 'cookie')
399
300
  return null;
400
301
  const session = who.session, local = fromThisComputer(request);
401
- // The same validity lookupSession applies, read again at the act: held here, within its idle and absolute
402
- // lifetimes, under the account's current credential generation, not revoked.
403
302
  const live = () => {
404
303
  const now = Date.now(), account = store.accountOf(who.name);
405
304
  return sessions.holds(session) && sessions.savedNow(session) && sessionWithinLifetime(session, now)
@@ -411,14 +310,12 @@ export function createDecisionServer(options) {
411
310
  consumeSsoNow: () => {
412
311
  const was = session.ssoNowAt;
413
312
  delete session.ssoNowAt;
414
- // A refund puts back only what this spend took, once, and only if nothing newer arrived (Forget still floors it).
415
313
  let refunded = false;
416
314
  return () => { if (refunded)
417
315
  return; refunded = true; if (was !== undefined && session.ssoNowAt === undefined)
418
316
  session.ssoNowAt = was; };
419
317
  },
420
318
  floor: () => session.freshFloor ?? 0,
421
- // Only a direct local request may start a password window (a typed password elsewhere proves now, nothing more).
422
319
  stamp: at => { if (local && live())
423
320
  session.passwordAt = at; } };
424
321
  }
@@ -430,9 +327,6 @@ export function createDecisionServer(options) {
430
327
  ssoProvider = { issuer, provider: found.provider, at: Date.now() };
431
328
  return found;
432
329
  }
433
- /** The identity provider as last discovered: what starting a sign-in uses (a GET, so it fetches nothing,
434
- * docs/plans/get-side-effects.md). Discovered as the console starts, by the background checks every ten minutes, and
435
- * when sign-in settings are saved or tested. */
436
330
  function providerKnown(issuer) {
437
331
  return ssoProvider !== null && ssoProvider.issuer === issuer ? ssoProvider.provider : null;
438
332
  }
@@ -441,10 +335,8 @@ export function createDecisionServer(options) {
441
335
  if (settings !== null)
442
336
  void providerFor(settings.issuer).catch(() => undefined);
443
337
  }
444
- /** Password sign-in is only for instance operators when the provider says so (a way in if it's down). */
445
338
  const passwordAllowed = (name) => { const settings = ssoSettings(); return settings === null || settings.passwords === "everyone" || store.isInstanceOperator(name); };
446
339
  const minutesWords = (ms) => { const minutes = Math.max(1, Math.ceil(ms / 60_000)); return minutes >= 120 ? `${Math.round(minutes / 60)} hours` : `${minutes} minute${minutes === 1 ? "" : "s"}`; };
447
- /** A sign-in event names the account only when it exists: what someone typed into the name box stays out of history. */
448
340
  const signInActor = (name) => name !== null && store.accountOf(name) !== null ? name : "unknown account";
449
341
  const recordSignIn = (actor, action, outcome, detail = null) => {
450
342
  try {
@@ -461,28 +353,14 @@ export function createDecisionServer(options) {
461
353
  };
462
354
  let joinGlobal = { tokens: 30, refilledAt: Date.now() };
463
355
  const approvalNonces = new Map();
464
- // Startup authority: the configured repos and roots as their identities say (startupCeiling). Missing or unresolved
465
- // paths remain restrictive. Native additions come only from the controller after its admission checks.
466
356
  const { ceiling, unresolved: unresolvedRepos, defaultProject, configured, configuredPaths } = startupCeiling([...(options.repo === undefined ? [] : [options.repo]), ...(options.repos ?? [])], options.projectRoots ?? [], options.identities === undefined ? undefined : identities, identities.strict);
467
- /** No ceiling configured at all: the legacy trust-everything mode, named. */
468
- // An `up` console (it is handed its admitted set) is never unscoped: with every saved project away it is empty.
469
- // Judged by what was configured, never by what has resolved so far: a console whose folders haven't answered yet is
470
- // scoped and empty, not unscoped.
471
357
  const unscopedMode = !configured && options.admittedRepos === undefined;
472
- /** Per-row visibility under the ceiling — the authorization question for reads. */
473
- /** The exact repositories this console serves now: `up`'s live admitted set when it supplies one, else startup's. */
474
358
  const exactRepos = () => options.admittedRepos?.() ?? ceiling.repos;
475
359
  const liveCeiling = () => {
476
360
  const repos = [...exactRepos(), ...(options.additionalProjectRepos?.() ?? [])];
477
- // An admitted set that is empty for now is an empty ceiling, never the legacy unscoped mode.
478
361
  return { repos: repos.length === 0 && ceiling.roots.length === 0 && !unscopedMode ? [NO_PROJECT] : repos, roots: ceiling.roots, canon: identities.strict };
479
362
  };
480
- /** The explicit, currently proved project list. The callback is supplied
481
- * only by `up`, after it has independently checked git-ness and the root
482
- * ceiling; this server still filters every row through its own ceiling. */
483
- /** Projects deleted while this console runs: gone from its lists though a builder started with them still watches. */
484
363
  const deletedRepos = new Set();
485
- /** Those still gone: a project added again (from here, `repos add`, or the lead) has its row back and shows again. */
486
364
  const goneRepos = () => {
487
365
  if (deletedRepos.size === 0)
488
366
  return deletedRepos;
@@ -503,7 +381,6 @@ export function createDecisionServer(options) {
503
381
  }
504
382
  return repos;
505
383
  };
506
- /** Settings → Project's view of a project: what's held for it, what's running, and whether this person may delete it. */
507
384
  const projectViewOf = (repo, who) => ({
508
385
  repo, name: projectName(repo), holdings: projectHoldings(store, repo), running: projectRunning(store, repo, clock()),
509
386
  canDelete: who.via === "cookie" && store.isInstanceOperator(who.name),
@@ -523,18 +400,15 @@ export function createDecisionServer(options) {
523
400
  liveView: (() => {
524
401
  const commands = liveCommandsShown(store, repo);
525
402
  const canChange = who.via === "cookie" && who.role === "approver" && !store.isDemo() && store.accountCanAccess(who.name, repo);
526
- // Showing commands is consent to one exact change: a single-use nonce for this person, project and terms.
527
403
  return { commands, canChange, ...(canChange && !commands ? { nonce: mintApprovalNonce(who.name, LIVE_VIEW_CONSENT, liveViewConsentDigest(repo)) } : {}) };
528
404
  })(),
529
405
  });
530
- /** Settings → Project → Build access: the project's named tools and whether each loads for its builds. */
531
406
  const projectAccessOf = (repo) => {
532
407
  try {
533
408
  const policy = store.orgPolicy();
534
409
  return { tools: projectToolsOf(store, repo).map(tool => {
535
410
  const refused = toolRefusal(policy, tool.name);
536
411
  const set = secretsSetFor(repo, tool.spec, toolHome);
537
- // As a launch decides (toolLaunchFor): a tool the organisation doesn't allow, or missing a secret, is left out.
538
412
  return refused !== null ? { name: tool.name, loads: false, words: refused }
539
413
  : { name: tool.name, loads: tool.spec.secrets.every(one => one.optional || set.includes(one.name)), words: toolStanding(tool, set).words };
540
414
  }) };
@@ -543,7 +417,6 @@ export function createDecisionServer(options) {
543
417
  return { problem: "Couldn't read this project's tools right now." };
544
418
  }
545
419
  };
546
- /** Settings → Project → Builds at once: the saved number, its workers' capacity, and what builds now. */
547
420
  const projectBuildsOf = (repo, who) => {
548
421
  const capacities = store.listRunners().filter(one => one.retiredAt === null && one.repos.includes(repo)).map(one => one.capacity);
549
422
  return {
@@ -553,7 +426,6 @@ export function createDecisionServer(options) {
553
426
  canChange: who.via === "cookie" && who.role === "approver" && store.accountCanAccess(who.name, repo),
554
427
  };
555
428
  };
556
- /** Codex's own MCP servers for a project (`codex mcp list --json`), for "Found on this computer"; null when Codex can't say. */
557
429
  const codexServers = async (repo) => {
558
430
  try {
559
431
  const listed = await (options.codexToolList ?? (async (cwd) => {
@@ -567,38 +439,28 @@ export function createDecisionServer(options) {
567
439
  return null;
568
440
  }
569
441
  };
570
- /** One project's Tools page: its tools with which secrets are set (never values), the common tools not yet added, and what this computer already has. */
571
- // A test's own folder for tool secrets and found tools; Toolroll's own (beside its database, and this home) otherwise.
572
442
  const toolHome = options.toolHome;
573
443
  const toolsViewOf = (repo, codex, kit = null, wanted = null) => {
574
444
  const tools = projectToolsOf(store, repo);
575
445
  const names = new Set(tools.map(one => one.name));
576
446
  return {
577
447
  repo, project: repo.split(/[\\/]/).filter(Boolean).at(-1) ?? repo,
578
- // Secrets that can't be read (a refused folder, a locked keychain) read as none set: the page says why once (storage).
579
448
  tools: tools.map(tool => { let secretsSet = []; try {
580
449
  secretsSet = secretsSetFor(repo, tool.spec, toolHome);
581
450
  }
582
451
  catch {
583
452
  secretsSet = [];
584
453
  } return { tool, secretsSet }; }),
585
- // A service that connects by signing in (or an app's own Connect) is offered only that way.
586
454
  catalog: TOOL_CATALOG.filter(one => !names.has(one.name) && oneClickOf(one.name) === null && localConnectOf(one.name) === null),
587
455
  connections: connectionsOf(store, repo, toolHome), kit, wanted,
588
- // The project's own .mcp.json as the background pass last read it off the console's thread (never read here).
589
456
  found: discoverTools(repo, codex, toolHome, process.env, options.identities === undefined ? undefined : savedProjectMcp.get(repo) ?? null).filter(one => !names.has(one.spec.name)),
590
457
  storage: toolSecretStorage(),
591
458
  };
592
459
  };
593
460
  const codingProjects = () => [...new Set([...managedRepos(), ...store.listProjects().map(project => project.path)])].filter(repo => rowVisible(liveCeiling(), repo));
594
- /** Open chat streams (live replies), ended when the server closes. */
595
461
  let liveTurnStarted = () => { };
596
- /** Google sign-ins in progress (v89): each consent visit's state, for 10 minutes. */
597
462
  const googleVisits = new Map();
598
- /** One-click connections on their way: the service's sign-in page and back, 15 minutes at most. */
599
463
  const connectVisits = new Map();
600
- /** Flows open in a browser (v88): who's here, and a nudge when one changes. */
601
- // Live views push on write (live-bus.ts): each commit moves the workspace revision, the rooms hear it.
602
464
  const liveBus = createLiveBus();
603
465
  const liveFollower = followWorkspace(store, () => workspaceRevision.current(), liveBus, { file: store.databaseFile() });
604
466
  const flowRooms = createFlowRooms(flow => flowFingerprint(store, flow), { bus: liveBus });
@@ -609,9 +471,6 @@ export function createDecisionServer(options) {
609
471
  provider: teamChatProvider,
610
472
  ...(options.subscriptionChatRunner ? { subscriptionRunner: options.subscriptionChatRunner } : {}),
611
473
  });
612
- // The personal lead queue (docs/plans/lead-message-queue.md). Projects and a message's task are re-proved AS the
613
- // person (never from a live request's context), and its live reply display is the console's own (chat handlers below,
614
- // reached only once the server is listening).
615
474
  const asActor = (account, work) => requestContext.run({ csrf: "", returnTo: "/", actor: account }, work);
616
475
  const admittedReposFor = (account) => asActor(account, () => managedRepos());
617
476
  const personalQueue = createPersonalQueueRuntime({
@@ -631,12 +490,10 @@ export function createDecisionServer(options) {
631
490
  return run !== null && family.versions.some(one => one.refId === run.taskRef);
632
491
  }),
633
492
  names: { project: projectName, modes: TASK_COMPOSER_MODES },
634
- // A queued message's partials are shaped as its final reply will be: for its words, with this console's own addresses.
635
493
  live: { begin: (thread, asked) => chatHandlers.beginLiveTurn(thread, { asked, appOrigin: [publicOrigin?.origin ?? null, options.configDir === undefined ? null : loadConsoleUrl(process.env, options.configDir)] }), end: (thread, ok, progress) => chatHandlers.endLiveTurn(thread, ok, progress) },
636
494
  ...(options.chatFetcher ? { fetcher: options.chatFetcher } : {}),
637
495
  ...(options.subscriptionChatRunner ? { subscriptionRunner: options.subscriptionChatRunner } : {}),
638
496
  });
639
- // Only browser sessions receive HTML cards. The CLI keeps its summary contract.
640
497
  const teamBrowserReply = (reply, actor, csrf) => {
641
498
  const snapshot = reply.snapshot;
642
499
  if (!snapshot?.selected || !snapshot.proposals)
@@ -649,9 +506,7 @@ export function createDecisionServer(options) {
649
506
  return { ...summary, card: teamProposalCardParts(store, actor, proposal, snapshot, csrf, decision, clock(), teamChatProvider).card };
650
507
  }) } };
651
508
  };
652
- // v112: one request budget per server for person API tokens, shared by every route a token signs in at (request-budget.ts).
653
509
  const requestBudget = new RequestBudget({ store, ...(options.requestBudgetClock === undefined ? {} : { clock: options.requestBudgetClock }) });
654
- // Unproved password attempts share a source budget. Only successful proof spends an account budget.
655
510
  const sourceClock = options.requestBudgetClock === undefined ? {} : { clock: options.requestBudgetClock };
656
511
  const passwordSourceBudget = new SourceAdmission({ perMinute: SOURCE_BUDGET_DEFAULTS.password, ...sourceClock });
657
512
  const passwordAccountBudget = new SourceAdmission({ perMinute: SOURCE_BUDGET_DEFAULTS.password, keyMode: "exact", ...sourceClock });
@@ -660,27 +515,19 @@ export function createDecisionServer(options) {
660
515
  const oauthTokenBudget = new SourceAdmission({ perMinute: SOURCE_BUDGET_DEFAULTS.oauthToken, ...sourceClock });
661
516
  const presentsPassword = (request) => /^Bearer (.+):(.+)$/.test(request.headers.authorization ?? "");
662
517
  const admitPasswordSource = (request) => presentsPassword(request) ? passwordSourceBudget.admit(joinSourceOf(request)) : { ok: true };
663
- /** Called only with a proved identity; cookies spend neither bearer budget. */
664
518
  const admitBearer = (request, actor) => {
665
519
  if (actor.principal !== undefined)
666
520
  return requestBudget.admit(actor.principal.tokenId, "api");
667
521
  return presentsPassword(request) ? passwordAccountBudget.admit(actor.name) : { ok: true };
668
522
  };
669
- /** Every project this person may pick in the console — the switcher, Projects, Settings, Tools and Flows read this
670
- * one list: the live admitted set (taskless projects included) and every project with saved work, each through
671
- * the ceiling and this account's project grants. A project removed or deleted here is gone from it. */
672
523
  const consoleProjects = () => {
673
524
  const gone = goneRepos();
674
525
  return [...new Set([...(admissionList() ?? []), ...managedRepos(), ...store.knownRepos()])].filter(one => visible(one) && !gone.has(one));
675
526
  };
676
527
  const server = createServer((request, response) => {
677
528
  instrumentRequest(store.telemetry, request, response);
678
- // Every password checked while answering counts against where this request came from (sign-in-guard.ts).
679
- // A GET or HEAD only reads (docs/plans/get-side-effects.md): store reads that would tidy up as they go don't.
680
529
  const answer = () => consoleFolders(options, identities, () => handle(request, response));
681
530
  void withPasswordSource(joinSourceOf(request), () => request.method === "GET" || request.method === "HEAD" ? asReadOnlyRequest(answer) : answer()).catch(error => {
682
- // Every unhandled error is logged (v99): the path and the message, never the request's body or query. The reference
683
- // is what a person's error page shows, so the log line can be found from it.
684
531
  const reference = `err_${randomBytes(4).toString("hex")}`;
685
532
  logEvent("error", "serve.error", { method: request.method, path: redactedPath(new URL(request.url ?? "/", "http://placeholder").pathname), error: error instanceof Error ? error.message : String(error), reference });
686
533
  if (envValue(process.env, "SERVE_DEBUG") === "1")
@@ -689,15 +536,13 @@ export function createDecisionServer(options) {
689
536
  const updating = error instanceof Error && error.message.includes(UPDATE_PAUSED);
690
537
  if (updating)
691
538
  response.setHeader("Retry-After", "5");
692
- // A browser asking for a page gets a page (Wave E): what happened, whether anything changed, the reference. It
693
- // holds no error text. Everything else keeps the plain answer.
694
539
  if (/\btext\/html\b/.test(String(request.headers.accept ?? "")) && (request.method === "GET" || request.method === "POST")) {
695
540
  const read = request.method === "GET";
696
541
  const at = new URL(request.url ?? "/", "http://placeholder");
697
542
  try {
698
543
  return page(response, updating ? 503 : 500, serverErrorPage({ updating, read, reference, at: new Date(), retry: read ? at.pathname + at.search : null }));
699
544
  }
700
- catch { /* the plain answer below */ }
545
+ catch { }
701
546
  }
702
547
  respond(response, updating ? 503 : 500, "text/plain; charset=utf-8", updating ? UPDATE_PAUSED : "something broke");
703
548
  }
@@ -708,9 +553,6 @@ export function createDecisionServer(options) {
708
553
  });
709
554
  server.once('listening', () => store.telemetry.start());
710
555
  server.once('close', () => store.telemetry.stop());
711
- // --public-url (arc 3): validated to EXACTLY an https origin. Its host
712
- // joins the allowed set, its origin authorizes POSTs, and cookies turn
713
- // Secure. Anything malformed refuses at startup, loudly.
714
556
  const publicOrigin = (() => {
715
557
  if (options.publicUrl === undefined)
716
558
  return null;
@@ -727,9 +569,7 @@ export function createDecisionServer(options) {
727
569
  return parsed;
728
570
  })();
729
571
  const cookieSecure = publicOrigin === null ? "" : "; Secure";
730
- /** Where Google may send someone back to (v89): the public https address, or this computer's own. */
731
572
  const consoleOrigin = (host) => host === undefined ? null : publicOrigin !== null && host === publicOrigin.host ? publicOrigin.origin : /^(localhost|127\.0\.0\.1|\[::1\]):[0-9]{1,5}$/.test(host) ? `http://${host}` : null;
732
- /** This computer's tailnet names, the last ones read (onboarding). */
733
573
  let tailnet = [];
734
574
  if (options.tailnetNames !== undefined) {
735
575
  const readTailnet = options.tailnetNames;
@@ -743,7 +583,7 @@ export function createDecisionServer(options) {
743
583
  const flushBudget = () => { try {
744
584
  requestBudget.flush();
745
585
  }
746
- catch { /* the next admit refuses if the database is unwell */ } };
586
+ catch { } };
747
587
  const timer = setInterval(flushBudget, REQUEST_BUDGET_FLUSH_MS);
748
588
  timer.unref?.();
749
589
  server.on("close", () => { clearInterval(timer); flushBudget(); });
@@ -752,7 +592,6 @@ export function createDecisionServer(options) {
752
592
  const address = server.address();
753
593
  return typeof address === "object" && address !== null ? address.port : null;
754
594
  };
755
- /** The names this server answers as. Anything else is a rebind, refused. */
756
595
  const allowedHost = (host) => {
757
596
  if (host === undefined)
758
597
  return false;
@@ -760,8 +599,6 @@ export function createDecisionServer(options) {
760
599
  const locals = port === null ? [] : [`localhost:${port}`, `127.0.0.1:${port}`, `[::1]:${port}`, ...tailnet.map(name => `${name}:${port}`)];
761
600
  return [...locals, ...(options.allowedHosts ?? []), ...(publicOrigin === null ? [] : [publicOrigin.host])].includes(host);
762
601
  };
763
- /** Easy-start C2: a protected loopback install (bound to loopback only, no --allow-host, no public URL, no tailnet
764
- * names) has one browser host, and there every browser mutation also presents the session's key (mutation-key.ts). */
765
602
  const browserKeys = createBrowserKeys({
766
603
  enabled: options.browserKey === true,
767
604
  epoch: keyEpoch,
@@ -774,7 +611,6 @@ export function createDecisionServer(options) {
774
611
  return address.address === "127.0.0.1" ? `127.0.0.1:${port}` : address.address === "::1" ? `[::1]:${port}` : null;
775
612
  },
776
613
  });
777
- /** The exact command that starts this console again as it runs now, plus a listening address or one more allowed host. */
778
614
  const consoleCommand = (change) => {
779
615
  const port = servedPort() ?? 4180;
780
616
  const address = server.address();
@@ -784,7 +620,6 @@ export function createDecisionServer(options) {
784
620
  return [`toolroll ${options.upConsole === true ? "up" : "serve"}`, ...(host === null ? [] : [`--host ${host}`]), ...(port === 4180 ? [] : [`--port ${port}`]),
785
621
  ...(allowed.length === 0 ? [] : [`--allow-host ${allowed.join(",")}`])].join(" ");
786
622
  };
787
- /** The wrong-host page's facts: the address opened, where the console answers, and the exact command that admits it. */
788
623
  const wrongHost = (host) => {
789
624
  const opened = host !== undefined && /^[A-Za-z0-9.-]{1,253}(:[0-9]{1,5})?$|^\[[0-9A-Fa-f:.]{2,45}\](:[0-9]{1,5})?$/.test(host) ? host : null;
790
625
  return { opened, served: `127.0.0.1:${servedPort() ?? 4180}`, command: opened === null ? null : consoleCommand({ allow: opened }) };
@@ -799,7 +634,6 @@ export function createDecisionServer(options) {
799
634
  approvalNonces.set(nonce, { name, taskId, digest, expiresAt: Date.now() + NONCE_TTL_MS });
800
635
  return nonce;
801
636
  }
802
- /** Single use, bound to who saw which digest of which task, and young. */
803
637
  function consumeApprovalNonce(nonce, name, taskId, digest) {
804
638
  const held = approvalNonces.get(nonce);
805
639
  if (held === undefined)
@@ -812,22 +646,13 @@ export function createDecisionServer(options) {
812
646
  }
813
647
  const hookContext = { store, clock, options };
814
648
  async function handle(request, response) {
815
- // Webhooks come through a public relay (Tailscale Funnel, a reverse
816
- // proxy) that forwards its own host name. The host check guards pages a
817
- // signed-in browser reads; a delivery carries no session and its answer
818
- // reveals nothing, so /hooks/ is answered before it, and only there.
819
649
  const hook = new URL(request.url ?? "/", "http://placeholder");
820
- // v99: a liveness probe for a load balancer or orchestrator. It answers before the host check (a probe
821
- // uses the address it reached), reads one row, and says nothing else about the installation.
822
650
  const method = request.method ?? "GET";
823
651
  const matchedRoute = matchRoute(method, hook.pathname);
824
- // Where a slow answer's time went (latency-timeline.ts): milestones by route id only, kept when it took a second.
825
652
  const timeline = new Timeline();
826
653
  timeline.mark("route matched");
827
654
  const edgeRoute = matchedRoute?.stage === 'edge' ? matchedRoute : null;
828
655
  const wrongMethodEdge = edgeRoute === null ? ROUTES.find(row => row.stage === 'edge' && new RegExp(row.pattern).test(hook.pathname)) ?? null : null;
829
- // D7: a password on a request still signs in this release, announced on every answer and named in every refusal;
830
- // from the release that removes it, it is refused here before anything checks it.
831
656
  if (isPasswordBearer(request.headers.authorization)) {
832
657
  if (!(options.passwordBearerAccepted ?? passwordBearerAccepted())) {
833
658
  request.resume();
@@ -844,9 +669,6 @@ export function createDecisionServer(options) {
844
669
  if (!allowedHost(request.headers.host)) {
845
670
  return respond(response, 421, "text/html; charset=utf-8", wrongHostPage(wrongHost(request.headers.host)));
846
671
  }
847
- // Easy-start C2: a protected loopback install has one browser origin, whose storage holds the session's mutation key.
848
- // A browser's page read at another loopback name (localhost, [::1]) moves there; machine callers and protocol
849
- // adapters (an API token, MCP's own addresses) are left where they are.
850
672
  const canonical = browserKeys.canonicalHost();
851
673
  if (canonical !== null && request.headers.host !== canonical && (method === "GET" || method === "HEAD") && request.headers.authorization === undefined
852
674
  && (edgeRoute === null || edgeRoute.domain === "people")) {
@@ -855,8 +677,6 @@ export function createDecisionServer(options) {
855
677
  response.end();
856
678
  return;
857
679
  }
858
- // A real domain (public-access.ts): HSTS for the public https host reached over HTTPS, and no API token over
859
- // plain HTTP from outside this computer and the tailnet — refused before anything reads or checks it.
860
680
  const transport = transportOf({ peer: request.socket.remoteAddress, joinSource: forwardedSourceOf(request), forwardedProto: request.headers["x-forwarded-proto"], forwarded: request.headers["forwarded"] });
861
681
  const hsts = hstsFor(publicOrigin?.host ?? null, request.headers.host, transport);
862
682
  if (hsts !== null)
@@ -867,31 +687,19 @@ export function createDecisionServer(options) {
867
687
  return respond(response, 403, "text/plain; charset=utf-8", insecure);
868
688
  }
869
689
  const url = new URL(request.url ?? "/", "http://placeholder");
870
- // A token in a URL is a token in history, logs, and referers. Refused
871
- // outright rather than ignored, so nobody learns the habit works.
872
690
  if (url.searchParams.has("token")) {
873
691
  return respond(response, 400, "text/plain; charset=utf-8", "credentials never travel in URLs");
874
692
  }
875
693
  if (edgeRoute === null && isEdgeAddress(url.pathname))
876
694
  return refuseEdge(request, response, url.pathname, wrongMethodEdge);
877
- // Live rooms share the browser identity/context below; their adapter carries token limits into each room.
878
695
  if (edgeRoute !== null && edgeRoute.domain !== 'people' && edgeRoute.domain !== 'live')
879
696
  return dispatchEdge(edgeRoute, { url, who: null, request, response, method });
880
- // Passive polls authenticate without extending the browser session.
881
697
  const fragmentName = url.searchParams.get("fragment");
882
698
  const workspaceRead = method === "GET" && url.searchParams.get('format') === 'workspace';
883
- // A workspace read's purpose (live-pages-and-home.md A1.4): bookkeeping only. Read on workspace GETs alone; on any other
884
- // request the header means nothing. No authorisation decision below reads it.
885
699
  const purpose = workspaceRead ? readPurpose(request.headers['x-toolroll-read']) : 'poll';
886
- // The reads that never extend the session, whatever their header says.
887
700
  const noTouch = edgeRoute?.domain === 'live' || (fragmentName !== null && NO_TOUCH_FRAGMENTS.has(fragmentName)) || /^\/code\/[a-f0-9]{32}\/state$/.test(url.pathname) || url.pathname === '/term/state'
888
- // The Agents view's Live grid only watches: its polls never extend or write the session.
889
701
  || url.pathname === '/agents/live' || /^\/agents\/live\/[0-9]{1,15}$/.test(url.pathname) || (url.pathname === '/agents' && url.searchParams.get('view') === 'live');
890
- // A followed link (`navigate`) extends the session exactly as the HTML GET of the same address would; every other
891
- // workspace read (a re-read, a prefetch) does not.
892
702
  const touch = !(method === "GET" && (noTouch || (workspaceRead && purpose !== 'navigate')));
893
- // A read ahead is answered only for a browser session, only for the prefetch allowlist (in-place.ts): anything else
894
- // hears 204 before any sign-in bookkeeping (a token's last use, a sign-in charge) is written.
895
703
  if (purpose === 'prefetch' && (request.headers.authorization !== undefined || !prefetchRoute(matchedRoute?.id, url))) {
896
704
  request.resume();
897
705
  return respond(response, 204, "text/plain; charset=utf-8", "");
@@ -905,12 +713,16 @@ export function createDecisionServer(options) {
905
713
  respond(response, admitted.status, "text/plain; charset=utf-8", admitted.status === 429 ? limitWords(admitted.limit, admitted.retryAfter) : "Request limits could not be checked; nothing ran. Try again shortly.");
906
714
  return true;
907
715
  };
908
- // One source charge before password proof and one account/token charge after it, including GET /login.
909
716
  if (refuseBudget(admitPasswordSource(request)))
910
717
  return;
911
718
  const refusedToken = {};
912
719
  const who = identify(request, touch, edgeRoute?.domain === 'live', refusedToken);
913
720
  timeline.mark("signed in");
721
+ if (refusedToken.elsewhere === true && edgeRoute?.domain !== 'people') {
722
+ request.resume();
723
+ response.setHeader("x-toolroll-refused", "local-owner-elsewhere");
724
+ return respond(response, 403, "text/plain; charset=utf-8", LOCAL_OWNER_ELSEWHERE);
725
+ }
914
726
  if (refusedToken.principal !== undefined) {
915
727
  if (refuseBudget(requestBudget.admit(refusedToken.principal.tokenId, "api")))
916
728
  return;
@@ -921,7 +733,6 @@ export function createDecisionServer(options) {
921
733
  }
922
734
  if (who?.via === "bearer" && refuseBudget(admitBearer(request, who)))
923
735
  return;
924
- // A read ahead from anything but a signed-in browser session (signed out, a token): 204, never the sign-in page.
925
736
  if (purpose === 'prefetch' && who?.via !== 'cookie') {
926
737
  request.resume();
927
738
  return respond(response, 204, "text/plain; charset=utf-8", "");
@@ -931,11 +742,8 @@ export function createDecisionServer(options) {
931
742
  if (edgeRoute?.domain === 'people')
932
743
  return freshFacts.run(fresh, () => provenPasswordAccount.run(passwordProof, () => dispatchEdge(edgeRoute, { url, who, request, response, method })));
933
744
  if (who === null) {
934
- // A password on a request that did not sign in is a machine's refusal, never a login page.
935
745
  if (isPasswordBearer(request.headers.authorization))
936
746
  return respond(response, 401, "text/plain; charset=utf-8", "authenticate first");
937
- // A GET to an exact task or result (a phone's deep link) signs in and
938
- // comes back to it — the destination is a same-site path only.
939
747
  return method === "GET"
940
748
  ? redirect(response, loginHref(url.pathname + url.search))
941
749
  : respond(response, 401, "text/plain; charset=utf-8", "authenticate first");
@@ -947,15 +755,11 @@ export function createDecisionServer(options) {
947
755
  actor: who.name,
948
756
  csrf: who.via === "cookie" ? who.session.csrf : "",
949
757
  returnTo: safeReturn(url.pathname + url.search),
950
- // This console's own addresses: a lead reply's links there read as "the task", "the result", "Settings → Lead".
951
758
  appOrigins: [consoleOrigin(request.headers.host), publicOrigin?.origin ?? null, options.configDir === undefined ? null : loadConsoleUrl(process.env, options.configDir)],
952
- // Every signed-in page shares the workspace shell; pages showing a one-time secret opt out (forceSensitive).
953
759
  browser: who.via === 'cookie',
954
- // Passwordless (read once for rendering; every act proves it again at the act): ceremony fields render as nothing.
955
760
  passwordless: who.via === 'cookie' && passwordlessOn(store),
761
+ advanced: advancedShownFor(store, who.name),
956
762
  openProject: who.via === 'cookie' ? who.session.project : null,
957
- // v100: signed in with the identity provider: its label, and whether it checked them recently enough to stand in for a password.
958
- // Cockpit B2: "fresh" is an explicit re-check made on request and not yet spent (read live; one step-up uses it).
959
763
  sso: who.via === 'cookie' && who.session.sso !== undefined ? { label: ssoSettings()?.label ?? "your identity provider",
960
764
  get fresh() { return freshFacts.getStore() != null && ssoNowAvailable(who.name); } } : undefined,
961
765
  refusal: (answer, status, body) => sendScreen(answer, status, screen(status === 404 ? "Not found" : "Request refused", body, { chrome: chromeFor(who.via === "cookie" ? who.session.project : null, "work") })),
@@ -967,15 +771,11 @@ export function createDecisionServer(options) {
967
771
  ...(workspaceRead && typeof request.headers['if-none-match'] === 'string' ? { workspaceIfNoneMatch: request.headers['if-none-match'] } : {}),
968
772
  workspaceRequest: url.searchParams.get('request'),
969
773
  timeline,
970
- // Easy-start C2: every page that posts carries the key fill while the key is required; a session whose key is from
971
- // an earlier start (or has none) is told to reconnect.
972
774
  keyFill: browserKeys.required(),
973
- // Easy start: a local owner with no password sees "Set a password to do this." where a step-up field would be.
974
775
  ...(who.via === "cookie" && who.authority === "local-owner" && store.accountOf(who.name)?.passwordSet === false
975
776
  ? { localStepUp: localOwnerRefusal(false, method === "GET" ? passwordSetNext(pagePathOf(url)) : "/").href } : {}),
976
777
  reconnect: browserKeys.stale(who, method === "GET" ? safeReturn(pagePathOf(url)) : "/"),
977
778
  };
978
- // A read ahead writes nothing, not even a slow request's record.
979
779
  if (purpose !== 'prefetch')
980
780
  response.once("finish", () => keepSlowRequest(store, timeline, matchedRoute?.id ?? "unmatched", response.statusCode, clock()));
981
781
  if (method === "GET" || method === "POST")
@@ -985,16 +785,11 @@ export function createDecisionServer(options) {
985
785
  const body = method === "POST" ? await form(request, (matchedRoute?.stage === "console" ? matchedRoute.bodyCap : undefined) ?? BODY_CAP) : null;
986
786
  const target = actionTarget(url, who, request, body === null ? null : readForm(body, CONSOLE_FORMS.ledgerTarget));
987
787
  const execute = async () => {
988
- // THE ROUTE TABLE (server/route-table.ts): nothing reaches a handler unless a row declares this method and
989
- // path and admits this kind of caller. Undeclared addresses retain the legacy instance-access refusal
990
- // for project-limited accounts, before the unrestricted router's not-found response.
991
788
  const route = matchedRoute?.stage === "console" ? matchedRoute : null;
992
789
  if (route === null)
993
790
  return restricted()
994
791
  ? refuse(response, who, 403, "This area requires instance access. Your account operates within its assigned projects.", "/projects")
995
792
  : refuse(response, who, 404, "There's no page at this address.", "/chat");
996
- // Easy-start C1: a local owner's session reaches only the rows marked for it (route-table.ts `local`), decided
997
- // first, before the route's policy reads anything and before any handler runs, GET and POST alike.
998
793
  if (who.via === "cookie" && who.authority !== "full" && (route.local !== "allow" || localPrincipalOf(who, route) === null)) {
999
794
  request.resume();
1000
795
  return refuseLocalOwner(response, who, method, url, request.headers.accept);
@@ -1006,8 +801,6 @@ export function createDecisionServer(options) {
1006
801
  request.resume();
1007
802
  if (method === "POST" && who.via === "bearer" && who.principal?.scope === "read")
1008
803
  return refuse(response, who, 403, REMOTE_MESSAGES.read);
1009
- // A viewer's act stays refused even when the table rejects their caller first (for example a
1010
- // password bearer at a step-up route). Preserve the viewer wording and explicit protocol refusals.
1011
804
  if (policy.reason === "scope" || (method === "POST" && who.role === "viewer" && !route.viewer && route.callerRefusal === undefined)) {
1012
805
  return refuse(response, who, 403, route.scopeRefusal ?? "your login can watch, not act — ask an approver to upgrade you");
1013
806
  }
@@ -1016,8 +809,6 @@ export function createDecisionServer(options) {
1016
809
  : respond(response, route.callerRefusal.status, route.callerRefusal.type, route.callerRefusal.body);
1017
810
  }
1018
811
  if (method === "GET") {
1019
- // Authorize every read before considering a conditional response.
1020
- // Task/result opening and receipt reconciliation always re-read work.
1021
812
  const facts = requestContext.getStore();
1022
813
  if (facts?.workspaceRead && who.via === 'cookie' && route.id === 'chat.page' &&
1023
814
  !url.searchParams.has('task') && !url.searchParams.has('result') && !url.searchParams.has('request')) {
@@ -1031,15 +822,11 @@ export function createDecisionServer(options) {
1031
822
  return respond(response, 304, 'application/json; charset=utf-8', '');
1032
823
  }
1033
824
  const expiresAt = workspaceRevision.expiresAt(now);
1034
- // A clock-bound refresh receives a different validator even when
1035
- // no database row changed (for example an expired worker lease).
1036
825
  facts.workspaceValidator = { key, revision, expiresAt,
1037
826
  etag: '"' + createHash('sha256').update(`${key}:${revision}:${expiresAt}`).digest('hex') + '"' };
1038
827
  }
1039
828
  await prefetchChrome(route, url, who);
1040
829
  timeline.mark("chrome and worker reads");
1041
- // The worker wait lets a sign-out, credential/access change or console ceiling change land. Prove the
1042
- // cookie and route again before rendering protected content or answering with a content validator.
1043
830
  if (who.via === 'cookie') {
1044
831
  const current = identify(request, false);
1045
832
  if (current?.via !== 'cookie' || current.session !== who.session)
@@ -1051,16 +838,12 @@ export function createDecisionServer(options) {
1051
838
  }
1052
839
  return handlePost(route, url, who, request, response, body);
1053
840
  };
1054
- // Easy-start C1: an allowed row runs as the local owner, in the act the row is (execute refuses every other): the
1055
- // prover answers "local-owner" only for that act, and every write it makes re-proves it still stands.
1056
841
  const local = who.via === "cookie" && who.authority !== "full" && matchedRoute?.stage === "console" && matchedRoute.local === "allow" ? localPrincipalOf(who, matchedRoute) : null;
1057
842
  if (local !== null)
1058
843
  response.once("close", () => { local.request.ended = true; });
1059
844
  const run = () => local === null ? execute() : asLocalOwner(local, execute);
1060
845
  if (method === "GET")
1061
846
  return projectAuthority.run({ actor: who.name, repo: target.repo }, run);
1062
- // Request acceptance is separate from durable work completion. Never
1063
- // persist a body, query string, token, password, or arbitrary URL.
1064
847
  const entry = { at: clock().toISOString(), actor: who.name, ...target, source: "request", ...(who.via === "bearer" && who.token !== undefined ? { detail: `API token: ${who.token}` } : {}) };
1065
848
  store.recordAction({ ...entry, outcome: "requested" });
1066
849
  try {
@@ -1084,7 +867,7 @@ export function createDecisionServer(options) {
1084
867
  try {
1085
868
  repo = coding.get(match[1], { name: who.name, generation: who.session.generation }).repo;
1086
869
  }
1087
- catch { /* The route refuses unknown/foreign sessions. */ }
870
+ catch { }
1088
871
  }
1089
872
  return { repo, taskId: null, runId: null, action: `coding ${body ? url.pathname.split('/').at(-1) : 'view'}` };
1090
873
  }
@@ -1135,9 +918,6 @@ export function createDecisionServer(options) {
1135
918
  if (project === undefined) {
1136
919
  return refuse(response, who, 403, "that project is outside what this server was configured to show");
1137
920
  }
1138
- // A project link is a read context, not a session-changing operation.
1139
- // Prove it against both admission and the known project catalog before
1140
- // collection queries; unknown/foreign paths reveal no work.
1141
921
  if ((route.id === 'tasks' || route.id === 'work' || route.id === 'system') && url.searchParams.has('project')) {
1142
922
  const wanted = url.searchParams.get('project') ?? '';
1143
923
  if (url.searchParams.getAll('project').length !== 1 || !visible(wanted) ||
@@ -1146,8 +926,6 @@ export function createDecisionServer(options) {
1146
926
  }
1147
927
  project = wanted;
1148
928
  }
1149
- // Home (UI revamp wave B) shows every project unless its address names one (proved the same way), and the rail's
1150
- // and the dock's Needs-you count follow that same one scope.
1151
929
  if (route.id === 'home') {
1152
930
  const wanted = url.searchParams.get('project');
1153
931
  if (wanted !== null && (url.searchParams.getAll('project').length !== 1 || !visible(wanted) ||
@@ -1156,19 +934,12 @@ export function createDecisionServer(options) {
1156
934
  }
1157
935
  project = wanted;
1158
936
  }
1159
- // All projects, asked for by name on Tasks (its project filter): the rolled-up list, admission-bound as ever.
1160
- // Tasks (P1.4) says every project as scope=all; an old link's all=1 still reads so.
1161
937
  if (route.id === 'tasks' && !url.searchParams.has('project') && ((url.searchParams.get('scope') === 'all' && url.searchParams.getAll('scope').length === 1)
1162
938
  || (url.searchParams.get('all') === '1' && url.searchParams.getAll('all').length === 1)))
1163
939
  project = null;
1164
- // Every page's Tasks count covers this one project view, whatever project the page itself shows.
1165
940
  const facts = requestContext.getStore();
1166
941
  if (facts !== undefined)
1167
942
  facts.lens = project;
1168
- // Exact result links carry their own read context. Check the stored
1169
- // placement against both account and instance access before using it;
1170
- // viewing a result never changes the session's selected project, and
1171
- // the page's project switch keeps showing the person's own choice.
1172
943
  const chosenProject = project;
1173
944
  if (route.id === "review" && url.searchParams.has("result")) {
1174
945
  const wanted = url.searchParams.get("result") ?? "";
@@ -1181,24 +952,6 @@ export function createDecisionServer(options) {
1181
952
  if (who.via === "cookie" && ref !== null && visible(ref.repo))
1182
953
  project = ref.repo;
1183
954
  }
1184
- // Nothing open and more than one thing to choose: land on the opener.
1185
- // Decisions and their evidence stay reachable — answering must never be
1186
- // blocked by project state — and the opener itself must not loop.
1187
- // A run's page and its evidence (workspace package 1): a bookmarked
1188
- // `/r/<id>` from All projects used to bounce to the opener until a
1189
- // project was chosen. The handler below re-proves the run's repo
1190
- // against the ceiling and the account (`runVisible`) before a byte
1191
- // renders, so letting the path through widens nothing.
1192
- // The chat's two read-only refresh routes (package 2 revision): the
1193
- // page itself is allowed from All projects, so its status poll and
1194
- // task fragment must be too — a 303 to the opener answered the poll
1195
- // with HTML and the page wrongly said the sign-in was lost. Each
1196
- // route keeps its own cookie, role, session, ceiling, and task
1197
- // admission checks. Shared action links likewise recheck the saved
1198
- // owner and project in their handler, so they stay reachable from All
1199
- // projects without changing the selected project or granting access.
1200
- // Which reads first need an open project is the route table's `needsProject` column; an exact result link
1201
- // and the all-projects board carry their own read context.
1202
955
  const needsProject = who.via === "cookie" && project === null && !unscopedMode &&
1203
956
  route.needsProject &&
1204
957
  !(route.id === "review" && url.searchParams.has("result")) &&
@@ -1207,32 +960,15 @@ export function createDecisionServer(options) {
1207
960
  return redirect(response, `/projects?return=${encodeURIComponent(safeReturn(url.pathname + url.search))}`);
1208
961
  return dispatchConsole(route, { url, who, request, response, route, now, project, chosenProject, posted: new URLSearchParams() });
1209
962
  }
1210
- /**
1211
- * The first run (adoption track, step 3): three plain steps derived from
1212
- * live state on every render, never a stored cursor, and retired
1213
- * PERMANENTLY by the first-success installation fact (Codex adoption
1214
- * review, finding 14). Each step is either something this console can do,
1215
- * or the exact command where only the CLI can (finding e).
1216
- */
1217
963
  function firstRunStepsNow(now) {
1218
964
  if (restricted() || store.isDemo() || store.firstSuccessAt(now) !== null)
1219
965
  return null;
1220
966
  return firstRunSteps({ agentSignedIn: agentSignedIn(now), projects: managedRepos().length, hasTask: store.hasAnyWork(), firstResultAt: null, signInCommand: agentSignInCommand() });
1221
967
  }
1222
- /**
1223
- * Whether a coding agent is signed in where the work runs. This machine's
1224
- * own checks (the ones Settings makes) speak only for a worker on this
1225
- * machine, or for the first one while none is registered yet (it is started
1226
- * here); a worker elsewhere speaks through its own readiness report, and
1227
- * the console never claims to have checked that machine (finding 15).
1228
- * Nothing here waits on a probe: this machine's answer is the last one
1229
- * seen, refreshed in the background, and null until the first one is in.
1230
- */
1231
968
  function agentSignedIn(now) {
1232
969
  const here = hostname();
1233
970
  const registered = store.listRunners().filter(one => one.retiredAt === null);
1234
971
  const workers = registered.filter(one => runnerAlive(one, now));
1235
- // This machine under any of its own names (machine-identity.ts): a hostname that moved with the network is still here.
1236
972
  if (workers.some(one => !sameMachineHost(one.host, here) && store.providerReadiness(one.name).some(seen => seen.state === "ready")))
1237
973
  return true;
1238
974
  return options.localRunner !== undefined || registered.length === 0 || workers.some(one => sameMachineHost(one.host, here)) ? localAgentSignedIn() : false;
@@ -1240,7 +976,6 @@ export function createDecisionServer(options) {
1240
976
  let localSignIn = null;
1241
977
  let localSignInChecking = null;
1242
978
  let leadRecheckedAt = 0;
1243
- /** Ask this computer's agent CLIs again (no model, nothing spent); `fresh` skips their 30-second cache. */
1244
979
  function checkLocalAgents(fresh = false) {
1245
980
  if (localSignInChecking !== null)
1246
981
  return localSignInChecking;
@@ -1248,22 +983,16 @@ export function createDecisionServer(options) {
1248
983
  .then(([claude, codex]) => {
1249
984
  localSignIn = { at: Date.now(), signedIn: [claude, codex].some(state => state === "connected" || state === "key-works" || state === "key-present"), states: { claude: claude, codex: codex } };
1250
985
  leadByDefault();
986
+ if (options.leadByDefault === true && !store.isDemo())
987
+ fillRoutingOnSignIn(store, localSignIn.states, clock());
1251
988
  })
1252
989
  .catch(() => { })
1253
990
  .finally(() => { localSignInChecking = null; });
1254
991
  return localSignInChecking;
1255
992
  }
1256
- /** The last answer only (docs/plans/get-side-effects.md): this computer is asked again by the background checks or a
1257
- * person's Check now, never because a page was opened. */
1258
993
  function localAgentSignedIn() {
1259
994
  return localSignIn?.signedIn ?? null;
1260
995
  }
1261
- /**
1262
- * The lead on by default (onboarding): with no lead set up yet, the agent CLI signed in on this computer runs it
1263
- * (Claude Code first, else Codex) on its membership with today's safe defaults: the CLI's own default model, 50 turns
1264
- * a day, no dollar spend, and every action it proposes still a card a person confirms. Once only, ever: a lead
1265
- * someone turned off stays off, and Settings → Lead changes it.
1266
- */
1267
996
  function leadByDefault() {
1268
997
  if (options.leadByDefault !== true || store.isDemo() || store.getChatConfig() !== null || store.installationFact(LEAD_BY_DEFAULT_FACT) !== null)
1269
998
  return;
@@ -1274,29 +1003,21 @@ export function createDecisionServer(options) {
1274
1003
  store.transact(() => {
1275
1004
  store.setChatConfig({ provider, model: "default", dailyTurns: 50, weeklyCeilingMicrousd: 0, priceInMicrousd: 0, priceOutMicrousd: 0 }, "toolroll", now);
1276
1005
  store.recordInstallationFact(LEAD_BY_DEFAULT_FACT, provider, now);
1277
- // A laptop install (local mode on): the agent chosen here also starts the models, on its default preset, while
1278
- // nothing is chosen yet, so the owner's first task plans without a password (model-choices.ts fillDefaultRouting).
1279
1006
  const agent = defaultAgentOf(provider);
1280
1007
  if (agent !== null && localModeOn(store))
1281
1008
  fillDefaultRouting(store, agent, "toolroll", { kind: "first-start" }, now);
1282
1009
  });
1283
1010
  }
1284
- // Look once at start, so the lead is on by the time the browser opens.
1285
1011
  if (options.leadByDefault === true && !store.isDemo() && store.getChatConfig() === null)
1286
1012
  void checkLocalAgents();
1287
- /** What the lead runs on, in words for one line ("your Claude Code sign-in"); null for a direct API or no lead. */
1288
1013
  function leadWords() {
1289
1014
  const config = store.getChatConfig();
1290
1015
  return config?.provider === "claude-subscription" ? "your Claude Code sign-in" : config?.provider === "codex-subscription" ? "your Codex sign-in" : null;
1291
1016
  }
1292
- /** The one command that gets an agent signed in here, for this operating system: sign in when its CLI is installed, else install Claude Code and sign in. */
1293
1017
  function agentSignInCommand() {
1294
1018
  return signInCommandFor(localSignIn?.states ?? null, options.platform ?? process.platform);
1295
1019
  }
1296
- /** First tasks per project: the last ones found (safe generic ones until then), re-read in the background at most
1297
- * every ten minutes. A render never waits on `gh` or `git grep`. */
1298
1020
  const firstTasks = new Map();
1299
- /** The phone setup itself (Settings → Chat apps): a chat app, or this console over Tailscale. */
1300
1021
  function phoneSetup(who) {
1301
1022
  if (who.role !== "approver" || store.isDemo())
1302
1023
  return undefined;
@@ -1311,49 +1032,27 @@ export function createDecisionServer(options) {
1311
1032
  dismissHref: "/onboarding/phone/dismiss",
1312
1033
  };
1313
1034
  }
1314
- // ---- fleet chat (v13) ----------------------------------------------------
1315
1035
  const chatFetcher = options.chatFetcher ?? fetch;
1316
1036
  const chatEnv = options.chatEnv ?? process.env;
1317
- /** The lead's last non-answer per BROWSER session (keyed by its csrf —
1318
- * never by name, so two browsers on one account do not read each other's
1319
- * notes), bound to the mate turn it came from so a note from a session
1320
- * that has since ended never shows; bounded; read once. */
1321
1037
  const leadSaid = new Map();
1322
- /** The unified conversation's rows for one reader (package 2): the SAME
1323
- * rows the page renders and the status poll's fragments re-render, so a
1324
- * live update can never show a card the page would not. A task lens
1325
- * keeps only that task's coordinator cards; the lead's own thread is one
1326
- * thread regardless of lens. */
1327
1038
  function leadConversationRows(who, principal, focusTask, now, chatProject = null) {
1328
1039
  const allCoordinatorRows = store.listCoordinatorProposals({ repos: managedRepos(), states: ["pending", "confirmed", "refused"], limit: 30 });
1329
1040
  const coordinatorProposals = focusTask !== null ? allCoordinatorRows.filter(one => focusTask.family.versions.some(version => version.id === one.payload["task"]))
1330
1041
  : chatProject !== null ? allCoordinatorRows.filter(one => one.repo === chatProject) : allCoordinatorRows;
1331
- // A visit only reads (quiet page visits): this opens no thread. The first message opens it (chatSend), and a
1332
- // live thread kept under another ceiling is what that message replaces, so it reads here as the earlier one.
1333
1042
  const found = store.liveLeadThreadFor(who.name, chatScopeOf(focusTask, chatProject));
1334
1043
  const thread = found !== null && found.ceilingDigest === principal.ceilingDigest ? found : null;
1335
1044
  const proposals = thread === null ? [] : store.listLeadProposals(thread.id);
1336
- // One reply runs at a time per person; this thread shows it only when
1337
- // the reply is its own.
1338
1045
  const live = store.liveLeadTurnFor(who.name);
1339
1046
  const messages = thread === null ? [] : store.listLeadMessages(thread.id, 40);
1340
- // The lead's question with buttons, while its reply is the last word in the thread.
1341
1047
  const last = messages.at(-1);
1342
1048
  const asking = last?.role === "assistant" && last.turn !== null && store.getLeadTurn(last.turn)?.approver === who.name ? store.leadAskOpen(last.turn, now) : null;
1343
- // A question about this task loses its buttons once the version shown moved after it was asked (its plan
1344
- // rewritten or approved, a new attempt started): its options answered a state that is gone. Its words stay, marked so.
1345
1049
  const staleAsk = asking !== null && focusTask !== null && taskMovedSince(store, focusTask.executionId, asking.createdAt) ? asking.turn : null;
1346
1050
  const ask = staleAsk === null ? asking : null;
1347
- // Answered questions stay readable above the answer; only their buttons go.
1348
1051
  const asks = new Map(messages.flatMap(one => { const asked = one.role === "assistant" && one.turn !== null ? store.leadAsk(one.turn) : null; return asked === null ? [] : [[asked.turn, asked]]; }));
1349
- // The person's queued messages in this thread: each shows waiting (with Remove) or why it was not sent.
1350
1052
  const queue = new Map(thread === null ? [] : personalQueue.queue.forThread(thread.id).map(row => [row.message, row]));
1351
- // The thread a ceiling change replaced (ruling 9), display only: closed already, or still live under the old ceiling.
1352
1053
  const replaced = thread !== null ? store.replacedLeadThread(thread)
1353
1054
  : found !== null && found.scope.kind === "lead" && store.listLeadMessages(found.id, 1).length > 0 ? found : null;
1354
1055
  const previousProposals = replaced === null ? [] : store.listLeadProposals(replaced.id);
1355
- // How this thread's last reply ended, read from its saved turn (never process memory, which a restart loses): a
1356
- // failed turn that saved no message of its own says why in the thread, until the next reply starts.
1357
1056
  const lastTurn = thread === null ? null : latestLeadTurnOfThread(store, thread.id);
1358
1057
  const failure = lastTurn !== null && lastTurn.state === "failed" && !messages.some(one => one.role === "assistant" && one.turn === lastTurn.id)
1359
1058
  ? leadFailureText(lastTurn.failureReason, store.leadTurnCostUnconfirmed(lastTurn.id), lastTurn.failureDetail ?? null) : null;
@@ -1372,18 +1071,10 @@ export function createDecisionServer(options) {
1372
1071
  recent: store.recentLeadTurns(who.name, 5),
1373
1072
  };
1374
1073
  }
1375
- /** The thread a chat surface speaks in (v77): the task's own thread, the
1376
- * project's, or the lead conversation across every project. */
1377
1074
  function chatScopeOf(focusTask, chatProject) {
1378
1075
  return focusTask !== null ? { kind: "task", key: focusTask.id } : chatProject !== null ? { kind: "project", key: chatProject } : LEAD_THREAD;
1379
1076
  }
1380
1077
  const liveTurns = new Map();
1381
- /** The Ask panel (v77): the conversation a task, result or project page
1382
- * docks beside itself — that page's own thread, the same session and
1383
- * cards as /chat. Null when this person has no lead chat here. A page
1384
- * view starts nothing (quiet page visits): with no membership
1385
- * conversation yet, the panel binds its sends to NOT_STARTED_SESSION and
1386
- * the first message starts one (chatSend). */
1387
1078
  function dockedConversation(who, focusTask, chatProject, now, back, resultRunId = null) {
1388
1079
  if (who.via !== "cookie" || who.role !== "approver" || (focusTask === null && chatProject === null))
1389
1080
  return null;
@@ -1404,21 +1095,13 @@ export function createDecisionServer(options) {
1404
1095
  taskId: focusTask?.id ?? null, resultRunId, project: focusTask === null ? chatProject : null, failure: rows.pending === null ? rows.failure : null,
1405
1096
  };
1406
1097
  }
1407
- /** The session-layer principal (ruling 3): cookie, csrf, and role were
1408
- * proved at the edge; the row and the generation are re-proved here. */
1409
- /** Start the person's lead conversation: the session every later turn
1410
- * debits (a membership spends nothing; direct API gets a per-conversation
1411
- * ceiling) and its thread. Starting ends any older session. */
1412
1098
  function startLeadConversation(who, principal, enabled, ceilingUsd, follow, now, scope = LEAD_THREAD, request) {
1413
- // A page's first send (quiet page visits) starts it under that send's request: the start and its record are one
1414
- // write, so a retry of the same request finds the conversation it started and never starts another.
1415
1099
  if (request !== undefined) {
1416
1100
  return store.transact(() => store.replay({ idempotencyKey: `mate-start:${who.name}:${request}`, actor: who.name, at: now }, "mate-start", () => ({ session: startLeadConversation(who, principal, enabled, ceilingUsd, follow, now, scope) })).session);
1417
1101
  }
1418
1102
  const ceilingMicrousd = enabled.billing === "subscription" ? 0 : Math.round(ceilingUsd * 1_000_000);
1419
1103
  const termsDigest = createHash("sha256").update(`${ceilingMicrousd}\n${principal.ceilingDigest}`).digest("hex");
1420
1104
  const sessionId = store.mintLeadSession({ approver: who.name, approverGeneration: principal.generation, credentialKey: enabled.credentialKey, ceilingMicrousd, ceilingDigest: principal.ceilingDigest, termsDigest }, now);
1421
- // The thread the first message goes to (quiet page visits: a task's first message opens only the task's thread).
1422
1105
  const thread = store.openLeadThread(who.name, principal.ceilingDigest, now, scope).thread;
1423
1106
  if (follow)
1424
1107
  configureLeadFollow(store, principal, store.getLeadSession(sessionId), thread, true, now);
@@ -1431,15 +1114,10 @@ export function createDecisionServer(options) {
1431
1114
  }
1432
1115
  const CHAT_CANDIDATES_PER_APPROVER = 9;
1433
1116
  const CHAT_CANDIDATE_TTL_MS = 30 * 60_000;
1434
- /** The frozen explicit repo list, digested canonically (sorted) — every
1435
- * candidate binds to it and filing re-proves it (v2 new finding 5). */
1436
1117
  const chatCeilingDigest = (repos = managedRepos()) => createHash("sha256").update([...repos].sort().join("\n")).digest("hex");
1437
- /** The scripted lead answers only inside a demo database. */
1438
1118
  function demoLeadHere() {
1439
1119
  return options.demoLead !== undefined && store.isDemo() ? options.demoLead : null;
1440
1120
  }
1441
- /** Every condition re-proved per request — the render and the POST each
1442
- * ask again; nothing is cached into authority. */
1443
1121
  function chatEnablement() {
1444
1122
  if (store.isDemo())
1445
1123
  return { ok: false, code: "demo", why: "this is a demo database — chat cannot contact an external model" };
@@ -1472,13 +1150,6 @@ export function createDecisionServer(options) {
1472
1150
  return { ok: false, code: "no-key", why: `no ${config.provider} key — paste one below (stored 0600 beside the database, never in it), or export ${CHAT_KEY_ENV[config.provider]} in the serve environment` };
1473
1151
  return { ok: true, billing: "metered", config: config, key: key.key, keySource: key.source, price, credentialKey: credentialKeyOf(config.provider, key.key) };
1474
1152
  }
1475
- /**
1476
- * Where a chat key comes from, in priority order: the serve process
1477
- * environment, then the 0600 key file under the config directory (the
1478
- * Telegram bot-token precedent — settable from the console, never the
1479
- * database, never echoed whole). The file exists so onboarding lives
1480
- * in the UI; the environment exists so operators who prefer it keep it.
1481
- */
1482
1153
  function chatKeyFor(provider) {
1483
1154
  const fromEnv = chatEnv[CHAT_KEY_ENV[provider]];
1484
1155
  if (fromEnv !== undefined && fromEnv !== "")
@@ -1493,13 +1164,7 @@ export function createDecisionServer(options) {
1493
1164
  return null;
1494
1165
  }
1495
1166
  }
1496
- /** OpenRouter's live catalog, cached briefly: every selectable model
1497
- * arrives WITH the price the config will pin (operator request — the
1498
- * whole catalog, not a hand-pinned shortlist). null = no key or the
1499
- * catalog is unreachable; callers fall back to the compiled table. */
1500
1167
  let catalogCache = null;
1501
- /** The catalog as last fetched, for a page to show (docs/plans/get-side-effects.md): a page never fetches it. The
1502
- * background checks keep it current while an OpenRouter key is saved; saving a choice fetches it (chatCatalog). */
1503
1168
  function chatCatalogKnown() {
1504
1169
  return chatKeyFor("openrouter-api") === null ? null : catalogCache?.models ?? null;
1505
1170
  }
@@ -1525,11 +1190,6 @@ export function createDecisionServer(options) {
1525
1190
  clearTimeout(timer);
1526
1191
  }
1527
1192
  }
1528
- /**
1529
- * The palette's server-rendered index (attended review, finding 4): a
1530
- * non-executable JSON block on an already-authorized page — the same
1531
- * titles the page itself may render, bounded, saturation declared.
1532
- */
1533
1193
  function paletteIndexTag(project) {
1534
1194
  const admitted = project === null ? admissionList() : null;
1535
1195
  const entries = [
@@ -1559,15 +1219,6 @@ export function createDecisionServer(options) {
1559
1219
  const safeEntries = restricted() ? entries.filter(one => ["/tasks", "/tasks?view=needs-you", "/", "/tasks?view=board", "/flows", "/tasks?view=done", "/tasks?view=ready", "/runs", "/projects", "/ledger"].includes(one.href) || one.href.startsWith("/t/")) : entries;
1560
1220
  return jsonScript(saturated ? [...safeEntries, { label: "… more in Tasks", href: "/tasks" }] : safeEntries, { id: "palette-index" });
1561
1221
  }
1562
- /**
1563
- * The palette cache (arc 4, finding 6), and its honest contract: a
1564
- * render may be up to five seconds stale after OUT-OF-PROCESS changes;
1565
- * an accepted in-process mutation invalidates immediately (bustBadge),
1566
- * so "one query per five seconds" holds only between invalidations;
1567
- * and an OPEN page keeps its navigation-time snapshot until the next
1568
- * navigation — no refresh mechanism exists or is promised. The key
1569
- * carries the one configuration bit the entries vary by.
1570
- */
1571
1222
  const paletteCache = new Map();
1572
1223
  function paletteTagCached(project) {
1573
1224
  const actor = requestContext.getStore()?.actor;
@@ -1579,44 +1230,26 @@ export function createDecisionServer(options) {
1579
1230
  paletteCache.set(key, { at: Date.now(), tag });
1580
1231
  return tag;
1581
1232
  }
1582
- /**
1583
- * Every chromed HTML response leaves through here (arc 4, findings
1584
- * 5/18): one place owns the sensitivity call, the nonce, the palette
1585
- * index, the shortcuts overlay, script composition, and the CSP —
1586
- * at most one nonce-bearing script per response, connect-src only when
1587
- * that script fetches. The named exception: /fleet and /settings keep
1588
- * their FUNCTIONAL scripts beside credential fields (a poller and the
1589
- * push enrollment — neither reads the fields); the chrome additions
1590
- * are what sensitivity strips.
1591
- */
1592
1233
  function sendScreen(response, status, s) {
1593
1234
  requestContext.getStore()?.timeline?.mark("handler done; rendering");
1594
- // Sensitivity is the page as authored (cockpit §2, R14): its own explicit word, else a password field it was written
1595
- // with — judged before an identity-provider sign-in replaces that field, so an SSO step-up page stays sensitive.
1596
1235
  const authored = s.sensitive ?? (s.forceSensitive === true ||
1597
1236
  SENSITIVE_INPUT.test(htmlString(s.body)) ||
1598
1237
  (s.workspace?.pageHtml != null && SENSITIVE_INPUT.test(htmlString(s.workspace.pageHtml))) ||
1599
1238
  (s.chrome?.listPane !== undefined && SENSITIVE_INPUT.test(htmlString(s.chrome.listPane))));
1600
- // v100: signed in with the identity provider, a step-up's password field is that sign-in instead.
1601
1239
  const ssoFacts = requestContext.getStore()?.sso;
1602
1240
  if (ssoFacts !== undefined) {
1603
1241
  const back = requestContext.getStore()?.returnTo ?? "/";
1604
- // A typed-only proof (settings-kit.ts) stays a password field: its handler takes nothing else.
1605
1242
  s = { ...s, body: keepTypedFields(s.body, ssoStepUps, ssoFacts, back), ...(s.workspace?.pageHtml == null ? {} : { workspace: { ...s.workspace, pageHtml: keepTypedFields(s.workspace.pageHtml, ssoStepUps, ssoFacts, back) } }) };
1606
1243
  if (s.workspace?.view?.kind === "flow")
1607
1244
  s = { ...s, workspace: { ...s.workspace, view: { ...s.workspace.view, stepUp: { label: ssoFacts.label, fresh: ssoFacts.fresh, confirmHref: `/login/sso?reauth=1&return=${encodeURIComponent(back)}` } } } };
1608
1245
  }
1609
- // Easy start: a local owner with no password has none to type: each step-up field says how to set one instead.
1610
1246
  const localStepUp = requestContext.getStore()?.localStepUp;
1611
1247
  if (localStepUp !== undefined) {
1612
1248
  s = { ...s, body: localOwnerStepUps(s.body, localStepUp), ...(s.workspace?.pageHtml == null ? {} : { workspace: { ...s.workspace, pageHtml: localOwnerStepUps(s.workspace.pageHtml, localStepUp) } }) };
1613
1249
  }
1614
- // D5: team chat (the central team service) is deprecated; /chat?team=1 still opens this release, but nothing links to it.
1615
1250
  const sensitive = authored || s.forceSensitive === true;
1616
1251
  const requestFacts = requestContext.getStore();
1617
- // Easy-start C2: while the browser mutation key is required, every page's one nonce'd script also fills the key.
1618
1252
  const keyFill = requestFacts?.keyFill === true ? KEY_FILL_SCRIPT : "";
1619
- // The settings frame (settings-kit.ts): its breadcrumb, for the shell and the workspace alike.
1620
1253
  if (s.chrome !== undefined && s.chrome.crumbs === undefined) {
1621
1254
  const crumbs = settingsCrumbs(new URL(requestFacts?.returnTo ?? '/', 'http://standing-orders.local').pathname, s.title, htmlString(s.body));
1622
1255
  if (crumbs !== undefined)
@@ -1628,8 +1261,6 @@ export function createDecisionServer(options) {
1628
1261
  path.searchParams.delete('request');
1629
1262
  const currentPath = path.pathname + path.search;
1630
1263
  path.searchParams.set('format', 'workspace');
1631
- // The legacy list pane (every task or build as links) duplicates the
1632
- // Crew panel and Tasks page; inside the workspace the page stands alone.
1633
1264
  const pageHtml = htmlString(s.body);
1634
1265
  const extras = s.workspace ?? {};
1635
1266
  const notices = [...(extras.notices ?? [])];
@@ -1643,7 +1274,6 @@ export function createDecisionServer(options) {
1643
1274
  try {
1644
1275
  const project = s.chrome.active === 'chat' ? null : s.chrome.project;
1645
1276
  crew = extras.team?.tasks ? browserCrewFromIndex(extras.team.tasks, extras.team.selected?.id) : requestFacts.workCrew?.project === project ? browserCrewFromIndex(requestFacts.workCrew.page)
1646
- // The reader's own lead's claims read "<name> is on it" here too.
1647
1277
  : (() => {
1648
1278
  const access = { principal: 'operator', repos: managedRepos(), includeUnplaced: false, viewer: requestFacts.actor ?? null };
1649
1279
  return chromeRead(`crew\u0000${accessKey(access)}\u0000${project ?? ''}`, () => browserCrewOf(store, clock(), access, { evidenceRoot, project }));
@@ -1652,7 +1282,6 @@ export function createDecisionServer(options) {
1652
1282
  catch {
1653
1283
  notices.push('Crew updates are unavailable. Open Tasks to inspect saved work.');
1654
1284
  }
1655
- // A running row says what its agent did last, and when (the task page's own line).
1656
1285
  try {
1657
1286
  const now = clock(), live = new Map();
1658
1287
  if (crew.crew.length > 0)
@@ -1664,14 +1293,9 @@ export function createDecisionServer(options) {
1664
1293
  if (live.size > 0)
1665
1294
  crew = { ...crew, crew: crew.crew.map(item => { const activity = live.get(item.id); return activity === undefined ? item : { ...item, activity }; }) };
1666
1295
  }
1667
- catch { /* the rows keep their status; the line returns on the next read */ }
1668
- // "Wake me only for these": the navigation carries the sidebar's own
1669
- // Tasks count (chromeFor) and links to the project view it covers, so
1670
- // it matches that page's Needs you tab on every screen.
1296
+ catch { }
1671
1297
  const needsYou = s.chrome.inboxCount;
1672
1298
  const tasksProject = s.chrome.inboxProject === undefined ? s.chrome.project : s.chrome.inboxProject;
1673
- // The person's own project and task conversations (v77), for the
1674
- // sidebar's chat list; a thread whose project is out of view is left out.
1675
1299
  let chats = [];
1676
1300
  try {
1677
1301
  const actor = requestFacts.actor ?? '';
@@ -1694,31 +1318,18 @@ export function createDecisionServer(options) {
1694
1318
  }
1695
1319
  const conversation = extras.conversation ?? null;
1696
1320
  const request = requestFacts.workspaceRequest;
1697
- // React owns the conversation and its refresh/draft lifecycle. Native
1698
- // guarded forms keep their current behavior after React inserts them.
1699
- // A page with its own view keeps its script; the chat page runs the result script.
1700
- // The exact page script the document would run: the JSON arm and the document arm read this one value.
1701
1321
  const ownScript = conversation === null || extras.view;
1702
1322
  const pageScript = ownScript ? (s.functional?.script ?? '') : RESULT_REVIEW_SCRIPT;
1703
1323
  const routeInPlace = inPlaceRoute(requestFacts.routeId, path);
1704
- // The app runs the page's behaviour itself (docs/plans/task-page-in-app.md §2) only when all of these hold: the
1705
- // app covers the WHOLE script, no password field (a password page keeps its string path), an in-place route, and a
1706
- // reader that can run it: a document load (its bundle is this server's, served no-store) or a workspace read that
1707
- // says so. Anything else is the page exactly as before: the string, no work, a document.
1708
1324
  const covered = ownScript ? s.functional?.app : undefined;
1709
1325
  const work = pageScript !== '' && covered !== undefined && covered.length > 0 && !sensitive && routeInPlace
1710
1326
  && (!requestFacts.workspaceRead || requestFacts.appWork === true) ? covered : null;
1711
1327
  const functional = work === null ? pageScript : '';
1712
- // May replace another page without a document load (live-pages-and-home.md A1.1): an allowlisted route, no password
1713
- // field, no page script (a page script runs once per document, so its page always loads as one).
1714
1328
  const inPlace = routeInPlace && !sensitive && functional === '';
1715
1329
  const workspace = {
1716
1330
  version: 1, path: currentPath, title: s.title, user: requestFacts.actor ?? '', csrf: requestFacts.csrf, sensitive, inPlace,
1717
1331
  ...(work === null ? {} : { work }),
1718
- // Said on the document that ships it: this document's page script listens for as long as the document lives.
1719
1332
  ...(functional !== '' && !requestFacts.workspaceRead ? { scripted: true } : {}),
1720
- // The project picker names the open project; the settings frame carries its breadcrumb.
1721
- // Only a project this person may see now: never the raw saved path (settings-kit.ts openProjectFor).
1722
1333
  openProject: openProjectFor(requestFacts.openProject ?? null, s.chrome.project, s.chrome.projects ?? []),
1723
1334
  ...(s.chrome.crumbs === undefined ? {} : { crumbs: s.chrome.crumbs }),
1724
1335
  ...(requestFacts.passwordless === true ? { passwordless: true } : {}),
@@ -1727,7 +1338,6 @@ export function createDecisionServer(options) {
1727
1338
  receipt: conversation !== null && request && REQUEST_TOKEN.test(request)
1728
1339
  ? { request, received: store.leadRequestReceived(conversation.sessionId, request) } : null,
1729
1340
  projects: browserProjectsOf(s.chrome.projects ?? []), ...crew,
1730
- // The sidebar's project states: never on a sensitive page (no rail, no summary stream there).
1731
1341
  ...(() => { if (sensitive)
1732
1342
  return {}; try {
1733
1343
  return { projectStates: projectSummary() };
@@ -1735,7 +1345,6 @@ export function createDecisionServer(options) {
1735
1345
  catch {
1736
1346
  return {};
1737
1347
  } })(),
1738
- // Cockpit B2: the remembered password's chip, only where it could be used (a direct local request).
1739
1348
  ...(() => {
1740
1349
  const facts = freshFacts.getStore();
1741
1350
  if (sensitive || facts == null || !facts.local || !facts.live())
@@ -1746,10 +1355,9 @@ export function createDecisionServer(options) {
1746
1355
  const left = FRESH_WINDOW_MS - (Date.now() - at);
1747
1356
  return left <= 0 ? {} : { fresh: { minutes: Math.max(1, Math.ceil(left / 60_000)), forget: '/session/forget-password' } };
1748
1357
  })(),
1749
- // The usage chip: the Limits view's own audience (an operator on a browser session), never a sensitive page.
1750
1358
  ...(() => {
1751
1359
  const actor = requestFacts.actor;
1752
- if (sensitive || !actor || requestFacts.csrf === '' || !store.isInstanceOperator(actor))
1360
+ if (sensitive || !actor || requestFacts.csrf === '' || requestFacts.advanced === false || !store.isInstanceOperator(actor))
1753
1361
  return {};
1754
1362
  try {
1755
1363
  const usage = usageChipOf(store.providerLimits(), clock());
@@ -1763,15 +1371,12 @@ export function createDecisionServer(options) {
1763
1371
  catchUpHtml: extras.catchUpHtml === undefined ? '' : htmlString(extras.catchUpHtml), controlsHtml: extras.controlsHtml === undefined ? '' : htmlString(extras.controlsHtml), notices, view: extras.view ?? null,
1764
1372
  ...(s.chrome.demo ? { demo: { text: DEMO_BANNER, short: DEMO_BANNER_SHORT } } : {}),
1765
1373
  pageHtml: extras.pageHtml === undefined ? (conversation === null ? pageHtml : null) : extras.pageHtml === null ? null : htmlString(extras.pageHtml),
1766
- navigation: browserNavigationOf(currentPath, s.chrome.project, needsYou, tasksProject, s.chrome.inboxLabel),
1767
- // The one Needs-you count (tasks only), with the scope it covers: the Tasks list's own count for this project
1768
- // view (or every project), so the rail, the phone header and Home all read the same number.
1374
+ navigation: browserNavigationOf(currentPath, s.chrome.project, needsYou, tasksProject, s.chrome.inboxLabel, requestFacts.advanced !== false),
1375
+ ...(requestFacts.advanced === false ? { advanced: false } : {}),
1769
1376
  needsYou: { count: needsYou, saturated: s.chrome.inboxSaturated === true, scope: tasksProject ?? null,
1770
1377
  label: s.chrome.inboxLabel ?? `${needsYou} ${needsYou === 1 ? 'needs' : 'need'} you`,
1771
- // Every project, said by name (all=1), so a session's own open project never narrows the list the count opens.
1772
1378
  href: tasksProject === null ? '/tasks?scope=all&view=needs-you' : `/tasks?project=${encodeURIComponent(tasksProject)}&view=needs-you` },
1773
1379
  chats,
1774
- // The same count per project (the rail's project rows), read from the same work index totals.
1775
1380
  ...(() => { if (sensitive)
1776
1381
  return {}; try {
1777
1382
  return { needsYouByProject: projectCounts(clock()).map(one => ({ path: one.repo, count: one.totals['needs-you'] })) };
@@ -1785,7 +1390,6 @@ export function createDecisionServer(options) {
1785
1390
  ...(extras.firstRun === undefined ? {} : { firstRun: extras.firstRun }),
1786
1391
  ...(extras.phone === undefined ? {} : { phone: extras.phone }),
1787
1392
  ...(extras.home == null ? {} : { home: extras.home }),
1788
- // Easy-start C2: this tab's key is from an earlier start (or it has none): one way to reconnect.
1789
1393
  ...(requestFacts.reconnect == null ? {} : { reconnect: requestFacts.reconnect }),
1790
1394
  };
1791
1395
  if (requestFacts.workspaceRead) {
@@ -1795,9 +1399,6 @@ export function createDecisionServer(options) {
1795
1399
  response.setHeader('ETag', validator.etag);
1796
1400
  }
1797
1401
  const body = JSON.stringify(workspace);
1798
- // Every other page's re-read after a live `change` (chat keeps its own validator, and its receipt, task and
1799
- // result reads none): when what it renders now is exactly what the page holds, it hears 304 and keeps its view
1800
- // (no transfer, no re-render).
1801
1402
  if (status === 200 && validator === undefined && path.pathname !== '/chat') {
1802
1403
  const etag = '"w' + createHash('sha256').update(body).digest('base64url') + '"';
1803
1404
  response.setHeader('ETag', etag);
@@ -1808,14 +1409,8 @@ export function createDecisionServer(options) {
1808
1409
  }
1809
1410
  const nonce = randomBytes(16).toString('base64');
1810
1411
  const document = shell(s.title, s.body, { chrome: s.chrome, sensitive });
1811
- // The keys and their list (keymap.ts) work here as on every chromed page; the list sits beside the app React owns.
1812
- // A sensitive page keeps to its own script.
1813
1412
  return page(response, status, browserWorkspaceDocument(document, workspace, nonce, functional + MOBILE_VIEWPORT_SCRIPT + keyFill + (sensitive ? '' : chromeScript()), sensitive ? html `` : KBD_HELP), nonce, true);
1814
1413
  }
1815
- // A one-time secret on screen (a token, an invite link, a pairing code): the
1816
- // page carries no script of any kind, so it leaves the workspace for a
1817
- // focused page in the same look: the brand, the one card, and the way back.
1818
- // Easy-start C2: but for the key fill when it has a form that posts (the fill reads nothing on the page).
1819
1414
  if (s.forceSensitive === true) {
1820
1415
  if (keyFill === "" || !/<form\b[^>]*method="post"/i.test(htmlString(s.body)))
1821
1416
  return page(response, status, focusDocument(s.title, s.body));
@@ -1824,10 +1419,7 @@ export function createDecisionServer(options) {
1824
1419
  }
1825
1420
  const chromeLayer = !sensitive && s.chrome !== undefined;
1826
1421
  const functional = s.functional?.script ?? "";
1827
- // Sensitive pages strip the palette and keys but keep the sidebar toggle.
1828
1422
  const sensitiveChrome = sensitive && s.chrome !== undefined ? sidebarScript() : "";
1829
- // Kit markup the workspace bundle would have wired (a composer, an overlay, a switch, an idea) gets the kit's own small
1830
- // behaviour here (kit-standalone.ts); never on a sensitive page, which carries no chrome additions.
1831
1423
  const kitBehavior = chromeLayer && KIT_BEHAVIOR_MARKUP.test(htmlString(s.body)) ? KIT_STANDALONE_SCRIPT : "";
1832
1424
  const script = functional + (chromeLayer ? chromeScript() + WORKSPACE_MOTION_SCRIPT + kitBehavior : sensitiveChrome) + keyFill;
1833
1425
  const nonce = script === "" ? undefined : randomBytes(16).toString("base64");
@@ -1841,23 +1433,14 @@ export function createDecisionServer(options) {
1841
1433
  ...(s.refreshSeconds === undefined ? {} : { refreshSeconds: s.refreshSeconds }),
1842
1434
  ...(nonce === undefined ? {} : { live: { nonce, script, fallbackRefresh: s.functional?.fetches === true } }),
1843
1435
  });
1844
- // Pages that ship the chrome layer keep connect-src (v28 granted it for
1845
- // the since-removed watched-session beat), beside pages whose own
1846
- // functional script polls.
1847
1436
  return page(response, status, document, nonce, s.functional?.fetches === true || chromeLayer || sensitiveChrome !== "");
1848
1437
  }
1849
- /** The needs-you count every surface wears, read from this request's own
1850
- * Work counts (one read per request, kept only while the workspace revision
1851
- * it was read at stands), so a live page's badge and its Needs you tab
1852
- * always agree. */
1853
1438
  function needsYouBadge(project) {
1854
1439
  return needsYouCount(project);
1855
1440
  }
1856
1441
  const bustBadge = () => {
1857
1442
  paletteCache.clear();
1858
1443
  };
1859
- /** Enrolled projects first (most recently opened), then the repos this server was told to serve that nobody has
1860
- * opened yet — the switcher lists every project it is allowed to show, each exactly once. */
1861
1444
  function sidebarProjects() {
1862
1445
  const seen = new Set();
1863
1446
  const rows = [];
@@ -1872,33 +1455,21 @@ export function createDecisionServer(options) {
1872
1455
  }
1873
1456
  return rows;
1874
1457
  }
1875
- /** The sidebar's projects with their states (agent-state.ts), for the request's own reader: the page's first read
1876
- * and the summary room's snapshots are this one function, so the two never disagree. Never marks anything seen.
1877
- * Work with no project yet is its own entry when this reader may see it and something counts there. */
1878
1458
  function projectSummary() {
1879
1459
  const projects = sidebarProjects();
1880
1460
  const actor = requestContext.getStore()?.actor ?? '';
1881
1461
  const access = workAccess();
1882
1462
  return chromeRead(summaryKey(actor, access, projects), () => projectSummaryOf(store, clock(), access, actor, projects, evidenceRoot));
1883
1463
  }
1884
- /** What one account may see now, as the summary room keys it: a narrowed ceiling or grant is a different key, so a
1885
- * snapshot read for the wider scope never reaches it. Null: no such account. */
1886
1464
  const projectScopeFor = (account) => store.accountOf(account) === null ? null : requestContext.run({ csrf: '', returnTo: '/', actor: account }, () => {
1887
- // Canonical: what may be seen, never the order it was last opened in.
1888
1465
  const access = workAccess();
1889
1466
  return JSON.stringify({ projects: sidebarProjects().map(one => one.path).sort(), access: { ...access, repos: access.repos === null ? null : [...access.repos].sort() } });
1890
1467
  });
1891
- /** One account's summary snapshot, read as that account for this exact scope (the summary room's fingerprint): null
1892
- * when the account is gone or its scope moved. */
1893
1468
  const projectSummaryFor = (account, scope) => projectScopeFor(account) !== scope ? null : requestContext.run({ csrf: '', returnTo: '/', actor: account }, () => JSON.stringify(projectSummary()));
1894
- /** The sidebar's facts for this request. */
1895
1469
  function chromeFor(project, active, listPane, scope) {
1896
1470
  if (restricted() && !visible(project))
1897
1471
  project = null;
1898
1472
  const actor = requestContext.getStore()?.actor;
1899
- // One Tasks count per request: Needs you in the request's project view
1900
- // (the open project, else every admitted project), never the page's own
1901
- // project — a flow or task in another project shows the same number.
1902
1473
  const lens = requestContext.getStore()?.lens;
1903
1474
  const inboxProject = lens !== undefined && (!restricted() || visible(lens)) ? lens : project;
1904
1475
  const badge = needsYouBadge(inboxProject);
@@ -1910,7 +1481,6 @@ export function createDecisionServer(options) {
1910
1481
  projectPeek = projectFamilyPeek(project, clock());
1911
1482
  }
1912
1483
  catch {
1913
- // Chrome is orientation, never a reason to fail the actual screen.
1914
1484
  projectPeek = undefined;
1915
1485
  }
1916
1486
  }
@@ -1921,9 +1491,6 @@ export function createDecisionServer(options) {
1921
1491
  project,
1922
1492
  projectScoped: restricted(),
1923
1493
  ...(projectPeek === undefined ? {} : { projectPeek }),
1924
- // Enrolled projects first (most recently opened), then the repos this
1925
- // server was told to serve that nobody has opened yet — the switcher
1926
- // lists every project it is allowed to show, each exactly once.
1927
1494
  projects: sidebarProjects(),
1928
1495
  ...(facts === undefined ? {} : { csrf: facts.csrf, returnTo: facts.returnTo }),
1929
1496
  inboxCount: badge.count,
@@ -1935,7 +1502,6 @@ export function createDecisionServer(options) {
1935
1502
  ...(store.isDemo() ? { demo: true } : {}),
1936
1503
  ...(() => { const signIn = signInNotices(store); return signIn.length === 0 ? {} : { signIn }; })(),
1937
1504
  ...(() => {
1938
- // Operators only (only someone at this computer can update it), and gone once this version is dismissed.
1939
1505
  if (!facts?.csrf || !actor || !store.isInstanceOperator(actor))
1940
1506
  return {};
1941
1507
  const update = updateFacts();
@@ -1945,7 +1511,6 @@ export function createDecisionServer(options) {
1945
1511
  })(),
1946
1512
  ...(() => {
1947
1513
  const databaseFile = store.databaseFile();
1948
- // Settings → Updates says a `toolroll update` in full; every other page (and the app's update everywhere) names it once.
1949
1514
  if (!actor || databaseFile === null || !store.isInstanceOperator(actor))
1950
1515
  return {};
1951
1516
  const waiting = waitingUpdate(databaseFile, run => store.stopQuiescenceProblem(run) !== null, clock());
@@ -1960,15 +1525,11 @@ export function createDecisionServer(options) {
1960
1525
  },
1961
1526
  }),
1962
1527
  ...(!restricted() && !unscopedMode && managedRepos().length > 0 ? { chat: true } : {}),
1963
- // Live terminals: offered to an installation-wide operator (the routes prove it again).
1964
1528
  ...(actor !== undefined && !store.isDemo() && store.isInstanceOperator(actor) ? { code: true } : {}),
1965
1529
  ...(listPane === undefined ? {} : { listPane }),
1966
1530
  ...(scope === undefined ? {} : { scope }),
1967
1531
  };
1968
1532
  }
1969
- // All project counts are read together, at most once per workspace revision
1970
- // for this reader's access. No task artifacts or processes are inspected to
1971
- // paint a badge or a project switcher.
1972
1533
  function projectCounts(now) {
1973
1534
  const facts = requestContext.getStore();
1974
1535
  if (facts?.workCounts !== undefined)
@@ -1984,16 +1545,11 @@ export function createDecisionServer(options) {
1984
1545
  .reduce((sum, one) => sum + one.totals['needs-you'], 0);
1985
1546
  return { count, saturated: false };
1986
1547
  }
1987
- /** One work index page for an already-admitted reader, through the chrome cache: a whole view the chat landing reads
1988
- * on every refresh. */
1989
1548
  function sharedIndexPage(access, options) {
1990
- // Receipt reconciliation, task and result reads always read work afresh (disk state included).
1991
1549
  if (requestContext.getStore()?.freshWork === true)
1992
1550
  return workIndexPage(store, clock(), access, options);
1993
1551
  return chromeRead(indexKey(access, options), () => workIndexPage(store, clock(), access, options));
1994
1552
  }
1995
- /** A chrome read for this request: what it already read (its prefetch included) stands for the whole request, else
1996
- * the revision cache's value, else `compute()` now. */
1997
1553
  function chromeRead(key, compute) {
1998
1554
  const facts = requestContext.getStore();
1999
1555
  const held = facts?.chromeReads?.get(key);
@@ -2004,23 +1560,16 @@ export function createDecisionServer(options) {
2004
1560
  (facts.chromeReads ??= new Map()).set(key, value);
2005
1561
  return value;
2006
1562
  }
2007
- /** The chat landing's three whole views (chat.ts chatHomeOf), as it asks for them. */
2008
1563
  const chatHomeViews = () => ["all", "needs-you", "completed"]
2009
1564
  .map(view => ({ view, limit: WORK_INDEX_MAX_LIMIT, ...(evidenceRoot === undefined ? {} : { root: evidenceRoot }) }));
2010
- /** Pages that wear the chrome (the sidebar's states and the Tasks count). */
2011
1565
  const CHROME_PAGES = new Set(["home", "work", "board", "agents", "agents.live", "task.page", "run.page", "chat.page", "review", "tasks", "inbox",
2012
1566
  "next", "done", "projects.page", "flows.page", "flow.page", "settings.page", "decision.page", "menu"]);
2013
- /** Before a chromed page renders: its chrome reads (and the chat landing's views) run on a read worker, so the
2014
- * request thread finds them cached instead of computing them. The reader is the one this request admitted; the keys
2015
- * carry its exact access (console-chrome.ts). Without a worker, or when one fails, the page computes them as before. */
2016
1567
  async function prefetchChrome(route, url, who) {
2017
1568
  if (reads === null || who.via !== "cookie" || !CHROME_PAGES.has(route.id))
2018
1569
  return;
2019
1570
  try {
2020
1571
  const actor = requestContext.getStore()?.actor ?? "";
2021
1572
  const access = workAccess(), projects = sidebarProjects(), now = clock();
2022
- // Populate only the revision cache. Each answer must still pass its revision/expiry check when rendering:
2023
- // another job can remain pending while an earlier answer's approval or Needs-you state changes.
2024
1573
  const fill = async (key, read) => { await chromeReads.fill(key, read); };
2025
1574
  const jobs = [
2026
1575
  fill(countsKey(access), () => reads.workCounts(now, access)),
@@ -2030,7 +1579,6 @@ export function createDecisionServer(options) {
2030
1579
  if (!["project", "room", "team"].some(name => url.searchParams.has(name)) && requestContext.getStore()?.freshWork !== true)
2031
1580
  for (const options of chatHomeViews())
2032
1581
  jobs.push(fill(indexKey(access, options), () => reads.workIndexPage(now, access, options)));
2033
- // The conversation's briefing (chat.ts: the fleet snapshot's states), read as chat reads it.
2034
1582
  const repos = managedRepos();
2035
1583
  if (repos.length > 0 && requestContext.getStore()?.freshWork !== true) {
2036
1584
  const fleet = { principal: "operator", repos, includeUnplaced: false, viewer: who.name };
@@ -2040,26 +1588,15 @@ export function createDecisionServer(options) {
2040
1588
  }
2041
1589
  await Promise.all(jobs);
2042
1590
  }
2043
- catch { /* the page computes what is missing */ }
1591
+ catch { }
2044
1592
  }
2045
- /** A live page's own beat without a docked chat: 10 s while any admitted task is building, else 30 s. */
2046
1593
  function liveRefreshSeconds() {
2047
1594
  return projectCounts(clock()).some(one => one.totals.running > 0) ? 10 : 30;
2048
1595
  }
2049
- /** This exact run's review facts for the shared projection (review
2050
- * fixes, finding 4): the store's bounded retry projection plus the live
2051
- * reviewer's own liveness — read per run, so an older selected result
2052
- * never wears a newer run's review. */
2053
1596
  const reviewFactsFor = (runId) => reviewFactsOf(store.reviewRetryStateOf(runId), runner => {
2054
1597
  const one = store.getRunner(runner)?.runner;
2055
1598
  return one !== undefined && runnerAlive(one, clock());
2056
1599
  }, buildReviewOf(store, runId)?.state === "pending");
2057
- // ---- the live peek (A2; three review rounds' findings are the spec) ----
2058
- //
2059
- // Names and counts only, never content; nothing durable, ever. The cache
2060
- // holds finished ESCAPED fragments keyed by run:base:epoch — the epoch
2061
- // rotates with every lease AND release, so a stale entry's key can never
2062
- // be asked for again; hits still re-prove the whole guard list.
2063
1600
  const peekCache = new Map();
2064
1601
  let peekCacheBytes = 0;
2065
1602
  const peekInFlight = new Map();
@@ -2078,39 +1615,24 @@ export function createDecisionServer(options) {
2078
1615
  peekCacheBytes -= entry.bytes;
2079
1616
  }
2080
1617
  };
2081
- /** One typed sentence inside the region — plain words, no raw errors.
2082
- * `final` marks conditions that cannot heal for this run (finished,
2083
- * superseded, wrong machine): the region poller reads the marker and
2084
- * stops, instead of refetching a dead build every beat forever. */
2085
1618
  const peekSay = (message, final = false) => html `<p class="meta"${final ? html ` data-region-stop` : ""}>${message}</p>`;
2086
- /** The sanitize pipeline (finding 30/35): normalize → mask → escape. */
2087
1619
  const peekName = (path) => {
2088
1620
  const normalized = path.replace(/[\u0000-\u001f\u007f]/g, "");
2089
1621
  const masked = scanForSecrets(normalized).length > 0 ? "[redacted: a credential-shaped name]" : normalized;
2090
1622
  return textHtml(masked);
2091
1623
  };
2092
1624
  async function handlePost(route, url, who, request, response, posted) {
2093
- // Every POST passes the shared mutation guard. Caller, scope, project (including a limited account's posted repo)
2094
- // and role were admitted by the route table.
2095
1625
  const denied = authorizeMutation(request, who, readForm(posted, CONSOLE_FORMS.mutationGuard));
2096
1626
  if (denied !== null)
2097
1627
  return refuse(response, who, denied.status, denied.message, "/", denied.reconnect?.kind === "password" ? { label: "Reconnect", href: denied.reconnect.href } : undefined);
2098
- // Standing can change after a token was minted: a viewer's act stays refused, cookie and bearer alike, except
2099
- // the row's session-local acts.
2100
1628
  if (who.role === "viewer" && !route.viewer)
2101
1629
  return refuse(response, who, 403, "your login can watch, not act — ask an approver to upgrade you");
2102
1630
  const now = clock();
2103
- // Any accepted mutation may change what the inbox owes; the badge
2104
- // re-counts within five seconds either way, this just makes it exact.
2105
1631
  bustBadge();
2106
1632
  return dispatchConsole(route, { url, who, request, response, route, now, project: projectOf(who, request) ?? null, chosenProject: projectOf(who, request) ?? null, posted });
2107
1633
  }
2108
- // Only explicitly authorized conversations receive automatic turns. The
2109
- // deterministic scan is idle without new meaningful work; shutdown drains it.
2110
1634
  let leadMaintenance = null;
2111
1635
  let leadClosing = false;
2112
- // Started in the console's folder scope (folder-gate.ts), so their own timers and the personal queue's kick (which
2113
- // restores the context it was started in, never a request's) read folders as the console's work does.
2114
1636
  server.once('listening', () => consoleFolders(options, identities, () => {
2115
1637
  team.start();
2116
1638
  personalQueue.start();
@@ -2118,23 +1640,17 @@ export function createDecisionServer(options) {
2118
1640
  run: () => runLeadFollowPass({ store, repos: managedRepos, evidenceRoot, clock,
2119
1641
  provider: () => { const enabled = chatEnablement(); return enabled.ok ? { config: enabled.config, key: enabled.key } : null; },
2120
1642
  fetcher: chatFetcher, ...(options.subscriptionChatRunner ? { subscriptionRunner: options.subscriptionChatRunner } : {}) }),
2121
- // Pending delivery is durable and is read again on the next pass; a failure is said where follow status is read.
2122
1643
  onError: error => recordLeadFollowFailure(store, error, clock()),
2123
1644
  });
2124
1645
  }));
2125
- // Background checks (docs/plans/get-side-effects.md): what pages show about this computer's agent sign-ins and the
2126
- // services Toolroll uses is asked here, on a timer, and a page reads the last answer. A page visit never starts a
2127
- // process or a network call, and never acts on what a check finds: lifting a sign-in pause and the lead-by-default
2128
- // rule run from this pass (or a person's Check now), not from a GET.
2129
1646
  let backgroundChecks = null;
2130
1647
  let agentsCheckedAt = 0;
2131
1648
  if (options.backgroundChecks === true)
2132
1649
  server.once('listening', () => {
2133
- // This Toolroll's folder for secrets, checked once now, so a page can read which are set without preparing it.
2134
1650
  try {
2135
1651
  secretFolder();
2136
1652
  }
2137
- catch { /* a page says secrets can't be read; the next action reports why */ }
1653
+ catch { }
2138
1654
  backgroundChecks = startMaintenance({ intervalMs: options.backgroundChecksMs ?? BACKGROUND_CHECKS_MS, shouldStop: () => leadClosing,
2139
1655
  run: () => consoleFolders(options, identities, async () => {
2140
1656
  const now = Date.now();
@@ -2142,11 +1658,9 @@ export function createDecisionServer(options) {
2142
1658
  if (now - agentsCheckedAt >= (options.backgroundChecksMs ?? LOCAL_AGENTS_EVERY_MS)) {
2143
1659
  agentsCheckedAt = now;
2144
1660
  waits.push(checkLocalAgents());
2145
- // The other agents Settings lists: their last answer is what the page shows.
2146
1661
  for (const provider of PROVIDER_IDS.filter(isKeyedProvider).filter(one => one !== "claude" && one !== "codex"))
2147
1662
  waits.push(connectionCheck(provider).catch(() => undefined));
2148
1663
  }
2149
- // Project identities, resolved off the thread: what pages asked about, and answers gone stale.
2150
1664
  waits.push(identities.refresh([...configuredPaths, ...exactRepos(), ...(options.currentRepos?.() ?? []), ...store.listProjects().map(one => one.path), ...store.knownRepos()]));
2151
1665
  integrations.refreshIfDue();
2152
1666
  const sso = ssoSettings();
@@ -2155,28 +1669,22 @@ export function createDecisionServer(options) {
2155
1669
  if (chatKeyFor("openrouter-api") !== null)
2156
1670
  waits.push(chatCatalog());
2157
1671
  const openrouter = readProviderKey("openrouter", providerHome);
2158
- // The cache answers until its list is due again (ten minutes, or 30 s after a failure), then fetches.
2159
1672
  if (openrouter !== null)
2160
1673
  waits.push(modelCatalog(openrouter));
2161
- // What used to be closed by whichever page read it first: an operating mode or a flow's "runs on its own"
2162
- // grant past its expiry, a stalled update, old coordinator proposals. (Lead turns past their deadline are the
2163
- // follow pass's, which settles them even while an update drains.)
2164
1674
  const at = clock();
2165
1675
  store.closeExpiredModes(at);
2166
1676
  closeExpiredUnattendedGrants(store, at);
2167
1677
  store.sweepCoordinatorProposals(at);
2168
- // The demo's scripted story, if a beat timer missed (its pages only read it).
2169
1678
  try {
2170
1679
  options.demoLead?.advance(at);
2171
1680
  }
2172
- catch { /* the next pass tries again */ }
1681
+ catch { }
2173
1682
  const databaseFile = store.databaseFile();
2174
1683
  if (databaseFile !== null && !updateChecksOff(process.env, options.configDir ?? dirname(databaseFile)).off) {
2175
1684
  const last = lastChecks.known("release");
2176
1685
  if (lastChecks.due("release", last !== null && "problem" in last.value ? 60_000 : 15 * 60_000))
2177
1686
  waits.push(checkRelease());
2178
1687
  }
2179
- // Chat's first tasks (issues and TODOs) while the first run is open and nothing is filed yet.
2180
1688
  if (firstRunStepsNow(clock()) !== null && !store.hasAnyWork()) {
2181
1689
  for (const repo of managedRepos()) {
2182
1690
  const entry = firstTasks.get(repo);
@@ -2184,18 +1692,11 @@ export function createDecisionServer(options) {
2184
1692
  continue;
2185
1693
  const reading = { until: Date.now() + 10 * 60_000, found: entry?.found ?? null, reading: true };
2186
1694
  firstTasks.set(repo, reading);
2187
- // A test's runner reads in-process; otherwise in a process of its own (learning-look.ts), so the hardened
2188
- // git's synchronous reads of the project's folder never hold the console's thread.
2189
1695
  waits.push((options.firstTaskRunner !== undefined ? findFirstTasks(repo, options.firstTaskRunner) : firstTasksOffThread(repo)).then(found => { reading.found = found; }, () => { }).finally(() => { reading.reading = false; }));
2190
1696
  }
2191
1697
  }
2192
- // Learning recovered from reviewed runs (and a project's saved rows carried to its current identity), which
2193
- // Settings → Learning and Knowledge used to do as they opened.
2194
1698
  if (lastChecks.due("learning", 10 * 60_000)) {
2195
1699
  waits.push(lastChecks.run("learning", async () => {
2196
- // Its reads of each project's Git folder are synchronous, so with a database file they run in a process of
2197
- // their own (learning-look.ts): a folder that doesn't answer costs its own recovery, never the console. An
2198
- // in-memory database (a test) can't be shared, so it is read here.
2199
1700
  if (databaseFile !== null) {
2200
1701
  await recoverLearningOffThread({ databaseFile, evidenceRoot, repos: managedRepos() }, options.learningRunner === undefined ? {} : { runner: options.learningRunner });
2201
1702
  return;
@@ -2204,17 +1705,15 @@ export function createDecisionServer(options) {
2204
1705
  try {
2205
1706
  acceptedIdentities(store, repo);
2206
1707
  }
2207
- catch { /* the next pass tries again */ }
1708
+ catch { }
2208
1709
  try {
2209
1710
  recoverLearning(store, evidenceRoot, repo);
2210
1711
  }
2211
- catch { /* the next pass tries again */ }
1712
+ catch { }
2212
1713
  }
2213
1714
  }));
2214
1715
  }
2215
- // What Codex has configured, per project, for Settings → Tools to offer.
2216
1716
  for (const repo of managedRepos()) {
2217
- // The project's own .mcp.json, read off the console's thread (folder-look.ts) for the Tools page and the lead.
2218
1717
  if (options.identities !== undefined && lastChecks.due(`project-mcp:${repo}`, 10 * 60_000)) {
2219
1718
  waits.push(lastChecks.run(`project-mcp:${repo}`, async () => { const looked = await lookProjectMcp(repo); if (looked.ok)
2220
1719
  savedProjectMcp.set(repo, looked.value); return looked.ok; }));
@@ -2225,25 +1724,17 @@ export function createDecisionServer(options) {
2225
1724
  if (databaseFile !== null && lastChecks.due("storage", 30 * 60_000)) {
2226
1725
  waits.push(lastChecks.run("storage", () => checkoutPlan(store, storagePool(databaseFile), clock(), { manual: true })));
2227
1726
  }
2228
- // The same reading the chrome does, outside a page visit, so it releases a stalled `toolroll update` and a stalled
2229
- // desktop update in every folder the chrome looks in.
2230
1727
  if (databaseFile !== null) {
2231
1728
  try {
2232
1729
  waitingUpdate(databaseFile, run => store.stopQuiescenceProblem(run) !== null, at);
2233
1730
  }
2234
- catch { /* shown as last saved */ }
1731
+ catch { }
2235
1732
  }
2236
1733
  await Promise.all(waits);
2237
1734
  }),
2238
1735
  onError: () => { }, });
2239
1736
  void backgroundChecks.runNow();
2240
1737
  });
2241
- // Keep native process custody until shutdown has verified agent/tool exit.
2242
- // Coding custody does not depend on subagents or the lead's follow pass, so
2243
- // it closes at once and never waits behind a model turn: a stop must release
2244
- // the owner record well inside the service's exit window (Oct 2: deploys
2245
- // over 0.9.11 found it still held by a killed process).
2246
- /** Set once the terminal handlers exist (below): drops every socket and ends every program. */
2247
1738
  const terminalClosing = {};
2248
1739
  let codingClosing = null;
2249
1740
  const closeCoding = () => {
@@ -2260,14 +1751,13 @@ export function createDecisionServer(options) {
2260
1751
  try {
2261
1752
  requestBudget.flush();
2262
1753
  }
2263
- catch { /* saved again on the close event when it can be */ }
1754
+ catch { }
2264
1755
  flowRooms.close();
2265
1756
  taskRooms.close();
2266
1757
  liveHandlers.close();
2267
1758
  detachReads();
2268
1759
  liveFollower.close();
2269
1760
  void Promise.all([closeCoding(), terminalClosing.close?.().then(problem => { terminalClosing.problem = problem; }), bounded(team.close()), bounded(personalQueue.close()), bounded(leadMaintenance?.stop()), bounded(backgroundChecks?.stop()), bounded(reads?.close())])
2270
- // The server always closes; a terminal whose processes couldn't be proved stopped is the close's error.
2271
1761
  .then(() => closeServer(error => callback?.(error ?? terminalClosing.problem ?? undefined))).catch(error => {
2272
1762
  if (callback)
2273
1763
  callback(error instanceof Error ? error : Error('Coding session shutdown failed.'));
@@ -2465,7 +1955,6 @@ export function createDecisionServer(options) {
2465
1955
  };
2466
1956
  const liveHandlers = createLiveHandlers(handlerRuntime, { bus: liveBus, workspaceRevision, chatProjectOf: chatHandlers.chatProjectOf, projectSummaryFor, projectScopeFor });
2467
1957
  liveTurnStarted = liveHandlers.turnStarted;
2468
- // The one upgrade this server takes is a terminal's socket (terminals.ts listens); anything else is dropped.
2469
1958
  const terminalHandlers = createTerminalHandlers(handlerRuntime, { ...terminals, bus: liveBus, allowedHost, publicOrigin, forwardedSourceOf, server });
2470
1959
  terminalClosing.close = terminalHandlers.close;
2471
1960
  const remoteHandlers = createRemoteHandlers(remoteRuntime);
@@ -2475,7 +1964,6 @@ export function createDecisionServer(options) {
2475
1964
  ...remoteHandlers.registrations, ...liveHandlers.registrations, ...terminalHandlers.registrations, ...createSweepHandlers(handlerRuntime).registrations,
2476
1965
  ...createWelcomeHandlers(handlerRuntime).registrations,
2477
1966
  ]);
2478
- /** The row's role, after admission and before its one handler. */
2479
1967
  function dispatchConsole(route, ctx) {
2480
1968
  const { who, response } = ctx;
2481
1969
  const held = route.role === "any" || ((!route.roleBrowser || who.via === "cookie") &&
@@ -2498,8 +1986,6 @@ export function createDecisionServer(options) {
2498
1986
  }
2499
1987
  return withEdgePolicy(route, () => registry.edge(route, { ...ctx, route }));
2500
1988
  }
2501
- /** Easy-start C1: the local owner a browser session acts as on an allowed row, bound to its session's saved row and
2502
- * the generations it was made under; null when it no longer stands (refused like any other row). */
2503
1989
  function localPrincipalOf(who, route) {
2504
1990
  const sessionHash = sessions.hashOf(who.session);
2505
1991
  if (route.localAct === null || who.session.localGeneration === null || sessionHash === null)
@@ -2508,17 +1994,13 @@ export function createDecisionServer(options) {
2508
1994
  transport: "browser", act: route.localAct, sessionHash, request: { ended: false } };
2509
1995
  return localOwnerStandsNow(store, principal) ? principal : null;
2510
1996
  }
2511
- /** What a local owner hears on a row not marked for it: set a first password, or sign in with the one set. */
2512
1997
  function refuseLocalOwner(response, who, method, url, accept) {
2513
- // The page it was refused on, built here from the request (never from a header): a form's nearest page above it.
2514
1998
  const words = localOwnerRefusal(store.accountOf(who.name)?.passwordSet === true, refusalNext(method, url));
2515
- // Which refusal this was, for the shell (it offers the same way on) and the route inventory's rule table.
2516
1999
  response.setHeader("x-toolroll-refused", "local-owner");
2517
2000
  if (String(accept ?? "").includes("application/json"))
2518
2001
  return respond(response, 403, "application/json", JSON.stringify({ ok: false, said: words.message, href: words.href }));
2519
2002
  return refuse(response, who, 403, words.message, words.href, { label: words.action, href: words.href });
2520
2003
  }
2521
- // Defined last, so the reviewed functions above keep their places (password-freshness.test.ts).
2522
2004
  function holdSignInLink(link) {
2523
2005
  for (const [key, one] of signInLinks)
2524
2006
  if (one.expires < Date.now())
@@ -2529,8 +2011,6 @@ export function createDecisionServer(options) {
2529
2011
  signInLinks.set(linkKey(code), link);
2530
2012
  return `${SIGN_IN_LINK_PATH}${code}`;
2531
2013
  }
2532
- /** Easy-start C4: a local owner's one-time link. It names no account: local mode's own owner, read now, while local
2533
- * mode is on and the owner is active. Redemption reads local mode again and issues only a local-owner session. */
2534
2014
  function mintLocalLink() {
2535
2015
  const binding = localOwnerBinding(store);
2536
2016
  if (binding === null)
@@ -2547,12 +2027,6 @@ export { ssoStepUps, wrongHostPage } from "./server/render-people.js";
2547
2027
  export { diffFileAnchor, editorFileHref, needActionOf, orderChangedFiles, plainConclusionOf, rankReviewQueue, reviewFilePriority, reviewPriorityOf, runFactsFragment, withinSignedTouches } from "./server/render-results.js";
2548
2028
  export { decisionAnswerScript, earlierVersionsWords, revisionLineageWords } from "./server/render-tasks.js";
2549
2029
  export { SIGN_IN_LINK_MS, SIGN_IN_LINK_PATH } from "./server/session.js";
2550
- /**
2551
- * The console's configured repos and roots. Without identities (embedders and tests) they resolve once, synchronously,
2552
- * as before. With them, the console resolves them in the background after it listens (operate.ts startConsole), so
2553
- * each is read from the last answer: a configured path counts by its real path from the moment its folder answers,
2554
- * and until then only by its spelling, which the strict `canon` never matches for an unresolved row.
2555
- */
2556
2030
  function startupCeiling(repos, roots, identities, canon) {
2557
2031
  const configured = repos.length > 0 || roots.length > 0;
2558
2032
  const configuredPaths = [...repos, ...roots];
@@ -2566,8 +2040,6 @@ function startupCeiling(repos, roots, identities, canon) {
2566
2040
  configuredPaths,
2567
2041
  };
2568
2042
  }
2569
- // Only resolved entries authorize: an unresolved configured path is in no list, so it matches nothing (not even its
2570
- // own spelling) and is no session's default until its folder answers.
2571
2043
  const resolved = (paths) => [...new Set(paths.flatMap(path => { const real = identities.known(path); return typeof real === "string" ? [real] : []; }))];
2572
2044
  const ceiling = {
2573
2045
  get repos() { return resolved(repos); },
@@ -2582,14 +2054,7 @@ function startupCeiling(repos, roots, identities, canon) {
2582
2054
  configuredPaths,
2583
2055
  };
2584
2056
  }
2585
- /** Each console's folder gate (folder-gate.ts), made once for its options. */
2586
2057
  const consoleGates = new WeakMap();
2587
- /**
2588
- * Runs the console's own work (a request, a background pass) in its folder scope: with identities resolved off its
2589
- * thread (up and serve), it reads a person's folder synchronously only while that folder answered a look lately; its
2590
- * own data (the database's folder, evidence, build checkouts) is read freely. Without identities (embedders, tests):
2591
- * as before. Work that isn't the console's (a worker in the same process) never runs in it.
2592
- */
2593
2058
  function consoleFolders(options, identities, work) {
2594
2059
  if (options.identities === undefined)
2595
2060
  return work();