approval-md 0.2.0 → 0.4.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 (378) hide show
  1. package/README.md +85 -877
  2. package/SPEC.md +150 -19
  3. package/cli.js +66 -7
  4. package/dist/src/adapters/smtp.d.ts +18 -0
  5. package/dist/src/adapters/smtp.js +24 -3
  6. package/dist/src/adapters/smtp.js.map +1 -1
  7. package/dist/src/channels/contract.d.ts +53 -1
  8. package/dist/src/channels/contract.js +304 -7
  9. package/dist/src/channels/contract.js.map +1 -1
  10. package/dist/src/channels/relay-server.d.ts +90 -0
  11. package/dist/src/channels/relay-server.js +295 -0
  12. package/dist/src/channels/relay-server.js.map +1 -0
  13. package/dist/src/channels/relay.d.ts +273 -0
  14. package/dist/src/channels/relay.js +564 -0
  15. package/dist/src/channels/relay.js.map +1 -0
  16. package/dist/src/channels/tagging.js +6 -1
  17. package/dist/src/channels/tagging.js.map +1 -1
  18. package/dist/src/channels/telegram-webhook.d.ts +273 -0
  19. package/dist/src/channels/telegram-webhook.js +536 -0
  20. package/dist/src/channels/telegram-webhook.js.map +1 -0
  21. package/dist/src/channels/telegram.d.ts +394 -12
  22. package/dist/src/channels/telegram.js +621 -68
  23. package/dist/src/channels/telegram.js.map +1 -1
  24. package/dist/src/channels/web.d.ts +9 -0
  25. package/dist/src/channels/web.js +17 -0
  26. package/dist/src/channels/web.js.map +1 -1
  27. package/dist/src/cli/amend.js +564 -34
  28. package/dist/src/cli/amend.js.map +1 -1
  29. package/dist/src/cli/attest.d.ts +9 -0
  30. package/dist/src/cli/attest.js +177 -13
  31. package/dist/src/cli/attest.js.map +1 -1
  32. package/dist/src/cli/channel-relay.d.ts +108 -0
  33. package/dist/src/cli/channel-relay.js +334 -0
  34. package/dist/src/cli/channel-relay.js.map +1 -0
  35. package/dist/src/cli/channel-telegram-webhook.d.ts +273 -0
  36. package/dist/src/cli/channel-telegram-webhook.js +709 -0
  37. package/dist/src/cli/channel-telegram-webhook.js.map +1 -0
  38. package/dist/src/cli/channel-telegram.d.ts +347 -28
  39. package/dist/src/cli/channel-telegram.js +763 -28
  40. package/dist/src/cli/channel-telegram.js.map +1 -1
  41. package/dist/src/cli/channel.d.ts +10 -1
  42. package/dist/src/cli/channel.js +14 -1
  43. package/dist/src/cli/channel.js.map +1 -1
  44. package/dist/src/cli/codex-bridge.d.ts +819 -0
  45. package/dist/src/cli/codex-bridge.js +1607 -0
  46. package/dist/src/cli/codex-bridge.js.map +1 -0
  47. package/dist/src/cli/codex.d.ts +1 -1
  48. package/dist/src/cli/codex.js +304 -7
  49. package/dist/src/cli/codex.js.map +1 -1
  50. package/dist/src/cli/daemon.js +41 -6
  51. package/dist/src/cli/daemon.js.map +1 -1
  52. package/dist/src/cli/doctor.d.ts +63 -0
  53. package/dist/src/cli/doctor.js +1322 -122
  54. package/dist/src/cli/doctor.js.map +1 -1
  55. package/dist/src/cli/execute.d.ts +17 -1
  56. package/dist/src/cli/execute.js +366 -22
  57. package/dist/src/cli/execute.js.map +1 -1
  58. package/dist/src/cli/exit-codes.d.ts +12 -0
  59. package/dist/src/cli/exit-codes.js +13 -0
  60. package/dist/src/cli/exit-codes.js.map +1 -1
  61. package/dist/src/cli/gate.d.ts +2 -0
  62. package/dist/src/cli/gate.js +233 -2
  63. package/dist/src/cli/gate.js.map +1 -1
  64. package/dist/src/cli/help.d.ts +14 -2
  65. package/dist/src/cli/help.js +395 -82
  66. package/dist/src/cli/help.js.map +1 -1
  67. package/dist/src/cli/hook-codex.d.ts +49 -1
  68. package/dist/src/cli/hook-codex.js +60 -1
  69. package/dist/src/cli/hook-codex.js.map +1 -1
  70. package/dist/src/cli/hook.d.ts +828 -4
  71. package/dist/src/cli/hook.js +2972 -142
  72. package/dist/src/cli/hook.js.map +1 -1
  73. package/dist/src/cli/import.js +1 -1
  74. package/dist/src/cli/import.js.map +1 -1
  75. package/dist/src/cli/init.js +16 -7
  76. package/dist/src/cli/init.js.map +1 -1
  77. package/dist/src/cli/instructions.js +24 -3
  78. package/dist/src/cli/instructions.js.map +1 -1
  79. package/dist/src/cli/log-anchor.d.ts +55 -0
  80. package/dist/src/cli/log-anchor.js +199 -60
  81. package/dist/src/cli/log-anchor.js.map +1 -1
  82. package/dist/src/cli/main.d.ts +0 -12
  83. package/dist/src/cli/main.js +56 -3
  84. package/dist/src/cli/main.js.map +1 -1
  85. package/dist/src/cli/muse.d.ts +2 -0
  86. package/dist/src/cli/muse.js +62 -0
  87. package/dist/src/cli/muse.js.map +1 -0
  88. package/dist/src/cli/payload.js +79 -1
  89. package/dist/src/cli/payload.js.map +1 -1
  90. package/dist/src/cli/policy-apply.d.ts +195 -0
  91. package/dist/src/cli/policy-apply.js +573 -0
  92. package/dist/src/cli/policy-apply.js.map +1 -0
  93. package/dist/src/cli/policy.js +14 -1
  94. package/dist/src/cli/policy.js.map +1 -1
  95. package/dist/src/cli/preflight.d.ts +151 -13
  96. package/dist/src/cli/preflight.js +398 -41
  97. package/dist/src/cli/preflight.js.map +1 -1
  98. package/dist/src/cli/sandbox.js +17 -1
  99. package/dist/src/cli/sandbox.js.map +1 -1
  100. package/dist/src/cli/scaffold.d.ts +1 -1
  101. package/dist/src/cli/scaffold.js +7 -1
  102. package/dist/src/cli/scaffold.js.map +1 -1
  103. package/dist/src/cli/serve.d.ts +53 -0
  104. package/dist/src/cli/serve.js +270 -0
  105. package/dist/src/cli/serve.js.map +1 -0
  106. package/dist/src/cli/setup-channel.d.ts +9 -0
  107. package/dist/src/cli/setup-channel.js +28 -1
  108. package/dist/src/cli/setup-channel.js.map +1 -1
  109. package/dist/src/cli/setup-common.d.ts +3 -1
  110. package/dist/src/cli/setup-common.js +3 -2
  111. package/dist/src/cli/setup-common.js.map +1 -1
  112. package/dist/src/cli/setup.d.ts +2 -0
  113. package/dist/src/cli/setup.js +94 -2
  114. package/dist/src/cli/setup.js.map +1 -1
  115. package/dist/src/cli/up.js +134 -51
  116. package/dist/src/cli/up.js.map +1 -1
  117. package/dist/src/cli/values.js +3 -4
  118. package/dist/src/cli/values.js.map +1 -1
  119. package/dist/src/cli/verb-registry.d.ts +2 -0
  120. package/dist/src/cli/verb-registry.js +510 -47
  121. package/dist/src/cli/verb-registry.js.map +1 -1
  122. package/dist/src/cli/wordmark.d.ts +2 -2
  123. package/dist/src/cli/wordmark.js +2 -2
  124. package/dist/src/codex/broker.d.ts +229 -0
  125. package/dist/src/codex/broker.js +548 -0
  126. package/dist/src/codex/broker.js.map +1 -0
  127. package/dist/src/codex/runner.d.ts +178 -0
  128. package/dist/src/codex/runner.js +231 -0
  129. package/dist/src/codex/runner.js.map +1 -0
  130. package/dist/src/codex/serve.d.ts +56 -0
  131. package/dist/src/codex/serve.js +98 -0
  132. package/dist/src/codex/serve.js.map +1 -0
  133. package/dist/src/codex/workspace-commit.d.ts +219 -0
  134. package/dist/src/codex/workspace-commit.js +549 -0
  135. package/dist/src/codex/workspace-commit.js.map +1 -0
  136. package/dist/src/core/advance-cycle.d.ts +51 -0
  137. package/dist/src/core/advance-cycle.js +66 -2
  138. package/dist/src/core/advance-cycle.js.map +1 -1
  139. package/dist/src/core/agents-md.d.ts +20 -18
  140. package/dist/src/core/agents-md.js +33 -31
  141. package/dist/src/core/agents-md.js.map +1 -1
  142. package/dist/src/core/attest-bootstrap.d.ts +95 -0
  143. package/dist/src/core/attest-bootstrap.js +135 -0
  144. package/dist/src/core/attest-bootstrap.js.map +1 -0
  145. package/dist/src/core/attest.d.ts +234 -2
  146. package/dist/src/core/attest.js +342 -7
  147. package/dist/src/core/attest.js.map +1 -1
  148. package/dist/src/core/audit.d.ts +73 -3
  149. package/dist/src/core/audit.js +65 -5
  150. package/dist/src/core/audit.js.map +1 -1
  151. package/dist/src/core/channel-lease.d.ts +322 -0
  152. package/dist/src/core/channel-lease.js +663 -0
  153. package/dist/src/core/channel-lease.js.map +1 -0
  154. package/dist/src/core/channel-owner.d.ts +213 -0
  155. package/dist/src/core/channel-owner.js +358 -0
  156. package/dist/src/core/channel-owner.js.map +1 -0
  157. package/dist/src/core/command-class.d.ts +205 -0
  158. package/dist/src/core/command-class.js +1433 -28
  159. package/dist/src/core/command-class.js.map +1 -1
  160. package/dist/src/core/commit-guard.d.ts +272 -0
  161. package/dist/src/core/commit-guard.js +424 -0
  162. package/dist/src/core/commit-guard.js.map +1 -0
  163. package/dist/src/core/daemon-actor.d.ts +45 -0
  164. package/dist/src/core/daemon-actor.js +54 -0
  165. package/dist/src/core/daemon-actor.js.map +1 -0
  166. package/dist/src/core/daemon-host.d.ts +178 -0
  167. package/dist/src/core/daemon-host.js +228 -0
  168. package/dist/src/core/daemon-host.js.map +1 -0
  169. package/dist/src/core/daemon-identity.d.ts +238 -0
  170. package/dist/src/core/daemon-identity.js +252 -0
  171. package/dist/src/core/daemon-identity.js.map +1 -0
  172. package/dist/src/core/dark-session.d.ts +109 -8
  173. package/dist/src/core/dark-session.js +266 -82
  174. package/dist/src/core/dark-session.js.map +1 -1
  175. package/dist/src/core/decision-refusal.d.ts +23 -2
  176. package/dist/src/core/decision-refusal.js +24 -2
  177. package/dist/src/core/decision-refusal.js.map +1 -1
  178. package/dist/src/core/env-file.d.ts +5 -0
  179. package/dist/src/core/env-file.js +60 -1
  180. package/dist/src/core/env-file.js.map +1 -1
  181. package/dist/src/core/execute.d.ts +15 -2
  182. package/dist/src/core/execute.js +15 -2
  183. package/dist/src/core/execute.js.map +1 -1
  184. package/dist/src/core/gate.d.ts +392 -6
  185. package/dist/src/core/gate.js +852 -24
  186. package/dist/src/core/gate.js.map +1 -1
  187. package/dist/src/core/gesture-refusal.d.ts +166 -0
  188. package/dist/src/core/gesture-refusal.js +188 -0
  189. package/dist/src/core/gesture-refusal.js.map +1 -0
  190. package/dist/src/core/harness-version.d.ts +128 -4
  191. package/dist/src/core/harness-version.js +181 -12
  192. package/dist/src/core/harness-version.js.map +1 -1
  193. package/dist/src/core/harness-wait.d.ts +82 -3
  194. package/dist/src/core/harness-wait.js +89 -3
  195. package/dist/src/core/harness-wait.js.map +1 -1
  196. package/dist/src/core/instance.d.ts +59 -2
  197. package/dist/src/core/instance.js +113 -0
  198. package/dist/src/core/instance.js.map +1 -1
  199. package/dist/src/core/log-subscribe.d.ts +21 -0
  200. package/dist/src/core/log-subscribe.js +16 -6
  201. package/dist/src/core/log-subscribe.js.map +1 -1
  202. package/dist/src/core/log-write-layer.d.ts +55 -0
  203. package/dist/src/core/log-write-layer.js +91 -0
  204. package/dist/src/core/log-write-layer.js.map +1 -0
  205. package/dist/src/core/log.d.ts +89 -22
  206. package/dist/src/core/log.js +197 -19
  207. package/dist/src/core/log.js.map +1 -1
  208. package/dist/src/core/payload-census.d.ts +51 -0
  209. package/dist/src/core/payload-census.js +125 -2
  210. package/dist/src/core/payload-census.js.map +1 -1
  211. package/dist/src/core/payload-store.d.ts +31 -0
  212. package/dist/src/core/payload-store.js +113 -8
  213. package/dist/src/core/payload-store.js.map +1 -1
  214. package/dist/src/core/payload.d.ts +18 -3
  215. package/dist/src/core/payload.js +20 -4
  216. package/dist/src/core/payload.js.map +1 -1
  217. package/dist/src/core/policy-diff.d.ts +10 -0
  218. package/dist/src/core/policy-diff.js +10 -2
  219. package/dist/src/core/policy-diff.js.map +1 -1
  220. package/dist/src/core/policy-explain.d.ts +17 -1
  221. package/dist/src/core/policy-explain.js +48 -1
  222. package/dist/src/core/policy-explain.js.map +1 -1
  223. package/dist/src/core/policy-load.d.ts +65 -1
  224. package/dist/src/core/policy-load.js +21 -3
  225. package/dist/src/core/policy-load.js.map +1 -1
  226. package/dist/src/core/policy-match.d.ts +81 -0
  227. package/dist/src/core/policy-match.js +87 -0
  228. package/dist/src/core/policy-match.js.map +1 -1
  229. package/dist/src/core/policy-proposal.d.ts +75 -0
  230. package/dist/src/core/policy-proposal.js +110 -4
  231. package/dist/src/core/policy-proposal.js.map +1 -1
  232. package/dist/src/core/protected-path-guard.d.ts +117 -4
  233. package/dist/src/core/protected-path-guard.js +362 -48
  234. package/dist/src/core/protected-path-guard.js.map +1 -1
  235. package/dist/src/core/question-preempted.d.ts +141 -0
  236. package/dist/src/core/question-preempted.js +152 -0
  237. package/dist/src/core/question-preempted.js.map +1 -0
  238. package/dist/src/core/read-scope.d.ts +182 -0
  239. package/dist/src/core/read-scope.js +256 -0
  240. package/dist/src/core/read-scope.js.map +1 -0
  241. package/dist/src/core/run-payload.d.ts +160 -0
  242. package/dist/src/core/run-payload.js +304 -0
  243. package/dist/src/core/run-payload.js.map +1 -0
  244. package/dist/src/core/sandbox.d.ts +81 -0
  245. package/dist/src/core/sandbox.js +190 -1
  246. package/dist/src/core/sandbox.js.map +1 -1
  247. package/dist/src/core/sender-identity.d.ts +501 -0
  248. package/dist/src/core/sender-identity.js +609 -0
  249. package/dist/src/core/sender-identity.js.map +1 -0
  250. package/dist/src/core/shlex.d.ts +102 -0
  251. package/dist/src/core/shlex.js +159 -0
  252. package/dist/src/core/shlex.js.map +1 -0
  253. package/dist/src/core/state.d.ts +52 -1
  254. package/dist/src/core/state.js +52 -6
  255. package/dist/src/core/state.js.map +1 -1
  256. package/dist/src/core/telegram-config.d.ts +79 -0
  257. package/dist/src/core/telegram-config.js +108 -0
  258. package/dist/src/core/telegram-config.js.map +1 -1
  259. package/dist/src/core/values.d.ts +18 -8
  260. package/dist/src/core/values.js +36 -1
  261. package/dist/src/core/values.js.map +1 -1
  262. package/dist/src/core/verify.d.ts +23 -1
  263. package/dist/src/core/verify.js +20 -2
  264. package/dist/src/core/verify.js.map +1 -1
  265. package/dist/src/daemon/advance.d.ts +10 -0
  266. package/dist/src/daemon/advance.js +25 -4
  267. package/dist/src/daemon/advance.js.map +1 -1
  268. package/dist/src/daemon/audit.d.ts +80 -5
  269. package/dist/src/daemon/audit.js +126 -6
  270. package/dist/src/daemon/audit.js.map +1 -1
  271. package/dist/src/daemon/daemon.d.ts +174 -2
  272. package/dist/src/daemon/daemon.js +307 -7
  273. package/dist/src/daemon/daemon.js.map +1 -1
  274. package/dist/src/daemon/git-evidence.d.ts +2 -2
  275. package/dist/src/daemon/git-evidence.js +1 -1
  276. package/dist/src/daemon/projection.d.ts +13 -2
  277. package/dist/src/daemon/projection.js +39 -6
  278. package/dist/src/daemon/projection.js.map +1 -1
  279. package/dist/src/mcp/server.d.ts +39 -3
  280. package/dist/src/mcp/server.js +30 -3
  281. package/dist/src/mcp/server.js.map +1 -1
  282. package/dist/src/muse/server.d.ts +16 -0
  283. package/dist/src/muse/server.js +238 -0
  284. package/dist/src/muse/server.js.map +1 -0
  285. package/dist/src/serve/archive.d.ts +158 -0
  286. package/dist/src/serve/archive.js +354 -0
  287. package/dist/src/serve/archive.js.map +1 -0
  288. package/dist/src/serve/arguments.d.ts +93 -0
  289. package/dist/src/serve/arguments.js +228 -0
  290. package/dist/src/serve/arguments.js.map +1 -0
  291. package/dist/src/serve/credentials.d.ts +91 -0
  292. package/dist/src/serve/credentials.js +143 -0
  293. package/dist/src/serve/credentials.js.map +1 -0
  294. package/dist/src/serve/follow.d.ts +86 -0
  295. package/dist/src/serve/follow.js +101 -0
  296. package/dist/src/serve/follow.js.map +1 -0
  297. package/dist/src/serve/hook-thread.d.ts +134 -0
  298. package/dist/src/serve/hook-thread.js +333 -0
  299. package/dist/src/serve/hook-thread.js.map +1 -0
  300. package/dist/src/serve/hook-worker.d.ts +134 -0
  301. package/dist/src/serve/hook-worker.js +173 -0
  302. package/dist/src/serve/hook-worker.js.map +1 -0
  303. package/dist/src/serve/server.d.ts +412 -0
  304. package/dist/src/serve/server.js +1251 -0
  305. package/dist/src/serve/server.js.map +1 -0
  306. package/docs/README-extended.md +766 -0
  307. package/docs/cli-reference.md +2563 -73
  308. package/docs/codex-enforced-session.md +75 -2
  309. package/docs/codex-workspace-broker.md +118 -0
  310. package/package.json +6 -2
  311. package/schema/event.schema.json +595 -9
  312. package/schema/fixtures/event/invalid/approval-granted-sender-hashed-false.json +20 -0
  313. package/schema/fixtures/event/invalid/approval-granted-sender-hashed-raw-id.json +20 -0
  314. package/schema/fixtures/event/invalid/audit-gesture-refused-human-actor.json +16 -0
  315. package/schema/fixtures/event/invalid/audit-gesture-refused-no-actor-no-sender.json +15 -0
  316. package/schema/fixtures/event/invalid/audit-gesture-refused-unknown-gesture.json +16 -0
  317. package/schema/fixtures/event/invalid/audit-question-preempted-agent-actor.json +16 -0
  318. package/schema/fixtures/event/invalid/audit-question-preempted-no-question-id.json +16 -0
  319. package/schema/fixtures/event/invalid/audit-question-preempted-unknown-source.json +15 -0
  320. package/schema/fixtures/event/invalid/daemon-id-malformed.json +15 -0
  321. package/schema/fixtures/event/invalid/execution-started-truncated-policy-sha256.json +18 -0
  322. package/schema/fixtures/event/invalid/gate-path-signed-off-absolute-path.json +14 -0
  323. package/schema/fixtures/event/invalid/gate-path-signed-off-agent-actor.json +14 -0
  324. package/schema/fixtures/event/invalid/gate-path-signed-off-missing-path.json +13 -0
  325. package/schema/fixtures/event/invalid/harness-cap-at-margin.json +16 -0
  326. package/schema/fixtures/event/invalid/harness-cap-fractional.json +16 -0
  327. package/schema/fixtures/event/invalid/harness-cap-negative.json +16 -0
  328. package/schema/fixtures/event/invalid/harness-cap-string.json +16 -0
  329. package/schema/fixtures/event/invalid/harness-cap-without-harness-execution.json +16 -0
  330. package/schema/fixtures/event/invalid/harness-cap-zero.json +16 -0
  331. package/schema/fixtures/event/valid/approval-granted-sender-hashed.json +20 -0
  332. package/schema/fixtures/event/valid/approval-requested-harness-cap.json +18 -0
  333. package/schema/fixtures/event/valid/audit-gesture-refused-review-note.json +21 -0
  334. package/schema/fixtures/event/valid/audit-gesture-refused-sender-key-unavailable.json +19 -0
  335. package/schema/fixtures/event/valid/audit-gesture-refused.json +19 -0
  336. package/schema/fixtures/event/valid/audit-question-preempted-no-verdict.json +16 -0
  337. package/schema/fixtures/event/valid/audit-question-preempted.json +20 -0
  338. package/schema/fixtures/event/valid/daemon-identity-declared.json +17 -0
  339. package/schema/fixtures/event/valid/daemon-identity.json +15 -0
  340. package/schema/fixtures/event/valid/execution-started-policy-sha256.json +18 -0
  341. package/schema/fixtures/event/valid/gate-path-signed-off.json +14 -0
  342. package/schema/fixtures/event/valid/harness-kind-claude-code.json +23 -0
  343. package/schema/fixtures/event/valid/harness-kind-codex.json +23 -0
  344. package/schema/fixtures/event/valid/harness-kind-cursor.json +23 -0
  345. package/schema/fixtures/event/valid/harness-kind-grok.json +23 -0
  346. package/schema/fixtures/event/valid/harness-kind-hermes.json +23 -0
  347. package/schema/fixtures/event/valid/harness-kind-muse.json +23 -0
  348. package/schema/fixtures/policy/invalid/daemons-malformed-id.json +10 -0
  349. package/schema/fixtures/policy/invalid/senders-half-keyed.json +20 -0
  350. package/schema/fixtures/policy/valid/canonical.json +1 -1
  351. package/schema/fixtures/policy/valid/daemons-allowlist.json +19 -0
  352. package/schema/fixtures/policy/valid/senders-keyed.json +24 -0
  353. package/schema/fixtures/policy-md/invalid/schema-invalid-agent-may-request.md +21 -0
  354. package/schema/fixtures/policy-md/valid/agent-may-request.md +24 -0
  355. package/schema/fixtures/policy-md/valid/canonical.md +1 -1
  356. package/schema/fixtures/policy-md/valid/with-values.md +5 -7
  357. package/schema/fixtures/values/invalid/class-shaped.json +1 -1
  358. package/schema/fixtures/values/invalid/duplicate-entry.json +1 -1
  359. package/schema/fixtures/values/invalid/non-string-item.json +1 -1
  360. package/schema/fixtures/values/invalid/over-cap.json +1 -1
  361. package/schema/fixtures/values/invalid/unknown-key.json +1 -1
  362. package/schema/fixtures/values/invalid/version-float.json +1 -0
  363. package/schema/fixtures/values/invalid/version-integer.json +1 -0
  364. package/schema/fixtures/values/invalid/version-wrong-string.json +1 -0
  365. package/schema/fixtures/values/valid/empty-lists.json +2 -3
  366. package/schema/fixtures/values/valid/full.json +5 -7
  367. package/schema/fixtures/values/valid/minimal.json +1 -1
  368. package/schema/fixtures/values-md/invalid/schema-invalid.md +5 -3
  369. package/schema/fixtures/values-md/invalid/two-blocks.md +3 -3
  370. package/schema/fixtures/values-md/invalid/unterminated.md +2 -2
  371. package/schema/fixtures/values-md/invalid/version-1.md +69 -0
  372. package/schema/fixtures/values-md/invalid/version-unquoted.md +64 -0
  373. package/schema/fixtures/values-md/invalid/yaml-error.md +2 -2
  374. package/schema/fixtures/values-md/valid/absent.md +1 -1
  375. package/schema/fixtures/values-md/valid/with-values.md +5 -7
  376. package/schema/policy.schema.json +100 -4
  377. package/schema/values.schema.json +7 -11
  378. package/schema/fixtures/values/invalid/version-string.json +0 -1
