harnery 0.29.0 → 0.31.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 (512) hide show
  1. package/README.md +4 -4
  2. package/dist/commander.d.ts +8 -0
  3. package/dist/commander.d.ts.map +1 -1
  4. package/dist/commander.js +14 -13
  5. package/dist/commands/adapter.d.ts +12 -0
  6. package/dist/commands/adapter.d.ts.map +1 -0
  7. package/dist/commands/{harness.js → adapter.js} +35 -35
  8. package/dist/commands/agents.d.ts +3 -2
  9. package/dist/commands/agents.d.ts.map +1 -1
  10. package/dist/commands/agents.js +61 -60
  11. package/dist/commands/artifacts.d.ts +4 -0
  12. package/dist/commands/artifacts.d.ts.map +1 -0
  13. package/dist/commands/artifacts.js +143 -0
  14. package/dist/commands/backup.d.ts +1 -1
  15. package/dist/commands/backup.d.ts.map +1 -1
  16. package/dist/commands/backup.js +5 -2
  17. package/dist/commands/browse.d.ts.map +1 -1
  18. package/dist/commands/browse.js +310 -7
  19. package/dist/commands/checkpoint.d.ts +12 -0
  20. package/dist/commands/checkpoint.d.ts.map +1 -0
  21. package/dist/commands/checkpoint.js +162 -0
  22. package/dist/commands/context.d.ts +2 -2
  23. package/dist/commands/context.d.ts.map +1 -1
  24. package/dist/commands/context.js +3 -151
  25. package/dist/commands/decision.d.ts.map +1 -1
  26. package/dist/commands/decision.js +31 -7
  27. package/dist/commands/deinit.d.ts +2 -2
  28. package/dist/commands/deinit.js +15 -15
  29. package/dist/commands/doctor.js +23 -23
  30. package/dist/commands/governor.d.ts +4 -0
  31. package/dist/commands/governor.d.ts.map +1 -0
  32. package/dist/commands/{supervisor.js → governor.js} +133 -108
  33. package/dist/commands/init.d.ts +12 -12
  34. package/dist/commands/init.d.ts.map +1 -1
  35. package/dist/commands/init.js +44 -30
  36. package/dist/commands/{session.d.ts → journal.d.ts} +2 -2
  37. package/dist/commands/journal.d.ts.map +1 -0
  38. package/dist/commands/{scratch.js → journal.js} +47 -47
  39. package/dist/commands/policy.js +1 -1
  40. package/dist/commands/presence.js +2 -2
  41. package/dist/commands/sync.d.ts +1 -1
  42. package/dist/commands/sync.js +3 -3
  43. package/dist/commands/tunnel.d.ts +16 -0
  44. package/dist/commands/tunnel.d.ts.map +1 -1
  45. package/dist/commands/tunnel.js +193 -23
  46. package/dist/commands/web-fetch.js +1 -1
  47. package/dist/commands/web.d.ts +19 -0
  48. package/dist/commands/web.d.ts.map +1 -1
  49. package/dist/commands/web.js +51 -0
  50. package/dist/commands/work.d.ts +2 -1
  51. package/dist/commands/work.d.ts.map +1 -1
  52. package/dist/commands/work.js +55 -25
  53. package/dist/commands/workflow.d.ts.map +1 -1
  54. package/dist/commands/workflow.js +35 -28
  55. package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
  56. package/dist/core/adapters/attest-projection.d.ts.map +1 -0
  57. package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
  58. package/dist/core/adapters/attest.d.ts.map +1 -0
  59. package/dist/core/{harnesses → adapters}/attest.js +9 -9
  60. package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
  61. package/dist/core/adapters/attestation.d.ts.map +1 -0
  62. package/dist/core/{harnesses → adapters}/attestation.js +20 -20
  63. package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
  64. package/dist/core/adapters/bench.d.ts.map +1 -0
  65. package/dist/core/{harnesses → adapters}/bench.js +12 -12
  66. package/dist/core/adapters/index.d.ts +13 -0
  67. package/dist/core/adapters/index.d.ts.map +1 -0
  68. package/dist/core/adapters/index.js +6 -0
  69. package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
  70. package/dist/core/adapters/profiles.d.ts.map +1 -0
  71. package/dist/core/{harnesses → adapters}/profiles.js +11 -11
  72. package/dist/core/adapters/registry.d.ts +15 -0
  73. package/dist/core/adapters/registry.d.ts.map +1 -0
  74. package/dist/core/{harnesses → adapters}/registry.js +11 -11
  75. package/dist/core/{harnesses → adapters}/types.d.ts +28 -23
  76. package/dist/core/adapters/types.d.ts.map +1 -0
  77. package/dist/core/{harnesses → adapters}/types.js +1 -1
  78. package/dist/core/agents/canonical-emit.d.ts +4 -4
  79. package/dist/core/agents/canonical-emit.js +5 -5
  80. package/dist/core/agents/cli-emit.js +1 -1
  81. package/dist/core/agents/cli.js +30 -26
  82. package/dist/core/agents/codex-replay.d.ts +1 -1
  83. package/dist/core/agents/codex-replay.js +6 -6
  84. package/dist/core/agents/coord-client.d.ts +21 -2
  85. package/dist/core/agents/coord-client.d.ts.map +1 -1
  86. package/dist/core/agents/coord-client.js +122 -27
  87. package/dist/core/agents/events/consume.d.ts +1 -1
  88. package/dist/core/agents/events/emit.d.ts +5 -6
  89. package/dist/core/agents/events/emit.d.ts.map +1 -1
  90. package/dist/core/agents/events/emit.js +2 -2
  91. package/dist/core/agents/render/prompt-context.d.ts +21 -9
  92. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  93. package/dist/core/agents/render/prompt-context.js +82 -30
  94. package/dist/core/agents/render/session-context.d.ts +1 -1
  95. package/dist/core/agents/render/session-context.js +5 -5
  96. package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
  97. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  98. package/dist/core/agents/rules/claim-conflict.js +1 -1
  99. package/dist/core/agents/rules/commit-conflict.js +98 -22
  100. package/dist/core/agents/rules/stop-hook.d.ts +9 -9
  101. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  102. package/dist/core/agents/rules/stop-hook.js +23 -5
  103. package/dist/core/agents/rules/verdict.d.ts +14 -0
  104. package/dist/core/agents/rules/verdict.d.ts.map +1 -0
  105. package/dist/core/agents/rules/verdict.js +1 -0
  106. package/dist/core/agents/session-events.js +3 -3
  107. package/dist/core/agents/state/council.d.ts +1 -1
  108. package/dist/core/agents/state/council.js +1 -1
  109. package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
  110. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
  111. package/dist/core/agents/state/heartbeat-projector.js +14 -10
  112. package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
  113. package/dist/core/agents/state/heartbeat-writer.js +12 -12
  114. package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
  115. package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
  116. package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
  117. package/dist/core/agents/state/pidmap.d.ts +28 -4
  118. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  119. package/dist/core/agents/state/pidmap.js +130 -15
  120. package/dist/core/agents/state/proc-start.d.ts +95 -0
  121. package/dist/core/agents/state/proc-start.d.ts.map +1 -0
  122. package/dist/core/agents/state/proc-start.js +199 -0
  123. package/dist/core/agents/state/shell-mutation.d.ts +1 -1
  124. package/dist/core/agents/state/shell-mutation.js +1 -1
  125. package/dist/core/agents/state/stale-sweep.js +7 -7
  126. package/dist/core/artifacts/index.d.ts +86 -0
  127. package/dist/core/artifacts/index.d.ts.map +1 -0
  128. package/dist/core/artifacts/index.js +421 -0
  129. package/dist/core/config.d.ts +9 -2
  130. package/dist/core/config.d.ts.map +1 -1
  131. package/dist/core/config.js +26 -2
  132. package/dist/core/context/index.d.ts +12 -12
  133. package/dist/core/context/index.js +10 -10
  134. package/dist/core/governor/adapter-spread.d.ts +52 -0
  135. package/dist/core/governor/adapter-spread.d.ts.map +1 -0
  136. package/dist/core/governor/adapter-spread.js +52 -0
  137. package/dist/core/governor/index.d.ts +7 -0
  138. package/dist/core/governor/index.d.ts.map +1 -0
  139. package/dist/core/governor/index.js +6 -0
  140. package/dist/core/governor/plan-api.d.ts +38 -0
  141. package/dist/core/governor/plan-api.d.ts.map +1 -0
  142. package/dist/core/governor/plan-api.js +83 -0
  143. package/dist/core/governor/plan-read.d.ts +5 -0
  144. package/dist/core/governor/plan-read.d.ts.map +1 -0
  145. package/dist/core/{supervisor → governor}/plan-read.js +71 -51
  146. package/dist/core/governor/plan-types.d.ts +181 -0
  147. package/dist/core/governor/plan-types.d.ts.map +1 -0
  148. package/dist/core/{supervisor → governor}/plan-types.js +4 -4
  149. package/dist/core/governor/planning.d.ts +48 -0
  150. package/dist/core/governor/planning.d.ts.map +1 -0
  151. package/dist/core/{supervisor → governor}/planning.js +143 -94
  152. package/dist/core/governor/read.d.ts +6 -0
  153. package/dist/core/governor/read.d.ts.map +1 -0
  154. package/dist/core/governor/read.js +4 -0
  155. package/dist/core/governor/runner.d.ts +37 -0
  156. package/dist/core/governor/runner.d.ts.map +1 -0
  157. package/dist/core/{supervisor → governor}/runner.js +15 -15
  158. package/dist/core/governor/service-read.d.ts +6 -0
  159. package/dist/core/governor/service-read.d.ts.map +1 -0
  160. package/dist/core/{supervisor → governor}/service-read.js +12 -12
  161. package/dist/core/governor/service.d.ts +114 -0
  162. package/dist/core/governor/service.d.ts.map +1 -0
  163. package/dist/core/{supervisor → governor}/service.js +57 -57
  164. package/dist/core/governor/state.d.ts +116 -0
  165. package/dist/core/governor/state.d.ts.map +1 -0
  166. package/dist/core/{supervisor → governor}/state.js +290 -116
  167. package/dist/core/hooks/adapter/detect.d.ts +9 -0
  168. package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
  169. package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
  170. package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
  171. package/dist/core/hooks/adapter/events.d.ts.map +1 -0
  172. package/dist/core/hooks/{harness → adapter}/events.js +5 -5
  173. package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
  174. package/dist/core/hooks/adapter/output.d.ts.map +1 -0
  175. package/dist/core/hooks/{harness → adapter}/output.js +30 -22
  176. package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
  177. package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
  178. package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
  179. package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
  180. package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
  181. package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
  182. package/dist/core/hooks/cli.d.ts +3 -3
  183. package/dist/core/hooks/cli.js +175 -151
  184. package/dist/core/hooks/effects/image-capture.d.ts +5 -5
  185. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  186. package/dist/core/hooks/effects/image-capture.js +3 -3
  187. package/dist/core/hooks/effects/index.d.ts +12 -12
  188. package/dist/core/hooks/effects/index.d.ts.map +1 -1
  189. package/dist/core/hooks/effects/index.js +17 -17
  190. package/dist/core/hooks/events/emit.d.ts +2 -2
  191. package/dist/core/hooks/events/emit.d.ts.map +1 -1
  192. package/dist/core/hooks/events/emit.js +1 -1
  193. package/dist/core/hooks/events/rotate.js +1 -1
  194. package/dist/core/hooks/events/schema.d.ts +13 -5
  195. package/dist/core/hooks/events/schema.d.ts.map +1 -1
  196. package/dist/core/hooks/guard-path.d.ts +2 -2
  197. package/dist/core/hooks/guard-path.js +2 -2
  198. package/dist/core/hooks/index.d.ts +1 -1
  199. package/dist/core/hooks/index.d.ts.map +1 -1
  200. package/dist/core/hooks/resolve/anchor.d.ts +14 -5
  201. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
  202. package/dist/core/hooks/resolve/anchor.js +64 -7
  203. package/dist/core/hooks/resolve/coord-root.d.ts +3 -3
  204. package/dist/core/hooks/resolve/coord-root.js +4 -4
  205. package/dist/core/hooks/resolve/intent.js +1 -1
  206. package/dist/core/hooks/resolve/owner.d.ts +1 -1
  207. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  208. package/dist/core/hooks/resolve/owner.js +11 -5
  209. package/dist/core/{scratch → journal}/index.d.ts +25 -25
  210. package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
  211. package/dist/core/{scratch → journal}/index.js +38 -38
  212. package/dist/core/policy/evaluate.d.ts +1 -1
  213. package/dist/core/policy/evaluate.d.ts.map +1 -1
  214. package/dist/core/policy/evaluate.js +7 -7
  215. package/dist/core/policy/types.d.ts +3 -3
  216. package/dist/core/policy/types.d.ts.map +1 -1
  217. package/dist/core/work/runner.d.ts.map +1 -1
  218. package/dist/core/work/runner.js +11 -2
  219. package/dist/core/work/state.d.ts +28 -3
  220. package/dist/core/work/state.d.ts.map +1 -1
  221. package/dist/core/work/state.js +148 -16
  222. package/dist/core/workflow/adapters.d.ts +17 -0
  223. package/dist/core/workflow/adapters.d.ts.map +1 -0
  224. package/dist/core/workflow/adapters.js +21 -0
  225. package/dist/core/workflow/approvals.js +6 -6
  226. package/dist/core/workflow/billing.d.ts +9 -9
  227. package/dist/core/workflow/billing.js +9 -9
  228. package/dist/core/workflow/child-env.d.ts +10 -2
  229. package/dist/core/workflow/child-env.d.ts.map +1 -1
  230. package/dist/core/workflow/child-env.js +12 -4
  231. package/dist/core/workflow/engine.d.ts +15 -5
  232. package/dist/core/workflow/engine.d.ts.map +1 -1
  233. package/dist/core/workflow/engine.js +151 -83
  234. package/dist/core/workflow/evidence-preflight.d.ts +24 -0
  235. package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
  236. package/dist/core/workflow/evidence-preflight.js +134 -0
  237. package/dist/core/workflow/index.d.ts +3 -2
  238. package/dist/core/workflow/index.d.ts.map +1 -1
  239. package/dist/core/workflow/index.js +2 -1
  240. package/dist/core/workflow/proof.d.ts +28 -5
  241. package/dist/core/workflow/proof.d.ts.map +1 -1
  242. package/dist/core/workflow/proof.js +77 -34
  243. package/dist/core/workflow/run-state.d.ts +1 -1
  244. package/dist/core/workflow/run-state.js +7 -7
  245. package/dist/core/workflow/sandbox-projection.d.ts +6 -6
  246. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  247. package/dist/core/workflow/sandbox-projection.js +11 -11
  248. package/dist/core/workflow/spawn-claude.d.ts +3 -3
  249. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  250. package/dist/core/workflow/spawn-claude.js +28 -8
  251. package/dist/core/workflow/spawn-codex.d.ts +4 -4
  252. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  253. package/dist/core/workflow/spawn-codex.js +26 -8
  254. package/dist/core/workflow/spawn-cursor.d.ts +4 -4
  255. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  256. package/dist/core/workflow/spawn-cursor.js +27 -8
  257. package/dist/core/workflow/spawn-failure.d.ts +15 -1
  258. package/dist/core/workflow/spawn-failure.d.ts.map +1 -1
  259. package/dist/core/workflow/spawn-failure.js +35 -1
  260. package/dist/core/workflow/specialists.js +2 -2
  261. package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
  262. package/dist/core/workflow/transcript.d.ts.map +1 -0
  263. package/dist/core/workflow/{journal.js → transcript.js} +14 -14
  264. package/dist/core/workflow/types.d.ts +119 -46
  265. package/dist/core/workflow/types.d.ts.map +1 -1
  266. package/dist/core/workflow/types.js +11 -1
  267. package/dist/core/workflow/validate.d.ts +1 -1
  268. package/dist/core/workflow/validate.js +1 -1
  269. package/dist/core/workflow/workspaces/cancellation.js +2 -2
  270. package/dist/core/workflow/workspaces/cleanup.js +2 -2
  271. package/dist/core/workflow/workspaces/execution.js +6 -6
  272. package/dist/core/workflow/workspaces/inspect.js +9 -9
  273. package/dist/core/workflow/workspaces/integration.js +14 -14
  274. package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
  275. package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
  276. package/dist/core/workflow/workspaces/lifecycle.js +9 -9
  277. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  278. package/dist/core/workflow/workspaces/local-git.js +39 -5
  279. package/dist/core/workflow/workspaces/recovery.js +3 -3
  280. package/dist/core/workflow/workspaces/state.d.ts +1 -1
  281. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  282. package/dist/core/workflow/workspaces/state.js +3 -3
  283. package/dist/core/workflow/workspaces/types.d.ts +1 -1
  284. package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
  285. package/dist/lib/browser/asserts.d.ts +28 -0
  286. package/dist/lib/browser/asserts.d.ts.map +1 -0
  287. package/dist/lib/browser/asserts.js +152 -0
  288. package/dist/lib/browser/client.d.ts +49 -0
  289. package/dist/lib/browser/client.d.ts.map +1 -1
  290. package/dist/lib/browser/client.js +155 -14
  291. package/dist/lib/browser/content-checks.d.ts +108 -0
  292. package/dist/lib/browser/content-checks.d.ts.map +1 -0
  293. package/dist/lib/browser/content-checks.js +474 -0
  294. package/dist/lib/browser/critique.d.ts +91 -0
  295. package/dist/lib/browser/critique.d.ts.map +1 -0
  296. package/dist/lib/browser/critique.js +167 -0
  297. package/dist/lib/browser/geometry.d.ts +32 -0
  298. package/dist/lib/browser/geometry.d.ts.map +1 -1
  299. package/dist/lib/browser/geometry.js +244 -1
  300. package/dist/lib/browser/index.d.ts +4 -1
  301. package/dist/lib/browser/index.d.ts.map +1 -1
  302. package/dist/lib/browser/index.js +2 -0
  303. package/dist/lib/claude-desktop.d.ts.map +1 -1
  304. package/dist/lib/claude-desktop.js +4 -1
  305. package/dist/lib/council/index.d.ts +6 -6
  306. package/dist/lib/council/index.d.ts.map +1 -1
  307. package/dist/lib/council/index.js +8 -8
  308. package/dist/lib/exec.d.ts +7 -0
  309. package/dist/lib/exec.d.ts.map +1 -1
  310. package/dist/lib/exec.js +6 -3
  311. package/dist/lib/identities/assume.d.ts +2 -2
  312. package/dist/lib/identities/assume.js +7 -7
  313. package/dist/lib/instructions/apply.d.ts +3 -3
  314. package/dist/lib/instructions/apply.d.ts.map +1 -1
  315. package/dist/lib/instructions/apply.js +75 -27
  316. package/dist/lib/instructions/host-addendum.d.ts +54 -0
  317. package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
  318. package/dist/lib/instructions/host-addendum.js +107 -0
  319. package/dist/lib/instructions/templates.d.ts +10 -3
  320. package/dist/lib/instructions/templates.d.ts.map +1 -1
  321. package/dist/lib/instructions/templates.js +41 -12
  322. package/dist/lib/machine.d.ts +2 -2
  323. package/dist/lib/machine.js +2 -2
  324. package/package.json +26 -21
  325. package/schemas/config.schema.json +26 -1
  326. package/src/commander.ts +22 -13
  327. package/src/commands/{harness.ts → adapter.ts} +46 -46
  328. package/src/commands/agents.ts +71 -64
  329. package/src/commands/artifacts.ts +168 -0
  330. package/src/commands/backup.ts +47 -33
  331. package/src/commands/browse.ts +438 -2
  332. package/src/commands/checkpoint.ts +196 -0
  333. package/src/commands/context.ts +3 -176
  334. package/src/commands/decision.ts +41 -7
  335. package/src/commands/deinit.ts +16 -16
  336. package/src/commands/doctor.ts +28 -28
  337. package/src/commands/{supervisor.ts → governor.ts} +184 -154
  338. package/src/commands/init.ts +50 -34
  339. package/src/commands/{scratch.ts → journal.ts} +60 -60
  340. package/src/commands/policy.ts +1 -1
  341. package/src/commands/presence.ts +2 -2
  342. package/src/commands/sync.ts +3 -3
  343. package/src/commands/tunnel.ts +237 -34
  344. package/src/commands/web-fetch.ts +1 -1
  345. package/src/commands/web.ts +56 -1
  346. package/src/commands/work.ts +72 -38
  347. package/src/commands/workflow.ts +43 -34
  348. package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
  349. package/src/core/{harnesses → adapters}/attest.ts +27 -27
  350. package/src/core/{harnesses → adapters}/attestation.ts +41 -41
  351. package/src/core/{harnesses → adapters}/bench.ts +34 -43
  352. package/src/core/adapters/index.ts +56 -0
  353. package/src/core/{harnesses → adapters}/profiles.ts +16 -16
  354. package/src/core/{harnesses → adapters}/registry.ts +23 -23
  355. package/src/core/{harnesses → adapters}/types.ts +28 -23
  356. package/src/core/agents/canonical-emit.ts +6 -6
  357. package/src/core/agents/cli-emit.ts +1 -1
  358. package/src/core/agents/cli.ts +30 -28
  359. package/src/core/agents/codex-replay.ts +6 -6
  360. package/src/core/agents/coord-client.ts +119 -28
  361. package/src/core/agents/events/consume.ts +1 -1
  362. package/src/core/agents/events/emit.ts +7 -6
  363. package/src/core/agents/render/prompt-context.ts +107 -31
  364. package/src/core/agents/render/session-context.ts +6 -6
  365. package/src/core/agents/rules/claim-conflict.ts +4 -7
  366. package/src/core/agents/rules/commit-conflict.ts +103 -22
  367. package/src/core/agents/rules/stop-hook.ts +33 -17
  368. package/src/core/agents/rules/verdict.ts +13 -0
  369. package/src/core/agents/session-events.ts +4 -4
  370. package/src/core/agents/state/council.ts +1 -1
  371. package/src/core/agents/state/heartbeat-projector.ts +16 -12
  372. package/src/core/agents/state/heartbeat-writer.ts +12 -12
  373. package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
  374. package/src/core/agents/state/pidmap.ts +130 -15
  375. package/src/core/agents/state/proc-start.ts +208 -0
  376. package/src/core/agents/state/shell-mutation.ts +1 -1
  377. package/src/core/agents/state/stale-sweep.ts +7 -7
  378. package/src/core/artifacts/index.ts +557 -0
  379. package/src/core/config.ts +30 -2
  380. package/src/core/context/index.ts +15 -15
  381. package/src/core/governor/adapter-spread.ts +82 -0
  382. package/src/core/governor/index.ts +91 -0
  383. package/src/core/governor/plan-api.ts +115 -0
  384. package/src/core/{supervisor → governor}/plan-read.ts +120 -96
  385. package/src/core/{supervisor → governor}/plan-types.ts +64 -50
  386. package/src/core/{supervisor → governor}/planning.ts +240 -188
  387. package/src/core/governor/read.ts +59 -0
  388. package/src/core/{supervisor → governor}/runner.ts +39 -39
  389. package/src/core/{supervisor → governor}/service-read.ts +22 -22
  390. package/src/core/{supervisor → governor}/service.ts +117 -119
  391. package/src/core/{supervisor → governor}/state.ts +389 -174
  392. package/src/core/hooks/adapter/detect.ts +30 -0
  393. package/src/core/hooks/{harness → adapter}/events.ts +16 -14
  394. package/src/core/hooks/{harness → adapter}/output.ts +31 -23
  395. package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
  396. package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
  397. package/src/core/hooks/cli.ts +185 -162
  398. package/src/core/hooks/effects/image-capture.ts +6 -6
  399. package/src/core/hooks/effects/index.ts +17 -17
  400. package/src/core/hooks/events/emit.ts +3 -3
  401. package/src/core/hooks/events/rotate.ts +1 -1
  402. package/src/core/hooks/events/schema.ts +15 -7
  403. package/src/core/hooks/guard-path.ts +2 -2
  404. package/src/core/hooks/index.ts +1 -1
  405. package/src/core/hooks/resolve/anchor.ts +63 -8
  406. package/src/core/hooks/resolve/coord-root.ts +4 -4
  407. package/src/core/hooks/resolve/intent.ts +1 -1
  408. package/src/core/hooks/resolve/owner.ts +11 -5
  409. package/src/core/{scratch → journal}/index.ts +53 -53
  410. package/src/core/policy/evaluate.ts +8 -8
  411. package/src/core/policy/types.ts +3 -3
  412. package/src/core/work/runner.ts +11 -2
  413. package/src/core/work/state.ts +185 -21
  414. package/src/core/workflow/adapters.ts +33 -0
  415. package/src/core/workflow/approvals.ts +7 -7
  416. package/src/core/workflow/billing.ts +12 -12
  417. package/src/core/workflow/child-env.ts +13 -4
  418. package/src/core/workflow/engine.ts +166 -90
  419. package/src/core/workflow/evidence-preflight.ts +165 -0
  420. package/src/core/workflow/index.ts +6 -3
  421. package/src/core/workflow/proof.ts +94 -48
  422. package/src/core/workflow/run-state.ts +7 -7
  423. package/src/core/workflow/sandbox-projection.ts +16 -16
  424. package/src/core/workflow/spawn-claude.ts +34 -12
  425. package/src/core/workflow/spawn-codex.ts +30 -12
  426. package/src/core/workflow/spawn-cursor.ts +31 -12
  427. package/src/core/workflow/spawn-failure.ts +41 -1
  428. package/src/core/workflow/specialists.ts +2 -2
  429. package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
  430. package/src/core/workflow/types.ts +130 -46
  431. package/src/core/workflow/validate.ts +1 -1
  432. package/src/core/workflow/workspaces/cancellation.ts +2 -2
  433. package/src/core/workflow/workspaces/cleanup.ts +2 -2
  434. package/src/core/workflow/workspaces/execution.ts +6 -6
  435. package/src/core/workflow/workspaces/inspect.ts +14 -11
  436. package/src/core/workflow/workspaces/integration.ts +18 -14
  437. package/src/core/workflow/workspaces/lifecycle.ts +10 -10
  438. package/src/core/workflow/workspaces/local-git.ts +47 -5
  439. package/src/core/workflow/workspaces/recovery.ts +3 -3
  440. package/src/core/workflow/workspaces/state.ts +4 -3
  441. package/src/core/workflow/workspaces/types.ts +1 -1
  442. package/src/lib/browser/asserts.ts +177 -0
  443. package/src/lib/browser/client.ts +189 -14
  444. package/src/lib/browser/content-checks.ts +571 -0
  445. package/src/lib/browser/critique.ts +231 -0
  446. package/src/lib/browser/geometry.ts +297 -1
  447. package/src/lib/browser/index.ts +34 -0
  448. package/src/lib/claude-desktop.ts +4 -1
  449. package/src/lib/council/index.ts +9 -9
  450. package/src/lib/exec.ts +13 -3
  451. package/src/lib/identities/assume.ts +7 -7
  452. package/src/lib/instructions/apply.ts +87 -25
  453. package/src/lib/instructions/host-addendum.ts +126 -0
  454. package/src/lib/instructions/templates.ts +44 -15
  455. package/src/lib/machine.ts +2 -2
  456. package/dist/commands/harness.d.ts +0 -12
  457. package/dist/commands/harness.d.ts.map +0 -1
  458. package/dist/commands/scratch.d.ts +0 -4
  459. package/dist/commands/scratch.d.ts.map +0 -1
  460. package/dist/commands/session.d.ts.map +0 -1
  461. package/dist/commands/session.js +0 -162
  462. package/dist/commands/supervisor.d.ts +0 -4
  463. package/dist/commands/supervisor.d.ts.map +0 -1
  464. package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
  465. package/dist/core/harnesses/attest.d.ts.map +0 -1
  466. package/dist/core/harnesses/attestation.d.ts.map +0 -1
  467. package/dist/core/harnesses/bench.d.ts.map +0 -1
  468. package/dist/core/harnesses/index.d.ts +0 -13
  469. package/dist/core/harnesses/index.d.ts.map +0 -1
  470. package/dist/core/harnesses/index.js +0 -6
  471. package/dist/core/harnesses/profiles.d.ts.map +0 -1
  472. package/dist/core/harnesses/registry.d.ts +0 -15
  473. package/dist/core/harnesses/registry.d.ts.map +0 -1
  474. package/dist/core/harnesses/types.d.ts.map +0 -1
  475. package/dist/core/hooks/harness/detect.d.ts +0 -9
  476. package/dist/core/hooks/harness/events.d.ts.map +0 -1
  477. package/dist/core/hooks/harness/output.d.ts.map +0 -1
  478. package/dist/core/supervisor/index.d.ts +0 -7
  479. package/dist/core/supervisor/index.d.ts.map +0 -1
  480. package/dist/core/supervisor/index.js +0 -6
  481. package/dist/core/supervisor/plan-api.d.ts +0 -23
  482. package/dist/core/supervisor/plan-api.d.ts.map +0 -1
  483. package/dist/core/supervisor/plan-api.js +0 -50
  484. package/dist/core/supervisor/plan-read.d.ts +0 -5
  485. package/dist/core/supervisor/plan-read.d.ts.map +0 -1
  486. package/dist/core/supervisor/plan-types.d.ts +0 -170
  487. package/dist/core/supervisor/plan-types.d.ts.map +0 -1
  488. package/dist/core/supervisor/planning.d.ts +0 -33
  489. package/dist/core/supervisor/planning.d.ts.map +0 -1
  490. package/dist/core/supervisor/read.d.ts +0 -6
  491. package/dist/core/supervisor/read.d.ts.map +0 -1
  492. package/dist/core/supervisor/read.js +0 -4
  493. package/dist/core/supervisor/runner.d.ts +0 -37
  494. package/dist/core/supervisor/runner.d.ts.map +0 -1
  495. package/dist/core/supervisor/service-read.d.ts +0 -6
  496. package/dist/core/supervisor/service-read.d.ts.map +0 -1
  497. package/dist/core/supervisor/service.d.ts +0 -114
  498. package/dist/core/supervisor/service.d.ts.map +0 -1
  499. package/dist/core/supervisor/state.d.ts +0 -95
  500. package/dist/core/supervisor/state.d.ts.map +0 -1
  501. package/dist/core/workflow/harnesses.d.ts +0 -17
  502. package/dist/core/workflow/harnesses.d.ts.map +0 -1
  503. package/dist/core/workflow/harnesses.js +0 -21
  504. package/dist/core/workflow/journal.d.ts.map +0 -1
  505. package/src/commands/session.ts +0 -187
  506. package/src/core/harnesses/index.ts +0 -56
  507. package/src/core/hooks/harness/detect.ts +0 -30
  508. package/src/core/supervisor/index.ts +0 -89
  509. package/src/core/supervisor/plan-api.ts +0 -73
  510. package/src/core/supervisor/read.ts +0 -59
  511. package/src/core/workflow/harnesses.ts +0 -33
  512. /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/commands/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA2yB1E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,YAAY,CAAC,EAAE,qBAAqB,GACnC,IAAI,CAmEN"}
