toolroll 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (626) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1113 -0
  3. package/THIRD_PARTY_NOTICES.md +449 -0
  4. package/dist/accent-colors.d.ts +48 -0
  5. package/dist/accent-colors.js +122 -0
  6. package/dist/action-ledger.d.ts +26 -0
  7. package/dist/action-ledger.js +75 -0
  8. package/dist/agent-fence.d.ts +42 -0
  9. package/dist/agent-fence.js +183 -0
  10. package/dist/agentconfig.d.ts +216 -0
  11. package/dist/agentconfig.js +454 -0
  12. package/dist/api-tokens.d.ts +16 -0
  13. package/dist/api-tokens.js +27 -0
  14. package/dist/approval-policy.d.ts +69 -0
  15. package/dist/approval-policy.js +137 -0
  16. package/dist/approval-rules-ui.d.ts +25 -0
  17. package/dist/approval-rules-ui.js +39 -0
  18. package/dist/assignment-adapters.d.ts +180 -0
  19. package/dist/assignment-adapters.js +239 -0
  20. package/dist/assignment-brief.d.ts +71 -0
  21. package/dist/assignment-brief.js +129 -0
  22. package/dist/assignment-delivery.d.ts +56 -0
  23. package/dist/assignment-delivery.js +160 -0
  24. package/dist/assignment-presentation.d.ts +26 -0
  25. package/dist/assignment-presentation.js +80 -0
  26. package/dist/assignment-status.d.ts +62 -0
  27. package/dist/assignment-status.js +152 -0
  28. package/dist/assignment-ui.d.ts +71 -0
  29. package/dist/assignment-ui.js +103 -0
  30. package/dist/assignment.d.ts +222 -0
  31. package/dist/assignment.js +399 -0
  32. package/dist/attest.d.ts +56 -0
  33. package/dist/attest.js +153 -0
  34. package/dist/backend.d.ts +97 -0
  35. package/dist/backend.js +166 -0
  36. package/dist/backup-ui.d.ts +22 -0
  37. package/dist/backup-ui.js +59 -0
  38. package/dist/backup.d.ts +84 -0
  39. package/dist/backup.js +421 -0
  40. package/dist/beads.d.ts +34 -0
  41. package/dist/beads.js +135 -0
  42. package/dist/bin.d.ts +2 -0
  43. package/dist/bin.js +22 -0
  44. package/dist/board.d.ts +150 -0
  45. package/dist/board.js +210 -0
  46. package/dist/boot-identity.d.ts +63 -0
  47. package/dist/boot-identity.js +99 -0
  48. package/dist/browser/THIRD_PARTY_NOTICES.txt +2295 -0
  49. package/dist/browser/workspace.css +4 -0
  50. package/dist/browser/workspace.js +225 -0
  51. package/dist/browser-crew.d.ts +11 -0
  52. package/dist/browser-crew.js +50 -0
  53. package/dist/browser-shell.d.ts +8 -0
  54. package/dist/browser-shell.js +60 -0
  55. package/dist/browser-workspace.d.ts +780 -0
  56. package/dist/browser-workspace.js +47 -0
  57. package/dist/budget-alerts.d.ts +19 -0
  58. package/dist/budget-alerts.js +46 -0
  59. package/dist/builder.d.ts +370 -0
  60. package/dist/builder.js +3262 -0
  61. package/dist/capscan.d.ts +35 -0
  62. package/dist/capscan.js +113 -0
  63. package/dist/chat-acceptance.d.ts +71 -0
  64. package/dist/chat-acceptance.js +120 -0
  65. package/dist/chat-actions.d.ts +265 -0
  66. package/dist/chat-actions.js +1273 -0
  67. package/dist/chat-channel.d.ts +109 -0
  68. package/dist/chat-channel.js +652 -0
  69. package/dist/chat-continuity.d.ts +32 -0
  70. package/dist/chat-continuity.js +317 -0
  71. package/dist/chat-controls.d.ts +113 -0
  72. package/dist/chat-controls.js +53 -0
  73. package/dist/chat-delivery-state.d.ts +159 -0
  74. package/dist/chat-delivery-state.js +309 -0
  75. package/dist/chat-delivery.d.ts +38 -0
  76. package/dist/chat-delivery.js +693 -0
  77. package/dist/chat-display.d.ts +1 -0
  78. package/dist/chat-display.js +18 -0
  79. package/dist/chat-evidence.d.ts +123 -0
  80. package/dist/chat-evidence.js +207 -0
  81. package/dist/chat-flow.d.ts +44 -0
  82. package/dist/chat-flow.js +215 -0
  83. package/dist/chat-inbox.d.ts +57 -0
  84. package/dist/chat-inbox.js +123 -0
  85. package/dist/chat-polish.d.ts +16 -0
  86. package/dist/chat-polish.js +135 -0
  87. package/dist/chat-review.d.ts +46 -0
  88. package/dist/chat-review.js +98 -0
  89. package/dist/chat-rooms.d.ts +123 -0
  90. package/dist/chat-rooms.js +216 -0
  91. package/dist/chat-task-actions.d.ts +44 -0
  92. package/dist/chat-task-actions.js +79 -0
  93. package/dist/check-progress.d.ts +51 -0
  94. package/dist/check-progress.js +290 -0
  95. package/dist/child-database.d.ts +12 -0
  96. package/dist/child-database.js +30 -0
  97. package/dist/claim.d.ts +688 -0
  98. package/dist/claim.js +1740 -0
  99. package/dist/cli.d.ts +137 -0
  100. package/dist/cli.js +1461 -0
  101. package/dist/codex-limits.d.ts +15 -0
  102. package/dist/codex-limits.js +145 -0
  103. package/dist/coding-context.d.ts +55 -0
  104. package/dist/coding-context.js +92 -0
  105. package/dist/coding-handoff.d.ts +57 -0
  106. package/dist/coding-handoff.js +277 -0
  107. package/dist/coding-provider.d.ts +72 -0
  108. package/dist/coding-provider.js +424 -0
  109. package/dist/coding-shipping-ui.d.ts +4 -0
  110. package/dist/coding-shipping-ui.js +12 -0
  111. package/dist/coding-types.d.ts +62 -0
  112. package/dist/coding-types.js +1 -0
  113. package/dist/coding-ui.d.ts +17 -0
  114. package/dist/coding-ui.js +364 -0
  115. package/dist/coding-update.d.ts +15 -0
  116. package/dist/coding-update.js +149 -0
  117. package/dist/coding-workspace.d.ts +124 -0
  118. package/dist/coding-workspace.js +768 -0
  119. package/dist/container-state.d.ts +5 -0
  120. package/dist/container-state.js +62 -0
  121. package/dist/containment.d.ts +197 -0
  122. package/dist/containment.js +559 -0
  123. package/dist/contest.d.ts +318 -0
  124. package/dist/contest.js +753 -0
  125. package/dist/control-setup.d.ts +35 -0
  126. package/dist/control-setup.js +40 -0
  127. package/dist/control-ui.d.ts +29 -0
  128. package/dist/control-ui.js +53 -0
  129. package/dist/controller-service.d.ts +1 -0
  130. package/dist/controller-service.js +19 -0
  131. package/dist/controller-supervisor.d.ts +30 -0
  132. package/dist/controller-supervisor.js +104 -0
  133. package/dist/converse.d.ts +304 -0
  134. package/dist/converse.js +849 -0
  135. package/dist/coordinator-proposals.d.ts +29 -0
  136. package/dist/coordinator-proposals.js +137 -0
  137. package/dist/coordinator.d.ts +186 -0
  138. package/dist/coordinator.js +447 -0
  139. package/dist/credentials-ui.d.ts +25 -0
  140. package/dist/credentials-ui.js +48 -0
  141. package/dist/daemon.d.ts +209 -0
  142. package/dist/daemon.js +604 -0
  143. package/dist/decision.d.ts +120 -0
  144. package/dist/decision.js +388 -0
  145. package/dist/demo.d.ts +55 -0
  146. package/dist/demo.js +992 -0
  147. package/dist/desktop-access.d.ts +28 -0
  148. package/dist/desktop-access.js +88 -0
  149. package/dist/desktop-bundle.d.ts +16 -0
  150. package/dist/desktop-bundle.js +74 -0
  151. package/dist/desktop-host.d.ts +54 -0
  152. package/dist/desktop-host.js +508 -0
  153. package/dist/desktop-update-gate.d.ts +12 -0
  154. package/dist/desktop-update-gate.js +91 -0
  155. package/dist/desktop-update-recovery.d.ts +14 -0
  156. package/dist/desktop-update-recovery.js +243 -0
  157. package/dist/desktop-update.d.ts +110 -0
  158. package/dist/desktop-update.js +740 -0
  159. package/dist/discord-api.d.ts +20 -0
  160. package/dist/discord-api.js +138 -0
  161. package/dist/discord-chat.d.ts +16 -0
  162. package/dist/discord-chat.js +381 -0
  163. package/dist/discord-settings.d.ts +7 -0
  164. package/dist/discord-settings.js +75 -0
  165. package/dist/discord.d.ts +10 -0
  166. package/dist/discord.js +169 -0
  167. package/dist/discover.d.ts +75 -0
  168. package/dist/discover.js +150 -0
  169. package/dist/dispatch.d.ts +100 -0
  170. package/dist/dispatch.js +311 -0
  171. package/dist/dispose.d.ts +161 -0
  172. package/dist/dispose.js +803 -0
  173. package/dist/email-settings.d.ts +34 -0
  174. package/dist/email-settings.js +50 -0
  175. package/dist/envelope.d.ts +47 -0
  176. package/dist/envelope.js +105 -0
  177. package/dist/evidence-pack.d.ts +185 -0
  178. package/dist/evidence-pack.js +258 -0
  179. package/dist/evidence.d.ts +345 -0
  180. package/dist/evidence.js +782 -0
  181. package/dist/exec.d.ts +285 -0
  182. package/dist/exec.js +1841 -0
  183. package/dist/exhaustion.d.ts +85 -0
  184. package/dist/exhaustion.js +141 -0
  185. package/dist/export-ui.d.ts +4 -0
  186. package/dist/export-ui.js +17 -0
  187. package/dist/export.d.ts +48 -0
  188. package/dist/export.js +305 -0
  189. package/dist/flow-actions.d.ts +77 -0
  190. package/dist/flow-actions.js +203 -0
  191. package/dist/flow-code.d.ts +50 -0
  192. package/dist/flow-code.js +159 -0
  193. package/dist/flow-draft.d.ts +38 -0
  194. package/dist/flow-draft.js +80 -0
  195. package/dist/flow-engine.d.ts +66 -0
  196. package/dist/flow-engine.js +416 -0
  197. package/dist/flow-insights.d.ts +95 -0
  198. package/dist/flow-insights.js +149 -0
  199. package/dist/flow-live.d.ts +24 -0
  200. package/dist/flow-live.js +150 -0
  201. package/dist/flow-people.d.ts +24 -0
  202. package/dist/flow-people.js +91 -0
  203. package/dist/flow-replies.d.ts +48 -0
  204. package/dist/flow-replies.js +113 -0
  205. package/dist/flow-scripts.d.ts +38 -0
  206. package/dist/flow-scripts.js +73 -0
  207. package/dist/flow-secrets.d.ts +13 -0
  208. package/dist/flow-secrets.js +45 -0
  209. package/dist/flow-sort.d.ts +82 -0
  210. package/dist/flow-sort.js +153 -0
  211. package/dist/flow-steps.d.ts +40 -0
  212. package/dist/flow-steps.js +408 -0
  213. package/dist/flow-triggers.d.ts +244 -0
  214. package/dist/flow-triggers.js +959 -0
  215. package/dist/flows-ui.d.ts +20 -0
  216. package/dist/flows-ui.js +175 -0
  217. package/dist/flows.d.ts +229 -0
  218. package/dist/flows.js +968 -0
  219. package/dist/fonts.d.ts +19 -0
  220. package/dist/fonts.js +19 -0
  221. package/dist/gaps.d.ts +35 -0
  222. package/dist/gaps.js +101 -0
  223. package/dist/gate-failure.d.ts +40 -0
  224. package/dist/gate-failure.js +66 -0
  225. package/dist/git.d.ts +54 -0
  226. package/dist/git.js +94 -0
  227. package/dist/google-mail.d.ts +58 -0
  228. package/dist/google-mail.js +151 -0
  229. package/dist/grant.d.ts +136 -0
  230. package/dist/grant.js +238 -0
  231. package/dist/graph.d.ts +164 -0
  232. package/dist/graph.js +383 -0
  233. package/dist/guides.d.ts +22 -0
  234. package/dist/guides.js +363 -0
  235. package/dist/held.d.ts +150 -0
  236. package/dist/held.js +799 -0
  237. package/dist/invoke.d.ts +112 -0
  238. package/dist/invoke.js +780 -0
  239. package/dist/issues.d.ts +41 -0
  240. package/dist/issues.js +131 -0
  241. package/dist/job-object-helper.ps1 +252 -0
  242. package/dist/jsonl-discriminants.d.ts +11 -0
  243. package/dist/jsonl-discriminants.js +93 -0
  244. package/dist/keys.d.ts +104 -0
  245. package/dist/keys.js +229 -0
  246. package/dist/kits-ui.d.ts +17 -0
  247. package/dist/kits-ui.js +46 -0
  248. package/dist/kits.d.ts +86 -0
  249. package/dist/kits.js +215 -0
  250. package/dist/knowledge-cli.d.ts +101 -0
  251. package/dist/knowledge-cli.js +92 -0
  252. package/dist/knowledge-ui.d.ts +24 -0
  253. package/dist/knowledge-ui.js +40 -0
  254. package/dist/lead-context.d.ts +8 -0
  255. package/dist/lead-context.js +56 -0
  256. package/dist/lead-follow.d.ts +22 -0
  257. package/dist/lead-follow.js +167 -0
  258. package/dist/lead-status.d.ts +75 -0
  259. package/dist/lead-status.js +285 -0
  260. package/dist/ledger-chain.d.ts +46 -0
  261. package/dist/ledger-chain.js +187 -0
  262. package/dist/ledger-csv.d.ts +4 -0
  263. package/dist/ledger-csv.js +11 -0
  264. package/dist/ledger-view.d.ts +24 -0
  265. package/dist/ledger-view.js +58 -0
  266. package/dist/limits-ui.d.ts +26 -0
  267. package/dist/limits-ui.js +67 -0
  268. package/dist/link.d.ts +72 -0
  269. package/dist/link.js +217 -0
  270. package/dist/live.d.ts +96 -0
  271. package/dist/live.js +366 -0
  272. package/dist/liveness.d.ts +30 -0
  273. package/dist/liveness.js +42 -0
  274. package/dist/log.d.ts +7 -0
  275. package/dist/log.js +25 -0
  276. package/dist/mailbox.d.ts +57 -0
  277. package/dist/mailbox.js +150 -0
  278. package/dist/maintenance.d.ts +11 -0
  279. package/dist/maintenance.js +35 -0
  280. package/dist/mate-cli.d.ts +52 -0
  281. package/dist/mate-cli.js +345 -0
  282. package/dist/mate-contract.d.ts +10 -0
  283. package/dist/mate-contract.js +30 -0
  284. package/dist/mate-doors.d.ts +69 -0
  285. package/dist/mate-doors.js +548 -0
  286. package/dist/mate-progress.d.ts +29 -0
  287. package/dist/mate-progress.js +121 -0
  288. package/dist/mate-tools.d.ts +94 -0
  289. package/dist/mate-tools.js +1878 -0
  290. package/dist/mate.d.ts +92 -0
  291. package/dist/mate.js +435 -0
  292. package/dist/mcp-connect.d.ts +103 -0
  293. package/dist/mcp-connect.js +252 -0
  294. package/dist/mcp.d.ts +27 -0
  295. package/dist/mcp.js +651 -0
  296. package/dist/memory-cli.d.ts +466 -0
  297. package/dist/memory-cli.js +111 -0
  298. package/dist/memory-pass.d.ts +160 -0
  299. package/dist/memory-pass.js +409 -0
  300. package/dist/metrics.d.ts +3 -0
  301. package/dist/metrics.js +56 -0
  302. package/dist/mobile-viewport.d.ts +3 -0
  303. package/dist/mobile-viewport.js +37 -0
  304. package/dist/model-catalog.d.ts +118 -0
  305. package/dist/model-catalog.js +376 -0
  306. package/dist/models-cli.d.ts +102 -0
  307. package/dist/models-cli.js +66 -0
  308. package/dist/models-ui.d.ts +34 -0
  309. package/dist/models-ui.js +68 -0
  310. package/dist/modes.d.ts +80 -0
  311. package/dist/modes.js +182 -0
  312. package/dist/monitoring-settings.d.ts +44 -0
  313. package/dist/monitoring-settings.js +173 -0
  314. package/dist/monitoring-ui.d.ts +20 -0
  315. package/dist/monitoring-ui.js +51 -0
  316. package/dist/monitoring.d.ts +34 -0
  317. package/dist/monitoring.js +221 -0
  318. package/dist/names.d.ts +67 -0
  319. package/dist/names.js +102 -0
  320. package/dist/observations.d.ts +40 -0
  321. package/dist/observations.js +211 -0
  322. package/dist/oidc.d.ts +71 -0
  323. package/dist/oidc.js +182 -0
  324. package/dist/onboard.d.ts +108 -0
  325. package/dist/onboard.js +325 -0
  326. package/dist/openrouter-models.d.ts +30 -0
  327. package/dist/openrouter-models.js +120 -0
  328. package/dist/operate.d.ts +118 -0
  329. package/dist/operate.js +11321 -0
  330. package/dist/peek-cli.d.ts +97 -0
  331. package/dist/peek-cli.js +215 -0
  332. package/dist/peek.d.ts +134 -0
  333. package/dist/peek.js +578 -0
  334. package/dist/phase-routing.d.ts +307 -0
  335. package/dist/phase-routing.js +658 -0
  336. package/dist/plan-auto.d.ts +14 -0
  337. package/dist/plan-auto.js +92 -0
  338. package/dist/plan.d.ts +186 -0
  339. package/dist/plan.js +401 -0
  340. package/dist/planner-source.d.ts +251 -0
  341. package/dist/planner-source.js +460 -0
  342. package/dist/planner.d.ts +75 -0
  343. package/dist/planner.js +992 -0
  344. package/dist/policy-ui.d.ts +20 -0
  345. package/dist/policy-ui.js +41 -0
  346. package/dist/policy.d.ts +111 -0
  347. package/dist/policy.js +231 -0
  348. package/dist/prepared-evidence.d.ts +16 -0
  349. package/dist/prepared-evidence.js +96 -0
  350. package/dist/pricing.d.ts +45 -0
  351. package/dist/pricing.js +77 -0
  352. package/dist/principal.d.ts +42 -0
  353. package/dist/principal.js +82 -0
  354. package/dist/probe.d.ts +46 -0
  355. package/dist/probe.js +79 -0
  356. package/dist/process-custody.d.ts +17 -0
  357. package/dist/process-custody.js +91 -0
  358. package/dist/process-liveness.d.ts +10 -0
  359. package/dist/process-liveness.js +81 -0
  360. package/dist/process-recovery-anchor.d.ts +75 -0
  361. package/dist/process-recovery-anchor.js +188 -0
  362. package/dist/process-recovery-coalition.d.ts +25 -0
  363. package/dist/process-recovery-coalition.js +105 -0
  364. package/dist/process-recovery-eligibility.d.ts +178 -0
  365. package/dist/process-recovery-eligibility.js +170 -0
  366. package/dist/process-recovery-native.d.ts +172 -0
  367. package/dist/process-recovery-native.js +592 -0
  368. package/dist/process-recovery-provenance.d.ts +163 -0
  369. package/dist/process-recovery-provenance.js +292 -0
  370. package/dist/process-recovery-services.d.ts +56 -0
  371. package/dist/process-recovery-services.js +191 -0
  372. package/dist/process-recovery-settlement.d.ts +32 -0
  373. package/dist/process-recovery-settlement.js +132 -0
  374. package/dist/process-recovery.d.ts +41 -0
  375. package/dist/process-recovery.js +91 -0
  376. package/dist/process-tree.d.ts +41 -0
  377. package/dist/process-tree.js +264 -0
  378. package/dist/project-access.d.ts +14 -0
  379. package/dist/project-access.js +34 -0
  380. package/dist/project-cli.d.ts +18 -0
  381. package/dist/project-cli.js +104 -0
  382. package/dist/project-delete-ui.d.ts +22 -0
  383. package/dist/project-delete-ui.js +48 -0
  384. package/dist/project-delete.d.ts +55 -0
  385. package/dist/project-delete.js +413 -0
  386. package/dist/project-knowledge.d.ts +111 -0
  387. package/dist/project-knowledge.js +241 -0
  388. package/dist/project-learning.d.ts +100 -0
  389. package/dist/project-learning.js +438 -0
  390. package/dist/project-memory.d.ts +81 -0
  391. package/dist/project-memory.js +264 -0
  392. package/dist/project-skills.d.ts +152 -0
  393. package/dist/project-skills.js +660 -0
  394. package/dist/project-tools.d.ts +219 -0
  395. package/dist/project-tools.js +796 -0
  396. package/dist/project.d.ts +61 -0
  397. package/dist/project.js +125 -0
  398. package/dist/prompt.d.ts +22 -0
  399. package/dist/prompt.js +72 -0
  400. package/dist/proof.d.ts +513 -0
  401. package/dist/proof.js +1140 -0
  402. package/dist/proposal.d.ts +82 -0
  403. package/dist/proposal.js +210 -0
  404. package/dist/provider-connection.d.ts +22 -0
  405. package/dist/provider-connection.js +98 -0
  406. package/dist/provider-limits.d.ts +35 -0
  407. package/dist/provider-limits.js +95 -0
  408. package/dist/provider.d.ts +279 -0
  409. package/dist/provider.js +935 -0
  410. package/dist/publish.d.ts +107 -0
  411. package/dist/publish.js +650 -0
  412. package/dist/pulls.d.ts +118 -0
  413. package/dist/pulls.js +240 -0
  414. package/dist/push.d.ts +95 -0
  415. package/dist/push.js +353 -0
  416. package/dist/quality.d.ts +8 -0
  417. package/dist/quality.js +6 -0
  418. package/dist/recipe-ui.d.ts +18 -0
  419. package/dist/recipe-ui.js +152 -0
  420. package/dist/recipes.d.ts +81 -0
  421. package/dist/recipes.js +332 -0
  422. package/dist/remote.d.ts +67 -0
  423. package/dist/remote.js +122 -0
  424. package/dist/render.d.ts +64 -0
  425. package/dist/render.js +587 -0
  426. package/dist/report-summary.d.ts +13 -0
  427. package/dist/report-summary.js +15 -0
  428. package/dist/repos.d.ts +65 -0
  429. package/dist/repos.js +277 -0
  430. package/dist/repository-context-ui.d.ts +2 -0
  431. package/dist/repository-context-ui.js +10 -0
  432. package/dist/repository-context.d.ts +67 -0
  433. package/dist/repository-context.js +376 -0
  434. package/dist/restart-certification.d.ts +134 -0
  435. package/dist/restart-certification.js +226 -0
  436. package/dist/result-actions.d.ts +28 -0
  437. package/dist/result-actions.js +270 -0
  438. package/dist/result-completion.d.ts +18 -0
  439. package/dist/result-completion.js +66 -0
  440. package/dist/result-review.d.ts +213 -0
  441. package/dist/result-review.js +430 -0
  442. package/dist/retention-ui.d.ts +12 -0
  443. package/dist/retention-ui.js +39 -0
  444. package/dist/retention.d.ts +72 -0
  445. package/dist/retention.js +288 -0
  446. package/dist/review-context.d.ts +243 -0
  447. package/dist/review-context.js +1043 -0
  448. package/dist/review-evidence.d.ts +33 -0
  449. package/dist/review-evidence.js +56 -0
  450. package/dist/reviewer.d.ts +97 -0
  451. package/dist/reviewer.js +202 -0
  452. package/dist/routine.d.ts +228 -0
  453. package/dist/routine.js +764 -0
  454. package/dist/runner.d.ts +266 -0
  455. package/dist/runner.js +399 -0
  456. package/dist/scan.d.ts +32 -0
  457. package/dist/scan.js +92 -0
  458. package/dist/scope.d.ts +695 -0
  459. package/dist/scope.js +1176 -0
  460. package/dist/scout-report.d.ts +42 -0
  461. package/dist/scout-report.js +108 -0
  462. package/dist/scout.d.ts +69 -0
  463. package/dist/scout.js +351 -0
  464. package/dist/serve.d.ts +313 -0
  465. package/dist/serve.js +21776 -0
  466. package/dist/session-brief.d.ts +8 -0
  467. package/dist/session-brief.js +24 -0
  468. package/dist/session-cli.d.ts +13 -0
  469. package/dist/session-cli.js +284 -0
  470. package/dist/session-contract.d.ts +183 -0
  471. package/dist/session-contract.js +122 -0
  472. package/dist/session-http.d.ts +19 -0
  473. package/dist/session-http.js +154 -0
  474. package/dist/session-server.d.ts +12 -0
  475. package/dist/session-server.js +37 -0
  476. package/dist/session-service.d.ts +22 -0
  477. package/dist/session-service.js +157 -0
  478. package/dist/setup-guide.d.ts +39 -0
  479. package/dist/setup-guide.js +93 -0
  480. package/dist/sign-in-guard.d.ts +45 -0
  481. package/dist/sign-in-guard.js +74 -0
  482. package/dist/skills-ui.d.ts +11 -0
  483. package/dist/skills-ui.js +58 -0
  484. package/dist/skills.d.ts +97 -0
  485. package/dist/skills.js +276 -0
  486. package/dist/slack-api.d.ts +55 -0
  487. package/dist/slack-api.js +229 -0
  488. package/dist/slack-chat.d.ts +28 -0
  489. package/dist/slack-chat.js +413 -0
  490. package/dist/slack-settings.d.ts +7 -0
  491. package/dist/slack-settings.js +75 -0
  492. package/dist/slack-state.d.ts +13 -0
  493. package/dist/slack-state.js +9 -0
  494. package/dist/slack.d.ts +13 -0
  495. package/dist/slack.js +167 -0
  496. package/dist/spend-ui.d.ts +28 -0
  497. package/dist/spend-ui.js +95 -0
  498. package/dist/spend.d.ts +142 -0
  499. package/dist/spend.js +313 -0
  500. package/dist/sqlite-runtime.d.ts +3 -0
  501. package/dist/sqlite-runtime.js +6 -0
  502. package/dist/sso-settings.d.ts +33 -0
  503. package/dist/sso-settings.js +103 -0
  504. package/dist/sso-ui.d.ts +22 -0
  505. package/dist/sso-ui.js +39 -0
  506. package/dist/storage.d.ts +15 -0
  507. package/dist/storage.js +84 -0
  508. package/dist/store.d.ts +7754 -0
  509. package/dist/store.js +23279 -0
  510. package/dist/structured-output.d.ts +58 -0
  511. package/dist/structured-output.js +103 -0
  512. package/dist/style-asset.d.ts +7 -0
  513. package/dist/style-asset.js +41 -0
  514. package/dist/subscription-chat.d.ts +46 -0
  515. package/dist/subscription-chat.js +275 -0
  516. package/dist/summary.d.ts +33 -0
  517. package/dist/summary.js +71 -0
  518. package/dist/supervisor.mjs +297 -0
  519. package/dist/surface.d.ts +63 -0
  520. package/dist/surface.js +352 -0
  521. package/dist/sync.d.ts +94 -0
  522. package/dist/sync.js +279 -0
  523. package/dist/task-composer.d.ts +13 -0
  524. package/dist/task-composer.js +52 -0
  525. package/dist/task-control.d.ts +165 -0
  526. package/dist/task-control.js +214 -0
  527. package/dist/task-outcome-cli.d.ts +10 -0
  528. package/dist/task-outcome-cli.js +92 -0
  529. package/dist/task-text.d.ts +30 -0
  530. package/dist/task-text.js +41 -0
  531. package/dist/team-cli.d.ts +15 -0
  532. package/dist/team-cli.js +618 -0
  533. package/dist/team-contract.d.ts +92 -0
  534. package/dist/team-contract.js +1 -0
  535. package/dist/team-http.d.ts +17 -0
  536. package/dist/team-http.js +144 -0
  537. package/dist/team-leads.d.ts +81 -0
  538. package/dist/team-leads.js +565 -0
  539. package/dist/team-runtime.d.ts +27 -0
  540. package/dist/team-runtime.js +264 -0
  541. package/dist/team-ui.d.ts +3 -0
  542. package/dist/team-ui.js +9 -0
  543. package/dist/team-updates.d.ts +8 -0
  544. package/dist/team-updates.js +57 -0
  545. package/dist/teammate-admin.d.ts +53 -0
  546. package/dist/teammate-admin.js +111 -0
  547. package/dist/teammate-desk.d.ts +60 -0
  548. package/dist/teammate-desk.js +154 -0
  549. package/dist/teammate-memory.d.ts +64 -0
  550. package/dist/teammate-memory.js +196 -0
  551. package/dist/teammate-question.d.ts +59 -0
  552. package/dist/teammate-question.js +175 -0
  553. package/dist/teammate-tools.d.ts +108 -0
  554. package/dist/teammate-tools.js +271 -0
  555. package/dist/teammate-week.d.ts +68 -0
  556. package/dist/teammate-week.js +132 -0
  557. package/dist/teammate-work.d.ts +76 -0
  558. package/dist/teammate-work.js +280 -0
  559. package/dist/teammates-ui.d.ts +20 -0
  560. package/dist/teammates-ui.js +166 -0
  561. package/dist/teammates.d.ts +180 -0
  562. package/dist/teammates.js +253 -0
  563. package/dist/teams-api.d.ts +33 -0
  564. package/dist/teams-api.js +204 -0
  565. package/dist/teams-chat.d.ts +26 -0
  566. package/dist/teams-chat.js +215 -0
  567. package/dist/teams-settings.d.ts +12 -0
  568. package/dist/teams-settings.js +57 -0
  569. package/dist/teams.d.ts +21 -0
  570. package/dist/teams.js +124 -0
  571. package/dist/telegram-flow.d.ts +49 -0
  572. package/dist/telegram-flow.js +110 -0
  573. package/dist/telegram-mate.d.ts +137 -0
  574. package/dist/telegram-mate.js +707 -0
  575. package/dist/telegram-progress.d.ts +14 -0
  576. package/dist/telegram-progress.js +129 -0
  577. package/dist/telegram-settings.d.ts +9 -0
  578. package/dist/telegram-settings.js +36 -0
  579. package/dist/telegram-status.d.ts +75 -0
  580. package/dist/telegram-status.js +265 -0
  581. package/dist/telegram-team.d.ts +85 -0
  582. package/dist/telegram-team.js +359 -0
  583. package/dist/telegram.d.ts +230 -0
  584. package/dist/telegram.js +1931 -0
  585. package/dist/templates.d.ts +65 -0
  586. package/dist/templates.js +118 -0
  587. package/dist/tool-launcher.d.ts +1 -0
  588. package/dist/tool-launcher.js +101 -0
  589. package/dist/tools-ui.d.ts +30 -0
  590. package/dist/tools-ui.js +40 -0
  591. package/dist/transitions-recipes.d.ts +1 -0
  592. package/dist/transitions-recipes.js +203 -0
  593. package/dist/tree-proof.d.ts +34 -0
  594. package/dist/tree-proof.js +58 -0
  595. package/dist/verification-evidence.d.ts +44 -0
  596. package/dist/verification-evidence.js +238 -0
  597. package/dist/version.d.ts +2 -0
  598. package/dist/version.js +10 -0
  599. package/dist/webhooks.d.ts +91 -0
  600. package/dist/webhooks.js +283 -0
  601. package/dist/work-index.d.ts +68 -0
  602. package/dist/work-index.js +384 -0
  603. package/dist/work-summary.d.ts +57 -0
  604. package/dist/work-summary.js +116 -0
  605. package/dist/workspace-motion.d.ts +4 -0
  606. package/dist/workspace-motion.js +133 -0
  607. package/dist/workspace-revision.d.ts +19 -0
  608. package/dist/workspace-revision.js +92 -0
  609. package/dist/workspace-ui.d.ts +204 -0
  610. package/dist/workspace-ui.js +411 -0
  611. package/dist/worktree-notices.d.ts +13 -0
  612. package/dist/worktree-notices.js +17 -0
  613. package/dist/worktree.d.ts +249 -0
  614. package/dist/worktree.js +720 -0
  615. package/package.json +122 -0
  616. package/scripts/canary-assertions.mjs +42 -0
  617. package/scripts/crash-canary.mjs +253 -0
  618. package/scripts/fixtures/crash-process.mjs +74 -0
  619. package/scripts/fixtures/pilot-scenarios.mjs +85 -0
  620. package/scripts/fixtures/restart-service.mjs +27 -0
  621. package/scripts/launchd-certification.mjs +143 -0
  622. package/scripts/pilot.mjs +121 -0
  623. package/scripts/proof-preflight.mjs +140 -0
  624. package/scripts/provider-canary.mjs +379 -0
  625. package/scripts/recovery-canary.mjs +135 -0
  626. package/scripts/restart-certification.mjs +98 -0
