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
package/dist/demo.js ADDED
@@ -0,0 +1,992 @@
1
+ /**
2
+ * `toolroll demo` (adoption track, step 4) — a seeded, throwaway
3
+ * sandbox: ninety seconds from npx to seeing the product mid-flight, with
4
+ * zero real repos, zero agents, zero spend.
5
+ *
6
+ * The honesty contract (Codex adoption review, findings 8 and 9):
7
+ *
8
+ * - The database is stamped `demo` BEFORE any row exists — an append-only
9
+ * installation fact with no unset API. Every spending or external-effect
10
+ * command (tick, watch, build, publish, reconcile, daemon, bridge,
11
+ * outbox deliver, intake) fails closed on the stamp, so a kept sandbox
12
+ * can never be mistaken for real work by a worker pointed at it later.
13
+ * The console banner is decoration; the fence is enforcement.
14
+ * - The seeded history is SYNTHETIC and does not pretend otherwise: runs
15
+ * are written with the same permissive store methods the test suite
16
+ * uses, inside a database that can never join operational history,
17
+ * because nothing that computes provider success or spends quota will
18
+ * open it (the fence again).
19
+ * - The throwaway password goes to the terminal and to a mode-0600 file
20
+ * inside the sandbox — NEVER into the --json envelope, a URL, or the
21
+ * database.
22
+ *
23
+ * Everything lives under one mkdtemp directory: database, evidence,
24
+ * "repos". Ctrl-C tears it down; --keep preserves it (still fenced).
25
+ */
26
+ import { execFileSync } from "node:child_process";
27
+ import { mkdirSync, mkdtempSync, realpathSync, writeFileSync } from "node:fs";
28
+ import { tmpdir } from "node:os";
29
+ import { join } from "node:path";
30
+ import { randomBytes } from "node:crypto";
31
+ import { openStore } from "./store.js";
32
+ import { addApprover, propose, approve } from "./scope.js";
33
+ import { legOf, routeDigestOf } from "./phase-routing.js";
34
+ import { acquire } from "./claim.js";
35
+ import { register } from "./runner.js";
36
+ import { approveRoutine, fireRoutine } from "./routine.js";
37
+ import { fileTaskProposal, fileRoutineProposal } from "./proposal.js";
38
+ import { storeEvidence, budgetedStatJson, imageDimensions } from "./evidence.js";
39
+ import { parseProof, adjudicate } from "./proof.js";
40
+ import { parseExecutionPlanDocument, milestonesOf } from "./plan.js";
41
+ import { maybeTriggerRepair } from "./dispose.js";
42
+ import { deflateSync } from "node:zlib";
43
+ import { FLOW_TEMPLATES } from "./flows.js";
44
+ // The demo demonstrates a CONFIGURED install: routing is named once, the
45
+ // way `config set build` would, so approvals bind it like production.
46
+ const DEMO_PROFILE = {
47
+ provider: "claude",
48
+ model: "sonnet",
49
+ permissionArgv: "auto",
50
+ maxTurns: 1_000, repairMaxTurns: 4, timeoutSeconds: 1_200, timeoutKind: "idle", repairTimeoutSeconds: 300,
51
+ repairModel: "inherit",
52
+ };
53
+ /** The exact route authority a demo run presents at admission (v48 authority repair): the
54
+ * store dictates nothing, so every routed row here presents the sealed (or,
55
+ * for a planner, the working) leg exactly as a real dispatch would. */
56
+ function presentedRoute(store, taskRef, role, spend = { provider: "claude", model: null }) {
57
+ // A task with no scope presents the bare word `legacy` for the exact
58
+ // pair it spends as (atomic authority closure) — nothing opens unstamped.
59
+ const authority = store.routeAuthorityFor(taskRef, role) ?? store.routeAuthorityFor(taskRef, role, null, spend);
60
+ if (authority === null || !authority.ok)
61
+ throw new Error(`demo seed: ${authority === null ? "no task" : authority.problem}`);
62
+ return { route: authority.stamp };
63
+ }
64
+ /** A believable patch for the finished run's review card. */
65
+ const DEMO_PATCH = `diff --git a/src/payout.ts b/src/payout.ts
66
+ index 3f1c2aa..9e07b41 100644
67
+ --- a/src/payout.ts
68
+ +++ b/src/payout.ts
69
+ @@ -41,7 +41,9 @@ export function settle(cents: number, rate: number): number {
70
+ - return Math.round(cents * rate);
71
+ + // Banker's rounding: half-cents were accumulating a payable drift of
72
+ + // ~$14/day across the fleet. Verified against the ledger fixtures.
73
+ + return Math.round(cents * rate * 100) / 100;
74
+ }
75
+
76
+ export function settleAll(rows: PayoutRow[]): number {
77
+ diff --git a/src/payout.test.ts b/src/payout.test.ts
78
+ index 11aa0b2..c44d1f7 100644
79
+ --- a/src/payout.test.ts
80
+ +++ b/src/payout.test.ts
81
+ @@ -12,4 +12,12 @@ describe("settle", () => {
82
+ + test("half-cent boundaries do not drift", () => {
83
+ + expect(settle(1005, 0.031)).toBe(31.16);
84
+ + });
85
+ `;
86
+ const DEMO_HANDOFF = {
87
+ schema: 1,
88
+ outcome: "built",
89
+ committed: true,
90
+ conclusion: "Fixed the payout rounding drift: settle() now rounds at cent precision instead of accumulating half-cent errors. Added boundary tests against the ledger fixtures. All 214 tests pass.",
91
+ changes: [
92
+ "Rounded settlement values at cent precision in src/payout.ts.",
93
+ "Added ledger-fixture coverage for half-cent boundaries.",
94
+ ],
95
+ verification: ["All 214 tests pass, including the new rounding boundary cases."],
96
+ followUps: [],
97
+ decisionsIncorporated: [],
98
+ };
99
+ /** The evidence bundle's own manifest (Acceptance Contract v2 demo): the
100
+ * seeded sandbox answers its OWN signed rubric by exact id, with typed
101
+ * evidence references — the same shape a real builder writes — so a
102
+ * fresh install sees the finished feature end to end, not a stub. */
103
+ const DEMO_PROOF = {
104
+ version: 1,
105
+ criteria: [
106
+ {
107
+ id: "c1",
108
+ statement: "Ledger-fixture tests demonstrate the half-cent drift is gone.",
109
+ verdict: "met",
110
+ how: "Added and ran boundary tests against the ledger fixtures.",
111
+ evidence: [
112
+ { kind: "check", ref: "npm test" },
113
+ { kind: "changed-path", ref: "src/payout.ts" },
114
+ { kind: "changed-path", ref: "src/payout.test.ts" },
115
+ ],
116
+ },
117
+ {
118
+ id: "c2",
119
+ statement: "The human console formatter still renders payout dashboards.",
120
+ verdict: "met",
121
+ how: "Ran the dashboard's own snapshot tests.",
122
+ evidence: [{ kind: "screenshot", ref: "evidence/payout-dashboard.png" }],
123
+ },
124
+ ],
125
+ checks: [{ command: "npm test", exitCode: 0, summary: "214 tests passed, including the new rounding boundary cases." }],
126
+ changed: ["src/payout.ts", "src/payout.test.ts"],
127
+ // One declared caveat, so the review cockpit's "caveats" row shows a real
128
+ // agent-declared concern in the sandbox rather than only its empty state.
129
+ caveats: ["The dashboard screenshot was captured against the ledger fixtures, not production data."],
130
+ screenshots: [{ path: "evidence/payout-dashboard.png", caption: "Payout dashboard after the fix — totals match the ledger." }],
131
+ };
132
+ const DEMO_COPY_PATCH = `diff --git a/src/inbox-copy.ts b/src/inbox-copy.ts
133
+ index a1b2c3d..d4e5f6a 100644
134
+ --- a/src/inbox-copy.ts
135
+ +++ b/src/inbox-copy.ts
136
+ @@ -8,5 +8,7 @@ export const EMPTY_STATE = {
137
+ - body: "Nothing here.",
138
+ + body: "Nothing needs you right now — approvals, decisions, and proofs waiting on a human all land in this list.",
139
+ };
140
+ +
141
+ +export const EMPTY_STATE_ILLUSTRATION = "quiet-inbox";
142
+ `;
143
+ const DEMO_COPY_HANDOFF = {
144
+ schema: 1,
145
+ outcome: "built",
146
+ committed: true,
147
+ conclusion: "Rewrote the inbox's empty-state copy so it explains why the list is empty instead of just saying so.",
148
+ changes: ["Replaced the empty-state body copy in src/inbox-copy.ts."],
149
+ verification: ["Opened the inbox pane with zero items and read the new copy."],
150
+ followUps: [],
151
+ decisionsIncorporated: [],
152
+ };
153
+ /** A criterion whose only required evidence is `manual-review` (Acceptance
154
+ * Contract v2, review finding): no check, no screenshot, nothing a machine
155
+ * can resolve on its own — a human has to read the copy and say it is
156
+ * good. The seeded verdict below is computed by the REAL adjudicate(),
157
+ * so the sandbox proves the fix live: this build reads "needs
158
+ * verification", never "verified" or "attested", until an operator uses
159
+ * the same "accept anyway" act a short/refuted proof already offers. */
160
+ const DEMO_COPY_PROOF = {
161
+ version: 1,
162
+ criteria: [
163
+ {
164
+ id: "c1",
165
+ statement: "An operator confirms the new empty-state copy reads clearly.",
166
+ verdict: "met",
167
+ how: "Opened the inbox pane with zero items and read the new copy aloud.",
168
+ evidence: [{ kind: "manual-review", ref: "read the new copy in src/inbox-copy.ts" }],
169
+ },
170
+ ],
171
+ checks: [],
172
+ changed: ["src/inbox-copy.ts"],
173
+ caveats: [],
174
+ screenshots: [],
175
+ };
176
+ const DEMO_EXECUTION_PLAN = [
177
+ "## Approach",
178
+ "Move the request logger to structured JSON lines at the existing boundary, then update only the dashboards that still parse the legacy text format.",
179
+ "## Milestones",
180
+ "1. Trace the logger and the two dashboard consumers.",
181
+ "2. Add the JSON-line formatter without changing local human-readable output.",
182
+ "3. Migrate both dashboard parsers and cover the compatibility boundary.",
183
+ "## Dependencies",
184
+ "- The collector accepts one JSON object per line.",
185
+ "- Local development keeps the existing console formatter.",
186
+ "## Risks",
187
+ "- A partial rollout could mix formats; keep parsing compatibility at the collector boundary during the change.",
188
+ "- Dashboard field names could drift; lock them with fixture-based checks.",
189
+ "## Proof",
190
+ "- c1 — run the logger and dashboard fixture checks and review the rendered JSON lines.",
191
+ "",
192
+ ].join("\n");
193
+ /** Adaptive execution plans (v44): the "building" demo task's revision 1,
194
+ * the planner's original plan before the running build's own evidence
195
+ * revised it. */
196
+ const DEMO_BUILDING_PLAN_V1 = [
197
+ "## Approach",
198
+ "Add a per-endpoint token-bucket limiter and enforce it before dispatch, reusing the existing webhook queue.",
199
+ "## Milestones",
200
+ "1. Add a per-endpoint token-bucket limiter.",
201
+ "2. Enforce the limiter before dispatch.",
202
+ "3. Add timeout budgets per endpoint.",
203
+ "4. Cover the limiter and budget interaction with load tests.",
204
+ "## Dependencies",
205
+ "- The existing webhook queue exposes a stable per-endpoint key.",
206
+ "## Risks",
207
+ "- A shared limiter could starve a burst-y but healthy endpoint; scope it per-endpoint from the start.",
208
+ "## Proof",
209
+ "- c1 — load-test one slow and one healthy endpoint together.",
210
+ "",
211
+ ].join("\n");
212
+ /** Revision 2: a prior builder attempt found the named dependency was
213
+ * false (the queue has no stable per-endpoint key) and filed a bounded,
214
+ * evidence-linked, plan-only revision — auto-applied, no operator wait,
215
+ * exactly what c3/c4's plan-only path resumes without another approval. */
216
+ const DEMO_BUILDING_PLAN_V2 = [
217
+ "## Approach",
218
+ "Derive a stable per-endpoint key from the normalized webhook URL host, since the queue has none; add a per-endpoint token-bucket limiter keyed on it and enforce it before dispatch.",
219
+ "## Milestones",
220
+ "1. Derive a stable per-endpoint key from the normalized URL host.",
221
+ "2. Add a per-endpoint token-bucket limiter.",
222
+ "3. Enforce the limiter before dispatch.",
223
+ "4. Confirm the dispatch feature flag is enabled in every deploy target.",
224
+ "5. Add timeout budgets per endpoint.",
225
+ "6. Cover the limiter and budget interaction with load tests.",
226
+ "## Dependencies",
227
+ "- None found — the per-endpoint key is now derived, not assumed.",
228
+ "## Risks",
229
+ "- A shared limiter could starve a burst-y but healthy endpoint; scope it per-endpoint from the start.",
230
+ "## Proof",
231
+ "- c1 — load-test one slow and one healthy endpoint together.",
232
+ "",
233
+ ].join("\n");
234
+ const DEMO_BUILDING_REVISION_REASON = "The webhook queue has no stable per-endpoint key (src/webhooks/queue.ts) — the planned limiter needed one, so this revision derives it from the normalized URL host instead.";
235
+ const DEMO_BUILDING_REVISION_EVIDENCE = "src/webhooks/queue.ts";
236
+ /**
237
+ * A minimal, real, uncompressed-per-scanline PNG encoder — no image
238
+ * library, just IHDR + one zlib-deflated IDAT + IEND. Used only to give
239
+ * the demo's screenshot evidence REAL, non-placeholder dimensions and
240
+ * byte size (Acceptance Contract v2: a screenshot criterion needs a real
241
+ * file of at least 320×200 and meaningful bytes to verify) without
242
+ * shipping a binary asset for a run nobody actually captured.
243
+ */
244
+ function encodeDemoPng(width, height, rgb) {
245
+ const crcTable = Array.from({ length: 256 }, (_, n) => {
246
+ let c = n;
247
+ for (let k = 0; k < 8; k++)
248
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
249
+ return c >>> 0;
250
+ });
251
+ const crc32 = (buf) => {
252
+ let c = 0xffffffff;
253
+ for (const byte of buf)
254
+ c = crcTable[(c ^ byte) & 0xff] ^ (c >>> 8);
255
+ return (c ^ 0xffffffff) >>> 0;
256
+ };
257
+ const chunk = (type, data) => {
258
+ const len = Buffer.alloc(4);
259
+ len.writeUInt32BE(data.length, 0);
260
+ const typed = Buffer.concat([Buffer.from(type, "ascii"), data]);
261
+ const crc = Buffer.alloc(4);
262
+ crc.writeUInt32BE(crc32(typed), 0);
263
+ return Buffer.concat([len, typed, crc]);
264
+ };
265
+ const ihdr = Buffer.alloc(13);
266
+ ihdr.writeUInt32BE(width, 0);
267
+ ihdr.writeUInt32BE(height, 4);
268
+ ihdr[8] = 8; // bit depth
269
+ ihdr[9] = 2; // color type: RGB
270
+ // A faint vertical gradient so the file is not one repeated byte —
271
+ // "meaningful", not merely large.
272
+ const stride = width * 3;
273
+ const raw = Buffer.alloc((stride + 1) * height);
274
+ for (let y = 0; y < height; y++) {
275
+ const rowStart = y * (stride + 1);
276
+ raw[rowStart] = 0; // filter: none
277
+ const shade = Math.round((y / Math.max(1, height - 1)) * 40);
278
+ for (let x = 0; x < width; x++) {
279
+ const p = rowStart + 1 + x * 3;
280
+ raw[p] = Math.min(255, rgb[0] + shade);
281
+ raw[p + 1] = Math.min(255, rgb[1] + shade);
282
+ raw[p + 2] = Math.min(255, rgb[2] + shade);
283
+ }
284
+ }
285
+ const idat = deflateSync(raw);
286
+ return Buffer.concat([
287
+ Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
288
+ chunk("IHDR", ihdr),
289
+ chunk("IDAT", idat),
290
+ chunk("IEND", Buffer.alloc(0)),
291
+ ]);
292
+ }
293
+ /** A real 640×400 PNG — comfortably past the 320×200 / meaningful-byte-size
294
+ * floor a screenshot criterion needs to verify. */
295
+ const DEMO_SCREENSHOT_PNG = encodeDemoPng(640, 400, [16, 24, 32]);
296
+ /**
297
+ * Seed a believable fleet mid-flight. The store MUST already carry the
298
+ * demo stamp — this function refuses to seed an unfenced database, so no
299
+ * caller can accidentally write synthetic history somewhere real.
300
+ */
301
+ export function seedDemo(store, repos, evidenceRoot, now) {
302
+ if (!store.isDemo()) {
303
+ throw new Error("seedDemo refuses an unfenced database — stamp it demo first");
304
+ }
305
+ const password = `demo-${randomBytes(9).toString("base64url")}`;
306
+ const added = addApprover(store, "demo", now, undefined, undefined, {}, password);
307
+ if (!added.ok)
308
+ throw new Error(`demo approver: ${added.reason}`);
309
+ const token = password;
310
+ const hoursAgo = (hours) => new Date(now.getTime() - hours * 3_600_000);
311
+ // Configure the install before filing any task, exactly as a normal first
312
+ // run does. Every seeded scope can then be approved from the demo instead
313
+ // of inheriting an artificial "model not set" blocker.
314
+ store.setPhaseConfig("installation", "build", "claude", "sonnet", "demo", now);
315
+ // Approvals bind EXACT routing for every phase (v47): the planner and
316
+ // reviewer name their models too, or no scope could file.
317
+ store.setPhaseConfig("installation", "plan", "claude", "sonnet", "demo", now);
318
+ store.setPhaseConfig("installation", "review", "claude", "sonnet", "demo", now);
319
+ // The strong tier (v47): the named agents high-risk, strict, screenshot-
320
+ // proof, and automerge routes reach for — configured, never inferred.
321
+ store.setPhaseTierConfig("installation", "build", "strong", "claude", "opus", "demo", now);
322
+ store.setPhaseTierConfig("installation", "review", "strong", "codex", "gpt-5-codex", "demo", now);
323
+ // The demo's builder goes through the REAL claim machinery, and the claim
324
+ // primitive proves identity and repo binding in-transaction — so the demo
325
+ // runner is registered like a real one, bound to both demo repos.
326
+ const nightShift = register(store, {
327
+ name: "night-shift-1",
328
+ host: "demo",
329
+ capacity: 2,
330
+ repos: [repos.api, repos.web],
331
+ now: hoursAgo(30),
332
+ });
333
+ // What the demo machine observed about each provider without spending
334
+ // (v47): claude installed but unproven (no non-spending login check),
335
+ // codex logged in, openrouter without a key, gemini not installed.
336
+ store.recordProviderReadiness("night-shift-1", [
337
+ { provider: "claude", state: "unknown", reason: "installed (claude 2.1.0); no non-spending login check exists — a real run is the proof", probe: "version" },
338
+ { provider: "codex", state: "ready", reason: "installed (codex 0.62.0); logged in as demo@standing-orders.dev", probe: "identity" },
339
+ { provider: "openrouter", state: "unavailable", reason: "OPENROUTER_API_KEY is absent from this runner's environment", probe: "key" },
340
+ { provider: "gemini", state: "unavailable", reason: "`gemini` is not installed on this runner's PATH", probe: "version" },
341
+ ], hoursAgo(0.2));
342
+ const genericAcceptance = [
343
+ { id: "c1", statement: "The described change is made and verified.", how: null, evidence: ["manual-review"] },
344
+ ];
345
+ const task = (id, title, repo, goal, acceptance = genericAcceptance) => {
346
+ const made = fileTaskProposal(store, { id, title, repo, ...(goal === undefined ? {} : { goal, acceptance }), filedVia: "demo" }, hoursAgo(30));
347
+ if (!made.ok)
348
+ throw new Error(`seed task ${id}: ${made.reason}`);
349
+ return made.id;
350
+ };
351
+ // --- needs-you: an approval waiting -----------------------------------
352
+ const planned = task("rotate-log-format", "Rotate the request-log format to JSON lines", repos.web, "Switch the request logger to JSON lines so the collector stops parsing free text. Keep the human console formatter for local dev. Migrate the two dashboards that grep the old format.");
353
+ const plannedRef = store.refFor("built-in", planned).id;
354
+ // An explainable route (v47): the operator declared elevated risk and
355
+ // overrode the reviewer, so the ceremony shows a recommended leg, a
356
+ // strong-tier leg, and an overridden leg side by side, with the runner's
357
+ // readiness per provider.
358
+ store.editTaskRoute(plannedRef, { by: "demo", authenticate: () => ({ ok: true }), risk: "elevated" }, hoursAgo(3.5));
359
+ store.editTaskRoute(plannedRef, { by: "demo", authenticate: () => ({ ok: true }), override: { phase: "review", provider: "claude", model: "opus" } }, hoursAgo(3.2));
360
+ store.setPlanState(plannedRef, "drafted");
361
+ const plannerRun = store.startRun({
362
+ taskRef: plannedRef,
363
+ leaseId: "demo-lease-plan",
364
+ runner: "night-shift-1",
365
+ role: "planner",
366
+ branch: `toolroll-plan/${planned}`,
367
+ worktree: join(repos.web, ".demo-worktree-plan"),
368
+ now: hoursAgo(3),
369
+ ...presentedRoute(store, plannedRef, "planner"),
370
+ });
371
+ storeEvidence(store, evidenceRoot, plannerRun, "plan", "plan.md", Buffer.from(DEMO_EXECUTION_PLAN, "utf8"), "planner handoff (verified tree) [demo: synthetic]", hoursAgo(2.8));
372
+ store.finishRun(plannerRun, { outcome: "built", reason: "plan-drafted", now: hoursAgo(2.8) });
373
+ // --- needs-you: a blocking decision -----------------------------------
374
+ const asking = task("choose-retry-policy", "Choose the webhook retry policy", repos.api, "Give outbound webhooks a bounded retry policy with dead-lettering.");
375
+ // The build that parked this question ran under an approval (v48: a
376
+ // routed task opens no run without its sealed route).
377
+ approve(store, asking, "demo", hoursAgo(3), store.getScope(asking)?.digest ?? "", token);
378
+ const askingRun = store.startRun({
379
+ taskRef: store.refFor("built-in", asking).id,
380
+ leaseId: "demo-lease-ask",
381
+ runner: "night-shift-1",
382
+ branch: `toolroll/${asking}`,
383
+ worktree: join(repos.api, ".demo-worktree"),
384
+ now: hoursAgo(2),
385
+ ...presentedRoute(store, store.refFor("built-in", asking).id, "builder"),
386
+ });
387
+ store.saveDecision({
388
+ run: askingRun,
389
+ urgency: "blocking",
390
+ recap: "Retries currently hammer failing endpoints forever. The collector at partner X was down 40 minutes yesterday and we sent 8,400 attempts.",
391
+ question: "How should webhook retries back off?",
392
+ options: [
393
+ {
394
+ id: "exp",
395
+ label: "Exponential, cap 1h, dead-letter after 24h",
396
+ consequence: "Slowest to give up; partners see at most ~30 attempts/day.",
397
+ reversible: true,
398
+ },
399
+ {
400
+ id: "fixed",
401
+ label: "Fixed 5-minute retries, dead-letter after 2h",
402
+ consequence: "Faster surrender; brief outages on their side can drop events.",
403
+ reversible: true,
404
+ },
405
+ ],
406
+ recommendation: "exp",
407
+ }, hoursAgo(1));
408
+ // --- building now ------------------------------------------------------
409
+ const building = task("harden-webhook-retries", "Harden webhook delivery against slow consumers", repos.api, "Add per-endpoint concurrency caps and timeout budgets to webhook delivery.");
410
+ const proposedBuilding = propose(store, {
411
+ profile: DEMO_PROFILE,
412
+ taskId: building,
413
+ goal: "Add per-endpoint concurrency caps and timeout budgets to webhook delivery.",
414
+ outOfScope: "No changes to the public webhook payload shape.",
415
+ touches: ["src/webhooks/"],
416
+ acceptance: [
417
+ { id: "c1", statement: "Slow consumers cannot starve other endpoints' delivery.", how: "Load-test one slow and one healthy endpoint together.", evidence: ["check"] },
418
+ ],
419
+ now: hoursAgo(21),
420
+ });
421
+ approve(store, building, "demo", hoursAgo(20), proposedBuilding.digest, token);
422
+ const buildingRef = store.refFor("built-in", building).id;
423
+ // Adaptive execution plans (v44): the planner's revision 1, and a prior
424
+ // builder attempt that found a stated dependency false and filed a
425
+ // bounded, evidence-linked, plan-only revision — auto-applied, no
426
+ // operator wait (c3, c4's plan-only path). The CURRENT live build below
427
+ // resumes under revision 2, exactly as a real fresh claim would.
428
+ const buildingPlannerRun = store.startRun({
429
+ taskRef: buildingRef,
430
+ leaseId: "demo-lease-plan-2",
431
+ runner: "night-shift-1",
432
+ role: "planner",
433
+ branch: `toolroll-plan/${building}`,
434
+ worktree: join(repos.api, ".demo-worktree-plan-2"),
435
+ now: hoursAgo(19),
436
+ ...presentedRoute(store, buildingRef, "planner"),
437
+ });
438
+ const buildingRev1Artifact = storeEvidence(store, evidenceRoot, buildingPlannerRun, "plan", "plan.md", Buffer.from(DEMO_BUILDING_PLAN_V1, "utf8"), "planner handoff (verified tree) [demo: synthetic]", hoursAgo(18.9));
439
+ store.finishRun(buildingPlannerRun, { outcome: "built", reason: "plan-drafted", now: hoursAgo(18.9) });
440
+ const buildingRev1Sha = store.getArtifact(buildingRev1Artifact)?.sha256 ?? null;
441
+ const buildingPriorRun = store.startRun({
442
+ taskRef: buildingRef,
443
+ leaseId: "demo-lease-prior",
444
+ runner: "night-shift-1",
445
+ branch: `toolroll/${building}`,
446
+ worktree: join(repos.api, ".demo-worktree-1"),
447
+ now: hoursAgo(2),
448
+ ...presentedRoute(store, buildingRef, "builder"),
449
+ });
450
+ const buildingRev2Artifact = storeEvidence(store, evidenceRoot, buildingPriorRun, "plan", "revision.md", Buffer.from(DEMO_BUILDING_PLAN_V2, "utf8"), "builder-filed revision proposal [demo: synthetic]", hoursAgo(1.6));
451
+ const buildingRev2Id = store.insertPlanRevision({
452
+ taskRef: buildingRef,
453
+ revision: 2,
454
+ artifact: buildingRev2Artifact,
455
+ parentHash: buildingRev1Sha,
456
+ reason: DEMO_BUILDING_REVISION_REASON,
457
+ evidenceLink: DEMO_BUILDING_REVISION_EVIDENCE,
458
+ author: `builder:${buildingPriorRun}`,
459
+ originRun: buildingPriorRun,
460
+ kind: "builder-proposal",
461
+ authorityKind: "plan-only",
462
+ authorityDigest: "demo-authority-digest-unchanged",
463
+ changedFields: [],
464
+ status: "applied",
465
+ }, hoursAgo(1.6));
466
+ store.setRunPlanRevision(buildingPriorRun, buildingRev2Id, "demo-authority-digest-unchanged");
467
+ store.finishRun(buildingPriorRun, { outcome: "refused", reason: "plan-revised", now: hoursAgo(1.6) });
468
+ // The board's "building" lane keys off a live claim — take one through
469
+ // the real claim machinery so the card wears worker and lease honestly.
470
+ acquire(store, buildingRef, "night-shift-1", {
471
+ now: hoursAgo(0.4),
472
+ token: nightShift.token,
473
+ ttlMs: 4 * 3_600_000,
474
+ });
475
+ const liveRun = store.startRun({
476
+ taskRef: buildingRef,
477
+ leaseId: "demo-lease-live",
478
+ runner: "night-shift-1",
479
+ branch: `toolroll/${building}`,
480
+ worktree: join(repos.api, ".demo-worktree-2"),
481
+ now: hoursAgo(0.4),
482
+ ...presentedRoute(store, buildingRef, "builder"),
483
+ });
484
+ store.setRunPlanRevision(liveRun, buildingRev2Id, "demo-authority-digest-unchanged");
485
+ {
486
+ // Mixed milestone states (c1, c2): completed, in progress, blocked, and
487
+ // pending all shown at once on the live build's own checkpoint.
488
+ const buildingRev2Parsed = parseExecutionPlanDocument(DEMO_BUILDING_PLAN_V2);
489
+ if (!buildingRev2Parsed.ok)
490
+ throw new Error("demo building revision 2 plan is malformed");
491
+ const buildingMilestones = milestonesOf(buildingRev2Parsed.document);
492
+ const state = (index) => index === 0 || index === 1 ? "completed" : index === 2 ? "current" : index === 3 ? "blocked" : "pending";
493
+ const note = (index) => index === 3 ? "the flag is off in the staging deploy target — confirming before enforcing" : null;
494
+ store.insertRunCheckpoint({
495
+ run: liveRun,
496
+ taskRef: buildingRef,
497
+ planRevision: buildingRev2Id,
498
+ snapshot: {
499
+ revisionHash: store.getArtifact(buildingRev2Artifact)?.sha256 ?? "",
500
+ milestones: buildingMilestones.map((one, index) => ({ id: one.id, state: state(index), note: note(index) })),
501
+ },
502
+ }, hoursAgo(0.1));
503
+ }
504
+ store.setRunPhase(liveRun, "agent-running");
505
+ store.setTaskState(building, "running", hoursAgo(0.4));
506
+ // --- done recently: a finished run with a reviewable terminal diff ----
507
+ const done = task("fix-payout-rounding", "Fix the payout rounding drift", repos.api, "Find and fix the half-cent drift in payout settlement; prove it with ledger-fixture tests.");
508
+ const doneProposed = propose(store, {
509
+ profile: DEMO_PROFILE,
510
+ taskId: done,
511
+ goal: "Find and fix the half-cent drift in payout settlement; prove it with ledger-fixture tests.",
512
+ outOfScope: "No ledger schema changes.",
513
+ touches: ["src/payout.ts", "src/payout.test.ts"],
514
+ acceptance: [
515
+ { id: "c1", statement: "Ledger-fixture tests demonstrate the half-cent drift is gone.", how: null, evidence: ["check", "changed-path"] },
516
+ { id: "c2", statement: "The human console formatter still renders payout dashboards.", how: null, evidence: ["screenshot"] },
517
+ ],
518
+ now: hoursAgo(27),
519
+ });
520
+ approve(store, done, "demo", hoursAgo(26), doneProposed.digest, token);
521
+ // Route provenance (v47): the demo's finished build names the exact
522
+ // agent it spent as, under the route its approval sealed — the same
523
+ // stamp a real admission writes.
524
+ const doneRoute = store.approvedRouteOf(done);
525
+ const doneRun = store.startRun({
526
+ taskRef: store.refFor("built-in", done).id,
527
+ leaseId: "demo-lease-done",
528
+ runner: "night-shift-2",
529
+ branch: `toolroll/${done}`,
530
+ worktree: join(repos.api, ".demo-worktree-3"),
531
+ now: hoursAgo(9),
532
+ ...(doneRoute === null ? {} : { route: { routeDigest: routeDigestOf(doneRoute), phase: "build", provider: legOf(doneRoute, "build").provider, model: legOf(doneRoute, "build").model, chosen: legOf(doneRoute, "build").chosen } }),
533
+ });
534
+ store.stampRun(doneRun, { baseRevision: "4b825dc642cb6eb9a060e54bf8d69288fbee4904", scopeDigest: doneProposed.digest });
535
+ storeEvidence(store, evidenceRoot, doneRun, "terminal-diff", "terminal-diff.patch", Buffer.from(DEMO_PATCH, "utf8"), "git diff --no-ext-diff --no-textconv --no-color 4b825dc6..HEAD (exit 0) [demo: synthetic]", hoursAgo(8.5));
536
+ const stat = {
537
+ schema: 1,
538
+ base: "4b825dc642cb6eb9a060e54bf8d69288fbee4904",
539
+ head: "9e07b4152aa01c9f3d7700e54bf8d69288fbe777",
540
+ fileCount: 2,
541
+ additions: 13,
542
+ deletions: 1,
543
+ binaryCount: 0,
544
+ files: [
545
+ { path: "src/payout.ts", additions: 4, deletions: 1 },
546
+ { path: "src/payout.test.ts", additions: 9, deletions: 0 },
547
+ ],
548
+ filesTruncated: false,
549
+ };
550
+ storeEvidence(store, evidenceRoot, doneRun, "diff-stat", "diff-stat.json", budgetedStatJson(stat), "parsed from git diff --numstat -z [demo: synthetic]", hoursAgo(8.5));
551
+ storeEvidence(store, evidenceRoot, doneRun, "handoff", "handoff.json", Buffer.from(JSON.stringify(DEMO_HANDOFF, null, 2), "utf8"), "composed at completion [demo: synthetic]", hoursAgo(8.4));
552
+ // The evidence bundle (Priority 2): a validated proof, its claimed
553
+ // screenshot stored as immutable image evidence, the plane's own re-run
554
+ // check, and the closed verdict — computed once, exactly as the real
555
+ // builder would leave it, so a fresh install sees the finished feature.
556
+ storeEvidence(store, evidenceRoot, doneRun, "proof", "proof.json", Buffer.from(JSON.stringify(DEMO_PROOF, null, 2), "utf8"), "agent-authored proof (validated, re-serialized) [demo: synthetic]", hoursAgo(8.4));
557
+ storeEvidence(store, evidenceRoot, doneRun, "screenshot", "screenshot-demo.png", DEMO_SCREENSHOT_PNG, "agent-claimed screenshot at evidence/payout-dashboard.png (validated png) [demo: synthetic]", hoursAgo(8.4));
558
+ storeEvidence(store, evidenceRoot, doneRun, "check-log", "check-log.txt", Buffer.from(`$ npm test\n(exit 0)\n\n--- stdout ---\n214 tests passed.\n\n--- stderr ---\n`, "utf8"), `sh -c "npm test" (exit 0) [demo: synthetic]`, hoursAgo(8.4));
559
+ // The verdict AND the criterion-to-evidence matrix are computed by the
560
+ // real adjudicate() — same function, same rules the builder runs —
561
+ // never hand-authored, so the seeded sandbox shows exactly what the
562
+ // feature actually renders, dimensions read from the real PNG above.
563
+ const demoProofParse = parseProof(JSON.stringify(DEMO_PROOF));
564
+ const demoPngDims = imageDimensions(DEMO_SCREENSHOT_PNG, "png");
565
+ const demoAdjudicated = adjudicate({
566
+ proofArtifactPresent: true,
567
+ proofParse: demoProofParse,
568
+ handoffPresent: true,
569
+ terminalDiffPresent: true,
570
+ terminalDiffCaptureStatus: "ok",
571
+ diffStat: { captured: true, truncated: false, paths: new Set(stat.files.map(one => one.path)) },
572
+ verifyCommand: { configured: true, ran: true, exitCode: 0 },
573
+ screenshots: [{ path: "evidence/payout-dashboard.png", ok: true, bytes: DEMO_SCREENSHOT_PNG.length, dims: demoPngDims }],
574
+ approvedCriteria: doneProposed.acceptance,
575
+ });
576
+ store.saveProofVerdict(doneRun, demoAdjudicated.verdict, demoAdjudicated.reasons, hoursAgo(8.4), demoAdjudicated.matrix);
577
+ store.finishRun(doneRun, { outcome: "built", committed: true, now: hoursAgo(8.4) });
578
+ store.setTaskState(done, "done", hoursAgo(8.4));
579
+ store.addRunNote(doneRun, "demo", "Reviewed the diff — the fixture numbers check out. Shipping.", hoursAgo(3));
580
+ // --- attention: a failed attempt --------------------------------------
581
+ const failed = task("retire-legacy-flag", "Retire the legacy payout feature flag", repos.api, "Remove LEGACY_PAYOUT and every branch behind it.");
582
+ const failedProposed = propose(store, {
583
+ profile: DEMO_PROFILE,
584
+ taskId: failed,
585
+ goal: "Remove LEGACY_PAYOUT and every branch behind it.",
586
+ acceptance: [
587
+ { id: "c1", statement: "No reference to LEGACY_PAYOUT remains in the codebase.", how: null, evidence: ["changed-path"] },
588
+ ],
589
+ now: hoursAgo(16),
590
+ });
591
+ approve(store, failed, "demo", hoursAgo(15), failedProposed.digest, token);
592
+ const failedRun = store.startRun({
593
+ taskRef: store.refFor("built-in", failed).id,
594
+ leaseId: "demo-lease-failed",
595
+ runner: "night-shift-2",
596
+ branch: `toolroll/${failed}`,
597
+ worktree: join(repos.api, ".demo-worktree-4"),
598
+ now: hoursAgo(6),
599
+ ...presentedRoute(store, store.refFor("built-in", failed).id, "builder"),
600
+ });
601
+ store.finishRun(failedRun, {
602
+ outcome: "failed",
603
+ reason: "acceptance",
604
+ now: hoursAgo(5.5),
605
+ });
606
+ store.setTaskState(failed, "failed", hoursAgo(5.5));
607
+ // --- attention: needs verification (manual-review, unaccepted) --------
608
+ // Acceptance Contract v2's own review finding, made visible: a signed
609
+ // rubric can require a human's eyes ("manual-review" evidence), and
610
+ // that alone must cap the build below verified/attested until an
611
+ // operator explicitly accepts it — the SAME "accept anyway" act a
612
+ // short/refuted proof already uses, never a new mechanism.
613
+ const copyReview = task("confirm-empty-state-copy", "Confirm the new inbox empty-state copy reads well", repos.web, "Rewrite the inbox's empty-state copy so it explains why nothing is there yet.");
614
+ const copyReviewProposed = propose(store, {
615
+ profile: DEMO_PROFILE,
616
+ taskId: copyReview,
617
+ goal: "Rewrite the inbox's empty-state copy so it explains why nothing is there yet.",
618
+ acceptance: [
619
+ {
620
+ id: "c1",
621
+ statement: "An operator confirms the new empty-state copy reads clearly.",
622
+ how: "Open the inbox pane with zero items and read it.",
623
+ evidence: ["manual-review"],
624
+ },
625
+ ],
626
+ now: hoursAgo(10),
627
+ });
628
+ approve(store, copyReview, "demo", hoursAgo(9), copyReviewProposed.digest, token);
629
+ const copyReviewRun = store.startRun({
630
+ taskRef: store.refFor("built-in", copyReview).id,
631
+ leaseId: "demo-lease-copy",
632
+ runner: "night-shift-1",
633
+ branch: `toolroll/${copyReview}`,
634
+ worktree: join(repos.web, ".demo-worktree-5"),
635
+ now: hoursAgo(4),
636
+ ...presentedRoute(store, store.refFor("built-in", copyReview).id, "builder"),
637
+ });
638
+ store.stampRun(copyReviewRun, { baseRevision: "4b825dc642cb6eb9a060e54bf8d69288fbee4904", scopeDigest: copyReviewProposed.digest });
639
+ storeEvidence(store, evidenceRoot, copyReviewRun, "terminal-diff", "terminal-diff.patch", Buffer.from(DEMO_COPY_PATCH, "utf8"), "git diff --no-ext-diff --no-textconv --no-color 4b825dc6..HEAD (exit 0) [demo: synthetic]", hoursAgo(3.6));
640
+ const copyStat = {
641
+ schema: 1,
642
+ base: "4b825dc642cb6eb9a060e54bf8d69288fbee4904",
643
+ head: "1c2d3e4f52aa01c9f3d7700e54bf8d69288fbe999",
644
+ fileCount: 1,
645
+ additions: 3,
646
+ deletions: 1,
647
+ binaryCount: 0,
648
+ files: [{ path: "src/inbox-copy.ts", additions: 3, deletions: 1 }],
649
+ filesTruncated: false,
650
+ };
651
+ storeEvidence(store, evidenceRoot, copyReviewRun, "diff-stat", "diff-stat.json", budgetedStatJson(copyStat), "parsed from git diff --numstat -z [demo: synthetic]", hoursAgo(3.6));
652
+ storeEvidence(store, evidenceRoot, copyReviewRun, "handoff", "handoff.json", Buffer.from(JSON.stringify(DEMO_COPY_HANDOFF, null, 2), "utf8"), "composed at completion [demo: synthetic]", hoursAgo(3.5));
653
+ storeEvidence(store, evidenceRoot, copyReviewRun, "proof", "proof.json", Buffer.from(JSON.stringify(DEMO_COPY_PROOF, null, 2), "utf8"), "agent-authored proof (validated, re-serialized) [demo: synthetic]", hoursAgo(3.5));
654
+ const copyReviewProofParse = parseProof(JSON.stringify(DEMO_COPY_PROOF));
655
+ const copyReviewAdjudicated = adjudicate({
656
+ proofArtifactPresent: true,
657
+ proofParse: copyReviewProofParse,
658
+ handoffPresent: true,
659
+ terminalDiffPresent: true,
660
+ terminalDiffCaptureStatus: "ok",
661
+ diffStat: { captured: true, truncated: false, paths: new Set(copyStat.files.map(one => one.path)) },
662
+ verifyCommand: { configured: false },
663
+ screenshots: [],
664
+ approvedCriteria: copyReviewProposed.acceptance,
665
+ });
666
+ store.saveProofVerdict(copyReviewRun, copyReviewAdjudicated.verdict, copyReviewAdjudicated.reasons, hoursAgo(3.5), copyReviewAdjudicated.matrix);
667
+ store.finishRun(copyReviewRun, { outcome: "built", committed: true, now: hoursAgo(3.5) });
668
+ store.setTaskState(copyReview, "done", hoursAgo(3.5));
669
+ // --- reviewed + repaired: an independent reviewer contradicts a signed
670
+ // criterion, and the bounded repair loop drafts one unapproved fix
671
+ // (evidence-review-v1) — every step through the REAL functions the tick
672
+ // itself runs: adjudicate(), addReviewerComments/ingestCriterionReviews
673
+ // (the same fold reviewPass performs), and maybeTriggerRepair. Nothing
674
+ // here hand-authors a verdict or a chain row.
675
+ const reviewed = task("guard-payout-limiter", "Guard the payout limiter against concurrent settlement", repos.api, "Add a per-account concurrency guard so two settlements never race the same payout limiter.");
676
+ const reviewedProposed = propose(store, {
677
+ profile: DEMO_PROFILE,
678
+ taskId: reviewed,
679
+ goal: "Add a per-account concurrency guard so two settlements never race the same payout limiter.",
680
+ outOfScope: "No changes to the limiter's public API.",
681
+ touches: ["src/payout-limiter.ts"],
682
+ acceptance: [
683
+ {
684
+ id: "c1",
685
+ statement: "Two concurrent settlements for the same account cannot both pass the limiter.",
686
+ how: "Read the guard; an independent reviewer confirms it actually locks.",
687
+ evidence: ["manual-review"],
688
+ },
689
+ { id: "c2", statement: "The existing limiter tests still pass.", how: null, evidence: ["check"] },
690
+ ],
691
+ now: hoursAgo(6),
692
+ });
693
+ approve(store, reviewed, "demo", hoursAgo(5.8), reviewedProposed.digest, token);
694
+ const reviewedRun = store.startRun({
695
+ taskRef: store.refFor("built-in", reviewed).id,
696
+ leaseId: "demo-lease-reviewed",
697
+ runner: "night-shift-1",
698
+ branch: `toolroll/${reviewed}`,
699
+ worktree: join(repos.api, ".demo-worktree-4"),
700
+ now: hoursAgo(5),
701
+ ...presentedRoute(store, store.refFor("built-in", reviewed).id, "builder"),
702
+ });
703
+ store.stampRun(reviewedRun, {
704
+ baseRevision: "4b825dc642cb6eb9a060e54bf8d69288fbee4904",
705
+ scopeDigest: reviewedProposed.digest,
706
+ });
707
+ const DEMO_REPAIR_PATCH = `diff --git a/src/payout-limiter.ts b/src/payout-limiter.ts
708
+ --- a/src/payout-limiter.ts
709
+ +++ b/src/payout-limiter.ts
710
+ @@ -1,3 +1,4 @@
711
+ +// TODO: lock per account
712
+ export function settleWithLimiter(accountId: string, cents: number): number {
713
+ return settle(cents, currentRate(accountId));
714
+ }
715
+ `;
716
+ const reviewedDiffArtifact = storeEvidence(store, evidenceRoot, reviewedRun, "terminal-diff", "terminal-diff.patch", Buffer.from(DEMO_REPAIR_PATCH, "utf8"), "git diff --no-ext-diff --no-textconv --no-color 4b825dc6..HEAD (exit 0) [demo: synthetic]", hoursAgo(4.6),
717
+ // The seeded capture says its exit 0 in a typed verdict too: the real
718
+ // review door reads THIS, and it refuses a diff with no verdict.
719
+ { captureStatus: "ok" });
720
+ const reviewedStat = {
721
+ schema: 1,
722
+ base: "4b825dc642cb6eb9a060e54bf8d69288fbee4904",
723
+ head: "aa11bb22cc33dd44ee55ff6600112233445566aa",
724
+ fileCount: 1,
725
+ additions: 1,
726
+ deletions: 0,
727
+ binaryCount: 0,
728
+ files: [{ path: "src/payout-limiter.ts", additions: 1, deletions: 0 }],
729
+ filesTruncated: false,
730
+ };
731
+ storeEvidence(store, evidenceRoot, reviewedRun, "diff-stat", "diff-stat.json", budgetedStatJson(reviewedStat), "parsed from git diff --numstat -z [demo: synthetic]", hoursAgo(4.6));
732
+ const DEMO_REPAIR_HANDOFF = {
733
+ summary: "Added a TODO comment marking the per-account lock — ran out of turns before wiring the actual guard.",
734
+ filesTouched: ["src/payout-limiter.ts"],
735
+ };
736
+ storeEvidence(store, evidenceRoot, reviewedRun, "handoff", "handoff.json", Buffer.from(JSON.stringify(DEMO_REPAIR_HANDOFF, null, 2), "utf8"), "composed at completion [demo: synthetic]", hoursAgo(4.5));
737
+ const DEMO_REPAIR_PROOF = {
738
+ version: 1,
739
+ criteria: [
740
+ {
741
+ id: "c1",
742
+ statement: "Two concurrent settlements for the same account cannot both pass the limiter.",
743
+ verdict: "met",
744
+ how: "Added the lock.",
745
+ evidence: [{ kind: "manual-review", ref: "see src/payout-limiter.ts" }],
746
+ },
747
+ { id: "c2", statement: "The existing limiter tests still pass.", verdict: "met", how: "npm test", evidence: [{ kind: "check", ref: "npm test" }] },
748
+ ],
749
+ checks: [{ command: "npm test", exitCode: 0, summary: "214 tests passed." }],
750
+ changed: ["src/payout-limiter.ts"],
751
+ caveats: [],
752
+ screenshots: [],
753
+ };
754
+ const reviewedProofArtifact = storeEvidence(store, evidenceRoot, reviewedRun, "proof", "proof.json", Buffer.from(JSON.stringify(DEMO_REPAIR_PROOF, null, 2), "utf8"), "agent-authored proof (validated, re-serialized) [demo: synthetic]", hoursAgo(4.5));
755
+ // The verdict, computed by the real adjudicate() — the proof's OWN
756
+ // self-declared "met" reads clean until the independent reviewer looks.
757
+ const reviewedProofParse = parseProof(JSON.stringify(DEMO_REPAIR_PROOF));
758
+ const reviewedAdjudicated = adjudicate({
759
+ proofArtifactPresent: true,
760
+ proofParse: reviewedProofParse,
761
+ handoffPresent: true,
762
+ terminalDiffPresent: true,
763
+ terminalDiffCaptureStatus: "ok",
764
+ diffStat: { captured: true, truncated: false, paths: new Set(reviewedStat.files.map(one => one.path)) },
765
+ verifyCommand: { configured: true, ran: true, exitCode: 0 },
766
+ screenshots: [],
767
+ approvedCriteria: reviewedProposed.acceptance,
768
+ });
769
+ store.saveProofVerdict(reviewedRun, reviewedAdjudicated.verdict, reviewedAdjudicated.reasons, hoursAgo(4.4), reviewedAdjudicated.matrix);
770
+ store.finishRun(reviewedRun, { outcome: "built", committed: true, now: hoursAgo(4.4) });
771
+ store.setTaskState(reviewed, "done", hoursAgo(4.4));
772
+ // The independent reviewer: a real reviewer run, its comments AND its
773
+ // criterion judgement ingested through the SAME atomic store method
774
+ // reviewPass itself calls (ingestReview) — the fold is the real
775
+ // foldReview, never a hand-authored verdict, and the bindings are the
776
+ // real scope digest and proof artifact this run actually carries.
777
+ // The review is asked for through the real door and answered through
778
+ // the real admission (raw authority repair): the reviewer run consumes
779
+ // the open request inside its own insert, exactly as the review pass
780
+ // does — a reviewer row opens no other way.
781
+ const reviewAsked = store.requestReview(reviewedRun, "alex", hoursAgo(3.95));
782
+ if (!reviewAsked.ok)
783
+ throw new Error(`demo: the seeded review could not be requested (${reviewAsked.reason})`);
784
+ const reviewerRun = store.startRun({
785
+ taskRef: store.refFor("built-in", reviewed).id,
786
+ leaseId: "demo-lease-reviewer",
787
+ runner: "night-shift-1",
788
+ role: "reviewer",
789
+ parentRun: reviewedRun,
790
+ request: reviewAsked.id,
791
+ provider: "codex",
792
+ now: hoursAgo(3.9),
793
+ ...presentedRoute(store, store.refFor("built-in", reviewed).id, "reviewer"),
794
+ });
795
+ const reviewedProofSha = store.getArtifact(reviewedProofArtifact)?.sha256 ?? null;
796
+ const reviewedDiffSha = store.getArtifact(reviewedDiffArtifact)?.sha256 ?? "";
797
+ store.stampProviderStart(reviewerRun, hoursAgo(3.9));
798
+ const { folded } = store.ingestReview({
799
+ reviewerRunId: reviewerRun,
800
+ runId: reviewedRun,
801
+ artifactId: reviewedDiffArtifact,
802
+ author: "reviewer:codex",
803
+ comments: [
804
+ {
805
+ path: "src/payout-limiter.ts",
806
+ line: 1,
807
+ note: "This is a TODO, not a lock — two concurrent calls both still read the same rate before either settles.",
808
+ severity: "problem",
809
+ },
810
+ ],
811
+ judgements: [
812
+ {
813
+ id: "c1",
814
+ judgement: "contradicts",
815
+ note: "The diff adds a TODO comment, not an actual lock — two concurrent settlements still race the limiter.",
816
+ },
817
+ {
818
+ id: "c2",
819
+ judgement: "upholds",
820
+ note: "The stored check log supports that the existing limiter test suite still passes.",
821
+ },
822
+ ],
823
+ bindings: {
824
+ diffSha: reviewedDiffSha,
825
+ scopeDigest: reviewedProposed.digest,
826
+ headSha: store.getRun(reviewedRun)?.headRevision ?? store.getRun(reviewedRun)?.baseRevision ?? null,
827
+ proof: reviewedProofSha === null ? null : { artifactId: reviewedProofArtifact, sha256: reviewedProofSha },
828
+ checkLog: null,
829
+ screenshots: [],
830
+ },
831
+ }, hoursAgo(3.9));
832
+ if (folded === null)
833
+ throw new Error("seed reviewed+repaired: the fold produced nothing");
834
+ // The bounded repair loop's own trigger — the SAME function the tick
835
+ // calls after a review pass settles a verdict. No mode is signed, so
836
+ // the draft it composes waits unapproved, exactly as the default road
837
+ // promises.
838
+ const repairTrigger = maybeTriggerRepair(store, repos.api, evidenceRoot, reviewedRun, folded.verdict, hoursAgo(3.9));
839
+ if (repairTrigger.kind !== "drafted") {
840
+ throw new Error(`seed reviewed+repaired: expected a draft, got ${repairTrigger.kind}`);
841
+ }
842
+ // --- waiting: a repairable terminal dependency and a hold ---------------
843
+ task("design-tokens", "Extract the design tokens package", repos.web);
844
+ task("ship-dark-mode", "Ship dark mode", repos.web);
845
+ store.addEdge("ship-dark-mode", "design-tokens", {});
846
+ store.cancelTask("design-tokens", hoursAgo(10), "the token package was superseded");
847
+ const held = task("migrate-billing", "Migrate billing exports to the new vendor", repos.api);
848
+ store.hold(store.refFor("built-in", held).id, "waiting on the vendor sandbox account", null, hoursAgo(12));
849
+ // --- a standing order with a track record ------------------------------
850
+ const routine = fileRoutineProposal(store, {
851
+ name: "nightly-deps",
852
+ repo: repos.api,
853
+ goal: "Refresh the lockfile within existing ranges, run the suite, summarize anything notable.",
854
+ outOfScope: "No major version bumps.",
855
+ touches: [],
856
+ acceptance: [
857
+ { id: "c1", statement: "The full test suite passes against the refreshed lockfile.", how: null, evidence: ["check"] },
858
+ ],
859
+ requirements: [],
860
+ schedule: "daily:03:30",
861
+ costCeilingUsd: null,
862
+ filedVia: "demo",
863
+ }, hoursAgo(70));
864
+ if (!routine.ok)
865
+ throw new Error(`seed routine: ${routine.reason}`);
866
+ approveRoutine(store, routine.id, "demo", hoursAgo(69), routine.digest, token);
867
+ // Two nightly slots since approval: one fires, the second records its
868
+ // single-flight skip honestly (the first instance is still open).
869
+ fireRoutine(store, routine.id, hoursAgo(45));
870
+ fireRoutine(store, routine.id, hoursAgo(21));
871
+ // --- the outer loop: an opened PR with observed checks ----------------
872
+ const pub = store.createPublicationIntent({
873
+ run: doneRun,
874
+ taskRef: store.refFor("built-in", done).id,
875
+ githubRepo: "acme/payments-api",
876
+ remote: "origin",
877
+ base: "main",
878
+ head: `toolroll/${done}`,
879
+ headSha: "9e07b4152aa01c9f3d7700e54bf8d69288fbe777",
880
+ bodyHash: "demo",
881
+ draft: false,
882
+ }, hoursAgo(8.3));
883
+ store.markPublicationPushed(pub, hoursAgo(8.2));
884
+ store.markPublicationOpened(pub, 47, "https://github.com/acme/payments-api/pull/47", hoursAgo(8.1));
885
+ store.recordPublicationCheckState(pub, "passing", hoursAgo(1.5));
886
+ seedDemoFlows(store, repos.web, now);
887
+ return { login: { name: "demo", password }, repos: [repos.api, repos.web] };
888
+ }
889
+ /** Two tiny real repositories, so repo-bound surfaces have something true
890
+ * to point at. git is optional here — a plain directory still demos. */
891
+ export function makeDemoRepos(root) {
892
+ const make = (name, files) => {
893
+ const dir = join(root, name);
894
+ mkdirSync(join(dir, "src"), { recursive: true });
895
+ for (const [file, content] of Object.entries(files)) {
896
+ writeFileSync(join(dir, file), content);
897
+ }
898
+ try {
899
+ execFileSync("git", ["init", "-q", "-b", "main"], { cwd: dir, stdio: "ignore" });
900
+ execFileSync("git", ["add", "-A"], { cwd: dir, stdio: "ignore" });
901
+ execFileSync("git", ["-c", "user.email=demo@localhost", "-c", "user.name=demo", "commit", "-q", "-m", "seed"], {
902
+ cwd: dir,
903
+ stdio: "ignore",
904
+ });
905
+ }
906
+ catch {
907
+ // No git on PATH: a plain directory still serves the demo.
908
+ }
909
+ return dir;
910
+ };
911
+ return {
912
+ api: make("payments-api", {
913
+ "package.json": JSON.stringify({ name: "payments-api", private: true }, null, 2),
914
+ "src/payout.ts": "export function settle(cents: number, rate: number): number {\n return Math.round(cents * rate * 100) / 100;\n}\n",
915
+ }),
916
+ web: make("web-console", {
917
+ "package.json": JSON.stringify({ name: "web-console", private: true }, null, 2),
918
+ "src/app.ts": "export const app = () => 'hello';\n",
919
+ }),
920
+ };
921
+ }
922
+ /** The sandbox: one directory holding everything, stamped before seeding. */
923
+ /**
924
+ * Two flows mid-flight (v88), so the canvas has something to show on a first
925
+ * look: a support desk Jev has sorted, and customer replies Claude drafted —
926
+ * one waiting for the demo person's decision. Every decision and draft is
927
+ * written as the real steps write them; nothing runs, and nothing spends.
928
+ */
929
+ function seedDemoFlows(store, folder, now) {
930
+ // Projects are known by their real path (macOS's /var is /private/var): the Flows page matches on it.
931
+ const repo = realpathSync(folder);
932
+ const at = (minutes) => new Date(now.getTime() - minutes * 60_000);
933
+ const template = (id) => JSON.stringify(FLOW_TEMPLATES.find(one => one.id === id).definition);
934
+ // Cards arrive where their flow starts; a step's run is recorded, then the card moves where it said.
935
+ const step = (card, stage, kind, when, result, output, extra = {}) => {
936
+ store.claimFlowStep({ card, entry: store.getFlowCard(card).entry, stage, kind, script: null, scriptVersion: null }, when);
937
+ store.finishFlowStep(card, store.getFlowCard(card).entry, { state: "passed", result, durationMs: kind === "sort" ? 180 : 4200, ...extra }, when);
938
+ store.updateFlowCard(card, { outputs: { ...store.getFlowCard(card).outputs, [stage]: output } }, when);
939
+ };
940
+ const move = (card, to, when, actor = "flow") => store.moveFlowCard(card, { to, outcome: actor === "flow" ? "ok" : "moved", actor }, when);
941
+ const sorted = (answer, sure, to, urgency, refund) => JSON.stringify({
942
+ model: "typesafe/jev-1.13", answer, sure, sureAt: 0.8, confident: sure >= 0.8, to, chances: { [answer]: sure }, ms: 170, cost: 0.000017,
943
+ notes: [{ id: "urgency", question: "How urgent is it?", kind: "score", answer: urgency, sure: 0.8 }, { id: "refund", question: "Is the customer asking for money back?", kind: "yes-no", answer: refund ? "yes" : "no", sure: 0.9 }],
944
+ });
945
+ const desk = store.createFlow({ repo, name: "Support desk", definitionJson: template("exception-routing"), by: "demo" }, at(300));
946
+ for (const [title, description, answer, sure, to, urgency, refund, minutes] of [
947
+ ["Please cancel order #4471", "I ordered the wrong size. Can you cancel it before it ships? — Priya", "Order change", 0.97, "orders", "Soon: the customer is waiting on it", false, 240],
948
+ ["Charged twice for invoice INV-2291", "My card was charged twice this morning. I need the duplicate back before Friday's payroll.", "Invoice problem", 0.94, "billing", "Now: money is at stake or a deadline is named", true, 180],
949
+ ["Parcel arrived crushed", "The box was crushed and two glasses inside are broken.", "Delivery problem", 0.91, "delivery", "Soon: the customer is waiting on it", true, 120],
950
+ ["Where is my order and why was I billed?", "It hasn't arrived and there's a charge I don't recognise.", "Delivery problem", 0.58, "by-hand", "Soon: the customer is waiting on it", false, 45],
951
+ ]) {
952
+ const card = store.addFlowCard({ flow: desk, title, description, stage: "sort", by: "Support form" }, at(minutes));
953
+ const confident = sure >= 0.8;
954
+ step(card, "sort", "sort", at(minutes - 1), confident ? `${answer}, ${Math.round(sure * 100)}% sure.` : `Not sure: ${Math.round(sure * 100)}% ${answer}.`, `${confident ? `${answer}, ${Math.round(sure * 100)}% sure.` : `Not sure: ${Math.round(sure * 100)}% ${answer}.`} How urgent is it? ${urgency.split(":")[0]}.`, { decisionJson: sorted(answer, sure, to, urgency, refund) });
955
+ move(card, to, at(minutes - 1));
956
+ }
957
+ const replies = store.createFlow({ repo, name: "Customer replies", definitionJson: template("email-replies"), by: "demo" }, at(200));
958
+ const drafted = (title, description, draft, minutes) => {
959
+ const card = store.addFlowCard({ flow: replies, title, description, stage: "write", by: "Contact form" }, at(minutes));
960
+ step(card, "write", "draft", at(minutes - 1), `Drafted ${draft.split(/\s+/).length} words.`, draft, { log: `Claude (sonnet) · 4.2 s\n\n${draft}` });
961
+ move(card, "check", at(minutes - 1));
962
+ return card;
963
+ };
964
+ const sent = drafted("Do you ship to Canada?", "Thinking of ordering but I'm in Toronto. — sam@example.com", "Hi Sam,\n\nYes, we ship to Canada, including Toronto. Delivery usually takes 5–8 business days, and you'll get a tracking link as soon as it leaves us.\n\nThe team", 150);
965
+ store.moveFlowCard(sent, { to: "send", outcome: "approved", actor: "demo" }, at(140));
966
+ step(sent, "send", "email", at(139), "Emailed sam@example.com.", "Sent to sam@example.com: “Re: Do you ship to Canada?”");
967
+ move(sent, "done", at(139));
968
+ store.updateFlowCard(sent, { state: "done" }, at(139));
969
+ drafted("Refund for order 42?", "I was charged twice for order 42. Can I get one refunded? — priya@example.com", "Hi Priya,\n\nSorry about that! We've refunded the duplicate charge for order 42; it should be back on your card within 5 days.\n\nThe team", 20);
970
+ store.updateFlowCard(store.flowCards(replies, false).find(one => one.title === "Refund for order 42?").id, { waiting: "Waiting for demo to approve or send it back" }, at(19));
971
+ }
972
+ export function createDemoSandbox(now) {
973
+ const sandbox = mkdtempSync(join(tmpdir(), "standing-orders-demo-"));
974
+ const repos = makeDemoRepos(sandbox);
975
+ const store = openStore(join(sandbox, "orders.db"));
976
+ // The stamp precedes every row — a half-seeded sandbox is still fenced.
977
+ store.recordInstallationFact("demo", "1", now);
978
+ const evidenceRoot = join(sandbox, "evidence");
979
+ mkdirSync(evidenceRoot, { recursive: true });
980
+ const seed = seedDemo(store, repos, evidenceRoot, now);
981
+ // v105: the plans' windows as Claude and Codex last said them, and a project budget (Tasks shows them as tiles).
982
+ const later = (hours) => new Date(now.getTime() + hours * 3_600_000).toISOString();
983
+ store.recordProviderLimits({ provider: "claude", plan: null, windows: [
984
+ { window: "five_hour", usedPercent: 48, windowMinutes: 300, resetsAt: later(2.2), reached: false },
985
+ { window: "seven_day", usedPercent: 83, windowMinutes: 10_080, resetsAt: later(62), reached: false },
986
+ ] }, now);
987
+ store.recordProviderLimits({ provider: "codex", plan: "pro", windows: [{ window: "seven_day", usedPercent: 12, windowMinutes: 10_080, resetsAt: later(130), reached: false }] }, now);
988
+ store.setBudget({ scope: "project", key: repos.web, limitMicrousd: 25_000_000, hardStop: true }, seed.login.name, now);
989
+ const passwordFile = join(sandbox, "demo-login.txt");
990
+ writeFileSync(passwordFile, `name: ${seed.login.name}\npassword: ${seed.login.password}\n`, { mode: 0o600 });
991
+ return { sandbox, store, seed, evidenceRoot, passwordFile };
992
+ }