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/telegram.js CHANGED
@@ -1,23 +1,3 @@
1
- /**
2
- * The Telegram bridge: decisions out, answers back, zero tokens spent.
3
- *
4
- * This is channel plumbing — no LLM is anywhere in this path, and everything
5
- * it renders is deterministic. The security model, in one breath: a chat is
6
- * not a person, so pairing is a local authenticated act that binds one
7
- * private chat AND one immutable user id to one approver generation; a
8
- * button is not a command, so callback_data carries only an opaque one-time
9
- * token whose meaning lives in this database where a stolen bot token
10
- * cannot read it; and an answer lands in the same transaction that proves
11
- * the binding is still live and consumes the token — or it does not land.
12
- *
13
- * What a stolen bot token CAN do is stated rather than wished away: read
14
- * the decision text this installation chose to send through Telegram,
15
- * repaint the bot's keyboards with deceptive labels, and race our poll for
16
- * updates. It cannot mint an action token, answer as the operator, or make
17
- * `answered_by` say anything the pairing did not authorize. Rotating the
18
- * BotFather token plus `bridge telegram unpair` is the recovery, and both
19
- * are one command.
20
- */
21
1
  import { recordTypedStart, typedStartCard, typedYes } from "./typed-start.js";
22
2
  import { telegramCardMessage } from "./card-render.js";
23
3
  import { flowDoneCard } from "./flow-result-card.js";
@@ -50,28 +30,17 @@ import { envValue } from "./names.js";
50
30
  import { applyProposalTap, processTelegramConversations, phoneLinkButton, replyContextFor, telegramConversationRepos, telegramRequestId, tooLongText, whichTaskText, } from "./telegram-lead.js";
51
31
  import { telegramAck } from "./telegram-live.js";
52
32
  import { askOf, parseTelegramUpdate, pickOf, readTelegramButtonData, readTelegramUpdate, telegramButton } from "./contracts/telegram-callback.js";
53
- /** Read the enrolled project list on demand. No callback means no task data,
54
- * never an implicit all-database ceiling. Shared by pass and embedded follower. */
55
- /** A delivery its person began watching after it was claimed: held or settled at the final fence (cockpit §3). */
56
33
  const WATCHED_SINCE_CLAIM = "Held: its person is watching this agent now";
57
- /** The environment name — and therefore the name the builder strips from agents (both names; see names.ts). */
58
34
  export { TELEGRAM_TOKEN_ENV as TOKEN_ENV, TELEGRAM_TOKEN_ENVS as TOKEN_ENVS } from "./names.js";
59
- /** BotFather's shape: numeric bot id, colon, secret. */
60
35
  const TOKEN_SHAPE = /^(\d+):[A-Za-z0-9_-]{20,}$/;
61
36
  export const PAIRING_TTL_MS = 10 * 60_000;
62
37
  export const BRIDGE_LEASE_MS = 2 * 60_000;
63
38
  export const DELIVERY_CLAIM_MS = 2 * 60_000;
64
- /** Telegram's own message ceiling, with room for our part headers. */
65
39
  const PART_CAP = 3_900;
66
- /** Telegram's own limit on one message's text (Bot API sendMessage), less room for the line a tap adds under it. */
67
40
  const TELEGRAM_TEXT_MAX = 4_096 - 300;
68
- /** Pages of getUpdates one pass will read before reporting a backlog. */
69
41
  const PAGE_BUDGET = 10;
70
- // ---- pushed updates (v98) ----------------------------------------------------
71
- /** Where Telegram pushes this bot's updates: under the public hooks address (Tailscale Funnel covers /hooks). */
72
42
  export const TELEGRAM_HOOK_PATH = "/hooks/telegram";
73
43
  const HOOK_SECRET_FILE = "telegram-hook-secret";
