approval-md 0.1.0 → 0.3.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 (416) hide show
  1. package/README.md +629 -559
  2. package/SPEC.md +99 -24
  3. package/dist/src/adapters/agentmail.d.ts +426 -0
  4. package/dist/src/adapters/agentmail.js +2 -2
  5. package/dist/src/adapters/conformance.d.ts +149 -0
  6. package/dist/src/adapters/contract.d.ts +628 -0
  7. package/dist/src/adapters/contract.js +110 -16
  8. package/dist/src/adapters/contract.js.map +1 -1
  9. package/dist/src/adapters/email.d.ts +324 -0
  10. package/dist/src/adapters/env-passphrase.d.ts +93 -0
  11. package/dist/src/adapters/public.d.ts +11 -0
  12. package/dist/src/adapters/public.js +11 -0
  13. package/dist/src/adapters/public.js.map +1 -0
  14. package/dist/src/adapters/registry.d.ts +59 -0
  15. package/dist/src/adapters/registry.js +2 -1
  16. package/dist/src/adapters/registry.js.map +1 -1
  17. package/dist/src/adapters/smtp.d.ts +213 -0
  18. package/dist/src/adapters/vault-provider.d.ts +114 -0
  19. package/dist/src/adapters/vault-provider.js +3 -3
  20. package/dist/src/adapters/zzz.d.ts +66 -0
  21. package/dist/src/adapters/zzz.js +299 -0
  22. package/dist/src/adapters/zzz.js.map +1 -0
  23. package/dist/src/channels/batch.d.ts +109 -0
  24. package/dist/src/channels/cli.d.ts +193 -0
  25. package/dist/src/channels/conformance.d.ts +92 -0
  26. package/dist/src/channels/contract.d.ts +656 -0
  27. package/dist/src/channels/contract.js +200 -7
  28. package/dist/src/channels/contract.js.map +1 -1
  29. package/dist/src/channels/payload-view.d.ts +35 -0
  30. package/dist/src/channels/render-queue.d.ts +149 -0
  31. package/dist/src/channels/tagging.d.ts +196 -0
  32. package/dist/src/channels/telegram.d.ts +1944 -0
  33. package/dist/src/channels/telegram.js +218 -23
  34. package/dist/src/channels/telegram.js.map +1 -1
  35. package/dist/src/channels/web.d.ts +350 -0
  36. package/dist/src/channels/web.js +17 -0
  37. package/dist/src/channels/web.js.map +1 -1
  38. package/dist/src/cli/adapter.d.ts +90 -0
  39. package/dist/src/cli/adapter.js +25 -15
  40. package/dist/src/cli/adapter.js.map +1 -1
  41. package/dist/src/cli/amend.d.ts +59 -0
  42. package/dist/src/cli/amend.js +214 -30
  43. package/dist/src/cli/amend.js.map +1 -1
  44. package/dist/src/cli/args.d.ts +43 -0
  45. package/dist/src/cli/attest.d.ts +50 -0
  46. package/dist/src/cli/attest.js +134 -7
  47. package/dist/src/cli/attest.js.map +1 -1
  48. package/dist/src/cli/audit-card.d.ts +62 -0
  49. package/dist/src/cli/audit.d.ts +59 -0
  50. package/dist/src/cli/channel-telegram.d.ts +879 -0
  51. package/dist/src/cli/channel-telegram.js +311 -13
  52. package/dist/src/cli/channel-telegram.js.map +1 -1
  53. package/dist/src/cli/channel-web.d.ts +131 -0
  54. package/dist/src/cli/channel.d.ts +80 -0
  55. package/dist/src/cli/channel.js +9 -0
  56. package/dist/src/cli/channel.js.map +1 -1
  57. package/dist/src/cli/checkpoint-tap.d.ts +169 -0
  58. package/dist/src/cli/codex-bridge.d.ts +819 -0
  59. package/dist/src/cli/codex-bridge.js +1607 -0
  60. package/dist/src/cli/codex-bridge.js.map +1 -0
  61. package/dist/src/cli/codex.d.ts +2 -0
  62. package/dist/src/cli/codex.js +469 -0
  63. package/dist/src/cli/codex.js.map +1 -0
  64. package/dist/src/cli/coverage.d.ts +61 -0
  65. package/dist/src/cli/daemon.d.ts +120 -0
  66. package/dist/src/cli/daemon.js +4 -1
  67. package/dist/src/cli/daemon.js.map +1 -1
  68. package/dist/src/cli/doctor.d.ts +129 -0
  69. package/dist/src/cli/doctor.js +586 -17
  70. package/dist/src/cli/doctor.js.map +1 -1
  71. package/dist/src/cli/env.d.ts +65 -0
  72. package/dist/src/cli/execute.d.ts +202 -0
  73. package/dist/src/cli/execute.js +25 -2
  74. package/dist/src/cli/execute.js.map +1 -1
  75. package/dist/src/cli/exit-codes.d.ts +73 -0
  76. package/dist/src/cli/feedback.d.ts +60 -0
  77. package/dist/src/cli/gate-window.d.ts +40 -0
  78. package/dist/src/cli/gate.d.ts +68 -0
  79. package/dist/src/cli/git-scope.d.ts +190 -0
  80. package/dist/src/cli/gloss-attach.d.ts +85 -0
  81. package/dist/src/cli/gloss-codex-child.d.ts +9 -0
  82. package/dist/src/cli/gloss-codex.d.ts +24 -0
  83. package/dist/src/cli/gloss-options.d.ts +42 -0
  84. package/dist/src/cli/gloss.d.ts +265 -0
  85. package/dist/src/cli/help.d.ts +107 -0
  86. package/dist/src/cli/help.js +320 -93
  87. package/dist/src/cli/help.js.map +1 -1
  88. package/dist/src/cli/hook-codex.d.ts +126 -0
  89. package/dist/src/cli/hook-codex.js +226 -0
  90. package/dist/src/cli/hook-codex.js.map +1 -0
  91. package/dist/src/cli/hook.d.ts +787 -0
  92. package/dist/src/cli/hook.js +1235 -181
  93. package/dist/src/cli/hook.js.map +1 -1
  94. package/dist/src/cli/import.d.ts +35 -0
  95. package/dist/src/cli/import.js +1 -1
  96. package/dist/src/cli/import.js.map +1 -1
  97. package/dist/src/cli/init.d.ts +84 -0
  98. package/dist/src/cli/init.js +2 -2
  99. package/dist/src/cli/init.js.map +1 -1
  100. package/dist/src/cli/instructions.d.ts +23 -0
  101. package/dist/src/cli/journal.d.ts +41 -0
  102. package/dist/src/cli/log-advance.d.ts +287 -0
  103. package/dist/src/cli/log-advance.js +102 -11
  104. package/dist/src/cli/log-advance.js.map +1 -1
  105. package/dist/src/cli/log-anchor.d.ts +176 -0
  106. package/dist/src/cli/log-checkpoint.d.ts +22 -0
  107. package/dist/src/cli/log-sync.d.ts +243 -0
  108. package/dist/src/cli/log-verbs.d.ts +16 -0
  109. package/dist/src/cli/log-verbs.js +7 -1
  110. package/dist/src/cli/log-verbs.js.map +1 -1
  111. package/dist/src/cli/long-help.d.ts +70 -0
  112. package/dist/src/cli/main.d.ts +77 -0
  113. package/dist/src/cli/main.js +159 -7
  114. package/dist/src/cli/main.js.map +1 -1
  115. package/dist/src/cli/mcp.d.ts +52 -0
  116. package/dist/src/cli/paths.d.ts +56 -0
  117. package/dist/src/cli/payload.d.ts +58 -0
  118. package/dist/src/cli/policy-apply.d.ts +195 -0
  119. package/dist/src/cli/policy-apply.js +573 -0
  120. package/dist/src/cli/policy-apply.js.map +1 -0
  121. package/dist/src/cli/policy.d.ts +43 -0
  122. package/dist/src/cli/policy.js +14 -1
  123. package/dist/src/cli/policy.js.map +1 -1
  124. package/dist/src/cli/preflight.d.ts +501 -0
  125. package/dist/src/cli/preflight.js +689 -45
  126. package/dist/src/cli/preflight.js.map +1 -1
  127. package/dist/src/cli/progress.d.ts +78 -0
  128. package/dist/src/cli/prompt.d.ts +209 -0
  129. package/dist/src/cli/quickstart.d.ts +46 -0
  130. package/dist/src/cli/quickstart.js +297 -0
  131. package/dist/src/cli/quickstart.js.map +1 -0
  132. package/dist/src/cli/records.d.ts +34 -0
  133. package/dist/src/cli/render.d.ts +22 -0
  134. package/dist/src/cli/sandbox.d.ts +51 -0
  135. package/dist/src/cli/sandbox.js +17 -1
  136. package/dist/src/cli/sandbox.js.map +1 -1
  137. package/dist/src/cli/scaffold.d.ts +79 -0
  138. package/dist/src/cli/scaffold.js +1 -1
  139. package/dist/src/cli/setup-adapter.d.ts +137 -0
  140. package/dist/src/cli/setup-adapter.js +38 -4
  141. package/dist/src/cli/setup-adapter.js.map +1 -1
  142. package/dist/src/cli/setup-channel.d.ts +126 -0
  143. package/dist/src/cli/setup-channel.js +28 -1
  144. package/dist/src/cli/setup-channel.js.map +1 -1
  145. package/dist/src/cli/setup-checkpoint.d.ts +57 -0
  146. package/dist/src/cli/setup-common.d.ts +277 -0
  147. package/dist/src/cli/setup-common.js +3 -2
  148. package/dist/src/cli/setup-common.js.map +1 -1
  149. package/dist/src/cli/setup-flow.d.ts +287 -0
  150. package/dist/src/cli/setup-service.d.ts +96 -0
  151. package/dist/src/cli/setup.d.ts +204 -0
  152. package/dist/src/cli/setup.js +94 -2
  153. package/dist/src/cli/setup.js.map +1 -1
  154. package/dist/src/cli/style.d.ts +320 -0
  155. package/dist/src/cli/token.d.ts +39 -0
  156. package/dist/src/cli/up.d.ts +155 -0
  157. package/dist/src/cli/up.js +119 -53
  158. package/dist/src/cli/up.js.map +1 -1
  159. package/dist/src/cli/usage.d.ts +37 -0
  160. package/dist/src/cli/values.d.ts +40 -0
  161. package/dist/src/cli/values.js +3 -4
  162. package/dist/src/cli/values.js.map +1 -1
  163. package/dist/src/cli/vault.d.ts +59 -0
  164. package/dist/src/cli/vault.js +2 -2
  165. package/dist/src/cli/vault.js.map +1 -1
  166. package/dist/src/cli/verb-registry.d.ts +76 -0
  167. package/dist/src/cli/verb-registry.js +344 -11
  168. package/dist/src/cli/verb-registry.js.map +1 -1
  169. package/dist/src/cli/wordmark.d.ts +31 -0
  170. package/dist/src/cli/wordmark.js +2 -2
  171. package/dist/src/codex/broker.d.ts +229 -0
  172. package/dist/src/codex/broker.js +548 -0
  173. package/dist/src/codex/broker.js.map +1 -0
  174. package/dist/src/codex/doctor.d.ts +13 -0
  175. package/dist/src/codex/doctor.js +41 -0
  176. package/dist/src/codex/doctor.js.map +1 -0
  177. package/dist/src/codex/manifest.d.ts +49 -0
  178. package/dist/src/codex/manifest.js +103 -0
  179. package/dist/src/codex/manifest.js.map +1 -0
  180. package/dist/src/codex/runner.d.ts +178 -0
  181. package/dist/src/codex/runner.js +231 -0
  182. package/dist/src/codex/runner.js.map +1 -0
  183. package/dist/src/codex/serve.d.ts +56 -0
  184. package/dist/src/codex/serve.js +98 -0
  185. package/dist/src/codex/serve.js.map +1 -0
  186. package/dist/src/codex/templates.d.ts +41 -0
  187. package/dist/src/codex/templates.js +319 -0
  188. package/dist/src/codex/templates.js.map +1 -0
  189. package/dist/src/codex/trust.d.ts +19 -0
  190. package/dist/src/codex/trust.js +183 -0
  191. package/dist/src/codex/trust.js.map +1 -0
  192. package/dist/src/codex/workspace-commit.d.ts +219 -0
  193. package/dist/src/codex/workspace-commit.js +549 -0
  194. package/dist/src/codex/workspace-commit.js.map +1 -0
  195. package/dist/src/codex/workspace-plan.d.ts +131 -0
  196. package/dist/src/codex/workspace-plan.js +561 -0
  197. package/dist/src/codex/workspace-plan.js.map +1 -0
  198. package/dist/src/core/actor.d.ts +2 -0
  199. package/dist/src/core/actor.js +5 -0
  200. package/dist/src/core/actor.js.map +1 -0
  201. package/dist/src/core/advance-cycle.d.ts +221 -0
  202. package/dist/src/core/advance-cycle.js +66 -2
  203. package/dist/src/core/advance-cycle.js.map +1 -1
  204. package/dist/src/core/agents-md.d.ts +278 -0
  205. package/dist/src/core/agents-md.js +33 -31
  206. package/dist/src/core/agents-md.js.map +1 -1
  207. package/dist/src/core/apply-patch.d.ts +49 -0
  208. package/dist/src/core/apply-patch.js +266 -0
  209. package/dist/src/core/apply-patch.js.map +1 -0
  210. package/dist/src/core/attest.d.ts +635 -0
  211. package/dist/src/core/attest.js +326 -4
  212. package/dist/src/core/attest.js.map +1 -1
  213. package/dist/src/core/audit.d.ts +510 -0
  214. package/dist/src/core/audit.js +13 -0
  215. package/dist/src/core/audit.js.map +1 -1
  216. package/dist/src/core/budgets.d.ts +238 -0
  217. package/dist/src/core/channel-owner.d.ts +213 -0
  218. package/dist/src/core/channel-owner.js +358 -0
  219. package/dist/src/core/channel-owner.js.map +1 -0
  220. package/dist/src/core/checkpoint.d.ts +500 -0
  221. package/dist/src/core/child-env.d.ts +88 -0
  222. package/dist/src/core/clock.d.ts +52 -0
  223. package/dist/src/core/command-class.d.ts +697 -0
  224. package/dist/src/core/command-class.js +713 -25
  225. package/dist/src/core/command-class.js.map +1 -1
  226. package/dist/src/core/commit-guard.d.ts +272 -0
  227. package/dist/src/core/commit-guard.js +424 -0
  228. package/dist/src/core/commit-guard.js.map +1 -0
  229. package/dist/src/core/coverage-sources/adapter.d.ts +40 -0
  230. package/dist/src/core/coverage-sources/gh.d.ts +48 -0
  231. package/dist/src/core/coverage-sources/git.d.ts +101 -0
  232. package/dist/src/core/coverage.d.ts +217 -0
  233. package/dist/src/core/credential-spec.d.ts +72 -0
  234. package/dist/src/core/daemon-actor.d.ts +45 -0
  235. package/dist/src/core/daemon-actor.js +54 -0
  236. package/dist/src/core/daemon-actor.js.map +1 -0
  237. package/dist/src/core/dark-session.d.ts +432 -0
  238. package/dist/src/core/dark-session.js +266 -82
  239. package/dist/src/core/dark-session.js.map +1 -1
  240. package/dist/src/core/decision-refusal.d.ts +206 -0
  241. package/dist/src/core/decision-refusal.js +24 -2
  242. package/dist/src/core/decision-refusal.js.map +1 -1
  243. package/dist/src/core/env-file.d.ts +455 -0
  244. package/dist/src/core/env-file.js +60 -1
  245. package/dist/src/core/env-file.js.map +1 -1
  246. package/dist/src/core/execute.d.ts +871 -0
  247. package/dist/src/core/execute.js +59 -8
  248. package/dist/src/core/execute.js.map +1 -1
  249. package/dist/src/core/frontmatter.d.ts +78 -0
  250. package/dist/src/core/gate-window.d.ts +312 -0
  251. package/dist/src/core/gate.d.ts +1449 -0
  252. package/dist/src/core/gate.js +149 -14
  253. package/dist/src/core/gate.js.map +1 -1
  254. package/dist/src/core/gesture-refusal.d.ts +166 -0
  255. package/dist/src/core/gesture-refusal.js +188 -0
  256. package/dist/src/core/gesture-refusal.js.map +1 -0
  257. package/dist/src/core/git-run.d.ts +73 -0
  258. package/dist/src/core/harness-version.d.ts +157 -0
  259. package/dist/src/core/harness-version.js +4 -1
  260. package/dist/src/core/harness-version.js.map +1 -1
  261. package/dist/src/core/harness-wait.d.ts +55 -0
  262. package/dist/src/core/head-retry.d.ts +107 -0
  263. package/dist/src/core/instance.d.ts +310 -0
  264. package/dist/src/core/instance.js +113 -0
  265. package/dist/src/core/instance.js.map +1 -1
  266. package/dist/src/core/intake-limits.d.ts +247 -0
  267. package/dist/src/core/jcs.d.ts +52 -0
  268. package/dist/src/core/journal.d.ts +144 -0
  269. package/dist/src/core/live-draw.d.ts +436 -0
  270. package/dist/src/core/log-reconcile.d.ts +89 -0
  271. package/dist/src/core/log-subscribe.d.ts +36 -0
  272. package/dist/src/core/log-subscribe.js +162 -0
  273. package/dist/src/core/log-subscribe.js.map +1 -0
  274. package/dist/src/core/log.d.ts +316 -0
  275. package/dist/src/core/log.js.map +1 -1
  276. package/dist/src/core/loop.d.ts +274 -0
  277. package/dist/src/core/loop.js +11 -0
  278. package/dist/src/core/loop.js.map +1 -1
  279. package/dist/src/core/md-fence.d.ts +41 -0
  280. package/dist/src/core/money.d.ts +147 -0
  281. package/dist/src/core/payload-census.d.ts +74 -0
  282. package/dist/src/core/payload-store.d.ts +175 -0
  283. package/dist/src/core/payload.d.ts +71 -0
  284. package/dist/src/core/policy-diff.d.ts +292 -0
  285. package/dist/src/core/policy-diff.js +27 -4
  286. package/dist/src/core/policy-diff.js.map +1 -1
  287. package/dist/src/core/policy-expectations.d.ts +199 -0
  288. package/dist/src/core/policy-explain.d.ts +160 -0
  289. package/dist/src/core/policy-explain.js +63 -3
  290. package/dist/src/core/policy-explain.js.map +1 -1
  291. package/dist/src/core/policy-load.d.ts +567 -0
  292. package/dist/src/core/policy-load.js +36 -6
  293. package/dist/src/core/policy-load.js.map +1 -1
  294. package/dist/src/core/policy-match.d.ts +324 -0
  295. package/dist/src/core/policy-match.js +72 -9
  296. package/dist/src/core/policy-match.js.map +1 -1
  297. package/dist/src/core/policy-proposal.d.ts +317 -0
  298. package/dist/src/core/policy-proposal.js +102 -2
  299. package/dist/src/core/policy-proposal.js.map +1 -1
  300. package/dist/src/core/prompt-layout.d.ts +221 -0
  301. package/dist/src/core/protected-path-guard.d.ts +566 -0
  302. package/dist/src/core/protected-path-guard.js +848 -55
  303. package/dist/src/core/protected-path-guard.js.map +1 -1
  304. package/dist/src/core/question-preempted.d.ts +141 -0
  305. package/dist/src/core/question-preempted.js +152 -0
  306. package/dist/src/core/question-preempted.js.map +1 -0
  307. package/dist/src/core/read-scope.d.ts +172 -0
  308. package/dist/src/core/read-scope.js +252 -0
  309. package/dist/src/core/read-scope.js.map +1 -0
  310. package/dist/src/core/registration.d.ts +25 -0
  311. package/dist/src/core/reindex.d.ts +99 -0
  312. package/dist/src/core/sampler.d.ts +313 -0
  313. package/dist/src/core/sandbox.d.ts +371 -0
  314. package/dist/src/core/sandbox.js +190 -1
  315. package/dist/src/core/sandbox.js.map +1 -1
  316. package/dist/src/core/seal.d.ts +165 -0
  317. package/dist/src/core/sender-identity.d.ts +476 -0
  318. package/dist/src/core/sender-identity.js +572 -0
  319. package/dist/src/core/sender-identity.js.map +1 -0
  320. package/dist/src/core/shlex.d.ts +102 -0
  321. package/dist/src/core/shlex.js +159 -0
  322. package/dist/src/core/shlex.js.map +1 -0
  323. package/dist/src/core/state.d.ts +505 -0
  324. package/dist/src/core/task-file.d.ts +185 -0
  325. package/dist/src/core/telegram-config.d.ts +93 -0
  326. package/dist/src/core/token.d.ts +409 -0
  327. package/dist/src/core/token.js +21 -38
  328. package/dist/src/core/token.js.map +1 -1
  329. package/dist/src/core/validate.d.ts +138 -0
  330. package/dist/src/core/values.d.ts +147 -0
  331. package/dist/src/core/values.js +36 -1
  332. package/dist/src/core/values.js.map +1 -1
  333. package/dist/src/core/vault.d.ts +291 -0
  334. package/dist/src/core/verified-snapshot.d.ts +204 -0
  335. package/dist/src/core/verify.d.ts +336 -0
  336. package/dist/src/core/version.d.ts +8 -0
  337. package/dist/src/core/wysiwys.d.ts +370 -0
  338. package/dist/src/daemon/advance-child.d.ts +39 -0
  339. package/dist/src/daemon/advance.d.ts +476 -0
  340. package/dist/src/daemon/advance.js +25 -4
  341. package/dist/src/daemon/advance.js.map +1 -1
  342. package/dist/src/daemon/audit.d.ts +87 -0
  343. package/dist/src/daemon/daemon.d.ts +1180 -0
  344. package/dist/src/daemon/daemon.js +9 -0
  345. package/dist/src/daemon/daemon.js.map +1 -1
  346. package/dist/src/daemon/dark-session.d.ts +64 -0
  347. package/dist/src/daemon/draw-child.d.ts +36 -0
  348. package/dist/src/daemon/draw.d.ts +154 -0
  349. package/dist/src/daemon/git-evidence.d.ts +173 -0
  350. package/dist/src/daemon/git-evidence.js +1 -1
  351. package/dist/src/daemon/projection.d.ts +180 -0
  352. package/dist/src/daemon/prune.d.ts +207 -0
  353. package/dist/src/mcp/http.d.ts +113 -0
  354. package/dist/src/mcp/server.d.ts +265 -0
  355. package/dist/src/mcp/server.js +17 -1
  356. package/dist/src/mcp/server.js.map +1 -1
  357. package/docs/adapter-api.md +106 -0
  358. package/docs/cli-reference.md +1316 -63
  359. package/docs/codex-enforced-session.md +103 -0
  360. package/docs/codex-workspace-broker.md +118 -0
  361. package/package.json +14 -2
  362. package/schema/codex-instance.schema.json +82 -0
  363. package/schema/event.schema.json +539 -9
  364. package/schema/fixtures/codex-instance/invalid/unpinned-codex-version.json +40 -0
  365. package/schema/fixtures/codex-instance/valid/canonical.json +40 -0
  366. package/schema/fixtures/event/invalid/approval-granted-sender-hashed-false.json +20 -0
  367. package/schema/fixtures/event/invalid/approval-granted-sender-hashed-raw-id.json +20 -0
  368. package/schema/fixtures/event/invalid/audit-gesture-refused-human-actor.json +16 -0
  369. package/schema/fixtures/event/invalid/audit-gesture-refused-no-actor-no-sender.json +15 -0
  370. package/schema/fixtures/event/invalid/audit-gesture-refused-unknown-gesture.json +16 -0
  371. package/schema/fixtures/event/invalid/audit-question-preempted-agent-actor.json +16 -0
  372. package/schema/fixtures/event/invalid/audit-question-preempted-no-question-id.json +16 -0
  373. package/schema/fixtures/event/invalid/audit-question-preempted-unknown-source.json +15 -0
  374. package/schema/fixtures/event/invalid/gate-path-signed-off-absolute-path.json +14 -0
  375. package/schema/fixtures/event/invalid/gate-path-signed-off-agent-actor.json +14 -0
  376. package/schema/fixtures/event/invalid/gate-path-signed-off-missing-path.json +13 -0
  377. package/schema/fixtures/event/valid/approval-granted-sender-hashed.json +20 -0
  378. package/schema/fixtures/event/valid/audit-gesture-refused-review-note.json +21 -0
  379. package/schema/fixtures/event/valid/audit-gesture-refused-sender-key-unavailable.json +19 -0
  380. package/schema/fixtures/event/valid/audit-gesture-refused.json +19 -0
  381. package/schema/fixtures/event/valid/audit-question-preempted-no-verdict.json +16 -0
  382. package/schema/fixtures/event/valid/audit-question-preempted.json +20 -0
  383. package/schema/fixtures/event/valid/gate-path-signed-off.json +14 -0
  384. package/schema/fixtures/event/valid/harness-kind-claude-code.json +23 -0
  385. package/schema/fixtures/event/valid/harness-kind-codex.json +23 -0
  386. package/schema/fixtures/event/valid/harness-kind-cursor.json +23 -0
  387. package/schema/fixtures/event/valid/harness-kind-grok.json +23 -0
  388. package/schema/fixtures/event/valid/harness-kind-muse.json +23 -0
  389. package/schema/fixtures/policy/invalid/senders-half-keyed.json +20 -0
  390. package/schema/fixtures/policy/valid/canonical.json +1 -1
  391. package/schema/fixtures/policy/valid/senders-keyed.json +24 -0
  392. package/schema/fixtures/policy-md/valid/canonical.md +1 -1
  393. package/schema/fixtures/policy-md/valid/with-values.md +5 -7
  394. package/schema/fixtures/values/invalid/class-shaped.json +1 -1
  395. package/schema/fixtures/values/invalid/duplicate-entry.json +1 -1
  396. package/schema/fixtures/values/invalid/non-string-item.json +1 -1
  397. package/schema/fixtures/values/invalid/over-cap.json +1 -1
  398. package/schema/fixtures/values/invalid/unknown-key.json +1 -1
  399. package/schema/fixtures/values/invalid/version-float.json +1 -0
  400. package/schema/fixtures/values/invalid/version-integer.json +1 -0
  401. package/schema/fixtures/values/invalid/version-wrong-string.json +1 -0
  402. package/schema/fixtures/values/valid/empty-lists.json +2 -3
  403. package/schema/fixtures/values/valid/full.json +5 -7
  404. package/schema/fixtures/values/valid/minimal.json +1 -1
  405. package/schema/fixtures/values-md/invalid/schema-invalid.md +5 -3
  406. package/schema/fixtures/values-md/invalid/two-blocks.md +3 -3
  407. package/schema/fixtures/values-md/invalid/unterminated.md +2 -2
  408. package/schema/fixtures/values-md/invalid/version-1.md +69 -0
  409. package/schema/fixtures/values-md/invalid/version-unquoted.md +64 -0
  410. package/schema/fixtures/values-md/invalid/yaml-error.md +2 -2
  411. package/schema/fixtures/values-md/valid/absent.md +1 -1
  412. package/schema/fixtures/values-md/valid/with-values.md +5 -7
  413. package/schema/policy.schema.json +75 -3
  414. package/schema/values.schema.json +7 -11
  415. package/templates/codex/README.md +9 -0
  416. package/schema/fixtures/values/invalid/version-string.json +0 -1
