@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,996 +0,0 @@
1
- // Phase 6 #4 — `harness approve understanding [--session <id>]` CLI verb.
2
- //
3
- // Round-trips both approval sources for the
4
- // `understanding-before-execution` pack:
5
- //
6
- // 1. Writes the evidence-ledger tag `understanding-approved:${SESSION_ID}`
7
- // via `grounding-mcp`'s `ledger_add` (best-effort: degraded ledger
8
- // surfaces as a warning, not a hard failure).
9
- // 2. Flips `approvalStatus: "approved"` on the latest persisted JSON
10
- // report under `.understanding-gate/reports/`. Atomic rewrite.
11
- //
12
- // Rationale for writing both: harnessed sessions consult the ledger as
13
- // canonical, but a solo `@lannguyensi/understanding-gate` user without
14
- // `grounding-mcp` wired only sees the persisted JSON. Round-tripping
15
- // both means switching between the two stacks doesn't lose history.
16
- import * as fs from "node:fs";
17
- import * as os from "node:os";
18
- import * as path from "node:path";
19
- import { atomicWriteFile } from "../../io/atomic-write.js";
20
- import { escapeForDisplay } from "../../io/display-path.js";
21
- import { approvedLedgerTagFor, defaultReportsDir, hashReportFile, listDirNamesBounded, listPersistedReportsBoundedWithSkips, MAX_HASHED_REPORT_BYTES, readReportFileBounded, readActiveClaim, selectReportForSession, TOLERANT_FALLBACK_MAX_AGE_MS, writeApprovalMarker, writeTaskApprovalMarker, } from "../../policy-packs/builtin/understanding-before-execution-runtime.js";
22
- import { PACK_NAME as UNDERSTANDING_PACK_NAME, resolveMode, toPackageMode, } from "../../policy-packs/builtin/understanding-before-execution.js";
23
- import { addLedgerFact } from "../../runtime/ledger-add.js";
24
- import { clearPendingApproval, resolveGeneratedDir, } from "../../runtime/pending-approval.js";
25
- import { resolveApprovalSessionId } from "../../runtime/session-id.js";
26
- import { EX_FAIL, HarnessExitError } from "../exit-codes.js";
27
- import { loadManifest, resolvePaths } from "../loader.js";
28
- import { describeSectionKey } from "../pack/understanding-report-schema-hint.js";
29
- import { persistStdinReport } from "./stdin-report.js";
30
- /**
31
- * Human-scale age for operator messages: minutes up to two hours,
32
- * hours up to two days, then days. A 17-day-old report should read
33
- * "17d", not "24893m" (review finding on harness-discovery C1).
34
- */
35
- function formatAge(ms) {
36
- const min = Math.round(ms / 60_000);
37
- if (Math.abs(min) < 120)
38
- return `${min}m`;
39
- const hours = Math.round(min / 60);
40
- if (Math.abs(hours) < 48)
41
- return `${hours}h`;
42
- return `${Math.round(hours / 24)}d`;
43
- }
44
- const DEFAULT_APPROVED_BY = "harness-approve-cli";
45
- function findGroundingMcp(manifest) {
46
- return manifest.tools.mcp.find((m) => m.name === "grounding-mcp") ?? null;
47
- }
48
- function expandHomePath(p) {
49
- if (p === "~")
50
- return process.env.HOME ?? os.homedir();
51
- if (p.startsWith("~/"))
52
- return path.join(process.env.HOME ?? os.homedir(), p.slice(2));
53
- return p;
54
- }
55
- /**
56
- * Load the manifest (best-effort, never throws) and resolve the
57
- * `understanding-before-execution` pack's declared config entry from it.
58
- * Extracted (agent-tasks 37ad0b05) so
59
- * `approveUnderstanding` and `issueDelegation` (`src/cli/delegate/index.ts`)
60
- * share one copy of this manifest-load-plus-pack-lookup shape instead of
61
- * each carrying its own byte-identical block
62
- * (`npm run check:duplication` was flagging the pair as a clone). Pure
63
- * extraction: the try/catch and the `declaredPack` fallback are unchanged
64
- * from what each call site did inline before this change.
65
- */
66
- export function loadDeclaredUnderstandingPack(opts) {
67
- let manifest = null;
68
- let manifestLoadError = null;
69
- try {
70
- manifest = opts.manifest ?? loadManifest(opts).manifest;
71
- }
72
- catch (err) {
73
- manifestLoadError = err instanceof Error ? err.message : String(err);
74
- }
75
- const declaredPack = manifest?.policy_packs.find((p) => p.name === UNDERSTANDING_PACK_NAME && p.enabled !== false) ?? { name: UNDERSTANDING_PACK_NAME, config: {} };
76
- return { manifest, manifestLoadError, declaredPack };
77
- }
78
- /**
79
- * Exported (agent-tasks 37ad0b05, Slice 3 of the auto-mode-approval ADR)
80
- * with an additive `source` parameter so `harness delegate` can reuse
81
- * this writer verbatim instead of re-implementing the same
82
- * findGroundingMcp + addLedgerFact shape a third time in this codebase
83
- * (branch-protection.ts already carries its own independent copy for
84
- * its own `harness-approve-branch-protection` source). `source` defaults
85
- * to this file's own literal, so `approveUnderstanding`'s own call below
86
- * (which does not pass it) is byte-identical to before this change: pure
87
- * additive parameterization, not a behaviour change for that caller.
88
- */
89
- export async function writeLedgerTag(manifest, sessionId, content, opts, source = "harness-approve-understanding") {
90
- if (opts.ledgerAdd)
91
- return opts.ledgerAdd(sessionId, content);
92
- const server = findGroundingMcp(manifest);
93
- if (!server) {
94
- return { ok: false, reason: "grounding-mcp not declared in manifest" };
95
- }
96
- const command = Array.isArray(server.command)
97
- ? server.command.map(expandHomePath)
98
- : server.command.trim().split(/\s+/).map(expandHomePath);
99
- return addLedgerFact({
100
- mcpCommand: command,
101
- ...(server.env && { mcpEnv: server.env }),
102
- timeoutMs: server.health?.timeout_ms ?? 5_000,
103
- sessionId,
104
- content,
105
- source,
106
- });
107
- }
108
- /**
109
- * Find the freshest parse-error log under `<dir>` (the
110
- * `<reports-dir>/../parse-errors/` location the standalone Stop hook
111
- * writes to when `parseReport` rejects the agent's last message). Used
112
- * to upgrade `approve understanding`'s "no reports found" diagnostic
113
- * from a silent dead end to a "hook fired but parse failed because X"
114
- * pointer. Best-effort: any I/O error is swallowed and we report no
115
- * parse-error, mirroring the listPersistedReports contract.
116
- *
117
- * `sessionId` filter (agent-tasks/b13205b2): each parse-error log's JSON
118
- * header carries the `sessionId` of the session that produced it. The
119
- * lookup used to return the directory-newest log regardless of whose
120
- * session wrote it, so a stale parse-error from a previous session would
121
- * surface in the current operator's approve output and read like a
122
- * failure of THEIR session. Logs whose header sessionId does not match
123
- * `sessionId` are now skipped entirely. Logs missing a `sessionId` field
124
- * (or whose header is not JSON) are also skipped, since we cannot
125
- * attribute them.
126
- *
127
- * `malformedSections` (task 823837fd, follow-up to 7e29e5d7): when the
128
- * log's JSON header carries a non-empty `malformedSections` array (a
129
- * (list) section that was present but not a markdown list), the returned
130
- * `summary` names those sections explicitly so the CLI's one-line reason
131
- * does not read as a bare "missing" when the agent actually wrote
132
- * *something* under the heading. Exported so the PreToolUse hooks
133
- * (hook-pre-tool-use.ts, hook-codex-pre-tool-use.ts) can reuse the same
134
- * lookup + attribution logic rather than re-implementing the header scan.
135
- *
136
- * Both hooks pass `maxEntries` (`MAX_HOOK_LISTING_ENTRIES`): a directory with
137
- * more `*.log` entries than that is read not at all and yields no parse error,
138
- * and the logs read are charged against the hash scan's byte budget (the
139
- * larger of the `fstat` size and the per-entry floor, newest first), so a
140
- * planted directory cannot run the hook past its time budget. Once the budget
141
- * is spent the lookup yields no parse error.
142
- */
143
- export function findLatestParseError(dir, sessionId, opts = {}) {
144
- // `maxEntries` is set by the PreToolUse hooks (the directory is agent-writable
145
- // and the lookup stats and reads its logs): past it nothing is opened and the
146
- // answer is no parse error (the listing of a too large directory is empty),
147
- // and the reads below spend a byte budget. The operator command leaves it unset.
148
- const listed = listDirNamesBounded(dir, ".log", opts.maxEntries ?? Number.POSITIVE_INFINITY);
149
- const budget = opts.maxEntries === undefined ? undefined : { spent: 0 };
150
- const candidates = [];
151
- for (const name of listed.names) {
152
- const full = path.join(dir, name);
153
- let stat;
154
- try {
155
- stat = fs.statSync(full);
156
- }
157
- catch {
158
- continue;
159
- }
160
- candidates.push({ filePath: full, mtimeMs: stat.mtimeMs });
161
- }
162
- candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
163
- for (const cand of candidates) {
164
- // Agent-writable dir, reached by both hooks on the no-marker path: the stat
165
- // above only orders the candidates; the bounded reader's descriptor decides
166
- // type and size, so a FIFO, a huge or a growing log is skipped like an
167
- // unreadable one.
168
- const bounded = readReportFileBounded(cand.filePath, { budget });
169
- if (!bounded.ok && bounded.reason === "over-budget")
170
- return null;
171
- if (!bounded.ok)
172
- continue;
173
- const raw = bounded.raw;
174
- // The standalone package writes a JSON header followed by `--- raw ---`
175
- // and the original assistant text. Read the header for a `message`,
176
- // `reason`, or `missing` field; fall back to the first line if the
177
- // schema is unfamiliar so a future format change still surfaces
178
- // *something* rather than going silent.
179
- const header = raw.split("\n--- raw ---")[0] ?? raw;
180
- let summary = (header.split("\n")[0] ?? "").trim();
181
- let headerSessionId = null;
182
- let malformedSections = [];
183
- // Tracks whether `summary` was taken verbatim from the package's own
184
- // `message` field: `@lannguyensi/understanding-gate` >= 0.4.10 already
185
- // annotates each malformed (list) section inline in that string
186
- // ("Prior Art (list) (present but not a markdown list -- use '- ' or
187
- // '1.' items)"). Appending the same names again below would duplicate
188
- // them in one line; the append is only useful when `summary` came from
189
- // the `reason` fallback or the raw first-line fallback, neither of
190
- // which mentions the malformed sections on its own.
191
- let summaryFromMessage = false;
192
- try {
193
- const parsed = JSON.parse(header);
194
- if (typeof parsed["sessionId"] === "string") {
195
- headerSessionId = parsed["sessionId"];
196
- }
197
- if (Array.isArray(parsed["malformedSections"])) {
198
- malformedSections = parsed["malformedSections"].filter((m) => typeof m === "string");
199
- }
200
- if (typeof parsed["message"] === "string" && parsed["message"].length > 0) {
201
- summary = parsed["message"];
202
- summaryFromMessage = true;
203
- }
204
- else if (typeof parsed["reason"] === "string") {
205
- const missing = Array.isArray(parsed["missing"])
206
- ? ` (missing: ${parsed["missing"].filter((m) => typeof m === "string").join(", ")})`
207
- : "";
208
- summary = `${parsed["reason"]}${missing}`;
209
- }
210
- }
211
- catch {
212
- /* keep the first-line fallback; headerSessionId stays null */
213
- }
214
- if (headerSessionId !== sessionId)
215
- continue;
216
- if (malformedSections.length > 0 && !summaryFromMessage) {
217
- summary = `${summary}; malformed (present but not a markdown list): ${malformedSections.join(", ")}`;
218
- }
219
- return { filePath: cand.filePath, summary, malformedSections };
220
- }
221
- return null;
222
- }
223
- /**
224
- * Render the agent-facing "your previous report had malformed sections"
225
- * sentence from a `ParseErrorSummary.malformedSections` list, or `null`
226
- * when there is nothing to say. Shared by both PreToolUse hooks
227
- * (hook-pre-tool-use.ts, hook-codex-pre-tool-use.ts, task 823837fd
228
- * review) so the sentence is defined once instead of duplicated
229
- * byte-identically in each runtime; same extraction shape as
230
- * `checkOperatorApprovalMarkers` (understanding-before-execution-runtime.ts),
231
- * a marker-check helper both hooks already call instead of
232
- * re-implementing.
233
- *
234
- * Section keys are mapped to their display name via `describeSectionKey`
235
- * (`Prior Art (priorArt)` rather than the bare camelCase key) so the
236
- * sentence reads consistently with `renderReportSchemaHint`'s section
237
- * bullets in the same block reason, instead of mixing two vocabularies
238
- * for the same section. The CLI's own one-line summary
239
- * (`findLatestParseError` above) intentionally stays on raw keys; it is
240
- * operator-facing and matches the parse-error log verbatim.
241
- */
242
- export function renderMalformedSectionsNotice(sections) {
243
- if (sections.length === 0)
244
- return null;
245
- const named = sections.map((s) => describeSectionKey(s)).join(", ");
246
- return (`Your previous Understanding Report attempt had malformed sections ` +
247
- `(present but not a markdown list): ${named}.`);
248
- }
249
- /**
250
- * Exported (agent-tasks/74b4b17d) so the PreToolUse hook's auto-approval
251
- * path applies the SAME approve-time content validation this CLI does,
252
- * rather than a second, drifting copy: the ADR
253
- * (docs/decisions/2026-08-27-ug-auto-mode-approval.md, Option A
254
- * condition 3) requires the auto path's report precondition to be the
255
- * approve CLI's own check. Export only; the logic is unchanged.
256
- */
257
- export function validatePersistedReport(parsed) {
258
- const mode = typeof parsed["mode"] === "string" ? parsed["mode"] : null;
259
- if (mode !== "grill_me")
260
- return { ok: true, mode };
261
- const priorArt = parsed["priorArt"];
262
- if (!Array.isArray(priorArt) || priorArt.length === 0) {
263
- return {
264
- ok: false,
265
- field: "priorArt",
266
- reason: "grill_me report is missing required Section 10 (Prior Art). " +
267
- "The schema requires a non-empty list naming the channels searched " +
268
- "and the closest existing solution.",
269
- };
270
- }
271
- // Mirror the schema's `items: { type: "string", minLength: 1 }`.
272
- for (const item of priorArt) {
273
- if (typeof item !== "string" || item.trim().length === 0) {
274
- return {
275
- ok: false,
276
- field: "priorArt",
277
- reason: "grill_me report's priorArt contains a non-string or empty item; " +
278
- "every entry must be a non-empty string.",
279
- };
280
- }
281
- }
282
- // Deterrent for the literal `- None` / `None` placeholder. The parser
283
- // intentionally accepts these structurally; approve-time is where the
284
- // prompt's "do not write `- None`" rule turns into a hard refusal.
285
- // Only blocks when EVERY item is the None literal; a mixed list with
286
- // real content is accepted.
287
- const isNone = (x) => typeof x === "string" && ["none", "- none"].includes(x.trim().toLowerCase());
288
- if (priorArt.every(isNone)) {
289
- return {
290
- ok: false,
291
- field: "priorArt",
292
- reason: "grill_me report's priorArt is entirely literal `None` / `- None`. " +
293
- "The section exists to force a written answer to 'should this be " +
294
- "built at all'; name the channels searched and the closest existing tool.",
295
- };
296
- }
297
- return { ok: true, mode };
298
- }
299
- /**
300
- * Exported (agent-tasks/74b4b17d) so the PreToolUse hook's auto-approval path
301
- * CONSUMES the report it used through the identical rewrite this CLI performs
302
- * (ADR Option A condition 5). `boundedRaw`: the text that path already read
303
- * through the bounded reader, so the consume never re-reads the agent-writable
304
- * path (a retargeted symlink); `harness approve understanding` reads by path
305
- * through the same bounded reader.
306
- */
307
- export function rewriteReportApproved(filePath, approvedAt, approvedBy, sessionId, boundedRaw) {
308
- let raw = boundedRaw;
309
- if (raw === undefined) {
310
- // Bounded like every other read of this agent-writable directory: the path
311
- // can be swapped for an oversized file or a FIFO after the listing.
312
- const read = readReportFileBounded(filePath, { noFollow: true });
313
- if (!read.ok)
314
- throw new Error(`report ${read.detail}`);
315
- raw = read.raw;
316
- }
317
- const { text, previousStatus, sessionIdStamped } = renderApprovedReport(raw, approvedAt, approvedBy, sessionId);
318
- // Temp file plus rename: the rename replaces the directory entry (a symlink
319
- // included) and never opens whatever a retargeted symlink points at.
320
- atomicWriteFile(filePath, text);
321
- return { previousStatus, sessionIdStamped };
322
- }
323
- /**
324
- * Thrown by {@link renderApprovedReport} when the approved report, once
325
- * pretty-printed with its approval fields, is over `MAX_HASHED_REPORT_BYTES`.
326
- * The gate-read scan reads no file over that cap, so a marker signed for such
327
- * a report would deny on every call and neither re-approval nor `--force`
328
- * could clear it.
329
- */
330
- export class ApprovedReportTooLargeError extends Error {
331
- bytes;
332
- constructor(bytes) {
333
- super(`the approved report would be ${bytes} bytes, over the ${MAX_HASHED_REPORT_BYTES}-byte cap ` +
334
- "for hashing its content, so the gate could not match it");
335
- this.bytes = bytes;
336
- this.name = "ApprovedReportTooLargeError";
337
- }
338
- }
339
- /**
340
- * The text `rewriteReportApproved` writes: the report with its approval
341
- * fields stamped and pretty-printed. Pure, so a producer can check the size
342
- * of the rewritten bytes before it signs a marker or changes any file. Throws
343
- * {@link ApprovedReportTooLargeError} when those bytes exceed
344
- * `MAX_HASHED_REPORT_BYTES`: a report accepted just under the cap can cross
345
- * it through the pretty-print and the added fields.
346
- */
347
- export function renderApprovedReport(raw, approvedAt, approvedBy, sessionId) {
348
- const parsed = JSON.parse(raw);
349
- const previousStatus = typeof parsed["approvalStatus"] === "string" ? parsed["approvalStatus"] : null;
350
- parsed["approvalStatus"] = "approved";
351
- parsed["approvedAt"] = approvedAt;
352
- parsed["approvedBy"] = approvedBy;
353
- // `expiredAt` and `expiredBy` are `expirePersistedReport`'s stamp for how a
354
- // report reached "expired" (understanding-before-execution-runtime.ts); they
355
- // describe that specific past state, not the report's current one.
356
- // Approving a report that was previously expired must not let that stale
357
- // timestamp survive into the new snapshot, or the persisted record becomes
358
- // self-contradictory: {approvalStatus: "approved", expiredAt: ...}. Mirrors
359
- // the same idiom in the standalone package's `withApprovalStatus`
360
- // (agent-grounding PR #173, from the 5120938c review). `delete` (not
361
- // `= undefined`) so `JSON.stringify` below drops the key entirely instead
362
- // of serializing `"expiredAt": null`-adjacent noise.
363
- delete parsed["expiredAt"];
364
- delete parsed["expiredBy"];
365
- // Stamp the session id when the report lacks one (older Stop-hook package
366
- // versions write reports without a `sessionId` field). This binds the report
367
- // to the session that approved it, so every later lookup strict-matches it and
368
- // the sessionId-null fallback can never re-adopt it for a different session
369
- // (harness/0dce3880 friction #1). An existing sessionId is left untouched.
370
- let sessionIdStamped = false;
371
- const existing = parsed["sessionId"];
372
- if (typeof existing !== "string" || existing.length === 0) {
373
- parsed["sessionId"] = sessionId;
374
- sessionIdStamped = true;
375
- }
376
- const text = `${JSON.stringify(parsed, null, 2)}\n`;
377
- const bytes = Buffer.byteLength(text);
378
- if (bytes > MAX_HASHED_REPORT_BYTES)
379
- throw new ApprovedReportTooLargeError(bytes);
380
- return { text, previousStatus, sessionIdStamped };
381
- }
382
- /**
383
- * Normalise a list of task ids supplied via `opts.tasks` (or the CLI's
384
- * variadic `--task`). Each entry is comma-split (so `--task a,b` and
385
- * `--task a b` are equivalent), trimmed, blank entries dropped, and the
386
- * result de-duplicated while preserving first-seen order.
387
- */
388
- export function dedupeTaskIds(raw) {
389
- const seen = new Set();
390
- const out = [];
391
- for (const entry of raw) {
392
- for (const part of entry.split(",")) {
393
- const id = part.trim();
394
- if (id.length === 0 || seen.has(id))
395
- continue;
396
- seen.add(id);
397
- out.push(id);
398
- }
399
- }
400
- return out;
401
- }
402
- /**
403
- * A reason `hashReportFile` gives for a report whose CONTENT cannot be hashed
404
- * (`--force` may sign a marker without a content binding over it), as opposed
405
- * to one that could not be read within the bound (oversized, not a regular
406
- * file, a link, unreadable, growing), which `--force` never overrides.
407
- */
408
- function isContentReason(reason) {
409
- return reason === "too-deep" || reason === "not-json-object";
410
- }
411
- /**
412
- * The reports directory is writable by the gated agent, so `harness approve
413
- * understanding` lists it through the bounded reader (one `O_NOFOLLOW` open
414
- * and `fstat` per entry, never a read past the size cap) and refuses while any `*.json`
415
- * entry cannot be read as a report: oversized, a FIFO or other non-regular
416
- * file, a symbolic link, unreadable, or growing. Refusing, rather than
417
- * leaving the entry out, keeps the approval from binding an older report
418
- * while a newer one is hidden from it. Thrown before any side effect, so
419
- * no marker, ledger tag or report flip is written; `--force` does not
420
- * override it (it overrides report content validation only).
421
- */
422
- function refuseSkippedReports(skipped, reportsDir) {
423
- if (skipped.length === 0)
424
- return;
425
- const lines = skipped.map((s) => ` ${escapeForDisplay(s.filePath)}: ${s.detail}`);
426
- throw new HarnessExitError([
427
- `refusing to approve: ${skipped.length === 1 ? "an entry" : `${skipped.length} entries`} in the reports directory ` +
428
- `cannot be read as a report, so approval cannot tell which report it would bind:`,
429
- ...lines,
430
- "",
431
- `Remove or move ${skipped.length === 1 ? "that file" : "those files"} out of ${reportsDir}, then re-run ` +
432
- "`harness approve understanding`. No approval marker, ledger tag or report change was written.",
433
- "(`harness gc` lists such entries too and leaves them in place.)",
434
- ].join("\n"), EX_FAIL);
435
- }
436
- export async function approveUnderstanding(opts = {}) {
437
- // harness.generated/ holds the `.pending-approval` staging file (the
438
- // third resolution tier below) and is the directory this command cleans
439
- // up after consuming a staged id. `resolvePaths` only computes paths —
440
- // it does not read or parse the manifest — so the lookup still works
441
- // even when the manifest itself is unparseable.
442
- const generatedDir = opts.generatedDir ??
443
- resolveGeneratedDir({
444
- ...(opts.homeDir !== undefined ? { homeDir: opts.homeDir } : {}),
445
- manifestPath: resolvePaths(opts).base,
446
- });
447
- // Session id resolution, in precedence order:
448
- // 1. explicit --session flag
449
- // 2. $CLAUDE_CODE_SESSION_ID — the canonical Claude Code env, the
450
- // variable Claude Code itself exports into the agent shell. Read
451
- // first so the runtime's id wins over a manually exported legacy
452
- // $CLAUDE_SESSION_ID that may not match.
453
- // 3. $CLAUDE_SESSION_ID — legacy / docs-name peer, kept for the
454
- // Codex pre-tool-use hook's own fallback chain and for operators
455
- // who set it by hand in older `!`-shell recipes.
456
- // 4. $CODEX_SESSION_ID (set inside a live Codex session — symmetric
457
- // with the Codex pre-tool-use hook's own env fallback).
458
- // 5. the `.pending-approval` file the gate hook staged on its last
459
- // block — this is what makes an arg-less `harness approve` work
460
- // from the operator's `!`-shell, where neither of the above is set.
461
- // 6. the freshest persisted Understanding Report under <reportsDir>
462
- // whose JSON `sessionId` field is non-null. Runtime-neutral
463
- // fallback when the gate has not blocked yet (e.g. arg-less
464
- // approval right after the agent produced an Understanding Report,
465
- // before any tool call hit the gate to stage `.pending-approval`).
466
- //
467
- // Reports-dir resolution mirrors the downstream persisted-report write
468
- // path: explicit opts.reportsDir wins (test injection), then
469
- // UNDERSTANDING_GATE_REPORT_DIR env (honoured by defaultReportsDir),
470
- // then manifest-anchored fallback via resolvePaths. resolvePaths is
471
- // evaluated lazily so a test that injects opts.reportsDir does not
472
- // also need to inject homeDir/configPath to satisfy the
473
- // HARNESS_ALLOW_REAL_GENERATED_DIR loader guard.
474
- const reportsDir = opts.reportsDir ??
475
- defaultReportsDir(path.dirname(resolvePaths(opts).base));
476
- // Refuse a planted entry before anything else: the session-id fallback
477
- // below and the report lookup further down both list this directory.
478
- refuseSkippedReports(listPersistedReportsBoundedWithSkips(reportsDir, { refuseSymlinks: true }).skipped, reportsDir);
479
- const resolved = resolveApprovalSessionId({
480
- session: opts.session,
481
- generatedDir,
482
- // Tier 6: guess the session from the freshest persisted report.
483
- // Restricted to `pending` reports. An `approved` / `expired`
484
- // report belongs to a finished gate cycle (often a different
485
- // session days ago); adopting its sessionId silently approves an
486
- // unrelated session while the live one stays gated
487
- // (harness/56f51f2b). A `pending` report is one the Stop hook
488
- // just produced that no approval has consumed yet, so it is far
489
- // more likely to be the current session's. This mirrors the
490
- // `tolerantFallback: "uncompleted"` restriction PR #218 applied
491
- // to the report-flip path below. The residual case — a stale
492
- // session left a never-approved `pending` report — is caught by
493
- // the loud newest-report warning the CLI prints, which names the report
494
- // file so the operator can verify before trusting the marker.
495
- newestReportFallback: () => {
496
- const newest = listPersistedReportsBoundedWithSkips(reportsDir, {
497
- refuseSymlinks: true,
498
- }).reports.find((r) => r.sessionId !== null && r.approvalStatus === "pending");
499
- if (newest && newest.sessionId !== null) {
500
- return { sessionId: newest.sessionId, filePath: newest.filePath };
501
- }
502
- return null;
503
- },
504
- });
505
- const sessionId = resolved.sessionId;
506
- const sessionSource = resolved.sessionSource;
507
- const newestReportPath = resolved.newestReportPath;
508
- if (sessionId === "") {
509
- // Reaching here means: no --session flag, no $CLAUDE_CODE_SESSION_ID
510
- // / $CLAUDE_SESSION_ID / $CODEX_SESSION_ID env, no staged
511
- // `.pending-approval`, AND no `pending` persisted Understanding
512
- // Report under <reportsDir> carries a sessionId field. Either the
513
- // gate has never blocked this session and the agent never produced a
514
- // report, or every report is already approved/expired or
515
- // sessionId-null (tier 6 only adopts a fresh `pending` report).
516
- // Spell out the retrieval paths so the operator does not have to
517
- // dig through docs.
518
- throw new HarnessExitError([
519
- "no session id available. Pass --session <id>, or set one of",
520
- "$CLAUDE_CODE_SESSION_ID (Claude Code) / $CLAUDE_SESSION_ID (legacy) /",
521
- "$CODEX_SESSION_ID (Codex).",
522
- "",
523
- `Both the understanding-gate PreToolUse hook AND \`harness session-start preflight\``,
524
- "stage the session id in",
525
- ` ${generatedDir}/.pending-approval`,
526
- "(the hook on block, the preflight on every run with a resolved id) so an",
527
- "arg-less `harness approve` works after either event. An empty result here means",
528
- "neither has fired for the current session yet, or the staging file was already consumed.",
529
- "",
530
- "Fastest fix: run `harness preflight` once, then re-run `harness approve",
531
- "understanding`. The preflight stages the staging file as a side effect.",
532
- "",
533
- "Other runtime-neutral recovery paths:",
534
- ` • Read the JSON \`sessionId\` field from the newest report under`,
535
- ` ${reportsDir}`,
536
- " The agent writes one report per Understanding Report it produces,",
537
- " so this is the canonical session-id source for both Claude Code",
538
- " and Codex runtimes regardless of cwd.",
539
- " • From inside the running agent: ask it to print its session id",
540
- " (Claude Code exposes $CLAUDE_CODE_SESSION_ID; Codex exposes",
541
- " $CODEX_SESSION_ID and also prints it in `codex doctor --json`).",
542
- "",
543
- "If approve writes the tag but the gate still blocks, the running",
544
- "session is using a different session id than the report you picked.",
545
- "In that case ask the agent to read its own session id and pass",
546
- "that exact value to --session.",
547
- ].join("\n"), EX_FAIL);
548
- }
549
- // Manifest is required for the ledger write path; if it can't load,
550
- // we still try to flip the persisted report so a solo user benefits.
551
- // Not blocking: a solo user still benefits from the report flip below
552
- // even with no manifest. `manifestLoadError` captures the cause so the
553
- // degraded-ok ledger result names WHY the write was skipped instead of
554
- // leaving the operator with a bare `ledger: ok false` (no-silent-errors,
555
- // M8).
556
- // Gap-fill mode for a stdin report that declares none of its own
557
- // (harness task 5d73d78d): resolve via `resolveMode` (Env >
558
- // config.mode > DEFAULT_MODE — this IS a live runtime consumer, unlike
559
- // `resolve()`/`buildHooks`'s generation path; see `MODE_ENV`'s doc
560
- // comment in understanding-before-execution.ts for why the two differ),
561
- // from whatever manifest is available (`loadDeclaredUnderstandingPack`
562
- // above), so a report captured via this path is validated against the
563
- // operator's actually-configured mode instead of a hardcoded
564
- // "fast_confirm" regardless of harness.yaml. A missing manifest, or a
565
- // manifest without the pack declared, resolves the same as an empty
566
- // `config:` block, resolveMode still applies Env > DEFAULT_MODE in
567
- // that case.
568
- //
569
- // A pack entry that IS declared but `enabled: false` is treated the
570
- // SAME as undeclared (task 5d73d78d review LOW-10): a disabled pack's
571
- // hooks never ran, so its `config.mode` is not "the operator's live
572
- // mode" in any sense this gap-fill should honor. The synthesized
573
- // fallback only needs `name` + `config` (resolveMode's minimal
574
- // `ModeConfigSource` shape) — `source`/`enabled` would otherwise have
575
- // to be invented for a pack entry that, by construction, was never
576
- // matched. `loadDeclaredUnderstandingPack` applies that same rule.
577
- const { manifest, manifestLoadError, declaredPack } = loadDeclaredUnderstandingPack(opts);
578
- // Task 5d73d78d review LOW (fix-round-3): `resolveMode`'s own warning
579
- // (an invalid `config.mode` or `UNDERSTANDING_GATE_MODE` value) used to
580
- // be dropped on the floor here — only `.mode` was read. The Codex
581
- // `UserPromptSubmit` injector (hook-codex-user-prompt-submit.ts)
582
- // already surfaces the identical warning shape to stderr on this same
583
- // `resolveMode` call; this path silently swallowed it, so an operator
584
- // with a typo'd `config.mode` got no signal at all from `harness
585
- // approve understanding`. Surfaced via `modeWarning` on the result so
586
- // the CLI can print it the same way the marker/ledger/report lines are
587
- // printed.
588
- const modeResolution = resolveMode(declaredPack);
589
- const resolvedMode = toPackageMode(modeResolution.mode);
590
- // Report capture from stdin (task 61fd36db): persist BEFORE the
591
- // lookup below so this very approve run selects, validates, and flips
592
- // the report the agent just attached. Session-bound via the resolved
593
- // sessionId, so the strict match wins over any stale leftovers.
594
- let stdinReport;
595
- if (typeof opts.reportMarkdown === "string" && opts.reportMarkdown.trim().length > 0) {
596
- stdinReport = persistStdinReport({
597
- markdown: opts.reportMarkdown,
598
- reportsDir,
599
- sessionId,
600
- now: opts.now ?? new Date(),
601
- mode: resolvedMode,
602
- });
603
- }
604
- // Approve-time validation. Resolve the report we would flip BEFORE
605
- // writing the marker, so a validation failure can short-circuit every
606
- // downstream write. The `latest` + `reports` values are reused later;
607
- // we do not list / find twice. The fallback age limit is what stops a
608
- // weeks-old sessionId-less leftover from being adopted, validated,
609
- // and stamped as if it were the live session's report when the
610
- // producer Stop hook silently failed (harness-discovery C1).
611
- // Listed again here (the stdin capture above may have written a report);
612
- // a planted entry that appeared since the first listing is refused too.
613
- const listing = listPersistedReportsBoundedWithSkips(reportsDir, { refuseSymlinks: true });
614
- refuseSkippedReports(listing.skipped, reportsDir);
615
- const reports = listing.reports;
616
- const selection = selectReportForSession(reports, sessionId, {
617
- tolerantFallback: "uncompleted",
618
- maxFallbackAgeMs: TOLERANT_FALLBACK_MAX_AGE_MS,
619
- now: opts.now,
620
- });
621
- const latest = selection.report;
622
- let validation;
623
- if (!latest) {
624
- validation = { skipped: true };
625
- }
626
- else {
627
- let parsed = null;
628
- // Bounded read, not following a symbolic link: the listing above saw the
629
- // file within the cap, but the path can be swapped for an oversized file,
630
- // a FIFO or a link since.
631
- const reread = readReportFileBounded(latest.filePath, { noFollow: true });
632
- if (reread.ok) {
633
- try {
634
- parsed = JSON.parse(reread.raw);
635
- }
636
- catch {
637
- parsed = null;
638
- }
639
- }
640
- if (!reread.ok) {
641
- // Enforced even under --force: a report that cannot be read within the
642
- // bound has no content to bind, and --force never signs a marker over
643
- // one (it overrides content validation only).
644
- validation = {
645
- ok: false,
646
- field: "report",
647
- reason: `${reread.detail}, so the approval could not bind it`,
648
- enforced: true,
649
- };
650
- }
651
- else if (!parsed) {
652
- validation = { skipped: true };
653
- }
654
- else {
655
- const v = validatePersistedReport(parsed);
656
- validation = v.ok ? v : { ...v, enforced: !opts.force };
657
- // A report the canonical hash cannot cover (larger than the size cap
658
- // the gate reads, not a regular file, nested too deeply) would sign a
659
- // marker whose `reportContentHash` is null, i.e. one the gate-read
660
- // content check never applies to, so it fails validation instead.
661
- // `--force` overrides only a content reason (too deep, not a JSON
662
- // object); a size, type or read failure is enforced whatever the flag
663
- // says. `hashReportFile` reads the file exactly as the gate-read scan
664
- // does, except that it does not follow a symbolic link.
665
- if (validation.ok) {
666
- const hashed = hashReportFile(latest.filePath, { noFollow: true });
667
- if (!hashed.ok) {
668
- validation = {
669
- ok: false,
670
- field: "report",
671
- reason: `${hashed.detail}, so the approval could not bind it`,
672
- enforced: !isContentReason(hashed.reason) || !opts.force,
673
- };
674
- }
675
- }
676
- }
677
- }
678
- // Task 5d73d78d review HIGH-2: a stdin report that was REJECTED (failed
679
- // to parse, e.g. because it does not meet the resolved mode's schema —
680
- // typically a fast_confirm-shaped report submitted against a
681
- // grill_me-configured host, see `resolvedMode` above) AND left no
682
- // persisted report to fall back on must not fall through to `{ skipped:
683
- // true }` above. "skipped" means "nothing was submitted to check"; here
684
- // something WAS submitted and it was refused. Before this fix, that
685
- // case still landed on `{ skipped: true }` (no `latest` report exists
686
- // yet, since persistStdinReport never wrote one), which is not an `ok:
687
- // false` validation outcome, so the enforced short-circuit below never
688
- // triggered and the marker was written anyway — silently approving a
689
- // session whose only report attempt was rejected.
690
- //
691
- // Fix-round-3 HIGH (5d73d78d review, verification round 2): the
692
- // original guard checked only `!latest`, but `latest` can also be a
693
- // sessionId-null report ADOPTED via `selectReportForSession`'s
694
- // `tolerantFallback: "uncompleted"` mode above (any pending, sessionId-
695
- // less report younger than `TOLERANT_FALLBACK_MAX_AGE_MS`). A rejected
696
- // stdin submission with such a leftover sitting on disk used to sail
697
- // through unconstrained: `latest` was truthy so this override never
698
- // fired, the ADOPTED (unrelated) report's own — already-valid — content
699
- // passed `validatePersistedReport` instead, and `rewriteReportApproved`
700
- // below then stamped the live session's id onto that foreign report and
701
- // wrote the marker: a session whose actual submission was refused got
702
- // silently approved anyway. The condition now also treats a fallback-
703
- // adopted `latest` as "nothing THIS session can claim":
704
- // `selection.fallbackAdopted` is `true` exactly when the match was NOT
705
- // a strict sessionId match.
706
- //
707
- // The deliberate carve-out for a genuine EARLIER same-session
708
- // submission stays: when `latest` is a STRICT sessionId match
709
- // (`selection.fallbackAdopted === false`), that report's own content
710
- // validation above already governs the outcome and this block does not
711
- // override it.
712
- if (typeof opts.reportMarkdown === "string" &&
713
- opts.reportMarkdown.trim().length > 0 &&
714
- stdinReport !== undefined &&
715
- stdinReport.ok === false &&
716
- (!latest || selection.fallbackAdopted)) {
717
- validation = {
718
- ok: false,
719
- field: "stdinReport",
720
- reason: stdinReport.reason,
721
- enforced: !opts.force,
722
- };
723
- }
724
- // Short-circuit before any side effect if validation rejects and the
725
- // operator did not pass --force. No marker, no ledger tag, no report
726
- // flip — the gate stays closed and the audit trail records no
727
- // approval. The CLI surfaces this as a hard failure so the operator
728
- // does not believe they approved when they didn't.
729
- if ("ok" in validation && validation.ok === false && validation.enforced) {
730
- // Any --task / --tasks ids the operator passed are dropped on the
731
- // floor: pre-approving a batch alongside a session whose own report
732
- // failed validation would write task markers for a session that the
733
- // gate is still going to refuse. The CLI surfaces this empty array
734
- // alongside the rejection so an operator who batched several tasks
735
- // can see the batch was NOT pre-approved.
736
- return {
737
- sessionId,
738
- sessionSource,
739
- ...(newestReportPath !== undefined ? { newestReportPath } : {}),
740
- ...(modeResolution.warning !== null ? { modeWarning: modeResolution.warning } : {}),
741
- marker: {
742
- ok: false,
743
- reason: `validation failed (${validation.field}): ${validation.reason}`,
744
- },
745
- taskMarkers: [],
746
- ...(stdinReport !== undefined ? { stdinReport } : {}),
747
- ledger: {
748
- ok: false,
749
- tag: approvedLedgerTagFor(sessionId),
750
- reason: `skipped: ${validation.field} validation failed`,
751
- },
752
- persistedReport: {
753
- ok: false,
754
- reason: `skipped: ${validation.field} validation failed`,
755
- },
756
- validation,
757
- };
758
- }
759
- // Report-content hash the marker's signature binds to (harness/f9485cc7):
760
- // the canonical hash of the persisted report AT APPROVAL TIME, computed
761
- // BEFORE `rewriteReportApproved` below flips its status/approvedAt/
762
- // approvedBy fields, so it covers what the operator actually reviewed.
763
- // `canonicalReportHash` leaves the lifecycle fields out, which is why the
764
- // value survives that flip and a later `expirePersistedReport` rewrite;
765
- // both PreToolUse hooks look for a report file with that hash at gate-read
766
- // time (`verifyApprovedReportHash`, task fa423e9b) and refuse the marker
767
- // when none is left. null when no persisted report was resolved or it
768
- // cannot be read as a JSON object (validation skipped above, nothing to
769
- // bind), or when its content cannot be hashed: nested too deeply or not a
770
- // JSON object (reachable only under --force: the validation above refuses
771
- // the first otherwise). A report larger than the size cap, not a regular
772
- // file or a link never gets here: the validation above enforces that
773
- // refusal under --force too, and the check below repeats it for a swap
774
- // since.
775
- let reportContentHash = null;
776
- if (latest) {
777
- const hashed = hashReportFile(latest.filePath, { noFollow: true });
778
- if (hashed.ok) {
779
- reportContentHash = hashed.hash;
780
- }
781
- else if (!isContentReason(hashed.reason)) {
782
- // Swapped for an oversized file, a FIFO or a link after the validation
783
- // above read it: refuse before any marker, ledger tag or report flip is
784
- // written, `--force` or not (the validation above enforces the same).
785
- throw new HarnessExitError(`refusing to approve: report ${escapeForDisplay(latest.filePath)} ${hashed.detail} ` +
786
- "since it was validated, so the approval cannot bind it. No approval marker, " +
787
- "ledger tag or report change was written; re-run `harness approve understanding`.", EX_FAIL);
788
- }
789
- }
790
- // Write the canonical approval marker first. The gate consults this
791
- // file (not the ledger) since agent-tasks/88ca4bb3 closed the self-
792
- // approval backdoor: the agent has direct MCP access to the ledger,
793
- // but no path to write a file under harness.generated/.
794
- const approvedAtMarker = (opts.now ?? new Date()).toISOString();
795
- const approvedByMarker = opts.approvedBy ?? DEFAULT_APPROVED_BY;
796
- // The rewrite below pretty-prints the report and adds its approval fields,
797
- // which can carry a report accepted just under the size cap over it. The
798
- // gate-read scan reads no file over the cap, so the marker signed here would
799
- // deny on every call, and neither re-approval nor --force could clear it.
800
- // Render the rewrite first and refuse on its bytes, before any marker,
801
- // ledger tag or report change is written, `--force` or not.
802
- if (latest) {
803
- const current = readReportFileBounded(latest.filePath, { noFollow: true });
804
- if (current.ok) {
805
- try {
806
- renderApprovedReport(current.raw, approvedAtMarker, approvedByMarker, sessionId);
807
- }
808
- catch (err) {
809
- if (err instanceof ApprovedReportTooLargeError) {
810
- throw new HarnessExitError(`refusing to approve: report ${escapeForDisplay(latest.filePath)}: ${err.message}. ` +
811
- "Shorten the report and re-run `harness approve understanding`. No approval marker, " +
812
- "ledger tag or report change was written.", EX_FAIL);
813
- }
814
- // Any other failure (unparseable text) keeps its existing handling below.
815
- }
816
- }
817
- }
818
- let markerResult;
819
- try {
820
- const filePath = writeApprovalMarker(generatedDir, sessionId, {
821
- approvedAt: approvedAtMarker,
822
- approvedBy: approvedByMarker,
823
- reportContentHash,
824
- });
825
- markerResult = { ok: true, filePath, approvedAt: approvedAtMarker };
826
- }
827
- catch (err) {
828
- markerResult = {
829
- ok: false,
830
- reason: `failed to write approval marker: ${err.message}`,
831
- };
832
- }
833
- // Task-scoped markers (harness/1ee26e77 + v2 auto-resolve in
834
- // harness/494fd1e5 + multi-task batch in harness/0dce3880). Written
835
- // alongside the session marker. Resolution precedence:
836
- // - opts.tasks (explicit, multi) — pre-approve a whole batch, OR
837
- // - opts.task (explicit, single, back-compat), OR
838
- // - the active-claim file (source: "active-claim").
839
- // A failure on any one id is surfaced loudly but does not abort the
840
- // approve flow; the session marker still satisfies the gate as a
841
- // fallback, and the other ids still get their markers.
842
- let resolvedTaskIds = [];
843
- let taskSource = "flag";
844
- if (opts.tasks && opts.tasks.length > 0) {
845
- resolvedTaskIds = dedupeTaskIds(opts.tasks);
846
- taskSource = "flag";
847
- }
848
- else if (typeof opts.task === "string" && opts.task.length > 0) {
849
- resolvedTaskIds = [opts.task];
850
- taskSource = "flag";
851
- }
852
- else {
853
- const fromFile = readActiveClaim(generatedDir);
854
- if (fromFile !== null) {
855
- resolvedTaskIds = [fromFile];
856
- taskSource = "active-claim";
857
- }
858
- }
859
- const taskMarkers = [];
860
- for (const taskId of resolvedTaskIds) {
861
- try {
862
- const filePath = writeTaskApprovalMarker(generatedDir, taskId, {
863
- approvedAt: approvedAtMarker,
864
- approvedBy: approvedByMarker,
865
- reportContentHash,
866
- });
867
- taskMarkers.push({
868
- ok: true,
869
- taskId,
870
- filePath,
871
- approvedAt: approvedAtMarker,
872
- source: taskSource,
873
- });
874
- }
875
- catch (err) {
876
- taskMarkers.push({
877
- ok: false,
878
- taskId,
879
- reason: `failed to write task marker: ${err.message}`,
880
- source: taskSource,
881
- });
882
- }
883
- }
884
- // Ledger tag content: a `--force`-bypass of a validation failure
885
- // stamps the bypass into the tag so audit can distinguish a clean
886
- // approval from one that overrode a structural rule. The base tag
887
- // shape (`understanding-approved:<session>`) stays intact so the gate
888
- // matcher still recognises it; the `:forced:<field>` suffix is
889
- // additive metadata.
890
- const tag = "ok" in validation && validation.ok === false
891
- ? `${approvedLedgerTagFor(sessionId)}:forced:${validation.field}`
892
- : approvedLedgerTagFor(sessionId);
893
- const ledgerResult = manifest
894
- ? await writeLedgerTag(manifest, sessionId, tag, opts)
895
- : {
896
- ok: false,
897
- reason: manifestLoadError
898
- ? `manifest unreadable (${manifestLoadError}); skipped ledger write`
899
- : "manifest unreadable; skipped ledger write",
900
- };
901
- // Persisted report: flip the latest matching one. `reports` + `latest`
902
- // were resolved up front (alongside validation) so both paths agree
903
- // on the same artefact.
904
- let persistedReport;
905
- if (!latest) {
906
- // When no matching report exists, look at the sibling parse-errors
907
- // directory (`<dir-of-reports>/../parse-errors/`, the path the
908
- // standalone @lannguyensi/understanding-gate Stop hook writes to
909
- // when its parser rejects the agent's last message). Surface the
910
- // newest entry's reason so "no reports found" becomes "the hook
911
- // fired but the parser rejected the report — here is why", rather
912
- // than a silent dead end.
913
- const parseErrorsDir = path.join(path.dirname(reportsDir), "parse-errors");
914
- const latestParseError = findLatestParseError(parseErrorsDir, sessionId);
915
- let reason;
916
- if (reports.length === 0) {
917
- reason = `no reports found at ${reportsDir}`;
918
- if (latestParseError) {
919
- reason += `; latest parse-error at ${escapeForDisplay(latestParseError.filePath)}: ${escapeForDisplay(latestParseError.summary)}`;
920
- }
921
- }
922
- else if (selection.staleRejected.length > 0) {
923
- // A sessionId-less pending report existed but exceeded the
924
- // fallback age limit. This is its own failure mode, distinct from
925
- // "no report": it usually means the live session's report was
926
- // never persisted and only an unrelated leftover was on disk —
927
- // exactly the artefact the limit refuses to bind (C1).
928
- const newest = selection.staleRejected[0];
929
- const age = formatAge((opts.now ?? new Date()).getTime() - newest.createdAtMs);
930
- const maxMin = Math.round(TOLERANT_FALLBACK_MAX_AGE_MS / 60_000);
931
- reason =
932
- `no report matched session_id=${escapeForDisplay(sessionId)}; rejected ${selection.staleRejected.length} ` +
933
- `stale sessionId-less candidate(s) for age (newest: ${escapeForDisplay(newest.filePath)}, ` +
934
- `created ${escapeForDisplay(newest.createdAt ?? "<unknown>")}, age ${age} > max ${maxMin}m). ` +
935
- `If the agent just wrote an Understanding Report, the Stop hook likely failed to ` +
936
- `persist it; check ${parseErrorsDir}`;
937
- if (latestParseError) {
938
- reason += `; latest parse-error at ${escapeForDisplay(latestParseError.filePath)}: ${escapeForDisplay(latestParseError.summary)}`;
939
- }
940
- }
941
- else {
942
- reason = `no report matched session_id=${escapeForDisplay(sessionId)} (${reports.length} report(s) for other sessions)`;
943
- }
944
- persistedReport = { ok: false, reason };
945
- }
946
- else {
947
- const approvedAt = (opts.now ?? new Date()).toISOString();
948
- const approvedBy = opts.approvedBy ?? DEFAULT_APPROVED_BY;
949
- try {
950
- const { previousStatus, sessionIdStamped } = rewriteReportApproved(latest.filePath, approvedAt, approvedBy, sessionId);
951
- persistedReport = {
952
- ok: true,
953
- filePath: latest.filePath,
954
- previousStatus,
955
- approvedAt,
956
- sessionIdStamped,
957
- ...(selection.fallbackAdopted
958
- ? {
959
- fallbackAdopted: {
960
- createdAt: latest.createdAt,
961
- ageMinutes: Math.round(((opts.now ?? new Date()).getTime() - latest.createdAtMs) / 60_000),
962
- },
963
- }
964
- : {}),
965
- };
966
- }
967
- catch (err) {
968
- persistedReport = {
969
- ok: false,
970
- reason: `failed to rewrite ${escapeForDisplay(latest.filePath)}: ${escapeForDisplay(err.message)}`,
971
- };
972
- }
973
- }
974
- // Drop the staging file once we have consumed it AND the canonical
975
- // (marker) write landed, so a later arg-less `harness approve` cannot
976
- // revive this id. A failed marker write keeps the file so the operator
977
- // can retry; an id supplied by flag/env was never "ours" to clean up.
978
- if (sessionSource === "pending-approval" && markerResult.ok) {
979
- clearPendingApproval(generatedDir);
980
- }
981
- return {
982
- sessionId,
983
- sessionSource,
984
- ...(newestReportPath !== undefined ? { newestReportPath } : {}),
985
- ...(modeResolution.warning !== null ? { modeWarning: modeResolution.warning } : {}),
986
- marker: markerResult,
987
- taskMarkers,
988
- ...(stdinReport !== undefined ? { stdinReport } : {}),
989
- ledger: ledgerResult.ok
990
- ? { ok: true, tag }
991
- : { ok: false, tag, reason: ledgerResult.reason },
992
- persistedReport,
993
- validation,
994
- };
995
- }
996
- //# sourceMappingURL=understanding.js.map