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
@@ -0,0 +1,188 @@
1
+ /**
2
+ * What the log says when a decision surface refused a gesture that is not a
3
+ * decision (APRV-355, amended SPEC.md §8).
4
+ *
5
+ * ## The fact this module is about
6
+ *
7
+ * Found while landing APRV-324 (PR #427, 2026-09-17). Once the policy maps
8
+ * Telegram senders, a tap on a CHECKPOINT signature or on a REVIEW from an
9
+ * account the attested policy names nobody for is refused before any verb runs
10
+ * — and records nothing. The only refusal record in the system is
11
+ * `audit.decision_refused`, and it requires a record-level `action_key` and a
12
+ * `payload.decision` of grant, reject or revoke. A signature answers for a
13
+ * chain head and a review answers for a sampled record; neither has either
14
+ * field, so writing one of these there would mean manufacturing both. The lane
15
+ * that found it declined to, correctly.
16
+ *
17
+ * The cost of recording nothing is the same cost `core/decision-refusal.ts`
18
+ * exists to end. Somebody's attention was spent — SPEC.md §11 calls human
19
+ * attention the audit budget — and an attempt was made from an account the
20
+ * operator did not map, and the only trace is a line on a terminal and an
21
+ * answer in a chat. An operator deciding whether to map that account has
22
+ * nothing in the log to read.
23
+ *
24
+ * ## What this record is, and what it is not
25
+ *
26
+ * `audit.gesture_refused` is an AUDIT-TIER record on the strict terms
27
+ * `audit.decision_refused` set, and the terms are the whole of its safety:
28
+ *
29
+ * - it grants nothing and mints no token;
30
+ * - `core/state.ts` settles nothing on it, so no verdict moves;
31
+ * - `core/budgets.ts` charges nothing for it, so no budget moves;
32
+ * - `core/audit.ts` does not sample it and no streak counts it;
33
+ * - NO ENFORCEMENT PATH READS IT. `tests/gesture-refusal.test.ts` pins that by
34
+ * reading the module graph rather than by asserting an intention.
35
+ *
36
+ * The record's own actor is `system:`, for the reason `audit.dark_session`'s
37
+ * and `audit.decision_refused`'s are: this is the runtime's statement about a
38
+ * refusal the runtime made, and a record of a refusal authored by either party
39
+ * to it is a record neither party can be held to. The person, when the runtime
40
+ * can name one, is the SUBJECT and sits in the payload.
41
+ *
42
+ * ## The asymmetry it inherits
43
+ *
44
+ * Refusals handed to AGENTS stay unlogged here too. An agent that is refused
45
+ * reads the code, stops or asks again, and nothing was spent that a record
46
+ * could account for. And a gesture is human by construction: an agent has no
47
+ * checkpoint to sign and no review to give.
48
+ *
49
+ * ## No attestation check, deliberately
50
+ *
51
+ * Nothing here asks whether the policy is attested, for the reason
52
+ * `core/decision-refusal.ts` does not: this write confers no authority.
53
+ * Refusing to record a refusal because a file changed would be the strict
54
+ * direction pointing the wrong way, and the case where it would bite hardest is
55
+ * `policy-not-attested` itself — exactly the refusal an operator most needs the
56
+ * log to remember. The write boundary still validates every record.
57
+ *
58
+ * ## Invariants
59
+ *
60
+ * - **Gate-typed events never accept caller timestamps** (§11.1). `ts` comes
61
+ * from the injected clock at the write boundary; there is no parameter.
62
+ * - **Every check-then-append passes through compare-and-append** (§11.1(5)).
63
+ * The write states the head it was derived against and the whole cycle
64
+ * re-enters from a fresh read on `head-moved` through {@link withHeadRetry}.
65
+ * - **Self-reported fields never reduce scrutiny** (§11.1). Everything here
66
+ * only ADDS to what a reviewer sees. The sender is the transport's own
67
+ * attribution, never anything the message claimed about itself.
68
+ * - **Refusals stay machine-readable and distinct** (§11.1). The surface's code
69
+ * is copied verbatim; nothing here invents, merges or softens one.
70
+ */
71
+ import { tick } from "./clock.js";
72
+ import { attemptsOf, withHeadRetry } from "./head-retry.js";
73
+ import { appendEvent } from "./log.js";
74
+ import { readVerifiedRecords } from "./state.js";
75
+ /** The actor every record here carries: the gate stating what the gate did. */
76
+ export const GESTURE_REFUSAL_ACTOR = "system:gate";
77
+ /**
78
+ * The gestures this record can be about. **Closed and additive-only** (§11.1
79
+ * invariant 6), and pinned against the event schema's own enum by
80
+ * `tests/gesture-refusal.test.ts`: a kind the sweep can produce and the write
81
+ * boundary refuses is an observation that never reaches a human, which is the
82
+ * failure APRV-358 named a few hours before this task.
83
+ *
84
+ * `review` and `review-note` are two members rather than one because a note is
85
+ * attention spent WRITING rather than attention spent tapping, and an operator
86
+ * reading this record to decide whether to map an account wants to know which
87
+ * they lost.
88
+ */
89
+ export const REFUSED_GESTURES = ["checkpoint-signature", "review", "review-note"];
90
+ /**
91
+ * The refusals a gesture can meet before any verb runs. **Closed**, and exactly
92
+ * what sender resolution can answer: `sender-unmapped`, `sender-ambiguous` and
93
+ * `sender-key-unavailable` from `core/sender-identity.ts`'s own union, and
94
+ * `policy-not-attested` from `core/attest.ts`, which fires when the policy
95
+ * declaring the mapping is not the attested one and is therefore not in force.
96
+ *
97
+ * `attest-requires-terminal` is deliberately absent: it belongs to an
98
+ * attestation tap, which is a decision and is recorded as one.
99
+ */
100
+ export const REFUSED_GESTURE_CODES = [
101
+ "sender-unmapped",
102
+ "sender-ambiguous",
103
+ // APRV-370. A keyed mapping this process holds no key for: the runtime could
104
+ // resolve no account at all, which is a different fact from "this account is
105
+ // not mapped" and wants a different repair.
106
+ "sender-key-unavailable",
107
+ "policy-not-attested",
108
+ ];
109
+ /** Is `code` one this record can carry? Used where a code arrives as a string. */
110
+ export function isRefusedGestureCode(code) {
111
+ return REFUSED_GESTURE_CODES.includes(code);
112
+ }
113
+ /** The gestures this module records: a person's, and nobody else's. */
114
+ const HUMAN_ACTOR = /^human:.+/u;
115
+ /**
116
+ * Record that a human's gesture was refused.
117
+ *
118
+ * Called by the surface that collected the gesture, on the branch where it
119
+ * refused — never from inside the verb the gesture would have reached, which is
120
+ * never called at all on this path.
121
+ *
122
+ * Best-effort by design: a failure here is returned, never thrown, and the
123
+ * caller shows the refusal either way. The gesture was already refused before
124
+ * this ran, and nothing about that outcome depends on this write landing.
125
+ *
126
+ * Two cases append nothing, and both are the honest answer rather than a
127
+ * silence:
128
+ *
129
+ * - a non-human actor, which is the misconfigured-surface case: nobody's
130
+ * attention was spent, so there is no spend for a record to account for;
131
+ * - a code this record cannot carry, which means a surface refused for a reason
132
+ * this vocabulary does not name. Minting a member here to fit it would widen
133
+ * a closed union at the write boundary from inside a best-effort path.
134
+ */
135
+ export function recordRefusedGesture(logPath, gesture, refusal, options = {}) {
136
+ if (gesture.actor !== null && !HUMAN_ACTOR.test(gesture.actor)) {
137
+ return { ok: true, audit: null };
138
+ }
139
+ // No person and no account is nothing to say: the record would name neither
140
+ // the subject nor the reason it could not, and the schema refuses it.
141
+ if (gesture.actor === null && gesture.sender === undefined) {
142
+ return { ok: true, audit: null };
143
+ }
144
+ if (!isRefusedGestureCode(refusal.code))
145
+ return { ok: true, audit: null };
146
+ const appended = withHeadRetry(attemptsOf(options.retryOnHeadMoved), () => appendAudit(logPath, gesture, refusal, options));
147
+ return appended.ok ? { ok: true, audit: appended.record } : appended;
148
+ }
149
+ /** The whole cycle: a fresh read for the head, then one append against it. */
150
+ function appendAudit(logPath, gesture, refusal, options) {
151
+ const ts = tick(options);
152
+ const read = readVerifiedRecords(logPath, options.schemaDir === undefined ? {} : { schemaDir: options.schemaDir });
153
+ if (!read.ok) {
154
+ return { ok: false, code: "log-unreadable", message: read.message };
155
+ }
156
+ const payload = {
157
+ ...(gesture.actor === null ? {} : { actor: gesture.actor }),
158
+ gesture: gesture.gesture,
159
+ code: refusal.code,
160
+ message: refusal.message,
161
+ };
162
+ if (gesture.sender !== undefined) {
163
+ payload["sender"] = {
164
+ channel: gesture.sender.channel,
165
+ id: gesture.sender.id,
166
+ // APRV-370: only when true, so a raw record does not change shape.
167
+ ...(gesture.sender.hashed === true ? { hashed: true } : {}),
168
+ };
169
+ if (gesture.senderSource !== undefined)
170
+ payload["sender_source"] = gesture.senderSource;
171
+ }
172
+ return appendOne(logPath, { ts, actor: GESTURE_REFUSAL_ACTOR, channel: gesture.channel, payload }, options, read.head);
173
+ }
174
+ function appendOne(logPath, input, options, expectedHead) {
175
+ const append = { ...options.append };
176
+ if (options.schemaDir !== undefined)
177
+ append.schemaDir = options.schemaDir;
178
+ const result = appendEvent(logPath, { ...input, event: "audit.gesture_refused" }, { ...append, expectedHead });
179
+ if (result.ok)
180
+ return { ok: true, record: result.record };
181
+ return {
182
+ ok: false,
183
+ code: "append-failed",
184
+ message: `audit.gesture_refused could not be appended: ${result.error.message}`,
185
+ append: result.error,
186
+ };
187
+ }
188
+ //# sourceMappingURL=gesture-refusal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gesture-refusal.js","sourceRoot":"","sources":["../../../src/core/gesture-refusal.ts"],"names":[],"mappings":"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"}
@@ -52,7 +52,7 @@
52
52
  * only seam, and a test puts a stub binary in front of it.