@@ -36,8 +36,10 @@ Usage:
36
36
  approval log verify [--log <path>] [--json]
37
37
  approval log tail [--log <path>] [-n <count>] [--json]
38
38
  approval log export [--log <path>] [--json]
39
+ approval log follow [--log <path>] [--from <seq>] [--cursor-hash <64hex>] --json
39
40
  approval instructions [--schemas] [--json]
40
41
  approval init [--dir <path>] [--json]
42
+ approval quickstart [--dir <path>] [--api-base <url>] (interactive; no --json)
41
43
  approval policy check|test <class> [--reversible true|false] [--policy <path>] [--dir <path>] [--json]
42
44
  approval policy attest [--policy <path>] [--dir <path>] [--as human:<id>] [--json]
43
45
  approval policy amend [--policy <path>] [--dir <path>] [--log <path>]
@@ -52,10 +54,12 @@ Usage:
52
54
  [--as <id>] [--json] (internal)
53
55
  approval run <action-key> [--token <t>] [--payload-hash <64hex>]
54
56
  [--as <id>] [--no-sandbox] [--json] -- <cmd…>
55
- approval sandbox [--allow-loopback] [--log <path>] -- <cmd…>
56
- approval adapter email <action-key> --token <t> --payload <file|->
57
+ approval sandbox [--allow-loopback] [--read-jail] [--log <path>] -- <cmd…>
58
+ approval adapter email <action-key> [--token <t>] --payload <file|->
57
59
  [--as <id>] [--vault <path>] [--timeout <ms>] [--json]