@@ -37,9 +37,12 @@
37
37
  *
38
38
  * ## Lazy expiry — the named requirement
39
39
  *
40
- * A request expires when `ts > requestTs + defaults.approval_ttl`, **whether or
41
- * not** an `approval.expired` event exists. Nothing may depend on a daemon
42
- * having run: if the expiry sweep is asleep, a late grant must still be refused.
40
+ * A request expires when `ts > requestTs + effective window`, **whether or
41
+ * not** an `approval.expired` event exists. The effective window is
42
+ * `defaults.approval_ttl`, narrowed since APRV-423 by whatever harness ceiling
43
+ * the requesting hook declared on `payload.harness_cap_ms` (a self-reported
44
+ * bound that can only shorten; see `core/harness-wait.ts`). Nothing may depend
45
+ * on a daemon having run: if the expiry sweep is asleep, a late grant must still be refused.
43
46
  * {@link requestState} therefore computes expiry two ways — from the event, and
44
47
  * lazily from the arithmetic — and treats them as equivalent.
45
48
  *
@@ -116,7 +119,7 @@ import { type ClockOptions } from "./clock.js";
116
119
  import { type HarnessProvenance } from "./harness-version.js";
117
120
  import { type AppendError, type AppendOptions, type EventRecord, type LogHead } from "./log.js";
