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
@@ -4,9 +4,9 @@ import { hostname } from "node:os";
4
4
  import { dirname, isAbsolute, join, resolve } from "node:path";
5
5
  import { readWorkflowApproval } from "../workflow/approvals.js";
6
6
  import { stableDigest } from "../workflow/durable-record.js";
7
- import { WORKFLOW_JOURNAL_EVENT_BYTES, workflowJournalPath } from "../workflow/journal.js";
8
7
  import { readWorkflowProof } from "../workflow/proof.js";
9
8
  import { readWorkflowRunManifest, workflowScriptDigest } from "../workflow/run-state.js";
9
+ import { WORKFLOW_TRANSCRIPT_EVENT_BYTES, workflowTranscriptPath } from "../workflow/transcript.js";
10
10
  import { isWorkspaceBoundExecutionEvidence } from "../workflow/workspaces/validate.js";
11
11
  export const WORK_INTENT_SCHEMA_VERSION = 1;
12
12
  export const WORK_EVENT_SCHEMA_VERSION = 1;
@@ -25,6 +25,12 @@ const MAX_EVENTS_BYTES = 4 * 1024 * 1024;
25
25
  const MAX_EVENT_BYTES = 16 * 1024;
26
26
  const MAX_EVENTS = 1_000;
27
27
  const FOREIGN_LEASE_STALE_MS = 24 * 60 * 60 * 1_000;