74
- /** The secret Telegram sends with every push (its header), kept beside the database; made once when asked to. */
75
44
  export function telegramHookSecret(dir, make = false) {
76
45
  const file = join(dir, HOOK_SECRET_FILE);
77
46
  try {
@@ -79,7 +48,7 @@ export function telegramHookSecret(dir, make = false) {
79
48
  if (/^[A-Za-z0-9_-]{32,256}$/.test(saved))
80
49
  return saved;
81
50
  }
82
- catch { /* none yet */ }
51
+ catch { }
83
52
  if (!make)
84
53
  return null;
85
54
  const made = randomBytes(32).toString("base64url");
@@ -87,7 +56,6 @@ export function telegramHookSecret(dir, make = false) {
87
56
  chmodSync(file, 0o600);
88
57
  return made;
89
58
  }
90
- /** The address Telegram pushes to: the public hooks address (https only) and /hooks/telegram; null without one. */
91
59
  export function telegramPushUrl(hooksBase) {
92
60
  if (hooksBase === null)
93
61
  return null;
@@ -99,14 +67,12 @@ export function telegramPushUrl(hooksBase) {
99
67
  return null;
100
68
  }
101
69
  }
102
- /** A push is Telegram's when its secret header matches ours (compared in constant time). */
103
70
  export function pushedByTelegram(header, secret) {
104
71
  if (secret === null || typeof header !== "string")
105
72
  return false;
106
73
  const given = Buffer.from(header), wanted = Buffer.from(secret);
107
74
  return given.length === wanted.length && timingSafeEqual(given, wanted);
108
75
  }
109
- /** Keep one pushed update for the bridge. A schema-invalid JSON update is logged and acknowledged, never retried. */
110
76
  export function keepPushedUpdate(store, botId, body, now) {
111
77
  let raw;
112
78
  try {
@@ -121,17 +87,10 @@ export function keepPushedUpdate(store, botId, body, now) {
121
87
  return { ok: true, kept: false };
122
88
  }
123
89
  const kept = store.queueTelegramUpdate(botId, update.value.update_id, JSON.stringify(raw), now);
124
- // The bridge in this process (if any) stops idling and drains it now; elsewhere it waits at most one cycle.
125
90
  if (kept)
126
91
  wakeTelegramBridge(botId);
127
92
  return { ok: true, kept };
128
93
  }
129
- /**
130
- * Environment wins, the credential file beside the database otherwise.
131
- * The file is how the CLI and the web settings card set it (0600, owner
132
- * only); the env var is how people who already run keychain tooling keep
133
- * it out of files entirely.
134
- */
135
94
  export function loadBotToken(env, file) {
136
95
  const fromEnv = envValue(env, "TELEGRAM_TOKEN");
137
96
  if (fromEnv !== undefined && fromEnv.trim() !== "") {
@@ -148,7 +107,6 @@ export function loadBotToken(env, file) {
148
107
  const parsed = TOKEN_SHAPE.exec(raw);
149
108
  return parsed === null ? null : { token: raw, botId: parsed[1], source: "file" };
150
109
  }
151
- /** Write the credential file, owner-only. Refuses a string that is not a bot token. */
152
110
  export function saveBotToken(file, token) {
153
111
  if (!TOKEN_SHAPE.test(token.trim())) {
154
112
  return {
@@ -157,8 +115,6 @@ export function saveBotToken(file, token) {
157
115
  };
158
116
  }
159
117
  writeFileSync(file, `${token.trim()}\n`, { mode: 0o600 });
160
- // writeFileSync applies the mode only on creation; an existing file keeps
161
- // whatever it had, so the permission is asserted rather than assumed.
162
118
  chmodSync(file, 0o600);
163
119
  return { ok: true };
164
120
  }
@@ -171,15 +127,12 @@ export function clearBotToken(file) {
171
127
  return false;
172
128
  }
173
129
  }
174
- /** The last four characters are enough to recognize a token without holding it. */
175
130
  export function redactToken(token) {
176
131
  return `…${token.slice(-4)}`;
177
132
  }
178
- /** Scrub a token out of any text on its way to a log, an error, or a row. */
179
133
  export function scrub(text, token) {
180
134
  return token === "" ? text : text.split(token).join(redactToken(token));
181
135
  }
182
- /** A release card's full terms (release-card.ts) as the document Telegram sends with it: text this process wrote. */
183
136
  export const termsUpload = (file) => ({ field: "document", fileName: file.name, contentType: "text/plain", bytes: Buffer.from(file.text, "utf8") });
184
137
  export function createTransport(token, timeoutMs = 30_000) {
185
138
  return async (method, params, signal, upload, more) => {
@@ -193,17 +146,11 @@ export function createTransport(token, timeoutMs = 30_000) {
193
146
  signal.addEventListener("abort", onAbort, { once: true });
194
147
  }
195
148
  try {
196
- // A JSON call stays byte for byte what it was. A multipart call lets
197
- // fetch mint the boundary and the content-type: scalars ride as
198
- // fields, objects (reply_parameters, reply_markup) as their JSON, and
199
- // the verified bytes as one Blob under the file name given.
200
149
  const request = upload === undefined
201
150
  ? { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(params), signal: controller.signal }
202
151
  : { method: "POST", body: multipartOf(params, upload, ...(more ?? [])), signal: controller.signal };
203
152
  const response = await fetch(`https://api.telegram.org/bot${token}/${method}`, request);
204
153
  const body = (await response.json());
205
- // A missing or malformed acknowledgement does not prove a send failed.
206
- // Only Telegram's explicit rejection is a definite failed delivery.
207
154
  if (body === null || typeof body !== "object" || Array.isArray(body) || typeof body.ok !== "boolean" || (body.ok && !response.ok)) {
208
155
  return { ok: false, description: "Telegram returned an invalid acknowledgement", uncertain: true };
209
156
  }
@@ -211,7 +158,6 @@ export function createTransport(token, timeoutMs = 30_000) {
211
158
  ok: body.ok === true,
212
159
  result: body.result,
213
160
  ...(body.parameters === undefined ? {} : { parameters: body.parameters }),
214
- // Whatever Telegram said, the token must not be in what we keep.
215
161
  ...(typeof body.description !== "string" ? {} : { description: scrub(body.description, token) }),
216
162
  };
217
163
  }
@@ -228,15 +174,6 @@ export function createTransport(token, timeoutMs = 30_000) {
228
174
  }
229
175
  };
230
176
  }
231
- /**
232
- * Why this process can't reach Telegram the way the service does, or null.
233
- * A coding agent's sandbox fences the network: Codex says so in its own
234
- * variables, and Claude Code's sandbox routes traffic through a proxy on
235
- * this computer, which curl uses and Node's fetch does not — so sends fail
236
- * "fetch failed" while curl works (Oct 2). Builds, checks and agents also
237
- * get a database of their own, so none of them can hold the live bridge;
238
- * this keeps an agent-launched `watch` or `bridge` from holding it either.
239
- */
240
177
  export function networkFence(env) {
241
178
  const set = (name) => (env[name] ?? "") !== "";
242
179
  if (set("CODEX_SANDBOX_NETWORK_DISABLED") || set("CODEX_SANDBOX"))
@@ -255,11 +192,9 @@ export function networkFence(env) {
255
192
  });
256
193
  return agent && loopbackProxy ? "a Claude Code sandbox" : null;
257
194
  }
258
- /** The plain line a fenced process says instead of polling or sending. */
259
195
  export function networkFenceLine(reason) {
260
196
  return `Telegram: not connecting from here — this process runs inside ${reason}, which blocks its network. Replies and notifications go out from the Toolroll service.`;
261
197
  }
262
- /** fetch's own message ("fetch failed") with the reason under it, e.g. "fetch failed (EMFILE: too many open files)". */
263
198
  export function transportError(error) {
264
199
  const message = error instanceof Error ? error.message : String(error);
265
200
  const cause = error instanceof Error ? error.cause : undefined;
@@ -270,7 +205,6 @@ export function transportError(error) {
270
205
  const why = code !== null && !detail.includes(code) ? `${code}: ${detail}` : detail;
271
206
  return why === "" || why === message ? message : `${message} (${why.slice(0, 160)})`;
272
207
  }
273
- /** The multipart body: every param a field (objects as JSON), the file last. Exported for the adapter's own test only. */
274
208
  export function multipartOf(params, upload, ...more) {
275
209
  const form = new FormData();
276
210
  for (const [key, value] of Object.entries(params)) {
@@ -282,20 +216,12 @@ export function multipartOf(params, upload, ...more) {
282
216
  form.append(one.field, new Blob([new Uint8Array(one.bytes)], { type: one.contentType }), one.fileName);
283
217
  return form;
284
218
  }
285
- // ---- pairing ---------------------------------------------------------------
286
219
  export function hashPairingCode(code) {
287
220
  return createHash("sha256").update(code, "utf8").digest("hex");
288
221
  }
289
- /** 128 bits, hex — pasteable, and not guessable inside any code's lifetime. */
290
222
  export function mintPairingCode() {
291
223
  return randomBytes(16).toString("hex");
292
224
  }
293
- /**
294
- * One bridge pass: claim and send what the outbox holds, then read one
295
- * budgeted window of updates and apply each in its own transaction. Cron
296
- * calls this; running it twice concurrently loses the lease race and does
297
- * nothing, which is the design working.
298
- */
299
225
  export async function bridgePass(store, options) {
300
226
  const clock = options.clock ?? (() => new Date());
301
227
  const owner = options.owner ?? randomBytes(8).toString("hex");
@@ -314,15 +240,11 @@ export async function bridgePass(store, options) {
314
240
  await deliverOutbox(store, botId, transport, owner, clock, report, options.readProjects, options.canDeliver, options.conversation?.phoneOrigin, options.conversation?.evidenceRoot);
315
241
  await deliverTeam(store, botId, transport, clock, report, options.readProjects, options.canDeliver, options.conversation?.phoneOrigin);
316
242
  }
317
- // v98: updates Telegram pushed to the console apply first; asking for more only works while it isn't pushing.
318
243
  const pushed = await drainInbox({ store, botId, transport, clock, report, readProjects: options.readProjects, conversation: options.conversation, projects: null }, owner, lease.generation);
319
244
  if (pushed > 0)
320
245
  report.pushed = pushed;
321
246
  await drainUpdates(store, botId, transport, owner, lease.generation, lease.cursor, clock, report, 0, undefined, options.readProjects, options.conversation);
322
247
  if (options.conversation !== undefined && options.readProjects !== undefined) {
323
- // The queued turns, outside any transaction. A model turn can outlive
324
- // the poll lease, so the lease is renewed under the same owner while
325
- // they run — the follower's own fenced renewal, reused.
326
248
  const renew = setInterval(() => { store.acquireBridgeLease(botId, owner, BRIDGE_LEASE_MS, clock()); }, 30_000);
327
249
  renew.unref?.();
328
250
  try {
@@ -334,45 +256,15 @@ export async function bridgePass(store, options) {
334
256
  }
335
257
  }
336
258
  finally {
337
- // Handed back so the next cron firing is not told busy for the rest of
338
- // this pass's TTL. A crash skips this and the lease expires instead —
339
- // which is exactly what the TTL is for.
340
259
  store.releaseBridgeLease(botId, owner, clock());
341
260
  }
342
261
  return { ok: true, report };
343
262
  }
344
- // ---- the follower ----------------------------------------------------------
345
- /**
346
- * The longest long poll the follower may ask for. `createTransport`'s HTTP
347
- * timeout is 30s and must outlive the poll window, or the client would abort
348
- * a poll Telegram is still honestly holding open.
349
- */
350
263
  export const MAX_POLL_SECONDS = 25;
351
- /** Reconnect backoff: starts here, doubles per consecutive failure, capped. */
352
264
  const FOLLOW_BACKOFF_MS = [1_000, 2_000, 4_000, 8_000, 16_000, 30_000];
353
- /** A cycle that returned instantly with nothing is padded to this — a scripted or broken server must not spin the loop hot. */
354
265
  const FOLLOW_IDLE_FLOOR_MS = 1_000;
355
- /** While a long poll is open, how often the follower looks for a message due to go out (live-wakeups.md). */
356
266
  const DELIVERY_CHECK_MS = 1_000;
357
- /** v98: how often the bridge checks Telegram still pushes to us; how long pushes may keep failing before it asks
358
- * for updates itself; and how long it asks before trying pushes again. */
359
267
  const PUSH_CHECK_MS = 60_000, PUSH_GIVE_UP_MS = 5 * 60_000, PUSH_RETRY_MS = 15 * 60_000, PUSH_IDLE_MS = 2_000;
360
- /**
361
- * The follower (§M4): one actor that holds the poll lease and stays on the
362
- * wire, so an answer tapped on a phone reaches the store in seconds, not at
363
- * the next cron firing. `bridge telegram --follow` runs it standalone;
364
- * watch embeds the same actor — the poll lease guarantees only one is
365
- * live, and a cron pass overlapping it simply loses the lease race.
366
- *
367
- * Each cycle re-acquires the lease under the same owner — that is the
368
- * fenced renewal: same generation while held, and if the lease lapsed
369
- * mid-poll (a stall longer than the TTL), the re-acquire takes the next
370
- * generation and the cursor rides it, so nothing this follower stamped
371
- * with the old generation can move state afterwards. Transport failures
372
- * back off exponentially and are counted, not hidden; cancellation aborts
373
- * the in-flight long poll instead of waiting it out.
374
- */
375
- /** What Telegram lists when the person taps "/". */
376
268
  export const TELEGRAM_COMMANDS = [
377
269
  { command: "tasks", description: "Pick a task to talk about" },
378
270
  { command: "status", description: "Recent work across your projects" },
@@ -394,7 +286,6 @@ export async function followBridge(store, options) {
394
286
  }
395
287
  signal.addEventListener("abort", finish, { once: true });
396
288
  }));
397
- /** The push idle: the ordinary wait, ended early when this process keeps a push for this bot. */
398
289
  const idle = (ms) => {
399
290
  if (bridgeWokenEarly.delete(botId))
400
291
  return Promise.resolve();
@@ -412,14 +303,6 @@ export async function followBridge(store, options) {
412
303
  const total = { cycles: 0, sent: 0, answered: 0, paired: 0, ignored: 0, problems: [] };
413
304
  let commandsListed = false;
414
305
  let failures = 0;
415
- // Queued turns run BESIDE the poll, never inside a cycle: a long model
416
- // turn must not stall the long poll, and each cycle's lease re-acquire is
417
- // the renewal that keeps this the only live poller meanwhile. One
418
- // processor at a time; its counts land on the totals when it finishes.
419
- // It only persists the reply: the cycle sends it, in the same slot as
420
- // notifications, so a reply never needs a connection of its own beside
421
- // the long poll (Oct 2: replies failed "fetch failed" for minutes while
422
- // notifications from the same process went out).
423
306
  let inFlight = null;
424
307
  const kick = () => {
425
308
  if (inFlight !== null || options.conversation === undefined || options.readProjects === undefined)
@@ -438,12 +321,6 @@ export async function followBridge(store, options) {
438
321
  options.onCycle?.(report);
439
322
  });
440
323
  };
441
- // v98: pushed updates. With a public address, Telegram pushes each update to
442
- // /hooks/telegram and the console keeps it for us; while it does, nobody can
443
- // ask Telegram for this bot's updates — no other program can take them. Every
444
- // minute we check the address is still ours (a framework starting up elsewhere
445
- // may delete it); if pushes keep failing we ask for updates ourselves for a
446
- // while, then try pushes again.
447
324
  const push = options.push ?? null;
448
325
  const pushCheckMs = options.pushCheckMs ?? PUSH_CHECK_MS;
449
326
  let pushMode = push === null ? "poll" : "push";
@@ -495,7 +372,6 @@ export async function followBridge(store, options) {
495
372
  return;
496
373
  }
497
374
  pushRegistered = true;
498
- // Telegram couldn't deliver lately and updates are waiting: the address isn't reachable.
499
375
  const failing = (hook.pending_update_count ?? 0) > 0 && typeof hook.last_error_date === "number" && now / 1000 - hook.last_error_date < 180;
500
376
  if (!failing) {
501
377
  pushFailingSince = null;
@@ -513,48 +389,34 @@ export async function followBridge(store, options) {
513
389
  while (!signal.aborted) {
514
390
  const lease = store.acquireBridgeLease(botId, owner, BRIDGE_LEASE_MS, clock());
515
391
  if (!lease.ok) {
516
- // A cron pass (or a rival follower) holds the poll. Not an error —
517
- // wait our turn and try again.
518
392
  await wait(FOLLOW_BACKOFF_MS[Math.min(failures, FOLLOW_BACKOFF_MS.length - 1)]);
519
393
  failures = Math.min(failures + 1, FOLLOW_BACKOFF_MS.length - 1);
520
394
  continue;
521
395
  }
522
- // The "/" menu in Telegram, once, by the poller that holds the lease:
523
- // the picker first. Best effort; typed commands work either way.
524
396
  if (!commandsListed && options.conversation !== undefined) {
525
397
  commandsListed = true;
526
- // Both carry the stop signal: a stop never waits on a slow Bot API for them.
527
398
  try {
528
399
  await transport("setMyCommands", { commands: TELEGRAM_COMMANDS }, signal);
529
400
  }
530
- catch { /* typed commands still work */ }
531
- // After an upgrade, a bot still called StandingOrders becomes Toolroll, once per start; any other name is kept.
401
+ catch { }
532
402
  await nameTelegramBot(transport, "upgrade", signal);
533
403
  }
534
404
  const startedAt = Date.now();
535
405
  const report = { sent: 0, answered: 0, paired: 0, ignored: 0, backlog: false, problems: [] };
536
406
  await managePush(report);
537
- // What this cycle's delivery below covers: anything newer may end the long poll early.
538
407
  const deliveredThrough = newestNotificationIdOf(store);
539
408
  if (options.deliver !== false) {
540
409
  await deliverOutbox(store, botId, transport, owner, clock, report, options.readProjects, options.canDeliver, options.conversation?.phoneOrigin, options.conversation?.evidenceRoot);
541
410
  await deliverTeam(store, botId, transport, clock, report, options.readProjects, options.canDeliver, options.conversation?.phoneOrigin);
542
411
  }
543
- // Replies the turn worker has planned go out here, like notifications.
544
412
  if (options.conversation !== undefined && options.readProjects !== undefined) {
545
413
  await processConversations(store, botId, transport, owner, clock, report, options.readProjects, options.conversation, signal, "replies");
546
414
  }
547
- // Pushed updates first (some may wait from before a fall back), then — only while
548
- // Telegram isn't pushing — ask for more.
549
415
  const pushed = await drainInbox({ store, botId, transport, clock, report, readProjects: options.readProjects, conversation: options.conversation, projects: null }, owner, lease.generation);
550
416
  if (pushed > 0)
551
417
  report.pushed = pushed;
552
418
  if (!pushing()) {
553
- // While a turn is running, poll briefly so its reply is sent within a second or two of being written.
554
419
  const seconds = inFlight === null ? pollSeconds : 1;
555
- // A DELIVERY WAKE (live-wakeups.md): while the long poll is open, a message written for this bot since this
556
- // cycle began delivering ends the poll, once per cycle, so it goes out now instead of after the poll. Same
557
- // owner, same generation, one connection; the cursor moves only past updates already processed.
558
420
  const poll = new AbortController();
559
421
  const endPoll = () => poll.abort();
560
422
  if (signal.aborted)
@@ -588,7 +450,6 @@ export async function followBridge(store, options) {
588
450
  clearInterval(checker);
589
451
  signal.removeEventListener("abort", endPoll);
590
452
  }
591
- // A push address nobody here wants any more (the public address was removed): take it down, so asking works again.
592
453
  if (report.webhookActive === true && push === null)
593
454
  await transport("deleteWebhook", { drop_pending_updates: false }, signal);
594
455
  }
@@ -613,7 +474,6 @@ export async function followBridge(store, options) {
613
474
  options.onCycle?.(report);
614
475
  }
615
476
  if (report.problems.length > 0 && report.sent === 0 && report.answered === 0 && (report.chatAnswered ?? 0) === 0) {
616
- // The wire is down. Back off; the counter resets on the first clean cycle.
617
477
  if (!signal.aborted) {
618
478
  await wait(FOLLOW_BACKOFF_MS[Math.min(failures, FOLLOW_BACKOFF_MS.length - 1)]);
619
479
  }
@@ -621,25 +481,16 @@ export async function followBridge(store, options) {
621
481
  continue;
622
482
  }
623
483
  failures = 0;
624
- // A healthy cycle's wait IS the long poll. A cycle that came back
625
- // instantly and empty (scripted transport, misbehaving server) gets
626
- // padded so the loop cannot spin hot.
627
484
  const took = Date.now() - startedAt;
628
- // While Telegram pushes (v98) there is no long poll to wait on: a pushed update waits at most this long.
629
485
  const floor = pushing() ? PUSH_IDLE_MS : FOLLOW_IDLE_FLOOR_MS;
630
- // A delivery wake goes straight back round to send: no padding.
631
486
  if (!signal.aborted && report.deliveryWake !== true && report.sent === 0 && report.answered === 0 && (report.chatAnswered ?? 0) === 0 && took < floor) {
632
- // While Telegram pushes, a push kept by this process's hook ends the idle at once.
633
487
  await (pushing() ? idle(floor - took) : wait(floor - took));
634
488
  }
635
489
  }
636
490
  }
637
491
  finally {
638
- // A turn in flight finishes on its own bounds (the engine's wall clock);
639
- // its reply is fenced on the claim and the channel like every other part.
640
492
  if (inFlight !== null) {
641
493
  await inFlight;
642
- // Its reply was written for the cycle that will not come: send it now, while the lease is still ours.
643
494
  if (options.conversation !== undefined && options.readProjects !== undefined) {
644
495
  const report = { sent: 0, answered: 0, paired: 0, ignored: 0, backlog: false, problems: [] };
645
496
  await processConversations(store, botId, transport, owner, clock, report, options.readProjects, options.conversation, undefined, "replies").catch(() => { });
@@ -652,7 +503,6 @@ export async function followBridge(store, options) {
652
503
  }
653
504
  return total;
654
505
  }
655
- /** The queued turns for one bot, counted onto the pass's report. */
656
506
  async function processConversations(store, botId, transport, owner, clock, report, readProjects, conversation, signal, only) {
657
507
  const chat = { answered: 0, refused: 0, problems: [] };
658
508
  await processTelegramConversations({ store, botId, transport, owner, clock, readProjects, options: conversation, report: chat, ...(signal === undefined ? {} : { signal }), ...(only === undefined ? {} : { only }) });
@@ -662,7 +512,6 @@ async function processConversations(store, botId, transport, owner, clock, repor
662
512
  report.chatRefused = (report.chatRefused ?? 0) + chat.refused;
663
513
  report.problems.push(...chat.problems);
664
514
  }
665
- /** A fact's own next-action button row under the trusted origin read now; none without one. */
666
515
  function factButton(phoneOrigin, link) {
667
516
  try {
668
517
  return phoneLinkButton(phoneOrigin?.() ?? null, { label: factLinkLabel(link), path: link });
@@ -671,7 +520,6 @@ function factButton(phoneOrigin, link) {
671
520
  return null;
672
521
  }
673
522
  }
674
- /** A view's buttons on one row: its link, then any others ([Merge] [Look first]); none without a trusted origin. */
675
523
  function viewKeyboard(phoneOrigin, view) {
676
524
  try {
677
525
  const origin = phoneOrigin?.() ?? null;
@@ -682,11 +530,9 @@ function viewKeyboard(phoneOrigin, view) {
682
530
  return [];
683
531
  }
684
532
  }
685
- /** Where a paired person taps: their binding and private chat. */
686
533
  function decideSeat(binding) {
687
534
  return { channel: "telegram", binding: binding.id, chat: binding.chatId, approver: binding.approver, generation: binding.approverGeneration };
688
535
  }
689
- /** Decide buttons as Telegram draws them: an act's opaque token, or a link under the trusted origin read now (none without one). */
690
536
  function decideKeyboard(phoneOrigin, rows) {
691
537
  let origin = null;
692
538
  try {
@@ -698,14 +544,12 @@ function decideKeyboard(phoneOrigin, rows) {
698
544
  return rows.map(row => row.flatMap((one) => "token" in one ? [telegramButton(one.label, one.token)]
699
545
  : phoneLinkButton(origin, one.link) ?? [])).filter(row => row.length > 0);
700
546
  }
701
- /** What this card may act on in the chat now, for this person under their current ceiling; null keeps its link. */
702
547
  function decideOfferFor(store, binding, target, projects, now, root) {
703
548
  if (target === null || target === undefined)
704
549
  return null;
705
550
  const principal = verifyApproverStanding(store, binding.approver, binding.approverGeneration, telegramConversationRepos(store, binding.approver, projects));
706
551
  return principal.ok ? decideOffer(store, target, principal.who, now, "telegram", root) : null;
707
552
  }
708
- /** Team-conversation traffic to the chats that follow one — after the outbox, under the same delivery switch, never a problem to raise when nothing follows anything. */
709
553
  async function deliverTeam(store, botId, transport, clock, report, readProjects, canDeliver, phoneOrigin) {
710
554
  if (store.listTelegramTeamChats(botId).length === 0)
711
555
  return;
@@ -732,38 +576,27 @@ async function deliverTeam(store, botId, transport, clock, report, readProjects,
732
576
  async function deliverOutbox(store, botId, transport, owner, clock, report, readProjects, canDeliver, phoneOrigin, evidenceRoot) {
733
577
  const bindings = store.liveTelegramBindings(botId);
734
578
  if (bindings.length === 0) {
735
- // Routine progress facts are not a problem to fix: a first pairing
736
- // starts from now and settles them as history. Anything else pending
737
- // is named, once per pass, as before.
738
579
  if (store.listNotifications("pending").some(row => !isLifecycleNotification(row) && !isShotsKind(row.kind)))
739
580
  report.problems.push("outbox rows are pending but no chat is paired — `toolroll bridge telegram pair`");
740
581
  return;
741
582
  }
742
583
  const digest = store.telegramDigest();
743
584
  const now = clock();
744
- // An evening digest someone asked for is due: record it as their own notification, delivered below.
745
585
  try {
746
586
  enqueueEveningDigests(store, now, evidenceRoot);
747
587
  }
748
588
  catch {
749
589
  report.problems.push("evening digest could not be prepared");
750
590
  }
751
- // A lead claim that went two hours quiet repaints its owner's card back to the task's real state.
752
591
  enqueueLeadLapses(store, now);
753
592
  const digestDue = digest.everyMs === null || digest.lastSentAt === null || now.getTime() >= new Date(digest.lastSentAt).getTime() + digest.everyMs;
754
- // Every paired person is a destination of their own: each binding claims
755
- // and settles its own rows under its own ceiling, in turn.
756
593
  for (const binding of bindings)
757
594
  await deliverOutboxTo(store, botId, binding, transport, owner, clock, report, digest, digestDue, readProjects, canDeliver, phoneOrigin, evidenceRoot);
758
595
  }
759
596
  async function deliverOutboxTo(store, botId, binding, transport, owner, clock, report, digest, digestDue, readProjects, canDeliver, phoneOrigin, evidenceRoot) {
760
597
  const now = clock();
761
- // Only when I'm needed (the default): a task's facts edit its one card and only what needs this person makes a
762
- // new message, so the installation's routine-fact cadence does not apply. Every step keeps today's behaviour.
763
598
  const quiet = store.notificationPreference(binding.approver).mode === "quiet";
764
599
  const claimed = store.claimTelegramDeliveries(binding, owner, DELIVERY_CLAIM_MS, now, quiet || digestDue ? "all" : "urgent");
765
- // Preserve ID order, flushing earlier routine facts before an urgent task
766
- // update. An earlier failed/retrying row also fences later rows for that task.
767
600
  const groups = [];
768
601
  for (const row of claimed) {
769
602
  const last = groups[groups.length - 1];
@@ -794,15 +627,10 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
794
627
  return null;
795
628
  };
796
629
  const retryAt = () => [store.telegramRetryAt(botId), new Date(clock().getTime() + 1_000).toISOString()].sort().at(-1);
797
- // Partition before anything is sent: a row without live authority is
798
- // retained with its reason, and the rows that ARE eligible go out now
799
- // rather than waiting on it. Walking in ID order with the eligible set
800
- // as the batch keeps a task's later facts behind its blocked earlier one.
801
630
  const rows = [];
802
631
  const blocked = [];
803
632
  const preflight = (await readAccess()) ?? channelProblem();
804
633
  for (const row of group) {
805
- // Watched since the claim (cockpit §3): held for later or settled quietly, never sent now, never a failure.
806
634
  if (preflight === null && store.telegramWatchFence(row, binding, owner, clock()) !== "send")
807
635
  continue;
808
636
  const problem = preflight ?? store.telegramDeliveryProblem(row, binding, owner, projects, clock(), [...rows.map(one => one.id), row.id]);
@@ -820,8 +648,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
820
648
  if (rows.length === 0)
821
649
  continue;
822
650
  const ids = rows.map(row => row.id);
823
- // Once any part of this delivery has reached Telegram it is committed: a watch opening between its parts never
824
- // releases it (that would send the parts already accepted again). Every transport call below goes through `wire`.
825
651
  let sentAny = false;
826
652
  const wire = async (...args) => {
827
653
  const answer = await transport(...args);
@@ -829,7 +655,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
829
655
  sentAny = true;
830
656
  return answer;
831
657
  };
832
- /** A release card's terms file (release-card.ts), sent before the card itself. */
833
658
  const fileSender = async (file) => {
834
659
  try {
835
660
  return (await wire("sendDocument", { chat_id: binding.chatId, caption: "Every term of this release" }, undefined, termsUpload(file))).ok === true;
@@ -838,8 +663,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
838
663
  return false;
839
664
  }
840
665
  };
841
- // `beforeSend`: the fence before a transport call also asks the watch — until something of this delivery went out;
842
- // the one after a confirmed send never does, so a message Telegram accepted is recorded as delivered.
843
666
  const fence = (beforeSend = !sentAny) => {
844
667
  const channel = channelProblem();
845
668
  if (channel !== null)
@@ -848,15 +671,12 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
848
671
  const problem = store.telegramDeliveryProblem(row, binding, owner, projects, clock(), ids);
849
672
  if (problem !== null)
850
673
  return problem;
851
- // The watch, at the last moment before the network: a held row's claim is released (its finalize is then a
852
- // no-op), so nothing is spent on it.
853
674
  if (beforeSend && store.telegramWatchFence(row, binding, owner, clock()) !== "send")
854
675
  return WATCHED_SINCE_CLAIM;
855
676
  }
856
677
  return null;
857
678
  };
858
679
  const sender = async (text, keyboard, messageRows = rows, entities, silent) => {
859
- // Finish every await before the synchronous fence and transport call.
860
680
  const problem = (await readAccess()) ?? fence();
861
681
  if (problem !== null)
862
682
  return { ok: false, error: problem };
@@ -870,7 +690,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
870
690
  return { ok: false, error: "Telegram returned no confirmed message identity" };
871
691
  for (const row of messageRows)
872
692
  store.recordTelegramMessage(row, binding, sent.messageId, clock());
873
- // Keep the old message's history but never acknowledge a replaced pairing.
874
693
  const after = (await readAccess()) ?? fence(false);
875
694
  return after === null ? sent : { ok: false, error: after };
876
695
  };
@@ -891,13 +710,10 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
891
710
  const sent = await sender(`A screenshot for result #${row.run} could not be sent: ${verified.problem}. Inspect the result before accepting.`);
892
711
  return sent.ok ? { ok: true, receipt: receiptFor(botId, binding.chatId, sent.messageId) } : sent;
893
712
  }
894
- // Already sent with its result (result-shots.ts): the same screenshot is not sent again.
895
713
  const artifact = Number(match[2]);
896
714
  if (store.resultShotsSent(row.destination, row.run).has(artifact))
897
715
  return { ok: true, receipt: "skipped:screenshot-sent" };
898
- // Marked while it goes, so the screenshots sent with the result skip it; any failure unmarks it for the retry.
899
716
  store.markResultShotsSent(row.destination, row.run, [artifact], clock());
900
- // No await between the access fence, file validation and upload.
901
717
  let answer;
902
718
  try {
903
719
  answer = await wire("sendDocument", { chat_id: binding.chatId, caption: `${resultTaskLabel(row.taskId)} · result #${row.run} · screenshot for acceptance` }, undefined, {
@@ -919,8 +735,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
919
735
  const after = (await readAccess()) ?? fence(false);
920
736
  return after === null ? { ok: true, receipt: receiptFor(botId, binding.chatId, String(messageId)) } : { ok: false, error: after };
921
737
  };
922
- /** Screenshots with a result (result-shots.ts): photos, several as one album, re-proved before every call. Each is
923
- * marked sent before it goes, so an unconfirmed send is never repeated; only Telegram's outright refusal unmarks it. */
924
738
  const shotsSender = async (row) => {
925
739
  let receipt = null;
926
740
  for (let call = 0; call <= 4; call++) {
@@ -934,7 +748,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
934
748
  const sent = await sender(plan.text, undefined, [row]);
935
749
  return sent.ok ? { ok: true, receipt: receiptFor(botId, binding.chatId, sent.messageId) } : sent;
936
750
  }
937
- // No await between the access fence, the files' verification and the upload.
938
751
  const photos = plan.shots.filter(one => one.photo);
939
752
  const batch = photos.length >= 2 ? photos : [plan.shots[0]];
940
753
  const upload = (one, field) => ({ field, fileName: one.fileName, contentType: one.format === "png" ? "image/png" : "image/jpeg", bytes: one.bytes });
@@ -959,7 +772,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
959
772
  }
960
773
  const messages = (Array.isArray(answer.result) ? answer.result : [answer.result])
961
774
  .map(one => one?.message_id).filter((one) => Number.isSafeInteger(one));
962
- // An unconfirmed send stays marked: it may have arrived, so it is never sent again.
963
775
  if (!answer.ok || messages.length === 0)
964
776
  report.problems.push(`notification ${row.id}: Telegram did not confirm the screenshots; they are not sent again`);
965
777
  for (const one of messages)
@@ -986,7 +798,7 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
986
798
  try {
987
799
  button = phoneLinkButton(phoneOrigin?.() ?? null, card.link);
988
800
  }
989
- catch { /* No trusted origin. */ }
801
+ catch { }
990
802
  const keyboard = button === null ? [] : [button];
991
803
  if (messageId === null)
992
804
  return sender(card.text, keyboard, rows, card.entities);
@@ -994,8 +806,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
994
806
  if (!edited.ok) {
995
807
  if (edited.retryAfter !== undefined)
996
808
  store.deferTelegram(botId, new Date(clock().getTime() + edited.retryAfter * 1000).toISOString());
997
- // Only Telegram's definitive missing/uneditable response permits a
998
- // replacement. Timeouts, rate limits and uncertain edits retry in place.
999
809
  if (!onlyExisting && edited.replace)
1000
810
  return sender(card.text, keyboard, rows, card.entities);
1001
811
  return edited;
@@ -1005,7 +815,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1005
815
  const after = (await readAccess()) ?? fence(false);
1006
816
  return after === null ? edited : { ok: false, error: after };
1007
817
  };
1008
- /** Quiet mode: the task's one card (or its group's), created silently and then only ever edited. */
1009
818
  const updateCard = async (fact) => {
1010
819
  const problem = (await readAccess()) ?? fence();
1011
820
  if (problem !== null)
@@ -1018,7 +827,7 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1018
827
  try {
1019
828
  button = phoneLinkButton(phoneOrigin?.() ?? null, view.link);
1020
829
  }
1021
- catch { /* No trusted origin. */ }
830
+ catch { }
1022
831
  const keyboard = button === null ? [] : [button];
1023
832
  const shown = createHash("sha256").update(JSON.stringify([view.text, view.entities, keyboard])).digest("hex");
1024
833
  if (card.message !== null && card.digest === shown) {
@@ -1035,12 +844,10 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1035
844
  }
1036
845
  if (edited.retryAfter !== undefined)
1037
846
  store.deferTelegram(botId, new Date(clock().getTime() + edited.retryAfter * 1000).toISOString());
1038
- // Only Telegram's definitive missing/uneditable answer permits a replacement card.
1039
847
  if (!edited.replace)
1040
848
  return edited;
1041
849
  }
1042
850
  const sent = await sender(view.text, keyboard, [fact], view.entities, true);
1043
- // A card that reached the chat is kept even if a later fence refused the acknowledgement: never a second card.
1044
851
  const placed = sent.ok ? sent.messageId : store.telegramMessageOf(fact.id, fact.destination);
1045
852
  if (placed !== null)
1046
853
  store.setChatCardMessage(card.id, placed, shown);
@@ -1054,9 +861,7 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1054
861
  return { ok: true, receipt: receiptFor(botId, binding.chatId, card.messageId) };
1055
862
  const readyRun = fact.kind === "run-finished" ? store.telegramProgressRun(fact) : null;
1056
863
  if (readyRun !== null || (fact.kind !== "run-finished" && joinsBatch(fact))) {
1057
- // Any update for this person joins their open batch: one message, edited in place while it grows.
1058
864
  const batch = store.chatBatchFor(fact.destination, fact.taskRef, readyRun?.id ?? store.telegramProgressRun(fact)?.id ?? null, clock(), BATCH_MS, readyRun !== null ? null : fact.id);
1059
- // A lone update that is not finished work goes out exactly as it always has; a later one edits it in place.
1060
865
  const lone = batch.items.length === 1 && batch.items[0].notification !== null;
1061
866
  if (batch.message === null && lone) {
1062
867
  const sent = await deliverOne(store, botId, binding, sender, fact, clock, phoneOrigin, evidenceRoot, projects, fileSender);
@@ -1066,26 +871,18 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1066
871
  return sent;
1067
872
  }
1068
873
  const view = finishedView(store, batch, clock(), evidenceRoot, binding.approver);
1069
- // Nothing in the batch reads as a line. Finished work left out on purpose (a release check, a replaced task,
1070
- // the reader's own completion) stays quiet; any other update that needs this person still reaches them alone.
1071
874
  if (view === null) {
1072
875
  if (readyRun !== null)
1073
876
  return { ok: true, receipt: receiptFor(botId, binding.chatId, card.messageId) };
1074
877
  return deliverOne(store, botId, binding, sender, fact, clock, phoneOrigin, evidenceRoot, projects, fileSender);
1075
878
  }
1076
- // A message about one result, plan, failure or pull request acts in place (chat-decide.ts); its buttons are
1077
- // minted only when what it offers changed, or its own were spent (Not now), so an unchanged repaint keeps the
1078
- // ones already in the chat.
1079
879
  const offer = decideOfferFor(store, binding, view.target, projects, clock(), evidenceRoot);
1080
880
  const text = offer?.text ?? view.text;
1081
- // While a lone update is still the only item, its edit keeps that update's own action button.
1082
881
  const own = offer === null && lone && fact.link !== null ? factButton(phoneOrigin, fact.link) : null;
1083
882
  let keyboard = own !== null ? [own] : viewKeyboard(phoneOrigin, view);
1084
883
  const shown = createHash("sha256").update(JSON.stringify(offer === null ? [view.text, keyboard] : [text, offerFingerprint(offer)])).digest("hex");
1085
884
  let tokens = [];
1086
- // A release card's terms go as a file first, on this road as on a lone delivery: no file accepted, no buttons.
1087
885
  const termsFirst = async () => offer?.file === undefined || (fileSender !== undefined && await fileSender(offer.file)) ? null : { ok: false, error: "The release's terms file wasn't accepted" };
1088
- // Minted unplaced: they ride a message only once it shows them, and until then the old card's buttons work.
1089
886
  const mintFor = () => {
1090
887
  if (offer === null)
1091
888
  return;
@@ -1107,7 +904,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1107
904
  mintFor();
1108
905
  const edited = await editProgress(wire, binding.chatId, batch.message, text, keyboard);
1109
906
  if (edited.ok) {
1110
- // The repaint landed: the old words' buttons retire and the new ones ride the message.
1111
907
  retireDecideTokens(store, "telegram", binding.chatId, batch.message, clock());
1112
908
  placeDecideTokens(store, tokens, batch.message);
1113
909
  store.setChatBatchMessage(batch.id, batch.message, shown);
@@ -1115,15 +911,12 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1115
911
  const after = (await readAccess()) ?? fence(false);
1116
912
  return after === null ? { ok: true, receipt: receiptFor(botId, binding.chatId, batch.message) } : { ok: false, error: after };
1117
913
  }
1118
- // A failed edit: the buttons it carried never act, and the card's old ones keep working.
1119
914
  dropDecideTokens(store, tokens, clock());
1120
915
  if (edited.retryAfter !== undefined)
1121
916
  store.deferTelegram(botId, new Date(clock().getTime() + edited.retryAfter * 1000).toISOString());
1122
- // Only Telegram's definitive missing/uneditable answer permits a new message.
1123
917
  if (!edited.replace)
1124
918
  return edited;
1125
919
  }
1126
- // A new message: its buttons are minted for it, never the ones a failed edit was given.
1127
920
  if (batch.message === null) {
1128
921
  const terms = await termsFirst();
1129
922
  if (terms !== null)
@@ -1135,7 +928,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1135
928
  if (placed !== null)
1136
929
  store.setChatBatchMessage(batch.id, placed, shown);
1137
930
  if (sent.ok && sent.messageId !== null) {
1138
- // The new card replaces the old one: only its buttons act.
1139
931
  if (batch.message !== null)
1140
932
  retireDecideTokens(store, "telegram", binding.chatId, batch.message, clock());
1141
933
  placeDecideTokens(store, tokens, sent.messageId);
@@ -1146,7 +938,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1146
938
  }
1147
939
  return fact.kind === "acceptance-evidence" ? imageSender(fact) : deliverOne(store, botId, binding, sender, fact, clock, phoneOrigin, evidenceRoot, projects, fileSender);
1148
940
  };
1149
- /** The lead's words (lead-voice.ts): one message; a later say within two minutes edits it in place. */
1150
941
  const leadSayOutcome = async (fact) => {
1151
942
  const words = leadSayText(store, fact, binding.approver);
1152
943
  const button = fact.link === null ? null : factButton(phoneOrigin, fact.link);
@@ -1164,7 +955,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1164
955
  }
1165
956
  if (edited.retryAfter !== undefined)
1166
957
  store.deferTelegram(botId, new Date(clock().getTime() + edited.retryAfter * 1000).toISOString());
1167
- // Only Telegram's definitive missing/uneditable answer permits a new message.
1168
958
  if (!edited.replace)
1169
959
  return edited;
1170
960
  }
@@ -1179,8 +969,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1179
969
  else if (quiet && rows.length === 1 && isTaskFact(row))
1180
970
  outcome = await quietOutcome(row);
1181
971
  else {
1182
- // A failure or decision still gets its own alert. Refresh an existing
1183
- // card first so it does not keep saying the build is running.
1184
972
  if (!progress && progressRun !== null)
1185
973
  await updateProgress(true);
1186
974
  const updated = progress ? await updateProgress(false) : null;
@@ -1191,7 +979,6 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1191
979
  }
1192
980
  const finalProblem = outcome.ok ? (await readAccess()) ?? fence(false) : null;
1193
981
  const settled = finalProblem === null ? outcome : { ok: false, error: finalProblem };
1194
- // A skipped screenshot settles its row but nothing reached the phone.
1195
982
  const skipped = settled.ok && settled.receipt !== null && settled.receipt.startsWith("skipped:");
1196
983
  const finalized = store.transact(() => {
1197
984
  let count = 0;
@@ -1214,18 +1001,12 @@ async function deliverOutboxTo(store, botId, binding, transport, owner, clock, r
1214
1001
  report.problems.push("Telegram delivery claim expired before acknowledgement; retry may duplicate a message");
1215
1002
  }
1216
1003
  }
1217
- /** What pages singly whatever the cadence: a decision, or an attention-class fact. */
1218
1004
  function isUrgent(notification) {
1219
1005
  return /^decision:\d+$/.test(notification.dedupeKey) || notification.pushClass === "attention" || notification.kind === "acceptance-evidence" || notification.kind === "acceptance-ready";
1220
1006
  }
1221
- /** A routine fact the digest may carry. Screenshots are never urgent (they follow their result message, which the
1222
- * task's order fence holds them behind) and never a digest line: they go as their own photos once it has gone. */
1223
1007
  function joinsDigest(notification) {
1224
1008
  return !isUrgent(notification) && !isShotsKind(notification.kind);
1225
1009
  }
1226
- /** The digest text: a header with the count and the window, then one
1227
- * fact per entry — its subject, then its body's first line, indented.
1228
- * Plain text, no buttons: nothing in a digest is tappable. */
1229
1010
  export function digestText(rows, since, now, titleOf) {
1230
1011
  const window = since === null ? "" : ` since ${since.slice(0, 16).replace("T", " ")}`;
1231
1012
  const lines = [`digest — ${rows.length} routine fact(s)${window} (as of ${now.toISOString().slice(0, 16).replace("T", " ")})`, ""];
@@ -1244,8 +1025,6 @@ function digestEntry(row, titleOf) {
1244
1025
  }
1245
1026
  async function deliverDigest(botId, binding, sender, rows, since, clock, titleOf) {
1246
1027
  const text = digestText(rows, since, clock(), titleOf);
1247
- // Track the exact rows represented by each text part. A split row may bind
1248
- // several messages; a digest message may bind several rows.
1249
1028
  let offset = text.indexOf("\n\n") + 2;
1250
1029
  const spans = rows.map(row => {
1251
1030
  const length = digestEntry(row, titleOf).length;
@@ -1272,11 +1051,6 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1272
1051
  return { ok: false, error: "Decision does not match notification provenance" };
1273
1052
  }
1274
1053
  if (decision === null || decision.state === "answered") {
1275
- // A plain fact, or a decision settled before the bridge got to it: the
1276
- // text is the message. Its one next-action button — the fact's
1277
- // machine-minted link under the trusted origin read now, never a token
1278
- // and never persisted — rides the LAST part only, exactly as `/task`'s
1279
- // does; with no trusted origin the words stand alone.
1280
1054
  const alreadyAccepted = notification.kind === "acceptance-ready" && notification.run !== null && store.proofAcceptance(notification.run) !== null;
1281
1055
  let body = alreadyAccepted ? "This result already has recorded human acceptance. No further acceptance is needed." : notification.body;
1282
1056
  let current = true;
@@ -1296,12 +1070,9 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1296
1070
  else
1297
1071
  body = `${packet.text}\n\n${notification.body}`;
1298
1072
  }
1299
- // A short title, never the task's id or a "— revision" suffix (chat-voice.ts).
1300
1073
  const title = notification.taskId === null ? undefined : chatTitle(store, notification.taskId);
1301
1074
  const task = notification.taskId === null ? [] : [{ id: notification.taskId, ...(title === undefined ? {} : { title }) }];
1302
1075
  const words = chatText(`${alreadyAccepted ? "Acceptance recorded" : leadSubjectOf(store, notification, binding.approver)}${body === "" ? "" : `\n\n${body}`}`, task);
1303
- // The task's title once: in front, unless the words already name it.
1304
- // A result, plan, failure or ready pull request acts in place (chat-decide.ts); otherwise its one link.
1305
1076
  const target = alreadyAccepted || !current ? null : decideTargetOf(notification);
1306
1077
  const offer = decideOfferFor(store, binding, target, projects, clock(), evidenceRoot);
1307
1078
  const decided = offer === null ? null : mintDecideButtons(store, decideSeat(binding), target, offer, clock());
@@ -1314,11 +1085,9 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1314
1085
  return null;
1315
1086
  } })()
1316
1087
  : offer === null && notification.link !== null && !alreadyAccepted && current ? factButton(phoneOrigin, notification.link) : null;
1317
- // A flow card waiting on a decision (v86): Approve, Edit, Send back on the last part, for this visit only.
1318
1088
  const visit = FLOW_DECIDE_KEY.exec(notification.dedupeKey);
1319
1089
  const waiting = visit === null ? null : flowDecisionAt(store, Number(visit[1]), Number(visit[2]));
1320
1090
  const flowKeys = waiting === null ? null : flowButtons(store, binding, waiting, clock());
1321
- // A flow's "Send to me" or "Person chooses" (flow-send.ts): its links as buttons, and a choice's options above them.
1322
1091
  const sentVisit = FLOW_SEND_KEY.exec(notification.dedupeKey) ?? FLOW_CHOOSE_KEY.exec(notification.dedupeKey);
1323
1092
  const sent = sentVisit === null ? null : flowSentContent(store, Number(sentVisit[1]), Number(sentVisit[2]));
1324
1093
  const choosing = sent === null || !FLOW_CHOOSE_KEY.test(notification.dedupeKey) || notification.recipient !== binding.approver ? null : flowChoiceAt(store, Number(sentVisit[1]), Number(sentVisit[2]));
@@ -1331,8 +1100,6 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1331
1100
  } })();
1332
1101
  if (sentRow !== null)
1333
1102
  button = sentRow.length === 0 ? null : sentRow;
1334
- // A flow decision or choice for this person leads with what to do and where each button takes the card
1335
- // (telegram-flow.ts); the flow and zone close it. The saved notice keeps its own words for every other place.
1336
1103
  const pull = sent === null ? [] : sent.links.flatMap(one => "url" in one ? [`${one.label}: ${one.url}`] : []).slice(0, 1);
1337
1104
  const choiceHead = choosing === null || sent === null ? null : flowChoiceHead(choosing, sent);
1338
1105
  const choiceTail = choosing === null ? [] : [...pull, `${choosing.flow.name}${sent?.from === undefined ? "" : ` · after ${sent.from}`}`];
@@ -1340,8 +1107,6 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1340
1107
  parts = split(`${notificationIdentity(notification)}${chatText(flowDecisionText(waiting, notification.body), task)}`);
1341
1108
  else if (offer === null && choiceHead !== null && sent !== null)
1342
1109
  parts = split(`${notificationIdentity(notification)}${chatText([...choiceHead, "", sent.summary, "", ...choiceTail.flatMap((line, index) => index === 0 ? [line] : ["", line])].join("\n"), task)}`);
1343
- // After research (flow-items.ts): each item numbered under the summary, its words cleaned as the rest of the message's
1344
- // are, within Telegram's limit with every link kept — one message, unless head, links and tail alone overflow it.
1345
1110
  let entities = [];
1346
1111
  if (sent?.items !== undefined && sent.items.length > 0 && offer === null) {
1347
1112
  const subject = chatText(leadSubjectOf(store, notification, binding.approver), task);
@@ -1352,21 +1117,17 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1352
1117
  parts = voiced.map(one => one.text);
1353
1118
  entities = voiced.map(one => one.entities);
1354
1119
  }
1355
- // A flow's result as a card (flow-result-card.ts): one more message, its tables as monospaced text.
1356
1120
  const resultCard = offer === null ? sent?.card ?? flowDoneCard(store, notification, clock()) : null;
1357
1121
  if (resultCard != null) {
1358
1122
  const message = telegramCardMessage(resultCard);
1359
1123
  entities = [...parts.map((_, at) => entities[at] ?? []), message.entities];
1360
1124
  parts = [...parts, message.text];
1361
1125
  }
1362
- // Its links stay on the words: the card follows them.
1363
1126
  const keyedPart = parts.length - (resultCard != null ? 2 : 1);
1364
- // A subagent's question (v93): its options and "Answer in words", for the person it asks.
1365
1127
  const asked = flowKeys === null && choiceKeys === null ? openQuestionOf(store, notification.dedupeKey) : null;
1366
1128
  const questionKeys = asked === null ? null : telegramQuestionButtons(store, binding, asked, clock());
1367
1129
  const keys = flowKeys ?? choiceKeys ?? questionKeys;
1368
1130
  let last = null;
1369
- // A release card: every term goes as a file first, so Continue is offered only once it has arrived.
1370
1131
  if (offer?.file !== undefined && decided !== null) {
1371
1132
  if (fileSender === undefined || !await fileSender(offer.file)) {
1372
1133
  dropDecideTokens(store, decided.tokens, clock());
@@ -1389,7 +1150,6 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1389
1150
  store.placeTelegramFlowActions(flowKeys.tokens, last);
1390
1151
  if (choiceKeys !== null && last !== null) {
1391
1152
  store.placeTelegramFlowChoices(choiceKeys.tokens, last);
1392
- // A reply to this message, instead of a tap, is the person's note (applyFlowReply).
1393
1153
  if (sent?.reply === true)
1394
1154
  store.recordTelegramFlowPrompt({ chatId: binding.chatId, messageId: last, binding: binding.id, card: choosing.card.id, entry: choosing.card.entry, mode: "send-back" }, clock(), 7 * 24);
1395
1155
  }
@@ -1399,25 +1159,15 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1399
1159
  placeDecideTokens(store, decided.tokens, last);
1400
1160
  return { ok: true, receipt: receiptFor(botId, binding.chatId, last) };
1401
1161
  }
1402
- // A decision. Every safety-bearing word goes out before anything tappable
1403
- // exists: the question and every option's consequence first, then the
1404
- // recap, split across as many plain messages as they need — a button whose
1405
- // warning was truncated away is a trap, so the keyboard rides the LAST part
1406
- // only, and only if every earlier part arrived.
1407
1162
  const parts = split([`${notificationIdentity(notification)}${decisionAsk(decision)}`, "", `Background: ${decision.recap}`].join("\n"));
1408
1163
  for (const part of parts.slice(0, -1)) {
1409
1164
  const sent = await sender(part);
1410
1165
  if (!sent.ok)
1411
1166
  return { ok: false, error: sent.error };
1412
- // Every part is a message somebody may REPLY to with a note: each id
1413
- // routes to this decision, exactly (Codex free-text review, finding 1).
1414
1167
  if (sent.messageId !== null) {
1415
1168
  store.recordTelegramDecisionMessage(binding.id, binding.chatId, sent.messageId, decision.id, clock());
1416
1169
  }
1417
1170
  }
1418
- // The buttons: one opaque token per option, minted before the send so a
1419
- // tap can never arrive for a token that does not exist, placed onto the
1420
- // message afterwards so a tap on any OTHER message proves itself stale.
1421
1171
  const tokens = decision.options.map(option => ({
1422
1172
  option,
1423
1173
  token: randomBytes(16).toString("hex"),
@@ -1446,8 +1196,6 @@ async function deliverOne(store, botId, binding, sender, notification, clock, ph
1446
1196
  return { ok: true, receipt: receiptFor(botId, binding.chatId, sent.messageId) };
1447
1197
  }
1448
1198
  async function send(transport, chatId, text, keyboard, entities, silent) {
1449
- // No markup parsing. Only machine-selected heading ranges may be bold;
1450
- // agent text remains literal and URLs never trigger link previews.
1451
1199
  let answer;
1452
1200
  try {
1453
1201
  answer = await transport("sendMessage", {
@@ -1455,7 +1203,6 @@ async function send(transport, chatId, text, keyboard, entities, silent) {
1455
1203
  text,
1456
1204
  ...(entities === undefined ? {} : { entities }),
1457
1205
  link_preview_options: { is_disabled: true },
1458
- // A new quiet card arrives without a sound; only a ping should buzz.
1459
1206
  ...(silent === true ? { disable_notification: true } : {}),
1460
1207
  ...(keyboard === undefined ? {} : { reply_markup: { inline_keyboard: keyboard } }),
1461
1208
  });
@@ -1479,8 +1226,6 @@ async function editProgress(transport, chatId, messageId, text, keyboard, entiti
1479
1226
  catch {
1480
1227
  return { ok: false, error: "Telegram progress update is unconfirmed; it will retry in place" };
1481
1228
  }
1482
- // The retry may be repainting the same bytes after an acknowledgement was
1483
- // lost. Telegram's explicit unchanged response confirms this target state.
1484
1229
  if (!answer.ok && !answer.uncertain && /^Bad Request: message is not modified\b/i.test(answer.description ?? ""))
1485
1230
  return { ok: true, messageId };
1486
1231
  if (!answer.ok) {
@@ -1492,7 +1237,6 @@ async function editProgress(transport, chatId, messageId, text, keyboard, entiti
1492
1237
  const confirmed = answer.result?.message_id;
1493
1238
  return String(confirmed) === messageId ? { ok: true, messageId } : { ok: false, error: "Telegram did not confirm the progress message identity" };
1494
1239
  }
1495
- /** A tapped message's own formatting, read back for its edit: only bold and links that still fall inside the text. */
1496
1240
  function keptEntities(raw, length) {
1497
1241
  return (raw ?? []).flatMap((one) => {
1498
1242
  if (typeof one !== "object" || one === null)
@@ -1525,34 +1269,25 @@ function taskOf(store, decision) {
1525
1269
  const run = store.getRun(decision.run);
1526
1270
  return run === null ? "?" : store.externalIdFor(run.taskRef) ?? "?";
1527
1271
  }
1528
- async function drainUpdates(store, botId, transport, owner, generation, cursor, clock, report, pollSeconds = 0, signal, readProjects, conversation,
1529
- /** True when the poll was ended on purpose for a delivery: an answer that failed then is that abort, not the wire. */
1530
- deliveryWake) {
1272
+ async function drainUpdates(store, botId, transport, owner, generation, cursor, clock, report, pollSeconds = 0, signal, readProjects, conversation, deliveryWake) {
1531
1273
  const context = { store, botId, transport, clock, report, readProjects, conversation, projects: null };
1532
1274
  let offset = cursor + 1;
1533
1275
  for (let page = 0; page < PAGE_BUDGET; page++) {
1534
1276
  const answer = await transport("getUpdates", {
1535
1277
  offset,
1536
- // Only the first page long-polls; a backlog drains at full speed.
1537
1278
  timeout: page === 0 ? pollSeconds : 0,
1538
1279
  allowed_updates: ["message", "callback_query"],
1539
1280
  }, signal);
1540
1281
  if (!answer.ok) {
1541
- // Ended on purpose so a due message goes out now: no problem, no backoff; the next cycle asks again from the
1542
- // same cursor, so nothing is lost.
1543
1282
  if (deliveryWake?.() === true) {
1544
1283
  report.deliveryWake = true;
1545
1284
  return;
1546
1285
  }
1547
1286
  const said = answer.description ?? "failed";
1548
- // v98: another program asked Telegram for this bot's updates, and Telegram ended our
1549
- // request in its favour. Nothing is lost: an update is only gone once someone
1550
- // confirms it, and the next request asks again. Not a problem to report.
1551
1287
  if (/terminated by other getUpdates/i.test(said)) {
1552
1288
  report.contention = (report.contention ?? 0) + 1;
1553
1289
  return;
1554
1290
  }
1555
- // Telegram is pushing this bot's updates to a webhook: polling isn't how they arrive now.
1556
1291
  if (/webhook is active/i.test(said)) {
1557
1292
  report.webhookActive = true;
1558
1293
  return;
@@ -1566,7 +1301,6 @@ deliveryWake) {
1566
1301
  for (const raw of updates) {
1567
1302
  const update = readTelegramUpdate(raw);
1568
1303
  if (!update.ok) {
1569
- // Telegram's own update in a shape this bridge doesn't read: said, and passed over so the next one is read.
1570
1304
  const id = raw?.update_id;
1571
1305
  report.problems.push(`an update Telegram sent couldn't be read: ${update.issues.map(issue => issue.line).join("; ")}`);
1572
1306
  if (typeof id !== "number" || !Number.isSafeInteger(id))
@@ -1578,24 +1312,11 @@ deliveryWake) {
1578
1312
  offset = update.value.update_id + 1;
1579
1313
  }
1580
1314
  }
1581
- // The budget ran out with Telegram still holding pages: said, not hidden.
1582
1315
  report.backlog = true;
1583
1316
  }
1584
- /**
1585
- * One update, polled or pushed (v98): the projects it may read, applied in
1586
- * its own transaction (once: applyUpdate refuses an update id it has seen),
1587
- * its Telegram-side effects, and the cursor moved past it.
1588
- */
1589
1317
  async function processUpdate(context, update, owner, generation) {
1590
- // A proposal tap confirms as a principal minted against the CURRENT
1591
- // enrolled ceiling, and the registry is a file read: it happens
1592
- // before the update's transaction, and only once the envelope has
1593
- // proved the exact paired sender and chat — a stranger reads nothing.
1594
1318
  context.projects = update.message !== undefined ? await enrolledForMessage(context, update) : await projectsForTap(context, update);
1595
1319
  const effects = applyUpdate(context, update);
1596
- // Effects are Telegram-side conveniences — acks, edits, replies. They
1597
- // retry-or-drop; they never decide whether the cursor moves, because
1598
- // an unreachable edit must not make the bridge re-apply an answer.
1599
1320
  for (const effect of effects) {
1600
1321
  try {
1601
1322
  await effect();
@@ -1606,7 +1327,6 @@ async function processUpdate(context, update, owner, generation) {
1606
1327
  }
1607
1328
  context.store.advanceBridgeCursor(context.botId, owner, generation, update.update_id, context.clock());
1608
1329
  }
1609
- /** v98: updates Telegram pushed to /hooks/telegram, applied in order through the same door as polled ones. */
1610
1330
  async function drainInbox(context, owner, generation) {
1611
1331
  let applied = 0;
1612
1332
  for (const queued of context.store.telegramInbox(context.botId, PAGE_BUDGET * 100)) {
@@ -1620,17 +1340,10 @@ async function drainInbox(context, owner, generation) {
1620
1340
  }
1621
1341
  return applied;
1622
1342
  }
1623
- /** The enrolled registry, read before a message is applied: the team layer
1624
- * scopes leads and conversations to it (each person's own access is checked
1625
- * inside the domain). Unreadable reads as null, and the personal paths stay
1626
- * exactly as they were. */
1627
1343
  async function enrolledForMessage(context, update) {
1628
1344
  const message = update.message;
1629
1345
  if (message?.chat === undefined || message.from === undefined || message.text === undefined || context.readProjects === undefined)
1630
1346
  return null;
1631
- // An untrusted envelope reads nothing: the sender must be paired, the
1632
- // text plain and direct, and the chat either that person's own private
1633
- // chat or a group that follows (or is being pointed at) a conversation.
1634
1347
  if (message.forward_origin !== undefined || message.forward_date !== undefined || message.via_bot !== undefined || message.sender_chat !== undefined || message.caption !== undefined)
1635
1348
  return null;
1636
1349
  const binding = context.store.liveTelegramBindingFor(context.botId, String(message.from.id));
@@ -1652,17 +1365,14 @@ async function enrolledForMessage(context, update) {
1652
1365
  }
1653
1366
  async function projectsForTap(context, update) {
1654
1367
  const callback = update.callback_query;
1655
- // Flow decision buttons (v86) work with or without the lead's conversation on this phone.
1656
1368
  const flowTap = callback !== undefined && (context.store.getTelegramFlowAction(callback.data ?? "") !== null || context.store.getTelegramFlowChoice(callback.data ?? "") !== null
1657
1369
  || flowConfirmOf(context.store, callback.data ?? "") !== null);
1658
- // So do a result's, plan's or pull request's own buttons (chat-decide.ts).
1659
1370
  const decideTap = callback !== undefined && isDecideToken(context.store, callback.data ?? "");
1660
1371
  if (callback === undefined || context.readProjects === undefined || (context.conversation === undefined && !flowTap && !decideTap))
1661
1372
  return null;
1662
1373
  const binding = callback.from === undefined ? null : context.store.liveTelegramBindingFor(context.botId, String(callback.from.id));
1663
1374
  if (binding === null || callback.from === undefined ||
1664
1375
  callback.message?.chat === undefined ||
1665
- // Proposal cards and task picks read the chat's project ceiling.
1666
1376
  (context.store.getTelegramProposalAction(callback.data ?? "") === null && !flowTap && !decideTap && !(callback.data ?? "").startsWith("pick:")))
1667
1377
  return null;
1668
1378
  const chat = callback.message.chat;
@@ -1677,18 +1387,10 @@ async function projectsForTap(context, update) {
1677
1387
  return null;
1678
1388
  }
1679
1389
  }
1680
- /**
1681
- * Apply one update in one transaction; return the Telegram-side effects to
1682
- * attempt afterwards. Everything suspicious lands in the same place:
1683
- * `ignored`, silently — an unbound stranger learns nothing, including
1684
- * whether there was anything to learn.
1685
- */
1686
1390
  function applyUpdate(context, update) {
1687
1391
  const effects = [];
1688
1392
  context.store.transact(() => {
1689
1393
  if (!context.store.markTelegramUpdateApplied(update.update_id, "seen", context.clock())) {
1690
- // Already applied by an earlier pass. The local mutation happened;
1691
- // the edits were attempted then; nothing repeats.
1692
1394
  return;
1693
1395
  }
1694
1396
  if (update.message !== undefined) {
@@ -1703,7 +1405,6 @@ function applyUpdate(context, update) {
1703
1405
  });
1704
1406
  return effects;
1705
1407
  }
1706
- /** A group message that connects the group to a flow, or that the group's flow takes as a card. False: not for an inbox. */
1707
1408
  function applyGroupInbox(context, message, effects) {
1708
1409
  const { store, botId, transport, clock } = context;
1709
1410
  const chatId = String(message.chat.id), text = message.text ?? "";
@@ -1733,7 +1434,6 @@ function applyGroupInbox(context, message, effects) {
1733
1434
  const trigger = watchedChannel(store, "telegram", botId, chatId);
1734
1435
  if (trigger === null)
1735
1436
  return false;
1736
- // Forwards, other bots and channel posts don't become cards: only people writing in the group.
1737
1437
  if (message.forward_origin !== undefined || message.forward_date !== undefined || message.via_bot !== undefined || message.sender_chat !== undefined) {
1738
1438
  context.report.ignored++;
1739
1439
  return true;
@@ -1752,13 +1452,9 @@ function applyMessage(context, update, effects) {
1752
1452
  const chat = message.chat;
1753
1453
  const from = message.from;
1754
1454
  const pair = /^\/pair\s+([0-9a-f]{32})\s*$/.exec(message.text ?? "");
1755
- // A group as a flow's inbox (v89): "/flow 12" from a paired approver connects it; after that its messages are cards.
1756
1455
  if (pair === null && chat !== undefined && from !== undefined && (chat.type === "group" || chat.type === "supergroup") && typeof message.text === "string" && applyGroupInbox(context, message, effects))
1757
1456
  return;
1758
1457
  if (pair === null && chat !== undefined && from !== undefined) {
1759
- // The team layer first: `/team` anywhere, everything in a followed
1760
- // group, and a private chat that chose a conversation. Its replies ride
1761
- // the same post-commit effects as every other answer.
1762
1458
  const consumed = applyTeamInbound({
1763
1459
  store, botId, now: clock(), report, projects: context.projects, phoneOrigin: context.conversation?.phoneOrigin, updateId: update.update_id, message,
1764
1460
  say: (chatId, text, keyboard) => {
@@ -1770,23 +1466,13 @@ function applyMessage(context, update, effects) {
1770
1466
  });
1771
1467
  if (consumed)
1772
1468
  return;
1773
- // Replies to decisions retain their existing note meaning, even if the
1774
- // note starts with a slash. New read commands are direct messages only.
1775
- // A bare "start" as the very next message after a Start card is that card's yes (docs/plans/one-step-chat.md C5),
1776
- // not the help command. Only the routing is decided here, by the same ids the message path reads again when it
1777
- // records the yes; "/start", and "start" anywhere else, stay help.
1778
1469
  const yesSeat = message.reply_to_message === undefined && chat.type === "private" && typeof message.text === "string" && typedYes(message.text)
1779
1470
  && context.conversation !== undefined && context.readProjects !== undefined ? store.liveTelegramBindingFor(botId, String(from.id)) : null;
1780
1471
  const answersStartCard = yesSeat !== null && String(chat.id) === yesSeat.chatId
1781
1472
  && typedStartCard(store, { binding: yesSeat.id, chatId: yesSeat.chatId, approver: yesSeat.approver }, { id: String(message.message_id), replyTo: null }) !== null;
1782
1473
  if (message.reply_to_message === undefined && !answersStartCard && applyPhoneRead(context, update, effects))
1783
1474
  return;
1784
- // A reply to a decision message this bot sent is a note, exactly as
1785
- // before. Everything else that is ordinary text talks to the shared
1786
- // assistant when a conversation is configured; otherwise silence.
1787
1475
  const binding = store.liveTelegramBindingFor(botId, String(from.id));
1788
- // A reply to an Edit or Send back prompt (v86): the new draft, or the note it goes back with.
1789
- // A reply to a subagent's "Answer in words" prompt (v93): the answer.
1790
1476
  const questionPrompt = binding !== null && message.reply_to_message !== undefined && String(chat.id) === binding.chatId
1791
1477
  ? store.telegramQuestionPrompt(binding.chatId, String(message.reply_to_message.message_id), clock()) : null;
1792
1478
  if (binding !== null && questionPrompt !== null) {
@@ -1811,8 +1497,6 @@ function applyMessage(context, update, effects) {
1811
1497
  }
1812
1498
  return;
1813
1499
  }
1814
- // After Request changes asked "What should change?": the person's next message in their own chat is the feedback.
1815
- // A reply to some other message (a decision, a result) keeps its own meaning.
1816
1500
  const decidePrompt = binding !== null && chat.type === "private" && String(chat.id) === binding.chatId && typeof message.text === "string" && message.text.trim() !== "" && !message.text.startsWith("/")
1817
1501
  ? openPromptFor(store, { channel: "telegram", binding: binding.id, chat: binding.chatId }, clock()) : null;
1818
1502
  if (binding !== null && decidePrompt !== null && answersPrompt(decidePrompt, message.reply_to_message === undefined ? null : String(message.reply_to_message.message_id))) {
@@ -1831,7 +1515,6 @@ function applyMessage(context, update, effects) {
1831
1515
  });
1832
1516
  return;
1833
1517
  }
1834
- // D5: a message naming a subagent ("@rosa …") goes to the lead like any other, which asks the subagent with a card.
1835
1518
  const repliedDecision = binding !== null && message.reply_to_message !== undefined
1836
1519
  ? store.decisionForTelegramMessage(binding.id, binding.chatId, String(message.reply_to_message.message_id))
1837
1520
  : null;
@@ -1842,9 +1525,6 @@ function applyMessage(context, update, effects) {
1842
1525
  applyNote(context, update, effects);
1843
1526
  return;
1844
1527
  }
1845
- // Only /pair, only in a private chat, only with the sender on the record.
1846
- // A group is exactly where "the chat" and "the person" diverge, which is
1847
- // why a group cannot pair at all.
1848
1528
  if (pair === null || chat === undefined || chat.type !== "private" || from === undefined) {
1849
1529
  report.ignored++;
1850
1530
  return;
@@ -1857,8 +1537,6 @@ function applyMessage(context, update, effects) {
1857
1537
  updateId: update.update_id,
1858
1538
  }, clock());
1859
1539
  if (!consumed.ok) {
1860
- // A wrong code gets the same silence as everything else wrong: replying
1861
- // "no such code" to a guesser is an oracle.
1862
1540
  report.ignored++;
1863
1541
  return;
1864
1542
  }
@@ -1866,27 +1544,14 @@ function applyMessage(context, update, effects) {
1866
1544
  const chatId = String(chat.id);
1867
1545
  const approver = consumed.binding.approver;
1868
1546
  effects.push(async () => {
1869
- // At-least-once across a crash-after-send window, by design: a repeated
1870
- // "paired" line is annoying; a paired chat that never heard so is worse.
1871
1547
  await transport("sendMessage", {
1872
1548
  chat_id: chatId,
1873
1549
  text: `paired: this chat now answers as ${approver}\n\nSend /status to check recent work, /task <id> for one task, or /help for your options.`,
1874
1550
  link_preview_options: { is_disabled: true },
1875
1551
  });
1876
- // The bot is Toolroll in every chat list from here on (best effort; pairing never waits on it).
1877
1552
  await nameTelegramBot(transport, "pairing");
1878
1553
  });
1879
1554
  }
1880
- /**
1881
- * An ordinary message from the paired person: persisted for the shared
1882
- * assistant in THIS transaction — before the cursor moves — with the exact
1883
- * binding, sender, update, message and the request identity the engine
1884
- * receipts its turn under. Two things are answered here and now without a
1885
- * model: text over the engine's bound (never truncated), and a reply to a
1886
- * message that carried several tasks (never guessed). Everything hostile is
1887
- * silence, as for every other inbound shape.
1888
- */
1889
- /** At most this many of a chat's messages wait for the lead at once (the personal lead queue's bound). */
1890
1555
  export const TELEGRAM_MAX_WAITING = 10;
1891
1556
  function applyConversation(context, update, effects) {
1892
1557
  const { store, botId, transport, clock, report } = context;
@@ -1923,8 +1588,6 @@ function applyConversation(context, update, effects) {
1923
1588
  report.chatRefused = (report.chatRefused ?? 0) + 1;
1924
1589
  return;
1925
1590
  }
1926
- // A reply binds to what the replied-to message carried: exactly one task
1927
- // (and its run) pins the turn; several ask which; none is a plain turn.
1928
1591
  let context_ = null;
1929
1592
  let taskId = null;
1930
1593
  let sourceRun = null;
@@ -1943,8 +1606,6 @@ function applyConversation(context, update, effects) {
1943
1606
  context_ = replyContextFor(taskId, sourceRun, bindings.find(one => one.image !== undefined)?.image);
1944
1607
  }
1945
1608
  }
1946
- // No reply target: the task this chat chose to talk about, if any. The
1947
- // turn re-proves it; a task no longer in reach reads as a plain message.
1948
1609
  if (taskId === null) {
1949
1610
  const focused = store.chatFocus("telegram", binding.id);
1950
1611
  if (focused !== null) {
@@ -1952,16 +1613,11 @@ function applyConversation(context, update, effects) {
1952
1613
  context_ = focusContextFor(focused);
1953
1614
  }
1954
1615
  }
1955
- // The lead queue's bound, per chat: ten messages wait at most; the next is answered at once instead of queued.
1956
1616
  if (store.telegramMessagesWaiting(binding.id) >= TELEGRAM_MAX_WAITING) {
1957
1617
  say(`${TELEGRAM_MAX_WAITING} messages are already waiting for the lead. Wait for a reply, then send this again.`);
1958
1618
  report.ignored++;
1959
1619
  return;
1960
1620
  }
1961
- // A typed yes to a Start card (docs/plans/one-step-chat.md C5) is read here, before any model runs, and recorded with
1962
- // the message in the same transaction: the fixed words only, tied to one exact card by message ids and Toolroll's own
1963
- // delivery record. The worker acts on it (confirmTypedStart) and no lead turn runs for it. Anything else is queued for
1964
- // the lead exactly as before.
1965
1621
  store.transact(() => {
1966
1622
  const typed = typedYes(text) ? typedStartCard(store, { binding: binding.id, chatId: binding.chatId, approver: binding.approver }, { id: String(message.message_id), replyTo }) : null;
1967
1623
  store.enqueueTelegramConversation({
@@ -1972,9 +1628,6 @@ function applyConversation(context, update, effects) {
1972
1628
  recordTypedStart(store, `m${update.update_id}`, typed, clock());
1973
1629
  });
1974
1630
  report.chatQueued = (report.chatQueued ?? 0) + 1;
1975
- // Saved: 👀 on the owner's message right away (docs/plans/responsive-chat.md §3.1), once this update's transaction
1976
- // has committed. It comes off when the answer or the failure notice is delivered. Never awaited: a burst of messages
1977
- // waits its turn on the chat's own lane, not the drain.
1978
1631
  const gapMs = context.conversation?.liveTiming?.ackGapMs;
1979
1632
  effects.push(async () => {
1980
1633
  void telegramAck({
@@ -1986,9 +1639,6 @@ function applyConversation(context, update, effects) {
1986
1639
  });
1987
1640
  });
1988
1641
  }
1989
- /** The picker's buttons: one task per row (its title and where it stands),
1990
- * carried by the task's numeric reference so the data fits Telegram's 64
1991
- * bytes; a tap re-proves the task against the ceiling. */
1992
1642
  function pickKeyboard(store, choices, focused) {
1993
1643
  const rows = [];
1994
1644
  for (const one of choices) {
@@ -2000,7 +1650,6 @@ function pickKeyboard(store, choices, focused) {
2000
1650
  rows.push([telegramButton("Back to the lead", "pick:lead")]);
2001
1651
  return rows;
2002
1652
  }
2003
- /** The title of the task this Telegram chat chose to talk about, if any. */
2004
1653
  function focusedTitle(store, binding) {
2005
1654
  const id = store.chatFocus("telegram", binding.id);
2006
1655
  return id === null ? null : { id, title: phoneText(store.getTask(id)?.title ?? id, 64) };
@@ -2020,8 +1669,6 @@ function applyPhoneRead(context, update, effects) {
2020
1669
  report.ignored++;
2021
1670
  return true;
2022
1671
  }
2023
- // Like decision-message edits, a read reply is best-effort after the update
2024
- // was consumed. A crash or send failure cannot turn replay into a new action.
2025
1672
  effects.push(async () => {
2026
1673
  const stillPaired = () => {
2027
1674
  const live = store.liveTelegramBindingById(binding.id);
@@ -2030,12 +1677,8 @@ function applyPhoneRead(context, update, effects) {
2030
1677
  if (!stillPaired())
2031
1678
  return;
2032
1679
  let response = PHONE_HELP;
2033
- // `/task` may carry ONE url button to the exact recorded task or result:
2034
- // minted from the trusted origin read now, never persisted, never a token.
2035
1680
  let button = null;
2036
- // `/tasks` and an ambiguous `/task <name>` offer tasks as buttons.
2037
1681
  let keyboard = null;
2038
- // The one task (and saved result) a `/task` reply shows: a reply to it is about that task.
2039
1682
  let shown = null;
2040
1683
  if (command.kind === "lead") {
2041
1684
  store.setChatFocus("telegram", binding.id, null, clock());
@@ -2043,9 +1686,6 @@ function applyPhoneRead(context, update, effects) {
2043
1686
  }
2044
1687
  else if (command.kind !== "help") {
2045
1688
  try {
2046
- // The registry, then — after the await — the pairing again and the
2047
- // account's OWN ceiling over it: a project this approver was never
2048
- // given, or lost since, is not read, named or linked from here.
2049
1689
  const registry = await context.readProjects?.() ?? [];
2050
1690
  if (!stillPaired())
2051
1691
  return;
@@ -2072,22 +1712,17 @@ function applyPhoneRead(context, update, effects) {
2072
1712
  const view = phoneTaskView(store, repos, pick.view, clock(), context.conversation?.evidenceRoot);
2073
1713
  shown = { task: pick.view, run: view.run };
2074
1714
  button = phoneLinkButton(context.conversation?.phoneOrigin?.() ?? null, view.link);
2075
- // A destination with no trusted origin to carry it: the words say where instead.
2076
1715
  response = phoneFocusText(button === null && view.link !== null ? `${view.text}\n\n${PHONE_CONSOLE_FOOTER}` : view.text);
2077
1716
  }
2078
1717
  }
2079
1718
  }
2080
1719
  catch {
2081
- // No registry paths, SQLite errors, credentials, or stale snapshots
2082
- // leave on the failure road. A new request can try again.
2083
1720
  response = "I couldn't read the current project status. No tasks were changed. Try /status again; if it persists, check Toolroll on the computer.";
2084
1721
  report.problems.push("phone status could not read the current project records");
2085
1722
  }
2086
1723
  }
2087
1724
  if (!stillPaired())
2088
1725
  return;
2089
- // Each view fits one message. Fail visibly if a future change violates
2090
- // that contract, rather than cutting off the important next action.
2091
1726
  if (response.length > PART_CAP) {
2092
1727
  response = "This status is too large for one phone message. Open the console for the full view, or send /task <id> for one task.";
2093
1728
  report.problems.push("phone status exceeded its message bound");
@@ -2105,24 +1740,14 @@ function applyPhoneRead(context, update, effects) {
2105
1740
  report.problems.push(`phone status reply failed for update ${update.update_id}; send a new command to retry`);
2106
1741
  const sentId = sent.ok ? sent.result?.message_id : undefined;
2107
1742
  if (shown !== null && typeof sentId === "number" && Number.isSafeInteger(sentId) && sentId > 0) {
2108
- // Best effort: without it a reply still reaches the chosen task through the focus.
2109
1743
  try {
2110
1744
  store.recordTelegramTaskMessage(binding, String(sentId), shown.task, shown.run, clock());
2111
1745
  }
2112
- catch { /* the focus still holds */ }
1746
+ catch { }
2113
1747
  }
2114
1748
  });
2115
1749
  return true;
2116
1750
  }
2117
- /**
2118
- * A free-text note, accepted only as an AUTHENTICATED REPLY to a recorded
2119
- * decision message (Codex free-text review, prescribed design): live
2120
- * binding, private chat, exact chat AND user, a reply_to that maps to
2121
- * exactly one decision this bot sent, the decision still unanswered, and
2122
- * direct initial plain text — no forwards, media, captions, bots, or
2123
- * channel identities. Everything else is silence: a reply naming what was
2124
- * wrong is an oracle. Choice stays TAP-ONLY; prose never selects an option.
2125
- */
2126
1751
  function applyNote(context, update, effects) {
2127
1752
  const { store, botId, transport, clock, report } = context;
2128
1753
  const message = update.message;
@@ -2155,8 +1780,6 @@ function applyNote(context, update, effects) {
2155
1780
  }
2156
1781
  const decisionId = store.decisionForTelegramMessage(binding.id, binding.chatId, String(message.reply_to_message.message_id));
2157
1782
  if (decisionId === null) {
2158
- // A reply to something that never carried a decision — including a
2159
- // send whose record was lost: fail closed, never guess by recency.
2160
1783
  report.ignored++;
2161
1784
  return;
2162
1785
  }
@@ -2185,16 +1808,11 @@ function applyNote(context, update, effects) {
2185
1808
  note: valid.note,
2186
1809
  }, clock());
2187
1810
  if (!saved) {
2188
- // An older or equal update raced in late: the newer note stands.
2189
1811
  report.ignored++;
2190
1812
  return;
2191
1813
  }
2192
- // A new note voids any ARMED irreversible confirmation: what it showed
2193
- // is no longer what would travel (Codex free-text review, finding 3).
2194
1814
  store.consumeTelegramChallenges(decision.id, clock());
2195
1815
  report.noted = (report.noted ?? 0) + 1;
2196
- // The echo IS the ceremony: the exact captured text, line-prefixed, so a
2197
- // later edit of the operator's own message cannot rewrite the audit.
2198
1816
  say([
2199
1817
  `noted for ${taskOf(store, decision)}:`,
2200
1818
  ...valid.note.split("\n").map((line) => `| ${line}`),
@@ -2234,15 +1852,9 @@ function applyCallback(context, update, effects) {
2234
1852
  });
2235
1853
  });
2236
1854
  };
2237
- // The person, the chat, and the message must all be the paired ones. A
2238
- // callback with no accessible message (inline mode, too-old messages) is
2239
- // out; so is a tap from anyone but the exact paired user id — usernames
2240
- // change hands, immutable ids do not.
2241
1855
  const binding = from === undefined ? null : store.liveTelegramBindingFor(botId, String(from.id));
2242
1856
  const tapChat = message?.chat === undefined ? null : String(message.chat.id);
2243
1857
  const followedGroup = tapChat !== null && binding !== null && tapChat !== binding.chatId && store.telegramTeamChat(botId, tapChat)?.kind === "group";
2244
- // A result's, plan's, failure's or pull request's own buttons act only in the paired person's own chat; a tap
2245
- // anywhere else is still answered, so the button never just spins.
2246
1858
  if (isDecideToken(store, token) && (binding === null || tapChat === null || tapChat !== binding.chatId)) {
2247
1859
  report.ignored++;
2248
1860
  ack(binding === null ? "These buttons work only for the person they were sent to. Nothing was done."
@@ -2257,16 +1869,12 @@ function applyCallback(context, update, effects) {
2257
1869
  report.ignored++;
2258
1870
  return;
2259
1871
  }
2260
- // The paired person, in their chat: a button whose data isn't one Toolroll makes is answered with why, and does nothing.
2261
1872
  const data = readTelegramButtonData(callback.data);
2262
1873
  if (!data.ok) {
2263
1874
  report.ignored++;
2264
1875
  ack(`That button couldn't be read (${data.issues.map(issue => issue.line).join("; ")}). Nothing was done.`.slice(0, 190));
2265
1876
  return;
2266
1877
  }
2267
- // A task picked from /tasks: this private chat now talks about it (or,
2268
- // "Back to the lead", about everything again). The task is re-proved
2269
- // against the chat's ceiling at the tap.
2270
1878
  const pick = pickOf(token);
2271
1879
  if (pick !== null) {
2272
1880
  if (tapChat !== binding.chatId) {
@@ -2297,7 +1905,6 @@ function applyCallback(context, update, effects) {
2297
1905
  editText(phoneFocusText(view.text), [[telegramButton("Back to the lead", "pick:lead")]]);
2298
1906
  return;
2299
1907
  }
2300
- // A subagent's question (v93): an option answers it; "Answer in words" asks for a reply.
2301
1908
  const questionAction = store.getTelegramQuestionAction(token);
2302
1909
  if (questionAction !== null) {
2303
1910
  if (questionAction.binding !== binding.id || questionAction.chatId !== tapChat || (questionAction.messageId !== null && questionAction.messageId !== String(message.message_id))) {
@@ -2320,13 +1927,11 @@ function applyCallback(context, update, effects) {
2320
1927
  }
2321
1928
  return;
2322
1929
  }
2323
- // A flow decision's repaint: its buttons (fresh ones stamped on this message) or links under the console.
2324
1930
  const flowEdit = (effect) => {
2325
1931
  if (effect.place !== undefined && effect.place.length > 0)
2326
1932
  store.placeTelegramFlowActions(effect.place, String(message.message_id));
2327
1933
  editText(effect.text, decideKeyboard(context.conversation?.phoneOrigin, effect.keyboard ?? []));
2328
1934
  };
2329
- // The Yes or Cancel a flow Approve armed (telegram-flow.ts): on the message it was armed on, by the person it was armed for.
2330
1935
  const flowConfirm = flowConfirmOf(store, token);
2331
1936
  if (flowConfirm !== null) {
2332
1937
  if (flowConfirm.binding !== binding.id || flowConfirm.chatId !== tapChat || flowConfirm.messageId !== String(message.message_id)) {
@@ -2358,7 +1963,6 @@ function applyCallback(context, update, effects) {
2358
1963
  flowEdit(effect);
2359
1964
  else
2360
1965
  effects.push(async () => {
2361
- // A reply box: whatever they send back as a reply to this prompt is the new draft, or the note.
2362
1966
  const answer = await transport("sendMessage", { chat_id: binding.chatId, text: effect.text, link_preview_options: { is_disabled: true },
2363
1967
  reply_parameters: { message_id: message.message_id }, reply_markup: { force_reply: true, input_field_placeholder: effect.placeholder } });
2364
1968
  const id = answer.result?.message_id;
@@ -2368,7 +1972,6 @@ function applyCallback(context, update, effects) {
2368
1972
  }
2369
1973
  return;
2370
1974
  }
2371
- // A "Person chooses" option (flow-send.ts): the card goes where it leads, or is ignored.
2372
1975
  const choiceAction = store.getTelegramFlowChoice(token);
2373
1976
  if (choiceAction !== null) {
2374
1977
  if (choiceAction.binding !== binding.id || choiceAction.chatId !== tapChat || (choiceAction.messageId !== null && choiceAction.messageId !== String(message.message_id))) {
@@ -2380,13 +1983,11 @@ function applyCallback(context, update, effects) {
2380
1983
  for (const effect of applyFlowChoiceTap(store, binding, choiceAction, { text: message.text ?? "" }, repos, clock())) {
2381
1984
  if (effect.kind === "ack")
2382
1985
  ack(effect.text);
2383
- // An item list's message (flow-items.ts) keeps its bold titles and labelled links under what was chosen; any other stays plain.
2384
1986
  else if (effect.kind === "edit")
2385
1987
  editText(effect.text, undefined, listed ? keptEntities(message.entities, effect.text.length) : undefined);
2386
1988
  }
2387
1989
  return;
2388
1990
  }
2389
- // The lead's question to its owner: an option is sent as their next message; "Something else" asks them to type it.
2390
1991
  const askTap = askOf(token);
2391
1992
  if (askTap !== null) {
2392
1993
  if (tapChat !== binding.chatId || context.conversation === undefined) {
@@ -2430,7 +2031,6 @@ function applyCallback(context, update, effects) {
2430
2031
  editText(`${message.text ?? ask.question}\n\nYou chose: ${option}`.slice(0, 4000));
2431
2032
  return;
2432
2033
  }
2433
- // A result's, plan's, failure's or pull request's own buttons (chat-decide.ts): in the person's own chat only.
2434
2034
  if (isDecideToken(store, token)) {
2435
2035
  const repos = context.projects === null ? null : telegramConversationRepos(store, binding.approver, context.projects);
2436
2036
  if (repos === null) {
@@ -2447,8 +2047,6 @@ function applyCallback(context, update, effects) {
2447
2047
  if (tapped.ignored === true)
2448
2048
  report.ignored++;
2449
2049
  ack(tapped.ack.slice(0, 190));
2450
- // A release card's terms, as a file, before its Approve is shown (chat-management.md §0a.5): Approve appears only
2451
- // once Telegram has accepted this file; a refused or failed upload shows the card without it, Continue to try again.
2452
2050
  if (tapped.file !== undefined && tapped.edit !== undefined && tapped.unsent !== undefined) {
2453
2051
  const file = tapped.file, edit = tapped.edit, unsent = tapped.unsent;
2454
2052
  effects.push(async () => {
@@ -2466,7 +2064,6 @@ function applyCallback(context, update, effects) {
2466
2064
  });
2467
2065
  }
2468
2066
  else if (tapped.file !== undefined) {
2469
- // A file without its gate never reaches here (chat-decide pairs them); fail closed: nothing that approves is shown.
2470
2067
  if (tapped.edit !== undefined)
2471
2068
  dropDecideTokens(store, tapped.edit.tokens, clock());
2472
2069
  editText(`${message.text ?? ""}\n\nThis release can't be approved here. Open it in Toolroll.`.trim().slice(0, 4000), []);
@@ -2485,7 +2082,6 @@ function applyCallback(context, update, effects) {
2485
2082
  }
2486
2083
  if (tapped.merge !== undefined) {
2487
2084
  const merge = tapped.merge, shown = tapped.edit?.text ?? message.text ?? "";
2488
- // GitHub is a network call: after the tap's transaction, then the card says how it went.
2489
2085
  effects.push(async () => {
2490
2086
  let merged;
2491
2087
  try {
@@ -2495,9 +2091,7 @@ function applyCallback(context, update, effects) {
2495
2091
  catch {
2496
2092
  merged = { ok: false, message: "GitHub couldn't be reached just now. Try again from the task." };
2497
2093
  }
2498
- // The ledger says what happened, failure included, once GitHub has answered.
2499
2094
  recordChatMerge(store, merge, merged.ok ? { ok: true } : { ok: false, message: merged.message }, clock());
2500
- // A merge that didn't land keeps a way to the task.
2501
2095
  await transport("editMessageText", { chat_id: binding.chatId, message_id: message.message_id, text: mergedText(shown, merged.ok ? { ok: true } : { ok: false, message: merged.message }).slice(0, 4000),
2502
2096
  link_preview_options: { is_disabled: true }, reply_markup: { inline_keyboard: merged.ok ? [] : decideKeyboard(context.conversation?.phoneOrigin, linksFor({ kind: "merge", taskId: merge.taskId, run: merge.runId })) } });
2503
2097
  });
@@ -2506,9 +2100,6 @@ function applyCallback(context, update, effects) {
2506
2100
  }
2507
2101
  const action = store.getTelegramAction(token);
2508
2102
  if (action === null && context.conversation !== undefined && store.getTelegramProposalAction(token) !== null) {
2509
- // A proposal card's button: the shared confirm door, inside this
2510
- // update's transaction, with the stop's process signal deferred to
2511
- // after its commit (the door's own ordering, preserved from here).
2512
2103
  const tapped = applyProposalTap(store, binding, token, message, context.projects, context.conversation, clock());
2513
2104
  for (const effect of tapped.effects) {
2514
2105
  if (effect.kind === "ack")
@@ -2528,7 +2119,6 @@ function applyCallback(context, update, effects) {
2528
2119
  action.binding !== binding.id ||
2529
2120
  action.chatId !== binding.chatId ||
2530
2121
  (action.messageId !== null && action.messageId !== String(message.message_id))) {
2531
- // Bound person, dead or foreign button: acknowledged, not acted on.
2532
2122
  ack("that button is stale — toolroll decide shows what still waits");
2533
2123
  report.ignored++;
2534
2124
  return;
@@ -2551,8 +2141,6 @@ function applyCallback(context, update, effects) {
2551
2141
  return;
2552
2142
  }
2553
2143
  if (expiredDraftGuard(store, binding, decision.id, clock())) {
2554
- // The token is NOT consumed: the same button answers on the next tap,
2555
- // now that the operator knows the note is gone.
2556
2144
  ack("your note expired — tap again to answer without it, or reply with a fresh note first");
2557
2145
  return;
2558
2146
  }
@@ -2561,16 +2149,9 @@ function applyCallback(context, update, effects) {
2561
2149
  return;
2562
2150
  }
2563
2151
  if (!option.reversible) {
2564
- // The arm. Nothing is answered here: two fresh one-time tokens make a
2565
- // real challenge — a stolen bot token can repaint a keyboard, but it
2566
- // cannot mint a row in this table, so a tap on a forged "confirm"
2567
- // lands in the stale-button branch above.
2568
2152
  const confirm = randomBytes(16).toString("hex");
2569
2153
  const cancel = randomBytes(16).toString("hex");
2570
2154
  const placedOn = String(message.message_id);
2571
- // The confirmation binds the EXACT answer tuple: option AND the note
2572
- // it displays (its digest; null when none). A note that changes,
2573
- // expires, or is cancelled strands this challenge (finding 3).
2574
2155
  const draft = store.liveNoteDraft(binding.id, decision.id, clock());
2575
2156
  const digest = draft === null ? undefined : noteDigestOf(draft.note);
2576
2157
  if (draft !== null)
@@ -2592,15 +2173,11 @@ function applyCallback(context, update, effects) {
2592
2173
  ack("that confirmation expired — start again from the option");
2593
2174
  return;
2594
2175
  }
2595
- // Re-proved at the moment of commitment, not remembered from the arm.
2596
2176
  const option = decision.options.find(one => one.id === action.optionId);
2597
2177
  if (option === undefined) {
2598
2178
  ack("that option no longer exists");
2599
2179
  return;
2600
2180
  }
2601
- // The tuple the challenge displayed must still be the tuple that
2602
- // travels: the CURRENT live draft's digest (or none) must equal what
2603
- // was armed. Anything else strands the yes (finding 3).
2604
2181
  const current = store.liveNoteDraft(binding.id, decision.id, clock());
2605
2182
  const currentDigest = current === null ? null : noteDigestOf(current.note);
2606
2183
  if ((action.noteDigest ?? null) !== currentDigest) {
@@ -2611,9 +2188,6 @@ function applyCallback(context, update, effects) {
2611
2188
  answerNow(context, decision, option.id, binding, ack, editText);
2612
2189
  return;
2613
2190
  }
2614
- // cancel: consume it, kill its sibling confirm, discard the note draft
2615
- // (cancel means cancelled — the note it displayed dies with it), and
2616
- // restore the choices.
2617
2191
  store.consumeTelegramAction(token, clock());
2618
2192
  store.consumeTelegramChallenges(decision.id, clock());
2619
2193
  {
@@ -2626,7 +2200,6 @@ function applyCallback(context, update, effects) {
2626
2200
  store.createTelegramAction({ token: choose, binding: binding.id, decision: decision.id, optionId: option.id, phase: "choose", chatId: binding.chatId, messageId: String(message.message_id) }, clock());
2627
2201
  }
2628
2202
  ack("cancelled");
2629
- // The card again, within one message; a decision too long for one keeps the consequences its earlier parts show.
2630
2203
  const ask = decisionAsk(decision);
2631
2204
  editText(ask.length <= PART_CAP ? ask : `Decide: ${decision.question}`, fresh.map(({ option, token: choose }) => [
2632
2205
  telegramButton(`${option.label}${option.id === decision.recommendation ? " ✓" : ""}${option.reversible ? "" : " ⚠"}`, choose),
@@ -2634,9 +2207,6 @@ function applyCallback(context, update, effects) {
2634
2207
  }
2635
2208
  function answerNow(context, decision, choice, binding, ack, editText) {
2636
2209
  const { store, clock, report } = context;
2637
- // The live draft is the note that travels — consumed WITH the answer in
2638
- // the same transaction the whole update already holds; a CAS loss
2639
- // discards it (Codex free-text review, finding 4: never choose-then-note).
2640
2210
  const draft = store.liveNoteDraft(binding.id, decision.id, clock());
2641
2211
  const answered = store.answerDecisionLocked({ id: decision.id, choice, by: binding.approver, via: "telegram", ...(draft === null ? {} : { note: draft.note }) }, clock());
2642
2212
  if (answered.ok) {
@@ -2658,7 +2228,6 @@ function answerNow(context, decision, choice, binding, ack, editText) {
2658
2228
  }
2659
2229
  ack(`could not answer: ${answered.reason}`);
2660
2230
  }
2661
- /** A decision's card, action first: the question, then each option with what it does, then its deadline. */
2662
2231
  function decisionAsk(decision) {
2663
2232
  return [
2664
2233
  `Decide: ${decision.question}`,
@@ -2666,7 +2235,6 @@ function decisionAsk(decision) {
2666
2235
  ...(decision.deadline === null ? [] : [`Decide by ${decision.deadline.slice(0, 16).replace("T", " ")} UTC`]),
2667
2236
  ].join("\n");
2668
2237
  }
2669
- /** The armed confirm of an option that can't be undone: what it is and what it does, then the note that travels. */
2670
2238
  function armedDecisionText(option, note) {
2671
2239
  return [
2672
2240
  `${option.label}? ⚠ This can't be undone.`,
@@ -2681,19 +2249,12 @@ function answeredText(store, decision) {
2681
2249
  return [
2682
2250
  `✓ Answered: ${chosen}`,
2683
2251
  `${taskOf(store, decision)} · by ${decision.answeredBy ?? "?"} via ${decision.answeredVia ?? "?"}`,
2684
- // Line-prefixed, never inline: a multiline note must not be able to
2685
- // draw fake status lines (Codex free-text review, finding 7).
2686
2252
  ...(decision.note === null ? [] : ["with note:", ...decision.note.split("\n").map(line => `| ${line}`)]),
2687
2253
  ].join("\n");
2688
2254
  }
2689
2255
  function noteDigestOf(note) {
2690
2256
  return createHash("sha256").update(note, "utf8").digest("hex").slice(0, 32);
2691
2257
  }
2692
- /**
2693
- * A pending draft that ALREADY EXPIRED must never silently drop: the tap
2694
- * proceeds only after the operator is told (Codex free-text review, state
2695
- * machine — "never silently answer without the expected note").
2696
- */
2697
2258
  function expiredDraftGuard(store, binding, decisionId, now) {
2698
2259
  const expired = store.telegramChat()
2699
2260
  .prepare(`SELECT id FROM chat_note_draft
@@ -2704,11 +2265,8 @@ function expiredDraftGuard(store, binding, decisionId, now) {
2704
2265
  store.setNoteDraftState(Number(expired["id"]), ["pending", "armed"], "discarded");
2705
2266
  return true;
2706
2267
  }
2707
- /** Bridges in this process waiting out their push idle, by bot: a kept push ends the wait early. */
2708
2268
  const bridgeWakers = new Map();
2709
- /** Bots with a push kept while no bridge idled (it was mid-cycle): the next idle doesn't wait. */
2710
2269
  const bridgeWokenEarly = new Set();
2711
- /** A pushed update was kept for this bot: wake its bridge if it runs in this process (docs/plans/responsive-chat.md §3.1). */
2712
2270
  export function wakeTelegramBridge(botId) {
2713
2271
  const wakers = bridgeWakers.get(botId);
2714
2272
  if (wakers === undefined || wakers.size === 0) {
@@ -2718,15 +2276,9 @@ export function wakeTelegramBridge(botId) {
2718
2276
  for (const wake of wakers)
2719
2277
  wake();
2720
2278
  }
2721
- /** The newest notification id now: a follower cycle's mark for what its delivery covers. */
2722
2279
  function newestNotificationIdOf(store) {
2723
2280
  return Number(store.handle.prepare("SELECT COALESCE(MAX(id), 0) AS id FROM notification").get()?.["id"] ?? 0);
2724
2281
  }
2725
- /**
2726
- * Whether a message for this bot was written after `mark` and is still due: unresolved, addressed to everyone or to a
2727
- * person paired with this bot, and the bot not held back by Telegram's rate limit. Read-only; delivery itself still
2728
- * decides each row under its own fences.
2729
- */
2730
2282
  export function telegramOutboxDue(store, botId, mark, now) {
2731
2283
  const approvers = [...new Set(store.liveTelegramBindings(botId).map(binding => binding.approver))];
2732
2284
  if (approvers.length === 0)