approval-md 0.0.1 → 0.2.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 (722) hide show
  1. package/LICENSE +176 -0
  2. package/NOTICE +5 -0
  3. package/README.md +940 -4
  4. package/SPEC.md +476 -34
  5. package/cli.js +29 -3
  6. package/dist/src/adapters/agentmail.d.ts +426 -0
  7. package/dist/src/adapters/agentmail.js +1200 -0
  8. package/dist/src/adapters/agentmail.js.map +1 -0
  9. package/dist/src/adapters/conformance.d.ts +149 -0
  10. package/dist/src/adapters/conformance.js +461 -0
  11. package/dist/src/adapters/conformance.js.map +1 -0
  12. package/dist/src/adapters/contract.d.ts +628 -0
  13. package/dist/src/adapters/contract.js +1035 -0
  14. package/dist/src/adapters/contract.js.map +1 -0
  15. package/dist/src/adapters/email.d.ts +324 -0
  16. package/dist/src/adapters/email.js +749 -0
  17. package/dist/src/adapters/email.js.map +1 -0
  18. package/dist/src/adapters/env-passphrase.d.ts +93 -0
  19. package/dist/src/adapters/env-passphrase.js +132 -0
  20. package/dist/src/adapters/env-passphrase.js.map +1 -0
  21. package/dist/src/adapters/public.d.ts +11 -0
  22. package/dist/src/adapters/public.js +11 -0
  23. package/dist/src/adapters/public.js.map +1 -0
  24. package/dist/src/adapters/registry.d.ts +59 -0
  25. package/dist/src/adapters/registry.js +77 -0
  26. package/dist/src/adapters/registry.js.map +1 -0
  27. package/dist/src/adapters/smtp.d.ts +213 -0
  28. package/dist/src/adapters/smtp.js +499 -0
  29. package/dist/src/adapters/smtp.js.map +1 -0
  30. package/dist/src/adapters/vault-provider.d.ts +114 -0
  31. package/dist/src/adapters/vault-provider.js +161 -0
  32. package/dist/src/adapters/vault-provider.js.map +1 -0
  33. package/dist/src/adapters/zzz.d.ts +66 -0
  34. package/dist/src/adapters/zzz.js +299 -0
  35. package/dist/src/adapters/zzz.js.map +1 -0
  36. package/dist/src/channels/batch.d.ts +109 -0
  37. package/dist/src/channels/batch.js +121 -0
  38. package/dist/src/channels/batch.js.map +1 -0
  39. package/dist/src/channels/cli.d.ts +193 -0
  40. package/dist/src/channels/cli.js +468 -0
  41. package/dist/src/channels/cli.js.map +1 -0
  42. package/dist/src/channels/conformance.d.ts +92 -0
  43. package/dist/src/channels/conformance.js +445 -0
  44. package/dist/src/channels/conformance.js.map +1 -0
  45. package/dist/src/channels/contract.d.ts +623 -0
  46. package/dist/src/channels/contract.js +494 -0
  47. package/dist/src/channels/contract.js.map +1 -0
  48. package/dist/src/channels/payload-view.d.ts +35 -0
  49. package/dist/src/channels/payload-view.js +43 -0
  50. package/dist/src/channels/payload-view.js.map +1 -0
  51. package/dist/src/channels/render-queue.d.ts +149 -0
  52. package/dist/src/channels/render-queue.js +564 -0
  53. package/dist/src/channels/render-queue.js.map +1 -0
  54. package/dist/src/channels/tagging.d.ts +196 -0
  55. package/dist/src/channels/tagging.js +723 -0
  56. package/dist/src/channels/tagging.js.map +1 -0
  57. package/dist/src/channels/telegram.d.ts +1832 -0
  58. package/dist/src/channels/telegram.js +3190 -0
  59. package/dist/src/channels/telegram.js.map +1 -0
  60. package/dist/src/channels/web.d.ts +341 -0
  61. package/dist/src/channels/web.js +903 -0
  62. package/dist/src/channels/web.js.map +1 -0
  63. package/dist/src/cli/adapter.d.ts +90 -0
  64. package/dist/src/cli/adapter.js +288 -0
  65. package/dist/src/cli/adapter.js.map +1 -0
  66. package/dist/src/cli/amend.d.ts +59 -0
  67. package/dist/src/cli/amend.js +2171 -0
  68. package/dist/src/cli/amend.js.map +1 -0
  69. package/dist/src/cli/args.d.ts +43 -0
  70. package/dist/src/cli/args.js +86 -0
  71. package/dist/src/cli/args.js.map +1 -0
  72. package/dist/src/cli/attest.d.ts +41 -0
  73. package/dist/src/cli/attest.js +307 -0
  74. package/dist/src/cli/attest.js.map +1 -0
  75. package/dist/src/cli/audit-card.d.ts +62 -0
  76. package/dist/src/cli/audit-card.js +201 -0
  77. package/dist/src/cli/audit-card.js.map +1 -0
  78. package/dist/src/cli/audit.d.ts +59 -0
  79. package/dist/src/cli/audit.js +460 -0
  80. package/dist/src/cli/audit.js.map +1 -0
  81. package/dist/src/cli/channel-telegram.d.ts +806 -0
  82. package/dist/src/cli/channel-telegram.js +2063 -0
  83. package/dist/src/cli/channel-telegram.js.map +1 -0
  84. package/dist/src/cli/channel-web.d.ts +131 -0
  85. package/dist/src/cli/channel-web.js +357 -0
  86. package/dist/src/cli/channel-web.js.map +1 -0
  87. package/dist/src/cli/channel.d.ts +71 -0
  88. package/dist/src/cli/channel.js +438 -0
  89. package/dist/src/cli/channel.js.map +1 -0
  90. package/dist/src/cli/checkpoint-tap.d.ts +169 -0
  91. package/dist/src/cli/checkpoint-tap.js +238 -0
  92. package/dist/src/cli/checkpoint-tap.js.map +1 -0
  93. package/dist/src/cli/codex.d.ts +2 -0
  94. package/dist/src/cli/codex.js +172 -0
  95. package/dist/src/cli/codex.js.map +1 -0
  96. package/dist/src/cli/coverage.d.ts +61 -0
  97. package/dist/src/cli/coverage.js +343 -0
  98. package/dist/src/cli/coverage.js.map +1 -0
  99. package/dist/src/cli/daemon.d.ts +120 -0
  100. package/dist/src/cli/daemon.js +631 -0
  101. package/dist/src/cli/daemon.js.map +1 -0
  102. package/dist/src/cli/doctor.d.ts +129 -0
  103. package/dist/src/cli/doctor.js +2762 -0
  104. package/dist/src/cli/doctor.js.map +1 -0
  105. package/dist/src/cli/env.d.ts +65 -0
  106. package/dist/src/cli/env.js +302 -0
  107. package/dist/src/cli/env.js.map +1 -0
  108. package/dist/src/cli/execute.d.ts +202 -0
  109. package/dist/src/cli/execute.js +1682 -0
  110. package/dist/src/cli/execute.js.map +1 -0
  111. package/dist/src/cli/exit-codes.d.ts +73 -0
  112. package/dist/src/cli/exit-codes.js +82 -0
  113. package/dist/src/cli/exit-codes.js.map +1 -0
  114. package/dist/src/cli/feedback.d.ts +60 -0
  115. package/dist/src/cli/feedback.js +205 -0
  116. package/dist/src/cli/feedback.js.map +1 -0
  117. package/dist/src/cli/gate-window.d.ts +40 -0
  118. package/dist/src/cli/gate-window.js +294 -0
  119. package/dist/src/cli/gate-window.js.map +1 -0
  120. package/dist/src/cli/gate.d.ts +68 -0
  121. package/dist/src/cli/gate.js +557 -0
  122. package/dist/src/cli/gate.js.map +1 -0
  123. package/dist/src/cli/git-scope.d.ts +190 -0
  124. package/dist/src/cli/git-scope.js +295 -0
  125. package/dist/src/cli/git-scope.js.map +1 -0
  126. package/dist/src/cli/gloss-attach.d.ts +85 -0
  127. package/dist/src/cli/gloss-attach.js +107 -0
  128. package/dist/src/cli/gloss-attach.js.map +1 -0
  129. package/dist/src/cli/gloss-codex-child.d.ts +9 -0
  130. package/dist/src/cli/gloss-codex-child.js +149 -0
  131. package/dist/src/cli/gloss-codex-child.js.map +1 -0
  132. package/dist/src/cli/gloss-codex.d.ts +24 -0
  133. package/dist/src/cli/gloss-codex.js +255 -0
  134. package/dist/src/cli/gloss-codex.js.map +1 -0
  135. package/dist/src/cli/gloss-options.d.ts +42 -0
  136. package/dist/src/cli/gloss-options.js +79 -0
  137. package/dist/src/cli/gloss-options.js.map +1 -0
  138. package/dist/src/cli/gloss.d.ts +265 -0
  139. package/dist/src/cli/gloss.js +362 -0
  140. package/dist/src/cli/gloss.js.map +1 -0
  141. package/dist/src/cli/help.d.ts +103 -0
  142. package/dist/src/cli/help.js +2339 -0
  143. package/dist/src/cli/help.js.map +1 -0
  144. package/dist/src/cli/hook-codex.d.ts +78 -0
  145. package/dist/src/cli/hook-codex.js +167 -0
  146. package/dist/src/cli/hook-codex.js.map +1 -0
  147. package/dist/src/cli/hook.d.ts +331 -0
  148. package/dist/src/cli/hook.js +2849 -0
  149. package/dist/src/cli/hook.js.map +1 -0
  150. package/dist/src/cli/import.d.ts +35 -0
  151. package/dist/src/cli/import.js +175 -0
  152. package/dist/src/cli/import.js.map +1 -0
  153. package/dist/src/cli/init.d.ts +84 -0
  154. package/dist/src/cli/init.js +336 -0
  155. package/dist/src/cli/init.js.map +1 -0
  156. package/dist/src/cli/instructions.d.ts +23 -0
  157. package/dist/src/cli/instructions.js +262 -0
  158. package/dist/src/cli/instructions.js.map +1 -0
  159. package/dist/src/cli/journal.d.ts +41 -0
  160. package/dist/src/cli/journal.js +238 -0
  161. package/dist/src/cli/journal.js.map +1 -0
  162. package/dist/src/cli/log-advance.d.ts +287 -0
  163. package/dist/src/cli/log-advance.js +840 -0
  164. package/dist/src/cli/log-advance.js.map +1 -0
  165. package/dist/src/cli/log-anchor.d.ts +176 -0
  166. package/dist/src/cli/log-anchor.js +387 -0
  167. package/dist/src/cli/log-anchor.js.map +1 -0
  168. package/dist/src/cli/log-checkpoint.d.ts +22 -0
  169. package/dist/src/cli/log-checkpoint.js +128 -0
  170. package/dist/src/cli/log-checkpoint.js.map +1 -0
  171. package/dist/src/cli/log-sync.d.ts +243 -0
  172. package/dist/src/cli/log-sync.js +849 -0
  173. package/dist/src/cli/log-sync.js.map +1 -0
  174. package/dist/src/cli/log-verbs.d.ts +16 -0
  175. package/dist/src/cli/log-verbs.js +360 -0
  176. package/dist/src/cli/log-verbs.js.map +1 -0
  177. package/dist/src/cli/long-help.d.ts +70 -0
  178. package/dist/src/cli/long-help.js +148 -0
  179. package/dist/src/cli/long-help.js.map +1 -0
  180. package/dist/src/cli/main.d.ts +77 -0
  181. package/dist/src/cli/main.js +1206 -0
  182. package/dist/src/cli/main.js.map +1 -0
  183. package/dist/src/cli/mcp.d.ts +52 -0
  184. package/dist/src/cli/mcp.js +306 -0
  185. package/dist/src/cli/mcp.js.map +1 -0
  186. package/dist/src/cli/paths.d.ts +56 -0
  187. package/dist/src/cli/paths.js +79 -0
  188. package/dist/src/cli/paths.js.map +1 -0
  189. package/dist/src/cli/payload.d.ts +58 -0
  190. package/dist/src/cli/payload.js +253 -0
  191. package/dist/src/cli/payload.js.map +1 -0
  192. package/dist/src/cli/policy.d.ts +43 -0
  193. package/dist/src/cli/policy.js +229 -0
  194. package/dist/src/cli/policy.js.map +1 -0
  195. package/dist/src/cli/preflight.d.ts +363 -0
  196. package/dist/src/cli/preflight.js +1175 -0
  197. package/dist/src/cli/preflight.js.map +1 -0
  198. package/dist/src/cli/progress.d.ts +78 -0
  199. package/dist/src/cli/progress.js +112 -0
  200. package/dist/src/cli/progress.js.map +1 -0
  201. package/dist/src/cli/prompt.d.ts +209 -0
  202. package/dist/src/cli/prompt.js +312 -0
  203. package/dist/src/cli/prompt.js.map +1 -0
  204. package/dist/src/cli/quickstart.d.ts +46 -0
  205. package/dist/src/cli/quickstart.js +297 -0
  206. package/dist/src/cli/quickstart.js.map +1 -0
  207. package/dist/src/cli/records.d.ts +34 -0
  208. package/dist/src/cli/records.js +66 -0
  209. package/dist/src/cli/records.js.map +1 -0
  210. package/dist/src/cli/render.d.ts +22 -0
  211. package/dist/src/cli/render.js +132 -0
  212. package/dist/src/cli/render.js.map +1 -0
  213. package/dist/src/cli/sandbox.d.ts +51 -0
  214. package/dist/src/cli/sandbox.js +150 -0
  215. package/dist/src/cli/sandbox.js.map +1 -0
  216. package/dist/src/cli/scaffold.d.ts +79 -0
  217. package/dist/src/cli/scaffold.js +137 -0
  218. package/dist/src/cli/scaffold.js.map +1 -0
  219. package/dist/src/cli/setup-adapter.d.ts +137 -0
  220. package/dist/src/cli/setup-adapter.js +509 -0
  221. package/dist/src/cli/setup-adapter.js.map +1 -0
  222. package/dist/src/cli/setup-channel.d.ts +117 -0
  223. package/dist/src/cli/setup-channel.js +635 -0
  224. package/dist/src/cli/setup-channel.js.map +1 -0
  225. package/dist/src/cli/setup-checkpoint.d.ts +57 -0
  226. package/dist/src/cli/setup-checkpoint.js +196 -0
  227. package/dist/src/cli/setup-checkpoint.js.map +1 -0
  228. package/dist/src/cli/setup-common.d.ts +275 -0
  229. package/dist/src/cli/setup-common.js +376 -0
  230. package/dist/src/cli/setup-common.js.map +1 -0
  231. package/dist/src/cli/setup-flow.d.ts +287 -0
  232. package/dist/src/cli/setup-flow.js +476 -0
  233. package/dist/src/cli/setup-flow.js.map +1 -0
  234. package/dist/src/cli/setup-service.d.ts +96 -0
  235. package/dist/src/cli/setup-service.js +308 -0
  236. package/dist/src/cli/setup-service.js.map +1 -0
  237. package/dist/src/cli/setup.d.ts +202 -0
  238. package/dist/src/cli/setup.js +473 -0
  239. package/dist/src/cli/setup.js.map +1 -0
  240. package/dist/src/cli/style.d.ts +320 -0
  241. package/dist/src/cli/style.js +469 -0
  242. package/dist/src/cli/style.js.map +1 -0
  243. package/dist/src/cli/token.d.ts +39 -0
  244. package/dist/src/cli/token.js +274 -0
  245. package/dist/src/cli/token.js.map +1 -0
  246. package/dist/src/cli/up.d.ts +155 -0
  247. package/dist/src/cli/up.js +849 -0
  248. package/dist/src/cli/up.js.map +1 -0
  249. package/dist/src/cli/usage.d.ts +37 -0
  250. package/dist/src/cli/usage.js +91 -0
  251. package/dist/src/cli/usage.js.map +1 -0
  252. package/dist/src/cli/values.d.ts +40 -0
  253. package/dist/src/cli/values.js +189 -0
  254. package/dist/src/cli/values.js.map +1 -0
  255. package/dist/src/cli/vault.d.ts +59 -0
  256. package/dist/src/cli/vault.js +362 -0
  257. package/dist/src/cli/vault.js.map +1 -0
  258. package/dist/src/cli/verb-registry.d.ts +76 -0
  259. package/dist/src/cli/verb-registry.js +2341 -0
  260. package/dist/src/cli/verb-registry.js.map +1 -0
  261. package/dist/src/cli/wordmark.d.ts +31 -0
  262. package/dist/src/cli/wordmark.js +52 -0
  263. package/dist/src/cli/wordmark.js.map +1 -0
  264. package/dist/src/codex/doctor.d.ts +13 -0
  265. package/dist/src/codex/doctor.js +41 -0
  266. package/dist/src/codex/doctor.js.map +1 -0
  267. package/dist/src/codex/manifest.d.ts +49 -0
  268. package/dist/src/codex/manifest.js +103 -0
  269. package/dist/src/codex/manifest.js.map +1 -0
  270. package/dist/src/codex/templates.d.ts +41 -0
  271. package/dist/src/codex/templates.js +319 -0
  272. package/dist/src/codex/templates.js.map +1 -0
  273. package/dist/src/codex/trust.d.ts +19 -0
  274. package/dist/src/codex/trust.js +183 -0
  275. package/dist/src/codex/trust.js.map +1 -0
  276. package/dist/src/codex/workspace-plan.d.ts +131 -0
  277. package/dist/src/codex/workspace-plan.js +561 -0
  278. package/dist/src/codex/workspace-plan.js.map +1 -0
  279. package/dist/src/core/actor.d.ts +2 -0
  280. package/dist/src/core/actor.js +5 -0
  281. package/dist/src/core/actor.js.map +1 -0
  282. package/dist/src/core/advance-cycle.d.ts +170 -0
  283. package/dist/src/core/advance-cycle.js +200 -0
  284. package/dist/src/core/advance-cycle.js.map +1 -0
  285. package/dist/src/core/agents-md.d.ts +276 -0
  286. package/dist/src/core/agents-md.js +747 -0
  287. package/dist/src/core/agents-md.js.map +1 -0
  288. package/dist/src/core/apply-patch.d.ts +49 -0
  289. package/dist/src/core/apply-patch.js +266 -0
  290. package/dist/src/core/apply-patch.js.map +1 -0
  291. package/dist/src/core/attest.d.ts +420 -0
  292. package/dist/src/core/attest.js +589 -0
  293. package/dist/src/core/attest.js.map +1 -0
  294. package/dist/src/core/audit.d.ts +492 -0
  295. package/dist/src/core/audit.js +882 -0
  296. package/dist/src/core/audit.js.map +1 -0
  297. package/dist/src/core/budgets.d.ts +238 -0
  298. package/dist/src/core/budgets.js +449 -0
  299. package/dist/src/core/budgets.js.map +1 -0
  300. package/dist/src/core/checkpoint.d.ts +500 -0
  301. package/dist/src/core/checkpoint.js +738 -0
  302. package/dist/src/core/checkpoint.js.map +1 -0
  303. package/dist/src/core/child-env.d.ts +88 -0
  304. package/dist/src/core/child-env.js +86 -0
  305. package/dist/src/core/child-env.js.map +1 -0
  306. package/dist/src/core/clock.d.ts +52 -0
  307. package/dist/src/core/clock.js +43 -0
  308. package/dist/src/core/clock.js.map +1 -0
  309. package/dist/src/core/command-class.d.ts +543 -0
  310. package/dist/src/core/command-class.js +2356 -0
  311. package/dist/src/core/command-class.js.map +1 -0
  312. package/dist/src/core/coverage-sources/adapter.d.ts +40 -0
  313. package/dist/src/core/coverage-sources/adapter.js +71 -0
  314. package/dist/src/core/coverage-sources/adapter.js.map +1 -0
  315. package/dist/src/core/coverage-sources/gh.d.ts +48 -0
  316. package/dist/src/core/coverage-sources/gh.js +136 -0
  317. package/dist/src/core/coverage-sources/gh.js.map +1 -0
  318. package/dist/src/core/coverage-sources/git.d.ts +101 -0
  319. package/dist/src/core/coverage-sources/git.js +269 -0
  320. package/dist/src/core/coverage-sources/git.js.map +1 -0
  321. package/dist/src/core/coverage.d.ts +217 -0
  322. package/dist/src/core/coverage.js +337 -0
  323. package/dist/src/core/coverage.js.map +1 -0
  324. package/dist/src/core/credential-spec.d.ts +72 -0
  325. package/dist/src/core/credential-spec.js +23 -0
  326. package/dist/src/core/credential-spec.js.map +1 -0
  327. package/dist/src/core/dark-session.d.ts +331 -0
  328. package/dist/src/core/dark-session.js +714 -0
  329. package/dist/src/core/dark-session.js.map +1 -0
  330. package/dist/src/core/decision-refusal.d.ts +185 -0
  331. package/dist/src/core/decision-refusal.js +265 -0
  332. package/dist/src/core/decision-refusal.js.map +1 -0
  333. package/dist/src/core/env-file.d.ts +450 -0
  334. package/dist/src/core/env-file.js +837 -0
  335. package/dist/src/core/env-file.js.map +1 -0
  336. package/dist/src/core/execute.d.ts +858 -0
  337. package/dist/src/core/execute.js +1271 -0
  338. package/dist/src/core/execute.js.map +1 -0
  339. package/dist/src/core/frontmatter.d.ts +78 -0
  340. package/dist/src/core/frontmatter.js +100 -0
  341. package/dist/src/core/frontmatter.js.map +1 -0
  342. package/dist/src/core/gate-window.d.ts +312 -0
  343. package/dist/src/core/gate-window.js +506 -0
  344. package/dist/src/core/gate-window.js.map +1 -0
  345. package/dist/src/core/gate.d.ts +1364 -0
  346. package/dist/src/core/gate.js +3002 -0
  347. package/dist/src/core/gate.js.map +1 -0
  348. package/dist/src/core/git-run.d.ts +73 -0
  349. package/dist/src/core/git-run.js +93 -0
  350. package/dist/src/core/git-run.js.map +1 -0
  351. package/dist/src/core/harness-version.d.ts +157 -0
  352. package/dist/src/core/harness-version.js +211 -0
  353. package/dist/src/core/harness-version.js.map +1 -0
  354. package/dist/src/core/harness-wait.d.ts +55 -0
  355. package/dist/src/core/harness-wait.js +58 -0
  356. package/dist/src/core/harness-wait.js.map +1 -0
  357. package/dist/src/core/head-retry.d.ts +107 -0
  358. package/dist/src/core/head-retry.js +121 -0
  359. package/dist/src/core/head-retry.js.map +1 -0
  360. package/dist/src/core/instance.d.ts +253 -0
  361. package/dist/src/core/instance.js +319 -0
  362. package/dist/src/core/instance.js.map +1 -0
  363. package/dist/src/core/intake-limits.d.ts +247 -0
  364. package/dist/src/core/intake-limits.js +350 -0
  365. package/dist/src/core/intake-limits.js.map +1 -0
  366. package/dist/src/core/jcs.d.ts +52 -0
  367. package/dist/src/core/jcs.js +132 -0
  368. package/dist/src/core/jcs.js.map +1 -0
  369. package/dist/src/core/journal.d.ts +144 -0
  370. package/dist/src/core/journal.js +200 -0
  371. package/dist/src/core/journal.js.map +1 -0
  372. package/dist/src/core/live-draw.d.ts +436 -0
  373. package/dist/src/core/live-draw.js +703 -0
  374. package/dist/src/core/live-draw.js.map +1 -0
  375. package/dist/src/core/log-reconcile.d.ts +89 -0
  376. package/dist/src/core/log-reconcile.js +136 -0
  377. package/dist/src/core/log-reconcile.js.map +1 -0
  378. package/dist/src/core/log-subscribe.d.ts +36 -0
  379. package/dist/src/core/log-subscribe.js +162 -0
  380. package/dist/src/core/log-subscribe.js.map +1 -0
  381. package/dist/src/core/log.d.ts +278 -0
  382. package/dist/src/core/log.js +546 -0
  383. package/dist/src/core/log.js.map +1 -0
  384. package/dist/src/core/loop.d.ts +274 -0
  385. package/dist/src/core/loop.js +487 -0
  386. package/dist/src/core/loop.js.map +1 -0
  387. package/dist/src/core/md-fence.d.ts +41 -0
  388. package/dist/src/core/md-fence.js +74 -0
  389. package/dist/src/core/md-fence.js.map +1 -0
  390. package/dist/src/core/money.d.ts +147 -0
  391. package/dist/src/core/money.js +195 -0
  392. package/dist/src/core/money.js.map +1 -0
  393. package/dist/src/core/payload-census.d.ts +74 -0
  394. package/dist/src/core/payload-census.js +146 -0
  395. package/dist/src/core/payload-census.js.map +1 -0
  396. package/dist/src/core/payload-store.d.ts +175 -0
  397. package/dist/src/core/payload-store.js +340 -0
  398. package/dist/src/core/payload-store.js.map +1 -0
  399. package/dist/src/core/payload.d.ts +71 -0
  400. package/dist/src/core/payload.js +80 -0
  401. package/dist/src/core/payload.js.map +1 -0
  402. package/dist/src/core/policy-diff.d.ts +292 -0
  403. package/dist/src/core/policy-diff.js +588 -0
  404. package/dist/src/core/policy-diff.js.map +1 -0
  405. package/dist/src/core/policy-expectations.d.ts +199 -0
  406. package/dist/src/core/policy-expectations.js +394 -0
  407. package/dist/src/core/policy-expectations.js.map +1 -0
  408. package/dist/src/core/policy-explain.d.ts +150 -0
  409. package/dist/src/core/policy-explain.js +258 -0
  410. package/dist/src/core/policy-explain.js.map +1 -0
  411. package/dist/src/core/policy-load.d.ts +527 -0
  412. package/dist/src/core/policy-load.js +536 -0
  413. package/dist/src/core/policy-load.js.map +1 -0
  414. package/dist/src/core/policy-match.d.ts +281 -0
  415. package/dist/src/core/policy-match.js +478 -0
  416. package/dist/src/core/policy-match.js.map +1 -0
  417. package/dist/src/core/policy-proposal.d.ts +265 -0
  418. package/dist/src/core/policy-proposal.js +458 -0
  419. package/dist/src/core/policy-proposal.js.map +1 -0
  420. package/dist/src/core/prompt-layout.d.ts +221 -0
  421. package/dist/src/core/prompt-layout.js +422 -0
  422. package/dist/src/core/prompt-layout.js.map +1 -0
  423. package/dist/src/core/protected-path-guard.d.ts +453 -0
  424. package/dist/src/core/protected-path-guard.js +1566 -0
  425. package/dist/src/core/protected-path-guard.js.map +1 -0
  426. package/dist/src/core/registration.d.ts +25 -0
  427. package/dist/src/core/registration.js +39 -0
  428. package/dist/src/core/registration.js.map +1 -0
  429. package/dist/src/core/reindex.d.ts +99 -0
  430. package/dist/src/core/reindex.js +336 -0
  431. package/dist/src/core/reindex.js.map +1 -0
  432. package/dist/src/core/sampler.d.ts +313 -0
  433. package/dist/src/core/sampler.js +388 -0
  434. package/dist/src/core/sampler.js.map +1 -0
  435. package/dist/src/core/sandbox.d.ts +290 -0
  436. package/dist/src/core/sandbox.js +424 -0
  437. package/dist/src/core/sandbox.js.map +1 -0
  438. package/dist/src/core/seal.d.ts +165 -0
  439. package/dist/src/core/seal.js +290 -0
  440. package/dist/src/core/seal.js.map +1 -0
  441. package/dist/src/core/state.d.ts +505 -0
  442. package/dist/src/core/state.js +1009 -0
  443. package/dist/src/core/state.js.map +1 -0
  444. package/dist/src/core/task-file.d.ts +185 -0
  445. package/dist/src/core/task-file.js +464 -0
  446. package/dist/src/core/task-file.js.map +1 -0
  447. package/dist/src/core/telegram-config.d.ts +93 -0
  448. package/dist/src/core/telegram-config.js +114 -0
  449. package/dist/src/core/telegram-config.js.map +1 -0
  450. package/dist/src/core/token.d.ts +409 -0
  451. package/dist/src/core/token.js +561 -0
  452. package/dist/src/core/token.js.map +1 -0
  453. package/dist/src/core/validate.d.ts +138 -0
  454. package/dist/src/core/validate.js +0 -0
  455. package/dist/src/core/validate.js.map +1 -0
  456. package/dist/src/core/values.d.ts +137 -0
  457. package/dist/src/core/values.js +153 -0
  458. package/dist/src/core/values.js.map +1 -0
  459. package/dist/src/core/vault.d.ts +291 -0
  460. package/dist/src/core/vault.js +612 -0
  461. package/dist/src/core/vault.js.map +1 -0
  462. package/dist/src/core/verified-snapshot.d.ts +204 -0
  463. package/dist/src/core/verified-snapshot.js +506 -0
  464. package/dist/src/core/verified-snapshot.js.map +1 -0
  465. package/dist/src/core/verify.d.ts +336 -0
  466. package/dist/src/core/verify.js +549 -0
  467. package/dist/src/core/verify.js.map +1 -0
  468. package/dist/src/core/version.d.ts +8 -0
  469. package/dist/src/core/version.js +9 -0
  470. package/dist/src/core/version.js.map +1 -0
  471. package/dist/src/core/wysiwys.d.ts +370 -0
  472. package/dist/src/core/wysiwys.js +728 -0
  473. package/dist/src/core/wysiwys.js.map +1 -0
  474. package/dist/src/daemon/advance-child.d.ts +39 -0
  475. package/dist/src/daemon/advance-child.js +78 -0
  476. package/dist/src/daemon/advance-child.js.map +1 -0
  477. package/dist/src/daemon/advance.d.ts +466 -0
  478. package/dist/src/daemon/advance.js +849 -0
  479. package/dist/src/daemon/advance.js.map +1 -0
  480. package/dist/src/daemon/audit.d.ts +87 -0
  481. package/dist/src/daemon/audit.js +90 -0
  482. package/dist/src/daemon/audit.js.map +1 -0
  483. package/dist/src/daemon/daemon.d.ts +1180 -0
  484. package/dist/src/daemon/daemon.js +1988 -0
  485. package/dist/src/daemon/daemon.js.map +1 -0
  486. package/dist/src/daemon/dark-session.d.ts +64 -0
  487. package/dist/src/daemon/dark-session.js +119 -0
  488. package/dist/src/daemon/dark-session.js.map +1 -0
  489. package/dist/src/daemon/draw-child.d.ts +36 -0
  490. package/dist/src/daemon/draw-child.js +132 -0
  491. package/dist/src/daemon/draw-child.js.map +1 -0
  492. package/dist/src/daemon/draw.d.ts +154 -0
  493. package/dist/src/daemon/draw.js +458 -0
  494. package/dist/src/daemon/draw.js.map +1 -0
  495. package/dist/src/daemon/git-evidence.d.ts +173 -0
  496. package/dist/src/daemon/git-evidence.js +345 -0
  497. package/dist/src/daemon/git-evidence.js.map +1 -0
  498. package/dist/src/daemon/projection.d.ts +180 -0
  499. package/dist/src/daemon/projection.js +233 -0
  500. package/dist/src/daemon/projection.js.map +1 -0
  501. package/dist/src/daemon/prune.d.ts +207 -0
  502. package/dist/src/daemon/prune.js +376 -0
  503. package/dist/src/daemon/prune.js.map +1 -0
  504. package/dist/src/mcp/http.d.ts +113 -0
  505. package/dist/src/mcp/http.js +343 -0
  506. package/dist/src/mcp/http.js.map +1 -0
  507. package/dist/src/mcp/server.d.ts +265 -0
  508. package/dist/src/mcp/server.js +602 -0
  509. package/dist/src/mcp/server.js.map +1 -0
  510. package/docs/adapter-api.md +106 -0
  511. package/docs/cli-reference.md +5716 -0
  512. package/docs/codex-enforced-session.md +30 -0
  513. package/package.json +53 -4
  514. package/schema/.gitkeep +0 -0
  515. package/schema/LICENSE +117 -0
  516. package/schema/codex-instance.schema.json +82 -0
  517. package/schema/envelope.schema.json +137 -0
  518. package/schema/event.schema.json +1811 -0
  519. package/schema/fixtures/codex-instance/invalid/unpinned-codex-version.json +40 -0
  520. package/schema/fixtures/codex-instance/valid/canonical.json +40 -0
  521. package/schema/fixtures/envelope/invalid/action-missing-idempotency-key.json +15 -0
  522. package/schema/fixtures/envelope/invalid/action-unknown-class-format.json +14 -0
  523. package/schema/fixtures/envelope/invalid/confidence-out-of-range.json +11 -0
  524. package/schema/fixtures/envelope/invalid/est-cost-bare-number.json +14 -0
  525. package/schema/fixtures/envelope/invalid/est-cost-noncanonical-string.json +14 -0
  526. package/schema/fixtures/envelope/invalid/malformed-assignee.json +10 -0
  527. package/schema/fixtures/envelope/invalid/malformed-created-by.json +7 -0
  528. package/schema/fixtures/envelope/invalid/malformed-max-latency.json +11 -0
  529. package/schema/fixtures/envelope/invalid/malformed-payload-hash.json +14 -0
  530. package/schema/fixtures/envelope/invalid/max-cost-bare-number.json +11 -0
  531. package/schema/fixtures/envelope/invalid/missing-origin.json +3 -0
  532. package/schema/fixtures/envelope/invalid/negative-est-cost.json +14 -0
  533. package/schema/fixtures/envelope/invalid/unknown-state.json +7 -0
  534. package/schema/fixtures/envelope/invalid/unknown-top-level-field.json +8 -0
  535. package/schema/fixtures/envelope/valid/action-payload-hash.json +17 -0
  536. package/schema/fixtures/envelope/valid/actions-without-budget.json +18 -0
  537. package/schema/fixtures/envelope/valid/canonical.json +25 -0
  538. package/schema/fixtures/envelope/valid/minimal.json +7 -0
  539. package/schema/fixtures/envelope/valid/multi-action-executed.json +30 -0
  540. package/schema/fixtures/envelope/valid/record-write-stage.json +22 -0
  541. package/schema/fixtures/event/invalid/approval-granted-agent-actor.json +15 -0
  542. package/schema/fixtures/event/invalid/approval-granted-empty-batch-delivery-id.json +17 -0
  543. package/schema/fixtures/event/invalid/approval-granted-fifth-reaction.json +16 -0
  544. package/schema/fixtures/event/invalid/approval-granted-missing-actor.json +14 -0
  545. package/schema/fixtures/event/invalid/approval-requested-missing-action-key.json +14 -0
  546. package/schema/fixtures/event/invalid/approval-withdrawn-agent-policy-drift.json +15 -0
  547. package/schema/fixtures/event/invalid/approval-withdrawn-missing-reason.json +15 -0
  548. package/schema/fixtures/event/invalid/approval-withdrawn-system-actor.json +15 -0
  549. package/schema/fixtures/event/invalid/audit-decision-refused-human-actor.json +17 -0
  550. package/schema/fixtures/event/invalid/audit-decision-refused-missing-code.json +16 -0
  551. package/schema/fixtures/event/invalid/audit-reviewed-agent-actor.json +15 -0
  552. package/schema/fixtures/event/invalid/audit-reviewed-loved-no-note.json +16 -0
  553. package/schema/fixtures/event/invalid/audit-reviewed-system-actor.json +15 -0
  554. package/schema/fixtures/event/invalid/bad-actor-prefix.json +15 -0
  555. package/schema/fixtures/event/invalid/est-cost-bare-number.json +17 -0
  556. package/schema/fixtures/event/invalid/execution-completed-fabricated-exit-code.json +16 -0
  557. package/schema/fixtures/event/invalid/execution-completed-provider-ref-empty-id.json +18 -0
  558. package/schema/fixtures/event/invalid/execution-completed-provider-ref-extra-field.json +19 -0
  559. package/schema/fixtures/event/invalid/execution-completed-provider-ref-id-not-string.json +18 -0
  560. package/schema/fixtures/event/invalid/execution-completed-provider-ref-missing-adapter.json +17 -0
  561. package/schema/fixtures/event/invalid/execution-failed-open-reported-by.json +16 -0
  562. package/schema/fixtures/event/invalid/execution-indeterminate-open-reason.json +14 -0
  563. package/schema/fixtures/event/invalid/execution-reconciled-agent-actor.json +17 -0
  564. package/schema/fixtures/event/invalid/execution-started-negative-env-stripped.json +16 -0
  565. package/schema/fixtures/event/invalid/gate-bypassed-missing-opened-seq.json +15 -0
  566. package/schema/fixtures/event/invalid/gate-closed-non-integer-opened-seq.json +13 -0
  567. package/schema/fixtures/event/invalid/gate-opened-agent-actor.json +16 -0
  568. package/schema/fixtures/event/invalid/gate-organ-attested-absolute-path.json +14 -0
  569. package/schema/fixtures/event/invalid/gate-organ-attested-agent-actor.json +14 -0
  570. package/schema/fixtures/event/invalid/gate-organ-attested-missing-organ-path.json +13 -0
  571. package/schema/fixtures/event/invalid/harness-unknown-kind.json +18 -0
  572. package/schema/fixtures/event/invalid/harness-version-multiline.json +16 -0
  573. package/schema/fixtures/event/invalid/log-checkpoint-agent-actor.json +17 -0
  574. package/schema/fixtures/event/invalid/log-checkpoint-missing-signature.json +16 -0
  575. package/schema/fixtures/event/invalid/log-checkpoint-short-signed-hash.json +17 -0
  576. package/schema/fixtures/event/invalid/log-checkpoint-unknown-signature-alg.json +17 -0
  577. package/schema/fixtures/event/invalid/malformed-ts.json +15 -0
  578. package/schema/fixtures/event/invalid/missing-alg.json +14 -0
  579. package/schema/fixtures/event/invalid/missing-hash.json +14 -0
  580. package/schema/fixtures/event/invalid/non-integer-seq.json +15 -0
  581. package/schema/fixtures/event/invalid/payload-pruned-human-actor.json +14 -0
  582. package/schema/fixtures/event/invalid/payload-pruned-missing-hash.json +14 -0
  583. package/schema/fixtures/event/invalid/policy-declined-agent-actor.json +15 -0
  584. package/schema/fixtures/event/invalid/policy-proposed-missing-diff.json +19 -0
  585. package/schema/fixtures/event/invalid/policy-proposed-system-actor.json +26 -0
  586. package/schema/fixtures/event/invalid/short-hash.json +15 -0
  587. package/schema/fixtures/event/invalid/unknown-alg.json +15 -0
  588. package/schema/fixtures/event/invalid/unknown-event-type.json +15 -0
  589. package/schema/fixtures/event/invalid/unknown-top-level-field.json +16 -0
  590. package/schema/fixtures/event/valid/approval-expired.json +15 -0
  591. package/schema/fixtures/event/valid/approval-granted-batch.json +19 -0
  592. package/schema/fixtures/event/valid/approval-granted-reaction.json +16 -0
  593. package/schema/fixtures/event/valid/approval-granted.json +15 -0
  594. package/schema/fixtures/event/valid/approval-rejected.json +15 -0
  595. package/schema/fixtures/event/valid/approval-requested.json +19 -0
  596. package/schema/fixtures/event/valid/approval-revoked.json +15 -0
  597. package/schema/fixtures/event/valid/approval-withdrawn-policy-drift.json +17 -0
  598. package/schema/fixtures/event/valid/approval-withdrawn.json +16 -0
  599. package/schema/fixtures/event/valid/audit-decision-refused.json +20 -0
  600. package/schema/fixtures/event/valid/audit-reviewed-reaction.json +17 -0
  601. package/schema/fixtures/event/valid/audit-reviewed.json +15 -0
  602. package/schema/fixtures/event/valid/audit-sampled.json +14 -0
  603. package/schema/fixtures/event/valid/budget-exceeded.json +21 -0
  604. package/schema/fixtures/event/valid/envelope-drift.json +16 -0
  605. package/schema/fixtures/event/valid/execution-completed-harness-report.json +16 -0
  606. package/schema/fixtures/event/valid/execution-completed-provider-ref.json +18 -0
  607. package/schema/fixtures/event/valid/execution-completed.json +15 -0
  608. package/schema/fixtures/event/valid/execution-failed-harness-report.json +16 -0
  609. package/schema/fixtures/event/valid/execution-failed.json +15 -0
  610. package/schema/fixtures/event/valid/execution-indeterminate.json +15 -0
  611. package/schema/fixtures/event/valid/execution-reconciled.json +17 -0
  612. package/schema/fixtures/event/valid/execution-started-env-stripped.json +17 -0
  613. package/schema/fixtures/event/valid/execution-started.json +14 -0
  614. package/schema/fixtures/event/valid/gate-bypassed-harness-version.json +18 -0
  615. package/schema/fixtures/event/valid/gate-bypassed.json +19 -0
  616. package/schema/fixtures/event/valid/gate-closed.json +14 -0
  617. package/schema/fixtures/event/valid/gate-opened.json +16 -0
  618. package/schema/fixtures/event/valid/gate-organ-attested.json +14 -0
  619. package/schema/fixtures/event/valid/genesis-null-prev.json +14 -0
  620. package/schema/fixtures/event/valid/log-checkpoint.json +17 -0
  621. package/schema/fixtures/event/valid/payload-pruned-orphan.json +13 -0
  622. package/schema/fixtures/event/valid/payload-pruned.json +17 -0
  623. package/schema/fixtures/event/valid/policy-declined.json +16 -0
  624. package/schema/fixtures/event/valid/policy-proposed.json +35 -0
  625. package/schema/fixtures/event/valid/policy-updated.json +14 -0
  626. package/schema/fixtures/event/valid/reconciliation-required.json +18 -0
  627. package/schema/fixtures/event/valid/reconciliation-satisfied.json +17 -0
  628. package/schema/fixtures/event/valid/route-accepted.json +15 -0
  629. package/schema/fixtures/event/valid/route-proposed.json +16 -0
  630. package/schema/fixtures/event/valid/spec-example.json +15 -0
  631. package/schema/fixtures/event/valid/task-registered-harness-version.json +23 -0
  632. package/schema/fixtures/event/valid/task-registered.json +14 -0
  633. package/schema/fixtures/hash/known-answer-pre-121.json +74 -0
  634. package/schema/fixtures/hash/known-answer.json +74 -0
  635. package/schema/fixtures/policy/invalid/bad-approval-ttl.json +7 -0
  636. package/schema/fixtures/policy/invalid/bad-web-port.json +4 -0
  637. package/schema/fixtures/policy/invalid/checkpoint-key-not-base64.json +6 -0
  638. package/schema/fixtures/policy/invalid/class-rule-missing-autonomy.json +9 -0
  639. package/schema/fixtures/policy/invalid/empty-class-key.json +6 -0
  640. package/schema/fixtures/policy/invalid/live-rate-on-human-only.json +7 -0
  641. package/schema/fixtures/policy/invalid/malformed-class-key.json +6 -0
  642. package/schema/fixtures/policy/invalid/missing-version.json +8 -0
  643. package/schema/fixtures/policy/invalid/negative-limit.json +9 -0
  644. package/schema/fixtures/policy/invalid/non-numeric-limit.json +9 -0
  645. package/schema/fixtures/policy/invalid/non-positive-max-pending.json +9 -0
  646. package/schema/fixtures/policy/invalid/on-expiry-grant.json +8 -0
  647. package/schema/fixtures/policy/invalid/payload-retention-bare-number.json +4 -0
  648. package/schema/fixtures/policy/invalid/payload-retention-compound.json +4 -0
  649. package/schema/fixtures/policy/invalid/payload-retention-fractional.json +4 -0
  650. package/schema/fixtures/policy/invalid/payload-retention-zero.json +4 -0
  651. package/schema/fixtures/policy/invalid/protected-paths-escape.json +4 -0
  652. package/schema/fixtures/policy/invalid/protected-paths-glob.json +4 -0
  653. package/schema/fixtures/policy/invalid/retro-rate-on-human-only.json +7 -0
  654. package/schema/fixtures/policy/invalid/retro-rate-on-manual.json +7 -0
  655. package/schema/fixtures/policy/invalid/retro-rate-zero.json +7 -0
  656. package/schema/fixtures/policy/invalid/sample-rate-too-high.json +5 -0
  657. package/schema/fixtures/policy/invalid/sampling-secret-env-empty.json +7 -0
  658. package/schema/fixtures/policy/invalid/sampling-secret-env-not-string.json +6 -0
  659. package/schema/fixtures/policy/invalid/skew-tolerance-compound.json +6 -0
  660. package/schema/fixtures/policy/invalid/unknown-autonomy.json +7 -0
  661. package/schema/fixtures/policy/invalid/unknown-class-rule-key.json +6 -0
  662. package/schema/fixtures/policy/invalid/unknown-top-level-key.json +7 -0
  663. package/schema/fixtures/policy/invalid/vault-passphrase-env-empty.json +6 -0
  664. package/schema/fixtures/policy/invalid/vault-passphrase-literal.json +6 -0
  665. package/schema/fixtures/policy/invalid/version-not-string.json +4 -0
  666. package/schema/fixtures/policy/valid/canonical.json +47 -0
  667. package/schema/fixtures/policy/valid/checkpoint-keys.json +18 -0
  668. package/schema/fixtures/policy/valid/class-approvers-limits.json +25 -0
  669. package/schema/fixtures/policy/valid/class-retro-rate.json +17 -0
  670. package/schema/fixtures/policy/valid/global-budgets.json +19 -0
  671. package/schema/fixtures/policy/valid/human-only.json +9 -0
  672. package/schema/fixtures/policy/valid/minimal.json +6 -0
  673. package/schema/fixtures/policy/valid/protected-paths.json +10 -0
  674. package/schema/fixtures/policy/valid/record-namespace.json +13 -0
  675. package/schema/fixtures/policy/valid/request-volume-limits.json +26 -0
  676. package/schema/fixtures/policy/valid/retention-and-sampling-secret.json +16 -0
  677. package/schema/fixtures/policy/valid/skew-tolerance.json +15 -0
  678. package/schema/fixtures/policy/valid/vault-passphrase-env.json +14 -0
  679. package/schema/fixtures/policy/valid/wildcards.json +15 -0
  680. package/schema/fixtures/policy-md/invalid/alias-bomb.md +15 -0
  681. package/schema/fixtures/policy-md/invalid/no-fence.md +7 -0
  682. package/schema/fixtures/policy-md/invalid/protected-route-not-a-subclass.md +16 -0
  683. package/schema/fixtures/policy-md/invalid/schema-invalid-autonomy.md +16 -0
  684. package/schema/fixtures/policy-md/invalid/schema-invalid-read-proof.md +17 -0
  685. package/schema/fixtures/policy-md/invalid/two-fences.md +19 -0
  686. package/schema/fixtures/policy-md/invalid/unclosed-fence.md +11 -0
  687. package/schema/fixtures/policy-md/invalid/wrong-info-string.md +11 -0
  688. package/schema/fixtures/policy-md/invalid/yaml-syntax-error.md +13 -0
  689. package/schema/fixtures/policy-md/precedence/both/APPROVAL.md +7 -0
  690. package/schema/fixtures/policy-md/precedence/both/APPROVALS.md +7 -0
  691. package/schema/fixtures/policy-md/precedence/fallback-only/APPROVALS.md +7 -0
  692. package/schema/fixtures/policy-md/valid/canonical.md +50 -0
  693. package/schema/fixtures/policy-md/valid/daemon-read-proof.md +18 -0
  694. package/schema/fixtures/policy-md/valid/minimal.md +3 -0
  695. package/schema/fixtures/policy-md/valid/prose-lookalikes.md +54 -0
  696. package/schema/fixtures/policy-md/valid/routed-protected-paths.md +49 -0
  697. package/schema/fixtures/policy-md/valid/with-values.md +79 -0
  698. package/schema/fixtures/sample-record/invalid/bad-date-time.json +4 -0
  699. package/schema/fixtures/sample-record/invalid/missing-required-field.json +3 -0
  700. package/schema/fixtures/sample-record/invalid/unknown-top-level-field.json +5 -0
  701. package/schema/fixtures/sample-record/invalid/wrong-type.json +4 -0
  702. package/schema/fixtures/sample-record/valid/minimal.json +4 -0
  703. package/schema/fixtures/sample-record/valid/with-note.json +5 -0
  704. package/schema/fixtures/values/invalid/class-shaped.json +9 -0
  705. package/schema/fixtures/values/invalid/duplicate-entry.json +4 -0
  706. package/schema/fixtures/values/invalid/non-string-item.json +4 -0
  707. package/schema/fixtures/values/invalid/over-cap.json +26 -0
  708. package/schema/fixtures/values/invalid/unknown-key.json +5 -0
  709. package/schema/fixtures/values/invalid/version-string.json +1 -0
  710. package/schema/fixtures/values/valid/empty-lists.json +7 -0
  711. package/schema/fixtures/values/valid/full.json +20 -0
  712. package/schema/fixtures/values/valid/minimal.json +1 -0
  713. package/schema/fixtures/values-md/invalid/schema-invalid.md +62 -0
  714. package/schema/fixtures/values-md/invalid/two-blocks.md +69 -0
  715. package/schema/fixtures/values-md/invalid/unterminated.md +61 -0
  716. package/schema/fixtures/values-md/invalid/yaml-error.md +63 -0
  717. package/schema/fixtures/values-md/valid/absent.md +50 -0
  718. package/schema/fixtures/values-md/valid/with-values.md +79 -0
  719. package/schema/policy.schema.json +501 -0
  720. package/schema/sample-record.schema.json +26 -0
  721. package/schema/values.schema.json +55 -0
  722. package/templates/codex/README.md +9 -0