53
53
  */
54
54
  /** The harnesses this runtime speaks a hook protocol for. */
55
- export declare const HARNESS_KINDS: readonly ["claude-code", "cursor", "codex"];
55
+ export declare const HARNESS_KINDS: readonly ["claude-code", "cursor", "codex", "grok", "muse", "hermes"];
56
56
  export type HarnessKind = (typeof HARNESS_KINDS)[number];
57
57
  /** Is `value` one of the harnesses this runtime knows? */
58
58
  export declare function isHarnessKind(value: unknown): value is HarnessKind;
@@ -102,7 +102,30 @@ export declare function normalizeHarnessVersion(raw: unknown): string | null;
102
102
  */
103
103
  export declare const HARNESS_PROBE_TIMEOUT_MS = 10000;
104
104
  /**
105
- * Run `<binary> --version` once, uncached, and normalize what came back.
105
+ * How long the RAW first line of `<binary> --version` may be.
106
+ *
107
+ * Wider than {@link HARNESS_VERSION_LIMIT} because it holds a different kind of
108
+ * value for a different reader: nothing capped by this number is ever appended to
109
+ * the log (only {@link normalizeHarnessVersion}'s output is), and what needs the
110
+ * raw line is a diagnostic that must be able to read a build stamp a harness
111
+ * prints beside its semver. Hermes prints
112
+ * `Hermes Agent v0.21.3 (2026.9.14) · upstream 913d4098`, which the log's own
113
+ * rule rejects on the non-ASCII separator alone. Capped and stripped of control
114
+ * characters all the same: this is third-party output on its way to a terminal.
115
+ */
116
+ export declare const HARNESS_RAW_VERSION_LIMIT = 200;
117
+ /**
118
+ * The first line of a `--version` output, as a line a diagnostic may print.
119
+ *
120
+ * One line, trimmed, control characters removed, capped. `null` for empty output
121
+ * or a line past the cap. It keeps non-ASCII bytes, which is the whole difference
122
+ * from {@link normalizeHarnessVersion}: a build stamp behind a typographic
123
+ * separator is exactly the fact a version floor has to read, and it is exactly
124
+ * the fact the write boundary will not accept.
125
+ */
126
+ export declare function rawHarnessVersionLine(raw: unknown): string | null;
127
+ /**
128
+ * Run `<binary> --version` once, uncached, and return its raw first line.
106
129
  *
107
130
  * Every failure is a value rather than an exception, in the manner of
108
131
  * {@link spawnGloss}: a missing binary, a non-zero exit and a timeout kill are
@@ -113,16 +136,117 @@ export declare const HARNESS_PROBE_TIMEOUT_MS = 10000;
113
136
  * vault passphrase, and it has no use for either. Nothing is declared, because
114
137
  * reading a version is not a granted action.
115
138
  */