118
121
  import { type UsdInput } from "./money.js";
119
- import { type Autonomy } from "./policy-load.js";
122
+ import { type Autonomy, type PolicyLoadResult } from "./policy-load.js";
120
123
  import { type Resolution } from "./policy-match.js";
121
124
  import { type DrawAsker, type DrawRefusalReason, type LiveDrawRecord } from "./live-draw.js";
122
125
  import { LIVE_SELECTION, type LiveSelectorUnavailableReason } from "./sampler.js";
@@ -312,6 +315,27 @@ export declare const GATE_REFUSAL_CODES: readonly [
312
315
  * decide it, under which policy hash, or against which budget.
313
316
  */
314
317
  "class-human-only",
318
+ /**
319
+ * A `harness.launch.*` class that no rule of this policy names (APRV-354).
320
+ *
321
+ * The gate's half of the hook's `hook-harness-launch-unruled`, and it exists
322
+ * so there is no second door. The hook refuses a harness launch it classified
323
+ * from a command line; this refuses one a caller DECLARES, through
324
+ * `approval register` and `approval request`, which is the other way an
325
+ * action class reaches the gate.
326
+ *
327
+ * SPEC.md §7: the family resolves only under an explicit rule, never under
328
+ * `defaults.autonomy`. What a grant of it covers is the launch and nothing
329
+ * the launched session then does, so a class arriving by upgrade rather than
330
+ * by an operator's decision would be a capability nobody chose.
331
+ *
332
+ * Evaluated in the same position as `class-human-only` and immediately above
333
+ * it: both are the policy answering before any question about registration,
334
+ * budget or approver, and this one is the narrower statement of the two — not
335
+ * "reserved to human hands" but "not spoken about at all". Nothing is
336
+ * appended, so no `approval.requested` exists for a class no rule governs.
337
+ */
338
+ "harness-launch-unruled",
315
339
  /**
316
340
  * Loop safety escalated the task to manual (SPEC.md §10.2, APRV-18): three
317
341
  * consecutive `execution.failed` events. Only the non-manual paths are
@@ -476,7 +500,51 @@ export declare const GATE_REFUSAL_CODES: readonly [
476
500
  * without an address would spend a human's decision on an authorization
477
501
  * nothing can ever open. Nothing is appended; the next attempt asks again.
478
502
  */
479
- "token-delivery-unavailable"];
503
+ "token-delivery-unavailable",
504
+ /**
505
+ * `approval propose` named a class the policy has not opened to agents
506
+ * (APRV-445, amended SPEC.md §5.2): the class is not an exact key of
507
+ * `policy.classes`, or neither that key nor a declared `<prefix>.*` family of
508
+ * it sets `agent_may_request: true`. Nothing is registered and nothing is
509
+ * appended. The repair is the operator's, a policy edit and a re-attestation;
510
+ * no retry by the agent changes it.
511
+ */
512
+ "class-not-agent-requestable",
513
+ /**
514
+ * `approval propose` / `approval start` carried a payload larger than
515
+ * {@link PROPOSE_PAYLOAD_MAX_BYTES} (APRV-445). Refused before the bytes are
516
+ * parsed or hashed; nothing is stored and nothing is appended.
517
+ */
518
+ "payload-too-large",
519
+ /**
520
+ * `approval request` (or a task FILE's registration) named a `propose:` task
521
+ * (APRV-445 refutation, S1). A proposal is requested only through `propose`,
522
+ * which re-checks the operator's opening of its class; a plain request on the
523
+ * same task would skip that check, and a file-registered `propose:` id would
524
+ * borrow the exclusions proposals get from the harness hook.
525
+ */
526
+ "task-is-proposal",
527
+ /**
528
+ * `approval start` named a task `propose` did not register (APRV-445, L9).
529
+ * `start` records executions of proposals and of nothing else; every other
530
+ * action executes through `approval run`, an adapter, or the hook.
531
+ */
532
+ "task-not-proposal",
533
+ /**
534
+ * `approval propose --key` does not begin with `<class>:` (APRV-445, S4). The
535
+ * key names the class it was proposed under, so a key cannot be read back
536
+ * later as belonging to a different class than its record says.
537
+ */
538
+ "key-class-mismatch",
539
+ /**
540
+ * `approval propose` found the log moving under it on every one of its
541
+ * bounded attempts (APRV-445 recheck 3): each re-read showed an answer the
542
+ * next append was refused for. Exit 1, nothing more was appended, and the
543
+ * proposal's standing is whatever the log now says; read it with `wait
544
+ * --timeout 0` or call again. Distinct from `already-decided`, which would
545
+ * tell a caller a proposal is answered when it may stand granted or pending.
546
+ */
547
+ "contended"];
480
548
  export type GateRefusalCode = (typeof GATE_REFUSAL_CODES)[number];