28
+ /** Default ceiling on consecutive uncharged attempts (ADR 0046). Kept low: each
29
+ * one is a real vendor round-trip, so a handful gives a transient outage room
30
+ * to recover before the item stops and names the outside service. There is no
31
+ * backoff between them beyond the cadence of the governor and the vendor's own
32
+ * responses, which is why the bound stays small. */
33
+ const DEFAULT_MAX_UNCHARGED_ATTEMPTS = 3;
28
34
  export function createWorkItem(input) {
29
35
  const coordRoot = resolve(input.coordRoot);
30
36
  const id = input.id ?? newWorkId();
@@ -45,6 +51,12 @@ export function createWorkItem(input) {
45
51
  if (!Number.isSafeInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > 100) {
46
52
  throw new Error("work maxAttempts must be an integer from 1 to 100");
47
53
  }
54
+ const maxUnchargedAttempts = input.maxUnchargedAttempts ?? DEFAULT_MAX_UNCHARGED_ATTEMPTS;
55
+ if (!Number.isSafeInteger(maxUnchargedAttempts) ||
56
+ maxUnchargedAttempts < 1 ||
57
+ maxUnchargedAttempts > 100) {
58
+ throw new Error("work maxUnchargedAttempts must be an integer from 1 to 100");
59
+ }
48
60
  const acceptance = (input.acceptance ?? []).map((value, index) => boundedString(value, `work acceptance[${index}]`, MAX_ACCEPTANCE_ITEM));
49
61
  if (acceptance.length > MAX_ACCEPTANCE) {
50
62
  throw new Error(`work acceptance exceeds ${MAX_ACCEPTANCE} criteria`);
@@ -59,6 +71,7 @@ export function createWorkItem(input) {
59
71
  dependencies,
60
72
  workflow: { path: workflowPath, sha256: workflowScriptDigest(workflowPath) },
61
73
  max_attempts: maxAttempts,
74
+ max_uncharged_attempts: maxUnchargedAttempts,
62
75
  source,
63
76
  created_at: new Date().toISOString(),
64
77
  };
@@ -178,13 +191,18 @@ function deriveWorkProjection(coordRoot, intent, events, ignoreLease = false) {
178
191
  const terminal = latestGovernance?.event === "work.accepted" || latestGovernance?.event === "work.cancelled";
179
192
  const attemptEvents = events.filter((event) => event.event === "attempt.started");
180
193
  const attempts = attemptEvents.map((event, index) => inspectAttempt(coordRoot, event, intent, attemptEvents[index - 1]?.run_id));
194
+ // Charged attempts — not the raw count — are what max_attempts budgets
195
+ // (ADR 0046). An uncharged environment/upstream attempt still increments
196
+ // attempts_used (ordering + next number) but not the budget.
197
+ const chargedAttempts = attempts.filter((attempt) => attempt.uncharged === undefined).length;
181
198
  const base = {
182
199
  id: intent.id,
183
200
  title: intent.title,
184
201
  unresolved_dependencies: [],
185
202
  attempts,
186
203
  attempts_used: attempts.length,
187
- attempts_remaining: Math.max(0, intent.max_attempts - attempts.length),
204
+ charged_attempts: chargedAttempts,
205
+ attempts_remaining: Math.max(0, intent.max_attempts - chargedAttempts),
188
206
  latest_run_id: attempts.at(-1)?.run_id,
189
207
  approval_id: attempts.at(-1)?.approval_id,
190
208
  proof_path: attempts.at(-1)?.proof_path,
@@ -266,15 +284,72 @@ function deriveWorkProjection(coordRoot, intent, events, ignoreLease = false) {
266
284
  next_action: "review",
267
285
  };
268
286
  }
269
- const attemptsRemaining = intent.max_attempts - attempts.length;
270
- if (latest.status === "journal_unreadable") {
287
+ const attemptsRemaining = intent.max_attempts - chargedAttempts;
288
+ if (latest.status === "transcript_unreadable") {
271
289
  return {
272
290
  ...base,
273
291
  state: "blocked",
274
- reason: `workflow attempt ${latest.number} journal is unreadable: ${latest.journal_error ?? "unknown journal read error"}`,
292
+ reason: `workflow attempt ${latest.number} transcript is unreadable: ${latest.transcript_error ?? "unknown transcript read error"}`,
275
293
  next_action: attemptsRemaining > 0 ? "retry" : "none",
276
294
  };
277
295
  }
296
+ // Uncharged failures (ADR 0046) are handled before the ordinary work-failure
297
+ // path: they did not touch the work, so they neither spent the budget nor
298
+ // signal that retrying the work would help.
299
+ if (latest.status === "failed" && latest.uncharged === "environment") {
300
+ // A missing precondition. The operator chose to STOP the item immediately
301
+ // rather than retry an unchanged environment (ADR 0046); next_action "none"
302
+ // stops the governor. A human who fixes the environment can still force a
303
+ // retry — the attempt was uncharged, so the budget is intact.
304
+ return {
305
+ ...base,
306
+ state: "blocked",
307
+ reason: environmentBlockedReason(latest),
308
+ next_action: "none",
309
+ };
310
+ }
311
+ if (latest.status === "failed" && latest.uncharged === "decision") {
312
+ // The script did its job and the answer was "a person has to settle this".
313
+ // Terminal for the same reason "environment" is terminal — retrying cannot
314
+ // change the blocker — but the fix is a ruling, not a repair, so the reason
315
+ // names the decision instead of a precondition. Uncharged, so once the
316
+ // decision lands the item can be retried with its budget intact.
317
+ return {
318
+ ...base,
319
+ state: "blocked",
320
+ reason: decisionBlockedReason(latest),
321
+ next_action: "none",
322
+ blocked_on_decision: latest.blocked_on ?? "",
323
+ };
324
+ }
325
+ if (latest.status === "failed" && latest.uncharged === "upstream") {
326
+ // Count trailing consecutive uncharged attempts in the current window. The
327
+ // bound is the only brake on an outage that never ends, so at the limit the
328
+ // item stops and names the outside service — distinct from work-blocked.
329
+ const maxUncharged = intent.max_uncharged_attempts ?? DEFAULT_MAX_UNCHARGED_ATTEMPTS;
330
+ let trailingUncharged = 0;
331
+ for (let index = currentAttempts.length - 1; index >= 0; index--) {
332
+ if (currentAttempts[index].uncharged === undefined)
333
+ break;
334
+ trailingUncharged++;
335
+ }
336
+ if (trailingUncharged >= maxUncharged || attemptsRemaining <= 0) {
337
+ return {
338
+ ...base,
339
+ state: "blocked",
340
+ reason: trailingUncharged >= maxUncharged
341
+ ? `blocked waiting on an outside service after ${trailingUncharged} consecutive uncharged attempt(s): ${upstreamReason(latest)}`
342
+ : `workflow attempt ${latest.number} was uncharged (${upstreamReason(latest)}) but the work attempt budget is exhausted`,
343
+ next_action: "none",
344
+ };
345
+ }
346
+ return {
347
+ ...base,
348
+ state: "blocked",
349
+ reason: `workflow attempt ${latest.number} did not touch the work; an outside service refused: ${upstreamReason(latest)}`,
350
+ next_action: "retry",
351
+ };
352
+ }
278
353
  return {
279
354
  ...base,
280
355
  state: "blocked",
@@ -284,6 +359,45 @@ function deriveWorkProjection(coordRoot, intent, events, ignoreLease = false) {
284
359
  next_action: attemptsRemaining > 0 ? "retry" : "none",
285
360
  };
286
361
  }
362
+ /** The failure reason for an uncharged attempt, read from the proof when
363
+ * present. Bounded so a verbose vendor transcript cannot bloat the projection
364
+ * reason (which is persisted verbatim into the reconciliation event). */
365
+ function unchargedProofError(attempt) {
366
+ if (!attempt.proof_path)
367
+ return undefined;
368
+ try {
369
+ const proof = parseObject(readFileSync(attempt.proof_path, "utf8"), "workflow proof");
370
+ const run = proof.run;
371
+ const error = run && typeof run === "object" ? run.error : undefined;
372
+ return typeof error === "string" && error.trim() ? boundedTranscriptError(error) : undefined;
373
+ }
374
+ catch {
375
+ return undefined;
376
+ }
377
+ }
378
+ function environmentBlockedReason(attempt) {
379
+ const detail = unchargedProofError(attempt);
380
+ return detail
381
+ ? `workflow attempt ${attempt.number} could not start; a required precondition is missing: ${detail}`
382
+ : `workflow attempt ${attempt.number} could not start; a required precondition is missing`;
383
+ }
384
+ function upstreamReason(attempt) {
385
+ return unchargedProofError(attempt) ?? "the vendor was reached and refused";
386
+ }
387
+ /** Operator-facing reason for a run that stopped on a human. Reads the script's
388
+ * own sentence out of the proof and drops the WorkflowBlockedError prefix the
389
+ * engine added, so the projection says the thing once rather than twice. */
390
+ function decisionBlockedReason(attempt) {
391
+ const raw = unchargedProofError(attempt);
392
+ const detail = raw
393
+ ?.replace(/^blocked on decision \S+: /, "")
394
+ .replace(/^blocked pending a human decision: /, "")
395
+ .trim();
396
+ const named = attempt.blocked_on ? ` (decision ${attempt.blocked_on})` : "";
397
+ return detail
398
+ ? `a human must rule before this can proceed: ${detail}${named}`
399
+ : `a human must rule before this can proceed${named}`;
400
+ }
287
401
  function inspectAttempt(coordRoot, event, intent, priorRunId) {
288
402
  const runId = event.run_id;
289
403
  const attempt = {
@@ -334,15 +448,27 @@ function inspectAttempt(coordRoot, event, intent, priorRunId) {
334
448
  proof.acceptance.summary.unknown === 0
335
449
  ? "succeeded"
336
450
  : "failed";
451
+ // A failed attempt the run classified as uninformative about the work is
452
+ // uncharged (ADR 0046). Absent class ⇒ charged, as before. Read only for a
453
+ // failed attempt: a succeeded run never carries a class.
454
+ if (attempt.status === "failed" &&
455
+ (proof.run.class === "environment" ||
456
+ proof.run.class === "upstream" ||
457
+ proof.run.class === "decision")) {
458
+ attempt.uncharged = proof.run.class;
459
+ if (proof.run.class === "decision" && typeof proof.run.decision_id === "string") {
460
+ attempt.blocked_on = proof.run.decision_id;
461
+ }
462
+ }
337
463
  return attempt;
338
464
  }
339
- const journalPath = workflowJournalPath(coordRoot, runId);
340
- if (existsSync(journalPath)) {
465
+ const transcriptPath = workflowTranscriptPath(coordRoot, runId);
466
+ if (existsSync(transcriptPath)) {
341
467
  let parked;
342
468
  let resumed = false;
343
469
  try {
344
- for (const line of readBoundedLines(journalPath, MAX_EVENTS_BYTES, WORKFLOW_JOURNAL_EVENT_BYTES, "workflow journal")) {
345
- const value = parseObject(line, `workflow run ${runId} journal`);
470
+ for (const line of readBoundedLines(transcriptPath, MAX_EVENTS_BYTES, WORKFLOW_TRANSCRIPT_EVENT_BYTES, "workflow transcript")) {
471
+ const value = parseObject(line, `workflow run ${runId} transcript`);
346
472
  if (value.event === "run.parked" && typeof value.approval_id === "string") {
347
473
  parked = value.approval_id;
348
474
  resumed = false;
@@ -361,8 +487,8 @@ function inspectAttempt(coordRoot, event, intent, priorRunId) {
361
487
  attempt.status = "running";
362
488
  }
363
489
  else {
364
- attempt.status = "journal_unreadable";
365
- attempt.journal_error = boundedJournalError(error.message);
490
+ attempt.status = "transcript_unreadable";
491
+ attempt.transcript_error = boundedTranscriptError(error.message);
366
492
  }
367
493
  return attempt;
368
494
  }
@@ -596,7 +722,13 @@ function validateWorkIntent(intent, workId) {
596
722
  !/^[a-f0-9]{64}$/.test(intent.workflow.sha256) ||
597
723
  !Number.isSafeInteger(intent.max_attempts) ||
598
724
  intent.max_attempts < 1 ||
599
- intent.max_attempts > 100) {
725
+ intent.max_attempts > 100 ||
726
+ // Optional for back-compat: absent on pre-ADR-0046 intents. When present it
727
+ // must be a valid bound.
728
+ (intent.max_uncharged_attempts !== undefined &&
729
+ (!Number.isSafeInteger(intent.max_uncharged_attempts) ||
730
+ intent.max_uncharged_attempts < 1 ||
731
+ intent.max_uncharged_attempts > 100))) {
600
732
  throw new Error(`work intent ${workId} has an unsupported or mismatched schema`);
601
733
  }
602
734
  boundedString(intent.title, "work title", MAX_TITLE);
@@ -743,9 +875,9 @@ function workDir(coordRoot, workId) {
743
875
  export function acquireWorkLease(coordRoot, workId) {
744
876
  return acquireWorkFileLease(coordRoot, workId, "lease.json", "is already active");
745
877
  }
746
- /** @internal Work journal mutation seam. */
878
+ /** @internal Work transcript mutation seam. */
747
879
  export function acquireWorkEventLease(coordRoot, workId) {
748
- return acquireWorkFileLease(coordRoot, workId, "events.lease.json", "event journal is already active");
880
+ return acquireWorkFileLease(coordRoot, workId, "events.lease.json", "event transcript is already active");
749
881
  }
750
882
  function acquireWorkFileLease(coordRoot, workId, filename, activeMessage) {
751
883
  readWorkIntent(coordRoot, workId);
@@ -862,8 +994,8 @@ function readBoundedLines(path, maxBytes, maxRecordBytes, field) {
862
994
  }
863
995
  return lines;
864
996
  }
865
- function boundedJournalError(message) {
866
- const normalized = message.trim() || "unknown journal read error";
997
+ function boundedTranscriptError(message) {
998
+ const normalized = message.trim() || "unknown transcript read error";
867
999
  return normalized.length > MAX_REASON ? normalized.slice(0, MAX_REASON) : normalized;
868
1000
  }
869
1001
  function parseObject(input, field) {
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Per-adapter CLI metadata: binary names plus install/login hints, shared by
3
+ * the spawn adapters (a not-found error should say how to fix it, not just
4
+ * that it happened) and `harn doctor`'s workflow-adapter checks.
5
+ *
6
+ * Install commands are the vendors' official one-liners; they drift rarely
7
+ * but they do drift — keep this module the single place they live.
8
+ */
9
+ import type { AdapterName } from "./types.js";
10
+ export declare const ADAPTER_BINARIES: Record<string, string>;
11
+ export declare const ADAPTER_INSTALL_HINTS: Record<string, string>;
12
+ /** How to authenticate each CLI with a subscription login (the billing
13
+ * default — see billing.ts). */
14
+ export declare const ADAPTER_LOGIN_HINTS: Record<string, string>;
15
+ /** One-line "it's missing, here's the fix" string for spawn adapters. */
16
+ export declare function notFoundError(adapter: AdapterName): string;
17
+ //# sourceMappingURL=adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEnD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAExD,CAAC;AAEF;gCACgC;AAChC,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEtD,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAK1D"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Per-adapter CLI metadata: binary names plus install/login hints, shared by
3
+ * the spawn adapters (a not-found error should say how to fix it, not just
4
+ * that it happened) and `harn doctor`'s workflow-adapter checks.
5
+ *
6
+ * Install commands are the vendors' official one-liners; they drift rarely
7
+ * but they do drift — keep this module the single place they live.
8
+ */
9
+ import { BUILTIN_ADAPTER_PROFILES } from "../adapters/profiles.js";
10
+ export const ADAPTER_BINARIES = Object.fromEntries(Object.values(BUILTIN_ADAPTER_PROFILES).map((profile) => [profile.id, profile.binary]));
11
+ export const ADAPTER_INSTALL_HINTS = Object.fromEntries(Object.values(BUILTIN_ADAPTER_PROFILES).map((profile) => [profile.id, profile.installHint]));
12
+ /** How to authenticate each CLI with a subscription login (the billing
13
+ * default — see billing.ts). */
14
+ export const ADAPTER_LOGIN_HINTS = Object.fromEntries(Object.values(BUILTIN_ADAPTER_PROFILES).map((profile) => [profile.id, profile.loginHint]));
15
+ /** One-line "it's missing, here's the fix" string for spawn adapters. */
16
+ export function notFoundError(adapter) {
17
+ const binary = ADAPTER_BINARIES[adapter] ?? adapter;
18
+ const install = ADAPTER_INSTALL_HINTS[adapter] ?? "install the adapter CLI";
19
+ const login = ADAPTER_LOGIN_HINTS[adapter] ?? "authenticate the adapter CLI";
20
+ return `${binary} CLI not found on PATH; ` + `install: ${install} then authenticate: ${login}`;
21
+ }
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { chmodSync, existsSync, linkSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
- import { appendWorkflowJournalEvent } from "./journal.js";
4
+ import { appendWorkflowTranscriptEvent } from "./transcript.js";
5
5
  export const WORKFLOW_APPROVAL_SCHEMA_VERSION = 1;
6
6
  const RECORD_LIMIT_BYTES = 128 * 1024;
7
7
  const RUN_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/;
@@ -67,7 +67,7 @@ export function resolveWorkflowApproval(input) {
67
67
  throw new Error(`approval ${input.approvalId} is already ${resolved.status}; conflicting ${input.verdict === "allow" ? "approval" : "denial"} refused`);
68
68
  }
69
69
  if (applied)
70
- appendResolutionJournal(input.coordRoot, resolved);
70
+ appendResolutionTranscript(input.coordRoot, resolved);
71
71
  return { approval: resolved, applied };
72
72
  }
73
73
  export function readWorkflowApproval(coordRoot, approvalId) {
@@ -133,11 +133,11 @@ export function renderWorkflowApproval(approval) {
133
133
  export function assertWorkflowRunId(runId) {
134
134
  assertRunId(runId);
135
135
  }
136
- function appendResolutionJournal(coordRoot, approval) {
137
- const journalPath = join(coordRoot, ".harnery", "workflows", approval.request.run_id, "journal.jsonl");
138
- if (!existsSync(journalPath) || !approval.decision)
136
+ function appendResolutionTranscript(coordRoot, approval) {
137
+ const transcriptPath = join(coordRoot, ".harnery", "workflows", approval.request.run_id, "transcript.jsonl");
138
+ if (!existsSync(transcriptPath) || !approval.decision)
139
139
  return;
140
- appendWorkflowJournalEvent(coordRoot, approval.request.run_id, "approval.resolved", {
140
+ appendWorkflowTranscriptEvent(coordRoot, approval.request.run_id, "approval.resolved", {
141
141
  ts: approval.decision.decided_at,
142
142
  stage: "",
143
143
  approval_id: approval.request.id,
@@ -1,23 +1,23 @@
1
1
  /**
2
- * Billing-mode probe: which auth a headless harness child will actually use.
2
+ * Billing-mode probe: which auth a headless adapter child will actually use.
3
3
  *
4
- * The engine never handles credentials — children are plain harness CLIs and
4
+ * The engine never handles credentials — children are plain adapter CLIs and
5
5
  * authenticate however that CLI does. But the CLIs prefer an exported API key
6
6
  * over a stored (subscription) login when both are present, and that override
7
7
  * is almost always an accident: a sourced .env or a leftover export silently
8
8
  * moves the run from subsidized subscription billing to per-token API billing.
9
- * This probe classifies the state per harness so the engine can refuse the
9
+ * This probe classifies the state per adapter so the engine can refuse the
10
10
  * silent-override case (see decision 0015 addendum) while leaving deliberate
11
11
  * key-only hosts (CI boxes with no login) working.
12
12
  *
13
13
  * Detection is a heuristic over well-known credential locations; when a
14
14
  * location can't prove presence or absence (e.g. Claude Code stores its OAuth
15
15
  * token in the macOS keychain, not a file), the state is "unknown" and the
16
- * engine never hard-fails on it — the harness CLI itself is the final
16
+ * engine never hard-fails on it — the adapter CLI itself is the final
17
17
  * authority and will error loudly if truly unauthenticated.
18
18
  */
19
- import type { HarnessName } from "./types.js";
20
- /** The env var each harness CLI reads as an API key (preferred over a stored
19
+ import type { AdapterName } from "./types.js";
20
+ /** The env var each adapter CLI reads as an API key (preferred over a stored
21
21
  * login when set). Shared with the child-env builder's subscription-only
22
22
  * scrub. */
23
23
  export declare const API_KEY_VARS: Record<string, string>;
@@ -31,7 +31,7 @@ export type BillingMode =
31
31
  * subsidized auth. The engine refuses this unless explicitly allowed. */
32
32
  | "api-key-override";
33
33
  export interface BillingProbe {
34
- harness: HarnessName;
34
+ adapter: AdapterName;
35
35
  /** The env var checked (from API_KEY_VARS), or a note when the key was
36
36
  * found in a credential file instead of the environment. */
37
37
  apiKeySource: string | null;
@@ -43,6 +43,6 @@ export interface ProbeIo {
43
43
  env?: NodeJS.ProcessEnv;
44
44
  home?: string;
45
45
  }
46
- export type BillingProber = (harness: HarnessName) => BillingProbe;
47
- export declare function probeBilling(harness: HarnessName, io?: ProbeIo): BillingProbe;
46
+ export type BillingProber = (adapter: AdapterName) => BillingProbe;
47
+ export declare function probeBilling(adapter: AdapterName, io?: ProbeIo): BillingProbe;
48
48
  //# sourceMappingURL=billing.d.ts.map
@@ -1,25 +1,25 @@
1
1
  /**
2
- * Billing-mode probe: which auth a headless harness child will actually use.
2
+ * Billing-mode probe: which auth a headless adapter child will actually use.
3
3
  *
4
- * The engine never handles credentials — children are plain harness CLIs and
4
+ * The engine never handles credentials — children are plain adapter CLIs and
5
5
  * authenticate however that CLI does. But the CLIs prefer an exported API key
6
6
  * over a stored (subscription) login when both are present, and that override
7
7
  * is almost always an accident: a sourced .env or a leftover export silently
8
8
  * moves the run from subsidized subscription billing to per-token API billing.
9
- * This probe classifies the state per harness so the engine can refuse the
9
+ * This probe classifies the state per adapter so the engine can refuse the
10
10
  * silent-override case (see decision 0015 addendum) while leaving deliberate
11
11
  * key-only hosts (CI boxes with no login) working.
12
12
  *
13
13
  * Detection is a heuristic over well-known credential locations; when a
14
14
  * location can't prove presence or absence (e.g. Claude Code stores its OAuth
15
15
  * token in the macOS keychain, not a file), the state is "unknown" and the
16
- * engine never hard-fails on it — the harness CLI itself is the final
16
+ * engine never hard-fails on it — the adapter CLI itself is the final
17
17
  * authority and will error loudly if truly unauthenticated.
18
18
  */
19
19
  import { existsSync, readFileSync } from "node:fs";
20
20
  import { homedir } from "node:os";
21
21
  import { join } from "node:path";
22
- /** The env var each harness CLI reads as an API key (preferred over a stored
22
+ /** The env var each adapter CLI reads as an API key (preferred over a stored
23
23
  * login when set). Shared with the child-env builder's subscription-only
24
24
  * scrub. */
25
25
  export const API_KEY_VARS = {
@@ -27,15 +27,15 @@ export const API_KEY_VARS = {
27
27
  codex: "OPENAI_API_KEY",
28
28
  cursor: "CURSOR_API_KEY",
29
29
  };
30
- export function probeBilling(harness, io = {}) {
30
+ export function probeBilling(adapter, io = {}) {
31
31
  const env = io.env ?? process.env;
32
32
  const home = io.home ?? homedir();
33
- const keyVar = API_KEY_VARS[harness];
33
+ const keyVar = API_KEY_VARS[adapter];
34
34
  const envKey = keyVar ? Boolean(env[keyVar]?.trim()) : false;
35
35
  let login;
36
36
  let apiKeyPresent = envKey;
37
37
  let apiKeySource = envKey ? keyVar : null;
38
- switch (harness) {
38
+ switch (adapter) {
39
39
  case "claude-code":
40
40
  login = probeClaudeLogin(home);
41
41
  break;
@@ -68,7 +68,7 @@ export function probeBilling(harness, io = {}) {
68
68
  : apiKeyPresent
69
69
  ? "api-key"
70
70
  : "subscription";
71
- return { harness, apiKeySource, apiKeyPresent, login, mode };
71
+ return { adapter, apiKeySource, apiKeyPresent, login, mode };
72
72
  }
73
73
  /** Claude Code: OAuth login lives at ~/.claude/.credentials.json on Linux;
74
74
  * macOS stores it in the keychain (dir exists, file doesn't → unknown). */
@@ -2,8 +2,8 @@
2
2
  * Child-process environment builder shared by every spawn adapter.
3
3
  *
4
4
  * Rules (the first is a hard-won Phase 1 spike finding):
5
- * 1. **Delete inherited harness-session vars, never blank them.** A nested
6
- * harness CLI under a live session inherits vars that make it exit 1 with
5
+ * 1. **Delete inherited adapter-session vars, never blank them.** A nested
6
+ * adapter CLI under a live session inherits vars that make it exit 1 with
7
7
  * empty output; an empty-string var still reads as set. Scrub all three
8
8
  * families (CLAUDE*, CODEX*, CURSOR*) regardless of which adapter spawns —
9
9
  * a codex child launched from inside a Claude Code session must not inherit
@@ -25,10 +25,18 @@
25
25
  * hooks stay on, keeping heartbeat + event capture.
26
26
  * 5. **Stamp the run id** (HARNERY_WORKFLOW_RUN_ID) so the coord layer and
27
27
  * web UI can associate child sessions with their workflow run.
28
+ * 6. **Stamp the agent id** (HARNERY_WORKFLOW_AGENT_ID) so that association is
29
+ * per-agent rather than only per-run. The orchestrator cannot use the child's
30
+ * session id for this: the adapter mints that id and reports it back only in
31
+ * the result envelope, which is to say only once the work being watched is
32
+ * over. Passing in the id the orchestrator already owns is the only way to
33
+ * attribute in-flight activity to a particular agent.
28
34
  */
29
35
  export interface ChildEnvOpts {
30
36
  /** Delete all API-key vars so children can only use stored logins. */
31
37
  subscriptionOnly?: boolean;
38
+ /** Transcript agent id (`a1`, `a2`, …) this child is running. */
39
+ agentId?: string;
32
40
  }
33
41
  export declare function buildChildEnv(runId?: string, opts?: ChildEnvOpts): Record<string, string>;
34
42
  //# sourceMappingURL=child-env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"child-env.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/child-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkB7F"}
1
+ {"version":3,"file":"child-env.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/child-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAOH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmB7F"}
@@ -2,8 +2,8 @@
2
2
  * Child-process environment builder shared by every spawn adapter.
3
3
  *
4
4
  * Rules (the first is a hard-won Phase 1 spike finding):
5
- * 1. **Delete inherited harness-session vars, never blank them.** A nested
6
- * harness CLI under a live session inherits vars that make it exit 1 with
5
+ * 1. **Delete inherited adapter-session vars, never blank them.** A nested
6
+ * adapter CLI under a live session inherits vars that make it exit 1 with
7
7
  * empty output; an empty-string var still reads as set. Scrub all three
8
8
  * families (CLAUDE*, CODEX*, CURSOR*) regardless of which adapter spawns —
9
9
  * a codex child launched from inside a Claude Code session must not inherit
@@ -25,10 +25,16 @@
25
25
  * hooks stay on, keeping heartbeat + event capture.
26
26
  * 5. **Stamp the run id** (HARNERY_WORKFLOW_RUN_ID) so the coord layer and
27
27
  * web UI can associate child sessions with their workflow run.
28
+ * 6. **Stamp the agent id** (HARNERY_WORKFLOW_AGENT_ID) so that association is
29
+ * per-agent rather than only per-run. The orchestrator cannot use the child's
30
+ * session id for this: the adapter mints that id and reports it back only in
31
+ * the result envelope, which is to say only once the work being watched is
32
+ * over. Passing in the id the orchestrator already owns is the only way to
33
+ * attribute in-flight activity to a particular agent.
28
34
  */
29
35
  import { API_KEY_VARS } from "./billing.js";
30
36
  const SCRUB_PREFIXES = ["CLAUDE", "CODEX", "CURSOR"];
31
- const PRESERVED_HARNESS_VARS = new Set(["CODEX_HOME"]);
37
+ const PRESERVED_ADAPTER_VARS = new Set(["CODEX_HOME"]);
32
38
  export function buildChildEnv(runId, opts = {}) {
33
39
  const env = {};
34
40
  const keyVars = new Set(Object.values(API_KEY_VARS));
@@ -39,7 +45,7 @@ export function buildChildEnv(runId, opts = {}) {
39
45
  continue;
40
46
  if (SCRUB_PREFIXES.some((p) => k.startsWith(p)) &&
41
47
  !keyVars.has(k) &&
42
- !PRESERVED_HARNESS_VARS.has(k)) {
48
+ !PRESERVED_ADAPTER_VARS.has(k)) {
43
49
  continue;
44
50
  }
45
51
  env[k] = v;
@@ -47,5 +53,7 @@ export function buildChildEnv(runId, opts = {}) {
47
53
  env.HARNERY_WORKFLOW_CHILD = "1";
48
54
  if (runId)
49
55
  env.HARNERY_WORKFLOW_RUN_ID = runId;
56
+ if (opts.agentId)
57
+ env.HARNERY_WORKFLOW_AGENT_ID = opts.agentId;
50
58
  return env;
51
59
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Workflow engine: loads a workflow script (plain JS, `export default
3
- * async (ctx) => …`), injects the ctx API, enforces the caps, journals every
4
- * step to `.harnery/workflows/<run-id>/journal.jsonl`, and returns a RunReport.
3
+ * async (ctx) => …`), injects the ctx API, enforces the caps, transcripts every
4
+ * step to `.harnery/workflows/<run-id>/transcript.jsonl`, and returns a RunReport.
5
5
  *
6
6
  * Guarantees the engine makes (the pitch, in code):
7
7
  * - **Bounded**: hard total-agent ceiling + bounded parallel() concurrency.
@@ -13,7 +13,7 @@
13
13
  * validate; failures re-prompt with the validation errors appended, up to
14
14
  * `maxAttempts`, then throw. Routing decisions read validated fields, so
15
15
  * the deterministic script — not a model — decides what runs next.
16
- * - **Journaled**: every stage/agent start+end lands in the run journal with
16
+ * - **Transcripted**: every stage/agent start+end lands in the run transcript with
17
17
  * cost, duration, and child session id (the resume + web-UI substrate).
18
18
  */
19
19
  import type { EngineOpts, RunReport } from "./types.js";
@@ -25,8 +25,18 @@ export declare class WorkflowRunError extends Error {
25
25
  export declare class WorkflowParkedError extends Error {
26
26
  readonly runId: string;
27
27
  readonly approvalId: string;
28
- readonly journalPath: string;
29
- constructor(message: string, runId: string, approvalId: string, journalPath: string);
28
+ readonly transcriptPath: string;
29
+ constructor(message: string, runId: string, approvalId: string, transcriptPath: string);
30
+ }
31
+ /** Thrown by ctx.blocked(). Carries the run out of the script and into the
32
+ * failure path, where its presence — not its message — is what stamps the proof
33
+ * with class "decision". A script cannot fake this by throwing an ordinary
34
+ * Error with a suggestive message, which is the point: the class has to mean
35
+ * "the script deliberately declared this", not "the text looked like it". */
36
+ export declare class WorkflowBlockedError extends Error {
37
+ readonly reason: string;
38
+ readonly decisionId?: string;
39
+ constructor(reason: string, decisionId?: string);
30
40
  }
31
41
  export declare function runWorkflow(scriptPath: string, opts: EngineOpts): Promise<RunReport>;
32
42
  //# sourceMappingURL=engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAyCH,OAAO,KAAK,EAEV,UAAU,EAGV,SAAS,EAYV,MAAM,YAAY,CAAC;AAsCpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM/E;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAOpF;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CA6E1F"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA0CH,OAAO,KAAK,EAIV,UAAU,EAEV,SAAS,EAYV,MAAM,YAAY,CAAC;AAsCpB,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAM/E;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;CAOvF;AAED;;;;6EAI6E;AAC7E,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAEjB,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAUhD;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CA6E1F"}