139
+ export declare function probeHarnessVersionRaw(kind: HarnessKind): string | null;
140
+ /**
141
+ * Run `<binary> --version` once, uncached, and normalize what came back.
142
+ *
143
+ * The recordable form: one line, printable ASCII, capped. Exported for the test
144
+ * that proves the memo below is a memo.
145
+ */
116
146
  export declare function probeHarnessVersion(kind: HarnessKind): string | null;
147
+ /** The raw first line of `<binary> --version`, read at most once per process. */
148
+ export declare function installedHarnessVersionRaw(kind: HarnessKind): string | null;
117
149
  /**
118
150
  * The installed version of `kind`, read at most once per process.
119
151
  *
120
- * This is the only entry point callers should use. `probeHarnessVersion` is
121
- * exported for the test that proves the memo is a memo.
152
+ * This is the only entry point callers should use for a RECORDABLE version.
153
+ * `probeHarnessVersion` is exported for the test that proves the memo is a memo.
122
154
  */
123
155
  export declare function installedHarnessVersion(kind: HarnessKind): string | null;
124
156
  /** Drop the memo. TEST ONLY: a process reads a version once, by design. */
125
157
  export declare function resetHarnessVersionCache(): void;
158
+ /**
159
+ * The build at which Hermes Agent starts honouring `fail_closed` (APRV-415).
160
+ *
161
+ * ## Why a floor exists at all, and why it is a DATE rather than a version
162
+ *
163
+ * `approval hook hermes` is enforcement rather than a backstop only because of a
164
+ * per-entry `fail_closed: true` that makes a hook crash, a hook timeout and
165
+ * unparseable hook output BLOCK. The live probe measured both halves of that on
166
+ * two builds of the same harness, and the answer differs between them:
167
+ *
168
+ * - `main` at `118984d7`, built 2026-09-20: crash, garbage and hang were all
169
+ * REFUSED (the hang at the 300s per-entry cap). The key works;
170
+ * - `v0.21.3`, built 2026.9.14: all three PROCEEDED. That build does not know the
171
+ * key and ignores it SILENTLY. `hermes hooks list` renders no `fail_closed`
172
+ * flag on either build, so the listing cannot be used to tell them apart.
173
+ *
174
+ * The two builds report the SAME semver. `hermes --version` on the older one
175
+ * prints `Hermes Agent v0.21.3 (2026.9.14) · upstream 913d4098`, and the update
176
+ * that fixed the behaviour moved 670 commits without moving `0.21.3`. So a floor
177
+ * expressed as a semantic version would compare the one field that did not
178
+ * change, and would pass a build that fails open. The build DATE and the upstream
179
+ * commit are the two fields that did move, and they are what this compares.
180
+ *
181
+ * ## What it can and cannot do
182
+ *
183
+ * It can only ADD a red line to `approval doctor` (SPEC.md §11.1 invariant 4: a
184
+ * self-reported field never reduces scrutiny). A build claiming a later date buys
185
+ * nothing — it defeats a row that would have asked a human to look — and nothing
186
+ * in the runtime reads this to widen a verdict, skip a wait or lower a class. The
187
+ * refusals the adapter emits are the same on every build; what changes below the
188
+ * floor is whether a BROKEN hook stops the call, which no code in this repository
189
+ * can observe from inside the hook it is broken in.
190
+ */
191
+ export declare const HERMES_FAIL_CLOSED_FLOOR: {
192
+ /** The first build observed to honour the key, by upstream commit. */
193
+ readonly upstream: "118984d7";
194
+ /** That build's date, in the `YYYY.M.D` stamp `hermes --version` prints. */
195
+ readonly date: {
196
+ readonly year: 2026;
197
+ readonly month: 9;
198
+ readonly day: 20;
199
+ };
200
+ /** The one sentence every surface quotes, so they cannot drift apart. */
201
+ readonly statement: "a build at or after main 118984d7 of 2026-09-20; v0.21.3 (2026.9.14) fails open silently";
202
+ };
203
+ /** A build stamp, as `hermes --version` prints one. */
204
+ export interface HermesBuildDate {
205
+ year: number;
206
+ month: number;
207
+ day: number;
208
+ }
209
+ /** What `hermes --version`'s first line states, field by field. */
210
+ export interface HermesVersionFields {
211
+ /** The semver, which did NOT move across the fail-closed fix. */
212
+ semver: string | null;
213
+ /** The build date, `(2026.9.14)`, which did. */
214
+ date: HermesBuildDate | null;
215
+ /** The upstream commit, `· upstream 913d4098`, which did. */
216
+ upstream: string | null;
217
+ }
218
+ /**
219
+ * Read the fields out of `hermes --version`'s first line, or `null`.
220
+ *
221
+ * Shape-only and forgiving in one direction: a field this cannot find is `null`
222
+ * rather than a guess, and a line naming none of the three is not a Hermes
223
+ * version line at all. The observed line is
224
+ * `Hermes Agent v0.21.3 (2026.9.14) · upstream 913d4098`; the separator is read
225
+ * past rather than required, because a release that changes its punctuation must
226
+ * not silently turn the floor check into an unknown.
227
+ */
228
+ export declare function parseHermesVersion(raw: unknown): HermesVersionFields | null;
229
+ /**
230
+ * Does this Hermes build honour `fail_closed`?
231
+ *
232
+ * - `"honours"` — its upstream commit IS the floor's, or its build date is on or
233
+ * after the floor's date;
234
+ * - `"ignores"` — its build date is BEFORE the floor's. This is the one answer
235
+ * that names a fault, and it is the state a live probe measured rather than
236
+ * inferred;
237
+ * - `"unknown"` — no version could be read, or the line carries neither a build
238
+ * date nor the floor's commit. Two commit hashes cannot be ORDERED without a
239
+ * repository, so a build stamped with an unfamiliar commit and no date is
240
+ * honestly unknown rather than quietly either.
241
+ *
242
+ * `"unknown"` is not a synonym for `"ignores"`, deliberately. This value feeds a
243
+ * health check, and a health check that cried fault on every unreadable banner
244
+ * would train an operator to stop reading it, which costs more than the case it
245
+ * would catch. What guards the unknown case instead is the doc, the help block
246
+ * and the probe's own report, all of which state {@link
247
+ * HERMES_FAIL_CLOSED_FLOOR.statement} verbatim.
248
+ */
249
+ export declare function hermesFailClosedSupport(raw: unknown): "honours" | "ignores" | "unknown";
126
250
  /**
127
251
  * The provenance pair a hook-written record carries, or `null` when this
128
252
  * process could not establish one.
@@ -54,7 +54,14 @@
54
54
  import { spawnSync } from "node:child_process";
55
55
  import { childEnvironment } from "./child-env.js";
56
56
  /** The harnesses this runtime speaks a hook protocol for. */