481
549
  /** Every gate failure is one of these. Nothing here throws. */
482
550
  export interface GateRefusal {
@@ -618,6 +686,26 @@ type ReadOutcome = {
618
686
  * underneath it.
619
687
  */
620
688
  export declare function readGateRecords(logPath: string, schemaDir?: string): ReadOutcome;
689
+ /**
690
+ * The policy as a gate operation would load it: one read through the seam of
691
+ * {@link GateOptions.policy}, parsed, failing closed (APRV-324).
692
+ *
693
+ * Exported for one caller, `channels/contract.ts`, which resolves an
694
+ * authenticated sender to an approver identity BEFORE it calls {@link decide}
695
+ * and must do so against the same file, discovered the same way, through the
696
+ * same injectable reader. Writing a second `loadPolicy` call there would have
697
+ * been a second discovery path that could find a different file.
698
+ *
699
+ * It is still a SECOND read of the bytes, one operation earlier, and that is
700
+ * deliberate rather than overlooked: `decide` reads once per attempt on purpose
701
+ * (see {@link PolicyRead}), and pinning bytes across its bounded retry would
702
+ * make a re-attestation inside the retry window invisible to the drift check.
703
+ * What closes the gap is the check itself — a policy that changes between the
704
+ * two reads is either unattested or a different hash from the one the request
705
+ * pinned, and `decide` refuses `policy-not-attested` or `policy-drift` rather
706
+ * than authorizing under bytes the resolution never saw.
707
+ */
708
+ export declare function readGatePolicy(options: GateOptions): PolicyLoadResult;
621
709
  /** One declared action of an envelope (SPEC.md §6.2 `actions[]`). */
622
710
  export interface RegisteredAction {
623
711
  class: string;
@@ -690,7 +778,24 @@ export declare function register(logPath: string, source: RegisterSource, actor:
690
778
  */
691
779
  export interface RegisterOptions extends GateOptions {
692
780
  harness?: HarnessProvenance;
781
+ /** Set by `propose` alone: the `propose:` task namespace is its (APRV-445). */
782
+ proposal?: true;
693
783
  }
784
+ /**
785
+ * The `task.registered` record for `task`, or the `not-registered` refusal.
786
+ *
787
+ * The one raise site for SPEC.md §11.2's `not-registered` ("no task.registered
788
+ * record exists for the task id"). `request` reaches it through
789
+ * {@link registeredAction}; `approval wait` calls it directly (APRV-428), so a
790
+ * wait on a task the log has never seen is refused in the same words rather
791
+ * than answered as a vacuous grant. The latest registration wins, as it always
792
+ * has for `registeredAction`; the register path refuses a second one, so a log
793
+ * carrying two was written by something else.
794
+ */
795
+ export declare function taskRegistration(records: EventRecord[], task: string): {
796
+ ok: true;
797
+ record: EventRecord;
798
+ } | GateRefusal;
694
799
  /**
695
800
  * The declared action for `(task, actionKey)`, as registered in the log.
696
801
  *
@@ -756,6 +861,25 @@ export interface RequestInput {
756
861
  * policy's `defaults.approval_ttl` remains the only deadline with authority.
757
862
  */
758
863
  wait_until?: string;
864
+ /**
865
+ * The ceiling the requesting harness imposes on the hook process that is
866
+ * asking, in milliseconds (APRV-423).
867
+ *
868
+ * Recorded as `payload.harness_cap_ms` and read back by `core/state.ts`,
869
+ * which judges the request against the SHORTER of this minus a fixed margin
870
+ * and the policy's own `defaults.approval_ttl`. It is the answer to APRV-410:
871
+ * a harness that kills the hook while the question is still on a phone turns
872
+ * the tap that follows into a grant on a call nobody holds, so the question
873
+ * is made to end first and both records say the same thing.
874
+ *
875
+ * Claimed, and structurally unable to reduce scrutiny (SPEC.md §11.1
876
+ * invariant 4): the runtime takes a MINIMUM, so an overstated cap changes
877
+ * nothing and an understated one only shortens the claimant's own window.
878
+ * The write boundary constrains it to a positive integer on a request that
879
+ * also declares `execution: "harness"` — a cap on a token-minting request
880
+ * would be a question with a shorter life than the authorization it mints.
881
+ */
882
+ harnessCapMs?: number;
759
883
  /**
760
884
  * The caller has established that loop safety floors this action to `manual`
761
885
  * for this invocation (APRV-145, amended SPEC.md §10.2).
@@ -801,6 +925,15 @@ export interface RequestInput {
801
925
  * spend a human's decision on an authorization that can never execute.
802
926
  */
803
927
  delivery?: "self";
928
+ /**
929
+ * This request was opened by `approval propose`, whose caller named the class
930
+ * itself (APRV-445). When set, intake re-checks `agentRequestability` against
931
+ * the policy bytes THIS attempt read, inside the retried read-check-append
932
+ * cycle, so a re-attestation between `propose`'s own check and the append
933
+ * cannot admit a class the policy no longer opens to agents (SPEC.md §11.1
934
+ * invariant 5). It only ever adds a refusal.
935
+ */
936
+ agentProposal?: true;
804
937
  }
805
938
  /**
806
939
  * Why a `supervised-live` action was, or was not, sent to the human gate
@@ -947,6 +1080,50 @@ export interface DecideOptions extends GateOptions {
947
1080
  * grade beside a refusal is a second answer to a question with one.
948
1081
  */
949
1082
  reaction?: Reaction;
1083
+ /**
1084
+ * The surface that collected the decision (amended SPEC.md §8, APRV-324),
1085
+ * recorded as the record's top-level `channel`.
1086
+ *
1087
+ * The base event schema has defined the field since v0.1 and the decision
1088
+ * events never set it, so a reader of a grant could not tell a tap on a phone
1089
+ * from a line typed into a terminal. Set by the decision surface, from its own
1090
+ * name, exactly as `audit.decision_refused` has always set it.
1091
+ */
1092
+ channel?: string;
1093
+ /**
1094
+ * The authenticated sender the `actor` was resolved from (amended SPEC.md
1095
+ * §6.3, APRV-324), recorded as `payload.sender`.
1096
+ *
1097
+ * ABSENT is meaningful and is the common case: it says the attribution came
1098
+ * from the surface's configuration rather than from anything the transport
1099
+ * authenticated, which is how every decision before this key existed was
1100
+ * made. Present, it is the transport's own attribution — never a name, handle
1101
+ * or id a message claimed about itself (§11.1 invariant 4).
1102
+ *
1103
+ * This is a RECORD of how the actor was chosen, and it is not the choosing:
1104
+ * `channels/contract.ts` resolves the sender against the attested policy
1105
+ * before calling this verb, and no check here reads this field. There is no
1106
+ * CLI flag that supplies it, so no agent-reachable surface mints one.
1107
+ *
1108
+ * `hashed` (APRV-370) says the `id` is the operator's keyed digest of the
1109
+ * account rather than the account, which is what a policy mapping senders in
1110
+ * the keyed form records. Present-and-`true` or absent, never `false`: a raw
1111
+ * record is the record this runtime already wrote, and it is written
1112
+ * unchanged.
1113
+ */
1114
+ sender?: {
1115
+ channel: string;
1116
+ id: string;
1117
+ hashed?: true;
1118
+ };
1119
+ /**
1120
+ * How {@link DecideOptions.sender} became the actor (APRV-324), recorded as
1121
+ * `payload.sender_source`. `policy` is the attested `approvers[id].senders`
1122
+ * mapping, and it is the only member today — a closed vocabulary so a future
1123
+ * source (a signed receipt, APRV-249) is distinguishable in a log rather than
1124
+ * silently mixed in with policy-attested ones.
1125
+ */
1126
+ senderSource?: "policy";
950
1127
  }
951
1128
  export type DecideResult = {
952
1129
  ok: true;
@@ -1005,6 +1182,15 @@ export type DecideResult = {
1005
1182
  */
1006
1183
  export declare function decide(logPath: string, actionKey: string, decision: Decision, actor: string, options?: DecideOptions): DecideResult;
1007
1184
  export interface WithdrawOptions extends GateOptions {
1185
+ /**
1186
+ * Withdraw only a pending request that is VOID at the moment of the append
1187
+ * (APRV-445 recheck, SF1): pinned to a policy hash that is no longer the
1188
+ * attested one. Judged inside the retried read-check-append cycle, so a
1189
+ * caller acting on a stale reading cannot retract a question a concurrent
1190
+ * caller has just re-asked under the policy in force. A live, non-void
1191
+ * request refuses `duplicate-request`.
1192
+ */
1193
+ onlyIfVoid?: true;
1008
1194
  /** Why the requester is retracting. Defaults to `cancelled`. */
1009
1195
  reason?: WithdrawReason;
1010
1196
  /** The requester's free-text elaboration, recorded in the payload. */
@@ -1087,7 +1273,19 @@ export interface HarnessCarry {
1087
1273
  /** `seq` of the `approval.granted`, on `granted` only. */
1088
1274
  decisionSeq: number | null;
1089
1275
  }
1090
- export declare function findHarnessCarry(records: EventRecord[], payloadHash: string, cls: string, ts: string, ttlMs: number | null): HarnessCarry | null;
1276
+ export declare function findHarnessCarry(records: EventRecord[], payloadHash: string, cls: string, ts: string, ttlMs: number | null,
1277
+ /**
1278
+ * How long a question of this caller's outlives the wait that opened it
1279
+ * (APRV-410, `core/harness-wait.ts`'s `abandonedAfterMs`), or `null` for a
1280
+ * caller that declares no such window.
1281
+ *
1282
+ * Only a GRANTED candidate is bounded by it. A pending one is the question
1283
+ * this invocation is about to adopt, and the withdrawal of an abandoned
1284
+ * pending question is the requester's own business, not this function's:
1285
+ * `cli/hook.ts` sweeps those through `withdraw`, which is requester-only by
1286
+ * design (APRV-106 rule 1).
1287
+ */
1288
+ abandonAfterMs?: number | null): HarnessCarry | null;
1091
1289
  /**
1092
1290
  * `GateOptions` plus the one thing a harness spend states about itself
1093
1291
  * (APRV-146).
@@ -1362,3 +1560,191 @@ export type ExpireResult = {
1362
1560
  * as `rejected`.
1363
1561
  */
1364
1562
  export declare function expire(logPath: string, actionKey: string, options?: GateOptions): ExpireResult;
1563
+ /**
1564
+ * The largest payload `approval propose` and `approval start` accept, in UTF-8
1565
+ * bytes of the JSON text as the caller sent it: 256 KiB.
1566
+ *
1567
+ * Well under `approval serve`'s 1 MiB body cap, so the refusal a caller meets is
1568
+ * this named one rather than a transport's. A proposal is a sentence or a
1569
+ * paragraph a human will read on a phone; a payload this size is not one.
1570
+ */
1571
+ export declare const PROPOSE_PAYLOAD_MAX_BYTES: number;
1572
+ /** The longest `--key` `propose` accepts, in UTF-8 bytes (APRV-445, L6). */
1573
+ export declare const PROPOSE_KEY_MAX_BYTES = 1024;
1574
+ /** The longest `--summary` `propose` accepts, in UTF-8 bytes (APRV-445, L6). */
1575
+ export declare const PROPOSE_SUMMARY_MAX_BYTES = 4096;
1576
+ /** `origin.app` on every envelope `propose` registers. */
1577
+ export declare const PROPOSE_ORIGIN_APP = "approval-propose";
1578
+ /** The task-id prefix `propose` derives under. */
1579
+ export declare const PROPOSE_TASK_PREFIX = "propose:";
1580
+ /**
1581
+ * Was this task registered by `propose` (APRV-445)?
1582
+ *
1583
+ * A proposal's request carries `execution: "harness"` like a hook's, so the two
1584
+ * hook-side readers of that marker (the carry and the abandoned-question sweep)
1585
+ * ask this first: a proposal waits days for a human, is spent only by `start`,
1586
+ * and is withdrawn only by its requester's own call.
1587
+ */
1588
+ export declare function isProposalTask(task: unknown): boolean;
1589
+ /**
1590
+ * The task id `propose` registers under, from who is asking, the class and the
1591
+ * key: `propose:` and the first 32 hex digits of the SHA-256 over the RFC 8785
1592
+ * canonical JSON of `[actor, class, key]`.
1593
+ *
1594
+ * Deterministic, so a retry lands on the task its first attempt registered and
1595
+ * is recognised as a retry. The ACTOR is the tenant half of the derivation: one
1596
+ * `approval serve` process serves one store as one fixed `agent:<id>`, so within
1597
+ * a store the actor is who the tenant's agent is, and two actors proposing the
1598
+ * same key derive two different tasks, the second of which `register` refuses
1599
+ * because the key is already declared under the first (`task-already-registered`).
1600
+ * The class is in it so that the same key proposed under a second class is a
1601
+ * different task rather than a silent re-declaration.
1602
+ */
1603
+ export declare function proposedTaskId(actor: string, cls: string, actionKey: string): string;
1604
+ /** What an agent proposes. The payload is a parsed JSON object. */
1605
+ export interface ProposeInput {
1606
+ cls: string;
1607
+ actionKey: string;
1608
+ summary: string;
1609
+ payload: unknown;
1610
+ }
1611
+ /**
1612
+ * How a proposal stands after the call.
1613
+ *
1614
+ * `decision` is what the caller branches on: `requested` means a human is (or
1615
+ * was) asked and `state` says where that stands; `autonomous` and `supervised`
1616
+ * mean the policy itself authorizes the action, nothing was put in front of a
1617
+ * human, and the caller proceeds and records the execution with `approval start`.
1618
+ *
1619
+ * `idempotent` is true exactly when this call appended nothing: a retry of a
1620
+ * proposal whose registration (and, on the manual path, whose request) already
1621
+ * stands under the same class, key and payload hash.
1622
+ */
1623
+ export type ProposeResult = {
1624
+ ok: true;
1625
+ task: string;
1626
+ actionKey: string;
1627
+ cls: string;
1628
+ payloadHash: string;
1629
+ decision: "requested" | "autonomous" | "supervised";
1630
+ /**
1631
+ * `null` off the manual path, where there is no request to be in a state;
1632
+ * `executed` once `start` recorded the execution (APRV-445, L7).
1633
+ */
1634
+ state: RequestState | "executed" | null;
1635
+ seq: number | null;
1636
+ idempotent: boolean;
1637
+ } | GateRefusal;
1638
+ /**
1639
+ * `approval propose` (APRV-445, amended SPEC.md §5.2): register and request one
1640
+ * action in one call, for a requester that holds the payload inline and no file
1641
+ * on the gate's machine.
1642
+ *
1643
+ * ## Why this verb may name its class when `request` may not
1644
+ *
1645
+ * `approval request` reads the class from the log's `task.registered` record so
1646
+ * that an agent cannot call a `financial.spend` a `read.web`. Here the agent is
1647
+ * also the registrant, so that rule alone would prove nothing, and the bound is
1648
+ * the operator's instead: the class must be an EXACT key of `policy.classes`, and
1649
+ * that key or a declared `<prefix>.*` family of it must say
1650
+ * `agent_may_request: true`. A class reached only through a wildcard is refused,
1651
+ * so the set of classes an agent can propose in is a set of lines the operator
1652
+ * wrote and attested by name. What the agent chooses among them is still its own
1653
+ * statement (SPEC.md §11.1 invariant 4 is why the choice is bounded at all), and
1654
+ * an operator opening two classes of different autonomy to agents is trusting
1655
+ * the agent to pick the right one; the record names the class it picked.
1656
+ *
1657
+ * ## Order
1658
+ *
1659
+ * Attestation, then the agent-requestability gate and the class's own autonomy
1660
+ * (`human-only`, an unruled `harness.launch.*`), all BEFORE anything is
1661
+ * registered, so a refused class leaves no registration behind. Then the
1662
+ * registration, then {@link request} with `agentProposal: true`, which repeats
1663
+ * the gate against the bytes its own attempt reads. `execution: "harness"` on the
1664
+ * request: nothing ever presents a token for a proposal, the requester proceeds
1665
+ * on the grant itself and records that with `approval start`, so a minted token
1666
+ * would be a live credential with no spender.
1667
+ *
1668
+ * ## Idempotency
1669
+ *
1670
+ * The task id is {@link proposedTaskId}. A second call with the same actor,
1671
+ * class, key and payload hash finds its own registration and appends nothing
1672
+ * while the request is live or decided, answering with the request's state and
1673
+ * `idempotent: true`. A withdrawn or expired request (a re-attestation voids
1674
+ * pending requests as `policy-drift`) is asked again under the same registration.
1675
+ * The same key with DIFFERENT bytes refuses: `duplicate-request` while a request
1676
+ * is live, `payload-mismatch` otherwise, because a key is bound to the bytes it
1677
+ * was first registered with and new bytes need a new key.
1678
+ */
1679
+ export declare function propose(logPath: string, input: ProposeInput, actor: string, options?: GateOptions, attempt?: number, appendedEarlier?: boolean): ProposeResult;
1680
+ export type StartProposedResult = {
1681
+ ok: true;
1682
+ task: string;
1683
+ actionKey: string;
1684
+ cls: string;
1685
+ /** `grant` when a human's harness grant was spent; `policy` when the policy authorized it. */
1686
+ authorization: "grant" | "policy";
1687
+ record: EventRecord;
1688
+ } | GateRefusal;
1689
+ /**
1690
+ * `approval start <task> --action <key> --payload-json <json>` (APRV-445): record
1691
+ * the `execution.started` for an action its requester is about to carry out
1692
+ * itself, outside any harness hook.
1693
+ *
1694
+ * Until this verb an agent holding only the serve agent credential could ask and
1695
+ * wait, and could not say that it then acted: `approval run` spawns argv on the
1696
+ * gate's machine, and the harness hook writes starts only for tool calls it
1697
+ * classified. A proposal the policy authorizes outright (`autonomous`,
1698
+ * `supervised`) therefore left no record at all, and one a human granted left a
1699
+ * grant nobody spent, so a second publication of the same key was indistinguishable
1700
+ * from the first.
1701
+ *
1702
+ * It adds no authority. It writes through the two existing spenders and through
1703
+ * nothing else: {@link consumeHarnessGrant} when the key carries a request (it
1704
+ * refuses unless that request is granted, unexpired, harness-executed and
1705
+ * unspent, under the policy it was asked under), and {@link startHarnessExecution}
1706
+ * when it carries none (it refuses a `manual` or `human-only` class, an escalated
1707
+ * loop and a spent key, and charges the budgets). Both pin the single-use rule:
1708
+ * a second start of one key is `already-executed`.
1709
+ *
1710
+ * Two checks of its own, both before either spender runs. REQUESTER-ONLY: the
1711
+ * actor must be the one that registered the task (`not-requester` otherwise), as
1712
+ * `withdraw` is, so an agent cannot spend or exhaust a key someone else declared.
1713
+ * And the bytes: the caller presents the payload it is about to act on, and its
1714
+ * hash must equal the registered `payload_hash` (`payload-mismatch` otherwise),
1715
+ * so the thing done is the thing that was approved, which the grant path checks
1716
+ * again against the grant's own binding.
1717
+ */
1718
+ export declare function startProposed(logPath: string, task: string, actionKey: string, payload: unknown, actor: string, options?: GateOptions): StartProposedResult;
1719
+ /**
1720
+ * A request's state as a waiter must read it (APRV-445 refutation, B1).
1721
+ *
1722
+ * `requestState` answers what the log RECORDED. A waiter needs what the record
1723
+ * still AUTHORIZES, and the two part in three ways the gate already enforces
1724
+ * at the spend and the decision but no reader was told about:
1725
+ *
1726
+ * - a GRANT whose request has lapsed its window is `expired`: there is no
1727
+ * separate grant TTL (`grantLapsed`), so a tap at hour 71 of a 72 h window
1728
+ * authorizes nothing at hour 73;
1729
+ * - a PENDING request pinned to a policy hash that is no longer the attested
1730
+ * one is `void` for every task, because the decision refuses `policy-drift`;
1731
+ * a GRANT is `void` on the same condition only where its spend enforces the
1732
+ * same refusal: a harness grant (`execution: "harness"`), which includes
1733
+ * every proposal. A token grant spent through `approval run` stays `granted`;
1734
+ * - a request the runtime withdrew for `policy-drift` (APRV-235) is `void` too,
1735
+ * for the same reason, rather than an ordinary requester `withdrawn`;
1736
+ * - a key whose execution started is `executed`.
1737
+ *
1738
+ * `void` and `expired` both mean "ask again": the question as asked can no
1739
+ * longer be answered usefully. Everything else is `requestState` verbatim. An
1740
+ * unattested policy (`attestedSha256` null) voids nothing, because that state is
1741
+ * the human's to repair and may end in the same bytes.
1742
+ */
1743
+ export type RequestStanding = RequestState | "void" | "executed";
1744
+ export declare function requestStanding(records: EventRecord[], actionKey: string, ts: string, ttlMs: number | null, attestedSha256: string | null): RequestStanding;
1745
+ /**
1746
+ * The SHA-256 the live policy bytes are attested under, or `null` when they are
1747
+ * not attested (unread, unattested, or changed since). One read of the file
1748
+ * through the same seam every gate operation uses.
1749
+ */
1750
+ export declare function attestedPolicySha256(records: EventRecord[], options?: GateOptions): string | null;