1
+ {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/commands/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAa1E,OAAO,EAYL,KAAK,WAAW,EAGjB,MAAM,wBAAwB,CAAC;AAgrBhC;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAsE7F;AAgND,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,YAAY,CAAC,EAAE,qBAAqB,GACnC,IAAI,CA4EN"}
@@ -6,6 +6,7 @@ function cachePath(tool, filename) {
6
6
  import { spawn, spawnSync } from "node:child_process";
7
7
  import { existsSync, openSync, readFileSync, writeFileSync } from "node:fs";
8
8
  import { resolve } from "node:path";
9
+ import { resolveBinName } from "../core/config.js";
9
10
  import { clearState, DEFAULT_INSTANCE, ensureCloudflared, gateLogFile, isProcessAlive, listStates, providerLogFile, readConfig, readState, writeConfig, writeState, } from "../lib/tunnel/state.js";
10
11
  /**
11
12
  * `tunnel`: provider-backed tunnel in front of a local upstream.
@@ -313,6 +314,33 @@ function providerIsAlive(state) {
313
314
  function tunnelIsAlive(state) {
314
315
  return isProcessAlive(state.gate_pid) && providerIsAlive(state);
315
316
  }
317
+ /**
318
+ * Spawn the detached gate worker.
319
+ *
320
+ * Shared by `up` (fresh start) and `reload` (in-place restart) so both hand the
321
+ * gate an identical environment and record the same kind of PID. The allowlist
322
+ * is passed as an env var, which the gate snapshots at module load and never
323
+ * re-reads — that snapshot is precisely why `reload` has to exist.
324
+ */
325
+ function spawnGate(o) {
326
+ const gateFd = openSync(o.gateLogPath, "a");
327
+ // `--name`/`--port` on argv mirror the env vars; they're what makes the gate
328
+ // process distinguishable per-instance in `pgrep -f` (see sweepStrays).
329
+ const gateProc = spawn("bun", ["run", gateScriptPath(), "--name", o.name, "--port", String(o.gatePort)], {
330
+ detached: true,
331
+ stdio: ["ignore", gateFd, gateFd],
332
+ env: {
333
+ ...process.env,
334
+ HARNERY_TUNNEL_ALLOW: o.allowedIps.join(","),
335
+ HARNERY_TUNNEL_ACCESS: o.provider === "cloudflare" ? "cloudflare-allowlist" : "trusted-local-proxy",
336
+ HARNERY_TUNNEL_TARGET: o.target,
337
+ HARNERY_TUNNEL_VHOST: o.vhost,
338
+ HARNERY_TUNNEL_PORT: String(o.gatePort),
339
+ },
340
+ });
341
+ gateProc.unref();
342
+ return gateProc;
343
+ }
316
344
  async function up(opts) {
317
345
  if (!bunAvailable()) {
318
346
  emit.error({
@@ -374,22 +402,15 @@ async function up(opts) {
374
402
  const providerLogPath = cachePath("tunnel", providerLogFile(name, provider));
375
403
  writeFileSync(gateLogPath, "");
376
404
  writeFileSync(providerLogPath, "");
377
- const gateFd = openSync(gateLogPath, "a");
378
- // `--name`/`--port` on argv mirror the env vars; they're what makes the gate
379
- // process distinguishable per-instance in `pgrep -f` (see sweepStrays).
380
- const gateProc = spawn("bun", ["run", gateScriptPath(), "--name", name, "--port", String(gatePort)], {
381
- detached: true,
382
- stdio: ["ignore", gateFd, gateFd],
383
- env: {
384
- ...process.env,
385
- HARNERY_TUNNEL_ALLOW: cfg.allowed_ips.join(","),
386
- HARNERY_TUNNEL_ACCESS: provider === "cloudflare" ? "cloudflare-allowlist" : "trusted-local-proxy",
387
- HARNERY_TUNNEL_TARGET: target,
388
- HARNERY_TUNNEL_VHOST: vhost,
389
- HARNERY_TUNNEL_PORT: String(gatePort),
390
- },
405
+ const gateProc = spawnGate({
406
+ name,
407
+ gatePort,
408
+ target,
409
+ vhost,
410
+ provider,
411
+ allowedIps: cfg.allowed_ips,
412
+ gateLogPath,
391
413
  });
392
- gateProc.unref();
393
414
  await sleep(800);
394
415
  if (!isProcessAlive(gateProc.pid)) {
395
416
  emit.error({
@@ -538,6 +559,140 @@ function down(opts) {
538
559
  ? `No tunnel processes found for [${name}]. Nothing to stop.\n`
539
560
  : `Stopped ${killed.size} process(es). Tunnel [${name}] down.\n`);
540
561
  }
562
+ /** Poll until `port` has no LISTEN socket (or the deadline passes). */
563
+ async function waitForPortFree(port, timeoutMs) {
564
+ const deadline = Date.now() + timeoutMs;
565
+ while (Date.now() < deadline) {
566
+ if (!listeningPorts().has(port))
567
+ return true;
568
+ await sleep(100);
569
+ }
570
+ return !listeningPorts().has(port);
571
+ }
572
+ /** Poll until `port` has a LISTEN socket (or the deadline passes). */
573
+ async function waitForPortBound(port, timeoutMs) {
574
+ const deadline = Date.now() + timeoutMs;
575
+ while (Date.now() < deadline) {
576
+ if (listeningPorts().has(port))
577
+ return true;
578
+ await sleep(100);
579
+ }
580
+ return listeningPorts().has(port);
581
+ }
582
+ /**
583
+ * Restart ONE instance's gate in place, deliberately leaving the provider
584
+ * process running.
585
+ *
586
+ * That asymmetry is the whole point. A Cloudflare quick tunnel's hostname is
587
+ * minted by cloudflared at startup, so a full `down`/`up` hands back a NEW
588
+ * random *.trycloudflare.com URL and breaks every link already shared — a
589
+ * miserable trade for adding one IP. cloudflared only ever forwards to
590
+ * `localhost:<gate_port>`, so the gate beneath it can be swapped out and the
591
+ * edge reconnects without noticing.
592
+ */
593
+ export async function reloadOne(state) {
594
+ const bin = resolveBinName();
595
+ const name = state.name;
596
+ const gatePort = state.gate_port;
597
+ if (!providerIsAlive(state)) {
598
+ return {
599
+ ok: false,
600
+ message: `[${name}] the provider process is gone, so the public URL is already dead. ` +
601
+ `Reloading the gate can't bring it back — run \`${bin} tunnel up --name ${name}\`.`,
602
+ };
603
+ }
604
+ if (!bunAvailable()) {
605
+ return { ok: false, message: `[${name}] bun is not on PATH, so the gate can't be respawned.` };
606
+ }
607
+ // Kill ONLY the gate. sweepStrays() is deliberately avoided here: it also
608
+ // matches `--url http://localhost:<port>`, which is the provider process we
609
+ // are going out of our way to keep alive.
610
+ const killed = new Set();
611
+ if (isProcessAlive(state.gate_pid)) {
612
+ try {
613
+ process.kill(state.gate_pid);
614
+ killed.add(state.gate_pid);
615
+ }
616
+ catch {
617
+ /* race: already gone */
618
+ }
619
+ }
620
+ killByPattern(`gate\\.ts.*--port ${gatePort}( |$)`, killed);
621
+ if (!(await waitForPortFree(gatePort, 5_000))) {
622
+ return {
623
+ ok: false,
624
+ message: `[${name}] port ${gatePort} never released, so the old gate looks wedged. ` +
625
+ `Tunnel is down; check \`${bin} tunnel status\`.`,
626
+ };
627
+ }
628
+ const cfg = readConfig();
629
+ const gateProc = spawnGate({
630
+ name,
631
+ gatePort,
632
+ target: state.target,
633
+ vhost: state.vhost,
634
+ provider: state.provider,
635
+ allowedIps: cfg.allowed_ips,
636
+ gateLogPath: cachePath("tunnel", gateLogFile(name)),
637
+ });
638
+ await sleep(800);
639
+ const pid = gateProc.pid;
640
+ if (typeof pid !== "number" ||
641
+ !isProcessAlive(pid) ||
642
+ !(await waitForPortBound(gatePort, 5_000))) {
643
+ return {
644
+ ok: false,
645
+ message: `[${name}] the gate did not come back on port ${gatePort}. ` +
646
+ `Tunnel is down; check \`${bin} tunnel logs --name ${name}\`.`,
647
+ };
648
+ }
649
+ writeState({ ...state, gate_pid: pid });
650
+ const allowNote = state.provider === "cloudflare" ? ` Allowlist: ${cfg.allowed_ips.length} IP(s).` : "";
651
+ return { ok: true, message: `[${name}] gate reloaded, URL unchanged: ${state.url}.${allowNote}` };
652
+ }
653
+ async function reload(opts) {
654
+ const bin = resolveBinName();
655
+ if (opts.all) {
656
+ const all = listStates();
657
+ // Only live tunnels are reloadable, and a box commonly accumulates stale
658
+ // state files from long-dead runs. Reporting those as failures would make
659
+ // the common post-`allow add` path exit non-zero for no real reason.
660
+ const live = all.filter((s) => providerIsAlive(s));
661
+ const stale = all.length - live.length;
662
+ if (live.length === 0) {
663
+ emit.text(all.length === 0
664
+ ? "No tunnels up. Nothing to reload.\n"
665
+ : `No live tunnels to reload (${all.length} stale). Start one with \`${bin} tunnel up\`.\n`);
666
+ return;
667
+ }
668
+ let failed = 0;
669
+ for (const s of live) {
670
+ const r = await reloadOne(s);
671
+ emit.text(`${r.ok ? "ok " : "FAIL"} ${r.message}\n`);
672
+ if (!r.ok)
673
+ failed++;
674
+ }
675
+ emit.text(`Reloaded ${live.length - failed} of ${live.length} live tunnel(s)` +
676
+ (stale > 0 ? `; skipped ${stale} stale.\n` : ".\n"));
677
+ if (failed > 0)
678
+ process.exitCode = 1;
679
+ return;
680
+ }
681
+ const name = resolveName(opts.name);
682
+ const state = readState(name);
683
+ if (!state) {
684
+ emit.error({
685
+ code: "tunnel_not_found",
686
+ message: `No tunnel state for [${name}]. Start it with \`${bin} tunnel up --name ${name}\`.`,
687
+ });
688
+ process.exit(1);
689
+ return;
690
+ }
691
+ const r = await reloadOne(state);
692
+ emit.text(`${r.message}\n`);
693
+ if (!r.ok)
694
+ process.exit(1);
695
+ }
541
696
  function instanceState(state) {
542
697
  return tunnelIsAlive(state) ? "up" : "stale";
543
698
  }
@@ -643,6 +798,21 @@ function allowList() {
643
798
  for (const ip of cfg.allowed_ips)
644
799
  emit.text(`${ip}\n`);
645
800
  }
801
+ /**
802
+ * Trailer for `allow add`/`allow rm`. Each gate snapshots the allowlist at
803
+ * spawn, so a config edit alone changes nothing until the gates restart.
804
+ * Only LIVE tunnels are listed — stale state files pile up on a long-running
805
+ * box, and naming nine dead instances made the old hint read like nine
806
+ * restarts were owed.
807
+ */
808
+ function allowChangedHint() {
809
+ const live = listStates().filter((s) => s.provider === "cloudflare" && providerIsAlive(s));
810
+ if (live.length === 0)
811
+ return;
812
+ emit.text(`Each gate reads the allowlist once at start, so this applies on reload ` +
813
+ `(${live.map((s) => s.name).join(", ")}):\n` +
814
+ ` ${resolveBinName()} tunnel reload --all\n`);
815
+ }
646
816
  function allowAdd(ip) {
647
817
  const cfg = readConfig();
648
818
  if (cfg.allowed_ips.includes(ip)) {
@@ -652,10 +822,7 @@ function allowAdd(ip) {
652
822
  cfg.allowed_ips.push(ip);
653
823
  writeConfig(cfg);
654
824
  emit.text(`Added ${ip}.\n`);
655
- const up = listStates().filter((s) => s.provider === "cloudflare");
656
- if (up.length > 0) {
657
- emit.text(`Cloudflare allowlist is shared across Cloudflare tunnels; restart each to apply (${up.map((s) => s.name).join(", ")}).\n`);
658
- }
825
+ allowChangedHint();
659
826
  }
660
827
  function allowRm(ip) {
661
828
  const cfg = readConfig();
@@ -667,10 +834,7 @@ function allowRm(ip) {
667
834
  cfg.allowed_ips.splice(idx, 1);
668
835
  writeConfig(cfg);
669
836
  emit.text(`Removed ${ip}.\n`);
670
- const up = listStates().filter((s) => s.provider === "cloudflare");
671
- if (up.length > 0) {
672
- emit.text(`Cloudflare allowlist is shared across Cloudflare tunnels; restart each to apply (${up.map((s) => s.name).join(", ")}).\n`);
673
- }
837
+ allowChangedHint();
674
838
  }
675
839
  let emit;
676
840
  let context;
@@ -700,6 +864,12 @@ export function registerTunnelCommand(program, emitParam, contextParam) {
700
864
  .option("--name <name>", "instance to stop", DEFAULT_INSTANCE)
701
865
  .option("--all", "stop every running tunnel")
702
866
  .action(down);
867
+ cmd
868
+ .command("reload")
869
+ .description("Restart an instance's gate in place to pick up allowlist changes, keeping the public URL")
870
+ .option("--name <name>", "instance to reload", DEFAULT_INSTANCE)
871
+ .option("--all", "reload every live tunnel")
872
+ .action(reload);
703
873
  cmd
704
874
  .command("status")
705
875
  .description("Show tunnel state: a table of all instances, or detail for one via --name")
@@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url";
14
14
  * harnery repo at the *matching version tag* into a cache dir and install the
15
15
  * web app's deps. Subsequent runs reuse the cache.
16
16
  *
17
- * The only thing `web/` pulls from `src/` is `harnery/core/scratch` (a single,
17
+ * The only thing `web/` pulls from `src/` is `harnery/core/journal` (a single,
18
18
  * dependency-free module), so the install is `web/` deps only: no root install,
19
19
  * no Playwright browser download.
20
20
  */
@@ -1,4 +1,23 @@
1
1
  import type { Command } from "commander";
2
2
  import type { EmitContext } from "../commander.js";
3
+ /**
4
+ * Resolve the V8 old-space ceiling for the dashboard process.
5
+ *
6
+ * Next sizes `--max-old-space-size` to roughly half of system RAM when the
7
+ * flag is absent, which on a large machine hands a long-lived dashboard a
8
+ * ceiling it will never approach — so V8 never feels enough pressure to run a
9
+ * major GC and the process settles at a multi-gigabyte working set made mostly
10
+ * of collectable garbage. Pinning a modest ceiling restores that pressure.
11
+ *
12
+ * Precedence: explicit flag → `HARNERY_WEB_MAX_OLD_SPACE` → the default.
13
+ * `0` (or any non-positive value) opts out and restores Next's own sizing.
14
+ */
15
+ export declare function resolveMaxOldSpaceMb(flag?: string): number;
16
+ /**
17
+ * Append the heap ceiling to any inherited `NODE_OPTIONS`. Next only supplies
18
+ * its own `--max-old-space-size` when the flag is absent, so appending here
19
+ * wins without clobbering flags the caller set (source maps, inspector, …).
20
+ */
21
+ export declare function nodeOptionsWithHeapCap(mb: number): string | undefined;
3
22
  export declare function registerWebCommand(program: Command, emit: EmitContext): void;
4
23
  //# sourceMappingURL=web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAwDnD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAwI5E"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAgCnD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKrE;AA8BD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA2J5E"}
@@ -27,6 +27,42 @@ function webRoot() {
27
27
  const here = path.dirname(fileURLToPath(import.meta.url));
28
28
  return path.resolve(here, "..", "..", "web");
29
29
  }
30
+ /** Default V8 old-space ceiling (MB) for the dashboard server. */
31
+ const DEFAULT_MAX_OLD_SPACE_MB = 2048;
32
+ /**
33
+ * Resolve the V8 old-space ceiling for the dashboard process.
34
+ *
35
+ * Next sizes `--max-old-space-size` to roughly half of system RAM when the
36
+ * flag is absent, which on a large machine hands a long-lived dashboard a
37
+ * ceiling it will never approach — so V8 never feels enough pressure to run a
38
+ * major GC and the process settles at a multi-gigabyte working set made mostly
39
+ * of collectable garbage. Pinning a modest ceiling restores that pressure.
40
+ *
41
+ * Precedence: explicit flag → `HARNERY_WEB_MAX_OLD_SPACE` → the default.
42
+ * `0` (or any non-positive value) opts out and restores Next's own sizing.
43
+ */
44
+ export function resolveMaxOldSpaceMb(flag) {
45
+ const raw = flag ?? process.env.HARNERY_WEB_MAX_OLD_SPACE;
46
+ if (raw === undefined || raw === "")
47
+ return DEFAULT_MAX_OLD_SPACE_MB;
48
+ const n = Number(raw);
49
+ if (!Number.isFinite(n) || n <= 0)
50
+ return 0;
51
+ return Math.floor(n);
52
+ }
53
+ /**
54
+ * Append the heap ceiling to any inherited `NODE_OPTIONS`. Next only supplies
55
+ * its own `--max-old-space-size` when the flag is absent, so appending here
56
+ * wins without clobbering flags the caller set (source maps, inspector, …).
57
+ */
58
+ export function nodeOptionsWithHeapCap(mb) {
59
+ const inherited = process.env.NODE_OPTIONS ?? "";
60
+ if (mb <= 0)
61
+ return inherited || undefined;
62
+ if (/--max-old-space-size[=\s]/.test(inherited))
63
+ return inherited;
64
+ return `${inherited} --max-old-space-size=${mb}`.trim();
65
+ }
30
66
  /**
31
67
  * Resolve the web app root. A local `web/` (source checkout / submodule) wins.
32
68
  * Otherwise, on an npm install, lazy-fetch it (clone + install) unless the
@@ -59,6 +95,7 @@ export function registerWebCommand(program, emit) {
59
95
  .option("--coord-root <dir>", "Override the coord root (default: cwd; web walks up looking for .harnery/)")
60
96
  .option("--prod", "Use next start instead of next dev (requires prior build)")
61
97
  .option("--no-fetch", "Don't auto-fetch the dashboard if it's missing (npm installs)")
98
+ .option("--max-old-space <mb>", `V8 old-space ceiling in MB; 0 restores Next's own sizing (default ${DEFAULT_MAX_OLD_SPACE_MB}, env HARNERY_WEB_MAX_OLD_SPACE)`)
62
99
  .action(async (opts) => {
63
100
  const root = resolveWebRoot(emit, opts.fetch !== false);
64
101
  if (!root) {
@@ -80,14 +117,21 @@ export function registerWebCommand(program, emit) {
80
117
  return;
81
118
  }
82
119
  }
120
+ const heapMb = resolveMaxOldSpaceMb(opts.maxOldSpace);
83
121
  emit.log(`harn web · http://localhost:${port} (${mode})`, "info");
122
+ emit.log(`files origin · http://harnery-files.localhost:${port}`, "info");
84
123
  emit.log(`reading .harnery/ from: ${coordRoot}`, "info");
124
+ if (heapMb > 0)
125
+ emit.log(`heap ceiling · ${heapMb} MB`, "info");
85
126
  const child = spawn(webRunner(), ["run", mode], {
86
127
  cwd: root,
87
128
  env: {
88
129
  ...process.env,
89
130
  HARNERY_COORD_ROOT: coordRoot,
90
131
  HARNERY_WEB_PORT: port,
132
+ ...(nodeOptionsWithHeapCap(heapMb)
133
+ ? { NODE_OPTIONS: nodeOptionsWithHeapCap(heapMb) }
134
+ : {}),
91
135
  },
92
136
  stdio: "inherit",
93
137
  });
@@ -130,6 +174,7 @@ export function registerWebCommand(program, emit) {
130
174
  .option("-p, --port <port>", "Listen port", "9000")
131
175
  .option("--coord-root <dir>", "Override the coord root")
132
176
  .option("--no-fetch", "Don't auto-fetch the dashboard if it's missing (npm installs)")
177
+ .option("--max-old-space <mb>", `V8 old-space ceiling in MB; 0 restores Next's own sizing (default ${DEFAULT_MAX_OLD_SPACE_MB}, env HARNERY_WEB_MAX_OLD_SPACE)`)
133
178
  .action((opts) => {
134
179
  const root = resolveWebRoot(emit, opts.fetch !== false);
135
180
  if (!root) {
@@ -148,14 +193,20 @@ export function registerWebCommand(program, emit) {
148
193
  }
149
194
  const coordRoot = opts.coordRoot ?? process.cwd();
150
195
  const port = String(opts.port);
196
+ const heapMb = resolveMaxOldSpaceMb(opts.maxOldSpace);
151
197
  emit.log(`harn web · http://localhost:${port} (start)`, "info");
152
198
  emit.log(`reading .harnery/ from: ${coordRoot}`, "info");
199
+ if (heapMb > 0)
200
+ emit.log(`heap ceiling · ${heapMb} MB`, "info");
153
201
  const child = spawn(webRunner(), ["run", "start"], {
154
202
  cwd: root,
155
203
  env: {
156
204
  ...process.env,
157
205
  HARNERY_COORD_ROOT: coordRoot,
158
206
  HARNERY_WEB_PORT: port,
207
+ ...(nodeOptionsWithHeapCap(heapMb)
208
+ ? { NODE_OPTIONS: nodeOptionsWithHeapCap(heapMb) }
209
+ : {}),
159
210
  },
160
211
  stdio: "inherit",
161
212
  });
@@ -1,6 +1,7 @@
1
1
  import type { Command } from "commander";
2
2
  import type { EmitContext } from "../commander.js";
3
- import { type WorkAttempt } from "../core/work/index.js";
3
+ import { type WorkAttempt, type WorkRecord } from "../core/work/index.js";
4
4
  export declare function registerWorkCommand(program: Command, emit: EmitContext): void;
5
5
  export declare function renderAttemptRow(attempt: WorkAttempt): string;
6
+ export declare function renderAttemptBudget(record: WorkRecord): string;
6
7
  //# sourceMappingURL=work.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"work.d.ts","sourceRoot":"","sources":["../../src/commands/work.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAUnD,OAAO,EAUL,KAAK,WAAW,EAEjB,MAAM,uBAAuB,CAAC;AAuC/B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA8F7E;AA0OD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAM7D"}
1
+ {"version":3,"file":"work.d.ts","sourceRoot":"","sources":["../../src/commands/work.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAWnD,OAAO,EAUL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAwC/B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAqG7E;AAwPD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAM7D;AAkBD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAK9D"}
@@ -1,14 +1,15 @@
1
1
  import { resolve } from "node:path";
2
+ import { adapterProofInputs, createBuiltinAdapterRegistry, probeBinaryVersion, } from "../core/adapters/index.js";
2
3
  import { workflowSubscriptionOnly } from "../core/config.js";
3
- import { createBuiltinHarnessRegistry, harnessProofInputs, probeBinaryVersion, } from "../core/harnesses/index.js";
4
+ import { findCompletedMissionGoverning, reopenGovernorMission } from "../core/governor/index.js";
4
5
  import { findCoordRoot } from "../core/hooks/resolve/coord-root.js";
5
6
  import { loadPolicyFile } from "../core/policy/index.js";
6
7
  import { acceptWorkItem, cancelWorkItem, createWorkItem, listWorkItems, readWorkItem, reconcileAllWorkItems, reconcileWorkItem, reopenWorkItem, runWorkItem, } from "../core/work/index.js";
7
8
  import { WorkflowParkedError } from "../core/workflow/index.js";
8
- const MAX_ATTEMPT_JOURNAL_ERROR_RENDER = 240;
9
+ const MAX_ATTEMPT_TRANSCRIPT_ERROR_RENDER = 240;
9
10
  export function registerWorkCommand(program, emit) {
10
- const registry = createBuiltinHarnessRegistry();
11
- const harnesses = registry.ids();
11
+ const registry = createBuiltinAdapterRegistry();
12
+ const adapters = registry.ids();
12
13
  const work = program
13
14
  .command("work")
14
15
  .description("Track durable objectives across bounded workflow attempts.");
@@ -19,7 +20,8 @@ export function registerWorkCommand(program, emit) {
19
20
  .option("--id <work-id>", "Stable work id (generated by default)")
20
21
  .option("--accept <text>", "Acceptance statement; repeat for more than one", collect, [])
21
22
  .option("--depends-on <ids>", "Comma-separated prerequisite work ids")
22
- .option("--max-attempts <n>", "Attempt ceiling (default 3)")
23
+ .option("--max-attempts <n>", "Charged-attempt ceiling (default 3)")
24
+ .option("--max-uncharged-attempts <n>", "Ceiling on consecutive uncharged upstream attempts (default 3)")
23
25
  .option("--source-kind <kind>", "human | workflow | external", "human")
24
26
  .option("--source-ref <ref>", "Bounded source reference")
25
27
  .option("--actor <name>", "Actor recorded in the creation receipt")
@@ -35,6 +37,9 @@ export function registerWorkCommand(program, emit) {
35
37
  acceptance: opts.accept,
36
38
  dependencies: splitIds(opts.dependsOn),
37
39
  maxAttempts: opts.maxAttempts ? Number.parseInt(opts.maxAttempts, 10) : undefined,
40
+ maxUnchargedAttempts: opts.maxUnchargedAttempts
41
+ ? Number.parseInt(opts.maxUnchargedAttempts, 10)
42
+ : undefined,
38
43
  source: opts.sourceKind ? { kind: opts.sourceKind, ref: opts.sourceRef } : undefined,
39
44
  actor: opts.actor,
40
45
  });
@@ -92,13 +97,13 @@ export function registerWorkCommand(program, emit) {
92
97
  }
93
98
  });
94
99
  });
95
- registerRunCommand(work, "run", false, registry, harnesses, emit);
96
- registerRunCommand(work, "retry", true, registry, harnesses, emit);
100
+ registerRunCommand(work, "run", false, registry, adapters, emit);
101
+ registerRunCommand(work, "retry", true, registry, adapters, emit);
97
102
  registerGovernanceCommand(work, "accept", emit);
98
103
  registerGovernanceCommand(work, "cancel", emit);
99
104
  registerGovernanceCommand(work, "reopen", emit);
100
105
  }
101
- function registerRunCommand(work, name, retry, registry, harnesses, emit) {
106
+ function registerRunCommand(work, name, retry, registry, adapters, emit) {
102
107
  work
103
108
  .command(`${name} <work-id>`)
104
109
  .description(retry
@@ -107,8 +112,8 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
107
112
  .option("--max-agents <n>", "Total-agent ceiling for the workflow")
108
113
  .option("--concurrency <n>", "Concurrent-subagent cap")
109
114
  .option("--cwd <dir>", "Working directory children spawn in")
110
- .option("--harness <name>", `Default harness: ${harnesses.join(" | ")}`)
111
- .option("--subscription-only", "Require stored harness-login billing")
115
+ .option("--adapter <name>", `Default adapter: ${adapters.join(" | ")}`)
116
+ .option("--subscription-only", "Require stored adapter-login billing")
112
117
  .option("--allow-api-billing", "Permit API-key override billing")
113
118
  .option("--policy <file>", "Host policy JSON/JSONC")
114
119
  .option("--isolation <mode>", "shared | worktree | sandbox | remote")
@@ -118,8 +123,8 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
118
123
  .option("--json", "Emit the workflow report or parked result as JSON")
119
124
  .action(async (workId, opts) => {
120
125
  await withWorkRootAsync(emit, async (coordRoot) => {
121
- if (opts.harness && !registry.get(opts.harness)) {
122
- throw new Error(`unknown harness ${JSON.stringify(opts.harness)}`);
126
+ if (opts.adapter && !registry.get(opts.adapter)) {
127
+ throw new Error(`unknown adapter ${JSON.stringify(opts.adapter)}`);
123
128
  }
124
129
  if (opts.workspaceRoot && opts.isolation !== "worktree") {
125
130
  throw new Error("--workspace-root requires --isolation worktree");
@@ -143,13 +148,13 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
143
148
  actor: opts.actor,
144
149
  engine: {
145
150
  spawners: registry.spawners(),
146
- defaultHarness: opts.harness,
151
+ defaultAdapter: opts.adapter,
147
152
  maxAgents: opts.maxAgents ? Number.parseInt(opts.maxAgents, 10) : undefined,
148
153
  concurrency: opts.concurrency ? Number.parseInt(opts.concurrency, 10) : undefined,
149
154
  cwd: opts.cwd,
150
155
  subscriptionOnly: opts.subscriptionOnly === true ? true : workflowSubscriptionOnly(coordRoot),
151
156
  allowApiBilling: opts.allowApiBilling,
152
- ...harnessProofInputs(registry.list().map((adapter) => adapter.profile), { versionProbe: probeBinaryVersion }),
157
+ ...adapterProofInputs(registry.list().map((adapter) => adapter.profile), { versionProbe: probeBinaryVersion }),
153
158
  policy: opts.policy ? loadPolicyFile(opts.policy) : undefined,
154
159
  approvalMode: "park",
155
160
  approvalAddressee: opts.approvalTo,
@@ -185,7 +190,7 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
185
190
  workId,
186
191
  runId: error.runId,
187
192
  approvalId: error.approvalId,
188
- journalPath: error.journalPath,
193
+ transcriptPath: error.transcriptPath,
189
194
  });
190
195
  }
191
196
  else {
@@ -220,11 +225,26 @@ function registerGovernanceCommand(work, name, emit) {
220
225
  command.action((workId, opts) => {
221
226
  withWorkRoot(emit, (coordRoot) => {
222
227
  const fn = name === "accept" ? acceptWorkItem : name === "cancel" ? cancelWorkItem : reopenWorkItem;
223
- emitWork(fn(coordRoot, workId, {
228
+ // ADR 0050: a reopen under a mission that already succeeded has to reopen the
229
+ // mission too, or the item lands in ready_work that the governor will never
230
+ // dispatch. Resolve the goal BEFORE touching the work item so a refusal leaves
231
+ // nothing half-done.
232
+ const goalId = name === "reopen" ? findCompletedMissionGoverning(coordRoot, workId) : undefined;
233
+ const record = fn(coordRoot, workId, {
224
234
  ...opts,
225
235
  ...(opts.finding?.length ? { findings: opts.finding } : {}),
226
236
  ...(opts.dispose?.length ? { dispositions: opts.dispose.map(parseDisposition) } : {}),
227
- }), opts.json, emit, true);
237
+ });
238
+ if (goalId) {
239
+ reopenGovernorMission({
240
+ coordRoot,
241
+ goalId,
242
+ actor: opts.actor,
243
+ reason: opts.reason?.trim() || `work ${workId} was reopened after mission completion`,
244
+ });
245
+ emit.log(`mission ${goalId} had completed; its completion was reopened so ${workId} can be dispatched`, "warn");
246
+ }
247
+ emitWork(record, opts.json, emit, true);
228
248
  });
229
249
  });
230
250
  }
@@ -263,7 +283,7 @@ function emitWork(record, json, emit, detail = false) {
263
283
  `objective: ${record.intent.objective}`,
264
284
  `reason: ${projection.reason}`,
265
285
  `next: ${projection.next_action}`,
266
- `attempts: ${projection.attempts_used}/${record.intent.max_attempts}`,
286
+ `attempts: ${renderAttemptBudget(record)}`,
267
287
  ];
268
288
  if (record.intent.dependencies.length)
269
289
  lines.push(`depends on: ${record.intent.dependencies.join(", ")}`);
@@ -280,21 +300,31 @@ function emitWork(record, json, emit, detail = false) {
280
300
  emit.text(`${lines.join("\n")}\n`);
281
301
  }
282
302
  export function renderAttemptRow(attempt) {
283
- const statusDetail = attempt.status === "journal_unreadable"
284
- ? `: ${renderAttemptJournalError(attempt.journal_error)}`
303
+ const statusDetail = attempt.status === "transcript_unreadable"
304
+ ? `: ${renderAttemptTranscriptError(attempt.transcript_error)}`
285
305
  : "";
286
306
  return ` ${attempt.number}. ${attempt.run_id} ${attempt.status}${statusDetail}`;
287
307
  }
288
- function renderAttemptJournalError(error) {
308
+ function renderAttemptTranscriptError(error) {
289
309
  const normalized = (error ?? "").replace(/\s+/g, " ").trim();
290
- const value = normalized || "unknown journal read error";
291
- if (value.length <= MAX_ATTEMPT_JOURNAL_ERROR_RENDER)
310
+ const value = normalized || "unknown transcript read error";
311
+ if (value.length <= MAX_ATTEMPT_TRANSCRIPT_ERROR_RENDER)
292
312
  return value;
293
- return `${value.slice(0, MAX_ATTEMPT_JOURNAL_ERROR_RENDER - 3).trimEnd()}...`;
313
+ return `${value.slice(0, MAX_ATTEMPT_TRANSCRIPT_ERROR_RENDER - 3).trimEnd()}...`;
294
314
  }
295
315
  function renderWorkRow(record) {
296
316
  const projection = record.projection;
297
- return `${record.intent.id} ${projection.state.padEnd(17)} ${projection.attempts_used}/${record.intent.max_attempts} ${projection.next_action.padEnd(21)} ${record.intent.title}`;
317
+ return `${record.intent.id} ${projection.state.padEnd(17)} ${renderAttemptBudget(record).padEnd(18)} ${projection.next_action.padEnd(21)} ${record.intent.title}`;
318
+ }
319
+ // `max_attempts` budgets CHARGED attempts (ADR 0046), so the budget is
320
+ // charged/max, not the raw attempt count. When uncharged environment/upstream
321
+ // attempts happened, surface them as a suffix rather than folding them into the
322
+ // numerator, where they would read as spent budget the item still has.
323
+ export function renderAttemptBudget(record) {
324
+ const { charged_attempts, attempts_used } = record.projection;
325
+ const uncharged = attempts_used - charged_attempts;
326
+ const base = `${charged_attempts}/${record.intent.max_attempts}`;
327
+ return uncharged > 0 ? `${base} (+${uncharged} uncharged)` : base;
298
328
  }
299
329
  function withWorkRoot(emit, fn) {
300
330
  const coordRoot = findCoordRoot();
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyEnD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAmuBjF"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyEnD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA4uBjF"}