@lannguyensi/harness 0.64.0 → 1.0.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 (710) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +46 -42
  3. package/dist/cli/add/index.js +17 -21
  4. package/dist/cli/add/index.js.map +1 -1
  5. package/dist/cli/adopt/derive.d.ts +2 -2
  6. package/dist/cli/adopt/derive.js +2 -19
  7. package/dist/cli/adopt/derive.js.map +1 -1
  8. package/dist/cli/adopt/index.d.ts +1 -1
  9. package/dist/cli/adopt/index.js +1 -12
  10. package/dist/cli/adopt/index.js.map +1 -1
  11. package/dist/cli/apply/apply.d.ts +20 -35
  12. package/dist/cli/apply/apply.js +61 -136
  13. package/dist/cli/apply/apply.js.map +1 -1
  14. package/dist/cli/apply/generate-codex-config.js +10 -58
  15. package/dist/cli/apply/generate-codex-config.js.map +1 -1
  16. package/dist/cli/apply/generate-memory-index.js +1 -2
  17. package/dist/cli/apply/generate-memory-index.js.map +1 -1
  18. package/dist/cli/apply/generate-opencode-config.d.ts +2 -10
  19. package/dist/cli/apply/generate-opencode-config.js +74 -113
  20. package/dist/cli/apply/generate-opencode-config.js.map +1 -1
  21. package/dist/cli/apply/generate-settings.d.ts +11 -64
  22. package/dist/cli/apply/generate-settings.js +27 -132
  23. package/dist/cli/apply/generate-settings.js.map +1 -1
  24. package/dist/cli/apply/index.d.ts +1 -1
  25. package/dist/cli/apply/index.js +1 -1
  26. package/dist/cli/apply/index.js.map +1 -1
  27. package/dist/cli/apply/install-codex-config.d.ts +153 -1
  28. package/dist/cli/apply/install-codex-config.js +445 -70
  29. package/dist/cli/apply/install-codex-config.js.map +1 -1
  30. package/dist/cli/apply/next-steps.d.ts +7 -0
  31. package/dist/cli/apply/next-steps.js +13 -1
  32. package/dist/cli/apply/next-steps.js.map +1 -1
  33. package/dist/cli/bounded-stdin.d.ts +0 -23
  34. package/dist/cli/bounded-stdin.js +2 -49
  35. package/dist/cli/bounded-stdin.js.map +1 -1
  36. package/dist/cli/describe.d.ts +1 -1
  37. package/dist/cli/describe.js +0 -3
  38. package/dist/cli/describe.js.map +1 -1
  39. package/dist/cli/diff/engine.d.ts +0 -11
  40. package/dist/cli/diff/engine.js +1 -17
  41. package/dist/cli/diff/engine.js.map +1 -1
  42. package/dist/cli/diff/index.js +14 -25
  43. package/dist/cli/diff/index.js.map +1 -1
  44. package/dist/cli/doctor/claude-mcp.d.ts +4 -19
  45. package/dist/cli/doctor/claude-mcp.js +11 -22
  46. package/dist/cli/doctor/claude-mcp.js.map +1 -1
  47. package/dist/cli/doctor/codex.d.ts +12 -14
  48. package/dist/cli/doctor/codex.js +31 -144
  49. package/dist/cli/doctor/codex.js.map +1 -1
  50. package/dist/cli/doctor/format.js +23 -345
  51. package/dist/cli/doctor/format.js.map +1 -1
  52. package/dist/cli/doctor/hook-liveness.d.ts +56 -0
  53. package/dist/cli/doctor/hook-liveness.js +455 -0
  54. package/dist/cli/doctor/hook-liveness.js.map +1 -0
  55. package/dist/cli/doctor/index.d.ts +13 -87
  56. package/dist/cli/doctor/index.js +57 -713
  57. package/dist/cli/doctor/index.js.map +1 -1
  58. package/dist/cli/doctor/opencode.d.ts +2 -1
  59. package/dist/cli/doctor/opencode.js.map +1 -1
  60. package/dist/cli/doctor/types.d.ts +21 -387
  61. package/dist/cli/doctor/types.js.map +1 -1
  62. package/dist/cli/drain-stdio.d.ts +31 -0
  63. package/dist/cli/drain-stdio.js +76 -0
  64. package/dist/cli/drain-stdio.js.map +1 -0
  65. package/dist/cli/export.d.ts +3 -1
  66. package/dist/cli/export.js +7 -16
  67. package/dist/cli/export.js.map +1 -1
  68. package/dist/cli/gate/codex-disable.d.ts +29 -0
  69. package/dist/cli/gate/codex-disable.js +195 -0
  70. package/dist/cli/gate/codex-disable.js.map +1 -0
  71. package/dist/cli/gate/codex-enable.d.ts +41 -0
  72. package/dist/cli/gate/codex-enable.js +127 -0
  73. package/dist/cli/gate/codex-enable.js.map +1 -0
  74. package/dist/cli/gate/codex-snapshot.d.ts +208 -0
  75. package/dist/cli/gate/codex-snapshot.js +402 -0
  76. package/dist/cli/gate/codex-snapshot.js.map +1 -0
  77. package/dist/cli/gate/disable.d.ts +9 -0
  78. package/dist/cli/gate/disable.js +263 -28
  79. package/dist/cli/gate/disable.js.map +1 -1
  80. package/dist/cli/gate/enable.d.ts +26 -6
  81. package/dist/cli/gate/enable.js +152 -80
  82. package/dist/cli/gate/enable.js.map +1 -1
  83. package/dist/cli/gate/link-chain.d.ts +53 -0
  84. package/dist/cli/gate/link-chain.js +122 -0
  85. package/dist/cli/gate/link-chain.js.map +1 -0
  86. package/dist/cli/gate/snapshot.d.ts +289 -12
  87. package/dist/cli/gate/snapshot.js +481 -22
  88. package/dist/cli/gate/snapshot.js.map +1 -1
  89. package/dist/cli/index.d.ts +0 -9
  90. package/dist/cli/index.js +9 -2131
  91. package/dist/cli/index.js.map +1 -1
  92. package/dist/cli/init/composer.d.ts +3 -6
  93. package/dist/cli/init/composer.js +6 -370
  94. package/dist/cli/init/composer.js.map +1 -1
  95. package/dist/cli/init/dependencies.d.ts +1 -2
  96. package/dist/cli/init/dependencies.js +4 -80
  97. package/dist/cli/init/dependencies.js.map +1 -1
  98. package/dist/cli/init/detect.js +5 -4
  99. package/dist/cli/init/detect.js.map +1 -1
  100. package/dist/cli/init/interactive.d.ts +1 -23
  101. package/dist/cli/init/interactive.js +33 -247
  102. package/dist/cli/init/interactive.js.map +1 -1
  103. package/dist/cli/init/profiles.d.ts +2 -2
  104. package/dist/cli/init/profiles.js +51 -245
  105. package/dist/cli/init/profiles.js.map +1 -1
  106. package/dist/cli/init/templates.d.ts +2 -37
  107. package/dist/cli/init/templates.js +25 -1237
  108. package/dist/cli/init/templates.js.map +1 -1
  109. package/dist/cli/list.d.ts +1 -1
  110. package/dist/cli/list.js +1 -38
  111. package/dist/cli/list.js.map +1 -1
  112. package/dist/cli/loader.d.ts +15 -1
  113. package/dist/cli/loader.js +56 -39
  114. package/dist/cli/loader.js.map +1 -1
  115. package/dist/cli/main.js +7 -2
  116. package/dist/cli/main.js.map +1 -1
  117. package/dist/cli/migrate-home/index.js +2 -2
  118. package/dist/cli/migrate-home/index.js.map +1 -1
  119. package/dist/cli/pack/add.js +1 -1
  120. package/dist/cli/pack/add.js.map +1 -1
  121. package/dist/cli/pack/hook-bootstrap.d.ts +5 -164
  122. package/dist/cli/pack/hook-bootstrap.js +15 -291
  123. package/dist/cli/pack/hook-bootstrap.js.map +1 -1
  124. package/dist/cli/pack/hook-branch-protection.d.ts +28 -21
  125. package/dist/cli/pack/hook-branch-protection.js +365 -340
  126. package/dist/cli/pack/hook-branch-protection.js.map +1 -1
  127. package/dist/cli/pack/index.d.ts +0 -1
  128. package/dist/cli/pack/index.js +0 -1
  129. package/dist/cli/pack/index.js.map +1 -1
  130. package/dist/cli/pack/list.js +1 -6
  131. package/dist/cli/pack/list.js.map +1 -1
  132. package/dist/cli/pack/mutate.d.ts +7 -9
  133. package/dist/cli/pack/mutate.js +6 -9
  134. package/dist/cli/pack/mutate.js.map +1 -1
  135. package/dist/cli/pack/reseed.d.ts +2 -2
  136. package/dist/cli/pack/reseed.js +16 -22
  137. package/dist/cli/pack/reseed.js.map +1 -1
  138. package/dist/cli/{delegate/register.d.ts → register-gate-group.d.ts} +1 -1
  139. package/dist/cli/register-gate-group.js +348 -0
  140. package/dist/cli/register-gate-group.js.map +1 -0
  141. package/dist/cli/register-inspect-group.d.ts +6 -0
  142. package/dist/cli/register-inspect-group.js +189 -0
  143. package/dist/cli/register-inspect-group.js.map +1 -0
  144. package/dist/cli/register-operator-lifecycle.d.ts +1 -1
  145. package/dist/cli/register-operator-lifecycle.js +3 -100
  146. package/dist/cli/register-operator-lifecycle.js.map +1 -1
  147. package/dist/cli/register-pack-group.d.ts +5 -0
  148. package/dist/cli/register-pack-group.js +134 -0
  149. package/dist/cli/register-pack-group.js.map +1 -0
  150. package/dist/cli/{register-audit-group.d.ts → register-setup-group.d.ts} +1 -1
  151. package/dist/cli/register-setup-group.js +495 -0
  152. package/dist/cli/register-setup-group.js.map +1 -0
  153. package/dist/cli/remove/index.d.ts +0 -14
  154. package/dist/cli/remove/index.js +2 -115
  155. package/dist/cli/remove/index.js.map +1 -1
  156. package/dist/cli/remove/mutate.d.ts +0 -2
  157. package/dist/cli/remove/mutate.js +1 -19
  158. package/dist/cli/remove/mutate.js.map +1 -1
  159. package/dist/cli/remove/register.js +2 -19
  160. package/dist/cli/remove/register.js.map +1 -1
  161. package/dist/cli/shell-quote.d.ts +7 -0
  162. package/dist/cli/shell-quote.js +17 -0
  163. package/dist/cli/shell-quote.js.map +1 -0
  164. package/dist/cli/uninstall/index.d.ts +4 -2
  165. package/dist/cli/uninstall/index.js +15 -7
  166. package/dist/cli/uninstall/index.js.map +1 -1
  167. package/dist/cli/uninstall/register.js +6 -4
  168. package/dist/cli/uninstall/register.js.map +1 -1
  169. package/dist/cli/uninstall/snapshot.d.ts +15 -0
  170. package/dist/cli/uninstall/snapshot.js +38 -0
  171. package/dist/cli/uninstall/snapshot.js.map +1 -1
  172. package/dist/cli/validate/checks.d.ts +0 -77
  173. package/dist/cli/validate/checks.js +3 -1049
  174. package/dist/cli/validate/checks.js.map +1 -1
  175. package/dist/cli/validate/index.js +19 -15
  176. package/dist/cli/validate/index.js.map +1 -1
  177. package/dist/index.d.ts +0 -3
  178. package/dist/index.js +0 -3
  179. package/dist/index.js.map +1 -1
  180. package/dist/io/claude-mcp.d.ts +1 -1
  181. package/dist/io/claude-mcp.js +27 -14
  182. package/dist/io/claude-mcp.js.map +1 -1
  183. package/dist/io/harness-lock.js +2 -2
  184. package/dist/io/harness-lock.js.map +1 -1
  185. package/dist/io/lock.d.ts +0 -26
  186. package/dist/io/lock.js +10 -27
  187. package/dist/io/lock.js.map +1 -1
  188. package/dist/io/merge-settings.js +6 -4
  189. package/dist/io/merge-settings.js.map +1 -1
  190. package/dist/io/project-name.d.ts +22 -39
  191. package/dist/io/project-name.js +25 -42
  192. package/dist/io/project-name.js.map +1 -1
  193. package/dist/io/read-regular-file.d.ts +103 -40
  194. package/dist/io/read-regular-file.js +196 -35
  195. package/dist/io/read-regular-file.js.map +1 -1
  196. package/dist/io/restart-hints.js +3 -6
  197. package/dist/io/restart-hints.js.map +1 -1
  198. package/dist/io/version-compare.d.ts +1 -3
  199. package/dist/io/version-compare.js +1 -3
  200. package/dist/io/version-compare.js.map +1 -1
  201. package/dist/io/write-regular-file.d.ts +30 -0
  202. package/dist/io/write-regular-file.js +85 -0
  203. package/dist/io/write-regular-file.js.map +1 -0
  204. package/dist/overrides/index.d.ts +1 -0
  205. package/dist/overrides/index.js +1 -0
  206. package/dist/overrides/index.js.map +1 -1
  207. package/dist/overrides/merge-layers.d.ts +43 -0
  208. package/dist/overrides/merge-layers.js +76 -0
  209. package/dist/overrides/merge-layers.js.map +1 -0
  210. package/dist/overrides/merge.d.ts +16 -0
  211. package/dist/overrides/merge.js +21 -8
  212. package/dist/overrides/merge.js.map +1 -1
  213. package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +4 -69
  214. package/dist/policy-packs/builtin/branch-protection-runtime.js +12 -84
  215. package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -1
  216. package/dist/policy-packs/builtin/branch-protection.d.ts +7 -30
  217. package/dist/policy-packs/builtin/branch-protection.js +56 -89
  218. package/dist/policy-packs/builtin/branch-protection.js.map +1 -1
  219. package/dist/policy-packs/config-check.d.ts +7 -5
  220. package/dist/policy-packs/config-check.js +2 -2
  221. package/dist/policy-packs/config-check.js.map +1 -1
  222. package/dist/policy-packs/expand.d.ts +1 -3
  223. package/dist/policy-packs/expand.js +5 -42
  224. package/dist/policy-packs/expand.js.map +1 -1
  225. package/dist/policy-packs/index.d.ts +3 -3
  226. package/dist/policy-packs/index.js +2 -2
  227. package/dist/policy-packs/index.js.map +1 -1
  228. package/dist/policy-packs/registry.d.ts +9 -38
  229. package/dist/policy-packs/registry.js +5 -65
  230. package/dist/policy-packs/registry.js.map +1 -1
  231. package/dist/policy-packs/runtime.d.ts +0 -4
  232. package/dist/policy-packs/runtime.js +9 -22
  233. package/dist/policy-packs/runtime.js.map +1 -1
  234. package/dist/policy-packs/types.d.ts +0 -19
  235. package/dist/policy-packs/ux-compare.d.ts +1 -11
  236. package/dist/policy-packs/ux-compare.js +6 -42
  237. package/dist/policy-packs/ux-compare.js.map +1 -1
  238. package/dist/policy-packs/ux-drift-check.d.ts +5 -5
  239. package/dist/policy-packs/ux-drift-check.js +17 -22
  240. package/dist/policy-packs/ux-drift-check.js.map +1 -1
  241. package/dist/policy-packs/version-check.d.ts +5 -26
  242. package/dist/policy-packs/version-check.js +19 -74
  243. package/dist/policy-packs/version-check.js.map +1 -1
  244. package/dist/probes/memory.d.ts +1 -1
  245. package/dist/probes/memory.js +1 -1
  246. package/dist/probes/memory.js.map +1 -1
  247. package/dist/runtime/agent-facing.d.ts +9 -0
  248. package/dist/runtime/agent-facing.js +28 -14
  249. package/dist/runtime/agent-facing.js.map +1 -1
  250. package/dist/runtime/bounded-text.d.ts +15 -0
  251. package/dist/runtime/bounded-text.js +27 -0
  252. package/dist/runtime/bounded-text.js.map +1 -0
  253. package/dist/runtime/git-branch.d.ts +125 -0
  254. package/dist/runtime/git-branch.js +381 -0
  255. package/dist/runtime/git-branch.js.map +1 -0
  256. package/dist/runtime/hermetic-spawn-guard.d.ts +2 -2
  257. package/dist/runtime/hermetic-spawn-guard.js +24 -34
  258. package/dist/runtime/hermetic-spawn-guard.js.map +1 -1
  259. package/dist/runtime/home-dir.js +3 -2
  260. package/dist/runtime/home-dir.js.map +1 -1
  261. package/dist/runtime/tool-name-aliases.d.ts +0 -6
  262. package/dist/runtime/tool-name-aliases.js +5 -18
  263. package/dist/runtime/tool-name-aliases.js.map +1 -1
  264. package/dist/schema/grounding.d.ts +7 -54
  265. package/dist/schema/grounding.js +10 -12
  266. package/dist/schema/grounding.js.map +1 -1
  267. package/dist/schema/hooks.d.ts +39 -136
  268. package/dist/schema/hooks.js +3 -6
  269. package/dist/schema/hooks.js.map +1 -1
  270. package/dist/schema/index.d.ts +114 -3828
  271. package/dist/schema/index.js +41 -80
  272. package/dist/schema/index.js.map +1 -1
  273. package/dist/schema/memory.d.ts +54 -131
  274. package/dist/schema/memory.js +2 -2
  275. package/dist/schema/memory.js.map +1 -1
  276. package/dist/schema/policy-packs.d.ts +3 -45
  277. package/dist/schema/policy-packs.js +7 -13
  278. package/dist/schema/policy-packs.js.map +1 -1
  279. package/dist/schema/policy-ux.d.ts +7 -0
  280. package/dist/schema/policy-ux.js +18 -0
  281. package/dist/schema/policy-ux.js.map +1 -0
  282. package/dist/schema/removed-keys.d.ts +185 -0
  283. package/dist/schema/removed-keys.js +531 -0
  284. package/dist/schema/removed-keys.js.map +1 -0
  285. package/dist/schema/tools.d.ts +30 -268
  286. package/dist/schema/tools.js +4 -4
  287. package/dist/schema/tools.js.map +1 -1
  288. package/package.json +5 -16
  289. package/dist/cli/approve/branch-protection.d.ts +0 -69
  290. package/dist/cli/approve/branch-protection.js +0 -144
  291. package/dist/cli/approve/branch-protection.js.map +0 -1
  292. package/dist/cli/approve/risk.d.ts +0 -112
  293. package/dist/cli/approve/risk.js +0 -197
  294. package/dist/cli/approve/risk.js.map +0 -1
  295. package/dist/cli/approve/stdin-report.d.ts +0 -57
  296. package/dist/cli/approve/stdin-report.js +0 -145
  297. package/dist/cli/approve/stdin-report.js.map +0 -1
  298. package/dist/cli/approve/understanding.d.ts +0 -410
  299. package/dist/cli/approve/understanding.js +0 -996
  300. package/dist/cli/approve/understanding.js.map +0 -1
  301. package/dist/cli/audit.d.ts +0 -80
  302. package/dist/cli/audit.js +0 -252
  303. package/dist/cli/audit.js.map +0 -1
  304. package/dist/cli/delegate/index.d.ts +0 -76
  305. package/dist/cli/delegate/index.js +0 -444
  306. package/dist/cli/delegate/index.js.map +0 -1
  307. package/dist/cli/delegate/register.js +0 -90
  308. package/dist/cli/delegate/register.js.map +0 -1
  309. package/dist/cli/doctor/auto-approve-mode.d.ts +0 -37
  310. package/dist/cli/doctor/auto-approve-mode.js +0 -80
  311. package/dist/cli/doctor/auto-approve-mode.js.map +0 -1
  312. package/dist/cli/doctor/bypass-without-auto-approve.d.ts +0 -38
  313. package/dist/cli/doctor/bypass-without-auto-approve.js +0 -95
  314. package/dist/cli/doctor/bypass-without-auto-approve.js.map +0 -1
  315. package/dist/cli/doctor/codex-config-drift.d.ts +0 -28
  316. package/dist/cli/doctor/codex-config-drift.js +0 -240
  317. package/dist/cli/doctor/codex-config-drift.js.map +0 -1
  318. package/dist/cli/doctor/expire-on-tool-match.d.ts +0 -15
  319. package/dist/cli/doctor/expire-on-tool-match.js +0 -58
  320. package/dist/cli/doctor/expire-on-tool-match.js.map +0 -1
  321. package/dist/cli/doctor/rogue-ledger.d.ts +0 -53
  322. package/dist/cli/doctor/rogue-ledger.js +0 -153
  323. package/dist/cli/doctor/rogue-ledger.js.map +0 -1
  324. package/dist/cli/doctor/session-start-preflight-setup-version.d.ts +0 -83
  325. package/dist/cli/doctor/session-start-preflight-setup-version.js +0 -114
  326. package/dist/cli/doctor/session-start-preflight-setup-version.js.map +0 -1
  327. package/dist/cli/doctor/settings-drift.d.ts +0 -25
  328. package/dist/cli/doctor/settings-drift.js +0 -213
  329. package/dist/cli/doctor/settings-drift.js.map +0 -1
  330. package/dist/cli/doctor/toolchain-parity.d.ts +0 -63
  331. package/dist/cli/doctor/toolchain-parity.js +0 -154
  332. package/dist/cli/doctor/toolchain-parity.js.map +0 -1
  333. package/dist/cli/doctor/ug-auto-approvals.d.ts +0 -40
  334. package/dist/cli/doctor/ug-auto-approvals.js +0 -91
  335. package/dist/cli/doctor/ug-auto-approvals.js.map +0 -1
  336. package/dist/cli/doctor/ug-delegations.d.ts +0 -26
  337. package/dist/cli/doctor/ug-delegations.js +0 -121
  338. package/dist/cli/doctor/ug-delegations.js.map +0 -1
  339. package/dist/cli/doctor/ug-inflight.d.ts +0 -35
  340. package/dist/cli/doctor/ug-inflight.js +0 -57
  341. package/dist/cli/doctor/ug-inflight.js.map +0 -1
  342. package/dist/cli/doctor/understanding-mode-env.d.ts +0 -51
  343. package/dist/cli/doctor/understanding-mode-env.js +0 -98
  344. package/dist/cli/doctor/understanding-mode-env.js.map +0 -1
  345. package/dist/cli/dry-run.d.ts +0 -58
  346. package/dist/cli/dry-run.js +0 -283
  347. package/dist/cli/dry-run.js.map +0 -1
  348. package/dist/cli/enriched-event.d.ts +0 -35
  349. package/dist/cli/enriched-event.js +0 -60
  350. package/dist/cli/enriched-event.js.map +0 -1
  351. package/dist/cli/event-input.d.ts +0 -28
  352. package/dist/cli/event-input.js +0 -73
  353. package/dist/cli/event-input.js.map +0 -1
  354. package/dist/cli/explain-action.d.ts +0 -25
  355. package/dist/cli/explain-action.js +0 -57
  356. package/dist/cli/explain-action.js.map +0 -1
  357. package/dist/cli/explain-policy.d.ts +0 -147
  358. package/dist/cli/explain-policy.js +0 -248
  359. package/dist/cli/explain-policy.js.map +0 -1
  360. package/dist/cli/explain.d.ts +0 -31
  361. package/dist/cli/explain.js +0 -159
  362. package/dist/cli/explain.js.map +0 -1
  363. package/dist/cli/gc/index.d.ts +0 -63
  364. package/dist/cli/gc/index.js +0 -566
  365. package/dist/cli/gc/index.js.map +0 -1
  366. package/dist/cli/pack/approve-escape.d.ts +0 -19
  367. package/dist/cli/pack/approve-escape.js +0 -190
  368. package/dist/cli/pack/approve-escape.js.map +0 -1
  369. package/dist/cli/pack/auto-approve-path.d.ts +0 -146
  370. package/dist/cli/pack/auto-approve-path.js +0 -462
  371. package/dist/cli/pack/auto-approve-path.js.map +0 -1
  372. package/dist/cli/pack/hook-codex-post-tool-use.d.ts +0 -25
  373. package/dist/cli/pack/hook-codex-post-tool-use.js +0 -160
  374. package/dist/cli/pack/hook-codex-post-tool-use.js.map +0 -1
  375. package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +0 -48
  376. package/dist/cli/pack/hook-codex-pre-tool-use.js +0 -474
  377. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +0 -1
  378. package/dist/cli/pack/hook-codex-stop.d.ts +0 -35
  379. package/dist/cli/pack/hook-codex-stop.js +0 -329
  380. package/dist/cli/pack/hook-codex-stop.js.map +0 -1
  381. package/dist/cli/pack/hook-codex-user-prompt-submit.d.ts +0 -24
  382. package/dist/cli/pack/hook-codex-user-prompt-submit.js +0 -93
  383. package/dist/cli/pack/hook-codex-user-prompt-submit.js.map +0 -1
  384. package/dist/cli/pack/hook-post-merge-gate-record.d.ts +0 -37
  385. package/dist/cli/pack/hook-post-merge-gate-record.js +0 -190
  386. package/dist/cli/pack/hook-post-merge-gate-record.js.map +0 -1
  387. package/dist/cli/pack/hook-post-merge-gate.d.ts +0 -34
  388. package/dist/cli/pack/hook-post-merge-gate.js +0 -277
  389. package/dist/cli/pack/hook-post-merge-gate.js.map +0 -1
  390. package/dist/cli/pack/hook-post-tool-use.d.ts +0 -45
  391. package/dist/cli/pack/hook-post-tool-use.js +0 -137
  392. package/dist/cli/pack/hook-post-tool-use.js.map +0 -1
  393. package/dist/cli/pack/hook-pre-tool-use.d.ts +0 -92
  394. package/dist/cli/pack/hook-pre-tool-use.js +0 -1328
  395. package/dist/cli/pack/hook-pre-tool-use.js.map +0 -1
  396. package/dist/cli/pack/hook-runtime-reality.d.ts +0 -63
  397. package/dist/cli/pack/hook-runtime-reality.js +0 -210
  398. package/dist/cli/pack/hook-runtime-reality.js.map +0 -1
  399. package/dist/cli/pack/hook-solution-acceptance-writeguard.d.ts +0 -32
  400. package/dist/cli/pack/hook-solution-acceptance-writeguard.js +0 -438
  401. package/dist/cli/pack/hook-solution-acceptance-writeguard.js.map +0 -1
  402. package/dist/cli/pack/hook-solution-acceptance.d.ts +0 -157
  403. package/dist/cli/pack/hook-solution-acceptance.js +0 -530
  404. package/dist/cli/pack/hook-solution-acceptance.js.map +0 -1
  405. package/dist/cli/pack/hook-stay-in-scope.d.ts +0 -37
  406. package/dist/cli/pack/hook-stay-in-scope.js +0 -128
  407. package/dist/cli/pack/hook-stay-in-scope.js.map +0 -1
  408. package/dist/cli/pack/hook-subagent-start.d.ts +0 -23
  409. package/dist/cli/pack/hook-subagent-start.js +0 -88
  410. package/dist/cli/pack/hook-subagent-start.js.map +0 -1
  411. package/dist/cli/pack/hook-subagent-stop.d.ts +0 -19
  412. package/dist/cli/pack/hook-subagent-stop.js +0 -41
  413. package/dist/cli/pack/hook-subagent-stop.js.map +0 -1
  414. package/dist/cli/pack/hook-track-active-claim.d.ts +0 -27
  415. package/dist/cli/pack/hook-track-active-claim.js +0 -275
  416. package/dist/cli/pack/hook-track-active-claim.js.map +0 -1
  417. package/dist/cli/pack/transcript-report-scan.d.ts +0 -71
  418. package/dist/cli/pack/transcript-report-scan.js +0 -359
  419. package/dist/cli/pack/transcript-report-scan.js.map +0 -1
  420. package/dist/cli/pack/understanding-report-schema-hint.d.ts +0 -26
  421. package/dist/cli/pack/understanding-report-schema-hint.js +0 -120
  422. package/dist/cli/pack/understanding-report-schema-hint.js.map +0 -1
  423. package/dist/cli/pack/upgrade.d.ts +0 -32
  424. package/dist/cli/pack/upgrade.js +0 -273
  425. package/dist/cli/pack/upgrade.js.map +0 -1
  426. package/dist/cli/pause/index.d.ts +0 -113
  427. package/dist/cli/pause/index.js +0 -251
  428. package/dist/cli/pause/index.js.map +0 -1
  429. package/dist/cli/pause-check.d.ts +0 -22
  430. package/dist/cli/pause-check.js +0 -54
  431. package/dist/cli/pause-check.js.map +0 -1
  432. package/dist/cli/policy/intercept.d.ts +0 -233
  433. package/dist/cli/policy/intercept.js +0 -1022
  434. package/dist/cli/policy/intercept.js.map +0 -1
  435. package/dist/cli/policy/risk-envelope-enrichment.d.ts +0 -40
  436. package/dist/cli/policy/risk-envelope-enrichment.js +0 -110
  437. package/dist/cli/policy/risk-envelope-enrichment.js.map +0 -1
  438. package/dist/cli/record/index.d.ts +0 -81
  439. package/dist/cli/record/index.js +0 -348
  440. package/dist/cli/record/index.js.map +0 -1
  441. package/dist/cli/register-audit-group.js +0 -91
  442. package/dist/cli/register-audit-group.js.map +0 -1
  443. package/dist/cli/resolve-env.d.ts +0 -32
  444. package/dist/cli/resolve-env.js +0 -46
  445. package/dist/cli/resolve-env.js.map +0 -1
  446. package/dist/cli/session-export/index.d.ts +0 -46
  447. package/dist/cli/session-export/index.js +0 -169
  448. package/dist/cli/session-export/index.js.map +0 -1
  449. package/dist/cli/session-export/redact.d.ts +0 -22
  450. package/dist/cli/session-export/redact.js +0 -47
  451. package/dist/cli/session-export/redact.js.map +0 -1
  452. package/dist/cli/session-export/transcript.d.ts +0 -24
  453. package/dist/cli/session-export/transcript.js +0 -164
  454. package/dist/cli/session-export/transcript.js.map +0 -1
  455. package/dist/cli/session-start/branch-check.d.ts +0 -18
  456. package/dist/cli/session-start/branch-check.js +0 -140
  457. package/dist/cli/session-start/branch-check.js.map +0 -1
  458. package/dist/cli/session-start/index.d.ts +0 -121
  459. package/dist/cli/session-start/index.js +0 -591
  460. package/dist/cli/session-start/index.js.map +0 -1
  461. package/dist/cli/session-start/shared-options.d.ts +0 -103
  462. package/dist/cli/session-start/shared-options.js +0 -107
  463. package/dist/cli/session-start/shared-options.js.map +0 -1
  464. package/dist/cli/session-start/stale-base-check.d.ts +0 -46
  465. package/dist/cli/session-start/stale-base-check.js +0 -352
  466. package/dist/cli/session-start/stale-base-check.js.map +0 -1
  467. package/dist/cli/session-start/toolchain-parity.d.ts +0 -267
  468. package/dist/cli/session-start/toolchain-parity.js +0 -797
  469. package/dist/cli/session-start/toolchain-parity.js.map +0 -1
  470. package/dist/cli/smoke/assertions.d.ts +0 -46
  471. package/dist/cli/smoke/assertions.js +0 -170
  472. package/dist/cli/smoke/assertions.js.map +0 -1
  473. package/dist/cli/smoke/index.d.ts +0 -76
  474. package/dist/cli/smoke/index.js +0 -245
  475. package/dist/cli/smoke/index.js.map +0 -1
  476. package/dist/cli/smoke/runner.d.ts +0 -55
  477. package/dist/cli/smoke/runner.js +0 -134
  478. package/dist/cli/smoke/runner.js.map +0 -1
  479. package/dist/cli/smoke/stream-parser.d.ts +0 -65
  480. package/dist/cli/smoke/stream-parser.js +0 -115
  481. package/dist/cli/smoke/stream-parser.js.map +0 -1
  482. package/dist/cli/test-risk.d.ts +0 -27
  483. package/dist/cli/test-risk.js +0 -38
  484. package/dist/cli/test-risk.js.map +0 -1
  485. package/dist/io/display-path.d.ts +0 -11
  486. package/dist/io/display-path.js +0 -29
  487. package/dist/io/display-path.js.map +0 -1
  488. package/dist/io/duration.d.ts +0 -5
  489. package/dist/io/duration.js +0 -50
  490. package/dist/io/duration.js.map +0 -1
  491. package/dist/io/extract.d.ts +0 -79
  492. package/dist/io/extract.js +0 -226
  493. package/dist/io/extract.js.map +0 -1
  494. package/dist/io/ledger-record.d.ts +0 -83
  495. package/dist/io/ledger-record.js +0 -301
  496. package/dist/io/ledger-record.js.map +0 -1
  497. package/dist/io/read-json-dir-entries.d.ts +0 -36
  498. package/dist/io/read-json-dir-entries.js +0 -48
  499. package/dist/io/read-json-dir-entries.js.map +0 -1
  500. package/dist/io/safe-json-parse.d.ts +0 -5
  501. package/dist/io/safe-json-parse.js +0 -21
  502. package/dist/io/safe-json-parse.js.map +0 -1
  503. package/dist/policies/index.d.ts +0 -5
  504. package/dist/policies/index.js +0 -6
  505. package/dist/policies/index.js.map +0 -1
  506. package/dist/policies/ledger-client.d.ts +0 -113
  507. package/dist/policies/ledger-client.js +0 -500
  508. package/dist/policies/ledger-client.js.map +0 -1
  509. package/dist/policies/producers.d.ts +0 -12
  510. package/dist/policies/producers.js +0 -61
  511. package/dist/policies/producers.js.map +0 -1
  512. package/dist/policies/requires.d.ts +0 -75
  513. package/dist/policies/requires.js +0 -240
  514. package/dist/policies/requires.js.map +0 -1
  515. package/dist/policies/timestamp.d.ts +0 -14
  516. package/dist/policies/timestamp.js +0 -36
  517. package/dist/policies/timestamp.js.map +0 -1
  518. package/dist/policy-packs/builtin/permission-profiles.d.ts +0 -11
  519. package/dist/policy-packs/builtin/permission-profiles.js +0 -74
  520. package/dist/policy-packs/builtin/permission-profiles.js.map +0 -1
  521. package/dist/policy-packs/builtin/post-merge-gate-runtime.d.ts +0 -286
  522. package/dist/policy-packs/builtin/post-merge-gate-runtime.js +0 -397
  523. package/dist/policy-packs/builtin/post-merge-gate-runtime.js.map +0 -1
  524. package/dist/policy-packs/builtin/post-merge-gate.d.ts +0 -56
  525. package/dist/policy-packs/builtin/post-merge-gate.js +0 -347
  526. package/dist/policy-packs/builtin/post-merge-gate.js.map +0 -1
  527. package/dist/policy-packs/builtin/solution-acceptance-reconnect.d.ts +0 -50
  528. package/dist/policy-packs/builtin/solution-acceptance-reconnect.js +0 -151
  529. package/dist/policy-packs/builtin/solution-acceptance-reconnect.js.map +0 -1
  530. package/dist/policy-packs/builtin/solution-acceptance-runtime.d.ts +0 -323
  531. package/dist/policy-packs/builtin/solution-acceptance-runtime.js +0 -672
  532. package/dist/policy-packs/builtin/solution-acceptance-runtime.js.map +0 -1
  533. package/dist/policy-packs/builtin/solution-acceptance.d.ts +0 -45
  534. package/dist/policy-packs/builtin/solution-acceptance.js +0 -226
  535. package/dist/policy-packs/builtin/solution-acceptance.js.map +0 -1
  536. package/dist/policy-packs/builtin/understanding-before-execution/active-claim.d.ts +0 -25
  537. package/dist/policy-packs/builtin/understanding-before-execution/active-claim.js +0 -94
  538. package/dist/policy-packs/builtin/understanding-before-execution/active-claim.js.map +0 -1
  539. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.d.ts +0 -35
  540. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js +0 -86
  541. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js.map +0 -1
  542. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.d.ts +0 -210
  543. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js +0 -361
  544. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js.map +0 -1
  545. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.d.ts +0 -304
  546. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js +0 -734
  547. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js.map +0 -1
  548. package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.d.ts +0 -36
  549. package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.js +0 -73
  550. package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.js.map +0 -1
  551. package/dist/policy-packs/builtin/understanding-before-execution/index.d.ts +0 -19
  552. package/dist/policy-packs/builtin/understanding-before-execution/index.js +0 -83
  553. package/dist/policy-packs/builtin/understanding-before-execution/index.js.map +0 -1
  554. package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.d.ts +0 -135
  555. package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.js +0 -643
  556. package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.js.map +0 -1
  557. package/dist/policy-packs/builtin/understanding-before-execution/ledger.d.ts +0 -25
  558. package/dist/policy-packs/builtin/understanding-before-execution/ledger.js +0 -56
  559. package/dist/policy-packs/builtin/understanding-before-execution/ledger.js.map +0 -1
  560. package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.d.ts +0 -20
  561. package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.js +0 -106
  562. package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.js.map +0 -1
  563. package/dist/policy-packs/builtin/understanding-before-execution/markers.d.ts +0 -126
  564. package/dist/policy-packs/builtin/understanding-before-execution/markers.js +0 -245
  565. package/dist/policy-packs/builtin/understanding-before-execution/markers.js.map +0 -1
  566. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.d.ts +0 -29
  567. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js +0 -82
  568. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js.map +0 -1
  569. package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.d.ts +0 -71
  570. package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js +0 -175
  571. package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js.map +0 -1
  572. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.d.ts +0 -625
  573. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js +0 -1076
  574. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js.map +0 -1
  575. package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.d.ts +0 -128
  576. package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js +0 -213
  577. package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js.map +0 -1
  578. package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.d.ts +0 -129
  579. package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.js +0 -166
  580. package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.js.map +0 -1
  581. package/dist/policy-packs/builtin/understanding-before-execution/task-markers.d.ts +0 -164
  582. package/dist/policy-packs/builtin/understanding-before-execution/task-markers.js +0 -275
  583. package/dist/policy-packs/builtin/understanding-before-execution/task-markers.js.map +0 -1
  584. package/dist/policy-packs/builtin/understanding-before-execution-runtime.d.ts +0 -1
  585. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js +0 -10
  586. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js.map +0 -1
  587. package/dist/policy-packs/builtin/understanding-before-execution.d.ts +0 -526
  588. package/dist/policy-packs/builtin/understanding-before-execution.js +0 -1078
  589. package/dist/policy-packs/builtin/understanding-before-execution.js.map +0 -1
  590. package/dist/policy-packs/permission-translator.d.ts +0 -9
  591. package/dist/policy-packs/permission-translator.js +0 -76
  592. package/dist/policy-packs/permission-translator.js.map +0 -1
  593. package/dist/runtime/action-envelope.d.ts +0 -64
  594. package/dist/runtime/action-envelope.js +0 -46
  595. package/dist/runtime/action-envelope.js.map +0 -1
  596. package/dist/runtime/approval-signing.d.ts +0 -111
  597. package/dist/runtime/approval-signing.js +0 -384
  598. package/dist/runtime/approval-signing.js.map +0 -1
  599. package/dist/runtime/bash-match-facts.d.ts +0 -60
  600. package/dist/runtime/bash-match-facts.js +0 -196
  601. package/dist/runtime/bash-match-facts.js.map +0 -1
  602. package/dist/runtime/bash-match-registry.d.ts +0 -112
  603. package/dist/runtime/bash-match-registry.js +0 -406
  604. package/dist/runtime/bash-match-registry.js.map +0 -1
  605. package/dist/runtime/bash-prefix-parse.d.ts +0 -31
  606. package/dist/runtime/bash-prefix-parse.js +0 -576
  607. package/dist/runtime/bash-prefix-parse.js.map +0 -1
  608. package/dist/runtime/command-normalize.d.ts +0 -658
  609. package/dist/runtime/command-normalize.js +0 -2410
  610. package/dist/runtime/command-normalize.js.map +0 -1
  611. package/dist/runtime/deletion-target-resolve.d.ts +0 -28
  612. package/dist/runtime/deletion-target-resolve.js +0 -1078
  613. package/dist/runtime/deletion-target-resolve.js.map +0 -1
  614. package/dist/runtime/destructive-shell-floor.d.ts +0 -19
  615. package/dist/runtime/destructive-shell-floor.js +0 -611
  616. package/dist/runtime/destructive-shell-floor.js.map +0 -1
  617. package/dist/runtime/environment-resolver.d.ts +0 -36
  618. package/dist/runtime/environment-resolver.js +0 -138
  619. package/dist/runtime/environment-resolver.js.map +0 -1
  620. package/dist/runtime/git-context.d.ts +0 -201
  621. package/dist/runtime/git-context.js +0 -422
  622. package/dist/runtime/git-context.js.map +0 -1
  623. package/dist/runtime/index.d.ts +0 -12
  624. package/dist/runtime/index.js +0 -13
  625. package/dist/runtime/index.js.map +0 -1
  626. package/dist/runtime/intercept.d.ts +0 -623
  627. package/dist/runtime/intercept.js +0 -1384
  628. package/dist/runtime/intercept.js.map +0 -1
  629. package/dist/runtime/kube-context.d.ts +0 -16
  630. package/dist/runtime/kube-context.js +0 -63
  631. package/dist/runtime/kube-context.js.map +0 -1
  632. package/dist/runtime/kubectl-target-parse.d.ts +0 -31
  633. package/dist/runtime/kubectl-target-parse.js +0 -249
  634. package/dist/runtime/kubectl-target-parse.js.map +0 -1
  635. package/dist/runtime/ledger-add.d.ts +0 -16
  636. package/dist/runtime/ledger-add.js +0 -150
  637. package/dist/runtime/ledger-add.js.map +0 -1
  638. package/dist/runtime/ledger-writer.d.ts +0 -27
  639. package/dist/runtime/ledger-writer.js +0 -46
  640. package/dist/runtime/ledger-writer.js.map +0 -1
  641. package/dist/runtime/pause-sentinel.d.ts +0 -60
  642. package/dist/runtime/pause-sentinel.js +0 -156
  643. package/dist/runtime/pause-sentinel.js.map +0 -1
  644. package/dist/runtime/pending-approval.d.ts +0 -23
  645. package/dist/runtime/pending-approval.js +0 -67
  646. package/dist/runtime/pending-approval.js.map +0 -1
  647. package/dist/runtime/read-only-bash.d.ts +0 -141
  648. package/dist/runtime/read-only-bash.js +0 -2204
  649. package/dist/runtime/read-only-bash.js.map +0 -1
  650. package/dist/runtime/recovery-git-commit.d.ts +0 -22
  651. package/dist/runtime/recovery-git-commit.js +0 -284
  652. package/dist/runtime/recovery-git-commit.js.map +0 -1
  653. package/dist/runtime/reject-malformed-session-id.d.ts +0 -8
  654. package/dist/runtime/reject-malformed-session-id.js +0 -16
  655. package/dist/runtime/reject-malformed-session-id.js.map +0 -1
  656. package/dist/runtime/risk-classifier.d.ts +0 -38
  657. package/dist/runtime/risk-classifier.js +0 -311
  658. package/dist/runtime/risk-classifier.js.map +0 -1
  659. package/dist/runtime/session-id.d.ts +0 -113
  660. package/dist/runtime/session-id.js +0 -193
  661. package/dist/runtime/session-id.js.map +0 -1
  662. package/dist/runtime/shell-word.d.ts +0 -62
  663. package/dist/runtime/shell-word.js +0 -410
  664. package/dist/runtime/shell-word.js.map +0 -1
  665. package/dist/runtime/task-providers/agent-tasks.d.ts +0 -105
  666. package/dist/runtime/task-providers/agent-tasks.js +0 -247
  667. package/dist/runtime/task-providers/agent-tasks.js.map +0 -1
  668. package/dist/runtime/when-eval.d.ts +0 -62
  669. package/dist/runtime/when-eval.js +0 -212
  670. package/dist/runtime/when-eval.js.map +0 -1
  671. package/dist/runtime/workflow-policies.d.ts +0 -207
  672. package/dist/runtime/workflow-policies.js +0 -596
  673. package/dist/runtime/workflow-policies.js.map +0 -1
  674. package/dist/schema/audit.d.ts +0 -71
  675. package/dist/schema/audit.js +0 -32
  676. package/dist/schema/audit.js.map +0 -1
  677. package/dist/schema/doctor.d.ts +0 -25
  678. package/dist/schema/doctor.js +0 -23
  679. package/dist/schema/doctor.js.map +0 -1
  680. package/dist/schema/environments.d.ts +0 -215
  681. package/dist/schema/environments.js +0 -101
  682. package/dist/schema/environments.js.map +0 -1
  683. package/dist/schema/extract.d.ts +0 -9
  684. package/dist/schema/extract.js +0 -86
  685. package/dist/schema/extract.js.map +0 -1
  686. package/dist/schema/permission-profiles.d.ts +0 -2292
  687. package/dist/schema/permission-profiles.js +0 -60
  688. package/dist/schema/permission-profiles.js.map +0 -1
  689. package/dist/schema/policies.d.ts +0 -974
  690. package/dist/schema/policies.js +0 -298
  691. package/dist/schema/policies.js.map +0 -1
  692. package/dist/schema/requires.d.ts +0 -131
  693. package/dist/schema/requires.js +0 -88
  694. package/dist/schema/requires.js.map +0 -1
  695. package/dist/schema/risk.d.ts +0 -144
  696. package/dist/schema/risk.js +0 -194
  697. package/dist/schema/risk.js.map +0 -1
  698. package/dist/schema/session-start-preflight.d.ts +0 -10
  699. package/dist/schema/session-start-preflight.js +0 -106
  700. package/dist/schema/session-start-preflight.js.map +0 -1
  701. package/dist/schema/stale-base-check.d.ts +0 -18
  702. package/dist/schema/stale-base-check.js +0 -37
  703. package/dist/schema/stale-base-check.js.map +0 -1
  704. package/dist/schema/toolchain-parity.d.ts +0 -21
  705. package/dist/schema/toolchain-parity.js +0 -48
  706. package/dist/schema/toolchain-parity.js.map +0 -1
  707. package/dist/schema/workflows.d.ts +0 -519
  708. package/dist/schema/workflows.js +0 -81
  709. package/dist/schema/workflows.js.map +0 -1
  710. package/scripts/runtime-reality-docker-probe.mjs +0 -71
