@lannguyensi/harness 0.63.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 (702) hide show
  1. package/CHANGELOG.md +90 -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 -338
  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 -705
  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 -378
  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 +15 -2607
  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 -243
  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/register-gate-group.d.ts +5 -0
  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 +5 -0
  145. package/dist/cli/register-operator-lifecycle.js +20 -0
  146. package/dist/cli/register-operator-lifecycle.js.map +1 -0
  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-setup-group.d.ts +5 -0
  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.d.ts +5 -0
  160. package/dist/cli/remove/register.js +25 -0
  161. package/dist/cli/remove/register.js.map +1 -0
  162. package/dist/cli/shell-quote.d.ts +7 -0
  163. package/dist/cli/shell-quote.js +17 -0
  164. package/dist/cli/shell-quote.js.map +1 -0
  165. package/dist/cli/uninstall/index.d.ts +4 -2
  166. package/dist/cli/uninstall/index.js +15 -7
  167. package/dist/cli/uninstall/index.js.map +1 -1
  168. package/dist/cli/uninstall/register.d.ts +5 -0
  169. package/dist/cli/uninstall/register.js +171 -0
  170. package/dist/cli/uninstall/register.js.map +1 -0
  171. package/dist/cli/uninstall/snapshot.d.ts +15 -0
  172. package/dist/cli/uninstall/snapshot.js +38 -0
  173. package/dist/cli/uninstall/snapshot.js.map +1 -1
  174. package/dist/cli/validate/checks.d.ts +0 -77
  175. package/dist/cli/validate/checks.js +3 -1049
  176. package/dist/cli/validate/checks.js.map +1 -1
  177. package/dist/cli/validate/index.js +19 -15
  178. package/dist/cli/validate/index.js.map +1 -1
  179. package/dist/index.d.ts +0 -3
  180. package/dist/index.js +0 -3
  181. package/dist/index.js.map +1 -1
  182. package/dist/io/claude-mcp.d.ts +1 -1
  183. package/dist/io/claude-mcp.js +27 -14
  184. package/dist/io/claude-mcp.js.map +1 -1
  185. package/dist/io/harness-lock.js +2 -2
  186. package/dist/io/harness-lock.js.map +1 -1
  187. package/dist/io/lock.d.ts +0 -26
  188. package/dist/io/lock.js +10 -27
  189. package/dist/io/lock.js.map +1 -1
  190. package/dist/io/merge-settings.js +6 -4
  191. package/dist/io/merge-settings.js.map +1 -1
  192. package/dist/io/project-name.d.ts +22 -39
  193. package/dist/io/project-name.js +25 -42
  194. package/dist/io/project-name.js.map +1 -1
  195. package/dist/io/read-regular-file.d.ts +103 -40
  196. package/dist/io/read-regular-file.js +196 -35
  197. package/dist/io/read-regular-file.js.map +1 -1
  198. package/dist/io/restart-hints.js +3 -6
  199. package/dist/io/restart-hints.js.map +1 -1
  200. package/dist/io/version-compare.d.ts +1 -3
  201. package/dist/io/version-compare.js +1 -3
  202. package/dist/io/version-compare.js.map +1 -1
  203. package/dist/io/write-regular-file.d.ts +30 -0
  204. package/dist/io/write-regular-file.js +85 -0
  205. package/dist/io/write-regular-file.js.map +1 -0
  206. package/dist/overrides/index.d.ts +1 -0
  207. package/dist/overrides/index.js +1 -0
  208. package/dist/overrides/index.js.map +1 -1
  209. package/dist/overrides/merge-layers.d.ts +43 -0
  210. package/dist/overrides/merge-layers.js +76 -0
  211. package/dist/overrides/merge-layers.js.map +1 -0
  212. package/dist/overrides/merge.d.ts +16 -0
  213. package/dist/overrides/merge.js +21 -8
  214. package/dist/overrides/merge.js.map +1 -1
  215. package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +4 -69
  216. package/dist/policy-packs/builtin/branch-protection-runtime.js +12 -84
  217. package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -1
  218. package/dist/policy-packs/builtin/branch-protection.d.ts +7 -30
  219. package/dist/policy-packs/builtin/branch-protection.js +56 -89
  220. package/dist/policy-packs/builtin/branch-protection.js.map +1 -1
  221. package/dist/policy-packs/config-check.d.ts +7 -5
  222. package/dist/policy-packs/config-check.js +2 -2
  223. package/dist/policy-packs/config-check.js.map +1 -1
  224. package/dist/policy-packs/expand.d.ts +1 -3
  225. package/dist/policy-packs/expand.js +5 -42
  226. package/dist/policy-packs/expand.js.map +1 -1
  227. package/dist/policy-packs/index.d.ts +3 -3
  228. package/dist/policy-packs/index.js +2 -2
  229. package/dist/policy-packs/index.js.map +1 -1
  230. package/dist/policy-packs/registry.d.ts +9 -38
  231. package/dist/policy-packs/registry.js +5 -65
  232. package/dist/policy-packs/registry.js.map +1 -1
  233. package/dist/policy-packs/runtime.d.ts +0 -4
  234. package/dist/policy-packs/runtime.js +9 -22
  235. package/dist/policy-packs/runtime.js.map +1 -1
  236. package/dist/policy-packs/types.d.ts +0 -19
  237. package/dist/policy-packs/ux-compare.d.ts +1 -11
  238. package/dist/policy-packs/ux-compare.js +6 -42
  239. package/dist/policy-packs/ux-compare.js.map +1 -1
  240. package/dist/policy-packs/ux-drift-check.d.ts +5 -5
  241. package/dist/policy-packs/ux-drift-check.js +17 -22
  242. package/dist/policy-packs/ux-drift-check.js.map +1 -1
  243. package/dist/policy-packs/version-check.d.ts +5 -26
  244. package/dist/policy-packs/version-check.js +19 -74
  245. package/dist/policy-packs/version-check.js.map +1 -1
  246. package/dist/probes/memory.d.ts +1 -1
  247. package/dist/probes/memory.js +1 -1
  248. package/dist/probes/memory.js.map +1 -1
  249. package/dist/runtime/agent-facing.d.ts +9 -0
  250. package/dist/runtime/agent-facing.js +28 -14
  251. package/dist/runtime/agent-facing.js.map +1 -1
  252. package/dist/runtime/bounded-text.d.ts +15 -0
  253. package/dist/runtime/bounded-text.js +27 -0
  254. package/dist/runtime/bounded-text.js.map +1 -0
  255. package/dist/runtime/git-branch.d.ts +125 -0
  256. package/dist/runtime/git-branch.js +381 -0
  257. package/dist/runtime/git-branch.js.map +1 -0
  258. package/dist/runtime/hermetic-spawn-guard.d.ts +2 -2
  259. package/dist/runtime/hermetic-spawn-guard.js +24 -34
  260. package/dist/runtime/hermetic-spawn-guard.js.map +1 -1
  261. package/dist/runtime/home-dir.js +3 -2
  262. package/dist/runtime/home-dir.js.map +1 -1
  263. package/dist/runtime/tool-name-aliases.d.ts +0 -6
  264. package/dist/runtime/tool-name-aliases.js +5 -18
  265. package/dist/runtime/tool-name-aliases.js.map +1 -1
  266. package/dist/schema/grounding.d.ts +7 -54
  267. package/dist/schema/grounding.js +10 -12
  268. package/dist/schema/grounding.js.map +1 -1
  269. package/dist/schema/hooks.d.ts +39 -136
  270. package/dist/schema/hooks.js +3 -6
  271. package/dist/schema/hooks.js.map +1 -1
  272. package/dist/schema/index.d.ts +114 -3828
  273. package/dist/schema/index.js +41 -80
  274. package/dist/schema/index.js.map +1 -1
  275. package/dist/schema/memory.d.ts +54 -131
  276. package/dist/schema/memory.js +2 -2
  277. package/dist/schema/memory.js.map +1 -1
  278. package/dist/schema/policy-packs.d.ts +3 -45
  279. package/dist/schema/policy-packs.js +7 -13
  280. package/dist/schema/policy-packs.js.map +1 -1
  281. package/dist/schema/policy-ux.d.ts +7 -0
  282. package/dist/schema/policy-ux.js +18 -0
  283. package/dist/schema/policy-ux.js.map +1 -0
  284. package/dist/schema/removed-keys.d.ts +185 -0
  285. package/dist/schema/removed-keys.js +531 -0
  286. package/dist/schema/removed-keys.js.map +1 -0
  287. package/dist/schema/tools.d.ts +30 -268
  288. package/dist/schema/tools.js +4 -4
  289. package/dist/schema/tools.js.map +1 -1
  290. package/package.json +5 -16
  291. package/dist/cli/approve/branch-protection.d.ts +0 -69
  292. package/dist/cli/approve/branch-protection.js +0 -144
  293. package/dist/cli/approve/branch-protection.js.map +0 -1
  294. package/dist/cli/approve/risk.d.ts +0 -112
  295. package/dist/cli/approve/risk.js +0 -197
  296. package/dist/cli/approve/risk.js.map +0 -1
  297. package/dist/cli/approve/stdin-report.d.ts +0 -57
  298. package/dist/cli/approve/stdin-report.js +0 -145
  299. package/dist/cli/approve/stdin-report.js.map +0 -1
  300. package/dist/cli/approve/understanding.d.ts +0 -410
  301. package/dist/cli/approve/understanding.js +0 -996
  302. package/dist/cli/approve/understanding.js.map +0 -1
  303. package/dist/cli/audit.d.ts +0 -80
  304. package/dist/cli/audit.js +0 -252
  305. package/dist/cli/audit.js.map +0 -1
  306. package/dist/cli/delegate/index.d.ts +0 -76
  307. package/dist/cli/delegate/index.js +0 -443
  308. package/dist/cli/delegate/index.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/rogue-ledger.d.ts +0 -53
  319. package/dist/cli/doctor/rogue-ledger.js +0 -153
  320. package/dist/cli/doctor/rogue-ledger.js.map +0 -1
  321. package/dist/cli/doctor/session-start-preflight-setup-version.d.ts +0 -83
  322. package/dist/cli/doctor/session-start-preflight-setup-version.js +0 -114
  323. package/dist/cli/doctor/session-start-preflight-setup-version.js.map +0 -1
  324. package/dist/cli/doctor/settings-drift.d.ts +0 -25
  325. package/dist/cli/doctor/settings-drift.js +0 -213
  326. package/dist/cli/doctor/settings-drift.js.map +0 -1
  327. package/dist/cli/doctor/toolchain-parity.d.ts +0 -63
  328. package/dist/cli/doctor/toolchain-parity.js +0 -154
  329. package/dist/cli/doctor/toolchain-parity.js.map +0 -1
  330. package/dist/cli/doctor/ug-auto-approvals.d.ts +0 -40
  331. package/dist/cli/doctor/ug-auto-approvals.js +0 -91
  332. package/dist/cli/doctor/ug-auto-approvals.js.map +0 -1
  333. package/dist/cli/doctor/ug-delegations.d.ts +0 -26
  334. package/dist/cli/doctor/ug-delegations.js +0 -121
  335. package/dist/cli/doctor/ug-delegations.js.map +0 -1
  336. package/dist/cli/doctor/ug-inflight.d.ts +0 -35
  337. package/dist/cli/doctor/ug-inflight.js +0 -57
  338. package/dist/cli/doctor/ug-inflight.js.map +0 -1
  339. package/dist/cli/doctor/understanding-mode-env.d.ts +0 -51
  340. package/dist/cli/doctor/understanding-mode-env.js +0 -98
  341. package/dist/cli/doctor/understanding-mode-env.js.map +0 -1
  342. package/dist/cli/dry-run.d.ts +0 -46
  343. package/dist/cli/dry-run.js +0 -250
  344. package/dist/cli/dry-run.js.map +0 -1
  345. package/dist/cli/event-input.d.ts +0 -28
  346. package/dist/cli/event-input.js +0 -73
  347. package/dist/cli/event-input.js.map +0 -1
  348. package/dist/cli/explain-action.d.ts +0 -20
  349. package/dist/cli/explain-action.js +0 -27
  350. package/dist/cli/explain-action.js.map +0 -1
  351. package/dist/cli/explain-policy.d.ts +0 -135
  352. package/dist/cli/explain-policy.js +0 -266
  353. package/dist/cli/explain-policy.js.map +0 -1
  354. package/dist/cli/explain.d.ts +0 -31
  355. package/dist/cli/explain.js +0 -159
  356. package/dist/cli/explain.js.map +0 -1
  357. package/dist/cli/gc/index.d.ts +0 -63
  358. package/dist/cli/gc/index.js +0 -566
  359. package/dist/cli/gc/index.js.map +0 -1
  360. package/dist/cli/pack/approve-escape.d.ts +0 -19
  361. package/dist/cli/pack/approve-escape.js +0 -190
  362. package/dist/cli/pack/approve-escape.js.map +0 -1
  363. package/dist/cli/pack/auto-approve-path.d.ts +0 -146
  364. package/dist/cli/pack/auto-approve-path.js +0 -462
  365. package/dist/cli/pack/auto-approve-path.js.map +0 -1
  366. package/dist/cli/pack/hook-codex-post-tool-use.d.ts +0 -25
  367. package/dist/cli/pack/hook-codex-post-tool-use.js +0 -160
  368. package/dist/cli/pack/hook-codex-post-tool-use.js.map +0 -1
  369. package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +0 -48
  370. package/dist/cli/pack/hook-codex-pre-tool-use.js +0 -474
  371. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +0 -1
  372. package/dist/cli/pack/hook-codex-stop.d.ts +0 -35
  373. package/dist/cli/pack/hook-codex-stop.js +0 -329
  374. package/dist/cli/pack/hook-codex-stop.js.map +0 -1
  375. package/dist/cli/pack/hook-codex-user-prompt-submit.d.ts +0 -24
  376. package/dist/cli/pack/hook-codex-user-prompt-submit.js +0 -93
  377. package/dist/cli/pack/hook-codex-user-prompt-submit.js.map +0 -1
  378. package/dist/cli/pack/hook-post-merge-gate-record.d.ts +0 -37
  379. package/dist/cli/pack/hook-post-merge-gate-record.js +0 -190
  380. package/dist/cli/pack/hook-post-merge-gate-record.js.map +0 -1
  381. package/dist/cli/pack/hook-post-merge-gate.d.ts +0 -34
  382. package/dist/cli/pack/hook-post-merge-gate.js +0 -277
  383. package/dist/cli/pack/hook-post-merge-gate.js.map +0 -1
  384. package/dist/cli/pack/hook-post-tool-use.d.ts +0 -45
  385. package/dist/cli/pack/hook-post-tool-use.js +0 -137
  386. package/dist/cli/pack/hook-post-tool-use.js.map +0 -1
  387. package/dist/cli/pack/hook-pre-tool-use.d.ts +0 -92
  388. package/dist/cli/pack/hook-pre-tool-use.js +0 -1328
  389. package/dist/cli/pack/hook-pre-tool-use.js.map +0 -1
  390. package/dist/cli/pack/hook-runtime-reality.d.ts +0 -63
  391. package/dist/cli/pack/hook-runtime-reality.js +0 -210
  392. package/dist/cli/pack/hook-runtime-reality.js.map +0 -1
  393. package/dist/cli/pack/hook-solution-acceptance-writeguard.d.ts +0 -32
  394. package/dist/cli/pack/hook-solution-acceptance-writeguard.js +0 -337
  395. package/dist/cli/pack/hook-solution-acceptance-writeguard.js.map +0 -1
  396. package/dist/cli/pack/hook-solution-acceptance.d.ts +0 -157
  397. package/dist/cli/pack/hook-solution-acceptance.js +0 -530
  398. package/dist/cli/pack/hook-solution-acceptance.js.map +0 -1
  399. package/dist/cli/pack/hook-stay-in-scope.d.ts +0 -37
  400. package/dist/cli/pack/hook-stay-in-scope.js +0 -128
  401. package/dist/cli/pack/hook-stay-in-scope.js.map +0 -1
  402. package/dist/cli/pack/hook-subagent-start.d.ts +0 -23
  403. package/dist/cli/pack/hook-subagent-start.js +0 -88
  404. package/dist/cli/pack/hook-subagent-start.js.map +0 -1
  405. package/dist/cli/pack/hook-subagent-stop.d.ts +0 -19
  406. package/dist/cli/pack/hook-subagent-stop.js +0 -41
  407. package/dist/cli/pack/hook-subagent-stop.js.map +0 -1
  408. package/dist/cli/pack/hook-track-active-claim.d.ts +0 -27
  409. package/dist/cli/pack/hook-track-active-claim.js +0 -275
  410. package/dist/cli/pack/hook-track-active-claim.js.map +0 -1
  411. package/dist/cli/pack/transcript-report-scan.d.ts +0 -71
  412. package/dist/cli/pack/transcript-report-scan.js +0 -359
  413. package/dist/cli/pack/transcript-report-scan.js.map +0 -1
  414. package/dist/cli/pack/understanding-report-schema-hint.d.ts +0 -26
  415. package/dist/cli/pack/understanding-report-schema-hint.js +0 -120
  416. package/dist/cli/pack/understanding-report-schema-hint.js.map +0 -1
  417. package/dist/cli/pack/upgrade.d.ts +0 -32
  418. package/dist/cli/pack/upgrade.js +0 -273
  419. package/dist/cli/pack/upgrade.js.map +0 -1
  420. package/dist/cli/pause/index.d.ts +0 -113
  421. package/dist/cli/pause/index.js +0 -251
  422. package/dist/cli/pause/index.js.map +0 -1
  423. package/dist/cli/pause-check.d.ts +0 -22
  424. package/dist/cli/pause-check.js +0 -54
  425. package/dist/cli/pause-check.js.map +0 -1
  426. package/dist/cli/policy/intercept.d.ts +0 -233
  427. package/dist/cli/policy/intercept.js +0 -1020
  428. package/dist/cli/policy/intercept.js.map +0 -1
  429. package/dist/cli/policy/risk-envelope-enrichment.d.ts +0 -40
  430. package/dist/cli/policy/risk-envelope-enrichment.js +0 -108
  431. package/dist/cli/policy/risk-envelope-enrichment.js.map +0 -1
  432. package/dist/cli/record/index.d.ts +0 -81
  433. package/dist/cli/record/index.js +0 -348
  434. package/dist/cli/record/index.js.map +0 -1
  435. package/dist/cli/resolve-env.d.ts +0 -32
  436. package/dist/cli/resolve-env.js +0 -47
  437. package/dist/cli/resolve-env.js.map +0 -1
  438. package/dist/cli/session-export/index.d.ts +0 -46
  439. package/dist/cli/session-export/index.js +0 -169
  440. package/dist/cli/session-export/index.js.map +0 -1
  441. package/dist/cli/session-export/redact.d.ts +0 -22
  442. package/dist/cli/session-export/redact.js +0 -47
  443. package/dist/cli/session-export/redact.js.map +0 -1
  444. package/dist/cli/session-export/transcript.d.ts +0 -24
  445. package/dist/cli/session-export/transcript.js +0 -164
  446. package/dist/cli/session-export/transcript.js.map +0 -1
  447. package/dist/cli/session-start/branch-check.d.ts +0 -18
  448. package/dist/cli/session-start/branch-check.js +0 -140
  449. package/dist/cli/session-start/branch-check.js.map +0 -1
  450. package/dist/cli/session-start/index.d.ts +0 -121
  451. package/dist/cli/session-start/index.js +0 -591
  452. package/dist/cli/session-start/index.js.map +0 -1
  453. package/dist/cli/session-start/shared-options.d.ts +0 -103
  454. package/dist/cli/session-start/shared-options.js +0 -107
  455. package/dist/cli/session-start/shared-options.js.map +0 -1
  456. package/dist/cli/session-start/stale-base-check.d.ts +0 -46
  457. package/dist/cli/session-start/stale-base-check.js +0 -352
  458. package/dist/cli/session-start/stale-base-check.js.map +0 -1
  459. package/dist/cli/session-start/toolchain-parity.d.ts +0 -267
  460. package/dist/cli/session-start/toolchain-parity.js +0 -797
  461. package/dist/cli/session-start/toolchain-parity.js.map +0 -1
  462. package/dist/cli/smoke/assertions.d.ts +0 -46
  463. package/dist/cli/smoke/assertions.js +0 -170
  464. package/dist/cli/smoke/assertions.js.map +0 -1
  465. package/dist/cli/smoke/index.d.ts +0 -76
  466. package/dist/cli/smoke/index.js +0 -245
  467. package/dist/cli/smoke/index.js.map +0 -1
  468. package/dist/cli/smoke/runner.d.ts +0 -55
  469. package/dist/cli/smoke/runner.js +0 -134
  470. package/dist/cli/smoke/runner.js.map +0 -1
  471. package/dist/cli/smoke/stream-parser.d.ts +0 -65
  472. package/dist/cli/smoke/stream-parser.js +0 -115
  473. package/dist/cli/smoke/stream-parser.js.map +0 -1
  474. package/dist/cli/test-risk.d.ts +0 -26
  475. package/dist/cli/test-risk.js +0 -34
  476. package/dist/cli/test-risk.js.map +0 -1
  477. package/dist/io/display-path.d.ts +0 -11
  478. package/dist/io/display-path.js +0 -29
  479. package/dist/io/display-path.js.map +0 -1
  480. package/dist/io/duration.d.ts +0 -5
  481. package/dist/io/duration.js +0 -50
  482. package/dist/io/duration.js.map +0 -1
  483. package/dist/io/extract.d.ts +0 -79
  484. package/dist/io/extract.js +0 -226
  485. package/dist/io/extract.js.map +0 -1
  486. package/dist/io/ledger-record.d.ts +0 -83
  487. package/dist/io/ledger-record.js +0 -301
  488. package/dist/io/ledger-record.js.map +0 -1
  489. package/dist/io/read-json-dir-entries.d.ts +0 -36
  490. package/dist/io/read-json-dir-entries.js +0 -48
  491. package/dist/io/read-json-dir-entries.js.map +0 -1
  492. package/dist/io/safe-json-parse.d.ts +0 -5
  493. package/dist/io/safe-json-parse.js +0 -21
  494. package/dist/io/safe-json-parse.js.map +0 -1
  495. package/dist/policies/index.d.ts +0 -5
  496. package/dist/policies/index.js +0 -6
  497. package/dist/policies/index.js.map +0 -1
  498. package/dist/policies/ledger-client.d.ts +0 -113
  499. package/dist/policies/ledger-client.js +0 -500
  500. package/dist/policies/ledger-client.js.map +0 -1
  501. package/dist/policies/producers.d.ts +0 -12
  502. package/dist/policies/producers.js +0 -61
  503. package/dist/policies/producers.js.map +0 -1
  504. package/dist/policies/requires.d.ts +0 -75
  505. package/dist/policies/requires.js +0 -240
  506. package/dist/policies/requires.js.map +0 -1
  507. package/dist/policies/timestamp.d.ts +0 -14
  508. package/dist/policies/timestamp.js +0 -36
  509. package/dist/policies/timestamp.js.map +0 -1
  510. package/dist/policy-packs/builtin/permission-profiles.d.ts +0 -11
  511. package/dist/policy-packs/builtin/permission-profiles.js +0 -74
  512. package/dist/policy-packs/builtin/permission-profiles.js.map +0 -1
  513. package/dist/policy-packs/builtin/post-merge-gate-runtime.d.ts +0 -286
  514. package/dist/policy-packs/builtin/post-merge-gate-runtime.js +0 -397
  515. package/dist/policy-packs/builtin/post-merge-gate-runtime.js.map +0 -1
  516. package/dist/policy-packs/builtin/post-merge-gate.d.ts +0 -56
  517. package/dist/policy-packs/builtin/post-merge-gate.js +0 -347
  518. package/dist/policy-packs/builtin/post-merge-gate.js.map +0 -1
  519. package/dist/policy-packs/builtin/solution-acceptance-reconnect.d.ts +0 -50
  520. package/dist/policy-packs/builtin/solution-acceptance-reconnect.js +0 -151
  521. package/dist/policy-packs/builtin/solution-acceptance-reconnect.js.map +0 -1
  522. package/dist/policy-packs/builtin/solution-acceptance-runtime.d.ts +0 -323
  523. package/dist/policy-packs/builtin/solution-acceptance-runtime.js +0 -672
  524. package/dist/policy-packs/builtin/solution-acceptance-runtime.js.map +0 -1
  525. package/dist/policy-packs/builtin/solution-acceptance.d.ts +0 -45
  526. package/dist/policy-packs/builtin/solution-acceptance.js +0 -226
  527. package/dist/policy-packs/builtin/solution-acceptance.js.map +0 -1
  528. package/dist/policy-packs/builtin/understanding-before-execution/active-claim.d.ts +0 -25
  529. package/dist/policy-packs/builtin/understanding-before-execution/active-claim.js +0 -94
  530. package/dist/policy-packs/builtin/understanding-before-execution/active-claim.js.map +0 -1
  531. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.d.ts +0 -35
  532. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js +0 -86
  533. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js.map +0 -1
  534. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.d.ts +0 -210
  535. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js +0 -361
  536. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js.map +0 -1
  537. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.d.ts +0 -304
  538. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js +0 -734
  539. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js.map +0 -1
  540. package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.d.ts +0 -36
  541. package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.js +0 -73
  542. package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.js.map +0 -1
  543. package/dist/policy-packs/builtin/understanding-before-execution/index.d.ts +0 -19
  544. package/dist/policy-packs/builtin/understanding-before-execution/index.js +0 -83
  545. package/dist/policy-packs/builtin/understanding-before-execution/index.js.map +0 -1
  546. package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.d.ts +0 -135
  547. package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.js +0 -618
  548. package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.js.map +0 -1
  549. package/dist/policy-packs/builtin/understanding-before-execution/ledger.d.ts +0 -25
  550. package/dist/policy-packs/builtin/understanding-before-execution/ledger.js +0 -56
  551. package/dist/policy-packs/builtin/understanding-before-execution/ledger.js.map +0 -1
  552. package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.d.ts +0 -20
  553. package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.js +0 -93
  554. package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.js.map +0 -1
  555. package/dist/policy-packs/builtin/understanding-before-execution/markers.d.ts +0 -126
  556. package/dist/policy-packs/builtin/understanding-before-execution/markers.js +0 -245
  557. package/dist/policy-packs/builtin/understanding-before-execution/markers.js.map +0 -1
  558. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.d.ts +0 -29
  559. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js +0 -82
  560. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js.map +0 -1
  561. package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.d.ts +0 -71
  562. package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js +0 -175
  563. package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js.map +0 -1
  564. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.d.ts +0 -620
  565. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js +0 -1047
  566. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js.map +0 -1
  567. package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.d.ts +0 -128
  568. package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js +0 -213
  569. package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js.map +0 -1
  570. package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.d.ts +0 -129
  571. package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.js +0 -166
  572. package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.js.map +0 -1
  573. package/dist/policy-packs/builtin/understanding-before-execution/task-markers.d.ts +0 -164
  574. package/dist/policy-packs/builtin/understanding-before-execution/task-markers.js +0 -275
  575. package/dist/policy-packs/builtin/understanding-before-execution/task-markers.js.map +0 -1
  576. package/dist/policy-packs/builtin/understanding-before-execution-runtime.d.ts +0 -1
  577. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js +0 -10
  578. package/dist/policy-packs/builtin/understanding-before-execution-runtime.js.map +0 -1
  579. package/dist/policy-packs/builtin/understanding-before-execution.d.ts +0 -526
  580. package/dist/policy-packs/builtin/understanding-before-execution.js +0 -1074
  581. package/dist/policy-packs/builtin/understanding-before-execution.js.map +0 -1
  582. package/dist/policy-packs/permission-translator.d.ts +0 -9
  583. package/dist/policy-packs/permission-translator.js +0 -76
  584. package/dist/policy-packs/permission-translator.js.map +0 -1
  585. package/dist/runtime/action-envelope.d.ts +0 -64
  586. package/dist/runtime/action-envelope.js +0 -46
  587. package/dist/runtime/action-envelope.js.map +0 -1
  588. package/dist/runtime/approval-signing.d.ts +0 -111
  589. package/dist/runtime/approval-signing.js +0 -384
  590. package/dist/runtime/approval-signing.js.map +0 -1
  591. package/dist/runtime/bash-match-facts.d.ts +0 -60
  592. package/dist/runtime/bash-match-facts.js +0 -196
  593. package/dist/runtime/bash-match-facts.js.map +0 -1
  594. package/dist/runtime/bash-match-registry.d.ts +0 -112
  595. package/dist/runtime/bash-match-registry.js +0 -406
  596. package/dist/runtime/bash-match-registry.js.map +0 -1
  597. package/dist/runtime/bash-prefix-parse.d.ts +0 -31
  598. package/dist/runtime/bash-prefix-parse.js +0 -576
  599. package/dist/runtime/bash-prefix-parse.js.map +0 -1
  600. package/dist/runtime/command-normalize.d.ts +0 -658
  601. package/dist/runtime/command-normalize.js +0 -2410
  602. package/dist/runtime/command-normalize.js.map +0 -1
  603. package/dist/runtime/deletion-target-resolve.d.ts +0 -28
  604. package/dist/runtime/deletion-target-resolve.js +0 -1078
  605. package/dist/runtime/deletion-target-resolve.js.map +0 -1
  606. package/dist/runtime/destructive-shell-floor.d.ts +0 -19
  607. package/dist/runtime/destructive-shell-floor.js +0 -611
  608. package/dist/runtime/destructive-shell-floor.js.map +0 -1
  609. package/dist/runtime/environment-resolver.d.ts +0 -36
  610. package/dist/runtime/environment-resolver.js +0 -138
  611. package/dist/runtime/environment-resolver.js.map +0 -1
  612. package/dist/runtime/git-context.d.ts +0 -201
  613. package/dist/runtime/git-context.js +0 -422
  614. package/dist/runtime/git-context.js.map +0 -1
  615. package/dist/runtime/index.d.ts +0 -12
  616. package/dist/runtime/index.js +0 -13
  617. package/dist/runtime/index.js.map +0 -1
  618. package/dist/runtime/intercept.d.ts +0 -494
  619. package/dist/runtime/intercept.js +0 -1313
  620. package/dist/runtime/intercept.js.map +0 -1
  621. package/dist/runtime/kube-context.d.ts +0 -16
  622. package/dist/runtime/kube-context.js +0 -63
  623. package/dist/runtime/kube-context.js.map +0 -1
  624. package/dist/runtime/kubectl-target-parse.d.ts +0 -31
  625. package/dist/runtime/kubectl-target-parse.js +0 -249
  626. package/dist/runtime/kubectl-target-parse.js.map +0 -1
  627. package/dist/runtime/ledger-add.d.ts +0 -16
  628. package/dist/runtime/ledger-add.js +0 -150
  629. package/dist/runtime/ledger-add.js.map +0 -1
  630. package/dist/runtime/ledger-writer.d.ts +0 -27
  631. package/dist/runtime/ledger-writer.js +0 -46
  632. package/dist/runtime/ledger-writer.js.map +0 -1
  633. package/dist/runtime/pause-sentinel.d.ts +0 -60
  634. package/dist/runtime/pause-sentinel.js +0 -156
  635. package/dist/runtime/pause-sentinel.js.map +0 -1
  636. package/dist/runtime/pending-approval.d.ts +0 -23
  637. package/dist/runtime/pending-approval.js +0 -67
  638. package/dist/runtime/pending-approval.js.map +0 -1
  639. package/dist/runtime/read-only-bash.d.ts +0 -141
  640. package/dist/runtime/read-only-bash.js +0 -2204
  641. package/dist/runtime/read-only-bash.js.map +0 -1
  642. package/dist/runtime/recovery-git-commit.d.ts +0 -22
  643. package/dist/runtime/recovery-git-commit.js +0 -284
  644. package/dist/runtime/recovery-git-commit.js.map +0 -1
  645. package/dist/runtime/reject-malformed-session-id.d.ts +0 -8
  646. package/dist/runtime/reject-malformed-session-id.js +0 -16
  647. package/dist/runtime/reject-malformed-session-id.js.map +0 -1
  648. package/dist/runtime/risk-classifier.d.ts +0 -38
  649. package/dist/runtime/risk-classifier.js +0 -311
  650. package/dist/runtime/risk-classifier.js.map +0 -1
  651. package/dist/runtime/session-id.d.ts +0 -113
  652. package/dist/runtime/session-id.js +0 -193
  653. package/dist/runtime/session-id.js.map +0 -1
  654. package/dist/runtime/shell-word.d.ts +0 -62
  655. package/dist/runtime/shell-word.js +0 -410
  656. package/dist/runtime/shell-word.js.map +0 -1
  657. package/dist/runtime/task-providers/agent-tasks.d.ts +0 -103
  658. package/dist/runtime/task-providers/agent-tasks.js +0 -245
  659. package/dist/runtime/task-providers/agent-tasks.js.map +0 -1
  660. package/dist/runtime/when-eval.d.ts +0 -62
  661. package/dist/runtime/when-eval.js +0 -212
  662. package/dist/runtime/when-eval.js.map +0 -1
  663. package/dist/runtime/workflow-policies.d.ts +0 -207
  664. package/dist/runtime/workflow-policies.js +0 -596
  665. package/dist/runtime/workflow-policies.js.map +0 -1
  666. package/dist/schema/audit.d.ts +0 -71
  667. package/dist/schema/audit.js +0 -32
  668. package/dist/schema/audit.js.map +0 -1
  669. package/dist/schema/doctor.d.ts +0 -25
  670. package/dist/schema/doctor.js +0 -23
  671. package/dist/schema/doctor.js.map +0 -1
  672. package/dist/schema/environments.d.ts +0 -215
  673. package/dist/schema/environments.js +0 -101
  674. package/dist/schema/environments.js.map +0 -1
  675. package/dist/schema/extract.d.ts +0 -9
  676. package/dist/schema/extract.js +0 -86
  677. package/dist/schema/extract.js.map +0 -1
  678. package/dist/schema/permission-profiles.d.ts +0 -2292
  679. package/dist/schema/permission-profiles.js +0 -60
  680. package/dist/schema/permission-profiles.js.map +0 -1
  681. package/dist/schema/policies.d.ts +0 -974
  682. package/dist/schema/policies.js +0 -298
  683. package/dist/schema/policies.js.map +0 -1
  684. package/dist/schema/requires.d.ts +0 -131
  685. package/dist/schema/requires.js +0 -88
  686. package/dist/schema/requires.js.map +0 -1
  687. package/dist/schema/risk.d.ts +0 -144
  688. package/dist/schema/risk.js +0 -194
  689. package/dist/schema/risk.js.map +0 -1
  690. package/dist/schema/session-start-preflight.d.ts +0 -10
  691. package/dist/schema/session-start-preflight.js +0 -106
  692. package/dist/schema/session-start-preflight.js.map +0 -1
  693. package/dist/schema/stale-base-check.d.ts +0 -18
  694. package/dist/schema/stale-base-check.js +0 -37
  695. package/dist/schema/stale-base-check.js.map +0 -1
  696. package/dist/schema/toolchain-parity.d.ts +0 -21
  697. package/dist/schema/toolchain-parity.js +0 -48
  698. package/dist/schema/toolchain-parity.js.map +0 -1
  699. package/dist/schema/workflows.d.ts +0 -519
  700. package/dist/schema/workflows.js +0 -81
  701. package/dist/schema/workflows.js.map +0 -1
  702. package/scripts/runtime-reality-docker-probe.mjs +0 -71