58
- approval adapter agentmail <action-key> --token <t> --payload <file|->
60
+ approval adapter agentmail <action-key> [--token <t>] --payload <file|->
61
+ [--as <id>] [--vault <path>] [--timeout <ms>] [--json]
62
+ approval adapter zzz <action-key> [--token <t>] --payload <file|->
59
63
  [--as <id>] [--vault <path>] [--timeout <ms>] [--json]
60
64
  approval execution resolve <action-key> --outcome completed|failed
61
65
  --note "<text>" [--as human:<id>] [--json]
@@ -114,6 +118,7 @@ Usage:
114
118
  [--log <path>] (reads preToolUse JSON)
115
119
  approval hook classify [--json] [--policy <path>] [--dir <path>] -- <command…>
116
120
  approval import agents-md <file> [--out <path>] [--json]
121
+ approval codex prepare|setup|doctor|start|serve (strict host workflow)
117
122
  approval mcp serve --as agent:<id> [--dir <path>] [--log <path>]
118
123
  [--policy <path>] (MCP over stdio; foreground)
119
124
  approval reindex [--log <path>] [--index <path>] [--force] [--json]
@@ -129,6 +134,10 @@ Set up — make this directory and this machine ready:
129
134
  atomic-write temp files. Appends
130
135
  nothing, attests nothing, overwrites nothing; a re-run writes