@@ -0,0 +1,658 @@
1
+ /**
2
+ * Explainable, risk-aware phase routing (v47).
3
+ *
4
+ * WHICH agent plans, builds, repairs, and reviews a task is decided here,
5
+ * once, from signed facts — never guessed from a model's name and never
6
+ * re-decided behind an approval's back. The policy is a small table over
7
+ * explicit inputs:
8
+ *
9
+ * risk — the task's declared risk (routine / elevated / high)
10
+ * quality — the evidence policy the scope signs (default / strict)
11
+ * evidence — what the acceptance rubric demands (screenshots, …)
12
+ * publication — how far the plane may carry the result unattended
13
+ * candidates — the operator's CONFIGURED routine and strong agents
14
+ * overrides — an approver's explicit per-phase choice, recorded
15
+ * pins — a routine firing's or plan request's pinned pair
16
+ *
17
+ * and its output is one canonical ROUTE: four legs, each with an exact
18
+ * provider AND an exact model id, which tier it came from, whether a
19
+ * person overrode it, and plain-English reasons. The same inputs always
20
+ * yield the same route and the same words — `recommendRoute` is pure, so
21
+ * the surfaces (CLI, task page, chat) render one projection rather than
22
+ * three.
23
+ *
24
+ * EXACTNESS is the law of this module: a candidate, an override, a pin,
25
+ * and every frozen leg name an exact model id — "the harness default"
26
+ * is not a term an approval can bind. A configuration that cannot make a
27
+ * leg exact (no model configured, a cross-provider repair row, gemini on
28
+ * the review phase) becomes a stated PROBLEM on that leg, and the scope
29
+ * files unresolved with those words; nothing is guessed or substituted.
30
+ *
31
+ * Strength is never inferred: "strong" means the operator named a strong
32
+ * candidate for that phase (`config set <phase> --tier strong …`). With
33
+ * none configured, a demanding task still routes to the configured
34
+ * default and SAYS so — and its posture reads as economical, because that
35
+ * is what actually runs. Provider readiness is a runner's observation,
36
+ * not a term — it rides beside the route (ready / unavailable / unknown),
37
+ * it is stated wherever the route is shown, and an unavailable provider
38
+ * is never substituted: admission halts with the reason, and only an
39
+ * already-approved explicit fallback entry may ever run instead.
40
+ *
41
+ * Approval seals the route (`approvedRouteJson`); its digest folds into
42
+ * the scope digest of EVERY route filed since v47 — routine-shaped routes
43
+ * included — so a task-level route edit stales the approval exactly as a
44
+ * goal edit does, while a global configuration change can never rewrite a
45
+ * sealed route. Only a row proven to predate v47 (no route era) reads as
46
+ * a legacy approval governed by its sealed profile alone.
47
+ */
48
+ import { createHash } from "node:crypto";
49
+ // Type-only imports above: provider.ts sits under evidence.ts and scope.ts
50
+ // in the module graph, and this policy is imported by scope.ts — a value
51
+ // import would be a cycle at load time. The id list is restated here and
52
+ // pinned to provider.ts's by the test suite.
53
+ export const PROVIDER_ID_LIST = ["claude", "codex", "openrouter", "gemini"];
54
+ function isProviderId(value) {
55
+ return PROVIDER_ID_LIST.includes(value);
56
+ }
57
+ /** provider.ts's MODEL_ID, restated for the same reason and pinned by the
58
+ * same test: an exact model id is argv-safe — no leading dash, no
59
+ * whitespace or control bytes — or it is not a model id this policy can
60
+ * seal, stamp, or rehydrate. */
61
+ export const MODEL_ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;
62
+ function exactModel(v) {
63
+ return typeof v === "string" && MODEL_ID_SHAPE.test(v);
64
+ }
65
+ /** The same exactness for callers outside this policy (the profile
66
+ * rehydrator): one shape, one definition. */
67
+ export function exactModelId(v) {
68
+ return exactModel(v);
69
+ }
70
+ export const ROUTE_VERSION = 1;
71
+ /** The durable route ERA a scope row carries once it was filed under this
72
+ * policy: NULL on a row proven to predate v47 (legacy — the sealed profile
73
+ * alone governs), this value on every row filed since. A row with an era
74
+ * and no readable route is corrupt and fails closed. */
75
+ export const ROUTE_ERA = ROUTE_VERSION;
76
+ export const PHASES = ["plan", "build", "repair", "review"];
77
+ /** The review leg remains readable in signed history but is no longer scheduled. */
78
+ export const ACTIVE_PHASES = ["plan", "build", "repair"];
79
+ export const RISK_LEVELS = ["routine", "elevated", "high"];
80
+ export function isRiskLevel(value) {
81
+ return value === "routine" || value === "elevated" || value === "high";
82
+ }
83
+ export function riskTitle(risk) {
84
+ return risk === "high" ? "High risk" : risk === "elevated" ? "Elevated risk" : "Routine";
85
+ }
86
+ /**
87
+ * What declaring each risk level DOES, in one plain sentence — derived
88
+ * from the tiering table below, so the explanation a form or a chat gives
89
+ * can never drift from the policy that acts on it. The same words on
90
+ * every surface: the task page's risk control, the chat's answer, the CLI.
91
+ */
92
+ export function riskConsequence(risk) {
93
+ if (risk === "high")
94
+ return "every active role — planner, builder, and repair — uses the strongest agent you have configured";
95
+ if (risk === "elevated")
96
+ return "planning and building keep the everyday agents unless the work itself asks for more (strict quality or screenshots)";
97
+ return "every role uses the everyday configured agent unless the work itself asks for more (strict quality, screenshots, or a self-merging mode)";
98
+ }
99
+ export const RISK_CHOICES = RISK_LEVELS.map(risk => ({ risk, title: riskTitle(risk), consequence: riskConsequence(risk) }));
100
+ const PHASE_NOUN = { plan: "planner", build: "builder", repair: "repair", review: "reviewer" };
101
+ const PHASE_VERB = { plan: "plans", build: "builds", repair: "repairs", review: "reviews" };
102
+ export function specWords(spec) {
103
+ return `${spec.provider} · ${spec.model}`;
104
+ }
105
+ const DEMANDS = [
106
+ {
107
+ when: input => input.risk === "high",
108
+ phases: ["plan", "build", "repair", "review"],
109
+ reason: "risk is high — every role uses the strongest configured agent",
110
+ },
111
+ {
112
+ when: input => input.risk === "elevated",
113
+ phases: ["review"],
114
+ reason: "risk is elevated — the review runs on the strongest configured reviewer",
115
+ },
116
+ {
117
+ when: input => input.qualityMode === "strict",
118
+ phases: ["plan", "build", "repair", "review"],
119
+ reason: "quality is strict / release — every role uses the strongest configured agent",
120
+ },
121
+ {
122
+ when: input => input.evidence.includes("screenshot"),
123
+ phases: ["build", "repair", "review"],
124
+ reason: "acceptance requires screenshots — visual proof gets the strongest configured builder and reviewer",
125
+ },
126
+ {
127
+ when: input => input.evidence.includes("manual-review"),
128
+ phases: ["review"],
129
+ reason: "acceptance asks for manual review — the strongest configured reviewer prepares it",
130
+ },
131
+ {
132
+ when: input => input.publication === "automerge",
133
+ phases: ["review"],
134
+ reason: "a live mode merges by itself — the review is the last gate, so it runs on the strongest configured reviewer",
135
+ },
136
+ ];
137
+ function demandedTier(input, phase) {
138
+ const reasons = DEMANDS.filter(one => one.when(input) && one.phases.includes(phase)).map(one => one.reason);
139
+ return reasons.length === 0 ? { tier: "routine", reasons: [] } : { tier: "strong", reasons };
140
+ }
141
+ function economyReason(input, phase) {
142
+ const facts = [
143
+ `risk is ${input.risk}`,
144
+ `quality is ${input.qualityMode === "strict" ? "strict" : "default"}`,
145
+ ...(input.publication === "notify" ? ["publication waits for a person"] : []),
146
+ ];
147
+ return `${facts.join(", ")} — the configured ${PHASE_NOUN[phase]} is economical enough`;
148
+ }
149
+ function reviewProblem(spec) {
150
+ return spec.provider === "gemini"
151
+ ? "gemini has no isolation posture for the review phase yet — configure or override the reviewer to claude or codex"
152
+ : null;
153
+ }
154
+ /**
155
+ * The recommendation: pure, deterministic, table-driven. Same inputs,
156
+ * same route, same words. Every leg it returns is exact; a leg the
157
+ * configuration cannot make runnable carries a `problem` instead of a
158
+ * guess.
159
+ */
160
+ export function recommendRoute(input) {
161
+ const demands = DEMANDS.filter(one => one.when(input)).map(one => one.reason);
162
+ const overrides = [...input.overrides]
163
+ .filter(one => PHASES.includes(one.phase))
164
+ .sort((a, b) => PHASES.indexOf(a.phase) - PHASES.indexOf(b.phase));
165
+ const overrideFor = (phase) => overrides.find(one => one.phase === phase) ?? null;
166
+ const legs = [];
167
+ const pick = (phase) => {
168
+ const demanded = demandedTier(input, phase);
169
+ const candidates = input.candidates[phase];
170
+ if (demanded.tier === "strong") {
171
+ if (candidates.strong !== null) {
172
+ return { spec: candidates.strong, tier: "strong", reasons: [...demanded.reasons, `strong ${PHASE_NOUN[phase]} from ${candidates.strong.source}`] };
173
+ }
174
+ return {
175
+ spec: candidates.routine,
176
+ tier: "routine",
177
+ reasons: [
178
+ ...demanded.reasons,
179
+ `no stronger ${PHASE_NOUN[phase]} is configured — using the configured default from ${candidates.routine.source}`,
180
+ ],
181
+ };
182
+ }
183
+ return { spec: candidates.routine, tier: "routine", reasons: [economyReason(input, phase), `configured ${PHASE_NOUN[phase]} from ${candidates.routine.source}`] };
184
+ };
185
+ // plan — pin > override > recommendation.
186
+ {
187
+ const rec = pick("plan");
188
+ const pin = input.pins?.plan ?? null;
189
+ const override = overrideFor("plan");
190
+ const recommended = { provider: rec.spec.provider, model: rec.spec.model, tier: rec.tier };
191
+ if (pin !== null) {
192
+ legs.push({ phase: "plan", provider: pin.provider, model: pin.model, tier: rec.tier, chosen: "pinned", recommended, reasons: [`pinned to ${specWords(pin)} by the plan request — nothing overrides a pin`], problem: null });
193
+ }
194
+ else if (override !== null) {
195
+ legs.push({ phase: "plan", provider: override.provider, model: override.model, tier: rec.tier, chosen: "override", recommended, reasons: [`overridden by ${override.by} to ${specWords(override)} (recommended ${specWords(rec.spec)})`], problem: null });
196
+ }
197
+ else {
198
+ legs.push({ phase: "plan", provider: rec.spec.provider, model: rec.spec.model, tier: rec.tier, chosen: "recommended", recommended, reasons: rec.reasons, problem: null });
199
+ }
200
+ }
201
+ // build — pin > override > recommendation.
202
+ const build = (() => {
203
+ const rec = pick("build");
204
+ const pin = input.pins?.build ?? null;
205
+ const override = overrideFor("build");
206
+ const recommended = { provider: rec.spec.provider, model: rec.spec.model, tier: rec.tier };
207
+ const leg = pin !== null
208
+ ? { phase: "build", provider: pin.provider, model: pin.model, tier: rec.tier, chosen: "pinned", recommended, reasons: [`pinned to ${specWords(pin)} by the firing that filed this task — nothing overrides a pin`], problem: null }
209
+ : override !== null
210
+ ? { phase: "build", provider: override.provider, model: override.model, tier: rec.tier, chosen: "override", recommended, reasons: [`overridden by ${override.by} to ${specWords(override)} (recommended ${specWords(rec.spec)})`], problem: null }
211
+ : { phase: "build", provider: rec.spec.provider, model: rec.spec.model, tier: rec.tier, chosen: "recommended", recommended, reasons: rec.reasons, problem: null };
212
+ legs.push(leg);
213
+ return leg;
214
+ })();
215
+ // repair — ALWAYS the build provider (repair resumes the builder's
216
+ // session; cross-provider repair does not exist). Only the model routes:
217
+ // the same-provider strong row when demanded, else the same-provider
218
+ // configured row, else the build's own exact model (inherit). A
219
+ // configured row on ANOTHER provider is a stated problem, never skipped.
220
+ {
221
+ const demanded = demandedTier(input, "repair");
222
+ const candidates = input.candidates.repair;
223
+ const override = overrideFor("repair");
224
+ let model;
225
+ let tier;
226
+ let reasons;
227
+ let problem = null;
228
+ if (demanded.tier === "strong" && candidates.strong !== null) {
229
+ if (candidates.strong.provider === build.provider) {
230
+ model = candidates.strong.model;
231
+ tier = "strong";
232
+ reasons = [...demanded.reasons, `strong repair model from ${candidates.strong.source}`];
233
+ }
234
+ else {
235
+ model = build.model;
236
+ tier = "routine";
237
+ reasons = [...demanded.reasons, `the strong repair agent runs ${candidates.strong.provider}, not the build's ${build.provider}`];
238
+ problem = `the strong repair agent runs ${candidates.strong.provider} but the build runs ${build.provider} — cross-provider repair does not exist; override the repair phase on ${build.provider} or fix \`config set repair --tier strong\``;
239
+ }
240
+ }
241
+ else if (candidates.routine !== null) {
242
+ if (candidates.routine.provider === build.provider) {
243
+ model = candidates.routine.model;
244
+ tier = "routine";
245
+ reasons =
246
+ demanded.tier === "strong"
247
+ ? [...demanded.reasons, `no stronger repair model is configured — using the configured repair model from ${candidates.routine.source}`]
248
+ : [economyReason(input, "repair"), `configured repair model from ${candidates.routine.source}`];
249
+ }
250
+ else {
251
+ model = build.model;
252
+ tier = "routine";
253
+ reasons = [...(demanded.tier === "strong" ? demanded.reasons : [economyReason(input, "repair")]), `the configured repair agent runs ${candidates.routine.provider}, not the build's ${build.provider}`];
254
+ problem = `the repair configuration names ${candidates.routine.provider} but the build runs ${build.provider} — cross-provider repair does not exist; fix \`config set repair\` or override the repair phase on ${build.provider}`;
255
+ }
256
+ }
257
+ else {
258
+ model = build.model;
259
+ tier = "routine";
260
+ reasons = [
261
+ ...(demanded.tier === "strong" ? [...demanded.reasons, "no stronger repair model is configured"] : [economyReason(input, "repair")]),
262
+ `no repair model is configured — repairs resume the builder's session on ${build.provider} with the build model (${build.model})`,
263
+ ];
264
+ }
265
+ const recommended = { provider: build.provider, model, tier };
266
+ const repairPin = input.pins?.repair ?? null;
267
+ if (repairPin !== null) {
268
+ legs.push({
269
+ phase: "repair",
270
+ provider: build.provider,
271
+ model: repairPin.model,
272
+ tier,
273
+ chosen: "pinned",
274
+ recommended,
275
+ reasons: [`pinned to ${specWords({ provider: build.provider, model: repairPin.model })} by the approved profile that filed this task — same provider as the build`],
276
+ problem: repairPin.provider === build.provider ? null : `the pinned repair agent runs ${repairPin.provider} but the build runs ${build.provider} — cross-provider repair does not exist`,
277
+ });
278
+ }
279
+ else if (override !== null && override.provider === build.provider) {
280
+ legs.push({ phase: "repair", provider: build.provider, model: override.model, tier, chosen: "override", recommended, reasons: [`overridden by ${override.by} to ${specWords(override)} (recommended ${specWords({ provider: build.provider, model })})`], problem: null });
281
+ }
282
+ else if (override !== null) {
283
+ legs.push({ phase: "repair", provider: build.provider, model, tier, chosen: "recommended", recommended, reasons: [...reasons, `the repair override to ${override.provider} cannot apply — repairs stay on the build provider (${build.provider})`], problem: `the repair override names ${override.provider} but the build runs ${build.provider} — cross-provider repair does not exist; clear or change the override` });
284
+ }
285
+ else {
286
+ legs.push({ phase: "repair", provider: build.provider, model, tier, chosen: "recommended", recommended, reasons: [...reasons, `same provider as the build (${build.provider}) — repairs resume the builder's session`], problem });
287
+ }
288
+ }
289
+ // review — override > recommendation; gemini cannot run it at all.
290
+ {
291
+ const rec = pick("review");
292
+ const override = overrideFor("review");
293
+ const recommended = { provider: rec.spec.provider, model: rec.spec.model, tier: rec.tier };
294
+ if (override !== null) {
295
+ legs.push({ phase: "review", provider: override.provider, model: override.model, tier: rec.tier, chosen: "override", recommended, reasons: [`overridden by ${override.by} to ${specWords(override)} (recommended ${specWords(rec.spec)})`], problem: reviewProblem(override) });
296
+ }
297
+ else {
298
+ legs.push({ phase: "review", provider: rec.spec.provider, model: rec.spec.model, tier: rec.tier, chosen: "recommended", recommended, reasons: rec.reasons, problem: reviewProblem(rec.spec) });
299
+ }
300
+ }
301
+ return {
302
+ version: ROUTE_VERSION,
303
+ risk: input.risk,
304
+ qualityMode: input.qualityMode,
305
+ publication: input.publication,
306
+ evidence: [...new Set(input.evidence)].sort(),
307
+ // The posture is what RUNS, not what was wanted: only a leg that
308
+ // actually draws from a configured strong agent makes the route strong
309
+ // — an overridden or pinned leg runs the person's choice, not a tier.
310
+ posture: drawsStrong(legs) ? "strong" : "economy",
311
+ demands,
312
+ legs,
313
+ overrides,
314
+ };
315
+ }
316
+ /** Whether any leg actually runs a configured strong agent. */
317
+ function drawsStrong(legs) {
318
+ return legs.some(leg => leg.chosen === "recommended" && leg.tier === "strong");
319
+ }
320
+ export function legOf(route, phase) {
321
+ const leg = route.legs.find(one => one.phase === phase);
322
+ if (leg === undefined)
323
+ throw new Error(`route has no ${phase} leg`);
324
+ return leg;
325
+ }
326
+ /** Every stated problem on the route, in phase order — a non-empty list
327
+ * means the scope files unresolved with these words. */
328
+ export function routeProblems(route) {
329
+ return route.legs.filter(leg => leg.phase !== "review").flatMap(leg => (leg.problem === null ? [] : [`${leg.phase}: ${leg.problem}`]));
330
+ }
331
+ /** Whether two exact pairs are the same agent. */
332
+ export function sameSpec(a, b) {
333
+ return a.provider === b.provider && a.model === b.model;
334
+ }
335
+ // ---- canonical bytes, digest, strict rehydration ---------------------------
336
+ /** Deterministic JSON: object keys sorted recursively, arrays in order. */
337
+ function canonicalJson(value) {
338
+ if (Array.isArray(value))
339
+ return `[${value.map(canonicalJson).join(",")}]`;
340
+ if (value !== null && typeof value === "object") {
341
+ const entries = Object.entries(value)
342
+ .filter(([, v]) => v !== undefined)
343
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
344
+ .map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`);
345
+ return `{${entries.join(",")}}`;
346
+ }
347
+ return JSON.stringify(value);
348
+ }
349
+ /** The stored snapshot bytes: the version rides IN the snapshot. */
350
+ export function canonicalRouteJson(route) {
351
+ return canonicalJson({
352
+ version: route.version,
353
+ risk: route.risk,
354
+ qualityMode: route.qualityMode,
355
+ publication: route.publication,
356
+ evidence: [...route.evidence].sort(),
357
+ posture: route.posture,
358
+ demands: route.demands,
359
+ legs: route.legs.map(leg => ({
360
+ phase: leg.phase,
361
+ provider: leg.provider,
362
+ model: leg.model,
363
+ tier: leg.tier,
364
+ chosen: leg.chosen,
365
+ recommended: leg.recommended,
366
+ reasons: leg.reasons,
367
+ problem: leg.problem,
368
+ })),
369
+ overrides: route.overrides.map(one => ({ phase: one.phase, provider: one.provider, model: one.model, by: one.by, at: one.at })),
370
+ });
371
+ }
372
+ /** sha256 over a domain-separated canonical encoding, truncated to the
373
+ * same 128 bits every other safety digest here uses. Its own domain, so a
374
+ * route digest can never collide with a profile or chain digest. */
375
+ export function routeDigestOf(route) {
376
+ return createHash("sha256")
377
+ .update(`standing-orders:route:v${ROUTE_VERSION}:${canonicalRouteJson(route)}`, "utf8")
378
+ .digest("hex")
379
+ .slice(0, 32);
380
+ }
381
+ function str(v) {
382
+ return typeof v === "string" && v !== "";
383
+ }
384
+ /** Exactly these keys, every one present, nothing unknown. */
385
+ function exactKeysOf(value, keys) {
386
+ const own = Object.keys(value);
387
+ return own.length === keys.length && keys.every(key => own.includes(key));
388
+ }
389
+ function strOrNull(v) {
390
+ return v === null || str(v);
391
+ }
392
+ function stringList(v) {
393
+ return Array.isArray(v) && v.every(one => typeof one === "string");
394
+ }
395
+ /** Strict rehydration of a stored route — every field type-proved, every
396
+ * model an exact non-empty string; anything unexpected is null, never a
397
+ * guess. A null from a row that carries a route era is a corrupt seal. */
398
+ // Recovery and normal admission share this strict decoder; neither may replace
399
+ // unreadable signed routing with a convenient current default.
400
+ export function routeFromJson(json) {
401
+ if (json === null)
402
+ return null;
403
+ let parsed;
404
+ try {
405
+ parsed = JSON.parse(json);
406
+ }
407
+ catch {
408
+ return null;
409
+ }
410
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
411
+ return null;
412
+ const r = parsed;
413
+ // Exact keys (v48 integrity): the snapshot carries what canonicalRouteJson
414
+ // writes and nothing else — on the route, on every leg, on every leg's
415
+ // recommendation, and on every override.
416
+ if (!exactKeysOf(r, ["version", "risk", "qualityMode", "publication", "evidence", "posture", "demands", "legs", "overrides"]))
417
+ return null;
418
+ if (r["version"] !== ROUTE_VERSION)
419
+ return null;
420
+ if (!isRiskLevel(r["risk"]))
421
+ return null;
422
+ if (r["qualityMode"] !== "default" && r["qualityMode"] !== "strict")
423
+ return null;
424
+ if (r["publication"] !== "none" && r["publication"] !== "notify" && r["publication"] !== "automerge")
425
+ return null;
426
+ if (r["posture"] !== "economy" && r["posture"] !== "strong")
427
+ return null;
428
+ if (!stringList(r["demands"]))
429
+ return null;
430
+ const evidence = r["evidence"];
431
+ if (!Array.isArray(evidence) || !evidence.every(one => one === "check" || one === "screenshot" || one === "changed-path" || one === "manual-review"))
432
+ return null;
433
+ if (!Array.isArray(r["legs"]) || r["legs"].length !== PHASES.length)
434
+ return null;
435
+ const legs = [];
436
+ for (const [index, raw] of r["legs"].entries()) {
437
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw))
438
+ return null;
439
+ const leg = raw;
440
+ if (!exactKeysOf(leg, ["phase", "provider", "model", "tier", "chosen", "recommended", "reasons", "problem"]))
441
+ return null;
442
+ if (leg["phase"] !== PHASES[index])
443
+ return null;
444
+ if (!str(leg["provider"]) || !isProviderId(leg["provider"]))
445
+ return null;
446
+ if (!exactModel(leg["model"]))
447
+ return null;
448
+ if (leg["tier"] !== "routine" && leg["tier"] !== "strong")
449
+ return null;
450
+ if (leg["chosen"] !== "recommended" && leg["chosen"] !== "override" && leg["chosen"] !== "pinned")
451
+ return null;
452
+ const rec = leg["recommended"];
453
+ if (rec === null || typeof rec !== "object" || Array.isArray(rec))
454
+ return null;
455
+ const recommended = rec;
456
+ if (!exactKeysOf(recommended, ["provider", "model", "tier"]))
457
+ return null;
458
+ if (!str(recommended["provider"]) || !isProviderId(recommended["provider"]))
459
+ return null;
460
+ if (!exactModel(recommended["model"]))
461
+ return null;
462
+ if (recommended["tier"] !== "routine" && recommended["tier"] !== "strong")
463
+ return null;
464
+ if (!stringList(leg["reasons"]))
465
+ return null;
466
+ if (!strOrNull(leg["problem"]))
467
+ return null;
468
+ legs.push({
469
+ phase: PHASES[index],
470
+ provider: leg["provider"],
471
+ model: leg["model"],
472
+ tier: leg["tier"],
473
+ chosen: leg["chosen"],
474
+ recommended: { provider: recommended["provider"], model: recommended["model"], tier: recommended["tier"] },
475
+ reasons: [...leg["reasons"]],
476
+ problem: leg["problem"],
477
+ });
478
+ }
479
+ // The posture must be what the legs say — a snapshot claiming a strong
480
+ // posture over routine legs (or the reverse) is not one this policy wrote.
481
+ if ((drawsStrong(legs) ? "strong" : "economy") !== r["posture"])
482
+ return null;
483
+ const overrides = parseOverrides(r["overrides"]);
484
+ if (overrides === null)
485
+ return null;
486
+ return {
487
+ version: ROUTE_VERSION,
488
+ risk: r["risk"],
489
+ qualityMode: r["qualityMode"],
490
+ publication: r["publication"],
491
+ evidence: [...evidence].sort(),
492
+ posture: r["posture"],
493
+ demands: [...r["demands"]],
494
+ legs,
495
+ overrides,
496
+ };
497
+ }
498
+ /** Strict parse of an override list: one per phase, every field proved,
499
+ * every model exact. */
500
+ export function parseOverrides(raw) {
501
+ if (!Array.isArray(raw))
502
+ return null;
503
+ const overrides = [];
504
+ const seen = new Set();
505
+ for (const entry of raw) {
506
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry))
507
+ return null;
508
+ const o = entry;
509
+ if (!exactKeysOf(o, ["phase", "provider", "model", "by", "at"]))
510
+ return null;
511
+ if (!str(o["phase"]) || !PHASES.includes(o["phase"]))
512
+ return null;
513
+ if (seen.has(o["phase"]))
514
+ return null;
515
+ seen.add(o["phase"]);
516
+ if (!str(o["provider"]) || !isProviderId(o["provider"]))
517
+ return null;
518
+ if (!exactModel(o["model"]))
519
+ return null;
520
+ if (!str(o["by"]) || !str(o["at"]))
521
+ return null;
522
+ overrides.push({ phase: o["phase"], provider: o["provider"], model: o["model"], by: o["by"], at: o["at"] });
523
+ }
524
+ return overrides.sort((a, b) => PHASES.indexOf(a.phase) - PHASES.indexOf(b.phase));
525
+ }
526
+ /** The stored override list (a task-level column). Malformed reads as
527
+ * null — the caller files the scope unresolved rather than routing as if
528
+ * nobody had overridden anything. */
529
+ export function overridesFromJson(json) {
530
+ if (json === null)
531
+ return [];
532
+ try {
533
+ return parseOverrides(JSON.parse(json));
534
+ }
535
+ catch {
536
+ return null;
537
+ }
538
+ }
539
+ export function canonicalOverridesJson(overrides) {
540
+ if (overrides.length === 0)
541
+ return null;
542
+ return canonicalJson([...overrides]
543
+ .sort((a, b) => PHASES.indexOf(a.phase) - PHASES.indexOf(b.phase))
544
+ .map(one => ({ phase: one.phase, provider: one.provider, model: one.model, by: one.by, at: one.at })));
545
+ }
546
+ /** What actually runs: stronger agents only when a leg draws from one. */
547
+ export function postureWords(route) {
548
+ return drawsStrong(route.legs.filter(leg => leg.phase !== "review")) ? "stronger configured agents" : "everyday configured agents";
549
+ }
550
+ export function readinessWords(state, reason) {
551
+ if (state === "ready")
552
+ return "ready";
553
+ if (state === "unavailable")
554
+ return `UNAVAILABLE${reason === null ? "" : ` — ${reason}`}`;
555
+ return `readiness unknown${reason === null ? "" : ` — ${reason}`}`;
556
+ }
557
+ export function chosenWords(leg) {
558
+ return leg.chosen === "override" ? "overridden" : leg.chosen === "pinned" ? "pinned" : leg.tier === "strong" ? "recommended · strong" : "recommended";
559
+ }
560
+ /**
561
+ * The one-line Agents summary every surface can show above the details:
562
+ * agents grouped by identical pair, in phase order — "claude · sonnet
563
+ * plans, builds, and repairs; claude · opus reviews" — with the posture
564
+ * said honestly (stronger agents only when one is actually selected).
565
+ */
566
+ export function agentsSummary(route) {
567
+ const groups = [];
568
+ for (const leg of route.legs.filter(leg => leg.phase !== "review")) {
569
+ const spec = specWords(leg);
570
+ const group = groups.find(one => one.spec === spec);
571
+ if (group === undefined)
572
+ groups.push({ spec, verbs: [PHASE_VERB[leg.phase]] });
573
+ else
574
+ group.verbs.push(PHASE_VERB[leg.phase]);
575
+ }
576
+ const list = (verbs) => (verbs.length <= 1 ? verbs.join("") : verbs.length === 2 ? `${verbs[0]} and ${verbs[1]}` : `${verbs.slice(0, -1).join(", ")}, and ${verbs.at(-1)}`);
577
+ return groups.map(one => `${one.spec} ${list(one.verbs)}`).join("; ");
578
+ }
579
+ export function legLine(leg) {
580
+ return `${leg.phase.padEnd(7)}${specWords(leg)} [${chosenWords(leg)}] — ${readinessWords(leg.readiness, leg.readinessReason)}${leg.problem === null ? "" : ` — ${leg.problem}`}`;
581
+ }
582
+ /** The one projection CLI, task page, and chat all render from. */
583
+ export function projectRoute(route, readiness) {
584
+ const legs = route.legs.filter(leg => leg.phase !== "review").map(leg => {
585
+ const seen = readiness(leg.provider);
586
+ const state = seen === null ? "unknown" : seen.state;
587
+ const projected = {
588
+ ...leg,
589
+ reasons: leg.reasons.map(reason => reason.replace("builder and reviewer", "builder")),
590
+ readiness: state,
591
+ readinessReason: seen === null ? "no runner has reported this provider yet" : seen.reason,
592
+ readinessRunner: seen === null ? null : seen.runner,
593
+ observedAt: seen === null ? null : seen.observedAt,
594
+ words: "",
595
+ };
596
+ projected.words = legLine(projected);
597
+ return projected;
598
+ });
599
+ return {
600
+ digest: routeDigestOf(route),
601
+ risk: route.risk,
602
+ riskTitle: riskTitle(route.risk),
603
+ posture: drawsStrong(legs) ? "strong" : "economy",
604
+ postureWords: postureWords(route),
605
+ demands: route.demands.filter(reason => !/review/i.test(reason)),
606
+ legs,
607
+ summary: agentsSummary(route),
608
+ halted: legs.some(leg => leg.readiness === "unavailable"),
609
+ problems: routeProblems(route),
610
+ };
611
+ }
612
+ /** The approval-card lines: one route header, one line per leg, then the
613
+ * reasons indented — identical bytes on every text surface. */
614
+ export function routeWords(projection, indent = " ") {
615
+ const pad = `${indent} `;
616
+ return [
617
+ `${indent}route ${projection.riskTitle.toLowerCase()} · ${projection.postureWords} · ${projection.digest}`,
618
+ `${pad}${projection.summary}`,
619
+ ...projection.legs.flatMap(leg => [`${pad}${leg.words}`, ...leg.reasons.map(reason => `${pad} ${reason}`)]),
620
+ ...(projection.halted ? [`${pad}HALTED: a provider on this route is reported unavailable — nothing substitutes; override the phase or restore the provider`] : []),
621
+ ];
622
+ }
623
+ /** The empty readiness lookup: every provider unknown. */
624
+ export const NO_READINESS = () => null;
625
+ export const ROUTE_CHOSEN = ["recommended", "override", "pinned", "legacy", "fallback"];
626
+ /** A run's role, as the route phase it spends as: a scout runs the build
627
+ * leg's agent (the same sealed profile a build proves against). */
628
+ export function phaseOfRole(role) {
629
+ return role === "planner" ? "plan" : role === "repair" ? "repair" : role === "reviewer" ? "review" : "build";
630
+ }
631
+ /**
632
+ * Strict proof of a route stamp's SHAPE, before anything about it is
633
+ * believed: a known phase and provenance word, a known provider, a
634
+ * non-empty digest, and an exact model on every stamp except a legacy
635
+ * one (a pre-routing profile may carry no model). Anything else is the
636
+ * words for why — admission refuses on them, never coerces.
637
+ */
638
+ export function routeStampProblem(stamp) {
639
+ if (stamp === null || typeof stamp !== "object")
640
+ return "the route stamp is not an object";
641
+ const s = stamp;
642
+ if (!str(s["routeDigest"]))
643
+ return "the route stamp names no route digest";
644
+ if (!str(s["phase"]) || !PHASES.includes(s["phase"]))
645
+ return `the route stamp names an unknown phase ${JSON.stringify(s["phase"])}`;
646
+ if (!str(s["chosen"]) || !ROUTE_CHOSEN.includes(s["chosen"]))
647
+ return `the route stamp names an unknown provenance ${JSON.stringify(s["chosen"])}`;
648
+ if (!str(s["provider"]) || !isProviderId(s["provider"]))
649
+ return `the route stamp names an unknown provider ${JSON.stringify(s["provider"])}`;
650
+ const model = s["model"];
651
+ if (model !== null && !str(model))
652
+ return "the route stamp's model is neither an exact id nor null";
653
+ if (model !== null && !exactModel(model))
654
+ return `the route stamp's model ${JSON.stringify(model)} is not a model id (letters, digits, and . _ : / -, never leading with a dash)`;
655
+ if (model === null && s["chosen"] !== "legacy")
656
+ return `a ${String(s["chosen"])} leg names an exact model — the stamp carries none`;
657
+ return null;
658
+ }
@@ -0,0 +1,14 @@
1
+ import type { Store } from "./store.js";
2
+ export declare const PLAN_AUTO_SCHEMA = "CREATE TABLE IF NOT EXISTS plan_authorization (\n task_id TEXT PRIMARY KEY REFERENCES task(id),\n source_digest TEXT NOT NULL,\n scope_digest TEXT NOT NULL,\n mode_digest TEXT NOT NULL,\n signed_by TEXT NOT NULL,\n created_at TEXT NOT NULL\n);";
3
+ /** Join the console's authority-free proposal to the authenticated filing
4
+ * road in one transaction. Planning defers the seal until verified ingestion. */
5
+ export declare function applyModeToNewFiling(store: Store, taskId: string, actor: string, now: Date): void;
6
+ /** Called only by credentialed operator roads, never by proposal/intake
7
+ * code. This authorizes the exact filed contract, not arbitrary future
8
+ * planner text. Rewrites, mode renewal, expiry and revocation fail closed. */
9
+ export declare function authorizePlanUnderMode(store: Store, taskId: string, actor: string, now: Date): boolean;
10
+ /** Read-side status only; finalization still proves the authority anew. */
11
+ export declare function planAutoPending(store: Store, taskId: string, now: Date): boolean;
12
+ /** Inside the verified planner finalization transaction, after the source,
13
+ * artifact, contract changes and lease fence have all been checked. */
14
+ export declare function sealUnchangedPlanUnderMode(store: Store, taskId: string, sourceDigest: string, runId: number, eligible: boolean, now: Date): boolean;