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,92 @@
1
+ import { modeTermsFromJson } from "./modes.js";
2
+ import { plannerContractOf, plannerSourceDigest } from "./planner-source.js";
3
+ import { modeFilingCoverage, propose } from "./scope.js";
4
+ export const PLAN_AUTO_SCHEMA = `CREATE TABLE IF NOT EXISTS plan_authorization (
5
+ task_id TEXT PRIMARY KEY REFERENCES task(id),
6
+ source_digest TEXT NOT NULL,
7
+ scope_digest TEXT NOT NULL,
8
+ mode_digest TEXT NOT NULL,
9
+ signed_by TEXT NOT NULL,
10
+ created_at TEXT NOT NULL
11
+ );`;
12
+ function plainPlan(store, taskId) {
13
+ const ref = store.lookupRef(taskId);
14
+ return ref !== null && ref.deliverable === "branch" && ref.coordinatorCid === null &&
15
+ store.activeTournamentTerms(ref.id) === null && store.openAuthorizationFor(ref.id) === null && store.mirrorByTask(taskId) === null;
16
+ }
17
+ /** Join the console's authority-free proposal to the authenticated filing
18
+ * road in one transaction. Planning defers the seal until verified ingestion. */
19
+ export function applyModeToNewFiling(store, taskId, actor, now) {
20
+ const ref = store.lookupRef(taskId);
21
+ const scope = store.getScope(taskId);
22
+ const coverage = modeFilingCoverage(store, ref?.repo ?? null, actor, now);
23
+ if (ref === null || scope === null || scope.proposedVia != null || coverage === null)
24
+ return;
25
+ const filed = propose(store, { taskId, goal: scope.goal, outOfScope: scope.outOfScope, touches: scope.touches, acceptance: scope.acceptance,
26
+ budgetMicrousd: scope.budgetMicrousd ?? coverage.defaultBudgetMicrousd,
27
+ qualityMode: scope.qualityMode ?? "default", riskLevel: scope.riskLevel ?? "routine",
28
+ ...(coverage.escalated ? { posture: "escalated" } : {}), now });
29
+ if (ref.plan === "requested")
30
+ authorizePlanUnderMode(store, taskId, actor, now);
31
+ else if (filed.profileState === "resolved")
32
+ store.sealScopeApproval(taskId, actor, now, {}, { kind: "mode", modeDigest: coverage.digest });
33
+ }
34
+ /** Called only by credentialed operator roads, never by proposal/intake
35
+ * code. This authorizes the exact filed contract, not arbitrary future
36
+ * planner text. Rewrites, mode renewal, expiry and revocation fail closed. */
37
+ export function authorizePlanUnderMode(store, taskId, actor, now) {
38
+ return store.transact(() => {
39
+ const ref = store.lookupRef(taskId);
40
+ if (ref === null || ref.repo === null || ref.plan !== "requested" || !plainPlan(store, taskId) || store.hasLiveClaim(ref.id, now))
41
+ return false;
42
+ const mode = store.activeMode(ref.repo, now);
43
+ const terms = mode === null ? null : modeTermsFromJson(mode.termsJson);
44
+ if (mode === null || mode.signedBy !== actor || !terms?.planAuto || !terms.autoApproveFiling || !store.accountCanAccess(actor, ref.repo))
45
+ return false;
46
+ const source = plannerContractOf(store, taskId);
47
+ if (!source.ok || source.contract.scope === null || source.contract.revision !== null)
48
+ return false;
49
+ const scope = source.contract.scope;
50
+ if (scope.proposedVia !== null || scope.acceptance.length === 0 || scope.touches.length === 0 || scope.terms.profileState !== "resolved" || store.scopeSealed(taskId))
51
+ return false;
52
+ store.raw().prepare(`INSERT INTO plan_authorization(task_id,source_digest,scope_digest,mode_digest,signed_by,created_at) VALUES (?,?,?,?,?,?)
53
+ ON CONFLICT(task_id) DO UPDATE SET source_digest=excluded.source_digest,scope_digest=excluded.scope_digest,mode_digest=excluded.mode_digest,signed_by=excluded.signed_by,created_at=excluded.created_at`)
54
+ .run(taskId, plannerSourceDigest(source.contract), scope.digest, mode.digest, actor, now.toISOString());
55
+ store.recordAction({ at: now.toISOString(), actor, repo: ref.repo, taskId, runId: null, action: "unchanged plan pre-authorized", outcome: "authorized", source: "work" });
56
+ return true;
57
+ });
58
+ }
59
+ /** Read-side status only; finalization still proves the authority anew. */
60
+ export function planAutoPending(store, taskId, now) {
61
+ const ref = store.lookupRef(taskId);
62
+ if (ref?.repo == null || ref.plan !== "requested" || !plainPlan(store, taskId))
63
+ return false;
64
+ const row = store.raw().prepare("SELECT * FROM plan_authorization WHERE task_id=?").get(taskId);
65
+ if (row === undefined)
66
+ return false;
67
+ const mode = store.activeMode(ref.repo, now);
68
+ const terms = mode === null ? null : modeTermsFromJson(mode.termsJson);
69
+ const source = plannerContractOf(store, taskId);
70
+ return mode !== null && terms?.planAuto === true && terms.autoApproveFiling && mode.digest === row["mode_digest"] && mode.signedBy === row["signed_by"] &&
71
+ store.accountCanAccess(mode.signedBy, ref.repo) && source.ok && plannerSourceDigest(source.contract) === row["source_digest"];
72
+ }
73
+ /** Inside the verified planner finalization transaction, after the source,
74
+ * artifact, contract changes and lease fence have all been checked. */
75
+ export function sealUnchangedPlanUnderMode(store, taskId, sourceDigest, runId, eligible, now) {
76
+ const authorization = store.raw().prepare("SELECT * FROM plan_authorization WHERE task_id = ?").get(taskId);
77
+ if (authorization === undefined)
78
+ return false;
79
+ // One conclusion consumes the authorization even when it needs a human.
80
+ store.raw().prepare("DELETE FROM plan_authorization WHERE task_id = ?").run(taskId);
81
+ const ref = store.lookupRef(taskId);
82
+ const scope = store.getScope(taskId);
83
+ const mode = ref?.repo == null ? null : store.activeMode(ref.repo, now);
84
+ const terms = mode === null ? null : modeTermsFromJson(mode.termsJson);
85
+ const by = String(authorization["signed_by"]);
86
+ const covered = eligible && plainPlan(store, taskId) && sourceDigest === authorization["source_digest"] && scope?.digest === authorization["scope_digest"] &&
87
+ mode !== null && mode.digest === authorization["mode_digest"] && mode.signedBy === by &&
88
+ terms?.planAuto === true && terms.autoApproveFiling && store.accountCanAccess(by, ref?.repo ?? null);
89
+ const approved = covered && store.sealScopeApproval(taskId, by, now, {}, { kind: "mode", modeDigest: mode.digest });
90
+ store.recordAction({ at: now.toISOString(), actor: by, repo: ref?.repo ?? null, taskId, runId, action: "plan auto-approval", outcome: approved ? "approved" : "needs approval", source: "work" });
91
+ return approved;
92
+ }
package/dist/plan.d.ts ADDED
@@ -0,0 +1,186 @@
1
+ /**
2
+ * The planner's terminal handoff, parsed with the 422 rule: fail closed,
3
+ * every problem reported at once, stable reasons, caps and control-character
4
+ * rejection on every string — because a plan payload reaches terminals, the
5
+ * approve card, and the builder's brief (Codex planning review, question 2:
6
+ * the scope proposal is authority-bearing, so it gets the park discipline).
7
+ */
8
+ import { type AcceptanceCriterion } from "./scope.js";
9
+ export type PlanProblem = {
10
+ reason: string;
11
+ message: string;
12
+ };
13
+ export type ParsedPlan = {
14
+ goal: string;
15
+ outOfScope: string | null;
16
+ touches: string[];
17
+ /** v39: the rubric the planner drafts alongside the goal — mandatory,
18
+ * because the planner is a scope-producing road like any other (the
19
+ * scope text names it explicitly). A malformed or empty rubric fails
20
+ * the whole plan the same way a missing goal always has. */
21
+ acceptance: AcceptanceCriterion[];
22
+ /** The plan document, markdown, rendered fenced-inert everywhere. */
23
+ plan: string;
24
+ /** Why the filed contract must change (contract handoff, task 1): a
25
+ * planner that proposes different goal/outOfScope/touches/acceptance
26
+ * than the operator filed says so HERE, or the plan is malformed. Null
27
+ * when the plan reproduces the filed terms, or when none were filed. */
28
+ amendment: string | null;
29
+ };
30
+ /** A deliberately small execution plan. The signed scope remains the
31
+ * authority; this is the durable road the builder is expected to follow.
32
+ * Fixed sections make the handoff scannable in the console and prevent the
33
+ * planner from hiding the useful parts in a long essay. */
34
+ export type ExecutionPlanDocument = {
35
+ approach: string;
36
+ milestones: string[];
37
+ dependencies: string[];
38
+ risks: string[];
39
+ proof: string[];
40
+ };
41
+ export type ExecutionPlanDocumentResult = {
42
+ ok: true;
43
+ document: ExecutionPlanDocument;
44
+ } | {
45
+ ok: false;
46
+ problems: PlanProblem[];
47
+ };
48
+ /** Parse the planner's human-readable artifact without executing Markdown.
49
+ * Older free-form plan artifacts remain renderable through the caller's
50
+ * fallback, while every newly accepted planner handoff uses this shape. */
51
+ export declare function parseExecutionPlanDocument(raw: string): ExecutionPlanDocumentResult;
52
+ /**
53
+ * The inverse of `parseExecutionPlanDocument`: the canonical fenced-section
54
+ * markdown for a document the parser already admitted.
55
+ *
56
+ * A builder's revision proposal arrives as free-form text that the parser
57
+ * validates and reduces to this shape; what gets STORED — and later
58
+ * hash-verified, re-read, and quoted into the next brief — is rendered back
59
+ * from that validated shape, never the agent's raw bytes (the scout
60
+ * report's rule, and settleProof's). `parseExecutionPlanDocument` composed
61
+ * with this function is the identity on every document the parser admits:
62
+ * sections in their fixed order, one bullet per item, nothing else.
63
+ */
64
+ export declare function renderExecutionPlanDocument(document: ExecutionPlanDocument): string;
65
+ export type PlanParseResult = {
66
+ ok: true;
67
+ plan: ParsedPlan;
68
+ } | {
69
+ ok: false;
70
+ problems: PlanProblem[];
71
+ };
72
+ /** Caps matching the scope ritual's fields, plus the document itself. */
73
+ export declare const PLAN_LIMITS: {
74
+ readonly payload: number;
75
+ readonly goal: 2000;
76
+ readonly outOfScope: 2000;
77
+ readonly touch: 200;
78
+ readonly touches: 32;
79
+ readonly document: number;
80
+ readonly amendment: 1000;
81
+ };
82
+ export declare function parsePlan(raw: string): PlanParseResult;
83
+ export type MilestoneState = "pending" | "current" | "completed" | "blocked";
84
+ export type Milestone = {
85
+ id: string;
86
+ description: string;
87
+ };
88
+ /**
89
+ * A milestone's identity is its position plus a short hash of its
90
+ * normalized text — stable across re-reads of the same revision, but a
91
+ * milestone whose wording changes materially becomes a NEW identity rather
92
+ * than silently inheriting stale completion state from a differently-worded
93
+ * predecessor.
94
+ */
95
+ export declare function milestoneId(index: number, description: string): string;
96
+ export declare function milestonesOf(document: ExecutionPlanDocument): Milestone[];
97
+ export type ProgressEntry = {
98
+ id: string;
99
+ state: MilestoneState;
100
+ note: string | null;
101
+ };
102
+ /** The builder's atomic progress checkpoint: every milestone in the plan
103
+ * revision it received, exactly once each, bound to that revision's exact
104
+ * hash so a checkpoint can never be misread against a different plan. */
105
+ export type ProgressSnapshot = {
106
+ revisionHash: string;
107
+ milestones: ProgressEntry[];
108
+ };
109
+ export type ProgressParseResult = {
110
+ ok: true;
111
+ snapshot: ProgressSnapshot;
112
+ } | {
113
+ ok: false;
114
+ problems: PlanProblem[];
115
+ };
116
+ export declare const PROGRESS_LIMITS: {
117
+ readonly payload: number;
118
+ readonly note: 300;
119
+ readonly milestones: 12;
120
+ };
121
+ /** Parse a progress checkpoint written by a running build. `expectedRevisionHash`
122
+ * and `knownIds` come from the plan revision the build's brief actually
123
+ * named — a snapshot naming a different revision, an unknown milestone id,
124
+ * a missing milestone, or more than one "current" milestone fails closed
125
+ * with every problem at once, the same 422 rule as the plan itself. */
126
+ export declare function parseProgressSnapshot(raw: string, expectedRevisionHash: string, knownIds: readonly string[]): ProgressParseResult;
127
+ /** Whether a checkpoint transition is a legitimate update or a regression:
128
+ * once a milestone is completed it never reverts — an agent restating an
129
+ * old snapshot (a stale pulse, a retried read) must never erase progress
130
+ * that a later, newer checkpoint already recorded. */
131
+ export declare function isMilestoneRegression(previous: MilestoneState | undefined, next: MilestoneState): boolean;
132
+ export type PlanRevisionProposal = {
133
+ /** The complete replacement plan document — the same shape the planner
134
+ * itself produces, never a diff, so a revision is always fully readable
135
+ * on its own. */
136
+ document: ExecutionPlanDocument;
137
+ /** Why: the named dependency, risk, or implementation assumption the
138
+ * repository evidence invalidated. */
139
+ reason: string;
140
+ /** Where: a path, commit, or command output the operator (or a later
141
+ * reader) can go re-check. */
142
+ evidenceLink: string;
143
+ };
144
+ export type PlanRevisionProposalParseResult = {
145
+ ok: true;
146
+ proposal: PlanRevisionProposal;
147
+ } | {
148
+ ok: false;
149
+ problems: PlanProblem[];
150
+ };
151
+ export declare const REVISION_LIMITS: {
152
+ readonly payload: number;
153
+ readonly reason: 2000;
154
+ readonly evidenceLink: 500;
155
+ };
156
+ /** Parse the builder's terminal revision-proposal file: a complete
157
+ * replacement plan document plus the evidence that invalidated the one it
158
+ * was given. One proposal per build — the caller enforces that by never
159
+ * offering the agent more than one nonce-named path to write. */
160
+ export declare function parsePlanRevisionProposal(raw: string): PlanRevisionProposalParseResult;
161
+ /** The exact authority a build's approval rests on: the signed scope
162
+ * (goal, out-of-scope, touches, acceptance, permissions, quality, budget —
163
+ * everything folded into the scope digest) plus publication authority
164
+ * (branch vs. report). A plan revision may only auto-resume when this is
165
+ * byte-identical to what it was when the build started; anything else
166
+ * stays paused for a person, named. */
167
+ export type AuthoritySnapshot = {
168
+ scopeDigest: string;
169
+ deliverable: "branch" | "report";
170
+ };
171
+ export declare function authoritySnapshotDigest(snapshot: AuthoritySnapshot): string;
172
+ export type AuthorityChangeField = "signed-scope" | "publication-authority";
173
+ export type RevisionAuthorityCheck = {
174
+ kind: "plan-only";
175
+ } | {
176
+ kind: "authority-change";
177
+ changed: AuthorityChangeField[];
178
+ };
179
+ /** Classify a revision against the complete authority snapshot the build
180
+ * actually started under. Everything the builder's own proposal can name is
181
+ * plan-only by construction (it carries no scope fields at all) — this
182
+ * check exists as the defense against the world moving underneath a live
183
+ * build: if the signed scope or publication authority changed by any other
184
+ * road while the build ran, the revision is never auto-applied, whatever it
185
+ * proposes. */
186
+ export declare function classifyRevisionAuthority(previous: AuthoritySnapshot, current: AuthoritySnapshot): RevisionAuthorityCheck;
package/dist/plan.js ADDED
@@ -0,0 +1,401 @@
1
+ /**
2
+ * The planner's terminal handoff, parsed with the 422 rule: fail closed,
3
+ * every problem reported at once, stable reasons, caps and control-character
4
+ * rejection on every string — because a plan payload reaches terminals, the
5
+ * approve card, and the builder's brief (Codex planning review, question 2:
6
+ * the scope proposal is authority-bearing, so it gets the park discipline).
7
+ */
8
+ import { createHash } from "node:crypto";
9
+ import { hasForbiddenControls } from "./decision.js";
10
+ import { parseAcceptanceCriteria } from "./scope.js";
11
+ const EXECUTION_PLAN_SECTIONS = ["approach", "milestones", "dependencies", "risks", "proof"];
12
+ const EXECUTION_PLAN_LIST_CAP = 12;
13
+ const EXECUTION_PLAN_ITEM_CAP = 600;
14
+ /** Parse the planner's human-readable artifact without executing Markdown.
15
+ * Older free-form plan artifacts remain renderable through the caller's
16
+ * fallback, while every newly accepted planner handoff uses this shape. */
17
+ export function parseExecutionPlanDocument(raw) {
18
+ const problems = [];
19
+ if (Buffer.byteLength(raw, "utf8") > PLAN_LIMITS.document) {
20
+ return { ok: false, problems: [{ reason: "plan-too-long", message: `plan is over ${PLAN_LIMITS.document} bytes` }] };
21
+ }
22
+ const normalized = raw.replace(/\r\n?/g, "\n");
23
+ if (hasForbiddenControls(normalized)) {
24
+ return { ok: false, problems: [{ reason: "plan-controls", message: "plan carries control characters that could become terminal escapes" }] };
25
+ }
26
+ const sections = new Map();
27
+ let current = null;
28
+ let lastSection = -1;
29
+ for (const line of normalized.split("\n")) {
30
+ const heading = /^##\s+(.+?)\s*$/.exec(line);
31
+ if (heading !== null) {
32
+ const name = (heading[1] ?? "").trim().toLowerCase();
33
+ if (!EXECUTION_PLAN_SECTIONS.includes(name)) {
34
+ problems.push({ reason: "plan-unknown-section", message: `plan section \"${heading[1]}\" is not one of Approach, Milestones, Dependencies, Risks, or Proof` });
35
+ current = null;
36
+ continue;
37
+ }
38
+ const position = EXECUTION_PLAN_SECTIONS.indexOf(name);
39
+ if (position < lastSection) {
40
+ problems.push({ reason: "plan-section-order", message: "plan sections must stay in order: Approach, Milestones, Dependencies, Risks, Proof" });
41
+ }
42
+ lastSection = Math.max(lastSection, position);
43
+ if (sections.has(name))
44
+ problems.push({ reason: `plan-duplicate-${name}`, message: `plan has more than one ${name} section` });
45
+ sections.set(name, []);
46
+ current = name;
47
+ continue;
48
+ }
49
+ if (current === null) {
50
+ if (line.trim() !== "")
51
+ problems.push({ reason: "plan-preamble", message: "plan must start with ## Approach" });
52
+ continue;
53
+ }
54
+ sections.get(current)?.push(line);
55
+ }
56
+ for (const section of EXECUTION_PLAN_SECTIONS) {
57
+ if (!sections.has(section))
58
+ problems.push({ reason: `plan-missing-${section}`, message: `plan needs a ## ${section[0]?.toUpperCase()}${section.slice(1)} section` });
59
+ }
60
+ if (problems.length > 0)
61
+ return { ok: false, problems };
62
+ const approach = (sections.get("approach") ?? []).join("\n").trim();
63
+ if (approach === "")
64
+ problems.push({ reason: "plan-empty-approach", message: "Approach must say how the work will be done" });
65
+ if (approach.length > 2_000)
66
+ problems.push({ reason: "plan-approach-too-long", message: "Approach is over 2000 characters" });
67
+ const list = (name) => {
68
+ const items = [];
69
+ for (const line of sections.get(name) ?? []) {
70
+ if (line.trim() === "")
71
+ continue;
72
+ const item = /^(?:[-*]\s+|\d+[.)]\s+)(.+)$/.exec(line.trim())?.[1]?.trim();
73
+ if (item === undefined || item === "") {
74
+ problems.push({ reason: `plan-bad-${name}-item`, message: `${name} entries must be bullets or numbered items` });
75
+ continue;
76
+ }
77
+ if (item.length > EXECUTION_PLAN_ITEM_CAP) {
78
+ problems.push({ reason: `plan-${name}-item-too-long`, message: `${name} entries are capped at ${EXECUTION_PLAN_ITEM_CAP} characters` });
79
+ continue;
80
+ }
81
+ items.push(item);
82
+ }
83
+ if (items.length === 0)
84
+ problems.push({ reason: `plan-empty-${name}`, message: `${name} needs at least one item (use \"None found.\" when honest)` });
85
+ if (items.length > EXECUTION_PLAN_LIST_CAP)
86
+ problems.push({ reason: `plan-too-many-${name}`, message: `${name} is capped at ${EXECUTION_PLAN_LIST_CAP} items` });
87
+ return items;
88
+ };
89
+ const document = {
90
+ approach,
91
+ milestones: list("milestones"),
92
+ dependencies: list("dependencies"),
93
+ risks: list("risks"),
94
+ proof: list("proof"),
95
+ };
96
+ return problems.length === 0 ? { ok: true, document } : { ok: false, problems };
97
+ }
98
+ /**
99
+ * The inverse of `parseExecutionPlanDocument`: the canonical fenced-section
100
+ * markdown for a document the parser already admitted.
101
+ *
102
+ * A builder's revision proposal arrives as free-form text that the parser
103
+ * validates and reduces to this shape; what gets STORED — and later
104
+ * hash-verified, re-read, and quoted into the next brief — is rendered back
105
+ * from that validated shape, never the agent's raw bytes (the scout
106
+ * report's rule, and settleProof's). `parseExecutionPlanDocument` composed
107
+ * with this function is the identity on every document the parser admits:
108
+ * sections in their fixed order, one bullet per item, nothing else.
109
+ */
110
+ export function renderExecutionPlanDocument(document) {
111
+ const bullets = (items) => items.map(item => `- ${item}`);
112
+ return [
113
+ "## Approach",
114
+ document.approach,
115
+ "",
116
+ "## Milestones",
117
+ ...bullets(document.milestones),
118
+ "",
119
+ "## Dependencies",
120
+ ...bullets(document.dependencies),
121
+ "",
122
+ "## Risks",
123
+ ...bullets(document.risks),
124
+ "",
125
+ "## Proof",
126
+ ...bullets(document.proof),
127
+ "",
128
+ ].join("\n");
129
+ }
130
+ /** Caps matching the scope ritual's fields, plus the document itself. */
131
+ export const PLAN_LIMITS = {
132
+ payload: 64 * 1024,
133
+ goal: 2_000,
134
+ outOfScope: 2_000,
135
+ touch: 200,
136
+ touches: 32,
137
+ document: 16 * 1024,
138
+ amendment: 1_000,
139
+ };
140
+ function refuse(reason, message) {
141
+ return { ok: false, problems: [{ reason, message }] };
142
+ }
143
+ function describe(value) {
144
+ if (value === undefined)
145
+ return "nothing";
146
+ if (value === null)
147
+ return "null";
148
+ if (typeof value === "string")
149
+ return `a ${value.length}-char string`;
150
+ return `a ${Array.isArray(value) ? "array" : typeof value}`;
151
+ }
152
+ function prose(value, field, cap, required, problems) {
153
+ if (value === undefined || value === null || value === "") {
154
+ if (required)
155
+ problems.push({ reason: `missing-${field}`, message: `${field} is required` });
156
+ return null;
157
+ }
158
+ if (typeof value !== "string") {
159
+ problems.push({ reason: `bad-${field}`, message: `${field} must be a string (got ${describe(value)})` });
160
+ return null;
161
+ }
162
+ if (value.length > cap) {
163
+ problems.push({ reason: `${field}-too-long`, message: `${field} is over ${cap} characters` });
164
+ return null;
165
+ }
166
+ if (hasForbiddenControls(value)) {
167
+ problems.push({ reason: `${field}-controls`, message: `${field} carries control characters that could become terminal escapes` });
168
+ return null;
169
+ }
170
+ return value;
171
+ }
172
+ export function parsePlan(raw) {
173
+ if (Buffer.byteLength(raw, "utf8") > PLAN_LIMITS.payload) {
174
+ return refuse("too-large", `the payload is over ${PLAN_LIMITS.payload} bytes`);
175
+ }
176
+ let parsed;
177
+ try {
178
+ parsed = JSON.parse(raw);
179
+ }
180
+ catch (error) {
181
+ return refuse("not-json", `the payload is not JSON: ${error instanceof Error ? error.message : String(error)}`);
182
+ }
183
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
184
+ return refuse("not-an-object", "the payload must be one JSON object");
185
+ }
186
+ const body = parsed;
187
+ const problems = [];
188
+ const goal = prose(body["goal"], "goal", PLAN_LIMITS.goal, true, problems);
189
+ const outOfScope = prose(body["outOfScope"], "outOfScope", PLAN_LIMITS.outOfScope, false, problems);
190
+ const document = prose(body["plan"], "plan", PLAN_LIMITS.document, true, problems);
191
+ const amendment = prose(body["amendment"], "amendment", PLAN_LIMITS.amendment, false, problems);
192
+ const touches = [];
193
+ if (body["touches"] !== undefined && body["touches"] !== null) {
194
+ if (!Array.isArray(body["touches"])) {
195
+ problems.push({ reason: "bad-touches", message: `touches must be an array of paths (got ${describe(body["touches"])})` });
196
+ }
197
+ else if (body["touches"].length > PLAN_LIMITS.touches) {
198
+ problems.push({ reason: "touches-too-many", message: `touches lists ${body["touches"].length} paths — cap is ${PLAN_LIMITS.touches}` });
199
+ }
200
+ else {
201
+ for (const [index, one] of body["touches"].entries()) {
202
+ const path = prose(one, `touches[${index}]`, PLAN_LIMITS.touch, true, problems);
203
+ if (path !== null) {
204
+ if (/[\n\t]/.test(path)) {
205
+ problems.push({ reason: `touches[${index}]-multiline`, message: `touches[${index}] must be one line` });
206
+ }
207
+ else {
208
+ touches.push(path);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ const acceptanceParse = parseAcceptanceCriteria(body["acceptance"]);
215
+ for (const problem of acceptanceParse.problems) {
216
+ problems.push({ reason: problem.reason, message: problem.message });
217
+ }
218
+ if (acceptanceParse.problems.length === 0 && acceptanceParse.criteria.length === 0) {
219
+ problems.push({ reason: "missing-acceptance", message: "acceptance is required — at least one signed criterion the build will be judged against" });
220
+ }
221
+ if (document !== null) {
222
+ const execution = parseExecutionPlanDocument(document);
223
+ if (!execution.ok) {
224
+ problems.push(...execution.problems);
225
+ }
226
+ else if (acceptanceParse.problems.length === 0) {
227
+ const proof = execution.document.proof.join("\n");
228
+ for (const criterion of acceptanceParse.criteria) {
229
+ const mentioned = new RegExp(`(^|[^A-Za-z0-9_-])${criterion.id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([^A-Za-z0-9_-]|$)`).test(proof);
230
+ if (!mentioned) {
231
+ problems.push({ reason: `plan-proof-missing-${criterion.id}`, message: `Proof must name acceptance criterion ${criterion.id}` });
232
+ }
233
+ }
234
+ }
235
+ }
236
+ if (problems.length > 0)
237
+ return { ok: false, problems };
238
+ return {
239
+ ok: true,
240
+ plan: { goal: goal, outOfScope, touches, acceptance: acceptanceParse.criteria, plan: document, amendment },
241
+ };
242
+ }
243
+ const MILESTONE_STATES = ["pending", "current", "completed", "blocked"];
244
+ /**
245
+ * A milestone's identity is its position plus a short hash of its
246
+ * normalized text — stable across re-reads of the same revision, but a
247
+ * milestone whose wording changes materially becomes a NEW identity rather
248
+ * than silently inheriting stale completion state from a differently-worded
249
+ * predecessor.
250
+ */
251
+ export function milestoneId(index, description) {
252
+ const hash = createHash("sha256").update(description.trim().toLowerCase(), "utf8").digest("hex").slice(0, 8);
253
+ return `m${index + 1}-${hash}`;
254
+ }
255
+ export function milestonesOf(document) {
256
+ return document.milestones.map((description, index) => ({ id: milestoneId(index, description), description }));
257
+ }
258
+ export const PROGRESS_LIMITS = {
259
+ payload: 8 * 1024,
260
+ note: 300,
261
+ milestones: EXECUTION_PLAN_LIST_CAP,
262
+ };
263
+ /** Parse a progress checkpoint written by a running build. `expectedRevisionHash`
264
+ * and `knownIds` come from the plan revision the build's brief actually
265
+ * named — a snapshot naming a different revision, an unknown milestone id,
266
+ * a missing milestone, or more than one "current" milestone fails closed
267
+ * with every problem at once, the same 422 rule as the plan itself. */
268
+ export function parseProgressSnapshot(raw, expectedRevisionHash, knownIds) {
269
+ if (Buffer.byteLength(raw, "utf8") > PROGRESS_LIMITS.payload) {
270
+ return { ok: false, problems: [{ reason: "progress-too-large", message: `progress is over ${PROGRESS_LIMITS.payload} bytes` }] };
271
+ }
272
+ let parsed;
273
+ try {
274
+ parsed = JSON.parse(raw);
275
+ }
276
+ catch (error) {
277
+ return { ok: false, problems: [{ reason: "progress-not-json", message: `progress is not JSON: ${error instanceof Error ? error.message : String(error)}` }] };
278
+ }
279
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
280
+ return { ok: false, problems: [{ reason: "progress-not-an-object", message: "progress must be one JSON object" }] };
281
+ }
282
+ const body = parsed;
283
+ const problems = [];
284
+ const revisionHash = typeof body["revisionHash"] === "string" ? body["revisionHash"] : null;
285
+ if (revisionHash === null) {
286
+ problems.push({ reason: "progress-missing-revision", message: "progress must name revisionHash" });
287
+ }
288
+ else if (revisionHash !== expectedRevisionHash) {
289
+ problems.push({ reason: "progress-stale-revision", message: "progress names a plan revision that is not the one this build received" });
290
+ }
291
+ const rawMilestones = body["milestones"];
292
+ const milestones = [];
293
+ if (!Array.isArray(rawMilestones)) {
294
+ problems.push({ reason: "progress-bad-milestones", message: `milestones must be an array (got ${describe(rawMilestones)})` });
295
+ }
296
+ else if (rawMilestones.length > PROGRESS_LIMITS.milestones) {
297
+ problems.push({ reason: "progress-too-many-milestones", message: `milestones is capped at ${PROGRESS_LIMITS.milestones} entries` });
298
+ }
299
+ else {
300
+ const seen = new Set();
301
+ for (const [index, entryRaw] of rawMilestones.entries()) {
302
+ if (typeof entryRaw !== "object" || entryRaw === null || Array.isArray(entryRaw)) {
303
+ problems.push({ reason: `progress-bad-entry-${index}`, message: `milestones[${index}] must be an object` });
304
+ continue;
305
+ }
306
+ const entry = entryRaw;
307
+ const id = typeof entry["id"] === "string" ? entry["id"] : null;
308
+ const state = typeof entry["state"] === "string" ? entry["state"] : null;
309
+ const note = prose(entry["note"], `milestones[${index}].note`, PROGRESS_LIMITS.note, false, problems);
310
+ if (id === null || !knownIds.includes(id)) {
311
+ problems.push({ reason: `progress-unknown-milestone-${index}`, message: `milestones[${index}] names a milestone id not in this plan revision` });
312
+ continue;
313
+ }
314
+ if (seen.has(id)) {
315
+ problems.push({ reason: `progress-duplicate-milestone-${index}`, message: `milestone ${id} appears more than once` });
316
+ continue;
317
+ }
318
+ seen.add(id);
319
+ if (state === null || !MILESTONE_STATES.includes(state)) {
320
+ problems.push({ reason: `progress-bad-state-${index}`, message: `milestones[${index}].state must be one of ${MILESTONE_STATES.join(", ")}` });
321
+ continue;
322
+ }
323
+ milestones.push({ id, state: state, note });
324
+ }
325
+ for (const knownId of knownIds) {
326
+ if (!seen.has(knownId))
327
+ problems.push({ reason: "progress-missing-milestone", message: `progress must report every milestone in the plan revision (missing ${knownId})` });
328
+ }
329
+ if (milestones.filter(entry => entry.state === "current").length > 1) {
330
+ problems.push({ reason: "progress-multiple-current", message: "at most one milestone may be current at a time" });
331
+ }
332
+ }
333
+ if (problems.length > 0)
334
+ return { ok: false, problems };
335
+ return { ok: true, snapshot: { revisionHash: revisionHash, milestones } };
336
+ }
337
+ /** Whether a checkpoint transition is a legitimate update or a regression:
338
+ * once a milestone is completed it never reverts — an agent restating an
339
+ * old snapshot (a stale pulse, a retried read) must never erase progress
340
+ * that a later, newer checkpoint already recorded. */
341
+ export function isMilestoneRegression(previous, next) {
342
+ return previous === "completed" && next !== "completed";
343
+ }
344
+ export const REVISION_LIMITS = {
345
+ payload: 32 * 1024,
346
+ reason: 2_000,
347
+ evidenceLink: 500,
348
+ };
349
+ /** Parse the builder's terminal revision-proposal file: a complete
350
+ * replacement plan document plus the evidence that invalidated the one it
351
+ * was given. One proposal per build — the caller enforces that by never
352
+ * offering the agent more than one nonce-named path to write. */
353
+ export function parsePlanRevisionProposal(raw) {
354
+ if (Buffer.byteLength(raw, "utf8") > REVISION_LIMITS.payload) {
355
+ return { ok: false, problems: [{ reason: "revision-too-large", message: `revision proposal is over ${REVISION_LIMITS.payload} bytes` }] };
356
+ }
357
+ let parsed;
358
+ try {
359
+ parsed = JSON.parse(raw);
360
+ }
361
+ catch (error) {
362
+ return { ok: false, problems: [{ reason: "revision-not-json", message: `revision proposal is not JSON: ${error instanceof Error ? error.message : String(error)}` }] };
363
+ }
364
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
365
+ return { ok: false, problems: [{ reason: "revision-not-an-object", message: "revision proposal must be one JSON object" }] };
366
+ }
367
+ const body = parsed;
368
+ const problems = [];
369
+ const reason = prose(body["reason"], "reason", REVISION_LIMITS.reason, true, problems);
370
+ const evidenceLink = prose(body["evidenceLink"], "evidenceLink", REVISION_LIMITS.evidenceLink, true, problems);
371
+ const planText = prose(body["plan"], "plan", PLAN_LIMITS.document, true, problems);
372
+ let document = null;
373
+ if (planText !== null) {
374
+ const execution = parseExecutionPlanDocument(planText);
375
+ if (!execution.ok)
376
+ problems.push(...execution.problems);
377
+ else
378
+ document = execution.document;
379
+ }
380
+ if (problems.length > 0)
381
+ return { ok: false, problems };
382
+ return { ok: true, proposal: { document: document, reason: reason, evidenceLink: evidenceLink } };
383
+ }
384
+ export function authoritySnapshotDigest(snapshot) {
385
+ return createHash("sha256").update(`${snapshot.scopeDigest}\u0000${snapshot.deliverable}`, "utf8").digest("hex").slice(0, 32);
386
+ }
387
+ /** Classify a revision against the complete authority snapshot the build
388
+ * actually started under. Everything the builder's own proposal can name is
389
+ * plan-only by construction (it carries no scope fields at all) — this
390
+ * check exists as the defense against the world moving underneath a live
391
+ * build: if the signed scope or publication authority changed by any other
392
+ * road while the build ran, the revision is never auto-applied, whatever it
393
+ * proposes. */
394
+ export function classifyRevisionAuthority(previous, current) {
395
+ const changed = [];
396
+ if (previous.scopeDigest !== current.scopeDigest)
397
+ changed.push("signed-scope");
398
+ if (previous.deliverable !== current.deliverable)
399
+ changed.push("publication-authority");
400
+ return changed.length === 0 ? { kind: "plan-only" } : { kind: "authority-change", changed };
401
+ }