harnery 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/dist/commands/agents.d.ts.map +1 -1
  2. package/dist/commands/agents.js +32 -8
  3. package/dist/commands/artifacts.d.ts.map +1 -1
  4. package/dist/commands/artifacts.js +97 -6
  5. package/dist/commands/backup.d.ts +16 -0
  6. package/dist/commands/backup.d.ts.map +1 -1
  7. package/dist/commands/backup.js +239 -33
  8. package/dist/commands/browse.d.ts +8 -0
  9. package/dist/commands/browse.d.ts.map +1 -1
  10. package/dist/commands/browse.js +466 -231
  11. package/dist/commands/diagnostics.d.ts.map +1 -1
  12. package/dist/commands/diagnostics.js +6 -3
  13. package/dist/commands/ledger-v3.d.ts.map +1 -1
  14. package/dist/commands/ledger-v3.js +20 -4
  15. package/dist/commands/qa-run.d.ts.map +1 -1
  16. package/dist/commands/qa-run.js +26 -3
  17. package/dist/commands/qa-status.d.ts.map +1 -1
  18. package/dist/commands/qa-status.js +7 -2
  19. package/dist/commands/resources.d.ts.map +1 -1
  20. package/dist/commands/resources.js +23 -3
  21. package/dist/commands/review-pack.d.ts.map +1 -1
  22. package/dist/commands/review-pack.js +98 -23
  23. package/dist/commands/tunnel.d.ts.map +1 -1
  24. package/dist/commands/tunnel.js +2 -2
  25. package/dist/core/adapters/profiles.d.ts +1 -1
  26. package/dist/core/agents/canonical-emit.d.ts +3 -2
  27. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  28. package/dist/core/agents/canonical-emit.js +2 -0
  29. package/dist/core/agents/cli.js +13 -6
  30. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  31. package/dist/core/agents/live-authority-v3.js +5 -3
  32. package/dist/core/agents/live-lifecycle-v3.d.ts +2 -2
  33. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
  34. package/dist/core/agents/render/prompt-context.d.ts +7 -5
  35. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  36. package/dist/core/agents/render/prompt-context.js +63 -8
  37. package/dist/core/agents/session-finalizer-v3.d.ts +2 -2
  38. package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
  39. package/dist/core/agents/state/live-coordination-view.d.ts +3 -3
  40. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  41. package/dist/core/agents/state/live-coordination-view.js +2 -1
  42. package/dist/core/agents/state/names.d.ts +35 -2
  43. package/dist/core/agents/state/names.d.ts.map +1 -1
  44. package/dist/core/agents/state/names.js +80 -5
  45. package/dist/core/agents/state/stale-sweep.d.ts +2 -1
  46. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  47. package/dist/core/agents/state/stale-sweep.js +23 -6
  48. package/dist/core/agents/turn-elapsed.d.ts +51 -0
  49. package/dist/core/agents/turn-elapsed.d.ts.map +1 -0
  50. package/dist/core/agents/turn-elapsed.js +91 -0
  51. package/dist/core/artifacts/activity.d.ts +14 -0
  52. package/dist/core/artifacts/activity.d.ts.map +1 -0
  53. package/dist/core/artifacts/activity.js +52 -0
  54. package/dist/core/artifacts/delivery-card.d.ts +39 -0
  55. package/dist/core/artifacts/delivery-card.d.ts.map +1 -0
  56. package/dist/core/artifacts/delivery-card.js +282 -0
  57. package/dist/core/artifacts/index.d.ts +42 -7
  58. package/dist/core/artifacts/index.d.ts.map +1 -1
  59. package/dist/core/artifacts/index.js +288 -76
  60. package/dist/core/artifacts/mutation-lock.d.ts +2 -0
  61. package/dist/core/artifacts/mutation-lock.d.ts.map +1 -0
  62. package/dist/core/artifacts/mutation-lock.js +91 -0
  63. package/dist/core/backup/host-snapshot.d.ts +18 -0
  64. package/dist/core/backup/host-snapshot.d.ts.map +1 -0
  65. package/dist/core/backup/host-snapshot.js +64 -0
  66. package/dist/core/config.d.ts +20 -5
  67. package/dist/core/config.d.ts.map +1 -1
  68. package/dist/core/config.js +44 -10
  69. package/dist/core/diagnostics/advice.d.ts +38 -3
  70. package/dist/core/diagnostics/advice.d.ts.map +1 -1
  71. package/dist/core/diagnostics/advice.js +103 -99
  72. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  73. package/dist/core/diagnostics/bundle.js +111 -47
  74. package/dist/core/diagnostics/comparison.d.ts.map +1 -1
  75. package/dist/core/diagnostics/comparison.js +3 -2
  76. package/dist/core/diagnostics/contract.d.ts +15 -31
  77. package/dist/core/diagnostics/contract.d.ts.map +1 -1
  78. package/dist/core/diagnostics/contract.js +2 -5
  79. package/dist/core/diagnostics/index.d.ts +2 -0
  80. package/dist/core/diagnostics/index.d.ts.map +1 -1
  81. package/dist/core/diagnostics/index.js +2 -0
  82. package/dist/core/diagnostics/pressure-contract.d.ts +260 -0
  83. package/dist/core/diagnostics/pressure-contract.d.ts.map +1 -0
  84. package/dist/core/diagnostics/pressure-contract.js +70 -0
  85. package/dist/core/diagnostics/pressure.d.ts +25 -0
  86. package/dist/core/diagnostics/pressure.d.ts.map +1 -0
  87. package/dist/core/diagnostics/pressure.js +1138 -0
  88. package/dist/core/diagnostics/replay.d.ts.map +1 -1
  89. package/dist/core/diagnostics/replay.js +90 -10
  90. package/dist/core/events/v3/adapter-id.d.ts +6 -0
  91. package/dist/core/events/v3/adapter-id.d.ts.map +1 -0
  92. package/dist/core/events/v3/adapter-id.js +7 -0
  93. package/dist/core/events/v3/archive-retention.d.ts.map +1 -1
  94. package/dist/core/events/v3/archive-retention.js +3 -2
  95. package/dist/core/events/v3/bootstrap.d.ts +41 -4
  96. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  97. package/dist/core/events/v3/bootstrap.js +120 -17
  98. package/dist/core/events/v3/capabilities.d.ts +16 -9
  99. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  100. package/dist/core/events/v3/capabilities.js +37 -2
  101. package/dist/core/events/v3/capability-drift.d.ts +2 -2
  102. package/dist/core/events/v3/capability-drift.d.ts.map +1 -1
  103. package/dist/core/events/v3/control-witness.d.ts +48 -5
  104. package/dist/core/events/v3/control-witness.d.ts.map +1 -1
  105. package/dist/core/events/v3/control-witness.js +91 -36
  106. package/dist/core/events/v3/control.d.ts.map +1 -1
  107. package/dist/core/events/v3/control.js +22 -2
  108. package/dist/core/events/v3/index.d.ts +2 -1
  109. package/dist/core/events/v3/index.d.ts.map +1 -1
  110. package/dist/core/events/v3/index.js +2 -1
  111. package/dist/core/events/v3/live-feed.d.ts +7 -1
  112. package/dist/core/events/v3/live-feed.d.ts.map +1 -1
  113. package/dist/core/events/v3/live-feed.js +21 -3
  114. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  115. package/dist/core/events/v3/live-routing.js +10 -2
  116. package/dist/core/events/v3/producers/command-recorder.d.ts +2 -2
  117. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
  118. package/dist/core/events/v3/producers/command-recorder.js +2 -1
  119. package/dist/core/events/v3/producers/coordination-recorder.d.ts +2 -2
  120. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  121. package/dist/core/events/v3/producers/coordination-recorder.js +2 -1
  122. package/dist/core/events/v3/producers/hook-base.d.ts +2 -2
  123. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  124. package/dist/core/events/v3/producers/hook-base.js +15 -5
  125. package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
  126. package/dist/core/events/v3/producers/hook.js +17 -4
  127. package/dist/core/events/v3/producers/intake.d.ts +4 -4
  128. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  129. package/dist/core/events/v3/producers/intake.js +3 -2
  130. package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -1
  131. package/dist/core/events/v3/producers/producer-state-observer.js +2 -1
  132. package/dist/core/events/v3/producers/recorder.d.ts +16 -5
  133. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  134. package/dist/core/events/v3/producers/recorder.js +31 -9
  135. package/dist/core/events/v3/reader.d.ts.map +1 -1
  136. package/dist/core/events/v3/reader.js +10 -13
  137. package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
  138. package/dist/core/events/v3/runtime-build.js +3 -2
  139. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +2 -2
  140. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
  141. package/dist/core/events/v3/turn-telemetry.d.ts +2 -2
  142. package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
  143. package/dist/core/hooks/adapter/output.d.ts +16 -14
  144. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  145. package/dist/core/hooks/adapter/output.js +36 -38
  146. package/dist/core/hooks/backup-schedule.d.ts +34 -0
  147. package/dist/core/hooks/backup-schedule.d.ts.map +1 -0
  148. package/dist/core/hooks/backup-schedule.js +114 -0
  149. package/dist/core/hooks/cli.js +61 -18
  150. package/dist/core/hooks/codex-wsl-bridge.d.ts +2 -0
  151. package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -1
  152. package/dist/core/hooks/codex-wsl-bridge.js +18 -4
  153. package/dist/core/hooks/index.d.ts +1 -0
  154. package/dist/core/hooks/index.d.ts.map +1 -1
  155. package/dist/core/hooks/index.js +1 -0
  156. package/dist/core/hooks/prompt-context/contract.d.ts +61 -0
  157. package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -0
  158. package/dist/core/hooks/prompt-context/contract.js +102 -0
  159. package/dist/core/hooks/prompt-context/index.d.ts +5 -0
  160. package/dist/core/hooks/prompt-context/index.d.ts.map +1 -0
  161. package/dist/core/hooks/prompt-context/index.js +2 -0
  162. package/dist/core/hooks/prompt-context/runner.d.ts +24 -0
  163. package/dist/core/hooks/prompt-context/runner.d.ts.map +1 -0
  164. package/dist/core/hooks/prompt-context/runner.js +249 -0
  165. package/dist/core/qa-artifacts.d.ts +3 -0
  166. package/dist/core/qa-artifacts.d.ts.map +1 -1
  167. package/dist/core/qa-artifacts.js +25 -3
  168. package/dist/core/resources/contract.d.ts +69 -3
  169. package/dist/core/resources/contract.d.ts.map +1 -1
  170. package/dist/core/resources/contract.js +1 -1
  171. package/dist/core/resources/index.d.ts +1 -0
  172. package/dist/core/resources/index.d.ts.map +1 -1
  173. package/dist/core/resources/index.js +1 -0
  174. package/dist/core/resources/native.d.ts +36 -0
  175. package/dist/core/resources/native.d.ts.map +1 -0
  176. package/dist/core/resources/native.js +418 -0
  177. package/dist/core/resources/sampler.d.ts +2 -0
  178. package/dist/core/resources/sampler.d.ts.map +1 -1
  179. package/dist/core/resources/sampler.js +31 -1
  180. package/dist/core/resources/status.d.ts +61 -0
  181. package/dist/core/resources/status.d.ts.map +1 -0
  182. package/dist/core/resources/status.js +536 -0
  183. package/dist/core/resources/system.d.ts +27 -0
  184. package/dist/core/resources/system.d.ts.map +1 -0
  185. package/dist/core/resources/system.js +439 -0
  186. package/dist/core/semantic/contract.d.ts +13 -13
  187. package/dist/core/semantic/service.d.ts +2 -0
  188. package/dist/core/semantic/service.d.ts.map +1 -1
  189. package/dist/core/semantic/service.js +27 -4
  190. package/dist/core/storage/builtins.js +41 -0
  191. package/dist/core/supervisor/contract.d.ts +41 -3
  192. package/dist/core/supervisor/contract.d.ts.map +1 -1
  193. package/dist/core/supervisor/contract.js +3 -2
  194. package/dist/core/supervisor/findings.d.ts +3 -0
  195. package/dist/core/supervisor/findings.d.ts.map +1 -1
  196. package/dist/core/supervisor/findings.js +88 -0
  197. package/dist/core/supervisor/history.d.ts.map +1 -1
  198. package/dist/core/supervisor/history.js +14 -0
  199. package/dist/core/supervisor/ledger-state.d.ts +55 -0
  200. package/dist/core/supervisor/ledger-state.d.ts.map +1 -0
  201. package/dist/core/supervisor/ledger-state.js +0 -0
  202. package/dist/core/supervisor/service.d.ts.map +1 -1
  203. package/dist/core/supervisor/service.js +120 -7
  204. package/dist/core/supervisor/storage.d.ts +3 -1
  205. package/dist/core/supervisor/storage.d.ts.map +1 -1
  206. package/dist/core/supervisor/storage.js +4 -0
  207. package/dist/core/workflow/admission.d.ts +3 -0
  208. package/dist/core/workflow/admission.d.ts.map +1 -1
  209. package/dist/core/workflow/admission.js +28 -16
  210. package/dist/core/workflow/engine.js +2 -2
  211. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  212. package/dist/core/workflow/live-session-v3.js +6 -1
  213. package/dist/core/workflow/proof.d.ts.map +1 -1
  214. package/dist/core/workflow/proof.js +4 -3
  215. package/dist/lib/browser/capture-fidelity.d.ts +7 -0
  216. package/dist/lib/browser/capture-fidelity.d.ts.map +1 -1
  217. package/dist/lib/browser/capture-fidelity.js +17 -0
  218. package/dist/lib/browser/client.d.ts +9 -0
  219. package/dist/lib/browser/client.d.ts.map +1 -1
  220. package/dist/lib/browser/client.js +85 -37
  221. package/dist/lib/browser/index.d.ts +3 -1
  222. package/dist/lib/browser/index.d.ts.map +1 -1
  223. package/dist/lib/browser/index.js +2 -1
  224. package/dist/lib/browser/page-review-budget.d.ts +13 -0
  225. package/dist/lib/browser/page-review-budget.d.ts.map +1 -0
  226. package/dist/lib/browser/page-review-budget.js +251 -0
  227. package/dist/lib/browser/page-review-contracts.d.ts +127 -0
  228. package/dist/lib/browser/page-review-contracts.d.ts.map +1 -0
  229. package/dist/lib/browser/page-review-contracts.js +5 -0
  230. package/dist/lib/browser/page-review-evidence.d.ts +48 -0
  231. package/dist/lib/browser/page-review-evidence.d.ts.map +1 -0
  232. package/dist/lib/browser/page-review-evidence.js +340 -0
  233. package/dist/lib/browser/page-review-judge.d.ts +1 -1
  234. package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
  235. package/dist/lib/browser/page-review-judge.js +46 -38
  236. package/dist/lib/browser/page-review-pack.d.ts +44 -22
  237. package/dist/lib/browser/page-review-pack.d.ts.map +1 -1
  238. package/dist/lib/browser/page-review-pack.js +116 -36
  239. package/dist/lib/browser/page-review-source.d.ts +12 -0
  240. package/dist/lib/browser/page-review-source.d.ts.map +1 -0
  241. package/dist/lib/browser/page-review-source.js +22 -0
  242. package/dist/lib/browser/qa-run-contracts.d.ts +35 -9
  243. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
  244. package/dist/lib/browser/qa-run-contracts.js +48 -14
  245. package/dist/lib/browser/qa-run.d.ts.map +1 -1
  246. package/dist/lib/browser/qa-run.js +215 -68
  247. package/dist/lib/browser/qa-snapshot.d.ts +6 -0
  248. package/dist/lib/browser/qa-snapshot.d.ts.map +1 -1
  249. package/dist/lib/browser/qa-snapshot.js +259 -48
  250. package/dist/lib/browser/review-capture-transaction.d.ts +13 -0
  251. package/dist/lib/browser/review-capture-transaction.d.ts.map +1 -0
  252. package/dist/lib/browser/review-capture-transaction.js +79 -0
  253. package/dist/lib/browser/standalone-html.d.ts.map +1 -1
  254. package/dist/lib/browser/standalone-html.js +4 -2
  255. package/dist/lib/browser/thumbnail-association.d.ts +34 -0
  256. package/dist/lib/browser/thumbnail-association.d.ts.map +1 -0
  257. package/dist/lib/browser/thumbnail-association.js +158 -0
  258. package/dist/lib/browser/tiling.d.ts +30 -0
  259. package/dist/lib/browser/tiling.d.ts.map +1 -1
  260. package/dist/lib/browser/tiling.js +38 -0
  261. package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
  262. package/dist/lib/docs-metadata-managed.js +4 -1
  263. package/dist/lib/identities/assume.d.ts.map +1 -1
  264. package/dist/lib/identities/assume.js +7 -1
  265. package/dist/lib/instructions/templates.d.ts.map +1 -1
  266. package/dist/lib/instructions/templates.js +1 -0
  267. package/dist/lib/local-file-url.d.ts +12 -0
  268. package/dist/lib/local-file-url.d.ts.map +1 -1
  269. package/dist/lib/local-file-url.js +16 -2
  270. package/dist/lib/tunnel/state.d.ts +19 -4
  271. package/dist/lib/tunnel/state.d.ts.map +1 -1
  272. package/dist/lib/tunnel/state.js +53 -13
  273. package/package.json +7 -4
  274. package/schemas/config.schema.json +69 -2
  275. package/src/commands/agents.ts +42 -9
  276. package/src/commands/artifacts.ts +130 -6
  277. package/src/commands/backup.ts +287 -34
  278. package/src/commands/browse.ts +564 -267
  279. package/src/commands/diagnostics.ts +6 -3
  280. package/src/commands/ledger-v3.ts +20 -3
  281. package/src/commands/qa-run.ts +37 -3
  282. package/src/commands/qa-status.ts +11 -2
  283. package/src/commands/resources.ts +23 -3
  284. package/src/commands/review-pack.ts +165 -62
  285. package/src/commands/tunnel.ts +2 -1
  286. package/src/core/agents/canonical-emit.ts +4 -2
  287. package/src/core/agents/cli.ts +14 -6
  288. package/src/core/agents/live-authority-v3.ts +7 -3
  289. package/src/core/agents/live-lifecycle-v3.ts +2 -2
  290. package/src/core/agents/render/prompt-context.ts +68 -14
  291. package/src/core/agents/session-finalizer-v3.ts +2 -2
  292. package/src/core/agents/state/live-coordination-view.ts +4 -4
  293. package/src/core/agents/state/names.ts +92 -7
  294. package/src/core/agents/state/stale-sweep.ts +22 -8
  295. package/src/core/agents/turn-elapsed.ts +135 -0
  296. package/src/core/artifacts/activity.ts +71 -0
  297. package/src/core/artifacts/delivery-card.ts +375 -0
  298. package/src/core/artifacts/index.ts +385 -91
  299. package/src/core/artifacts/mutation-lock.ts +106 -0
  300. package/src/core/backup/host-snapshot.ts +76 -0
  301. package/src/core/config.ts +66 -13
  302. package/src/core/diagnostics/advice.ts +148 -120
  303. package/src/core/diagnostics/bundle.ts +138 -52
  304. package/src/core/diagnostics/comparison.ts +6 -2
  305. package/src/core/diagnostics/contract.ts +39 -42
  306. package/src/core/diagnostics/index.ts +2 -0
  307. package/src/core/diagnostics/pressure-contract.ts +294 -0
  308. package/src/core/diagnostics/pressure.ts +1361 -0
  309. package/src/core/diagnostics/replay.ts +116 -11
  310. package/src/core/events/v3/adapter-id.ts +12 -0
  311. package/src/core/events/v3/archive-retention.ts +3 -6
  312. package/src/core/events/v3/bootstrap.ts +163 -16
  313. package/src/core/events/v3/capabilities.ts +75 -25
  314. package/src/core/events/v3/capability-drift.ts +2 -2
  315. package/src/core/events/v3/control-witness.ts +172 -41
  316. package/src/core/events/v3/control.ts +34 -2
  317. package/src/core/events/v3/index.ts +3 -0
  318. package/src/core/events/v3/live-feed.ts +23 -5
  319. package/src/core/events/v3/live-routing.ts +14 -2
  320. package/src/core/events/v3/producers/command-recorder.ts +4 -4
  321. package/src/core/events/v3/producers/coordination-recorder.ts +4 -4
  322. package/src/core/events/v3/producers/hook-base.ts +21 -16
  323. package/src/core/events/v3/producers/hook.ts +21 -4
  324. package/src/core/events/v3/producers/intake.ts +6 -6
  325. package/src/core/events/v3/producers/producer-state-observer.ts +2 -1
  326. package/src/core/events/v3/producers/recorder.ts +50 -21
  327. package/src/core/events/v3/reader.ts +14 -13
  328. package/src/core/events/v3/runtime-build.ts +3 -2
  329. package/src/core/events/v3/runtime-telemetry-capabilities.ts +3 -3
  330. package/src/core/events/v3/turn-telemetry.ts +4 -4
  331. package/src/core/hooks/adapter/output.ts +50 -36
  332. package/src/core/hooks/backup-schedule.ts +147 -0
  333. package/src/core/hooks/cli.ts +65 -14
  334. package/src/core/hooks/codex-wsl-bridge.ts +21 -5
  335. package/src/core/hooks/index.ts +1 -0
  336. package/src/core/hooks/prompt-context/contract.ts +177 -0
  337. package/src/core/hooks/prompt-context/index.ts +22 -0
  338. package/src/core/hooks/prompt-context/runner.ts +303 -0
  339. package/src/core/qa-artifacts.ts +29 -3
  340. package/src/core/resources/contract.ts +76 -3
  341. package/src/core/resources/index.ts +1 -0
  342. package/src/core/resources/native.ts +481 -0
  343. package/src/core/resources/sampler.ts +46 -1
  344. package/src/core/resources/status.ts +717 -0
  345. package/src/core/resources/system.ts +530 -0
  346. package/src/core/semantic/service.ts +37 -3
  347. package/src/core/storage/builtins.ts +41 -0
  348. package/src/core/supervisor/contract.ts +45 -3
  349. package/src/core/supervisor/findings.ts +159 -0
  350. package/src/core/supervisor/history.ts +15 -0
  351. package/src/core/supervisor/ledger-state.ts +0 -0
  352. package/src/core/supervisor/service.ts +133 -5
  353. package/src/core/supervisor/storage.ts +7 -0
  354. package/src/core/workflow/admission.ts +33 -17
  355. package/src/core/workflow/engine.ts +2 -2
  356. package/src/core/workflow/live-session-v3.ts +6 -8
  357. package/src/core/workflow/proof.ts +4 -3
  358. package/src/lib/browser/capture-fidelity.ts +23 -0
  359. package/src/lib/browser/client.ts +96 -44
  360. package/src/lib/browser/index.ts +15 -1
  361. package/src/lib/browser/page-review-budget.ts +309 -0
  362. package/src/lib/browser/page-review-contracts.ts +129 -0
  363. package/src/lib/browser/page-review-evidence.ts +465 -0
  364. package/src/lib/browser/page-review-judge.ts +56 -40
  365. package/src/lib/browser/page-review-pack.ts +181 -43
  366. package/src/lib/browser/page-review-source.ts +30 -0
  367. package/src/lib/browser/qa-run-contracts.ts +62 -18
  368. package/src/lib/browser/qa-run.ts +259 -71
  369. package/src/lib/browser/qa-snapshot.ts +289 -48
  370. package/src/lib/browser/review-capture-transaction.ts +106 -0
  371. package/src/lib/browser/standalone-html.ts +4 -2
  372. package/src/lib/browser/thumbnail-association.ts +190 -0
  373. package/src/lib/browser/tiling.ts +63 -0
  374. package/src/lib/docs-metadata-managed.ts +4 -1
  375. package/src/lib/identities/assume.ts +12 -4
  376. package/src/lib/instructions/templates.ts +1 -0
  377. package/src/lib/local-file-url.ts +17 -2
  378. package/src/lib/tunnel/state.ts +70 -13