131
136
  nothing and reports what already exists
137
+ quickstart ask three decisions, write a solo policy with the named human as
138
+ its sole approver, configure identity and an optional Telegram
139
+ channel, show the exact bytes, then require typed \`understood\`
140
+ before attesting. HUMAN-ONLY and INTERACTIVE ONLY
132
141
  setup the WRITER for that file: "setup identity|vault|sampling" and
133
142
  "setup channel <name>" store each secret in the OS keystore and
134
143
  record where it lives, and "setup adapter <name>" fills the VAULT
@@ -145,7 +154,7 @@ Set up — make this directory and this machine ready:
145
154
  "vault set|list|remove" are HUMAN-ONLY; list shows NAMES and never
146
155
  values, and there is no "vault get" — a credential's only sanctioned
147
156
  journey is from .approval/vault.enc into an adapter, inside the
148
- verified-token window. The passphrase comes from the environment
157
+ verified execution window. The passphrase comes from the environment
149
158
  variable the policy NAMES (vault.passphrase_env), never from a flag
150
159
  env resolve .approval/env — the environment SOURCE MAP — and print an
151
160
  export block for your shell to evaluate. THE ONLY VERB THAT READS
@@ -182,13 +191,15 @@ Ask — an agent declares an action and acts on the answer:
182
191
  run execute a command behind the gate: appends execution.started before
183
192
  spawning it, execution.completed/failed with the child's exit code
184
193
  after, and exits with that same code
185
- adapter execute an approved action through a side-effect adapter, the hard
194
+ adapter execute an action through a side-effect adapter, the hard
186
195
  boundary of SPEC.md §10.4. "adapter email" sends one RFC 5322
187
196
  message over SMTP for a communicate.email.external action: the
188
- credentials come from the vault inside the verified-token window,
189
- the payload is the bytes the grant bound to, and the runtime — not
190
- the adapter — recomputes the hash, spends the token, and writes both
191
- execution events around the send. "adapter agentmail" serves the
197
+ credentials come from the vault inside the execution window, the
198
+ payload is the bytes the declaration or grant bound to, and the
199
+ runtime recomputes the hash, applies policy, and writes both
200
+ execution events around the send. Manual and selected-live paths
201
+ require --token; policy-authorized supervised/autonomous paths do
202
+ not mint one. "adapter agentmail" serves the
192
203
  same class over the AgentMail API: a direct send, or the send of a
193
204
  draft the agent composed, refused if the draft changed after the
194
205
  snapshot a human approved
@@ -395,6 +406,7 @@ Usage:
395
406
  approval log verify [--log <path>] [--json]
396
407
  approval log tail [--log <path>] [-n <count>] [--json]
397
408
  approval log export [--log <path>] [--json]
409
+ approval log follow [--log <path>] [--from <seq>] [--cursor-hash <64hex>] --json
398
410
  approval log sync [--remote <name>] [--branch <name>] [--json]
399
411
  approval log advance [--branch <name>] [--pr] [--dry-run] [--json]
400
412
  approval log checkpoint --as human:<id> [--key-file <path>] [--json]
@@ -402,17 +414,40 @@ Usage:
402
414
  Subcommands:
403
415
  verify walk the hash chain end to end; clean | torn-tail | corrupt
404
416
  tail / export the last N records (default 10) / every line, verbatim
417
+ follow verified records after an exclusive cursor, then verified appends
405
418
  sync fast-forward pull, with a snapshot and a chain reconcile
406
419
  advance commit the log's new records onto a records branch
407
420
  checkpoint sign the current head with your own key (human-only)
408
421
 
409
- verify, tail and export only read. sync and advance move the FILE and append no
410
- record; checkpoint appends one. Default log: .approval/log/events.jsonl
411
- JSON shapes: docs/cli-reference.md
412
-
413
- ${EXIT_CODES_POINTER}
422
+ verify, tail, export and follow only read. sync and advance move the FILE and append no record;
423
+ checkpoint appends one. Default log: .approval/log/events.jsonl
424
+ JSON shapes: docs/cli-reference.md; ${EXIT_CODES_POINTER}
414
425
  ${JSON_ERRORS}
415
426
  ${why("log")}`;
427
+ export const FOLLOW_HELP = `approval log follow — follow verified records after a cursor
428
+
429
+ Usage:
430
+ approval log follow [--log <path>] [--from <seq>] [--cursor-hash <64hex>] --json
431
+
432
+ Flags:
433
+ --log <path> log file to read (default .approval/log/events.jsonl)
434
+ --from <seq> exclusive sequence cursor (default 0)
435
+ --cursor-hash <hex> hash of record --from, retained by the consumer
436
+ --json required; one complete event object per stdout line
437
+ -h, --help this text
438
+
439
+ The complete chain is verified before each emitted batch. Notifications only
440
+ wake another verification. Corrupt, torn, unreadable, truncated or cursor-
441
+ mismatched logs stop the stream before any record from that batch is printed.
442
+
443
+ Persist seq and hash after the external effect succeeds. Reconnecting from that
444
+ cursor is at-least-once across a crash between the effect and cursor storage;
445
+ exactly-once external effects require the consumer's own idempotency mechanism.
446
+
447
+ ${EXIT_CODES_POINTER} (0 on signal or broken-pipe cancellation; 1 corrupt or cursor
448
+ mismatch; 2 usage; 3 torn tail; 4 I/O)
449
+ ${JSON_ERRORS}
450
+ ${why("log-follow")}`;
416
451
  export const LOG_SYNC_HELP = `approval log sync — fast-forward the committed log, safely
417
452
 
418
453
  Usage:
@@ -441,12 +476,12 @@ export const LOG_ADVANCE_HELP = `approval log advance — commit and push the lo
441
476
 
442
477
  Usage:
443
478
  approval log advance [--remote <n>] [--branch <n>] [--base <n>] [--pr]
444
- [--no-auto-merge] [--dry-run] [--json]
445
-
479
+ [--co-author "Name <email>"] [--no-auto-merge] [--dry-run] [--json]
446
480
  Flags:
447
481
  --remote <name> remote to push to (default origin)
448
482
  --branch <name> records branch (default records-log-<date>); never main
449
483
  --base <name> branch to parent the commit on (default: the one you are on)
484
+ --co-author <id> append Name <email> display credit to commit and PR body
450
485
  --pr / --dry-run open the PR through gh and ARM its merge / write nothing
451
486
  --no-auto-merge / --json / -h, --help do not arm / JSON output / this text
452
487
 
@@ -572,24 +607,49 @@ const POLICY_MANUAL_BECAUSE = `manualBecause is "matched-rule", "irreversibility
572
607
  export const POLICY_HELP = `approval policy — explain what policy does with an action class
573
608
 
574
609
  Usage:
575
- approval policy check|test <class> [--reversible true|false] [--policy <p>]
576
- [--dir <p>] [--json]
577
- approval policy attest [--policy <p>] [--dir <p>] [--as human:<id>] [--json]
578
- approval policy amend [--policy <p>] [--dir <p>] [--log <p>] [--as human:<id>]
579
- [--require-load] [--dry-run] [--commit] [--yes] [--json]
610
+ approval policy check|test <class> [--reversible true|false] [--policy|--dir <p>] [--json]
611
+ approval policy attest [--policy|--dir <p>] [--as human:<id>] [--json]
612
+ approval policy amend [--policy|--dir|--log <p>] [--as human:<id>] [--require-load]
613
+ [--dry-run] [--commit|--pr] [--yes] [--json]
614
+ approval policy apply <proposal.md> [--dry-run] [--no-amend] [--pr] [--yes]
580
615
 
581
616
  Subcommands:
582
617
  check explain the autonomy resolution for <class>
583
618
  test exact alias of check (SPEC.md §10.1 names both)
584
619
  attest record a human's sign-off on the policy file's bytes (human-only)
585
620
  amend the whole amendment ceremony: diff, advisory, attestation, commit
621
+ apply apply a proposal document's quoted replacements, then amend (human-only)
586
622
 