57
- export const HARNESS_KINDS = ["claude-code", "cursor", "codex"];
57
+ export const HARNESS_KINDS = [
58
+ "claude-code",
59
+ "cursor",
60
+ "codex",
61
+ "grok",
62
+ "muse",
63
+ "hermes",
64
+ ];
58
65
  /** Is `value` one of the harnesses this runtime knows? */
59
66
  export function isHarnessKind(value) {
60
67
  return typeof value === "string" && HARNESS_KINDS.includes(value);
@@ -69,6 +76,9 @@ export const HARNESS_BINARY = {
69
76
  "claude-code": "claude",
70
77
  cursor: "cursor-agent",
71
78
  codex: "codex",
79
+ grok: "grok",
80
+ muse: "muse",
81
+ hermes: "hermes",
72
82
  };
73
83
  /**
74
84
  * How long a version string may be, and the reason there is a cap at all.
@@ -119,7 +129,40 @@ export function normalizeHarnessVersion(raw) {
119
129
  */
120
130
  export const HARNESS_PROBE_TIMEOUT_MS = 10_000;
121
131
  /**
122
- * Run `<binary> --version` once, uncached, and normalize what came back.
132
+ * How long the RAW first line of `<binary> --version` may be.
133
+ *
134
+ * Wider than {@link HARNESS_VERSION_LIMIT} because it holds a different kind of
135
+ * value for a different reader: nothing capped by this number is ever appended to
136
+ * the log (only {@link normalizeHarnessVersion}'s output is), and what needs the
137
+ * raw line is a diagnostic that must be able to read a build stamp a harness
138
+ * prints beside its semver. Hermes prints
139
+ * `Hermes Agent v0.21.3 (2026.9.14) · upstream 913d4098`, which the log's own
140
+ * rule rejects on the non-ASCII separator alone. Capped and stripped of control
141
+ * characters all the same: this is third-party output on its way to a terminal.
142
+ */
143
+ export const HARNESS_RAW_VERSION_LIMIT = 200;
144
+ /**
145
+ * The first line of a `--version` output, as a line a diagnostic may print.
146
+ *
147
+ * One line, trimmed, control characters removed, capped. `null` for empty output
148
+ * or a line past the cap. It keeps non-ASCII bytes, which is the whole difference
149
+ * from {@link normalizeHarnessVersion}: a build stamp behind a typographic
150
+ * separator is exactly the fact a version floor has to read, and it is exactly
151
+ * the fact the write boundary will not accept.
152
+ */
153
+ export function rawHarnessVersionLine(raw) {
154
+ if (typeof raw !== "string")
155
+ return null;
156
+ const first = raw.split("\n", 1)[0] ?? "";
157
+ // `\p{Cc}` rather than an escaped range: the class is the Unicode CONTROL
158
+ // category, which is the thing being removed, and it reads as that.
159
+ const text = first.replace(/\p{Cc}/gu, "").trim();
160
+ if (text.length === 0 || text.length > HARNESS_RAW_VERSION_LIMIT)
161
+ return null;
162
+ return text;
163
+ }
164
+ /**
165
+ * Run `<binary> --version` once, uncached, and return its raw first line.
123
166
  *
124
167
  * Every failure is a value rather than an exception, in the manner of
125
168
  * {@link spawnGloss}: a missing binary, a non-zero exit and a timeout kill are
@@ -130,7 +173,7 @@ export const HARNESS_PROBE_TIMEOUT_MS = 10_000;
130
173
  * vault passphrase, and it has no use for either. Nothing is declared, because
131
174
  * reading a version is not a granted action.
132
175
  */
133
- export function probeHarnessVersion(kind) {
176
+ export function probeHarnessVersionRaw(kind) {
134
177
  let result;
135
178
  try {
136
179
  result = spawnSync(HARNESS_BINARY[kind], ["--version"], {
@@ -148,32 +191,158 @@ export function probeHarnessVersion(kind) {
148
191
  }
149
192
  if (result.error !== undefined || result.status !== 0)
150
193
  return null;
151
- return normalizeHarnessVersion(result.stdout);
194
+ return rawHarnessVersionLine(result.stdout);
195
+ }
196
+ /**
197
+ * Run `<binary> --version` once, uncached, and normalize what came back.
198
+ *
199
+ * The recordable form: one line, printable ASCII, capped. Exported for the test
200
+ * that proves the memo below is a memo.
201
+ */
202
+ export function probeHarnessVersion(kind) {
203
+ return normalizeHarnessVersion(probeHarnessVersionRaw(kind));
152
204
  }
153
205
  /**
154
206
  * The memo. Holds the FAILURES too: a harness that is not on PATH is not on
155
207
  * PATH, and asking a second time in the same process would pay a second spawn
156
208
  * for the same `null`.
157
- */
158
- const probed = new Map();
159
- /**
160
- * The installed version of `kind`, read at most once per process.
161
209
  *
162
- * This is the only entry point callers should use. `probeHarnessVersion` is
163
- * exported for the test that proves the memo is a memo.
210
+ * It holds the RAW line rather than the recordable one, so the two readers — the
211
+ * provenance field and the version floor — still cost ONE spawn per process
212
+ * between them. A harness whose raw line the write boundary rejects has a
213
+ * `null` recordable version and a readable raw one, which is precisely Hermes's
214
+ * case and precisely why the floor is not read off a record.
164
215
  */
165
- export function installedHarnessVersion(kind) {
216
+ const probed = new Map();
217
+ /** The raw first line of `<binary> --version`, read at most once per process. */
218
+ export function installedHarnessVersionRaw(kind) {
166
219
  const memo = probed.get(kind);
167
220
  if (memo !== undefined)
168
221
  return memo;
169
- const value = probeHarnessVersion(kind);
222
+ const value = probeHarnessVersionRaw(kind);
170
223
  probed.set(kind, value);
171
224
  return value;
172
225
  }
226
+ /**
227
+ * The installed version of `kind`, read at most once per process.
228
+ *
229
+ * This is the only entry point callers should use for a RECORDABLE version.
230
+ * `probeHarnessVersion` is exported for the test that proves the memo is a memo.
231
+ */
232
+ export function installedHarnessVersion(kind) {
233
+ return normalizeHarnessVersion(installedHarnessVersionRaw(kind));
234
+ }
173
235
  /** Drop the memo. TEST ONLY: a process reads a version once, by design. */
174
236
  export function resetHarnessVersionCache() {
175
237
  probed.clear();
176
238
  }
239
+ // ---------------------------------------------------------------------------
240
+ // The Hermes fail-closed version floor (APRV-415)
241
+ // ---------------------------------------------------------------------------
242
+ /**
243
+ * The build at which Hermes Agent starts honouring `fail_closed` (APRV-415).
244
+ *
245
+ * ## Why a floor exists at all, and why it is a DATE rather than a version
246
+ *
247
+ * `approval hook hermes` is enforcement rather than a backstop only because of a
248
+ * per-entry `fail_closed: true` that makes a hook crash, a hook timeout and
249
+ * unparseable hook output BLOCK. The live probe measured both halves of that on
250
+ * two builds of the same harness, and the answer differs between them:
251
+ *
252
+ * - `main` at `118984d7`, built 2026-09-20: crash, garbage and hang were all
253
+ * REFUSED (the hang at the 300s per-entry cap). The key works;
254
+ * - `v0.21.3`, built 2026.9.14: all three PROCEEDED. That build does not know the
255
+ * key and ignores it SILENTLY. `hermes hooks list` renders no `fail_closed`
256
+ * flag on either build, so the listing cannot be used to tell them apart.
257
+ *
258
+ * The two builds report the SAME semver. `hermes --version` on the older one
259
+ * prints `Hermes Agent v0.21.3 (2026.9.14) · upstream 913d4098`, and the update
260
+ * that fixed the behaviour moved 670 commits without moving `0.21.3`. So a floor
261
+ * expressed as a semantic version would compare the one field that did not
262
+ * change, and would pass a build that fails open. The build DATE and the upstream
263
+ * commit are the two fields that did move, and they are what this compares.
264
+ *
265
+ * ## What it can and cannot do
266
+ *
267
+ * It can only ADD a red line to `approval doctor` (SPEC.md §11.1 invariant 4: a
268
+ * self-reported field never reduces scrutiny). A build claiming a later date buys
269
+ * nothing — it defeats a row that would have asked a human to look — and nothing
270
+ * in the runtime reads this to widen a verdict, skip a wait or lower a class. The
271
+ * refusals the adapter emits are the same on every build; what changes below the
272
+ * floor is whether a BROKEN hook stops the call, which no code in this repository
273
+ * can observe from inside the hook it is broken in.
274
+ */
275
+ export const HERMES_FAIL_CLOSED_FLOOR = {
276
+ /** The first build observed to honour the key, by upstream commit. */
277
+ upstream: "118984d7",
278
+ /** That build's date, in the `YYYY.M.D` stamp `hermes --version` prints. */
279
+ date: { year: 2026, month: 9, day: 20 },
280
+ /** The one sentence every surface quotes, so they cannot drift apart. */
281
+ statement: "a build at or after main 118984d7 of 2026-09-20; v0.21.3 (2026.9.14) fails open silently",
282
+ };
283
+ /**
284
+ * Read the fields out of `hermes --version`'s first line, or `null`.
285
+ *
286
+ * Shape-only and forgiving in one direction: a field this cannot find is `null`
287
+ * rather than a guess, and a line naming none of the three is not a Hermes
288
+ * version line at all. The observed line is
289
+ * `Hermes Agent v0.21.3 (2026.9.14) · upstream 913d4098`; the separator is read
290
+ * past rather than required, because a release that changes its punctuation must
291
+ * not silently turn the floor check into an unknown.
292
+ */
293
+ export function parseHermesVersion(raw) {
294
+ const line = rawHarnessVersionLine(raw);
295
+ if (line === null)
296
+ return null;
297
+ const semver = /\bv(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)\b/u.exec(line);
298
+ const stamp = /\((\d{4})\.(\d{1,2})\.(\d{1,2})\)/u.exec(line);
299
+ const upstream = /\bupstream\s+([0-9a-f]{7,40})\b/iu.exec(line);
300
+ if (semver === null && stamp === null && upstream === null)
301
+ return null;
302
+ return {
303
+ semver: semver?.[1] ?? null,
304
+ date: stamp === null
305
+ ? null
306
+ : {
307
+ year: Number(stamp[1]),
308
+ month: Number(stamp[2]),
309
+ day: Number(stamp[3]),
310
+ },
311
+ upstream: upstream?.[1]?.toLowerCase() ?? null,
312
+ };
313
+ }
314
+ /**
315
+ * Does this Hermes build honour `fail_closed`?
316
+ *
317
+ * - `"honours"` — its upstream commit IS the floor's, or its build date is on or
318
+ * after the floor's date;
319
+ * - `"ignores"` — its build date is BEFORE the floor's. This is the one answer
320
+ * that names a fault, and it is the state a live probe measured rather than
321
+ * inferred;
322
+ * - `"unknown"` — no version could be read, or the line carries neither a build
323
+ * date nor the floor's commit. Two commit hashes cannot be ORDERED without a
324
+ * repository, so a build stamped with an unfamiliar commit and no date is
325
+ * honestly unknown rather than quietly either.
326
+ *
327
+ * `"unknown"` is not a synonym for `"ignores"`, deliberately. This value feeds a
328
+ * health check, and a health check that cried fault on every unreadable banner
329
+ * would train an operator to stop reading it, which costs more than the case it
330
+ * would catch. What guards the unknown case instead is the doc, the help block
331
+ * and the probe's own report, all of which state {@link
332
+ * HERMES_FAIL_CLOSED_FLOOR.statement} verbatim.
333
+ */
334
+ export function hermesFailClosedSupport(raw) {
335
+ const fields = parseHermesVersion(raw);
336
+ if (fields === null)
337
+ return "unknown";
338
+ const floor = HERMES_FAIL_CLOSED_FLOOR;
339
+ if (fields.upstream !== null && fields.upstream.startsWith(floor.upstream))
340
+ return "honours";
341
+ if (fields.date === null)
342
+ return "unknown";
343
+ const asNumber = (date) => date.year * 10_000 + date.month * 100 + date.day;
344
+ return asNumber(fields.date) >= asNumber(floor.date) ? "honours" : "ignores";
345
+ }
177
346
  /**
178
347
  * Build the pair for `kind`, preferring the version the hook event supplied.
179
348
  *
@@ -1 +1 @@
1
- {"version":3,"file":"harness-version.js","sourceRoot":"","sources":["../../../src/core/harness-version.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"harness-version.js","sourceRoot":"","sources":["../../../src/core/harness-version.ts"],"names":[],"mappings":"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"}