@@ -8,16 +8,15 @@
8
8
  * - **Claude Code**: `{hookSpecificOutput: {hookEventName, additionalContext}}`
9
9
  * for SessionStart / UserPromptSubmit / SubagentStart; deny uses
10
10
  * `{hookSpecificOutput: {hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason}}`.
11
- * - **Cursor**: `{additional_context, env?}` flat for sessionStart and other
12
- * context-capable events. Its current beforeSubmitPrompt schema can validate
13
- * or block but cannot inject context, so UserPromptSubmit output is skipped.
14
- * Deny uses `{permission: "deny", agent_message, user_message}`.
11
+ * - **Cursor**: `{additional_context}` flat for context-capable events,
12
+ * including beforeSubmitPrompt. Deny uses
13
+ * `{permission: "deny", agent_message, user_message}`.
15
14
  * - **Codex**: structurally identical to Claude Code for context and tool
16
15
  * denials. Stop blocks are deliberately suppressed because their automatic
17
16
  * continuation can replace a completed user-facing answer.
18
17
  *
19
18
  * Every helper writes to process.stdout + newline-terminates so callers can
20
- * fire-and-forget. Empty text → no-op (no JSON written).
19
+ * fire-and-forget. Empty text is a no-op.
21
20
  */
22
21
 