@@ -0,0 +1,849 @@
1
+ /**
2
+ * The daemon's log advance, on a cadence and through the gate (APRV-204).
3
+ *
4
+ * ## Why the daemon does this at all
5
+ *
6
+ * The committed log is this project's truth, and until this module its
7
+ * freshness depended on somebody remembering to run `approval log advance`. The
8
+ * daemon is already the committed log's sole writer in the primary checkout, it
9
+ * is already awake, and since the seq 7413 ceremony `log.advance` resolves
10
+ * `supervised-live 0.1` — a class that needs no hand on the keyboard for nine
11
+ * runs in ten. So the bookkeeping moves here, and the human's part shrinks to
12
+ * the tenth run and the merge.
13
+ *
14
+ * ## It borrows every mechanism and owns none
15
+ *
16
+ * - The advance itself is `cli/log-advance.ts`'s `logAdvance`, called
17
+ * unmodified: the same append lock, the same chain verify, the same staged-set
18
+ * refusal, the same commit-on-the-remote-without-a-checkout. A second
19
+ * implementation would be a second thing to get wrong about the one file
20
+ * nothing may rewind.
21
+ * - The authorization is `core/gate.ts`'s `register` + `request` and
22
+ * `core/execute.ts`'s `startExecution` / `finishExecution`, in that order and
23
+ * with no shortcuts. The daemon proposes as `agent:daemon` and the runtime
24
+ * decides, exactly as it decides for a session.
25
+ * - The cadence and the reporting are the only decisions here, and neither
26
+ * touches the log.
27
+ *
28
+ * ## What happens when the gate says no
29
+ *
30
+ * A `supervised-live` draw that SELECTS this advance, a class amended to
31
+ * `manual`, a policy that will not load: all three end the attempt with nothing
32
+ * committed and nothing pushed. The outcome is reported on the daemon's event
33
+ * stream and readable afterwards from the log itself, and the next tick tries
34
+ * again — after the cadence interval, never immediately, because the
35
+ * last-attempt clock is set by a refusal exactly as it is by a success. There
36
+ * is no retry loop and no backoff ladder: the cadence IS the backoff.
37
+ *
38
+ * ## The merge: armed here, performed by nobody (APRV-284)
39
+ *
40
+ * This file still calls no merge. What it does is ask `logAdvance` to ARM one:
41
+ * `gh pr merge <branch> --merge --auto` on the day's records pull request, so
42
+ * the pull request lands when its checks and the repository's branch rules say
43
+ * it may, and never earlier. Before APRV-284 it sat at CLEAN until a person
44
+ * clicked, which is the failure mode CLAUDE.md's workflow item 7 is written
45
+ * against — and clicking was never a review, because a records branch carries
46
+ * only the log, `QUEUE.md` and `.approval/payloads/`, the three paths CI's
47
+ * protected-path guard exempts.
48
+ *
49
+ * Two things keep that from being a daemon approving its own evidence. The arm
50
+ * is `vcs.push.main` in this project's taxonomy — the same class as the same
51
+ * command in a session's hands — and it rides the SAME `log.advance`
52
+ * authorization this cycle already holds rather than opening a second question
53
+ * or claiming a second grant: one authorization, one act. And `cli/log-advance.
54
+ * ts`'s `armAutoMerge` withholds the arm outright when the branch it pushed
55
+ * carries a path an advance may not carry, so what gets armed is only ever
56
+ * evidence. `--no-advance-auto-merge` turns the whole thing off.
57
+ *
58
+ * ## The self-perpetuation trap, and how the trigger avoids it
59
+ *
60
+ * One advance cycle appends three records of its own (`task.registered`,
61
+ * `execution.started`, `execution.completed`). Two of them land before the
62
+ * commit and ride it; the third lands after, so every successful advance leaves
63
+ * the log one record ahead of the records branch. A trigger that counted those
64
+ * would advance forever on an idle repository. So the TRIGGER counts only
65
+ * records that are not an advance's own bookkeeping (`PublishedState.substantive`),
66
+ * while the count REPORTED to an operator is the honest raw one.
67
+ *
68
+ * ## Where the pieces live
69
+ *
70
+ * The cycle's vocabulary (the actor, the class, the task and key shapes, and
71
+ * reading the last cycle back out of the log) is `core/advance-cycle.ts`, and
72
+ * the git-side "what is already published" question is `cli/log-advance.ts`.
73
+ * Both are shared with `approval doctor`, which reports the same numbers in a
74
+ * different process — and a CLI module may not import the daemon.
75
+ */
76
+ import { spawn } from "node:child_process";
77
+ import { fileURLToPath } from "node:url";
78
+ import { tick } from "../core/clock.js";
79
+ import { ADVANCE_ACTOR, ADVANCE_CLASS, RESOLVE_DANGLING_COMMAND, advanceActionKey, advanceTaskId, danglingAdvances, openAdvanceRequest, proveDanglingAdvances, } from "../core/advance-cycle.js";
80
+ import { childEnvironment } from "../core/child-env.js";
81
+ import { finishExecution, startExecution, } from "../core/execute.js";
82
+ import { register, request } from "../core/gate.js";
83
+ import { attemptsOf, withHeadRetry } from "../core/head-retry.js";
84
+ import { payloadHash } from "../core/payload.js";
85
+ import { loadPolicy } from "../core/policy-load.js";
86
+ import { defaultRecordsBranch, logAdvance, publishedState, } from "../cli/log-advance.js";
87
+ import { repoRoot } from "../cli/git-scope.js";
88
+ /**
89
+ * How often the daemon advances, absent the record-count trigger: 15 minutes.
90
+ *
91
+ * Chosen against what a records pull request costs and what staleness costs. A
92
+ * shorter interval publishes a pull request whose diff is a handful of lines
93
+ * and burns a CI run for each; a longer one leaves the guards that read the
94
+ * committed log (the CI protected-path cross-check especially) looking at a log
95
+ * that is hours behind the decisions it is supposed to evidence.
96
+ */
97
+ export const DEFAULT_ADVANCE_INTERVAL_MS = 900_000;
98
+ /**
99
+ * How many unpublished records force an advance before the interval elapses: 20.
100
+ *
101
+ * The busy-hour case. Twenty records is a few minutes of an active session, and
102
+ * a records branch that far behind is a records branch a person starts doing
103
+ * arithmetic against.
104
+ */
105
+ export const DEFAULT_ADVANCE_AFTER_RECORDS = 20;
106
+ /** The default cadence, spelled once. */
107
+ export function defaultCadence() {
108
+ return {
109
+ intervalMs: DEFAULT_ADVANCE_INTERVAL_MS,
110
+ afterRecords: DEFAULT_ADVANCE_AFTER_RECORDS,
111
+ remote: "origin",
112
+ base: null,
113
+ pr: true,
114
+ autoMerge: true,
115
+ };
116
+ }
117
+ // ---------------------------------------------------------------------------
118
+ // One gated attempt
119
+ // ---------------------------------------------------------------------------
120
+ /** The argv the payload binds to: the verb this attempt is authorization for. */
121
+ export function advanceArgv(cadence) {
122
+ return [
123
+ "approval",
124
+ "log",
125
+ "advance",
126
+ ...(cadence.pr ? ["--pr"] : []),
127
+ // APRV-284. Present only when the arm is OFF, so the default cadence's argv
128
+ // is byte-identical to what it was before the arm existed and no payload
129
+ // hash or idempotency key moves under a running daemon.
130
+ ...(cadence.pr && !cadence.autoMerge ? ["--no-auto-merge"] : []),
131
+ "--remote",
132
+ cadence.remote,
133
+ ...(cadence.base === null ? [] : ["--base", cadence.base]),
134
+ ];
135
+ }
136
+ function detail(cause) {
137
+ return cause instanceof Error ? cause.message : String(cause);
138
+ }
139
+ /** Build an {@link AdvanceAttempt} with this attempt's fixed fields filled in. */
140
+ function answerFor(ts, recordsPending, recordsBranch) {
141
+ return (over) => ({
142
+ ts,
143
+ recordsPending,
144
+ recordsBranch,
145
+ commit: null,
146
+ prUrl: null,
147
+ prCreated: false,
148
+ autoMerge: null,
149
+ autoMergeNote: null,
150
+ range: null,
151
+ code: null,
152
+ rebuilt: false,
153
+ rebuiltOn: null,
154
+ pendingFinish: null,
155
+ ...over,
156
+ });
157
+ }
158
+ // ---------------------------------------------------------------------------
159
+ // The bounded head-moved retry on the outcome record (APRV-233)
160
+ // ---------------------------------------------------------------------------
161
+ /**
162
+ * Append the advance's outcome, re-deriving it against a fresh head on
163
+ * `head-moved` (APRV-233).
164
+ *
165
+ * ## What went wrong without it
166
+ *
167
+ * Observed 2026-09-02 on Carter's terminal: the advance pushed
168
+ * `records-log-2026-09-02`, and then `execution.completed could not be
169
+ * appended: head moved` — a harness hook's record landed between this module's
170
+ * read and its append, the compare-and-append refused the stale write exactly
171
+ * as SPEC.md §11.1 invariant 5 requires, and `daemon-log-advance-1-13984` was
172
+ * left open. Every other writer on this path has re-derived and re-attempted
173
+ * since APRV-150; this one did not, and the cost of losing the race was an
174
+ * execution the log said had never ended.
175
+ *
176
+ * ## What an attempt is
177
+ *
178
+ * The WHOLE operation, not a re-append: {@link finishExecution} re-reads the
179
+ * verified log, re-runs its `not-started` / `already-finished` /
180
+ * `execution-delegated` checks against that read, and appends with the head
181
+ * THAT read observed. Nothing crosses an attempt except the outcome the caller
182
+ * observed, which is a fact about the world rather than a conclusion about the
183
+ * log, so no stale derivation can authorize a write. A verdict that genuinely
184
+ * changed in the window (another writer closed the execution first) is the
185
+ * verdict returned, and the bound is returned unchanged once it is spent, so
186
+ * the caller still fails closed.
187
+ *
188
+ * ## One retry, in one place
189
+ *
190
+ * The loop and the bound are `core/head-retry.ts`'s (APRV-236 lifted them there
191
+ * for every gate writer, and APRV-233's first draft of this function was the
192
+ * local copy that helper replaced). `attemptsOf` clamps a caller's
193
+ * `retryOnHeadMoved` downward only, so the test harness can pin the unretried
194
+ * shape at `1` and nothing can raise the ceiling; `withHeadRetry` re-runs the
195
+ * whole `finishExecution` and adds the attempt count to the message it finally
196
+ * hands back. What remains here is only which operation is retried.
197
+ */
198
+ function finishWithHeadMovedRetry(logPath, actionKey, exitCode, options) {
199
+ return withHeadRetry(attemptsOf(options.retryOnHeadMoved), () => finishExecution(logPath, actionKey, exitCode, ADVANCE_ACTOR, options));
200
+ }
201
+ /**
202
+ * Close an execution whose outcome an EARLIER tick observed and could not
203
+ * record (APRV-233).
204
+ *
205
+ * The second half of the fix, and the one that matters after a restart of the
206
+ * loop rather than of the process: the outcome is carried in memory as a
207
+ * {@link PendingAdvanceFinish} and re-attempted here, on the fresh head,
208
+ * before the next tick evaluates any trigger. It appends the same record the
209
+ * failed attempt would have appended, through the same bounded retry.
210
+ *
211
+ * `already-finished` is a SUCCESS here: something (a concurrent settle, a
212
+ * human's `approval execution resolve`) closed the cycle in the meantime, the
213
+ * log holds an outcome, and there is nothing left to carry.
214
+ */
215
+ export function settleAdvanceFinish(input, pending) {
216
+ const result = finishWithHeadMovedRetry(input.logPath, pending.actionKey, pending.exitCode, {
217
+ policy: input.policy,
218
+ ...(input.schemaDir === undefined ? {} : { schemaDir: input.schemaDir }),
219
+ ...(input.clock === undefined ? {} : { clock: input.clock }),
220
+ ...(input.retryOnHeadMoved === undefined ? {} : { retryOnHeadMoved: input.retryOnHeadMoved }),
221
+ ...(input.afterFinishRead === undefined ? {} : { afterRead: input.afterFinishRead }),
222
+ ...(pending.reason === undefined ? {} : { reason: pending.reason }),
223
+ ...(pending.note === undefined ? {} : { note: pending.note }),
224
+ });
225
+ if (result.ok) {
226
+ return {
227
+ ok: true,
228
+ code: null,
229
+ message: `the outcome of ${pending.actionKey} is recorded (${result.event})`,
230
+ };
231
+ }
232
+ if (result.code === "already-finished") {
233
+ return {
234
+ ok: true,
235
+ code: null,
236
+ message: `${pending.actionKey} was already closed by another writer; nothing was appended`,
237
+ };
238
+ }
239
+ return {
240
+ ok: false,
241
+ code: result.code,
242
+ message: `the outcome of ${pending.actionKey} still could not be recorded: ${result.message}`,
243
+ };
244
+ }
245
+ /**
246
+ * Every open advance cycle, with what this checkout's refs prove (APRV-264).
247
+ *
248
+ * One `publishedState` for the whole list rather than one per key: it is the
249
+ * git read on the tick's hot path, and the answer it gives is the same for
250
+ * every key — the highest published seq, and the ref that carries it.
251
+ *
252
+ * Read from the log rather than from this process's memory, so a daemon that
253
+ * restarted still sees that an advance HAPPENED. It is the fact the cadence was
254
+ * missing on 2026-09-02: with no outcome record, nothing but an in-process
255
+ * clock said the branch had just been pushed.
256
+ */
257
+ export function proveDanglingAdvancesFor(input, records) {
258
+ const open = danglingAdvances(records);
259
+ if (open.length === 0)
260
+ return [];
261
+ const root = repoRoot(input.cwd) ?? input.cwd;
262
+ const today = input.today ?? tick(input.clock === undefined ? {} : { clock: input.clock });
263
+ const state = publishedState(root, input.logPath, records, input.cadence, today);
264
+ return proveDanglingAdvances(records, state);
265
+ }
266
+ /** Is this sweep's work done — nothing open, nothing owed to a person? */
267
+ export function sweepIsClear(sweep) {
268
+ return sweep.settled.length === 0 && sweep.outstanding.length === 0;
269
+ }
270
+ /**
271
+ * Close EVERY dangling advance cycle whose outcome the git refs still show
272
+ * (APRV-233, widened by APRV-264).
273
+ *
274
+ * ## The loop this breaks
275
+ *
276
+ * From Carter's terminal, 2026-09-02, with the APRV-211 build running: tick two
277
+ * advanced and pushed; its `execution.completed` lost the head race (expected
278
+ * 14874, found 14875) and `daemon-log-advance-1-14871` was left open. Tick
279
+ * three's authorization then reached `startExecution` on that same key and was
280
+ * refused `already-executed: an idempotency key is single-use and nothing here
281
+ * reconciles or reruns it` — which is the gate saying, correctly, that
282
+ * somebody has to close the books. Nobody did, so the span moved and the daemon
283
+ * pushed again, and again, every ninety seconds under a fifteen-minute
284
+ * interval.
285
+ *
286
+ * ## Why it sweeps rather than reconciles one
287
+ *
288
+ * APRV-233's version closed the LAST open cycle and returned. On 2026-09-05
289
+ * that was not enough: `approval status` listed FIVE, left by the 2026-09-02
290
+ * loop and by the restarts after it, the daemon refused one advance per tick
291
+ * naming one key each, and Carter closed all five by hand with five
292
+ * near-identical commands. One key per tick is a repair rate of one every
293
+ * thirty seconds behind a refusal that stops the cadence entirely, so the sweep
294
+ * takes every key it can prove in one pass and reports the rest together.
295
+ *
296
+ * ## What is and is not a guess here
297
+ *
298
+ * {@link settleAdvanceFinish} covers the case this process still holds the
299
+ * outcome for. This covers the other one — cycles left open by an earlier
300
+ * process, or by ticks whose memory of them is gone — and it closes each only
301
+ * on EVIDENCE: the records the cycle was authorized to publish are demonstrably
302
+ * on a records branch, read from git's own object store through the same
303
+ * `publishedState` the cadence and the doctor row read. When the evidence is
304
+ * there the outcome is recorded as the completion it was, with a note saying
305
+ * which ref proved it and that the RUNTIME observed it. When it is NOT there,
306
+ * nothing is written: the execution stays open for a person, the daemon warns
307
+ * once, and no new advance is started over work nobody has accounted for. A
308
+ * false `execution.failed` for an advance that actually published would be
309
+ * worse than the dangling record.
310
+ *
311
+ * The actor is {@link ADVANCE_ACTOR} and the record carries no
312
+ * `attested_by_human`: human attestation is for what a person went and looked
313
+ * at, and this is the runtime reading its own refs. The note says so in as many
314
+ * words, so no reader has to infer it from the actor field alone.
315
+ *
316
+ * This is a deliberate, narrow carve-out to `core/execute.ts`'s rule that
317
+ * nothing closes a dangling execution automatically. Narrow because it closes
318
+ * only executions THIS runtime started, for its own `log.advance` cycles, whose
319
+ * entire effect is a git ref this runtime can look at and did.
320
+ */
321
+ export function sweepDanglingAdvances(input, records) {
322
+ const sweep = { settled: [], outstanding: [] };
323
+ // One git read for the whole sweep. Appending an outcome below cannot change
324
+ // the answer: `publishedState` counts only a committed copy that is a PREFIX
325
+ // of the working log, so a record appended after it was read leaves both the
326
+ // published seq and the ref that carries it exactly where they were.
327
+ for (const entry of proveDanglingAdvancesFor(input, records)) {
328
+ if (entry.provenBy === null) {
329
+ sweep.outstanding.push({
330
+ actionKey: entry.actionKey,
331
+ provenBy: null,
332
+ message: `${entry.actionKey} is an advance execution nobody closed, and no ref in this checkout carries seq ${entry.toSeq === null ? "the span it named" : String(entry.toSeq)}. Nothing is recorded for it: an outcome this runtime cannot observe is a human's to establish.`,
333
+ });
334
+ continue;
335
+ }
336
+ const finished = finishWithHeadMovedRetry(input.logPath, entry.actionKey, 0, {
337
+ policy: input.policy,
338
+ ...(input.schemaDir === undefined ? {} : { schemaDir: input.schemaDir }),
339
+ ...(input.clock === undefined ? {} : { clock: input.clock }),
340
+ ...(input.retryOnHeadMoved === undefined ? {} : { retryOnHeadMoved: input.retryOnHeadMoved }),
341
+ ...(input.afterFinishRead === undefined ? {} : { afterRead: input.afterFinishRead }),
342
+ note: {
343
+ code: "advance-reconciled",
344
+ message: `the outcome record was lost when this cycle ran; ${entry.provenBy} carries seq ${String(entry.toSeq)} in this checkout, so the advance completed. Observed by the runtime (${ADVANCE_ACTOR}) from that ref, not attested by a human`,
345
+ },
346
+ });
347
+ if (finished.ok) {
348
+ sweep.settled.push({
349
+ actionKey: entry.actionKey,
350
+ provenBy: entry.provenBy,
351
+ message: `${entry.actionKey} was left open by an earlier advance; ${entry.provenBy} carries seq ${String(entry.toSeq)}, so its completion is now recorded`,
352
+ });
353
+ continue;
354
+ }
355
+ // `already-finished` is somebody else closing the books between the read
356
+ // and the append, which is the outcome this wanted and not a failure.
357
+ if (finished.code === "already-finished") {
358
+ sweep.settled.push({
359
+ actionKey: entry.actionKey,
360
+ provenBy: entry.provenBy,
361
+ message: `${entry.actionKey} was closed by another writer before this sweep reached it; nothing was appended`,
362
+ });
363
+ continue;
364
+ }
365
+ sweep.outstanding.push({
366
+ actionKey: entry.actionKey,
367
+ provenBy: entry.provenBy,
368
+ message: `${entry.actionKey} could not be closed: ${finished.message}`,
369
+ });
370
+ }
371
+ return sweep;
372
+ }
373
+ /**
374
+ * The refusal that stands while any advance cycle is open, naming all of them.
375
+ *
376
+ * One sentence for every outstanding key rather than one refusal per key per
377
+ * tick: the operator's next act is the same command whichever key they read
378
+ * first, so the command is on the line and every key it will close is under it.
379
+ */
380
+ export function unreconciledRefusal(keys) {
381
+ return `${String(keys.length)} advance execution(s) were started and their outcomes were never recorded; nothing new is authorized until they are closed (${keys.join(", ")}). \`approval status\` shows them; \`${RESOLVE_DANGLING_COMMAND}\` closes every one this checkout can prove and lists the rest.`;
382
+ }
383
+ /**
384
+ * Register, request, start. The authorization, and not one byte of side effect.
385
+ *
386
+ * The order is the whole point and none of it is optional: nothing is committed
387
+ * before the gate has answered, and nothing the gate answered for goes
388
+ * unrecorded. `execution.started` is appended BEFORE the advance runs, so the
389
+ * commit the advance builds carries the record of its own authorization; the
390
+ * `execution.completed` that follows lands after the commit and is published by
391
+ * the next advance, which is why the trigger discounts it.
392
+ *
393
+ * ## What APRV-211 changed: the tick asks the log what it already asked
394
+ *
395
+ * Observed live on 2026-09-02: three ticks over ONE owed advance put three
396
+ * questions on Carter's phone, because the idempotency key embedded the log
397
+ * HEAD and the head moved with each gated attempt's own two records. Two things
398
+ * fix it and both are here.
399
+ *
400
+ * 1. The key and the payload span end at `substantiveSeq` — the last unpublished
401
+ * record that is not an advance cycle's own bookkeeping — so a tick that
402
+ * appended only its own question computes the SAME key and the SAME hash.
403
+ * 2. Before it registers anything, the tick reads {@link openAdvanceRequest}.
404
+ * A question still open is ADOPTED (nothing is appended, the outcome is
405
+ * `gated`, and the human keeps the one question they already have); a grant
406
+ * on it is SPENT (straight to `startExecution` on that key, with the hash
407
+ * that key declared, so the single-use rule the log already enforces makes
408
+ * one decision authorise exactly one advance); a terminal answer on the
409
+ * CURRENT owed span is HONOURED (`advance-decided`, and nothing is asked
410
+ * again until the span itself changes).
411
+ */
412
+ export function authorizeAdvance(input, records) {
413
+ const ts = tick(input.clock === undefined ? {} : { clock: input.clock });
414
+ const today = input.today ?? ts;
415
+ const root = repoRoot(input.cwd) ?? input.cwd;
416
+ const recordsBranch = defaultRecordsBranch(today);
417
+ const state = publishedState(root, input.logPath, records, input.cadence, today);
418
+ const answer = answerFor(ts, state.pending, recordsBranch);
419
+ const no = (over) => ({ authorized: false, attempt: answer(over) });
420
+ if (state.pending === 0) {
421
+ return no({
422
+ outcome: "nothing-owed",
423
+ message: `every record through seq ${String(state.publishedSeq)} is already on a records branch`,
424
+ });
425
+ }
426
+ // APRV-233. An advance cycle nobody closed the books on. Reaching
427
+ // `startExecution` from here produced the bare `already-executed` Carter saw
428
+ // on 2026-09-02 — the gate saying, correctly, that an idempotency key is
429
+ // single-use and nothing there reconciles or reruns it — after which the span
430
+ // moved and the branch was pushed all over again. The sweep belongs to
431
+ // {@link sweepDanglingAdvances}, which the caller runs first; whatever is
432
+ // still here is still a human's, and nothing is authorized over it.
433
+ //
434
+ // APRV-264: EVERY outstanding key, and the one command that clears them. The
435
+ // refusal used to name the last one only, so an operator holding five of them
436
+ // learned about the second after they had closed the first.
437
+ const unreconciled = danglingAdvances(records).map((entry) => entry.actionKey);
438
+ if (unreconciled.length > 0) {
439
+ return no({
440
+ outcome: "refused",
441
+ code: "advance-unreconciled",
442
+ message: unreconciledRefusal(unreconciled),
443
+ });
444
+ }
445
+ const gate = { policy: input.policy };
446
+ if (input.schemaDir !== undefined)
447
+ gate.schemaDir = input.schemaDir;
448
+ if (input.clock !== undefined)
449
+ gate.clock = input.clock;
450
+ const task = advanceTaskId(state.substantiveSeq);
451
+ const actionKey = advanceActionKey(state.publishedSeq + 1, state.substantiveSeq);
452
+ // The bytes this authorization binds to: the command, where it runs, and the
453
+ // seq span it publishes. The span is IN the hash deliberately (APRV-204). A
454
+ // payload identical across cycles would give the `supervised-live` draw the
455
+ // same verdict forever — a selected advance would stay selected on every
456
+ // later tick and the cadence would stop for good — and a span is not a
457
+ // re-roll: different records are a different action, which is exactly what
458
+ // §5.2's no-re-roll property means by "changing the bytes is a different
459
+ // request".
460
+ //
461
+ // It ends at the OWED span's end rather than at the head (APRV-211). The
462
+ // advance publishes whatever the log holds when it runs, which is this span
463
+ // plus this cycle's own two or three bookkeeping records; naming the owed
464
+ // span is what makes one owed advance one question, and the bookkeeping is
465
+ // not work anybody is being asked to approve.
466
+ const hash = payloadHash({
467
+ argv: advanceArgv(input.cadence),
468
+ cwd: root,
469
+ seq: { from: state.publishedSeq + 1, to: state.substantiveSeq },
470
+ });
471
+ // What this daemon already asked, and what became of it. Read from the
472
+ // verified records the caller handed in — the enforcement path never reads an
473
+ // unverified log (SPEC.md §11.1) — and aged against the policy's own TTL, so a
474
+ // question whose window lapsed stops being adopted whether or not the
475
+ // `approval.expired` record has been materialised yet.
476
+ const loaded = loadPolicy({
477
+ ...(input.policy.file === undefined ? {} : { file: input.policy.file }),
478
+ ...(input.policy.dir === undefined ? {} : { dir: input.policy.dir }),
479
+ ...(input.schemaDir === undefined ? {} : { schemaDir: input.schemaDir }),
480
+ });
481
+ const open = openAdvanceRequest(records, ts, loaded.ok ? loaded.durations.approvalTtlMs : null);
482
+ const adopted = open !== null && open.actionKey === actionKey;
483
+ if (open !== null && open.state === "requested") {
484
+ // Whatever the span has done since, a question is standing. Asking a second
485
+ // one would multiply the taps this cadence exists to remove, and answering
486
+ // the standing one authorises the advance the moment the next tick runs.
487
+ return no({
488
+ outcome: "gated",
489
+ code: "advance-open",
490
+ message: `an advance question is already open as ${open.actionKey} and nobody has answered it; nothing was asked again and nothing was committed. Answering it authorises the next tick's advance.`,
491
+ });
492
+ }
493
+ if (adopted && open !== null && open.state !== "granted") {
494
+ return no({
495
+ outcome: "refused",
496
+ code: "advance-decided",
497
+ message: `the advance of seq ${String(state.publishedSeq + 1)}..${String(state.substantiveSeq)} was already answered (${open.state} as ${open.actionKey}); nothing is asked again until the owed span changes.`,
498
+ });
499
+ }
500
+ if (adopted && open !== null && open.state === "granted" && open.spent) {
501
+ // The grant was consumed — by the advance that failed, or by one whose
502
+ // `execution.completed` has not been published yet. Either way the
503
+ // authorisation is gone, and a fresh question about an unchanged span is a
504
+ // retry loop with a human in it. The reason the last one failed is on the
505
+ // `execution.failed` and on the doctor row.
506
+ return no({
507
+ outcome: "refused",
508
+ code: "advance-spent",
509
+ message: `the decision on ${open.actionKey} has already been spent on an execution; this owed span will not be asked again until it changes.`,
510
+ });
511
+ }
512
+ // The grant this tick is riding was earned by an earlier tick's question, so
513
+ // there is nothing to declare and nothing to ask: the declaration and the
514
+ // question are in the log already, and re-asking is the defect. Straight to
515
+ // the execution, bound to the hash THAT request declared.
516
+ const declaredHash = adopted && open !== null && open.payloadHash !== null ? open.payloadHash : hash;
517
+ if (!adopted) {
518
+ const registered = register(input.logPath, {
519
+ task,
520
+ envelope: {
521
+ origin: { app: "approval-daemon", created_by: ADVANCE_ACTOR },
522
+ state: "proposed",
523
+ actions: [
524
+ {
525
+ class: ADVANCE_CLASS,
526
+ idempotency_key: actionKey,
527
+ summary: `log advance: seq ${String(state.publishedSeq + 1)}..${String(state.substantiveSeq)} onto ${recordsBranch}`,
528
+ reversible: true,
529
+ est_cost_usd: "0",
530
+ payload_hash: hash,
531
+ },
532
+ ],
533
+ },
534
+ }, ADVANCE_ACTOR, gate);
535
+ // A re-attempt at an unchanged span finds its own registration already in
536
+ // the log. That is the retry working, not a failure: the cycle continues and
537
+ // the request below adopts the declaration this one already wrote.
538
+ if (!registered.ok && registered.code !== "task-already-registered") {
539
+ return no({ outcome: "refused", code: registered.code, message: registered.message });
540
+ }
541
+ const asked = request(input.logPath, {
542
+ task,
543
+ actionKey,
544
+ cls: ADVANCE_CLASS,
545
+ reversible: true,
546
+ est_cost_usd: "0",
547
+ summary: `log advance: seq ${String(state.publishedSeq + 1)}..${String(state.substantiveSeq)}`,
548
+ payload_hash: hash,
549
+ payload: { value: { argv: advanceArgv(input.cadence), cwd: root, seq: { from: state.publishedSeq + 1, to: state.substantiveSeq } } },
550
+ // APRV-211. The requester is this process, and it will open the grant
551
+ // itself through the sealed address this request publishes. No granting
552
+ // surface is handed a raw token, so no granting surface can print one on
553
+ // a terminal for an action nobody at that terminal is going to run.
554
+ delivery: "self",
555
+ }, ADVANCE_ACTOR, gate);
556
+ if (!asked.ok) {
557
+ return no({ outcome: "refused", code: asked.code, message: asked.message });
558
+ }
559
+ if (!asked.proceed) {
560
+ return no({
561
+ outcome: "gated",
562
+ code: asked.live?.reason ?? "manual",
563
+ message: `the gate sent this advance to a human (${asked.live === undefined
564
+ ? `class ${ADVANCE_CLASS} resolves ${asked.autonomy}`
565
+ : `supervised-live draw: ${asked.live.reason} at rate ${String(asked.live.rate)}`}); nothing was committed. The question is in the queue as ${actionKey}, and the next tick adopts it rather than asking again.`,
566
+ });
567
+ }
568
+ }
569
+ const started = startExecution(input.logPath, actionKey, {
570
+ policy: input.policy,
571
+ presentedPayloadHash: declaredHash,
572
+ ...(input.schemaDir === undefined ? {} : { schemaDir: input.schemaDir }),
573
+ ...(input.clock === undefined ? {} : { clock: input.clock }),
574
+ }, ADVANCE_ACTOR);
575
+ if (!started.ok) {
576
+ return no({ outcome: "refused", code: started.code, message: started.message });
577
+ }
578
+ return {
579
+ authorized: true,
580
+ ts,
581
+ today,
582
+ root,
583
+ recordsBranch,
584
+ actionKey,
585
+ recordsPending: state.pending,
586
+ adopted,
587
+ };
588
+ }
589
+ /** Run the verb here, on this stack. The shutdown flush's path. */
590
+ function runVerbHere(input, auth) {
591
+ try {
592
+ return logAdvance({
593
+ cwd: auth.root,
594
+ remote: input.cadence.remote,
595
+ base: input.cadence.base,
596
+ pr: input.cadence.pr,
597
+ autoMerge: input.cadence.autoMerge,
598
+ branch: auth.recordsBranch,
599
+ today: auth.today,
600
+ });
601
+ }
602
+ catch (cause) {
603
+ return { ok: false, code: "log-advance-git-failed", message: `the advance threw: ${detail(cause)}` };
604
+ }
605
+ }
606
+ /**
607
+ * Close the execution and report. The gate work, always in this process.
608
+ *
609
+ * A finish that is itself refused (an external writer moved the head between
610
+ * the advance and this append) leaves a dangling execution, which is the honest
611
+ * state and which nothing here auto-repairs: `approval status` surfaces it and
612
+ * a human resolves it. It is named in the reported message rather than
613
+ * swallowed.
614
+ *
615
+ * The verb's own refusal code and message travel onto `execution.failed`
616
+ * (APRV-211). Exit 1 with no reason was the reported half of the 2026-09-02
617
+ * incident: the daemon knew why the push failed and the log did not.
618
+ */
619
+ function recordFinish(input, auth, advanced) {
620
+ const answer = answerFor(auth.ts, auth.recordsPending, auth.recordsBranch);
621
+ const exitCode = advanced.ok ? 0 : 1;
622
+ const reason = advanced.ok ? undefined : { code: advanced.code, message: advanced.message };
623
+ // APRV-234. A rebuilt branch is worth explaining even when the advance
624
+ // succeeded: an operator reading the doctor row a day later needs to know
625
+ // that today's records branch was re-parented on the trunk rather than
626
+ // stacked, and on which commit. A REPORT, never an authorization — nothing in
627
+ // the gate reads it back.
628
+ const note = advanced.ok && advanced.report.rebuilt === true
629
+ ? {
630
+ code: "advance-rebuilt",
631
+ message: `the day's records branch was rebuilt on ${advanced.report.rebuiltOn?.ref ?? "the base"} ${(advanced.report.rebuiltOn?.sha ?? "").slice(0, 12)}${advanced.report.recordsBranch === auth.recordsBranch
632
+ ? ""
633
+ : ` and opened as ${advanced.report.recordsBranch}`}`,
634
+ }
635
+ : undefined;
636
+ // APRV-233. Bounded, and each attempt a whole operation against a fresh head.
637
+ const finished = finishWithHeadMovedRetry(input.logPath, auth.actionKey, exitCode, {
638
+ policy: input.policy,
639
+ ...(input.schemaDir === undefined ? {} : { schemaDir: input.schemaDir }),
640
+ ...(input.clock === undefined ? {} : { clock: input.clock }),
641
+ ...(input.retryOnHeadMoved === undefined ? {} : { retryOnHeadMoved: input.retryOnHeadMoved }),
642
+ ...(input.afterFinishRead === undefined ? {} : { afterRead: input.afterFinishRead }),
643
+ ...(reason === undefined ? {} : { reason }),
644
+ ...(note === undefined ? {} : { note }),
645
+ });
646
+ // The bound is spent and the execution is open. The effect HAPPENED and this
647
+ // process knows how it ended, so the outcome is carried to the next tick
648
+ // rather than lost; until it is recorded the cadence treats this advance as
649
+ // still in hand and starts no other.
650
+ const pendingFinish = finished.ok
651
+ ? null
652
+ : {
653
+ actionKey: auth.actionKey,
654
+ exitCode,
655
+ ...(reason === undefined ? {} : { reason }),
656
+ ...(note === undefined ? {} : { note }),
657
+ };
658
+ const dangling = finished.ok
659
+ ? ""
660
+ : ` (the execution outcome could not be recorded: ${finished.message}; ${auth.actionKey} is left open and the next tick settles it before it advances anything)`;
661
+ if (!advanced.ok) {
662
+ return answer({
663
+ outcome: "failed",
664
+ code: advanced.code,
665
+ message: `${advanced.message}${dangling}`,
666
+ pendingFinish,
667
+ });
668
+ }
669
+ const report = advanced.report;
670
+ return answer({
671
+ outcome: report.commit === null ? "nothing-owed" : "advanced",
672
+ commit: report.commit,
673
+ prUrl: report.prUrl,
674
+ prCreated: report.prCreated ?? false,
675
+ autoMerge: report.autoMerge ?? null,
676
+ autoMergeNote: report.autoMergeNote ?? null,
677
+ range: report.range,
678
+ recordsBranch: report.recordsBranch,
679
+ rebuilt: report.rebuilt === true,
680
+ rebuiltOn: report.rebuiltOn === undefined ? null : report.rebuiltOn.ref,
681
+ pendingFinish,
682
+ message: report.commit === null
683
+ ? "the records branch already carried these bytes; nothing was committed"
684
+ : `seq ${String(report.range?.from ?? 0)}..${String(report.range?.to ?? 0)} is on ${report.recordsBranch}${report.rebuilt === true
685
+ ? ` (rebuilt on ${report.rebuiltOn?.ref ?? "the base"} ${(report.rebuiltOn?.sha ?? "").slice(0, 12)})`
686
+ : ""}${report.prUrl === null ? "" : ` (${report.prUrl})`}${armNote(report)}${dangling}`,
687
+ });
688
+ }
689
+ /**
690
+ * What the attempt's message says about the arm (APRV-284).
691
+ *
692
+ * Every outcome but `armed` names its reason: a pull request nobody armed is
693
+ * one a person still has to land, and an operator reading this line is the one
694
+ * who has to know that from the line rather than from the pull request.
695
+ */
696
+ function armNote(report) {
697
+ switch (report.autoMerge ?? null) {
698
+ case null:
699
+ return "";
700
+ case "armed":
701
+ return ", auto-merge armed";
702
+ case "off":
703
+ return ", auto-merge not armed (--no-advance-auto-merge)";
704
+ case "withheld":
705
+ return `, auto-merge WITHHELD: ${report.autoMergeNote ?? "the branch carries more than an advance may"}`;
706
+ default:
707
+ return `, auto-merge refused by gh: ${report.autoMergeNote ?? "no reason given"}`;
708
+ }
709
+ }
710
+ /**
711
+ * The advance, on this stack, start to finish. The shutdown flush's path.
712
+ *
713
+ * Kept synchronous deliberately: `finish()` runs inside the daemon's shutdown,
714
+ * where there is no loop left to return to and an advance that settled after
715
+ * the process exited would be an advance nobody recorded.
716
+ */
717
+ export function runAdvanceSync(input, auth) {
718
+ return recordFinish(input, auth, runVerbHere(input, auth));
719
+ }
720
+ /**
721
+ * The advance, with the git work in a child, so this loop keeps answering.
722
+ *
723
+ * ## Why a child rather than an `await`
724
+ *
725
+ * The second half of the 2026-09-02 incident: `answerCallbackQuery: HTTP 400`,
726
+ * over and over, around the grants. Telegram drops a callback query that is not
727
+ * answered inside its window, and `approval up` runs the channel listener and
728
+ * the daemon in ONE process on ONE loop. `logAdvance` is `spawnSync` from end to
729
+ * end — `git fetch`, a scratch-index commit, `git push`, `gh pr create` — so
730
+ * every tap that arrived during an advance waited for the push to finish, and
731
+ * the human got a button that never toasted. A promise would not have helped:
732
+ * synchronous work does not yield no matter what it is wrapped in. Only another
733
+ * process does.
734
+ *
735
+ * ## What does NOT move
736
+ *
737
+ * The gate work. `core/child-env.ts` strips `APPROVAL_*` from a child's
738
+ * environment (APRV-205), and the `supervised-live` draw's secret is exactly
739
+ * such a variable, so a child that asked the gate would be a child that could
740
+ * not draw and would fail closed on every tick. Authorization happens in
741
+ * {@link authorizeAdvance}, in this process, before the child is spawned;
742
+ * {@link recordFinish} closes the execution in this process, after it settles.
743
+ * The child gets one job — the git side effect — and no authority whatsoever.
744
+ * It never touches the log: it cannot append, and everything it says comes back
745
+ * as one JSON line on its stdout.
746
+ */
747
+ export function runAdvanceAsync(input, auth) {
748
+ return new Promise((resolve) => {
749
+ const spec = input.runner ?? {
750
+ command: process.execPath,
751
+ args: [fileURLToPath(new URL("./advance-child.js", import.meta.url))],
752
+ };
753
+ const request_ = JSON.stringify({
754
+ cwd: auth.root,
755
+ remote: input.cadence.remote,
756
+ base: input.cadence.base,
757
+ pr: input.cadence.pr,
758
+ autoMerge: input.cadence.autoMerge,
759
+ branch: auth.recordsBranch,
760
+ today: auth.today,
761
+ });
762
+ let child;
763
+ try {
764
+ child = spawn(spec.command, [...spec.args, request_], {
765
+ cwd: auth.root,
766
+ env: childEnvironment().env,
767
+ stdio: ["ignore", "pipe", "pipe"],
768
+ });
769
+ }
770
+ catch (cause) {
771
+ resolve(recordFinish(input, auth, {
772
+ ok: false,
773
+ code: "log-advance-child-unspawnable",
774
+ message: `the advance child could not be started: ${detail(cause)}`,
775
+ }));
776
+ return;
777
+ }
778
+ let out = "";
779
+ let err = "";
780
+ child.stdout.setEncoding("utf8");
781
+ child.stderr.setEncoding("utf8");
782
+ child.stdout.on("data", (chunk) => (out += chunk));
783
+ child.stderr.on("data", (chunk) => (err += chunk));
784
+ const settle = (run) => {
785
+ resolve(recordFinish(input, auth, run));
786
+ };
787
+ child.on("error", (cause) => {
788
+ settle({
789
+ ok: false,
790
+ code: "log-advance-child-unspawnable",
791
+ message: `the advance child could not be started: ${detail(cause)}`,
792
+ });
793
+ });
794
+ child.on("close", (code) => {
795
+ const parsed = parseChildReport(out);
796
+ if (parsed !== null) {
797
+ settle(parsed);
798
+ return;
799
+ }
800
+ settle({
801
+ ok: false,
802
+ code: "log-advance-child-unreadable",
803
+ message: `the advance child exited ${String(code)} and said nothing this runtime could read${err.trim() === "" ? "" : `: ${err.trim().slice(0, 400)}`}`,
804
+ });
805
+ });
806
+ });
807
+ }
808
+ /**
809
+ * The child's one line, or `null` when it is not the shape this expects.
810
+ *
811
+ * Validated rather than cast: the child is another process, its stdout is
812
+ * input, and a report this runtime cannot recognise is a failed advance with a
813
+ * machine-readable reason — never a success taken on faith.
814
+ */
815
+ function parseChildReport(text) {
816
+ const line = text.trim().split("\n").pop();
817
+ if (line === undefined || line === "")
818
+ return null;
819
+ let value;
820
+ try {
821
+ value = JSON.parse(line);
822
+ }
823
+ catch {
824
+ return null;
825
+ }
826
+ if (typeof value !== "object" || value === null)
827
+ return null;
828
+ const shape = value;
829
+ if (shape["ok"] === true && typeof shape["report"] === "object" && shape["report"] !== null) {
830
+ return { ok: true, report: shape["report"] };
831
+ }
832
+ if (shape["ok"] === false && typeof shape["code"] === "string" && typeof shape["message"] === "string") {
833
+ return { ok: false, code: shape["code"], message: shape["message"] };
834
+ }
835
+ return null;
836
+ }
837
+ /**
838
+ * Register, request, start, advance, finish. One attempt, on this stack.
839
+ *
840
+ * The whole cycle for a caller that has no loop to protect: the shutdown flush,
841
+ * `--once`, and every test that asserts on what one tick did.
842
+ */
843
+ export function attemptAdvance(input, records) {
844
+ const auth = authorizeAdvance(input, records);
845
+ if (!auth.authorized)
846
+ return auth.attempt;
847
+ return runAdvanceSync(input, auth);
848
+ }
849
+ //# sourceMappingURL=advance.js.map