@@ -1,1074 +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.
412
- const DEFAULT_EXPIRE_ON_TOOL_MATCH = DEFAULT_BOUNDARY_TOOL_NAMES;
413
- const POST_TOOL_USE_COMMAND_CLAUDE = "harness pack hook post-tool-use";
414
- // Slice 2 of the subagent-gate work (docs/decisions/2026-08-27-ug-auto-
415
- // mode-approval.md "TTL, cwd, and subagents"): Claude-only for now (an
416
- // Agent-tool subagent is a Claude Code concept; Codex has no equivalent
417
- // event to emit these against). Always emitted alongside the PreToolUse
418
- // blocker, independent of `approval_lifecycle.mode` — an in-flight
419
- // record is a copy of whatever approval the parent holds at spawn time,
420
- // not itself governed by the marker-expiry opt-out.
421
- const SUBAGENT_START_COMMAND = "harness pack hook subagent-start";
422
- const SUBAGENT_STOP_COMMAND = "harness pack hook subagent-stop";
423
- // Task cf4cdc93 (Codex parity gap #3): unlike stop/pre-tool-use/
424
- // post-tool-use, the active-claim tracker and stay-in-scope reminder
425
- // need NO runtime-specific CLI verb — both hook bodies only ever
426
- // inspect the generic `tool_name` / `tool_input` fields already common
427
- // to Claude's and Codex's PostToolUse envelope (no session_id, no
428
- // shell-command extraction, no Codex-only synonym). One shared command
429
- // constant per hook is therefore reused verbatim on both runtimes below
430
- // instead of a `codex-track-active-claim` / `codex-stay-in-scope`
431
- // sibling binary — avoids reintroducing the exact Claude/Codex drift
432
- // class task e7c2ec3c fixed on the PreToolUse side.
433
- const TRACK_ACTIVE_CLAIM_COMMAND = "harness pack hook track-active-claim";
434
- // Hardcoded matcher for the v2 active-claim tracker (harness/494fd1e5).
435
- // Agent-tasks specific; operators on other tasking systems can ignore
436
- // this hook (the matcher won't fire for their tools). A config-driven
437
- // extension can land later if a second tasking system asks for it.
438
- const TRACK_ACTIVE_CLAIM_MATCH = `^(?:${ACTIVE_CLAIM_TOOL_NAMES.join("|")})$`;
439
- // Codex sibling of TRACK_ACTIVE_CLAIM_MATCH above (task cf4cdc93): a
440
- // bare, unescaped `|`-joined list, NOT the anchored `^(?:...)$` form —
441
- // same rationale as `codexPostToolUseMatchPattern`'s own doc comment
442
- // (task a1348c89 review finding): `expandCodexHookMatchPattern`'s
443
- // "simple token" guard (`isSimpleToolPatternToken`, generate-codex-config.ts)
444
- // only alias-expands a match string whose tokens are ALL "simple"; the
445
- // anchor characters `^`, `(`, `?` trip that guard and the anchored form
446
- // is passed through UNCHANGED at TOML-emit time, so a Codex session
447
- // sending a dotted/underscore-server MCP tool-name variant would never
448
- // even reach the hook. This bare form lets the emitted `config.toml`
449
- // matcher — and therefore Codex's own dispatcher — recognize those
450
- // variants, exactly like `PRE_TOOL_USE_MATCH_CODEX` already does.
451
- const TRACK_ACTIVE_CLAIM_MATCH_CODEX = ACTIVE_CLAIM_TOOL_NAMES.join("|");
452
- const STAY_IN_SCOPE_COMMAND = "harness pack hook stay-in-scope";
453
- function escapeMatcherLiteral(value) {
454
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
455
- }
456
- // Bash tool name used to widen the PostToolUse matcher when
457
- // `expire_on_bash_match` is configured (task bea04a03). Matches the
458
- // single entry of `DEFAULT_BASH_TOOL_NAMES` in
459
- // understanding-before-execution-runtime.ts.
460
- const BASH_TOOL_NAME_CLAUDE = "Bash";
461
- // Codex shell-tool aliases used for the same widening on the Codex
462
- // matcher builder below. Derived from the canonical `SHELL_ALIASES` in
463
- // `src/runtime/tool-name-aliases.ts` (task bea04a03 review finding) —
464
- // `policy-packs/` IS allowed to depend on `runtime/` (layering rule,
465
- // `.dependency-cruiser.cjs`; the sibling understanding-before-execution-runtime.ts
466
- // already imports from there), so this is a shared source of truth
467
- // rather than a third hand-maintained copy. `CODEX_SHELL_TOOLS` in
468
- // `src/cli/pack/hook-codex-pre-tool-use.ts` stays a separate literal:
469
- // `policy-packs/` may not depend on `cli/` (same layering rule), so that
470
- // one cannot be unified with this without a boundary violation.
471
- const BASH_TOOL_NAMES_CODEX = SHELL_ALIASES;
472
- /**
473
- * Compose the PostToolUse `match` regex from the configured tool list,
474
- * widened with the Bash tool name when `includeBash` is true (task
475
- * bea04a03: `approval_lifecycle.expire_on_bash_match` carries at least
476
- * one pattern). Before this widening, `expire_on_tool_match` alone
477
- * gated the matcher, so a real `Bash` call never reached the hook at
478
- * all — `matchPostToolUseBoundary`'s bash-regex check (which DOES
479
- * correctly evaluate `expire_on_bash_match` once invoked) was
480
- * unreachable in practice. Adding "Bash" here only ROUTES the call to
481
- * the hook; it does not add "Bash" to `expire_on_tool_match`'s own
482
- * semantics — the hook body still classifies a matched Bash call as a
483
- * bash-regex match (`toolNameMatched: false`), never a tool-name match.
484
- * Each tool name is regex-escaped and joined with `|` so settings.json
485
- * fires the hook only when the just-completed tool is one we care
486
- * about. When the operator declared `approval_lifecycle: { mode: session }`
487
- * (or cleared both lists), no PostToolUse hook is emitted at all (caller
488
- * filters).
489
- */
490
- function postToolUseMatchPattern(tools, includeBash) {
491
- const widened = includeBash && !tools.includes(BASH_TOOL_NAME_CLAUDE)
492
- ? [...tools, BASH_TOOL_NAME_CLAUDE]
493
- : tools;
494
- const escaped = widened.map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
495
- return `^(?:${escaped.join("|")})$`;
496
- }
497
- /**
498
- * Compose the CODEX PostToolUse `match` field — deliberately NOT
499
- * `postToolUseMatchPattern` above (review finding on task a1348c89,
500
- * verified via a direct probe of `expandCodexHookMatchPattern`). The
501
- * Claude builder anchors its output in `^(?:...)$` and regex-escapes
502
- * every tool name; `expandCodexHookMatchPattern` in
503
- * `generate-codex-config.ts` only alias-expands a match string whose
504
- * `|`-split tokens are ALL "simple" (`isSimpleToolPatternToken`,
505
- * `/^[A-Za-z0-9_.:-]+$/`) — the anchor characters `^`, `(`, `?` on the
506
- * first/last token trip that guard, so an anchored match is passed
507
- * through UNCHANGED at emit time. Concretely: a Codex session sending
508
- * the dotted `mcp__agent-tasks__.task_finish` or an underscore-server
509
- * `mcp__agent_tasks__task_finish` variant would never even reach the
510
- * hook — Codex's own dispatcher tests `tool_name` against the emitted
511
- * `matcher`, and the anchored form only contains the canonical forms.
512
- * (`matchPostToolUseBoundary`'s alias-aware body-side fix, same task,
513
- * only helps once the hook is actually invoked — it cannot compensate
514
- * for a dispatcher that never calls it.)
515
- *
516
- * This builder instead emits a BARE, unescaped `|`-joined list — same
517
- * shape as the existing `PRE_TOOL_USE_MATCH_CODEX` constant above —
518
- * so every token stays "simple" and `expandCodexHookMatchPattern`
519
- * expands each MCP tool name into its full alias set (server
520
- * hyphen/underscore swap, the `mcp__server__.tool` dotted form) at
521
- * `harness apply --runtime codex` time, exactly like the Codex
522
- * PreToolUse blocker's own matcher already does. No anchoring is
523
- * needed here: Codex's own hook dispatch (like the sibling PreToolUse
524
- * matcher) is unanchored substring-style matching already, and this
525
- * keeps the Codex and Claude builders independently tunable rather
526
- * than smuggling a Codex-only branch into the shared Claude helper.
527
- *
528
- * Like the Claude builder above, `includeBash` (task bea04a03) widens
529
- * the emitted list with the Codex shell-tool aliases
530
- * (`BASH_TOOL_NAMES_CODEX`: Bash/shell/exec_command/functions.exec_command)
531
- * when `approval_lifecycle.expire_on_bash_match` carries at least one
532
- * pattern, so a real Codex shell call is actually routed to the hook.
533
- * The aliases stay simple tokens (no anchors), so they still pass
534
- * through `expandCodexHookMatchPattern` unchanged — they have no MCP-style
535
- * variants to expand, but they must not trip the "simple token" guard
536
- * either.
537
- */
538
- function codexPostToolUseMatchPattern(tools, includeBash) {
539
- const widened = includeBash
540
- ? [...tools, ...BASH_TOOL_NAMES_CODEX.filter((t) => !tools.includes(t))]
541
- : tools;
542
- return widened.join("|");
543
- }
544
- function resolveExpireOnToolMatch(pack) {
545
- const raw = pack.config["approval_lifecycle"];
546
- // No config block at all: default-on with the agent-tasks tool list.
547
- // This is the intentional behaviour change in v0.18 — operators who
548
- // want the legacy "one approval per session" UX opt out via
549
- // `approval_lifecycle: { mode: session }`.
550
- if (raw === undefined || raw === null) {
551
- return { tools: [...DEFAULT_EXPIRE_ON_TOOL_MATCH], emitHook: true };
552
- }
553
- if (typeof raw !== "object" || Array.isArray(raw)) {
554
- return { tools: [...DEFAULT_EXPIRE_ON_TOOL_MATCH], emitHook: true };
555
- }
556
- const obj = raw;
557
- if (obj["mode"] === "session") {
558
- return { tools: [], emitHook: false };
559
- }
560
- const list = obj["expire_on_tool_match"];
561
- if (Array.isArray(list)) {
562
- const tools = list.filter((v) => typeof v === "string" && v.length > 0);
563
- return { tools, emitHook: tools.length > 0 };
564
- }
565
- return { tools: [...DEFAULT_EXPIRE_ON_TOOL_MATCH], emitHook: true };
566
- }
567
- /**
568
- * Whether `approval_lifecycle.expire_on_bash_match` carries at least one
569
- * non-empty pattern (task bea04a03). Used ONLY to decide whether the
570
- * emitted PostToolUse matcher should be widened to route Bash (Claude) /
571
- * shell-alias (Codex) calls to the hook at all — the actual regex
572
- * compiling and matching against `tool_input.command` happens downstream
573
- * in `parseApprovalLifecycle` / `matchPostToolUseBoundary`
574
- * (understanding-before-execution-runtime.ts). An entry that turns out to
575
- * be an invalid regex is silently dropped there with a warning; that is
576
- * harmless here — the matcher merely routes the call to the hook, and a
577
- * hook invocation that finds no live bash-regex match just no-ops
578
- * (mirrors the existing `noBoundariesConfigured` / `boundary.matched`
579
- * no-op paths in hook-post-tool-use.ts / hook-codex-post-tool-use.ts).
580
- *
581
- * Mirrors `resolveExpireOnToolMatch`'s traversal of the same config
582
- * block (undefined/non-object/`mode: session` all resolve to "not
583
- * configured"), but returns a bare boolean since the matcher builders
584
- * only need presence, not the pattern strings themselves.
585
- */
586
- function resolveExpireOnBashMatchConfigured(pack) {
587
- const raw = pack.config["approval_lifecycle"];
588
- if (raw === undefined || raw === null)
589
- return false;
590
- if (typeof raw !== "object" || Array.isArray(raw))
591
- return false;
592
- const obj = raw;
593
- if (obj["mode"] === "session")
594
- return false;
595
- const list = obj["expire_on_bash_match"];
596
- if (!Array.isArray(list))
597
- return false;
598
- return list.some((v) => typeof v === "string" && v.length > 0);
599
- }
600
- /**
601
- * Shared PostToolUse boundary resolution for BOTH the Claude and Codex
602
- * `buildHooks` branches (task bea04a03): combines
603
- * `resolveExpireOnToolMatch` and `resolveExpireOnBashMatchConfigured`
604
- * into the one decision each branch's IIFE needs. Extracted specifically
605
- * to avoid re-introducing the exact clone-avoidance problem
606
- * `understanding-before-execution-runtime.ts`'s `matchPostToolUseBoundary`
607
- * / `applyPostToolUseExpiry` / `describePostToolUseExpiry` extraction
608
- * already solved once for the two runtimes' hook CLIs (`check:duplication`
609
- * flagged the inline duplicate when this task first wired the two nearly-
610
- * identical IIFEs by hand).
611
- */
612
- function resolvePostToolUseBoundaries(pack) {
613
- const { tools, emitHook: toolsEmitHook } = resolveExpireOnToolMatch(pack);
614
- const bashConfigured = resolveExpireOnBashMatchConfigured(pack);
615
- return { tools, bashConfigured, emit: toolsEmitHook || bashConfigured };
616
- }
617
- function buildHooks(runtime, pack, mode, opts = {}) {
618
- // Per-mode hook commands are otherwise identical: the mode reaches the
619
- // package-owned Claude bins (BIN_USER_PROMPT_SUBMIT_CLAUDE,
620
- // BIN_STOP_CLAUDE) via the `UNDERSTANDING_GATE_MODE` env-var prefix
621
- // below (`wrapMode`), resolved by `resolveModeFromConfig` (config.mode >
622
- // DEFAULT_MODE — this is the GENERATION path, it does NOT read the env
623
- // var; see {@link MODE_ENV}'s doc comment for why) and coerced through
624
- // `toPackageMode` for the package's two-value enum. What changes per
625
- // mode beyond that is the instructions.md content + the actual injected
626
- // prompt (owned by the npm package, itself keyed off this same env var
627
- // at ITS OWN, later, live-invocation time).
628
- //
629
- // When `opts.reportsDir` is set (the apply path), each command is ALSO
630
- // prefixed with `UNDERSTANDING_GATE_REPORT_DIR=<absolute>` so all hooks
631
- // — including the standalone-package Stop bin which honors the same
632
- // env var — write/read the same directory.
633
- const wrap = (cmd) => prefixCommandWithReportsDir(cmd, opts.reportsDir);
634
- // When `opts.pauseFile` is set (the apply path), the Claude
635
- // UserPromptSubmit command ALSO gets prefixed with
636
- // `UNDERSTANDING_GATE_PAUSE_FILE=<absolute>` (see {@link PAUSE_FILE_ENV}'s
637
- // doc comment for why only this one hook needs it: the npm-backed bin
638
- // runs outside harness's own runtime and cannot resolve `generatedDir`
639
- // the way harness's own hooks do).
640
- const wrapPause = (cmd) => prefixCommandWithPauseFile(cmd, opts.pauseFile);
641
- // Task 5d73d78d review MEDIUM-7: omit the prefix entirely when the
642
- // resolved mode already coerces to the package's OWN default
643
- // (`fast_confirm`). Baking `UNDERSTANDING_GATE_MODE=fast_confirm`
644
- // unconditionally (as this did before this fix) made the package's
645
- // in-prompt `/grill` / "grill me" escalation marker permanently dead:
646
- // `pickMode()` (package `src/mode.ts`) checks its env var FIRST and
647
- // returns immediately on a match, never reaching the marker check —
648
- // so an operator on a `fast_confirm`-effective host could never
649
- // escalate a single prompt to `grill_me` via the marker, even though
650
- // the package ships exactly that mechanism. Leaving the command
651
- // unprefixed changes nothing about the EFFECTIVE default (the
652
- // package's own fallback is already `fast_confirm`) while restoring
653
- // the marker's liveness; a `grill_me`/`strict`-resolved mode still
654
- // gets the unconditional prefix, same as before.
655
- const wrapMode = (cmd) => {
656
- const pkgMode = toPackageMode(mode);
657
- if (pkgMode === "fast_confirm")
658
- return cmd;
659
- return `${MODE_ENV}=${shellQuoteSingle(pkgMode)} ${cmd}`;
660
- };
661
- if (runtime === "codex") {
662
- return [
663
- {
664
- name: `${HOOK_NAME_PREFIX}:codex:user-prompt-submit`,
665
- event: "UserPromptSubmit",
666
- command: COMMAND_USER_PROMPT_SUBMIT_CODEX,
667
- blocking: false,
668
- budget_ms: 5000,
669
- description: "Codex adapter: inject the Understanding-Gate instruction template before the agent acts. Phase 6 #6.",
670
- },
671
- {
672
- name: `${HOOK_NAME_PREFIX}:codex:stop`,
673
- event: "Stop",
674
- command: wrap(COMMAND_STOP_CODEX),
675
- blocking: false,
676
- budget_ms: 5000,
677
- description: "Codex adapter: capture the agent's Understanding Report into .understanding-gate/reports/ as approvalStatus:pending. Phase 6 #6 follow-up.",
678
- },
679
- {
680
- name: `${HOOK_NAME_PREFIX}:codex:pre-tool-use`,
681
- event: "PreToolUse",
682
- match: PRE_TOOL_USE_MATCH_CODEX,
683
- command: wrap(COMMAND_PRE_TOOL_USE_CODEX),
684
- blocking: "hard",
685
- // 15000 (task 7bf47554): `checkLedger` (src/cli/pack/hook-codex-
686
- // pre-tool-use.ts) runs an unconditional, ledger-consulting audit
687
- // probe on every invocation — even when the filesystem marker
688
- // already resolved the decision — bounded by the grounding-mcp
689
- // server's own `health.timeout_ms` (default 5000ms), the same
690
- // number budget_ms=5000 used for the outer Claude/Codex
691
- // kill-timeout, leaving no margin against a merely-slow (not
692
- // dead) ledger. See src/cli/init/templates.ts's budget note above
693
- // require-review-evidence for the full fail-open mechanism this
694
- // guards against.
695
- budget_ms: 15000,
696
- 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.",
697
- },
698
- // PostToolUse marker-expiry (task a1348c89, widened by task
699
- // bea04a03). Same boundary-tool list as the Claude hook below
700
- // (resolveExpireOnToolMatch) so Codex expires on the identical
701
- // configured set (agent-tasks task_finish / task_abandon /
702
- // task_merge / pull_requests_merge / tasks_transition in the
703
- // scaffolds), but a DIFFERENT
704
- // `match` builder (`codexPostToolUseMatchPattern`, not
705
- // `postToolUseMatchPattern`): see that function's own doc comment
706
- // for why the Claude builder's anchored regex form silently
707
- // defeats the Codex generator's MCP tool-name alias expansion
708
- // (review finding on task a1348c89).
709
- // `match` is ALSO widened with the Codex shell-tool aliases
710
- // (Bash/shell/exec_command/functions.exec_command) whenever
711
- // `approval_lifecycle.expire_on_bash_match` carries at least one
712
- // pattern (task bea04a03): before this, `match` was built ONLY
713
- // from `expire_on_tool_match`, so a real shell call never reached
714
- // the hook body at all on EITHER runtime, even though
715
- // `matchPostToolUseBoundary`'s bash-regex check correctly
716
- // evaluates `expire_on_bash_match` once invoked. The widened
717
- // aliases are NEVER added to `expire_on_tool_match` itself — the
718
- // hook body still classifies a matched shell call as a bash-regex
719
- // match, not a tool-name match, via `CODEX_SHELL_TOOLS.has(toolName)`
720
- // in the caller (hook-codex-post-tool-use.ts).
721
- ...(() => {
722
- const { tools, bashConfigured, emit } = resolvePostToolUseBoundaries(pack);
723
- if (!emit)
724
- return [];
725
- const hook = {
726
- name: `${HOOK_NAME_PREFIX}:codex:post-tool-use`,
727
- event: "PostToolUse",
728
- match: codexPostToolUseMatchPattern(tools, bashConfigured),
729
- command: wrap(COMMAND_POST_TOOL_USE_CODEX),
730
- blocking: false,
731
- budget_ms: 2000,
732
- 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.",
733
- };
734
- return [hook];
735
- })(),
736
- // Active-claim tracker (harness/494fd1e5), Codex parity task
737
- // cf4cdc93 (parity-gaps doc gap #3). Always emitted alongside the
738
- // pack, mirroring the Claude sibling below — the matcher won't
739
- // fire for operators on non-agent-tasks tasking systems, so the
740
- // file simply never appears for them. Same command as Claude
741
- // (see TRACK_ACTIVE_CLAIM_COMMAND's doc comment above): the hook
742
- // body needs no Codex-specific handling.
743
- {
744
- name: `${HOOK_NAME_PREFIX}:codex:track-active-claim`,
745
- event: "PostToolUse",
746
- match: TRACK_ACTIVE_CLAIM_MATCH_CODEX,
747
- command: TRACK_ACTIVE_CLAIM_COMMAND,
748
- blocking: false,
749
- budget_ms: 2000,
750
- 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).",
751
- },
752
- ...(() => {
753
- const stayInScope = resolveStayInScopeConfig(pack.config["stay_in_scope"]);
754
- if (stayInScope === null)
755
- return [];
756
- return [{
757
- name: `${HOOK_NAME_PREFIX}:codex:stay-in-scope`,
758
- event: "PostToolUse",
759
- match: stayInScope.tools.join("|"),
760
- command: STAY_IN_SCOPE_COMMAND,
761
- blocking: false,
762
- budget_ms: 2000,
763
- description: "Codex adapter: emit the configured soft stay-in-scope reminder and audit row.",
764
- }];
765
- })(),
766
- ];
767
- }
768
- // `min_version` floor on the npm-backed bins: 0.4.0 ships the
769
- // required "Prior Art" 10th section of the Understanding Report
770
- // (agent-grounding PR #85, harness task 798d7173). Operators below
771
- // this floor would silently miss the section because the Stop-capture
772
- // parser doesn't yet enforce it. The prior floor was 0.3.1 (first
773
- // release whose `understanding-gate --version` reported the actual
774
- // installed version rather than a stale literal; agent-grounding PRs
775
- // #80 + #81); 0.4.0 supersedes it. The PreToolUse blocker below is
776
- // the harness CLI itself, not an npm-backed bin, so it does not carry
777
- // a floor here.
778
- // 0.5.0 raises the floor again: the UserPromptSubmit hook now carries an
779
- // UNDERSTANDING_GATE_PAUSE_FILE prefix, and only 0.5.0 and later read that
780
- // variable. On an older gate the prefix is set but ignored, so the pause
781
- // wiring is silently inert; the floor makes `harness doctor` say so instead
782
- // of leaving the operator to discover it.
783
- const UG_MIN_VERSION = "0.5.0";
784
- const UG_VERSION_COMMAND = [
785
- "understanding-gate",
786
- "--version",
787
- ];
788
- return [
789
- {
790
- name: `${HOOK_NAME_PREFIX}:user-prompt-submit`,
791
- event: "UserPromptSubmit",
792
- command: wrapMode(wrapPause(BIN_USER_PROMPT_SUBMIT_CLAUDE)),
793
- blocking: false,
794
- budget_ms: 5000,
795
- min_version: UG_MIN_VERSION,
796
- version_command: UG_VERSION_COMMAND,
797
- description: "Inject the Understanding-Gate instruction template before the agent acts. Source: @lannguyensi/understanding-gate.",
798
- },
799
- {
800
- name: `${HOOK_NAME_PREFIX}:stop`,
801
- event: "Stop",
802
- command: wrapMode(wrap(BIN_STOP_CLAUDE)),
803
- blocking: false,
804
- budget_ms: 5000,
805
- min_version: UG_MIN_VERSION,
806
- version_command: UG_VERSION_COMMAND,
807
- description: "Capture the agent's Understanding Report into .understanding-gate/reports/. Source: @lannguyensi/understanding-gate.",
808
- },
809
- {
810
- name: `${HOOK_NAME_PREFIX}:pre-tool-use`,
811
- event: "PreToolUse",
812
- match: PRE_TOOL_USE_MATCH_CLAUDE,
813
- command: wrap(PRE_TOOL_USE_COMMAND_CLAUDE),
814
- blocking: "hard",
815
- // 15000: same rationale as the Codex sibling above (checkLedger in
816
- // src/cli/pack/hook-pre-tool-use.ts is the same unconditional
817
- // ledger-consulting audit probe, same health.timeout_ms bound).
818
- budget_ms: 15000,
819
- 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.",
820
- },
821
- // In-flight subagent records (slice 2, docs/decisions/2026-08-27-ug-
822
- // auto-mode-approval.md "TTL, cwd, and subagents"). An Agent-tool
823
- // subagent shares its parent's session_id but cannot itself call
824
- // `harness approve understanding`; SubagentStart copies whatever
825
- // approval the parent holds AT SPAWN TIME into a signed record the
826
- // subagent can present later even if the parent's own marker expires
827
- // mid-flight, and SubagentStop removes it when the subagent finishes.
828
- // Always emitted alongside the PreToolUse blocker above — never
829
- // gated behind `approval_lifecycle.mode` the way the marker-expiry
830
- // hook below is, since a record is a copy of authority, not itself
831
- // subject to that opt-out. Claude-only: the Agent tool (and its
832
- // SubagentStart/SubagentStop events) has no Codex equivalent.
833
- {
834
- name: `${HOOK_NAME_PREFIX}:subagent-start`,
835
- event: "SubagentStart",
836
- // Reads persisted reports (report-hash cross-check before minting the
837
- // record), so it carries the same reports-dir prefix as the other
838
- // report-reading hooks and agrees with where `harness approve` wrote.
839
- command: wrap(SUBAGENT_START_COMMAND),
840
- blocking: false,
841
- budget_ms: 2000,
842
- 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.",
843
- },
844
- {
845
- name: `${HOOK_NAME_PREFIX}:subagent-stop`,
846
- event: "SubagentStop",
847
- command: SUBAGENT_STOP_COMMAND,
848
- blocking: false,
849
- budget_ms: 2000,
850
- description: "Remove the in-flight record written for this subagent by subagent-start when it finishes.",
851
- },
852
- // PostToolUse marker-expiry hook (agent-tasks/d8ee60ca). Fires on the
853
- // configured task-boundary tools, and (task bea04a03) on a Bash call
854
- // when `approval_lifecycle.expire_on_bash_match` carries at least one
855
- // pattern, and deletes the approval marker so the next Edit / Write /
856
- // Bash forces a fresh Understanding Report. The runtime tool list is
857
- // the configured expire_on_tool_match (scaffolds: agent-tasks
858
- // task_finish / task_abandon / task_merge / pull_requests_merge /
859
- // tasks_transition); DEFAULT_BOUNDARY_TOOL_NAMES only shapes the
860
- // emitted matcher when no list is configured.
861
- // Operators on other task systems override the list via
862
- // config.approval_lifecycle.expire_on_tool_match; setting
863
- // `approval_lifecycle: { mode: session }` opts out entirely and
864
- // suppresses this hook from being emitted at all.
865
- //
866
- // Before task bea04a03, `match` was built ONLY from
867
- // `expire_on_tool_match`, so a real `Bash` call never invoked this
868
- // hook at all — `matchPostToolUseBoundary`'s bash-regex check (which
869
- // DOES correctly evaluate `expire_on_bash_match` once invoked)
870
- // was unreachable. Widening `match` to include "Bash" does not
871
- // change how the hook body classifies the match: a Bash call that
872
- // fires the hook is still evaluated as a bash-regex match
873
- // (`toolNameMatched: false`), never folded into
874
- // `expire_on_tool_match`'s own tool-name semantics.
875
- ...(() => {
876
- const { tools, bashConfigured, emit } = resolvePostToolUseBoundaries(pack);
877
- if (!emit)
878
- return [];
879
- const hook = {
880
- name: `${HOOK_NAME_PREFIX}:post-tool-use`,
881
- event: "PostToolUse",
882
- match: postToolUseMatchPattern(tools, bashConfigured),
883
- // Wrap with UNDERSTANDING_GATE_REPORT_DIR so the post-tool-use
884
- // hook resolves the same persisted-reports directory as the
885
- // pre-tool-use blocker; otherwise it can't expire the persisted
886
- // report alongside the marker (harness/1ee26e77 follow-up).
887
- command: wrap(POST_TOOL_USE_COMMAND_CLAUDE),
888
- blocking: false,
889
- budget_ms: 2000,
890
- 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.",
891
- };
892
- return [hook];
893
- })(),
894
- // Active-claim tracker (harness/494fd1e5). PostToolUse hook on
895
- // agent-tasks task_start / task_finish / task_abandon / task_merge
896
- // (task_merge added by task c86e3c4a: previously untracked here, so
897
- // a real task_merge tool call never dispatched to the hook at all).
898
- // Maintains a small file at <generatedDir>/active-claim so `harness
899
- // approve understanding` can auto-resolve the task id when --task is
900
- // absent. Always emitted alongside the pack — operators on other
901
- // tasking systems are unaffected (the matcher won't fire for
902
- // their tools), the file simply never appears.
903
- {
904
- name: `${HOOK_NAME_PREFIX}:track-active-claim`,
905
- event: "PostToolUse",
906
- match: TRACK_ACTIVE_CLAIM_MATCH,
907
- command: TRACK_ACTIVE_CLAIM_COMMAND,
908
- blocking: false,
909
- budget_ms: 2000,
910
- 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).",
911
- },
912
- ...(() => {
913
- const stayInScope = resolveStayInScopeConfig(pack.config["stay_in_scope"]);
914
- if (stayInScope === null)
915
- return [];
916
- return [{
917
- name: `${HOOK_NAME_PREFIX}:stay-in-scope`,
918
- event: "PostToolUse",
919
- match: `^(?:${stayInScope.tools.map(escapeMatcherLiteral).join("|")})$`,
920
- command: STAY_IN_SCOPE_COMMAND,
921
- blocking: false,
922
- budget_ms: 2000,
923
- description: "Emit the configured soft stay-in-scope reminder and audit row.",
924
- }];
925
- })(),
926
- ];
927
- }
928
- function modeFriction(mode) {
929
- switch (mode) {
930
- case "fast_confirm":
931
- return "low friction. The gate fires on prompts the classifier flags as execution-relevant. Brief Understanding Report; one-line approval.";
932
- case "grill_me":
933
- 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.";
934
- case "strict":
935
- return "high friction. The gate fires on every prompt. Report MUST include verificationPlan and outOfScope; requiresHumanApproval is forced to true.";
936
- }
937
- }
938
- function buildInstructions(pack, mode, runtime) {
939
- const description = pack.description?.trim() ?? "";
940
- const isCodex = runtime === "codex";
941
- const isOpencode = runtime === "opencode";
942
- const injectorCmd = isCodex
943
- ? COMMAND_USER_PROMPT_SUBMIT_CODEX
944
- : BIN_USER_PROMPT_SUBMIT_CLAUDE;
945
- const stopCmd = isCodex ? COMMAND_STOP_CODEX : BIN_STOP_CLAUDE;
946
- const blockerCmd = isCodex
947
- ? COMMAND_PRE_TOOL_USE_CODEX
948
- : PRE_TOOL_USE_COMMAND_CLAUDE;
949
- const blockerMatch = isCodex
950
- ? PRE_TOOL_USE_MATCH_CODEX
951
- : PRE_TOOL_USE_MATCH_CLAUDE;
952
- const settingsArtefact = isCodex
953
- ? "`harness.generated/codex/config.toml`"
954
- : "harness-managed `settings.json`";
955
- // HIGH-F1 (batch18 fix-round, task f34eb233): before this, opencode
956
- // fell through to the claude-code `else` branch above (buildHooks
957
- // does the same) and the "## Effect" text below claimed hooks were
958
- // wired into `settings.json` even though opencode has no declarative
959
- // hook/event field and `harness apply --runtime opencode` never
960
- // projects `hooks[]` into the generated opencode artefact (see
961
- // runtime.ts's header). Mirrors post-merge-gate.ts's "## Runtime"
962
- // UNSUPPORTED marker.
963
- const runtimeUnsupportedNote = isOpencode
964
- ? " (UNSUPPORTED — opencode has no declarative hook/event wiring; this pack's hooks are not projected into any opencode artefact)"
965
- : "";
966
- const wiringSentence = isOpencode
967
- ? "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."
968
- : `While this pack is enabled, hooks are wired into the ${settingsArtefact}:`;
969
- const stopBullet = `2. \`Stop\` capture (\`${stopCmd}\`): persists the emitted Understanding
970
- Report under \`.understanding-gate/reports/\` for audit and downstream
971
- approval consumption.
972
- `;
973
- const blockerOrdinal = "3";
974
- return `# Policy Pack: ${PACK_NAME}
975
-
976
- > Operator audit copy. The agent-facing prompt is injected at runtime by
977
- > the \`${injectorCmd}\` UserPromptSubmit hook; that text lives
978
- > in the \`@lannguyensi/understanding-gate\` package, not here. This file
979
- > records WHAT the pack is doing and HOW it is configured so that
980
- > \`harness diff --since-apply\` can flag operator-facing drift.
981
-
982
- ## Runtime
983
-
984
- ${runtime}${runtimeUnsupportedNote}
985
-
986
- ## Mode
987
-
988
- ${mode}
989
-
990
- ${modeFriction(mode)}
991
-
992
- ## Effect
993
-
994
- ${wiringSentence}
995
-
996
- 1. \`UserPromptSubmit\` injector (\`${injectorCmd}\`): inserts the
997
- Understanding-Gate instruction template into the agent's first response.
998
- ${stopBullet}${blockerOrdinal}. \`PreToolUse\` blocker (\`${blockerCmd}\`, blocking: hard)
999
- on \`${blockerMatch}\`: refuses the tool call until the operator has
1000
- approved the session's report. Opens ONLY on the HMAC-signed approval
1001
- marker under \`harness.generated/.approvals/\` written by
1002
- \`harness approve understanding\`; the persisted JSON report under
1003
- \`.understanding-gate/reports/\` and the evidence-ledger tag
1004
- (\`understanding-approved:\${SESSION_ID}\`) are audit evidence and
1005
- never open the gate on their own (task 7402301d).
1006
-
1007
- ## Approval
1008
-
1009
- The standalone blocker shipped in \`@lannguyensi/understanding-gate@>=0.2.0\`
1010
- checks the persisted JSON report's \`approvalStatus\`. Phase 6 #4 will
1011
- add a harness-side blocker that ALSO consults the evidence-ledger tag
1012
- \`understanding-approved:\${SESSION_ID}\` (canonical for harnessed
1013
- sessions), and \`harness approve understanding\` will round-trip both.
1014
- Until then, approval flows through the package's own CLI.
1015
-
1016
- ## Pack metadata
1017
- ${description ? `\n> ${description.replace(/\n/g, "\n> ")}\n` : ""}
1018
- - Source: \`builtin\`
1019
- - Pack: \`${PACK_NAME}\`
1020
- - Mode: \`${mode}\`
1021
- - Runtime: \`${runtime}\`
1022
-
1023
- ## See also
1024
-
1025
- - \`docs/policy-packs/understanding-before-execution.md\` (full reference)
1026
- - \`docs/ROADMAP.md\` Phase 6 sub-task decomposition
1027
- `;
1028
- }
1029
- function resolvePermissionProfile(pack) {
1030
- const raw = pack.config["permission_profile"];
1031
- if (raw === undefined)
1032
- return { permissions: null, warning: null };
1033
- if (typeof raw !== "string") {
1034
- return {
1035
- permissions: null,
1036
- warning: `policy_packs[${pack.name}].config.permission_profile: expected a string, got ${typeof raw}; skipping permission contribution.`,
1037
- };
1038
- }
1039
- if (!isKnownProfileName(raw)) {
1040
- return {
1041
- permissions: null,
1042
- warning: `policy_packs[${pack.name}].config.permission_profile: unrecognised profile ${JSON.stringify(raw)}. Allowed: ${KNOWN_PROFILE_NAMES.join(", ")}. Skipping permission contribution.`,
1043
- };
1044
- }
1045
- const profile = resolveProfile(raw);
1046
- if (!profile)
1047
- return { permissions: null, warning: null };
1048
- return { permissions: profileToSettingsPermissions(profile), warning: null };
1049
- }
1050
- export function resolve(pack, runtime = DEFAULT_RUNTIME, opts = {}) {
1051
- // GENERATION path (task 5d73d78d review HIGH-3): config-only, no env —
1052
- // see {@link MODE_ENV}'s doc comment for why apply-time artefacts must
1053
- // not depend on the live process environment.
1054
- const { mode, warning } = resolveModeFromConfig(pack);
1055
- const hooks = buildHooks(runtime, pack, mode, opts);
1056
- const instructionsContent = buildInstructions(pack, mode, runtime);
1057
- const files = [
1058
- {
1059
- relativePath: `policy-packs/${PACK_NAME}/instructions.md`,
1060
- content: instructionsContent,
1061
- },
1062
- ];
1063
- const warnings = [];
1064
- if (warning)
1065
- warnings.push(warning);
1066
- const profileResult = resolvePermissionProfile(pack);
1067
- if (profileResult.warning)
1068
- warnings.push(profileResult.warning);
1069
- const contribution = { hooks, files };
1070
- if (profileResult.permissions)
1071
- contribution.permissions = profileResult.permissions;
1072
- return { contribution, warnings };
1073
- }
1074
- //# sourceMappingURL=understanding-before-execution.js.map