@@ -1,1078 +0,0 @@
1
- // Builtin Policy Pack: `understanding-before-execution`.
2
- //
3
- // Bundles three hook contributions for Claude Code (UserPromptSubmit,
4
- // Stop, PreToolUse), plus a per-mode instructions.md that documents what
5
- // the pack is doing for human auditors. The actual prompt that the agent
6
- // sees at UserPromptSubmit time is owned by `@lannguyensi/understanding-gate`
7
- // (specifically `src/prompts/{full,fast-confirm,grill-me}.ts`); harness's
8
- // instructions.md is the operator-facing summary, not the agent-injected
9
- // text. Drift on instructions.md is therefore meaningful (someone edited
10
- // the audit copy), distinct from drift on the package's own templates
11
- // (which the package's own drift detection would handle on a future
12
- // `understanding-gate init` reinstall).
13
- import { z } from "zod";
14
- import { PolicyUxSchema, ProducerSchema } from "../../schema/policies.js";
15
- import { profileToSettingsPermissions } from "../permission-translator.js";
16
- import { DEFAULT_RUNTIME } from "../runtime.js";
17
- import { isKnownProfileName, resolveProfile, KNOWN_PROFILE_NAMES, } from "./permission-profiles.js";
18
- import { AUTO_APPROVE_HARNESS_VALUES, REPORTS_DIR_ENV, } from "./understanding-before-execution-runtime.js";
19
- // Through the `understanding-before-execution/index.ts` aggregator, not
20
- // through the concern-scoped `auto-approve.ts` sibling directly (review
21
- // fix): the prior direct import contradicted the
22
- // precedent every other symbol at this call site already follows (the
23
- // `AUTO_APPROVE_HARNESS_VALUES` / `REPORTS_DIR_ENV` import just above).
24
- // `parseReportScanMaxWait` is now part of the shim's pinned public surface
25
- // (tests/policy-packs/ube-export-surface.test.ts), alongside
26
- // `DEFAULT_REPORT_SCAN_MAX_WAIT_MS` and `REPORT_SCAN_MAX_WAIT_CEILING_MS`,
27
- // which this file only names in comments and so does not import.
28
- import { parseReportScanMaxWait } from "./understanding-before-execution/index.js";
29
- import { SHELL_ALIASES } from "../../runtime/tool-name-aliases.js";
30
- import { ACTIVE_CLAIM_TOOL_NAMES, DEFAULT_BOUNDARY_TOOL_NAMES, } from "../../runtime/task-providers/agent-tasks.js";
31
- import { resolveStayInScopeConfig, StayInScopeConfigSchema, } from "./understanding-before-execution/stay-in-scope-config.js";
32
- // Env var the npm-backed `understanding-gate-claude-hook` bin reads to find
33
- // the harness pause sentinel (`src/runtime/pause-sentinel.ts`,
34
- // SENTINEL_BASENAME = ".harness-paused"). The bin runs OUTSIDE harness's
35
- // own runtime (it's a package-owned process, not a `harness pack hook ...`
36
- // subcommand), so it cannot resolve `generatedDir` itself the way
37
- // `src/cli/pause-check.ts` does for harness's own hooks — the apply path
38
- // bakes the resolved sentinel path in as an env-var prefix instead, same
39
- // mechanism as UNDERSTANDING_GATE_REPORT_DIR below (agent-tasks 63fefe3a).
40
- export const PAUSE_FILE_ENV = "UNDERSTANDING_GATE_PAUSE_FILE";
41
- export const PACK_NAME = "understanding-before-execution";
42
- // Canonical version probe for the pack's package-side bin. Consumed by
43
- // `harness doctor` when the operator declares a pack-level `min_version`
44
- // floor. Mirrors the hook-level UG_VERSION_COMMAND (which is scoped to
45
- // individual hooks); a pack-level floor exists so a `config:` key only
46
- // the newer package honours (e.g. the v0.25.0 `--task` variadic flag)
47
- // can be caught at health-check time independent of any one hook.
48
- export const VERSION_COMMAND = [
49
- "understanding-gate",
50
- "--version",
51
- ];
52
- const MODES = ["fast_confirm", "grill_me", "strict"];
53
- export const DEFAULT_MODE = "grill_me";
54
- /**
55
- * Env var carrying an operator-set mode override. Also the exact name
56
- * `@lannguyensi/understanding-gate` reads on its own (package
57
- * `src/mode.ts`: "ENV wins because operators set it consciously").
58
- *
59
- * Two DIFFERENT resolution contracts read this name, deliberately (task
60
- * 5d73d78d, review HIGH-3 fix-round):
61
- *
62
- * - The GENERATION path — {@link resolve}/`buildHooks`, and
63
- * `resolveBuiltinDefaultConfig` in `../registry.ts` (consumed by
64
- * `harness doctor`'s UX-drift comparison and `harness pack reseed`) —
65
- * resolves mode via {@link resolveModeFromConfig}, which reads ONLY
66
- * `pack.config.mode`. It never consults this env var. Generation runs
67
- * at `harness apply` / `harness doctor` / `harness pack reseed` time,
68
- * writing artefacts (settings.json hook commands, instructions.md,
69
- * reseeded config) that persist until the NEXT apply; if that write
70
- * depended on whatever happened to be exported in the operator's
71
- * shell at that moment, the artefact would silently drift from
72
- * `config.mode` the instant the shell's env changed — exactly the
73
- * class of bug this task closes for the OTHER resolver (see below),
74
- * re-opened one layer up. `buildHooks` DOES still bake this env var
75
- * into the two npm-backed Claude bin commands it emits (`wrapMode`)
76
- * — but the value baked in is the GENERATION-time config-resolved
77
- * mode, frozen at apply time, not a live env read.
78
- * - LIVE runtime consumers — {@link resolveMode} (used by
79
- * `approve/understanding.ts`'s stdin-report gap-fill, and by the
80
- * Codex `UserPromptSubmit` injector,
81
- * `src/cli/pack/hook-codex-user-prompt-submit.ts`) — resolve mode at
82
- * INVOCATION time, with the live process environment actually
83
- * available, so Env > `config.mode` > {@link DEFAULT_MODE} is the
84
- * correct priority there: this is what makes a one-off
85
- * `UNDERSTANDING_GATE_MODE=fast_confirm harness approve understanding`
86
- * override work without editing harness.yaml, mirroring the npm
87
- * package's own env-wins rule for the exact same reason.
88
- *
89
- * Before task 5d73d78d, NEITHER resolver read `config.mode` for
90
- * enforcement at all — the package-owned Claude bins were invoked bare
91
- * (no env var), and `persistStdinReport`'s gap-fill default was a
92
- * hardcoded `"fast_confirm"` literal — so a host with `config.mode:
93
- * grill_me` was silently enforced as `fast_confirm` regardless. See
94
- * `docs/policy-packs/understanding-before-execution.md`'s "Mode
95
- * resolution and enforcement" section for the full narrative.
96
- */
97
- export const MODE_ENV = "UNDERSTANDING_GATE_MODE";
98
- /**
99
- * The agent-facing `required:` phrase for the understanding-gate deny
100
- * envelope, derived from the configured mode. Only `strict` forces
101
- * `requiresHumanApproval` (see {@link modeFriction}); in `fast_confirm`
102
- * and `grill_me` the agent self-attests and a structural validator
103
- * checks the report, so naming it "human-approved" there would overstate
104
- * what the gate actually enforces. Generation surfaces (the Custom
105
- * composer, the init templates) call this so the wording can never drift
106
- * from the mode it is paired with.
107
- */
108
- export function understandingApprovalRequirement(mode) {
109
- return mode === "strict"
110
- ? "a human-approved Understanding Report for this session"
111
- : "an approved Understanding Report for this session";
112
- }
113
- /**
114
- * Shipped default `config.producers` for this pack (agent-tasks/25bced52).
115
- * Canonical source for the "golden path" recovery command: both `harness
116
- * init` generation surfaces (Solo/Team/Full templates, the Custom
117
- * composer) and `harness pack reseed` (task 68b9ad9c) read from here, so
118
- * a future wording change to the producer descriptions only has to land
119
- * in one place to reach every manifest-generating surface plus the
120
- * reseed path used to backfill already-installed manifests.
121
- */
122
- export function defaultProducers() {
123
- return [
124
- {
125
- kind: "ask",
126
- command: "harness approve understanding",
127
- description: "Bare command, no pipes or chaining. The hook recognises it via isEscapeCommand and emits permissionDecision:ask; the operator's go on that prompt IS the gate approval. Golden path.",
128
- },
129
- {
130
- kind: "bash",
131
- command: "harness approve understanding",
132
- description: "Same command from any un-hooked terminal (operator only, not reachable from inside the gated session). Writes the canonical marker at harness.generated/.approvals/${SESSION_ID}.",
133
- },
134
- ];
135
- }
136
- /**
137
- * Shipped default `config.ux` for this pack, parameterised on the
138
- * resolved mode (only the `required` line varies across modes — see
139
- * `understandingApprovalRequirement` above). Canonical source consumed
140
- * by the same generation surfaces as `defaultProducers()`, plus
141
- * `harness doctor`'s divergence warning and `harness pack reseed` (task
142
- * 68b9ad9c): the dogfood motivating that task found that a deny-message
143
- * wording fix (e.g. the heredoc submission form, agent-tasks/e48e3b45)
144
- * only reached NEW `harness init` manifests, because nothing propagated
145
- * the improved text into an already-installed operator manifest whose
146
- * `config.ux` still taught the old wording. Reading from one function
147
- * here means a future wording fix is available to `pack reseed`
148
- * automatically, with no separate update needed.
149
- */
150
- export function defaultUx(mode) {
151
- return {
152
- cannot: "You cannot use write-capable tools yet.",
153
- required: [understandingApprovalRequirement(mode)],
154
- run: [
155
- "Write an Understanding Report covering: Current Understanding, Intended Outcome, Derived Todos, Acceptance Criteria, Assumptions, Open Questions, Out Of Scope, Risks, Verification Plan, Prior Art (state what you searched for an existing solution and what you found, with an explicit adopt-or-build judgment)",
156
- "Run `harness approve understanding` with the report attached as a quoted heredoc (harness approve understanding <<'UNDERSTANDING_REPORT' ...report... UNDERSTANDING_REPORT) so it is persisted for audit, then approve the prompt; the heredoc is the only extra shell shape the gate allows (no pipes, chaining, or other redirection)",
157
- ],
158
- };
159
- }
160
- const HOOK_NAME_PREFIX = `policy-pack:${PACK_NAME}`;
161
- // Per-runtime hook surface. Claude Code keys on tool name (Edit|Write|Bash);
162
- // Codex's write surface is `apply_patch` plus shell tool aliases used by
163
- // current runtimes (`Bash`/`shell`/`exec_command`). The hook contract Codex
164
- // feeds to the adapter is the same generic envelope harness publishes:
165
- // `{ session_id, tool_name, raw_input, event }` on stdin, `{ decision }`
166
- // on stdout, exit 2 on block. See dogfood/phase6-6/README.md for the wire
167
- // format.
168
- const PRE_TOOL_USE_MATCH_CLAUDE = "Edit|Write|Bash";
169
- const PRE_TOOL_USE_MATCH_CODEX = "apply_patch|Bash|shell|exec_command|functions.exec_command";
170
- // UserPromptSubmit + Stop hooks point at `@lannguyensi/understanding-gate`
171
- // bare bin names (npm i -g). The harness validator's checkHooks skips
172
- // PATH lookup for non-rooted commands by design, so missing-bin shows
173
- // up at runtime, not at lint. `harness doctor` (Phase 6 #4 follow-up)
174
- // will add the presence check.
175
- const BIN_USER_PROMPT_SUBMIT_CLAUDE = "understanding-gate-claude-hook";
176
- const BIN_STOP_CLAUDE = "understanding-gate-claude-stop";
177
- // PreToolUse blocker is the harness CLI itself (Phase 6 #4): it consults
178
- // BOTH the evidence-ledger tag (canonical for harnessed sessions) AND
179
- // the persisted JSON report under `.understanding-gate/reports/`
180
- // (fallback for sessions without grounding-mcp wired). The npm package's
181
- // own bin remains available for solo users; the harness blocker is
182
- // strictly more powerful.
183
- const PRE_TOOL_USE_COMMAND_CLAUDE = "harness pack hook pre-tool-use";
184
- // Codex variants. The package `@lannguyensi/understanding-gate` does
185
- // not yet ship Codex bins, so harness owns the adapter:
186
- //
187
- // - UserPromptSubmit-equivalent injector (Phase 6 #6).
188
- // - Stop-equivalent capture into `.understanding-gate/reports/`
189
- // (Phase 6 #6 follow-up).
190
- // - PreToolUse blocker on apply_patch plus Codex shell aliases (Phase 6 #6).
191
- // - PostToolUse marker-expiry (task a1348c89): Codex's published hooks
192
- // reference (developers.openai.com/codex/hooks) documents
193
- // `PostToolUse` as a first-class event — `[[hooks.PostToolUse]]`
194
- // with a `matcher` on `tool_name`, same allow/exit-0 or
195
- // block/exit-2 contract as PreToolUse. Mirrors the Claude
196
- // `post-tool-use` hook via the shared matching/clearing core in
197
- // understanding-before-execution-runtime.ts.
198
- //
199
- // Cross-runtime sessions can still approve from a Claude Code report:
200
- // the ledger tag is the canonical source for harnessed sessions,
201
- // independent of which runtime captured the report. The persisted-
202
- // report directory is shared between runtimes, so a Codex stop that
203
- // writes a report is approvable via `harness approve understanding`
204
- // regardless of which runtime invokes the next tool call.
205
- const COMMAND_USER_PROMPT_SUBMIT_CODEX = "harness pack hook codex-user-prompt-submit";
206
- const COMMAND_STOP_CODEX = "harness pack hook codex-stop";
207
- const COMMAND_PRE_TOOL_USE_CODEX = "harness pack hook codex-pre-tool-use";
208
- const COMMAND_POST_TOOL_USE_CODEX = "harness pack hook codex-post-tool-use";
209
- export function isMode(value) {
210
- return (typeof value === "string" && MODES.includes(value));
211
- }
212
- /**
213
- * Zod schema for this pack's `config:` block. Surfaced via
214
- * `resolveBuiltinConfigSchema()` and consumed by `harness validate` /
215
- * `harness doctor` so typo'd keys (e.g. `permision_profile`) or values
216
- * (e.g. `mode: fastConfirm`) fail loud at lint time instead of falling
217
- * through to the runtime fallback. Each shape mirrors what the pack's
218
- * own resolvers (`resolveMode`, `resolveExpireOnToolMatch`,
219
- * `resolvePermissionProfile`) accept — the schema is a typo guard, not
220
- * a replacement parser; the resolvers still own defaults + warnings for
221
- * borderline cases the schema lets through.
222
- *
223
- * `.strict()` is intentional: this pack already documents every
224
- * supported key, and an unknown key in the operator's manifest is far
225
- * more likely to be a typo than forward-compat. New keys added in a
226
- * future harness version land in this schema first, then in the pack.
227
- */
228
- export const configSchema = z
229
- .object({
230
- mode: z.enum(MODES).optional(),
231
- permission_profile: z
232
- .enum(KNOWN_PROFILE_NAMES)
233
- .optional(),
234
- approval_lifecycle: z
235
- .object({
236
- // `mode: session` opts out of the PostToolUse marker-expiry hook
237
- // entirely (legacy "one approval per session" UX).
238
- mode: z.literal("session").optional(),
239
- // Tool-name boundaries: clear the marker after one of these
240
- // agent-tasks (or operator-overridden) MCP tools fires.
241
- expire_on_tool_match: z.array(z.string().min(1)).optional(),
242
- // Bash-command boundaries: clear the marker when a Bash call
243
- // matches any of these regexes (e.g. `^gh pr (merge|close)\b`).
244
- // Operators on gh-cli workflows use this in place of MCP tools.
245
- expire_on_bash_match: z.array(z.string().min(1)).optional(),
246
- // Safety net for sessions that never hit a listed tool/Bash
247
- // boundary. Duration strings like `1h`, `4h`, `30m` are parsed
248
- // by `parseApprovalLifecycle`; enforced by the marker freshness
249
- // check on PreToolUse (`checkApprovalMarker`'s `max_age`
250
- // comparison), not by a PostToolUse hook — `max_age` still
251
- // applies under `mode: session`, which only opts out of the
252
- // PostToolUse boundary hooks and the session marker's task binding.
253
- max_age: z.string().min(1).optional(),
254
- })
255
- .strict()
256
- .optional(),
257
- // Operator opt-in to the hook-written signed auto-marker path for
258
- // an allowlisted `permission_mode` (docs/decisions/2026-08-27-ug-auto-mode-approval.md,
259
- // "Option A"). `when` names the exact permission-mode literals the
260
- // hook may auto-approve; `harnesses` names which runtimes' PreToolUse
261
- // hooks may take the auto path at all (absent means Claude Code only,
262
- // the meaning the key had before the Codex hook joined the shared
263
- // path, so an existing opt-in is never silently widened);
264
- // `require_report` is required and must be literal `true` in v1 (ADR
265
- // threat model (b) item 3: rejecting `false` here makes a future
266
- // relaxation a visible schema change instead of a silent default).
267
- // `report_scan.max_wait` (slice 3) bounds the child's transcript poll
268
- // under `claude -p`; it is optional, defaults to
269
- // `DEFAULT_REPORT_SCAN_MAX_WAIT_MS` when absent, and is range-checked
270
- // here so an over-long bound is a `harness validate` error rather
271
- // than a hook that parks a session.
272
- // Runtime parsing/validation lives in
273
- // `./understanding-before-execution/auto-approve.ts`.
274
- auto_approve: z
275
- .object({
276
- when: z.array(z.string().min(1)).min(1),
277
- harnesses: z
278
- .array(z.enum(AUTO_APPROVE_HARNESS_VALUES))
279
- .min(1)
280
- .refine((values) => new Set(values).size === values.length, {
281
- message: "harnesses must not contain duplicate entries",
282
- })
283
- .optional(),
284
- report_scan: z
285
- .object({
286
- // Parsed by the SAME function the runtime hook uses, so the
287
- // lint-time gate and the hook cannot drift on the grammar,
288
- // the zero/negative rejection, or the hard ceiling.
289
- max_wait: z.string().min(1).superRefine((value, ctx) => {
290
- const parsed = parseReportScanMaxWait(value);
291
- if (!parsed.ok) {
292
- ctx.addIssue({ code: z.ZodIssueCode.custom, message: parsed.reason });
293
- }
294
- }),
295
- })
296
- .strict()
297
- .optional(),
298
- require_report: z.literal(true),
299
- })
300
- .strict()
301
- .optional(),
302
- // `ux` + `producers` are consumed by the PreToolUse blocker
303
- // (`src/cli/pack/hook-pre-tool-use.ts`) to render an agent-facing
304
- // remediation block when the gate trips. Same shape as the
305
- // policy-layer `ux:` / `producers:` keys.
306
- ux: PolicyUxSchema.optional(),
307
- producers: z.array(ProducerSchema).min(1).optional(),
308
- stay_in_scope: StayInScopeConfigSchema.optional(),
309
- })
310
- .strict();
311
- /**
312
- * POSIX single-quote-escape for an arbitrary path. Safe inside the
313
- * `VAR=<value>` prefix of a `sh -c` command line. Always quotes — paths
314
- * derived from `path.dirname()` may contain spaces or other shell
315
- * metacharacters, and a plain `VAR=$path` would split on whitespace.
316
- */
317
- export function shellQuoteSingle(s) {
318
- return `'${s.replace(/'/g, "'\\''")}'`;
319
- }
320
- function prefixCommandWithReportsDir(command, reportsDir) {
321
- if (!reportsDir)
322
- return command;
323
- return `${REPORTS_DIR_ENV}=${shellQuoteSingle(reportsDir)} ${command}`;
324
- }
325
- function prefixCommandWithPauseFile(command, pauseFile) {
326
- if (!pauseFile)
327
- return command;
328
- return `${PAUSE_FILE_ENV}=${shellQuoteSingle(pauseFile)} ${command}`;
329
- }
330
- /**
331
- * Resolve the pack's effective mode from `pack.config.mode` alone —
332
- * `pack.config.mode` (harness.yaml) > {@link DEFAULT_MODE}. Never reads
333
- * {@link MODE_ENV}. This is the GENERATION-path resolver: see
334
- * {@link MODE_ENV}'s doc comment for why the artefacts this function's
335
- * callers write (hook commands, instructions.md, reseeded config) must
336
- * not depend on the live process environment. Used by {@link resolve} /
337
- * `buildHooks` below, and by `resolveBuiltinDefaultConfig` in
338
- * `../registry.ts`.
339
- */
340
- export function resolveModeFromConfig(pack) {
341
- const raw = pack.config["mode"];
342
- if (raw === undefined)
343
- return { mode: DEFAULT_MODE, warning: null };
344
- if (isMode(raw))
345
- return { mode: raw, warning: null };
346
- const warning = `policy_packs[${pack.name}].config.mode: unrecognised value ${JSON.stringify(raw)}, falling back to "${DEFAULT_MODE}". Allowed: ${MODES.join(", ")}.`;
347
- return { mode: DEFAULT_MODE, warning };
348
- }
349
- /**
350
- * Resolve the pack's effective mode for a LIVE runtime consumer. Priority:
351
- * {@link MODE_ENV} (env) > `pack.config.mode` (harness.yaml) >
352
- * {@link DEFAULT_MODE} — see {@link MODE_ENV}'s doc comment for which
353
- * callers this is (and is not) correct for. An invalid value at either
354
- * the env or the config layer is skipped (with a warning) rather than
355
- * short-circuiting straight to the default, so a typo'd env var does not
356
- * also stomp on an otherwise-valid YAML setting. The config layer is
357
- * VALIDATED (and its warning surfaced) even when a valid env value
358
- * already resolved `mode` (task 5d73d78d review LOW-8): otherwise a
359
- * config.mode typo would go unreported for as long as an operator happens
360
- * to have a valid env override exported, resurfacing silently the moment
361
- * they unset it. Env wins over YAML deliberately: it is the same
362
- * precedence `@lannguyensi/understanding-gate` gives its own
363
- * env-vs-marker resolution, and it is how an operator (or CI) does a
364
- * one-off override without editing harness.yaml.
365
- *
366
- * The env value is trimmed and lower-cased before matching (task 5d73d78d
367
- * review LOW-9), aligned with the npm package's own normalisation of the
368
- * same env var (`pickMode`, package `src/mode.ts`:
369
- * `env.UNDERSTANDING_GATE_MODE?.trim().toLowerCase()`) — so
370
- * `UNDERSTANDING_GATE_MODE=' Grill_Me '` resolves the same way on both
371
- * sides of the interop boundary instead of harness rejecting a value the
372
- * package would have accepted.
373
- */
374
- export function resolveMode(pack) {
375
- const configResult = resolveModeFromConfig(pack);
376
- const envRaw = process.env[MODE_ENV];
377
- if (envRaw === undefined || envRaw === "")
378
- return configResult;
379
- const normalizedEnv = envRaw.trim().toLowerCase();
380
- if (isMode(normalizedEnv)) {
381
- return { mode: normalizedEnv, warning: configResult.warning };
382
- }
383
- const envWarning = `${MODE_ENV}=${JSON.stringify(envRaw)}: unrecognised value, ignoring. Allowed: ${MODES.join(", ")}.`;
384
- return {
385
- mode: configResult.mode,
386
- warning: configResult.warning ? `${envWarning} ${configResult.warning}` : envWarning,
387
- };
388
- }
389
- /**
390
- * Map harness's {@link Mode} (which includes `strict`) onto the two-value
391
- * mode `@lannguyensi/understanding-gate` itself understands
392
- * (`fast_confirm` | `grill_me`; package `src/schema/types.ts`). The
393
- * package has no `strict` variant of its own; `grill_me` is the closest
394
- * available approximation (full Report, Prior Art enforced) — passing
395
- * `strict` through unmapped would mean the package silently ignores the
396
- * env override (it only recognises its own two literals) and falls back
397
- * to its own default, `fast_confirm`, i.e. the exact drift this task
398
- * closes for `grill_me`, just unfixed for `strict`. This does not change
399
- * what `strict` means inside harness (modeFriction/
400
- * understandingApprovalRequirement are untouched); it only picks what to
401
- * tell the external package, which cannot represent `strict` at all.
402
- */
403
- export function toPackageMode(mode) {
404
- return mode === "fast_confirm" ? "fast_confirm" : "grill_me";
405
- }
406
- // Default tools that mark task-completion boundaries when the operator
407
- // has not overridden `config.approval_lifecycle.expire_on_tool_match`.
408
- // agent-tasks verbs are the dogfood case; operators on Linear / JIRA /
409
- // other task systems override the list in their manifest. Kept here so
410
- // the PostToolUse hook always emits a sensible match pattern even when
411
- // the operator hasn't set the config explicitly. The runtime parser
412
- // (`parseApprovalLifecycle`) applies the same list when no explicit
413
- // list is configured, so the emitted matcher and the runtime boundary
414
- // agree (task 0c6b2cb9).
415
- const DEFAULT_EXPIRE_ON_TOOL_MATCH = DEFAULT_BOUNDARY_TOOL_NAMES;
416
- const POST_TOOL_USE_COMMAND_CLAUDE = "harness pack hook post-tool-use";
417
- // Slice 2 of the subagent-gate work (docs/decisions/2026-08-27-ug-auto-
418
- // mode-approval.md "TTL, cwd, and subagents"): Claude-only for now (an
419
- // Agent-tool subagent is a Claude Code concept; Codex has no equivalent
420
- // event to emit these against). Always emitted alongside the PreToolUse
421
- // blocker, independent of `approval_lifecycle.mode` — an in-flight
422
- // record is a copy of whatever approval the parent holds at spawn time,
423
- // not itself governed by the marker-expiry opt-out.
424
- const SUBAGENT_START_COMMAND = "harness pack hook subagent-start";
425
- const SUBAGENT_STOP_COMMAND = "harness pack hook subagent-stop";
426
- // Task cf4cdc93 (Codex parity gap #3): unlike stop/pre-tool-use/
427
- // post-tool-use, the active-claim tracker and stay-in-scope reminder
428
- // need NO runtime-specific CLI verb — both hook bodies only ever
429
- // inspect the generic `tool_name` / `tool_input` fields already common
430
- // to Claude's and Codex's PostToolUse envelope (no session_id, no
431
- // shell-command extraction, no Codex-only synonym). One shared command
432
- // constant per hook is therefore reused verbatim on both runtimes below
433
- // instead of a `codex-track-active-claim` / `codex-stay-in-scope`
434
- // sibling binary — avoids reintroducing the exact Claude/Codex drift
435
- // class task e7c2ec3c fixed on the PreToolUse side.
436
- const TRACK_ACTIVE_CLAIM_COMMAND = "harness pack hook track-active-claim";
437
- // Hardcoded matcher for the v2 active-claim tracker (harness/494fd1e5).
438
- // Agent-tasks specific; operators on other tasking systems can ignore
439
- // this hook (the matcher won't fire for their tools). A config-driven
440
- // extension can land later if a second tasking system asks for it.
441
- const TRACK_ACTIVE_CLAIM_MATCH = `^(?:${ACTIVE_CLAIM_TOOL_NAMES.join("|")})$`;
442
- // Codex sibling of TRACK_ACTIVE_CLAIM_MATCH above (task cf4cdc93): a
443
- // bare, unescaped `|`-joined list, NOT the anchored `^(?:...)$` form —
444
- // same rationale as `codexPostToolUseMatchPattern`'s own doc comment
445
- // (task a1348c89 review finding): `expandCodexHookMatchPattern`'s
446
- // "simple token" guard (`isSimpleToolPatternToken`, generate-codex-config.ts)
447
- // only alias-expands a match string whose tokens are ALL "simple"; the
448
- // anchor characters `^`, `(`, `?` trip that guard and the anchored form
449
- // is passed through UNCHANGED at TOML-emit time, so a Codex session
450
- // sending a dotted/underscore-server MCP tool-name variant would never
451
- // even reach the hook. This bare form lets the emitted `config.toml`
452
- // matcher — and therefore Codex's own dispatcher — recognize those
453
- // variants, exactly like `PRE_TOOL_USE_MATCH_CODEX` already does.
454
- const TRACK_ACTIVE_CLAIM_MATCH_CODEX = ACTIVE_CLAIM_TOOL_NAMES.join("|");
455
- const STAY_IN_SCOPE_COMMAND = "harness pack hook stay-in-scope";
456
- function escapeMatcherLiteral(value) {
457
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
458
- }
459
- // Bash tool name used to widen the PostToolUse matcher when
460
- // `expire_on_bash_match` is configured (task bea04a03). Matches the
461
- // single entry of `DEFAULT_BASH_TOOL_NAMES` in
462
- // understanding-before-execution-runtime.ts.
463
- const BASH_TOOL_NAME_CLAUDE = "Bash";
464
- // Codex shell-tool aliases used for the same widening on the Codex
465
- // matcher builder below. Derived from the canonical `SHELL_ALIASES` in
466
- // `src/runtime/tool-name-aliases.ts` (task bea04a03 review finding) —
467
- // `policy-packs/` IS allowed to depend on `runtime/` (layering rule,
468
- // `.dependency-cruiser.cjs`; the sibling understanding-before-execution-runtime.ts
469
- // already imports from there), so this is a shared source of truth
470
- // rather than a third hand-maintained copy. `CODEX_SHELL_TOOLS` in
471
- // `src/cli/pack/hook-codex-pre-tool-use.ts` stays a separate literal:
472
- // `policy-packs/` may not depend on `cli/` (same layering rule), so that
473
- // one cannot be unified with this without a boundary violation.
474
- const BASH_TOOL_NAMES_CODEX = SHELL_ALIASES;
475
- /**
476
- * Compose the PostToolUse `match` regex from the configured tool list,
477
- * widened with the Bash tool name when `includeBash` is true (task
478
- * bea04a03: `approval_lifecycle.expire_on_bash_match` carries at least
479
- * one pattern). Before this widening, `expire_on_tool_match` alone
480
- * gated the matcher, so a real `Bash` call never reached the hook at
481
- * all — `matchPostToolUseBoundary`'s bash-regex check (which DOES
482
- * correctly evaluate `expire_on_bash_match` once invoked) was
483
- * unreachable in practice. Adding "Bash" here only ROUTES the call to
484
- * the hook; it does not add "Bash" to `expire_on_tool_match`'s own
485
- * semantics — the hook body still classifies a matched Bash call as a
486
- * bash-regex match (`toolNameMatched: false`), never a tool-name match.
487
- * Each tool name is regex-escaped and joined with `|` so settings.json
488
- * fires the hook only when the just-completed tool is one we care
489
- * about. When the operator declared `approval_lifecycle: { mode: session }`
490
- * (or cleared both lists), no PostToolUse hook is emitted at all (caller
491
- * filters).
492
- */
493
- function postToolUseMatchPattern(tools, includeBash) {
494
- const widened = includeBash && !tools.includes(BASH_TOOL_NAME_CLAUDE)
495
- ? [...tools, BASH_TOOL_NAME_CLAUDE]
496
- : tools;
497
- const escaped = widened.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
498
- return `^(?:${escaped.join("|")})$`;
499
- }
500
- /**
501
- * Compose the CODEX PostToolUse `match` field — deliberately NOT
502
- * `postToolUseMatchPattern` above (review finding on task a1348c89,
503
- * verified via a direct probe of `expandCodexHookMatchPattern`). The
504
- * Claude builder anchors its output in `^(?:...)$` and regex-escapes
505
- * every tool name; `expandCodexHookMatchPattern` in
506
- * `generate-codex-config.ts` only alias-expands a match string whose
507
- * `|`-split tokens are ALL "simple" (`isSimpleToolPatternToken`,
508
- * `/^[A-Za-z0-9_.:-]+$/`) — the anchor characters `^`, `(`, `?` on the
509
- * first/last token trip that guard, so an anchored match is passed
510
- * through UNCHANGED at emit time. Concretely: a Codex session sending
511
- * the dotted `mcp__agent-tasks__.task_finish` or an underscore-server
512
- * `mcp__agent_tasks__task_finish` variant would never even reach the
513
- * hook — Codex's own dispatcher tests `tool_name` against the emitted
514
- * `matcher`, and the anchored form only contains the canonical forms.
515
- * (`matchPostToolUseBoundary`'s alias-aware body-side fix, same task,
516
- * only helps once the hook is actually invoked — it cannot compensate
517
- * for a dispatcher that never calls it.)
518
- *
519
- * This builder instead emits a BARE, unescaped `|`-joined list — same
520
- * shape as the existing `PRE_TOOL_USE_MATCH_CODEX` constant above —
521
- * so every token stays "simple" and `expandCodexHookMatchPattern`
522
- * expands each MCP tool name into its full alias set (server
523
- * hyphen/underscore swap, the `mcp__server__.tool` dotted form) at
524
- * `harness apply --runtime codex` time, exactly like the Codex
525
- * PreToolUse blocker's own matcher already does. No anchoring is
526
- * needed here: Codex's own hook dispatch (like the sibling PreToolUse
527
- * matcher) is unanchored substring-style matching already, and this
528
- * keeps the Codex and Claude builders independently tunable rather
529
- * than smuggling a Codex-only branch into the shared Claude helper.
530
- *
531
- * Like the Claude builder above, `includeBash` (task bea04a03) widens
532
- * the emitted list with the Codex shell-tool aliases
533
- * (`BASH_TOOL_NAMES_CODEX`: Bash/shell/exec_command/functions.exec_command)
534
- * when `approval_lifecycle.expire_on_bash_match` carries at least one
535
- * pattern, so a real Codex shell call is actually routed to the hook.
536
- * The aliases stay simple tokens (no anchors), so they still pass
537
- * through `expandCodexHookMatchPattern` unchanged — they have no MCP-style
538
- * variants to expand, but they must not trip the "simple token" guard
539
- * either.
540
- */
541
- function codexPostToolUseMatchPattern(tools, includeBash) {
542
- const widened = includeBash
543
- ? [...tools, ...BASH_TOOL_NAMES_CODEX.filter((t) => !tools.includes(t))]
544
- : tools;
545
- return widened.join("|");
546
- }
547
- function resolveExpireOnToolMatch(pack) {
548
- const raw = pack.config["approval_lifecycle"];
549
- // No config block at all: default-on with the agent-tasks tool list.
550
- // This is the intentional behaviour change in v0.18 — operators who
551
- // want the legacy "one approval per session" UX opt out via
552
- // `approval_lifecycle: { mode: session }`.
553
- if (raw === undefined || raw === null) {
554
- return { tools: [...DEFAULT_EXPIRE_ON_TOOL_MATCH], emitHook: true };
555
- }
556
- if (typeof raw !== "object" || Array.isArray(raw)) {
557
- return { tools: [...DEFAULT_EXPIRE_ON_TOOL_MATCH], emitHook: true };
558
- }
559
- const obj = raw;
560
- if (obj["mode"] === "session") {
561
- return { tools: [], emitHook: false };
562
- }
563
- const list = obj["expire_on_tool_match"];
564
- if (Array.isArray(list)) {
565
- const tools = list.filter((v) => typeof v === "string" && v.length > 0);
566
- return { tools, emitHook: tools.length > 0 };
567
- }
568
- return { tools: [...DEFAULT_EXPIRE_ON_TOOL_MATCH], emitHook: true };
569
- }
570
- /**
571
- * Whether `approval_lifecycle.expire_on_bash_match` carries at least one
572
- * non-empty pattern (task bea04a03). Used ONLY to decide whether the
573
- * emitted PostToolUse matcher should be widened to route Bash (Claude) /
574
- * shell-alias (Codex) calls to the hook at all — the actual regex
575
- * compiling and matching against `tool_input.command` happens downstream
576
- * in `parseApprovalLifecycle` / `matchPostToolUseBoundary`
577
- * (understanding-before-execution-runtime.ts). An entry that turns out to
578
- * be an invalid regex is silently dropped there with a warning; that is
579
- * harmless here — the matcher merely routes the call to the hook, and a
580
- * hook invocation that finds no live bash-regex match just no-ops
581
- * (mirrors the existing `noBoundariesConfigured` / `boundary.matched`
582
- * no-op paths in hook-post-tool-use.ts / hook-codex-post-tool-use.ts).
583
- *
584
- * Mirrors `resolveExpireOnToolMatch`'s traversal of the same config
585
- * block (undefined/non-object/`mode: session` all resolve to "not
586
- * configured"), but returns a bare boolean since the matcher builders
587
- * only need presence, not the pattern strings themselves.
588
- */
589
- function resolveExpireOnBashMatchConfigured(pack) {
590
- const raw = pack.config["approval_lifecycle"];
591
- if (raw === undefined || raw === null)
592
- return false;
593
- if (typeof raw !== "object" || Array.isArray(raw))
594
- return false;
595
- const obj = raw;
596
- if (obj["mode"] === "session")
597
- return false;
598
- const list = obj["expire_on_bash_match"];
599
- if (!Array.isArray(list))
600
- return false;
601
- return list.some((v) => typeof v === "string" && v.length > 0);
602
- }
603
- /**
604
- * Shared PostToolUse boundary resolution for BOTH the Claude and Codex
605
- * `buildHooks` branches (task bea04a03): combines
606
- * `resolveExpireOnToolMatch` and `resolveExpireOnBashMatchConfigured`
607
- * into the one decision each branch's IIFE needs. Extracted specifically
608
- * to avoid re-introducing the exact clone-avoidance problem
609
- * `understanding-before-execution-runtime.ts`'s `matchPostToolUseBoundary`
610
- * / `applyPostToolUseExpiry` / `describePostToolUseExpiry` extraction
611
- * already solved once for the two runtimes' hook CLIs (`check:duplication`
612
- * flagged the inline duplicate when this task first wired the two nearly-
613
- * identical IIFEs by hand).
614
- */
615
- function resolvePostToolUseBoundaries(pack) {
616
- const { tools, emitHook: toolsEmitHook } = resolveExpireOnToolMatch(pack);
617
- const bashConfigured = resolveExpireOnBashMatchConfigured(pack);
618
- return { tools, bashConfigured, emit: toolsEmitHook || bashConfigured };
619
- }
620
- function buildHooks(runtime, pack, mode, opts = {}) {
621
- // Per-mode hook commands are otherwise identical: the mode reaches the
622
- // package-owned Claude bins (BIN_USER_PROMPT_SUBMIT_CLAUDE,
623
- // BIN_STOP_CLAUDE) via the `UNDERSTANDING_GATE_MODE` env-var prefix
624
- // below (`wrapMode`), resolved by `resolveModeFromConfig` (config.mode >
625
- // DEFAULT_MODE — this is the GENERATION path, it does NOT read the env
626
- // var; see {@link MODE_ENV}'s doc comment for why) and coerced through
627
- // `toPackageMode` for the package's two-value enum. What changes per
628
- // mode beyond that is the instructions.md content + the actual injected
629
- // prompt (owned by the npm package, itself keyed off this same env var
630
- // at ITS OWN, later, live-invocation time).
631
- //
632
- // When `opts.reportsDir` is set (the apply path), each command is ALSO
633
- // prefixed with `UNDERSTANDING_GATE_REPORT_DIR=<absolute>` so all hooks
634
- // — including the standalone-package Stop bin which honors the same
635
- // env var — write/read the same directory.
636
- const wrap = (cmd) => prefixCommandWithReportsDir(cmd, opts.reportsDir);
637
- // When `opts.pauseFile` is set (the apply path), the Claude
638
- // UserPromptSubmit command ALSO gets prefixed with
639
- // `UNDERSTANDING_GATE_PAUSE_FILE=<absolute>` (see {@link PAUSE_FILE_ENV}'s
640
- // doc comment for why only this one hook needs it: the npm-backed bin
641
- // runs outside harness's own runtime and cannot resolve `generatedDir`
642
- // the way harness's own hooks do).
643
- const wrapPause = (cmd) => prefixCommandWithPauseFile(cmd, opts.pauseFile);
644
- // Task 5d73d78d review MEDIUM-7: omit the prefix entirely when the
645
- // resolved mode already coerces to the package's OWN default
646
- // (`fast_confirm`). Baking `UNDERSTANDING_GATE_MODE=fast_confirm`
647
- // unconditionally (as this did before this fix) made the package's
648
- // in-prompt `/grill` / "grill me" escalation marker permanently dead:
649
- // `pickMode()` (package `src/mode.ts`) checks its env var FIRST and
650
- // returns immediately on a match, never reaching the marker check —
651
- // so an operator on a `fast_confirm`-effective host could never
652
- // escalate a single prompt to `grill_me` via the marker, even though
653
- // the package ships exactly that mechanism. Leaving the command
654
- // unprefixed changes nothing about the EFFECTIVE default (the
655
- // package's own fallback is already `fast_confirm`) while restoring
656
- // the marker's liveness; a `grill_me`/`strict`-resolved mode still
657
- // gets the unconditional prefix, same as before.
658
- const wrapMode = (cmd) => {
659
- const pkgMode = toPackageMode(mode);
660
- if (pkgMode === "fast_confirm")
661
- return cmd;
662
- return `${MODE_ENV}=${shellQuoteSingle(pkgMode)} ${cmd}`;
663
- };
664
- if (runtime === "codex") {
665
- return [
666
- {
667
- name: `${HOOK_NAME_PREFIX}:codex:user-prompt-submit`,
668
- event: "UserPromptSubmit",
669
- command: COMMAND_USER_PROMPT_SUBMIT_CODEX,
670
- blocking: false,
671
- budget_ms: 5000,
672
- description: "Codex adapter: inject the Understanding-Gate instruction template before the agent acts. Phase 6 #6.",
673
- },
674
- {
675
- name: `${HOOK_NAME_PREFIX}:codex:stop`,
676
- event: "Stop",
677
- command: wrap(COMMAND_STOP_CODEX),
678
- blocking: false,
679
- budget_ms: 5000,
680
- description: "Codex adapter: capture the agent's Understanding Report into .understanding-gate/reports/ as approvalStatus:pending. Phase 6 #6 follow-up.",
681
- },
682
- {
683
- name: `${HOOK_NAME_PREFIX}:codex:pre-tool-use`,
684
- event: "PreToolUse",
685
- match: PRE_TOOL_USE_MATCH_CODEX,
686
- command: wrap(COMMAND_PRE_TOOL_USE_CODEX),
687
- blocking: "hard",
688
- // 15000 (task 7bf47554): `checkLedger` (src/cli/pack/hook-codex-
689
- // pre-tool-use.ts) runs an unconditional, ledger-consulting audit
690
- // probe on every invocation — even when the filesystem marker
691
- // already resolved the decision — bounded by the grounding-mcp
692
- // server's own `health.timeout_ms` (default 5000ms), the same
693
- // number budget_ms=5000 used for the outer Claude/Codex
694
- // kill-timeout, leaving no margin against a merely-slow (not
695
- // dead) ledger. See src/cli/init/templates.ts's budget note above
696
- // require-review-evidence for the full fail-open mechanism this
697
- // guards against.
698
- budget_ms: 15000,
699
- description: "Codex adapter: block apply_patch and Codex shell tools until the operator has approved the session's Understanding Report via harness approve understanding. Opens only on the signed approval marker; the persisted JSON report and the evidence-ledger tag are audit evidence.",
700
- },
701
- // PostToolUse marker-expiry (task a1348c89, widened by task
702
- // bea04a03). Same boundary-tool list as the Claude hook below
703
- // (resolveExpireOnToolMatch) so Codex expires on the identical
704
- // configured set (agent-tasks task_finish / task_abandon /
705
- // task_merge / pull_requests_merge / tasks_transition in the
706
- // scaffolds), but a DIFFERENT
707
- // `match` builder (`codexPostToolUseMatchPattern`, not
708
- // `postToolUseMatchPattern`): see that function's own doc comment
709
- // for why the Claude builder's anchored regex form silently
710
- // defeats the Codex generator's MCP tool-name alias expansion
711
- // (review finding on task a1348c89).
712
- // `match` is ALSO widened with the Codex shell-tool aliases
713
- // (Bash/shell/exec_command/functions.exec_command) whenever
714
- // `approval_lifecycle.expire_on_bash_match` carries at least one
715
- // pattern (task bea04a03): before this, `match` was built ONLY
716
- // from `expire_on_tool_match`, so a real shell call never reached
717
- // the hook body at all on EITHER runtime, even though
718
- // `matchPostToolUseBoundary`'s bash-regex check correctly
719
- // evaluates `expire_on_bash_match` once invoked. The widened
720
- // aliases are NEVER added to `expire_on_tool_match` itself — the
721
- // hook body still classifies a matched shell call as a bash-regex
722
- // match, not a tool-name match, via `CODEX_SHELL_TOOLS.has(toolName)`
723
- // in the caller (hook-codex-post-tool-use.ts).
724
- ...(() => {
725
- const { tools, bashConfigured, emit } = resolvePostToolUseBoundaries(pack);
726
- if (!emit)
727
- return [];
728
- const hook = {
729
- name: `${HOOK_NAME_PREFIX}:codex:post-tool-use`,
730
- event: "PostToolUse",
731
- match: codexPostToolUseMatchPattern(tools, bashConfigured),
732
- command: wrap(COMMAND_POST_TOOL_USE_CODEX),
733
- blocking: false,
734
- budget_ms: 2000,
735
- description: "Codex adapter: expire the approval marker AND the persisted report after a task-completion boundary tool listed in approval_lifecycle.expire_on_tool_match (scaffolds: agent-tasks task_finish / task_abandon / task_merge / pull_requests_merge / tasks_transition; a task_finish that lands in review keeps the approval) or an expire_on_bash_match shell command. Forces a fresh Understanding Report on the next task.",
736
- };
737
- return [hook];
738
- })(),
739
- // Active-claim tracker (harness/494fd1e5), Codex parity task
740
- // cf4cdc93 (parity-gaps doc gap #3). Always emitted alongside the
741
- // pack, mirroring the Claude sibling below — the matcher won't
742
- // fire for operators on non-agent-tasks tasking systems, so the
743
- // file simply never appears for them. Same command as Claude
744
- // (see TRACK_ACTIVE_CLAIM_COMMAND's doc comment above): the hook
745
- // body needs no Codex-specific handling.
746
- {
747
- name: `${HOOK_NAME_PREFIX}:codex:track-active-claim`,
748
- event: "PostToolUse",
749
- match: TRACK_ACTIVE_CLAIM_MATCH_CODEX,
750
- command: TRACK_ACTIVE_CLAIM_COMMAND,
751
- blocking: false,
752
- budget_ms: 2000,
753
- description: "Codex adapter: track the active agent-tasks claim by writing/clearing <generatedDir>/active-claim on task_start / task_finish / task_abandon / task_merge. Lets `harness approve understanding` auto-resolve the task id (harness/494fd1e5, Codex parity task cf4cdc93).",
754
- },
755
- ...(() => {
756
- const stayInScope = resolveStayInScopeConfig(pack.config["stay_in_scope"]);
757
- if (stayInScope === null)
758
- return [];
759
- return [{
760
- name: `${HOOK_NAME_PREFIX}:codex:stay-in-scope`,
761
- event: "PostToolUse",
762
- match: stayInScope.tools.join("|"),
763
- command: STAY_IN_SCOPE_COMMAND,
764
- blocking: false,
765
- budget_ms: 2000,
766
- description: "Codex adapter: emit the configured soft stay-in-scope reminder and audit row.",
767
- }];
768
- })(),
769
- ];
770
- }
771
- // `min_version` floor on the npm-backed bins: 0.4.0 ships the
772
- // required "Prior Art" 10th section of the Understanding Report
773
- // (agent-grounding PR #85, harness task 798d7173). Operators below
774
- // this floor would silently miss the section because the Stop-capture
775
- // parser doesn't yet enforce it. The prior floor was 0.3.1 (first
776
- // release whose `understanding-gate --version` reported the actual
777
- // installed version rather than a stale literal; agent-grounding PRs
778
- // #80 + #81); 0.4.0 supersedes it. The PreToolUse blocker below is
779
- // the harness CLI itself, not an npm-backed bin, so it does not carry
780
- // a floor here.
781
- // 0.5.0 raises the floor again: the UserPromptSubmit hook now carries an
782
- // UNDERSTANDING_GATE_PAUSE_FILE prefix, and only 0.5.0 and later read that
783
- // variable. On an older gate the prefix is set but ignored, so the pause
784
- // wiring is silently inert; the floor makes `harness doctor` say so instead
785
- // of leaving the operator to discover it.
786
- const UG_MIN_VERSION = "0.5.0";
787
- const UG_VERSION_COMMAND = [
788
- "understanding-gate",
789
- "--version",
790
- ];
791
- return [
792
- {
793
- name: `${HOOK_NAME_PREFIX}:user-prompt-submit`,
794
- event: "UserPromptSubmit",
795
- command: wrapMode(wrapPause(BIN_USER_PROMPT_SUBMIT_CLAUDE)),
796
- blocking: false,
797
- budget_ms: 5000,
798
- min_version: UG_MIN_VERSION,
799
- version_command: UG_VERSION_COMMAND,
800
- description: "Inject the Understanding-Gate instruction template before the agent acts. Source: @lannguyensi/understanding-gate.",
801
- },
802
- {
803
- name: `${HOOK_NAME_PREFIX}:stop`,
804
- event: "Stop",
805
- command: wrapMode(wrap(BIN_STOP_CLAUDE)),
806
- blocking: false,
807
- budget_ms: 5000,
808
- min_version: UG_MIN_VERSION,
809
- version_command: UG_VERSION_COMMAND,
810
- description: "Capture the agent's Understanding Report into .understanding-gate/reports/. Source: @lannguyensi/understanding-gate.",
811
- },
812
- {
813
- name: `${HOOK_NAME_PREFIX}:pre-tool-use`,
814
- event: "PreToolUse",
815
- match: PRE_TOOL_USE_MATCH_CLAUDE,
816
- command: wrap(PRE_TOOL_USE_COMMAND_CLAUDE),
817
- blocking: "hard",
818
- // 15000: same rationale as the Codex sibling above (checkLedger in
819
- // src/cli/pack/hook-pre-tool-use.ts is the same unconditional
820
- // ledger-consulting audit probe, same health.timeout_ms bound).
821
- budget_ms: 15000,
822
- description: "Block Edit/Write/Bash until the operator has approved the session's Understanding Report via harness approve understanding. Opens only on the signed approval marker; the persisted JSON report and the evidence-ledger tag (understanding-approved:${SESSION_ID}) are audit evidence.",
823
- },
824
- // In-flight subagent records (slice 2, docs/decisions/2026-08-27-ug-
825
- // auto-mode-approval.md "TTL, cwd, and subagents"). An Agent-tool
826
- // subagent shares its parent's session_id but cannot itself call
827
- // `harness approve understanding`; SubagentStart copies whatever
828
- // approval the parent holds AT SPAWN TIME into a signed record the
829
- // subagent can present later even if the parent's own marker expires
830
- // mid-flight, and SubagentStop removes it when the subagent finishes.
831
- // Always emitted alongside the PreToolUse blocker above — never
832
- // gated behind `approval_lifecycle.mode` the way the marker-expiry
833
- // hook below is, since a record is a copy of authority, not itself
834
- // subject to that opt-out. Claude-only: the Agent tool (and its
835
- // SubagentStart/SubagentStop events) has no Codex equivalent.
836
- {
837
- name: `${HOOK_NAME_PREFIX}:subagent-start`,
838
- event: "SubagentStart",
839
- // Reads persisted reports (report-hash cross-check before minting the
840
- // record), so it carries the same reports-dir prefix as the other
841
- // report-reading hooks and agrees with where `harness approve` wrote.
842
- command: wrap(SUBAGENT_START_COMMAND),
843
- blocking: false,
844
- budget_ms: 2000,
845
- description: "Write a signed in-flight record for a newly-started Agent-tool subagent when the parent session currently holds a valid understanding-gate approval, so the subagent can keep that approval independent of what happens to the parent's own marker afterwards.",
846
- },
847
- {
848
- name: `${HOOK_NAME_PREFIX}:subagent-stop`,
849
- event: "SubagentStop",
850
- command: SUBAGENT_STOP_COMMAND,
851
- blocking: false,
852
- budget_ms: 2000,
853
- description: "Remove the in-flight record written for this subagent by subagent-start when it finishes.",
854
- },
855
- // PostToolUse marker-expiry hook (agent-tasks/d8ee60ca). Fires on the
856
- // configured task-boundary tools, and (task bea04a03) on a Bash call
857
- // when `approval_lifecycle.expire_on_bash_match` carries at least one
858
- // pattern, and deletes the approval marker so the next Edit / Write /
859
- // Bash forces a fresh Understanding Report. The runtime tool list is
860
- // the configured expire_on_tool_match (scaffolds: agent-tasks
861
- // task_finish / task_abandon / task_merge / pull_requests_merge /
862
- // tasks_transition); when no explicit list is configured,
863
- // DEFAULT_BOUNDARY_TOOL_NAMES is both the emitted matcher and the
864
- // runtime boundary list (parseApprovalLifecycle).
865
- // Operators on other task systems override the list via
866
- // config.approval_lifecycle.expire_on_tool_match; setting
867
- // `approval_lifecycle: { mode: session }` opts out entirely and
868
- // suppresses this hook from being emitted at all.
869
- //
870
- // Before task bea04a03, `match` was built ONLY from
871
- // `expire_on_tool_match`, so a real `Bash` call never invoked this
872
- // hook at all — `matchPostToolUseBoundary`'s bash-regex check (which
873
- // DOES correctly evaluate `expire_on_bash_match` once invoked)
874
- // was unreachable. Widening `match` to include "Bash" does not
875
- // change how the hook body classifies the match: a Bash call that
876
- // fires the hook is still evaluated as a bash-regex match
877
- // (`toolNameMatched: false`), never folded into
878
- // `expire_on_tool_match`'s own tool-name semantics.
879
- ...(() => {
880
- const { tools, bashConfigured, emit } = resolvePostToolUseBoundaries(pack);
881
- if (!emit)
882
- return [];
883
- const hook = {
884
- name: `${HOOK_NAME_PREFIX}:post-tool-use`,
885
- event: "PostToolUse",
886
- match: postToolUseMatchPattern(tools, bashConfigured),
887
- // Wrap with UNDERSTANDING_GATE_REPORT_DIR so the post-tool-use
888
- // hook resolves the same persisted-reports directory as the
889
- // pre-tool-use blocker; otherwise it can't expire the persisted
890
- // report alongside the marker (harness/1ee26e77 follow-up).
891
- command: wrap(POST_TOOL_USE_COMMAND_CLAUDE),
892
- blocking: false,
893
- budget_ms: 2000,
894
- description: "Expire the approval marker AND the persisted report after a task-completion boundary tool listed in approval_lifecycle.expire_on_tool_match (scaffolds: agent-tasks task_finish / task_abandon / task_merge / pull_requests_merge / tasks_transition; a task_finish that lands in review keeps the approval) or an expire_on_bash_match Bash command. Forces a fresh Understanding Report on the next task.",
895
- };
896
- return [hook];
897
- })(),
898
- // Active-claim tracker (harness/494fd1e5). PostToolUse hook on
899
- // agent-tasks task_start / task_finish / task_abandon / task_merge
900
- // (task_merge added by task c86e3c4a: previously untracked here, so
901
- // a real task_merge tool call never dispatched to the hook at all).
902
- // Maintains a small file at <generatedDir>/active-claim so `harness
903
- // approve understanding` can auto-resolve the task id when --task is
904
- // absent. Always emitted alongside the pack — operators on other
905
- // tasking systems are unaffected (the matcher won't fire for
906
- // their tools), the file simply never appears.
907
- {
908
- name: `${HOOK_NAME_PREFIX}:track-active-claim`,
909
- event: "PostToolUse",
910
- match: TRACK_ACTIVE_CLAIM_MATCH,
911
- command: TRACK_ACTIVE_CLAIM_COMMAND,
912
- blocking: false,
913
- budget_ms: 2000,
914
- description: "Track the active agent-tasks claim by writing/clearing <generatedDir>/active-claim on task_start / task_finish / task_abandon / task_merge. Lets `harness approve understanding` auto-resolve the task id (harness/494fd1e5).",
915
- },
916
- ...(() => {
917
- const stayInScope = resolveStayInScopeConfig(pack.config["stay_in_scope"]);
918
- if (stayInScope === null)
919
- return [];
920
- return [{
921
- name: `${HOOK_NAME_PREFIX}:stay-in-scope`,
922
- event: "PostToolUse",
923
- match: `^(?:${stayInScope.tools.map(escapeMatcherLiteral).join("|")})$`,
924
- command: STAY_IN_SCOPE_COMMAND,
925
- blocking: false,
926
- budget_ms: 2000,
927
- description: "Emit the configured soft stay-in-scope reminder and audit row.",
928
- }];
929
- })(),
930
- ];
931
- }
932
- function modeFriction(mode) {
933
- switch (mode) {
934
- case "fast_confirm":
935
- return "low friction. The gate fires on prompts the classifier flags as execution-relevant. Brief Understanding Report; one-line approval.";
936
- case "grill_me":
937
- return "medium friction (default). The gate fires on any prompt the agent might respond to with a write. Full Understanding Report (assumptions, openQuestions, outOfScope, risks, verificationPlan). Push-back is encouraged.";
938
- case "strict":
939
- return "high friction. The gate fires on every prompt. Report MUST include verificationPlan and outOfScope; requiresHumanApproval is forced to true.";
940
- }
941
- }
942
- function buildInstructions(pack, mode, runtime) {
943
- const description = pack.description?.trim() ?? "";
944
- const isCodex = runtime === "codex";
945
- const isOpencode = runtime === "opencode";
946
- const injectorCmd = isCodex
947
- ? COMMAND_USER_PROMPT_SUBMIT_CODEX
948
- : BIN_USER_PROMPT_SUBMIT_CLAUDE;
949
- const stopCmd = isCodex ? COMMAND_STOP_CODEX : BIN_STOP_CLAUDE;
950
- const blockerCmd = isCodex
951
- ? COMMAND_PRE_TOOL_USE_CODEX
952
- : PRE_TOOL_USE_COMMAND_CLAUDE;
953
- const blockerMatch = isCodex
954
- ? PRE_TOOL_USE_MATCH_CODEX
955
- : PRE_TOOL_USE_MATCH_CLAUDE;
956
- const settingsArtefact = isCodex
957
- ? "`harness.generated/codex/config.toml`"
958
- : "harness-managed `settings.json`";
959
- // HIGH-F1 (batch18 fix-round, task f34eb233): before this, opencode
960
- // fell through to the claude-code `else` branch above (buildHooks
961
- // does the same) and the "## Effect" text below claimed hooks were
962
- // wired into `settings.json` even though opencode has no declarative
963
- // hook/event field and `harness apply --runtime opencode` never
964
- // projects `hooks[]` into the generated opencode artefact (see
965
- // runtime.ts's header). Mirrors post-merge-gate.ts's "## Runtime"
966
- // UNSUPPORTED marker.
967
- const runtimeUnsupportedNote = isOpencode
968
- ? " (UNSUPPORTED — opencode has no declarative hook/event wiring; this pack's hooks are not projected into any opencode artefact)"
969
- : "";
970
- const wiringSentence = isOpencode
971
- ? "This pack's hooks are **not wired** under `--runtime opencode`: opencode has no declarative hook/event field (only a JS/TS plugin API), and `harness apply --runtime opencode` never projects `hooks[]` into the generated opencode artefact. The mechanics below describe the Claude Code / Codex behavior this pack implements; none of it fires today under opencode."
972
- : `While this pack is enabled, hooks are wired into the ${settingsArtefact}:`;
973
- const stopBullet = `2. \`Stop\` capture (\`${stopCmd}\`): persists the emitted Understanding
974
- Report under \`.understanding-gate/reports/\` for audit and downstream
975
- approval consumption.
976
- `;
977
- const blockerOrdinal = "3";
978
- return `# Policy Pack: ${PACK_NAME}
979
-
980
- > Operator audit copy. The agent-facing prompt is injected at runtime by
981
- > the \`${injectorCmd}\` UserPromptSubmit hook; that text lives
982
- > in the \`@lannguyensi/understanding-gate\` package, not here. This file
983
- > records WHAT the pack is doing and HOW it is configured so that
984
- > \`harness diff --since-apply\` can flag operator-facing drift.
985
-
986
- ## Runtime
987
-
988
- ${runtime}${runtimeUnsupportedNote}
989
-
990
- ## Mode
991
-
992
- ${mode}
993
-
994
- ${modeFriction(mode)}
995
-
996
- ## Effect
997
-
998
- ${wiringSentence}
999
-
1000
- 1. \`UserPromptSubmit\` injector (\`${injectorCmd}\`): inserts the
1001
- Understanding-Gate instruction template into the agent's first response.
1002
- ${stopBullet}${blockerOrdinal}. \`PreToolUse\` blocker (\`${blockerCmd}\`, blocking: hard)
1003
- on \`${blockerMatch}\`: refuses the tool call until the operator has
1004
- approved the session's report. Opens ONLY on the HMAC-signed approval
1005
- marker under \`harness.generated/.approvals/\` written by
1006
- \`harness approve understanding\`; the persisted JSON report under
1007
- \`.understanding-gate/reports/\` and the evidence-ledger tag
1008
- (\`understanding-approved:\${SESSION_ID}\`) are audit evidence and
1009
- never open the gate on their own (task 7402301d).
1010
-
1011
- ## Approval
1012
-
1013
- The standalone blocker shipped in \`@lannguyensi/understanding-gate@>=0.2.0\`
1014
- checks the persisted JSON report's \`approvalStatus\`. Phase 6 #4 will
1015
- add a harness-side blocker that ALSO consults the evidence-ledger tag
1016
- \`understanding-approved:\${SESSION_ID}\` (canonical for harnessed
1017
- sessions), and \`harness approve understanding\` will round-trip both.
1018
- Until then, approval flows through the package's own CLI.
1019
-
1020
- ## Pack metadata
1021
- ${description ? `\n> ${description.replace(/\n/g, "\n> ")}\n` : ""}
1022
- - Source: \`builtin\`
1023
- - Pack: \`${PACK_NAME}\`
1024
- - Mode: \`${mode}\`
1025
- - Runtime: \`${runtime}\`
1026
-
1027
- ## See also
1028
-
1029
- - \`docs/policy-packs/understanding-before-execution.md\` (full reference)
1030
- - \`docs/ROADMAP.md\` Phase 6 sub-task decomposition
1031
- `;
1032
- }
1033
- function resolvePermissionProfile(pack) {
1034
- const raw = pack.config["permission_profile"];
1035
- if (raw === undefined)
1036
- return { permissions: null, warning: null };
1037
- if (typeof raw !== "string") {
1038
- return {
1039
- permissions: null,
1040
- warning: `policy_packs[${pack.name}].config.permission_profile: expected a string, got ${typeof raw}; skipping permission contribution.`,
1041
- };
1042
- }
1043
- if (!isKnownProfileName(raw)) {
1044
- return {
1045
- permissions: null,
1046
- warning: `policy_packs[${pack.name}].config.permission_profile: unrecognised profile ${JSON.stringify(raw)}. Allowed: ${KNOWN_PROFILE_NAMES.join(", ")}. Skipping permission contribution.`,
1047
- };
1048
- }
1049
- const profile = resolveProfile(raw);
1050
- if (!profile)
1051
- return { permissions: null, warning: null };
1052
- return { permissions: profileToSettingsPermissions(profile), warning: null };
1053
- }
1054
- export function resolve(pack, runtime = DEFAULT_RUNTIME, opts = {}) {
1055
- // GENERATION path (task 5d73d78d review HIGH-3): config-only, no env —
1056
- // see {@link MODE_ENV}'s doc comment for why apply-time artefacts must
1057
- // not depend on the live process environment.
1058
- const { mode, warning } = resolveModeFromConfig(pack);
1059
- const hooks = buildHooks(runtime, pack, mode, opts);
1060
- const instructionsContent = buildInstructions(pack, mode, runtime);
1061
- const files = [
1062
- {
1063
- relativePath: `policy-packs/${PACK_NAME}/instructions.md`,
1064
- content: instructionsContent,
1065
- },
1066
- ];
1067
- const warnings = [];
1068
- if (warning)
1069
- warnings.push(warning);
1070
- const profileResult = resolvePermissionProfile(pack);
1071
- if (profileResult.warning)
1072
- warnings.push(profileResult.warning);
1073
- const contribution = { hooks, files };
1074
- if (profileResult.permissions)
1075
- contribution.permissions = profileResult.permissions;
1076
- return { contribution, warnings };
1077
- }
1078
- //# sourceMappingURL=understanding-before-execution.js.map