23
22
  import type { Adapter } from "../../adapter.ts";
@@ -31,23 +30,17 @@ export type SystemEvent =
31
30
  | "PreToolUse"
32
31
  | "PostToolUse";
33
32
 
34
- /**
35
- * Whether this adapter can actually receive injected context for an event.
36
- * Cursor's beforeSubmitPrompt hook can allow or block a turn but cannot inject
37
- * model context, so anything rendered for that event is discarded. A caller
38
- * that consumes state to build the text (draining a mailbox, for instance)
39
- * must check this first, or the state is spent on output nobody reads.
40
- */
41
- export function canReceiveContext(adapter: Adapter, event: SystemEvent): boolean {
42
- return !(adapter === "cursor" && event === "UserPromptSubmit");
33
+ export interface StopOutputOptions {
34
+ /** Existing coordination verdict. Omit when that check passed. */
35
+ verdict?: { reason?: string; rule: string };
43
36
  }
44
37
 
45
38
  /** Emit a context-injection (peer table, wiring check, council pending, …). */
46
- export function emitContext(adapter: Adapter, event: SystemEvent, text: string): void {
47
- if (!text || text.length === 0) return;
48
- if (!canReceiveContext(adapter, event)) return;
39
+ export function emitContext(adapter: Adapter, event: SystemEvent, text: string): boolean {
40
+ if (!text) return false;
49
41
  const json = buildContextJson(adapter, event, text);
50
42
  process.stdout.write(`${JSON.stringify(json)}\n`);
43
+ return true;
51
44
  }
52
45
 
53
46
  /** Emit a PreToolUse deny: blocks the tool call with `reason` shown to the model. */
@@ -83,26 +76,32 @@ export function emitStopBlock(
83
76
  adapter: Adapter,
84
77
  verdict: { reason?: string; rule: string },
85
78
  coordRoot?: string,
79
+ ): 0 | 2 {
80
+ return emitStopOutcome(adapter, { verdict }, coordRoot);
81
+ }
82
+
83
+ /**
84
+ * Emit the adapter-specific response for one Stop outcome.
85
+ */
86
+ export function emitStopOutcome(
87
+ adapter: Adapter,
88
+ options: StopOutputOptions,
89
+ coordRoot?: string,
86
90
  ): 0 | 2 {
87
91
  if (adapter === "codex") return 0;
88
92
 
89
- const reason = verdict.reason ?? "End-of-turn coordination ritual incomplete.";
93
+ const verdict = options.verdict;
94
+ if (!verdict) return 0;
95
+
90
96
  if (adapter === "cursor") {
91
- // The marker leads the message so the Stop verdict can recognize the turn
92
- // Cursor opens from it (`STOP_REMEDIATION_MARKER`), and so the operator can
93
- // see in chat that the message came from Harnery rather than from them.
94
- // Both commands are named because one message that repairs the whole ritual
95
- // ends the chain in a single followup; the failing rule is context.
96
- const bin = resolveBinName(coordRoot);
97
- const statusCommand = endOfTurnStatusCommand(coordRoot);
98
- const message = [
99
- `${STOP_REMEDIATION_MARKER} rule=${verdict.rule}]`,
100
- reason,
101
- `Repair the ritual in this turn: run \`${bin} agents set-task "<short focus>"\` and then \`${statusCommand}\` as your last tool call.`,
102
- ].join("\n");
103
- process.stdout.write(`${JSON.stringify({ followup_message: message })}\n`);
97
+ process.stdout.write(
98
+ `${JSON.stringify({ followup_message: cursorCoordinationRemediation(verdict, coordRoot) })}\n`,
99
+ );
104
100
  return 0;
105
101
  }
102
+
103
+ if (!verdict) return 0;
104
+ const reason = verdict.reason ?? "End-of-turn coordination ritual incomplete.";
106
105
  // Claude Code re-prompts inside one native Stop remediation cycle, but tools
107
106
  // run after the first terminal are recorded in recovered telemetry turns.
108
107
  // Name the whole ritual so one continuation can repair every required signal.
@@ -113,17 +112,32 @@ export function emitStopBlock(
113
112
  return 2;
114
113
  }
115
114
 
115
+ function cursorCoordinationRemediation(
116
+ verdict: { reason?: string; rule: string },
117
+ coordRoot?: string,
118
+ ): string {
119
+ const reason = verdict.reason ?? "End-of-turn coordination ritual incomplete.";
120
+ // The marker leads the message so the Stop verdict can recognize the turn
121
+ // Cursor opens from it (`STOP_REMEDIATION_MARKER`), and so the operator can
122
+ // see in chat that the message came from Harnery rather than from them.
123
+ // Both commands are named because one message that repairs the whole ritual
124
+ // ends the chain in a single followup; the failing rule is context.
125
+ const bin = resolveBinName(coordRoot);
126
+ const statusCommand = endOfTurnStatusCommand(coordRoot);
127
+ const message = [
128
+ `${STOP_REMEDIATION_MARKER} rule=${verdict.rule}]`,
129
+ reason,
130
+ `Repair the ritual in this turn: run \`${bin} agents set-task "<short focus>"\` and then \`${statusCommand}\` as your last tool call.`,
131
+ ].join("\n");
132
+ return message;
133
+ }
134
+
116
135
  function buildContextJson(
117
136
  adapter: Adapter,
118
137
  event: SystemEvent,
119
138
  text: string,
120
139
  ): Record<string, unknown> {
121
140
  if (adapter === "cursor") {
122
- // Cursor uses a flat top-level key + an env block that survives across the
123
- // session. The dispatcher historically also wrote
124
- // `env: {HARNERY_AGENT_COORD_ADAPTER, HARNERY_AGENT_COORD_PLATFORM}`. These are
125
- // observer hints, not load-bearing; agent-hook + agent-coord recover the
126
- // adapter from event metadata. Drop them.
127
141
  return { additional_context: text };
128
142
  }
129
143
  // Claude Code + Codex share the `hookSpecificOutput` envelope.
@@ -0,0 +1,147 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
3
+ import { hostname } from "node:os";
4
+ import { dirname, join, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { parseBackupDuration, readHostSnapshotCache } from "../backup/host-snapshot.ts";
7
+ import { backupConfig } from "../config.ts";
8
+
9
+ /**
10
+ * Detached runner for the scheduled snapshot. It owns no inherited stdio: a
11
+ * hook that hands its stderr pipe to a background child keeps the harness
12
+ * waiting until restic and the remote provider finish, which is the delay the
13
+ * schedule exists to avoid. Output goes to the log; the exit code goes to the
14
+ * status file the next session start reads.
15
+ */
16
+ const RUNNER = `
17
+ harn_bin="$1"
18
+ if_stale="$2"
19
+ log_file="$3"
20
+ status_file="$4"
21
+ shift 4
22
+ stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; }
23
+ if [ -f "$log_file" ] && [ "$(wc -c <"$log_file")" -gt 262144 ]; then
24
+ tail -c 65536 "$log_file" >"$log_file.rotating" && mv "$log_file.rotating" "$log_file"
25
+ fi
26
+ printf '%s scheduled snapshot start (if-stale %s)\\n' "$(stamp)" "$if_stale" >>"$log_file"
27
+ "$harn_bin" backup snapshot --if-stale "$if_stale" "$@" >>"$log_file" 2>&1
28
+ status=$?
29
+ printf '%s scheduled snapshot exit %s\\n' "$(stamp)" "$status" >>"$log_file"
30
+ printf '{"exit_code":%s,"finished_at":"%s"}\\n' "$status" "$(stamp)" >"$status_file.tmp" && mv "$status_file.tmp" "$status_file"
31
+ exit "$status"
32
+ `.trim();
33
+
34
+ export interface ScheduledBackupInvocation {
35
+ harnBin: string;
36
+ ifStale: string;
37
+ tags: readonly string[];
38
+ logFile: string;
39
+ statusFile: string;
40
+ }
41
+
42
+ export interface ScheduledBackupStatus {
43
+ exitCode: number;
44
+ finishedAt: string;
45
+ }
46
+
47
+ export interface ScheduledBackupPlan {
48
+ /** `disabled`: no schedule; `fresh`: local cache proves this host is current; `launch`: run the snapshot. */
49
+ action: "disabled" | "fresh" | "launch";
50
+ /** One line for the session context when the previous scheduled run failed. */
51
+ cue: string | null;
52
+ invocation: ScheduledBackupInvocation | null;
53
+ }
54
+
55
+ export function scheduledBackupInvocation(coordRoot: string): ScheduledBackupInvocation | null {
56
+ const schedule = backupConfig(coordRoot).schedule;
57
+ if (!schedule) return null;
58
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
59
+ const logsDir = join(resolve(coordRoot), ".harnery", "logs");
60
+ return {
61
+ harnBin: join(packageRoot, "bin", "harn"),
62
+ ifStale: schedule.ifStale,
63
+ tags: schedule.tags,
64
+ logFile: join(logsDir, "backup-schedule.log"),
65
+ statusFile: join(logsDir, "backup-schedule.status.json"),
66
+ };
67
+ }
68
+
69
+ export function readScheduledBackupStatus(statusFile: string): ScheduledBackupStatus | null {
70
+ if (!existsSync(statusFile)) return null;
71
+ try {
72
+ const parsed = JSON.parse(readFileSync(statusFile, "utf8")) as {
73
+ exit_code?: unknown;
74
+ finished_at?: unknown;
75
+ };
76
+ if (typeof parsed.exit_code !== "number" || typeof parsed.finished_at !== "string") {
77
+ return null;
78
+ }
79
+ return { exitCode: parsed.exit_code, finishedAt: parsed.finished_at };
80
+ } catch {
81
+ return null;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Decide what session start should do. The local host cache written by
87
+ * `harn backup snapshot` is only an optimisation: when it is missing, stale,
88
+ * or from another host, the launched command still asks restic. A failed
89
+ * previous run always relaunches so a transient error heals on the next
90
+ * session instead of waiting out the freshness window.
91
+ */
92
+ export function planScheduledBackup(coordRoot: string, now = Date.now()): ScheduledBackupPlan {
93
+ const invocation = scheduledBackupInvocation(coordRoot);
94
+ if (!invocation) return { action: "disabled", cue: null, invocation: null };
95
+ const status = readScheduledBackupStatus(invocation.statusFile);
96
+ const failed = status !== null && status.exitCode !== 0;
97
+ const cue = failed
98
+ ? `harnery backup: the last scheduled snapshot failed (exit ${status.exitCode} at ${status.finishedAt}); see ${invocation.logFile}. Fix the cause or run \`harn backup snapshot --if-stale ${invocation.ifStale}\` to retry.`
99
+ : null;
100
+ const staleMs = parseBackupDuration(invocation.ifStale);
101
+ const cache = readHostSnapshotCache(join(resolve(coordRoot), ".harnery"));
102
+ const fresh =
103
+ !failed &&
104
+ staleMs !== null &&
105
+ cache !== null &&
106
+ cache.host === hostname() &&
107
+ now - cache.snapshotAt < staleMs;
108
+ return { action: fresh ? "fresh" : "launch", cue, invocation };
109
+ }
110
+
111
+ /** Launch the configured SessionStart snapshot without extending hook latency. */
112
+ export function scheduleBackupSnapshot(coordRoot: string): {
113
+ launched: boolean;
114
+ cue: string | null;
115
+ } {
116
+ const plan = planScheduledBackup(coordRoot);
117
+ if (plan.cue) process.stderr.write(`${plan.cue}\n`);
118
+ if (plan.action !== "launch" || !plan.invocation) return { launched: false, cue: plan.cue };
119
+ const invocation = plan.invocation;
120
+ mkdirSync(dirname(invocation.logFile), { recursive: true });
121
+ const tagArgs = invocation.tags.flatMap((tag) => ["--tag", tag]);
122
+ const child = spawn(
123
+ "bash",
124
+ [
125
+ "-c",
126
+ RUNNER,
127
+ "harnery-backup",
128
+ invocation.harnBin,
129
+ invocation.ifStale,
130
+ invocation.logFile,
131
+ invocation.statusFile,
132
+ ...tagArgs,
133
+ ],
134
+ {
135
+ cwd: resolve(coordRoot),
136
+ detached: true,
137
+ stdio: "ignore",
138
+ },
139
+ );
140
+ child.once("error", () => {
141
+ process.stderr.write(
142
+ `harnery backup: scheduled snapshot could not start; see ${invocation.logFile}\n`,
143
+ );
144
+ });
145
+ child.unref();
146
+ return { launched: true, cue: plan.cue };
147
+ }
@@ -56,7 +56,12 @@ import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.
56
56
  import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.ts";
57
57
  import { assignName } from "../agents/state/names.ts";
58
58
  import { writePidmapRow } from "../agents/state/pidmap.ts";
59
- import { agentsRequireGitFinalization, resolveBinName } from "../config.ts";
59
+ import {
60
+ agentsRequireGitFinalization,
61
+ coordFreshnessSeconds,
62
+ hostPromptContextConfig,
63
+ resolveBinName,
64
+ } from "../config.ts";
60
65
  import {
61
66
  checkpointContext,
62
67
  completeContextRecovery,
@@ -89,6 +94,7 @@ import {
89
94
  parsePayload,
90
95
  } from "./adapter/parse.ts";
91
96
  import { discoverCodexSessionTranscript } from "./adapter/runtime-telemetry.ts";
97
+ import { scheduleBackupSnapshot } from "./backup-schedule.ts";
92
98
  import {
93
99
  codexWslFileLinkTelemetry,
94
100
  inspectCodexWslBridge,
@@ -246,7 +252,10 @@ function assignNameInProcess(
246
252
  forkedFrom?: string,
247
253
  ): { name: string; kind: string } | null {
248
254
  try {
249
- const name = assignName(coordRoot, instanceId, kind, forkedFrom ? { forkedFrom } : undefined);
255
+ const name = assignName(coordRoot, instanceId, kind, {
256
+ freshnessSecs: coordFreshnessSeconds(coordRoot),
257
+ ...(forkedFrom ? { forkedFrom } : {}),
258
+ });
250
259
  return { name, kind };
251
260
  } catch {
252
261
  return null;
@@ -834,6 +843,11 @@ async function main(): Promise<number> {
834
843
 
835
844
  const sessionId = payload?.session_id ?? payload?.conversation_id ?? owner.instance_id;
836
845
  const priorCoordination = readHeartbeat(coordRoot, owner.instance_id);
846
+ const topLevelSession =
847
+ coordEnv("WORKFLOW_CHILD") !== "1" &&
848
+ priorCoordination?.kind !== "subagent" &&
849
+ priorCoordination?.kind !== "transient" &&
850
+ !priorCoordination?.workflow_run_id;
837
851
  if (
838
852
  norm.event_type !== "session.ended" &&
839
853
  coordEnv("WORKFLOW_CHILD") !== "1" &&
@@ -1074,6 +1088,16 @@ async function main(): Promise<number> {
1074
1088
  // Adapter-agnostic since v0.5.0; replaces the previous bash UX layer
1075
1089
  // and the equivalent per-adapter bash session_start handlers.
1076
1090
  if (norm.event_type === "session.started") {
1091
+ // A configured backup runs out of process and is freshness-gated per host.
1092
+ // Startup never waits for restic or a remote provider; the child owns no
1093
+ // hook stdio, so the harness is not held open until it finishes. A failed
1094
+ // previous run surfaces as one line in this session's context.
1095
+ let backupCue = "";
1096
+ try {
1097
+ backupCue = scheduleBackupSnapshot(coordRoot).cue ?? "";
1098
+ } catch (err) {
1099
+ logError(coordRoot, err, { phase: "backup-schedule" });
1100
+ }
1077
1101
  // Effect (claude-code): prune stale journal archives + sweep orphans.
1078
1102
  // The recovery-cue is merged into the
1079
1103
  // session-start additionalContext inside emitSessionStartSystemMessage.
@@ -1141,6 +1165,7 @@ async function main(): Promise<number> {
1141
1165
  data,
1142
1166
  adapter,
1143
1167
  recovery?.briefing ?? "",
1168
+ backupCue,
1144
1169
  );
1145
1170
  if (injected && recovery) {
1146
1171
  completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, recovery);
@@ -1240,6 +1265,29 @@ async function main(): Promise<number> {
1240
1265
  logError(coordRoot, err, { phase: "context-recovery-user-prompt" });
1241
1266
  }
1242
1267
  }
1268
+ let hostPromptContext = "";
1269
+ const hostPromptEnabled = hostPromptContextConfig(coordRoot)?.enabled === true;
1270
+ if (hostPromptEnabled && topLevelSession && !stopRemediation) {
1271
+ try {
1272
+ const { runPromptContext } = await import("./prompt-context/runner.ts");
1273
+ const result = await runPromptContext({
1274
+ coordRoot,
1275
+ adapter,
1276
+ sessionId,
1277
+ turnId: payload?.turn_id ?? v3EventId ?? sessionId,
1278
+ cwd: payload?.cwd ?? process.cwd(),
1279
+ prompt: payload?.prompt ?? "",
1280
+ });
1281
+ appendDebug(coordRoot, {
1282
+ ...debugBase,
1283
+ effect: "prompt-context",
1284
+ ...result.audit,
1285
+ });
1286
+ hostPromptContext = result.context ?? "";
1287
+ } catch (err) {
1288
+ logError(coordRoot, err, { phase: "prompt-context-user-prompt" });
1289
+ }
1290
+ }
1243
1291
  try {
1244
1292
  const injected = await emitUserPromptSubmitSystemMessage(
1245
1293
  coordRoot,
@@ -1248,6 +1296,7 @@ async function main(): Promise<number> {
1248
1296
  adapter,
1249
1297
  payload?.cwd,
1250
1298
  recovery?.briefing ?? "",
1299
+ hostPromptContext,
1251
1300
  );
1252
1301
  if (injected && recovery) {
1253
1302
  completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, recovery);
@@ -1311,10 +1360,9 @@ async function main(): Promise<number> {
1311
1360
  } else {
1312
1361
  // Adapter-aware enforcement channel: Claude Code honors exit-2 + stderr
1313
1362
  // as a turn block; Cursor ignores exit codes and re-prompts only via a
1314
- // `followup_message` it auto-submits. Codex returned observe-only above.
1315
- // emitStopBlock writes the right shape and returns the exit code to use.
1316
- const { emitStopBlock } = await import("./adapter/output.ts");
1317
- return emitStopBlock(adapter, verdict, coordRoot);
1363
+ // `followup_message` it auto-submits.
1364
+ const { emitStopOutcome } = await import("./adapter/output.ts");
1365
+ return emitStopOutcome(adapter, { verdict }, coordRoot);
1318
1366
  }
1319
1367
  } else {
1320
1368
  const { clearRemediationCount } = await import("./remediation-cap.ts");
@@ -1906,16 +1954,16 @@ async function emitUserPromptSubmitSystemMessage(
1906
1954
  adapter: Adapter,
1907
1955
  workspaceCwd?: string,
1908
1956
  recoveryBriefing = "",
1957
+ hostPromptContext = "",
1909
1958
  ): Promise<boolean> {
1910
1959
  const { renderPromptContext } = await import("../agents/render/prompt-context.ts");
1911
1960
  let additionalContext = renderPromptContext({
1912
1961
  coordRoot,
1913
1962
  instanceId,
1914
1963
  sessionId,
1915
- adapter,
1916
1964
  sessionNameNudge: true,
1917
1965
  taskNudge: adapter === "cursor" || adapter === "codex",
1918
- hostPromptReminder: adapter === "codex",
1966
+ hostPromptReminder: adapter === "codex" || adapter === "cursor",
1919
1967
  statusFooterNudge: adapter === "codex",
1920
1968
  turnRitualNudge: adapter === "claude-code" ? adapter : undefined,
1921
1969
  }).trim();
@@ -1928,11 +1976,13 @@ async function emitUserPromptSubmitSystemMessage(
1928
1976
  if (recoveryBriefing) {
1929
1977
  additionalContext = [additionalContext, recoveryBriefing].filter(Boolean).join("\n\n");
1930
1978
  }
1979
+ if (hostPromptContext) {
1980
+ additionalContext = [additionalContext, hostPromptContext].filter(Boolean).join("\n\n");
1981
+ }
1931
1982
  if (!additionalContext) return false;
1932
1983
 
1933
1984
  const { emitContext } = await import("./adapter/output.ts");
1934
- emitContext(adapter, "UserPromptSubmit", additionalContext);
1935
- return true;
1985
+ return emitContext(adapter, "UserPromptSubmit", additionalContext);
1936
1986
  }
1937
1987
 
1938
1988
  async function emitSubagentStartContext(
@@ -1989,6 +2039,7 @@ async function emitSessionStartSystemMessage(
1989
2039
  emittedData: Record<string, unknown>,
1990
2040
  adapter: Adapter,
1991
2041
  recoveryBriefing = "",
2042
+ backupCue = "",
1992
2043
  ): Promise<boolean> {
1993
2044
  const workflowChild = coordEnv("WORKFLOW_CHILD") === "1";
1994
2045
  let additionalContext = "";
@@ -2026,6 +2077,9 @@ async function emitSessionStartSystemMessage(
2026
2077
  if (recoveryBriefing && !workflowChild) {
2027
2078
  additionalContext = [additionalContext, recoveryBriefing].filter(Boolean).join("\n\n");
2028
2079
  }
2080
+ if (backupCue && !workflowChild) {
2081
+ additionalContext = [additionalContext, backupCue].filter(Boolean).join("\n\n");
2082
+ }
2029
2083
  if (adapter === "codex" && !workflowChild && isWslUncPath(emittedData.cwd)) {
2030
2084
  const fileLinkContext = renderCodexWslFileLinkContext(coordRoot, emittedData.cwd);
2031
2085
  if (fileLinkContext) {
@@ -2041,11 +2095,8 @@ async function emitSessionStartSystemMessage(
2041
2095
  .join("\n\n");
2042
2096
  }
2043
2097
  }
2044
- if (!additionalContext) return false;
2045
-
2046
2098
  const { emitContext } = await import("./adapter/output.ts");
2047
- emitContext(adapter, "SessionStart", additionalContext);
2048
- return true;
2099
+ return emitContext(adapter, "SessionStart", additionalContext);
2049
2100
  }
2050
2101
 
2051
2102
  function completeRecoveryInjection(
@@ -71,10 +71,7 @@ export function codexWslWorkspaceLinkMapping(
71
71
  const parsed = parseWslUncPath(workspaceCwd);
72
72
  const linuxRoot = trimTrailingSlash(coordRootRaw.replace(/\\/g, "/"));
73
73
  if (!parsed || !linuxRoot.startsWith("/")) return null;
74
- const linuxCwd = trimTrailingSlash(parsed.linuxPath);
75
- if (!isWithinOrEqual(linuxCwd, linuxRoot) && !isWithinOrEqual(linuxRoot, linuxCwd)) {
76
- return null;
77
- }
74
+ if (!codexWslWorkspaceLinuxPath(coordRootRaw, workspaceCwd)) return null;
78
75
  return {
79
76
  linuxRoot,
80
77
  hostRoot: `//${parsed.host}/${parsed.distro}${linuxRoot}`,
@@ -82,6 +79,21 @@ export function codexWslWorkspaceLinkMapping(
82
79
  };
83
80
  }
84
81
 
82
+ /** Translate an overlapping WSL UNC workspace into its Linux-native path. */
83
+ export function codexWslWorkspaceLinuxPath(
84
+ coordRootRaw: string,
85
+ workspaceCwd: unknown,
86
+ ): string | null {
87
+ const parsed = parseWslUncPath(workspaceCwd);
88
+ const linuxRoot = trimTrailingSlash(coordRootRaw.replace(/\\/g, "/"));
89
+ if (!parsed || !linuxRoot.startsWith("/")) return null;
90
+ const linuxCwd = trimTrailingSlash(parsed.linuxPath);
91
+ if (!isWithinOrEqual(linuxCwd, linuxRoot) && !isWithinOrEqual(linuxRoot, linuxCwd)) {
92
+ return null;
93
+ }
94
+ return linuxCwd;
95
+ }
96
+
85
97
  /** Fresh adapter context for the model. Shell paths stay Linux-native; only
86
98
  * Markdown destinations use the host-visible root. */
87
99
  export function renderCodexWslFileLinkContext(coordRoot: string, workspaceCwd: unknown): string {
@@ -90,7 +102,11 @@ export function renderCodexWslFileLinkContext(coordRoot: string, workspaceCwd: u
90
102
  return (
91
103
  "Codex WSL file links: this task is hosted by Windows while tools run inside WSL. " +
92
104
  `For clickable local-file Markdown links, replace the Linux workspace root \`${mapping.linuxRoot}\` with the host-visible root \`${mapping.hostRoot}\`. ` +
93
- `Example: \`[label](<${mapping.hostRoot}/path/to/file>)\`. ` +
105
+ `Example: \`[label](${mapping.hostRoot}/path/to/file)\`. ` +
106
+ "Percent-encode a space as %20 and a parenthesis as %28 or %29 in the link, " +
107
+ "and do not wrap the destination in angle brackets: that form is valid " +
108
+ "Markdown but some renderers style it as a link without keeping the target, " +
109
+ "so it looks clickable and does nothing. " +
94
110
  "Keep Linux paths unchanged in shell commands and tool inputs."
95
111
  );
96
112
  }
@@ -7,3 +7,4 @@
7
7
  export type { Adapter } from "../adapter.ts";
8
8
  export type { EventV3 as Event } from "../events/v3/contract.ts";
9
9
  export { EventV3Schema } from "../events/v3/contract.ts";
10
+ export * from "./prompt-context/index.ts";