587
- Nothing is executed, requested, or logged: this reads APPROVAL.md and answers a
588
- hypothetical. Discovery is APPROVAL.md then APPROVALS.md in --dir.
589
- ${POLICY_MANUAL_BECAUSE}
623
+ check and test read APPROVAL.md and answer a hypothetical, executing and logging nothing.
624
+ Discovery is APPROVAL.md then APPROVALS.md in --dir. ${POLICY_MANUAL_BECAUSE}
590
625
 
591
626
  ${POLICY_EXIT_CODES}
592
627
  ${why("policy")}`;
628
+ export const POLICY_APPLY_HELP = `approval policy apply — apply a proposal document to APPROVAL.md, then amend
629
+
630
+ Usage:
631
+ approval policy apply <proposal.md> [--policy <p>] [--dir <p>] [--log <p>]
632
+ [--as human:<id>] [--dry-run] [--no-amend] [--no-publish] [--yes] [--json]
633
+
634
+ Flags:
635
+ <proposal.md> the document whose Current/Replace-with pairs to apply
636
+ --policy <p> / --dir <p> the policy file, or the directory to discover it in
637
+ --dry-run / --no-amend show the replacements only / write them and stop
638
+ --no-publish / --yes / --json stop at the commit / skip both prompts / machine
639
+
640
+ HUMAN-ONLY: an agent identity refuses apply-agent-actor, and the verb classifies
641
+ policy.core, human-only in this project's policy. Every pair resolves against an
642
+ in-memory copy FIRST, so a stale proposal writes nothing at all. A pair is two
643
+ fenced blocks WITH a declared language (APRV-273), labelled \`Current:\` and
644
+ \`Replace with:\` above; \`Supersedes:\` names an earlier section's result to match
645
+ instead. Whole-file replacement is NOT accepted: every byte written is anchored
646
+ to a byte proved present. The values block is treated as the policy block is.
647
+ Refusals: usage, io, apply-agent-actor, proposal-empty, proposal-malformed,
648
+ proposal-stale, proposal-ambiguous. Then it runs \`policy amend --pr\`, which
649
+ PUBLISHES: refspec push, pull request, merge armed, checkout never moved.
650
+
651
+ ${EXIT_CODES_POINTER}
652
+ ${why("policy-apply")}`;
593
653
  function policyVerbHelp(verb, alias) {
594
654
  return `approval policy ${verb} — explain what policy does with an action class
595
655
 
@@ -618,21 +678,21 @@ export const POLICY_ATTEST_HELP = `approval policy attest — record a human's s
618
678
 
619
679
  Usage:
620
680
  approval policy attest [--policy <path>] [--dir <path>] [--organ <path>]
621
- [--as human:<id>] [--log <path>] [--json]
681
+ [--path <path>] [--as human:<id>] [--log <path>] [--json]
622
682
 
623
683
  Flags:
624
684
  --policy <path> / --dir <path> the policy file, or where to discover it
625
685
  --organ <path> attest a GATE ORGAN instead; one path per call, under --dir
686
+ --path <path> sign off a PROTECTED path's current bytes; one path per call
626
687
  --as human:<id> the human attesting; overrides APPROVAL_HUMAN
627
688
  --log <path> log file to append to (default .approval/log/events.jsonl)
628
- --json machine-readable output
629
- -h, --help this text
689
+ --json / -h, --help machine-readable output / this text
630
690
 
631
- Appends one policy.updated event carrying the SHA-256 of the policy file's exact
632
- bytes; gate operations refuse while it differs ("policy-not-attested").
633
- Human-only, identity CONFIG-DECLARED: the trust boundary is the local machine,
634
- so it proves someone with local control signed off, not who. Bytes, not parse.
635
- --organ appends gate.organ.attested for a policy.core harness file instead.
691
+ Appends one policy.updated event with the policy file's exact SHA-256; gate
692
+ operations refuse while it differs ("policy-not-attested"). Bytes, not parse.
693
+ Human-only, identity CONFIG-DECLARED. What attestation proves is bounded: the
694
+ trust boundary is the local machine, so someone with local control, not who.
695
+ --organ appends gate.organ.attested (policy.core); --path gate.path.signed_off.
636
696
 
637
697
  JSON shape: docs/cli-reference.md#policy-attest
638
698
  ${EXIT_CODES_POINTER}
@@ -642,22 +702,22 @@ export const POLICY_AMEND_HELP = `approval policy amend — the whole amendment
642
702
 
643
703
  Usage:
644
704
  approval policy amend [--policy|--dir|--log <p>] [--as human:<id>|agent:<id>] [--require-load]
645
- [--dry-run] [--commit] [--no-publish] [--yes] [--json] [--branch <n>|--direct] [--wait <d>]
705
+ [--dry-run] [--commit|--pr] [--no-publish] [--yes] [--json] [--branch <n>|--direct] [--wait <d>]
646
706
 
647
707
  Flags:
648
708
  --policy <p> / --dir <p> / --log <p> policy, its discovery dir, and the log
649
709
  --as human:<id> / agent:<id> attest HERE, or ask for a TAP (--wait/--interval/--note)
650
710
  --require-load refuse to attest a policy that does not load
651
711
  --dry-run / --commit / --no-publish write nothing / the ceremony / stop at commit
652
- --branch <name> / --direct force the BRANCH or the DIRECT flow
712
+ --pr / --branch <name> / --direct FINISH it (branch, push, PR, arm) / force either flow
653
713
  --yes / --json / -h, --help skip the prompt / machine-readable / this text
654
714
 
655
- Hashes the policy, diffs it against the BASELINE (classes AND every policy key), attests, then
656
- commits EXACTLY the policy, the log and the pins when they moved. commit-preconditions, the pins
657
- and the DOGFOOD SUITE refuse BEFORE the append; git-failed, push-rejected, pr-failed break after it.
658
- Attested TEXT is NOT recoverable from the log: HASH-ONLY MODE. Flows, in PRECEDENCE, highest first:
659
- --branch <name>, --direct; a refused push PUBLISHES ITSELF, dropping to a RUNBOOK. MERGE COMMIT it.
660
- --as agent: appends policy.proposed; the TAP attests. Fail closed: no-channel, declined, timeout.
715
+ Hashes the policy, diffs it against the BASELINE (classes AND every policy key), attests, then commits
716
+ EXACTLY the policy, the log and the pins when they moved. commit-preconditions, staged-unrelated,
717
+ dirty-tree, the pins and the DOGFOOD SUITE refuse BEFORE the append; git-failed, push-rejected and
718
+ pr-failed break after it, into a RUNBOOK. Attested TEXT is NOT recoverable from the log:
719
+ HASH-ONLY MODE. Flows, in PRECEDENCE, highest first: --branch <name>, --pr (opens or UPDATES the open
720
+ pull request, arms --auto), --direct. MERGE COMMIT it. --as agent: appends policy.proposed, TAP attests.
661
721
 
662
722
  ${EXIT_CODES_POINTER}
663
723
  ${JSON_ERRORS}
@@ -923,19 +983,21 @@ ${why("run")}`;
923
983
  export const SANDBOX_HELP = `approval sandbox — run a command with no way out (APRV-193)
924
984
 
925
985
  Usage:
926
- approval sandbox [--allow-loopback] [--log <path>] -- <cmd> [args…]
986
+ approval sandbox [--allow-loopback] [--read-jail] [--log <path>] -- <cmd…>
927
987
 
928
988
  Flags:
929
989
  --allow-loopback also allow connections to localhost. For a suite that
930
990
  starts its own server. A real widening: a port is a port
991
+ --read-jail also deny file reads outside the gate root and the scratch
992
+ roots. Already on when the policy declares read_scope, and
993
+ nothing turns it off where it did (APRV-347)
931
994
  --log <path> the log, so the credential material beside it can be made
932
995
  unreadable to the child (vault, env map, sealing keys)
933
996
  -h, --help this text ("--help --long" adds the reference section)
934
997
 
935
- Denies the child outbound network (macOS sandbox-exec), scrubs the
936
- credential-bearing variables out of its environment, and exits with the child's
937
- own exit code. It appends NOTHING: it removes a capability rather than
938
- authorizing anything, and the gate stays reachable because its IPC is a file.
998
+ Denies outbound network (macOS sandbox-exec), scrubs the credential variables
999
+ from the child's environment, exits with its code, and appends NOTHING: it
1000
+ removes a capability rather than authorizing anything.
939
1001
 
940
1002
  The point is laundered exec: "npm test" runs whatever was written a minute ago,
941
1003
  so the command's NAME stopped describing its effect. An agent HARNESS cannot run
@@ -1346,31 +1408,105 @@ JSON shape (one object on stdout):
1346
1408
  ${EXIT_CODES_POINTER}
1347
1409
  ${JSON_ERRORS}
1348
1410
  ${why("init")}`;
1411
+ export const QUICKSTART_HELP = `approval quickstart — make a small solo gate operative
1412
+
1413
+ Usage:
1414
+ approval quickstart [--dir <path>]
1415
+
1416
+ Asks three decisions: your human id, terminal or Telegram, and which five class
1417
+ families always ask. It refuses a directory that already has policy or .approval
1418
+ state, writes a fresh policy, configures identity, and runs doctor before showing
1419
+ the exact bytes. The one expected unattested row is ignored at that point; every
1420
+ other failed row stops setup before attestation. Typed \`understood\` attests only
1421
+ if the file still has the displayed digest. A Telegram token uses the existing
1422
+ OS-keystore setup path and is resolved explicitly for that preflight.
1423
+
1424
+ Interactive only. Piped stdin and --json exit 2 and print the manual sequence.
1425
+ The generated default applies only to classified reversible actions; protected
1426
+ controls, fail-closed policy loading and unclassified-command refusal remain.
1427
+
1428
+ Flags:
1429
+ --dir <path> project directory (default: current directory)
1430
+ --api-base <url> Telegram API base passed to channel setup and doctor
1431
+ -h, --help this text
1432
+
1433
+ ${EXIT_CODES_POINTER} (0 success; 1 doctor failure; 2 usage; 4 filesystem failure)
1434
+ ${why("quickstart")}`;
1349
1435
  export const HOOK_HELP = `approval hook — put the gate in front of an agent harness
1350
1436
 
1351
1437
  Usage:
1352
- approval hook claude-code|cursor [--as agent:<id>] [--timeout <d>] [--interval <d>]
1353
- [--retry-grace <d>] [--policy <p>] [--dir <p>] [--log <p>]
1438
+ approval hook claude-code|cursor|codex|grok|muse [--as agent:<id>] [--timeout <d>] [--interval <d>] [--retry-grace <d>] [--policy <p>] [--dir <p>] [--log <p>]
1354
1439
  approval hook classify [--json] [--policy <p>] [--dir <p>] -- <command…>
1355
1440
 
1356
1441
  Commands:
1357
1442
  claude-code Claude Pre/PostToolUse JSON in; decision JSON out. REGISTER BOTH
1358
1443
  cursor Cursor preToolUse JSON in; native {permission} JSON out
1444
+ codex Codex synchronous Pre/Post JSON; Bash denied, direct apply_patch experimentally gated
1445
+ grok Grok Build camelCase Pre/PostToolUse JSON in; {decision,reason} out, DENY IS EXIT 2. \`approval hook grok --help\` prints the config
1446
+ muse Muse Code snake_case Pre/PostToolUse; ONE dialect out or it fails open. \`approval hook muse --help\` prints the config
1359
1447
  classify print what the classifier makes of a command line and exit
1360
-
1361
- Flags (claude-code, cursor):
1362
- --as <id> proposing identity (default agent:claude-code / agent:cursor)
1363
- --timeout/--interval/--retry-grace <d> wait / poll / hold for a retry (55s/1s/5m)
1448
+ --as <id> proposing identity (default agent:<harness>)
1449
+ --timeout/--interval/--retry-grace <d> wait / poll / hold for a retry (9m/1s/5m)
1364
1450
  --dir/--policy/--log <p> policy+log root; --dir sets BOTH, default primary
1365
1451
  -h, --help this text
1366
1452
 
1367
- Deny: hook-unclassified, hook-class-human-only, hook-opaque, hook-unparseable,
1368
- hook-rejected, hook-revoked, hook-expired, hook-withdrawn, hook-timeout,
1369
- hook-gate-refused:<c>, hook-grant-unverified, hook-sandbox-required,
1370
- hook-policy-unavailable, hook-log-unreachable, hook-io.
1453
+ Codex opt-in: register exact Bash|apply_patch synchronously with timeout 600s (default wait 9m). Bash is denied because native events hide per-call workdir; direct apply_patch is experimental. PostToolUse is diagnostic.
1454
+
1455
+ Deny: hook-unclassified, hook-class-human-only, hook-harness-launch-unruled, hook-opaque, hook-unparseable, hook-rejected, hook-revoked, hook-expired, hook-withdrawn, hook-timeout,
1456
+ hook-gate-refused:<c>, hook-grant-unverified, hook-sandbox-required, hook-policy-unavailable, hook-log-unreachable, hook-unsupported-execution-context, hook-muse-contributor-model, hook-io.
1371
1457
 
1372
1458
  ${EXIT_CODES_POINTER} (harness verbs use 0 and 2 only; 0 is a verdict, never "ask")
1373
1459
  ${why("hook")}`;
1460
+ export const HOOK_GROK_HELP = `approval hook grok — the gate in front of Grok Build (APRV-243)
1461
+
1462
+ Usage:
1463
+ approval hook grok [--as agent:<id>] [--timeout <d>] [--interval <d>]
1464
+ [--retry-grace <d>] [--policy <p>] [--dir <p>] [--log <p>]
1465
+
1466
+ camelCase in (hookEventName, sessionId, cwd, workspaceRoot, toolName, toolInput);
1467
+ {"decision":"allow"|"deny","reason":"…"} out, never "ask". DENY IS EXIT 2,
1468
+ allow is 0, post-execution always 0.
1469
+
1470
+ READ docs/grok-hook.md BEFORE COMMITTING THIS: Grok Build fails OPEN on hook
1471
+ timeout, crash and malformed output, with no setting to change that. It
1472
+ contradicts the fail-closed invariant and the adapter cannot fix it.
1473
+
1474
+ The file the human commits, .grok/hooks/pre-tool-use.json:
1475
+ {"hooks":{"PreToolUse":[{"matcher":"*","hooks":[
1476
+ {"type":"command","command":"approval hook grok --dir <repo>",
1477
+ "timeout": 600}]}]}}
1478
+
1479
+ That "timeout" MUST EXCEED --timeout (default 9m), or Grok abandons the call
1480
+ mid-wait and, failing open, runs the command while a human is still deciding.
1481
+ .grok/hooks/ classifies policy.core, like .cursor/hooks.json.
1482
+
1483
+ ${EXIT_CODES_POINTER} (0 allow, 2 deny; never "ask")
1484
+ ${why("hook")}`;
1485
+ export const HOOK_MUSE_HELP = `approval hook muse — the gate in front of Meta Muse Code (APRV-350)
1486
+
1487
+ Usage:
1488
+ approval hook muse [--as agent:<id>] [--timeout <d>] [--interval <d>]
1489
+ [--retry-grace <d>] [--policy <p>] [--dir <p>] [--log <p>]
1490
+ snake_case in (hook_event_name, tool_name, tool_input, cwd, model); ONE dialect
1491
+ out, nested {"hookSpecificOutput":{"permissionDecision":…}} at exit 0, never
1492
+ "ask". Tools: bash (per-call workdir), write_file, read_file, search.
1493
+
1494
+ READ docs/muse-hook.md FIRST. Muse fails OPEN on hook crash, timeout and
1495
+ malformed output — and output MIXING dialects is itself malformed, so a payload
1496
+ satisfying every harness at once satisfies this one not at all.
1497
+ CONTRIBUTOR MODELS ARE REFUSED (hook-muse-contributor-model) on every tool call
1498
+ regardless of policy: Meta trains on that tier. The guard stops tool calls; it
1499
+ cannot recall a prompt already sent.
1500
+ The file the human commits, .muse/hooks.json (no "matcher"; policy.core):
1501
+ {"hooks":{"PreToolUse":[{"hooks":[
1502
+ {"type":"command","command":"approval hook muse --dir <repo>",
1503
+ "timeout": 600}]}],"PostToolUse":[{"hooks":[
1504
+ {"type":"command","command":"approval hook muse --dir <repo>",
1505
+ "timeout": 600}]}]}}
1506
+ That "timeout" MUST EXCEED --timeout (9m), or Muse abandons the call mid-wait
1507
+ and, failing open, runs it while a human is still deciding.
1508
+ ${EXIT_CODES_POINTER} (0 for every verdict; deny is the body, not the code)
1509
+ ${why("hook")}`;
1374
1510
  export const IMPORT_HELP = `approval import — turn existing permissions prose into a draft policy
1375
1511
 
1376
1512
  Usage:
@@ -1397,7 +1533,7 @@ Reads one markdown file, finds its permissions section, and prints a DRAFT
1397
1533
  \`\`\`yaml approval-policy block from a fixed, ordered keyword table.
1398
1534
  THE DRAFT AUTHORIZES NOTHING: this verb never writes APPROVAL.md, never logs and
1399
1535
  never attests. Fail closed: a bullet the table cannot place is kept verbatim.
1400
- "What I value"-style headings become a DRAFT values fence, all under \`wants\`.
1536
+ "What I value"-style headings become a DRAFT values fence, all under \`like\`.
1401
1537
 
1402
1538
  JSON shape (stdout, one object):
1403
1539
  {"ok":true,"source":"<path>","out":"<path>"|null,
@@ -1553,8 +1689,8 @@ Flags:
1553
1689
  --json / -h, --help machine-readable output / this text
1554
1690
 
1555
1691
  Prints the optional \`\`\`yaml approval-values block of APPROVAL.md: what the
1556
- operator loves, likes and dislikes, what they want from you as behaviour, and
1557
- how they read and answer. EVERY FORM CARRIES THE LABEL: this is GUIDANCE and
1692
+ operator loves, likes (including what they ask of you as behaviour) and
1693
+ dislikes, and how they read and answer. EVERY FORM CARRIES THE LABEL: this is GUIDANCE and
1558
1694
  never policy. It grants nothing, forbids nothing and changes no verdict; what
1559
1695
  you MAY do is the policy block, answered by \`approval policy check\`.
1560
1696
 
@@ -1622,15 +1758,18 @@ Usage:
1622
1758
  [--policy <path>] [--dir <path>]
1623
1759
  [--log <path>] [--api-base <url>]
1624
1760
  [--poll-timeout <seconds>] [--json]
1625
- approval channel telegram health [--json]
1761
+ approval channel telegram health [--dir <path>] [--log <path>] [--json]
1626
1762
 
1627
1763
  Configuration is ENVIRONMENT-ONLY: APPROVAL_TG_TOKEN holds the bot token and
1628
- APPROVAL_TG_CHAT the approver chat id. APPROVAL.md carries only those variable
1629
- NAMES, and there is no flag that would put a bot token into a shell history.
1764
+ APPROVAL_TG_CHAT the approver chat id by default. APPROVAL.md carries only those
1765
+ variable NAMES — a second gate on one machine declares a pair of its own — and
1766
+ there is no flag that would put a bot token into a shell history.
1630
1767
 
1631
1768
  Anyone in the configured chat can approve as the actor this process was started
1632
1769
  with, so the chat's membership is part of your trust boundary. Use a private
1633
- chat with the bot.
1770
+ chat with the bot — or map senders: approvers.<id>.senders.telegram: "<id>"
1771
+ records each decision against the person that Telegram account is attested to
1772
+ and refuses a tap from an account the policy does not name.
1634
1773
 
1635
1774
  ${EXIT_CODES_POINTER}
1636
1775
  ${JSON_ERRORS}
@@ -1649,7 +1788,7 @@ Flags:
1649
1788
  --as human:<id> the approver every decision is recorded against. REQUIRED
1650
1789
  --payloads <f> OPTIONAL OVERRIDE: JSON file of action key -> payload
1651
1790
  --policy <p> / --dir <p> / --log <p> the policy, its dir, the log written to
1652
- --api-base <url> / --poll-timeout <s> Bot API base / long-poll seconds (25)
1791
+ --api-base <url> / --poll-timeout <s> / --allow-cross-instance Bot API base / long-poll seconds (25) / start on another instance's bot
1653
1792
  -h, --help this text
1654
1793
  Config is ENVIRONMENT-ONLY and the policy names the variables. Delivery is per cycle;
1655
1794
  a new request reaches the phone without restart. THE TOKEN IS PRINTED HERE, NEVER SENT TO TELEGRAM.
@@ -1738,7 +1877,7 @@ Flags (every "daemon run" flag, unchanged, plus):
1738
1877
  --payloads <f> / --payload-dir <d> payload overrides: telegram / web
1739
1878
  --api-base <url> / --poll-timeout <s> Bot API base / long-poll seconds
1740
1879
  --port <n> queue-page port. Precedence: --port, channels.web.port
1741
- --no-telegram / --no-web leave that channel out of this process
1880
+ --no-telegram / --no-web / --allow-cross-instance leave that channel out / start on another instance's bot
1742
1881
  --no-gloss / --restart-backoff <d> drop gloss / first retry wait
1743
1882
  --gloss-provider <p> / --gloss-model <id> choose claude|codex (default claude); Codex requires model; no fallback
1744
1883
  -h, --help this text
@@ -1755,7 +1894,7 @@ ${why("up")}`;
1755
1894
  // ---------------------------------------------------------------------------
1756
1895
  /** One line, not a paragraph: the rest of the reasoning is in the reference. */
1757
1896
  const VAULT_NO_GET = `THERE IS NO "approval vault get": a credential's only sanctioned journey is from
1758
- the vault into an adapter, inside the verified-token window.`;
1897
+ the vault into an adapter, inside the verified execution window.`;
1759
1898
  export const VAULT_HELP = `approval vault — the encrypted credential store adapters read from
1760
1899
 
1761
1900
  Usage:
@@ -1849,39 +1988,39 @@ JSON shape: docs/cli-reference.md#vault-remove
1849
1988
  ${EXIT_CODES_POINTER}
1850
1989
  ${JSON_ERRORS}
1851
1990
  ${why("vault-remove")}`;
1852
- export const ADAPTER_HELP = `approval adapter — execute an approved action through a side-effect adapter
1991
+ export const ADAPTER_HELP = `approval adapter — execute an action through a side-effect adapter
1853
1992
 
1854
1993
  Usage:
1855
- approval adapter email|agentmail <action-key> --token <t> --payload <file|->
1856
- [--as human:<id>|agent:<id>] [--vault <path>]
1857
- [--policy|--dir|--log <path>] [--timeout <ms>] [--json]
1994
+ approval adapter email|agentmail|zzz <action-key> [--token <t>] --payload <file|->
1995
+ [--as human:<id>|agent:<id>] [--vault <path>] [--policy|--dir|--log <path>]
1996
+ [--timeout <ms>] [--json]
1858
1997
 
1859
1998
  Adapters:
1860
- email send one RFC 5322 message over SMTP, for actions declared under
1861
- communicate.email.external (SPEC.md §6.1's canonical example)
1862
- agentmail send the same class over the AgentMail API: a direct message, or
1863
- a draft the agent composed, re-read and refused if it drifted
1999
+ email send SMTP for communicate.email.external (SPEC.md §6.1)
2000
+ agentmail send that class through AgentMail, directly or from a re-read draft
2001
+ zzz create a thread or reply for communicate.zzz.external
2002
+
2003
+ An adapter is the HARD BOUNDARY of SPEC.md §10.4: it holds credentials while the
2004
+ runtime checks the payload and attested policy. Manual and selected-live actions
2005
+ require a valid, single-use --token bound to the action and payload. An explicitly
2006
+ policy-authorized nonmanual action has no token; its process must already hold the
2007
+ vault passphrase, and the token-scoped .approval/env fallback stays unavailable.
1864
2008
 
1865
- An adapter is the HARD BOUNDARY of SPEC.md §10.4: it holds the credentials and
1866
- refuses to act without a valid, unexpired, single-use execution token bound to
1867
- the action's idempotency_key AND its payload_hash. The runtime, not the adapter,
1868
- owns the sequence: recompute the hash, resolve the credentials the adapter
1869
- declared, run its pre-token check, verify and consume the token, append
1870
- execution.started, call the adapter, append the outcome. The two steps before
1871
- the spend refuse without appending or spending, so the token stays live.
2009
+ A no-token supervised-live call runs intake; selected/unavailable draws stop before
2010
+ credentials. An unselected draw proceeds. Existing approval cycles are not redrawn.
1872
2011
 
1873
- ${EXIT_CODES_POINTER} (5 when no valid token was presented; 1 for every refusal)
2012
+ ${EXIT_CODES_POINTER} (5 when a manual path needs a token; 1 for every refusal)
1874
2013
  ${JSON_ERRORS}
1875
2014
  ${why("adapter")}`;
1876
2015
  export const ADAPTER_EMAIL_HELP = `approval adapter email — send one approved message over SMTP
1877
2016
 
1878
2017
  Usage:
1879
- approval adapter email <action-key> --token <t> --payload <file|->
2018
+ approval adapter email <action-key> [--token <t>] --payload <file|->
1880
2019
  [--as <id>] [--vault <path>] [--policy <path>]
1881
2020
  [--dir <path>] [--log <path>] [--timeout <ms>] [--json]
1882
2021
 
1883
2022
  Flags:
1884
- --token <t> the single-use token "approval grant" printed. REQUIRED
2023
+ --token <t> REQUIRED for manual or selected-live; omit on authorized nonmanual
1885
2024
  --payload <file|-> the JSON payload the grant bound to. REQUIRED (a body on
1886
2025
  a command line is a body in the shell history)
1887
2026
  --as <id> / --vault <path> executing identity / the SMTP credential store
@@ -1894,17 +2033,17 @@ it, and a non-ASCII body goes quoted-printable. The VAULT holds smtp.host,
1894
2033
  smtp.port, smtp.security, smtp.user, smtp.password; failure codes add smtp-<NNN>.
1895
2034
 
1896
2035
  JSON shapes and failure codes: docs/cli-reference.md#adapter-email
1897
- ${EXIT_CODES_POINTER} (5 when no valid token was presented; 1 for every refusal)
2036
+ ${EXIT_CODES_POINTER} (5 when a manual path needs a token; 1 for every refusal)
1898
2037
  ${JSON_ERRORS}
1899
2038
  ${why("adapter-email")}`;
1900
2039
  export const ADAPTER_AGENTMAIL_HELP = `approval adapter agentmail — send one approved message through AgentMail
1901
2040
 
1902
2041
  Usage:
1903
- approval adapter agentmail <action-key> --token <t> --payload <file|->
2042
+ approval adapter agentmail <action-key> [--token <t>] --payload <file|->
1904
2043
  [--as <id>] [--vault|--policy|--dir|--log <p>] [--timeout <ms>] [--json]
1905
2044
 
1906
2045
  Flags:
1907
- --token <t> / --payload <file|-> the token and the bytes. BOTH REQUIRED
2046
+ --token <t> / --payload <file|-> token: manual or selected-live; payload: always
1908
2047
  --as <id> / --vault <p> / --policy <p> / --dir <p> / --log <p> as email
1909
2048
  --timeout <ms> / --json / -h, --help 15000 / machine-readable / this text
1910
2049
 
@@ -1918,9 +2057,33 @@ TWO PAYLOAD MODES, told apart by shape and never inferred between:
1918
2057
  The VAULT holds agentmail.inbox_id and agentmail.api_key, and that key is the one
1919
2058
  WITH draft_send and message_send; the agent's own key must not have them.
1920
2059
 
1921
- ${EXIT_CODES_POINTER} (5 when no valid token was presented; 1 for every refusal)
2060
+ ${EXIT_CODES_POINTER} (5 when a manual path needs a token; 1 for every refusal)
1922
2061
  ${JSON_ERRORS}
1923
2062
  ${why("adapter-agentmail")}`;
2063
+ export const ADAPTER_ZZZ_HELP = `approval adapter zzz — send one approved zzz.bot message
2064
+
2065
+ Usage:
2066
+ approval adapter zzz <action-key> [--token <t>] --payload <file|->
2067
+ [--as <id>] [--vault|--policy|--dir|--log <p>] [--timeout <ms>] [--json]
2068
+
2069
+ The tagged payload chooses create_thread or create_reply and production or
2070
+ preview. Both destinations are fixed in the adapter; the payload cannot supply
2071
+ an arbitrary URL. The runtime binds the complete payload, including metadata,
2072
+ tags and references, and derives ZZZ's retry-safe Idempotency-Key from the
2073
+ action key and payload hash. Actions use communicate.zzz.external. The VAULT
2074
+ holds zzz.agent_token.
2075
+
2076
+ --token is required for manual or selected-live and omitted for explicitly
2077
+ authorized nonmanual execution; then the process must already hold the passphrase.
2078
+
2079
+ A public-room write needs an invited token with write scope. A private-room
2080
+ write also needs current room membership and accepted, unexpired approval.md
2081
+ workflow evidence. zzz.bot intentionally hides missing private access as 404.
2082
+
2083
+ JSON shapes and failure codes: docs/cli-reference.md#adapter-zzz
2084
+ ${EXIT_CODES_POINTER} (5 when a manual path needs a token; 1 for every refusal)
2085
+ ${JSON_ERRORS}
2086
+ ${why("adapter-zzz")}`;
1924
2087
  export const ENV_HELP = `approval env — resolve .approval/env into an export block for your shell
1925
2088
 
1926
2089
  Usage:
@@ -1948,14 +2111,14 @@ ${why("env")}`;
1948
2111
  export const SETUP_HELP = `approval setup — interactive configuration (SPEC.md §5.2, §10.1)
1949
2112
 
1950
2113
  Usage:
1951
- approval setup identity|vault|sampling|checkpoint [--as human:<id>] …
2114
+ approval setup identity|vault|sampling|sender-key|checkpoint [--as human:<id>] …
1952
2115
  approval setup channel|adapter <name> [--api-base <url>] [--as human:<id>] …
1953
2116
  approval setup service [--platform launchd|systemd] [--uninstall] …
1954
-
1955
2117
  Subcommands:
1956
2118
  identity declare who the human is (APPROVAL_HUMAN); not human-only
1957
2119
  vault mint a vault passphrase, store it, and record where it lives
1958
2120
  sampling mint the audit sampling secret and print the policy line for it
2121
+ sender-key mint the key that hashes sender ids; --id prints one mapping line
1959
2122
  checkpoint mint the Ed25519 key you sign the log's head with (--rotate/--retire)
1960
2123
  channel configure one CHANNEL's transport credential (OS keystore)
1961
2124
  adapter fill the VAULT with one ADAPTER's credentials, from its manifest
@@ -2028,6 +2191,28 @@ does not edit an attested policy file: it prints the block to add and the
2028
2191
  ${EXIT_CODES_POINTER}
2029
2192
  ${JSON_ERRORS}
2030
2193
  ${why("setup-sampling")}`;
2194
+ export const SETUP_SENDER_KEY_HELP = `approval setup sender-key — mint the key that hashes sender ids (HUMAN-ONLY)
2195
+
2196
+ Usage:
2197
+ approval setup sender-key [--as human:<id>] [--log <path>] [--dir <path>]
2198
+ approval setup sender-key --id <account-id> [--log <path>] [--json]
2199
+
2200
+ Bare, it mints the operator-held key that turns a channel account id into the
2201
+ value an approvers[id].senders block carries, stores it as approval-sender-key,
2202
+ and writes its source line. It edits no policy file (APRV-370).
2203
+
2204
+ WITH --id it mints and stores nothing: it reads the key from the environment,
2205
+ prints the hmac-sha256:<hex> for that account, and prints the senders line and
2206
+ the paste-ready proposal pair around it. Run \`eval "$(approval env)"\` first.
2207
+ That is the one setup path that needs no terminal.
2208
+
2209
+ A LISTENER THAT HOLDS NO KEY UNDER A KEYED MAPPING REFUSES EVERY DECISION on
2210
+ that channel (sender-key-unavailable), never falling back to a raw comparison.
2211
+ The key authenticates nothing; losing it costs the ability to resolve accounts.
2212
+
2213
+ ${EXIT_CODES_POINTER}
2214
+ ${JSON_ERRORS}
2215
+ ${why("setup-sender-key")}`;
2031
2216
  export const SETUP_CHECKPOINT_HELP = `approval setup checkpoint — mint the log-checkpoint key (HUMAN-ONLY)
2032
2217
 
2033
2218
  Usage:
@@ -2059,10 +2244,11 @@ Usage:
2059
2244
  [--policy <path>]
2060
2245
 
2061
2246
  Known adapters:
2062
- email the SMTP settings \`approval adapter email\` reads: smtp.host,
2063
- smtp.port, smtp.security, smtp.user, smtp.password
2247
+ email smtp.host, smtp.port, smtp.security, smtp.user, smtp.password
2064
2248
  agentmail the two values \`approval adapter agentmail\` reads:
2065
2249
  agentmail.inbox_id and agentmail.api_key
2250
+ zzz the invited write credential \`approval adapter zzz\` reads:
2251
+ zzz.agent_token
2066
2252
 
2067
2253
  Asks for each credential the named adapter DECLARES, validates every answer with
2068
2254
  the adapter's own rules, stores them in .approval/vault.enc, and offers to prove
@@ -2081,7 +2267,7 @@ Usage:
2081
2267
  approval setup adapter email [--as human:<id>] [--log <path>] [--dir <path>]
2082
2268
  [--policy <path>]
2083
2269
 
2084
- The five names the email adapter reads inside the verified-token window:
2270
+ The five names the email adapter reads inside the verified execution window:
2085
2271
 
2086
2272
  smtp.host the submission server
2087
2273
  smtp.port 587 for STARTTLS submission, 465 for implicit TLS
@@ -2104,7 +2290,7 @@ Usage:
2104
2290
  approval setup adapter agentmail [--as human:<id>] [--log <path>]
2105
2291
  [--dir <path>] [--policy <path>]
2106
2292
 
2107
- The two names the AgentMail adapter reads inside the verified-token window:
2293
+ The two names the AgentMail adapter reads inside the verified execution window:
2108
2294
  agentmail.inbox_id the inbox this runtime sends from; the inbox IS the sender
2109
2295
  agentmail.api_key the key carrying draft_send and message_send, no echo
2110
2296
 
@@ -2122,6 +2308,23 @@ says so rather than claiming the key can send. A FAILED PROBE KEEPS THE VALUES:
2122
2308
  ${EXIT_CODES_POINTER} (1 means AgentMail refused, or the vault would not open)
2123
2309
  ${JSON_ERRORS}
2124
2310
  ${why("setup-adapter-agentmail")}`;
2311
+ export const SETUP_ADAPTER_ZZZ_HELP = `approval setup adapter zzz — the zzz.bot credential (HUMAN-ONLY)
2312
+
2313
+ Usage:
2314
+ approval setup adapter zzz [--as human:<id>] [--log <path>]
2315
+ [--dir <path>] [--policy <path>]
2316
+
2317
+ The vault name is zzz.agent_token: an invited principal token with write scope.
2318
+ Keep it out of the agent environment, so publication remains behind the adapter.
2319
+
2320
+ THE PROBE POSTS NOTHING. It performs one authenticated GET /api/v1/rooms. A
2321
+ success proves only that zzz.bot accepted the active credential. It does not
2322
+ prove write scope, room membership, or private-room workflow evidence; zzz.bot
2323
+ checks those when the approved message is sent.
2324
+
2325
+ ${EXIT_CODES_POINTER} (1 means zzz.bot refused, or the vault would not open)
2326
+ ${JSON_ERRORS}
2327
+ ${why("setup-adapter-zzz")}`;
2125
2328
  export const SETUP_CHANNEL_HELP = `approval setup channel — configure one channel's transport credential (HUMAN-ONLY)
2126
2329
 
2127
2330
  Usage:
@@ -2190,6 +2393,30 @@ ${why("setup-service")}`;
2190
2393
  // ---------------------------------------------------------------------------
2191
2394
  // The MCP wrapper (APRV-87)
2192
2395
  // ---------------------------------------------------------------------------
2396
+ export const CODEX_HELP = `approval codex — prepare a constrained Codex host and broker its workspace writes
2397
+
2398
+ Usage:
2399
+ approval codex prepare --instance <id> --workspace <abs> --primary <abs>
2400
+ --install-root <abs> --output <new-dir> --codex <abs> --node <abs> [--json]
2401
+ approval codex setup --check <bundle-dir> [--json]
2402
+ approval codex doctor --strict --manifest <abs> [--json]
2403
+ approval codex apply --manifest <abs> --proposal <file> [--json]
2404
+ [--token <class>=<token>]... [--require-exclusive-custody]
2405
+ approval codex serve|recover --manifest <abs> [--json]
2406
+ approval codex start --manifest <abs> [--timeout <dur>] [--json] [-- <cmd>...]
2407
+
2408
+ prepare, setup --check and doctor are the inert half: a review bundle, its exact
2409
+ file set and hashes, and host custody, executing no manifest binary. apply is the
2410
+ BROKER: a bounded create/replace/delete/move proposal, ONE ACTION PER PATH CLASS,
2411
+ gate-authorized, every leg started before any byte moves, then staged, journaled
2412
+ and applied under a workspace lock; the MANIFEST supplies actor, root, policy and
2413
+ log. recover READS a retained journal, repairing nothing. serve is EXACTLY ONE MCP
2414
+ tool, separate from \`approval mcp serve\`. start CONFINES a shell: one disposable
2415
+ writable path, read-only gate and workspace, no credentials, no egress, NO OPT-OUT.
2416
+
2417
+ ${EXIT_CODES_POINTER} (1: the boundary is absent, invalid, or the workspace mixed)
2418
+ ${JSON_ERRORS}
2419
+ why: docs/cli-reference.md#constrained-codex-preparation`;
2193
2420
  export const MCP_HELP = `approval mcp serve — the MCP wrapper of SPEC.md §10.5 (FOREGROUND)
2194
2421
 
2195
2422
  Usage: