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
@@ -5,9 +5,9 @@ import { dirname, isAbsolute, join, resolve } from "node:path";
5
5
  import { assertWorkId, readWorkItem } from "../work/read.js";
6
6
  import { workflowScriptDigest } from "../workflow/run-state.js";
7
7
  import { normalizeWorkflowSpecialists } from "../workflow/specialists.js";
8
- import { readSupervisorPlans } from "./plan-read.js";
9
- import { MAX_SUPERVISOR_PLAN_REVIEWERS, MAX_SUPERVISOR_PLAN_REVISION_ROUNDS, supervisorGraphFingerprint, } from "./plan-types.js";
10
- export const SUPERVISOR_INTENT_SCHEMA_VERSION = 1;
8
+ import { readGovernorPlans } from "./plan-read.js";
9
+ import { governorGraphFingerprint, MAX_GOVERNOR_PLAN_REVIEWERS, MAX_GOVERNOR_PLAN_REVISION_ROUNDS, } from "./plan-types.js";
10
+ export const GOVERNOR_INTENT_SCHEMA_VERSION = 1;
11
11
  const GOAL_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
12
12
  const MAX_TITLE = 200;
13
13
  const MAX_OBJECTIVE = 4_000;
@@ -16,16 +16,23 @@ const MAX_INTENT_BYTES = 256 * 1024;
16
16
  const MAX_TEMPLATES = 20;
17
17
  const TEMPLATE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
18
18
  const FOREIGN_LEASE_STALE_MS = 24 * 60 * 60 * 1_000;
19
- export function createSupervisor(input) {
19
+ /** Ceiling on CONSECUTIVE uncharged (upstream) replans (ADR 0046). Because an
20
+ * uncharged replan does not spend `max_replans`, an unending vendor outage would
21
+ * otherwise replan forever; this bound stops it and names the outside service.
22
+ * Kept low — each replan is a real planner round-trip — and a module constant
23
+ * rather than a policy field to keep the frozen replanning schema unchanged; an
24
+ * environment failure self-bounds at one because it stops immediately. */
25
+ const MAX_UNCHARGED_REPLANS = 3;
26
+ export function createGovernor(input) {
20
27
  const coordRoot = resolve(input.coordRoot);
21
- const id = input.id ?? newSupervisorId();
22
- assertSupervisorId(id);
28
+ const id = input.id ?? newGovernorId();
29
+ assertGovernorId(id);
23
30
  const mission = input.mission ? normalizeMission(input.mission) : undefined;
24
31
  if (mission && !input.replanning) {
25
- throw new Error("supervisor mission requires a replanning policy");
32
+ throw new Error("governor mission requires a replanning policy");
26
33
  }
27
34
  if (!input.rootWorkId && !mission) {
28
- throw new Error("supervisor creation without root work requires a mission and replanning policy");
35
+ throw new Error("governor creation without root work requires a mission and replanning policy");
29
36
  }
30
37
  if (input.rootWorkId)
31
38
  assertWorkId(input.rootWorkId);
@@ -41,9 +48,9 @@ export function createSupervisor(input) {
41
48
  throw new Error("objective-first mission max_replans must exceed max_milestones to reserve completion review");
42
49
  }
43
50
  const intent = {
44
- schema_version: SUPERVISOR_INTENT_SCHEMA_VERSION,
51
+ schema_version: GOVERNOR_INTENT_SCHEMA_VERSION,
45
52
  id,
46
- title: bounded(input.title ?? root?.intent.title ?? missionTitle(mission), "supervisor title", MAX_TITLE),
53
+ title: bounded(input.title ?? root?.intent.title ?? missionTitle(mission), "governor title", MAX_TITLE),
47
54
  root_work_id: input.rootWorkId ?? missionRootId(id),
48
55
  specialists: normalizeWorkflowSpecialists(input.specialists),
49
56
  limits,
@@ -52,39 +59,39 @@ export function createSupervisor(input) {
52
59
  ...(replanning ? { replanning } : {}),
53
60
  created_at: new Date().toISOString(),
54
61
  };
55
- const path = supervisorIntentPath(coordRoot, id);
62
+ const path = governorIntentPath(coordRoot, id);
56
63
  mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
57
64
  chmodSync(dirname(path), 0o700);
58
65
  writePrivateJson(path, intent);
59
- return readSupervisor(coordRoot, id);
66
+ return readGovernor(coordRoot, id);
60
67
  }
61
- export function readSupervisor(coordRoot, goalId) {
62
- return readSupervisorInternal(coordRoot, goalId, false);
68
+ export function readGovernor(coordRoot, goalId) {
69
+ return readGovernorInternal(coordRoot, goalId, false);
63
70
  }
64
- /** @internal Runner seam; ignores the lease held by this supervisor process. */
65
- export function readSupervisorIgnoringLease(coordRoot, goalId) {
66
- return readSupervisorInternal(coordRoot, goalId, true);
71
+ /** @internal Runner seam; ignores the lease held by this governor process. */
72
+ export function readGovernorIgnoringLease(coordRoot, goalId) {
73
+ return readGovernorInternal(coordRoot, goalId, true);
67
74
  }
68
- export function listSupervisors(coordRoot) {
69
- const base = join(resolve(coordRoot), ".harnery", "supervisors");
75
+ export function listGovernors(coordRoot) {
76
+ const base = join(resolve(coordRoot), ".harnery", "governors");
70
77
  if (!existsSync(base))
71
78
  return [];
72
79
  const records = [];
73
80
  for (const name of readdirSync(base)) {
74
- if (!GOAL_ID.test(name) || !existsSync(supervisorIntentPath(coordRoot, name)))
81
+ if (!GOAL_ID.test(name) || !existsSync(governorIntentPath(coordRoot, name)))
75
82
  continue;
76
- records.push(readSupervisor(coordRoot, name));
83
+ records.push(readGovernor(coordRoot, name));
77
84
  }
78
85
  return records.sort((left, right) => right.intent.created_at.localeCompare(left.intent.created_at));
79
86
  }
80
- export function collectSupervisorWork(coordRoot, rootWorkId) {
87
+ export function collectGovernorWork(coordRoot, rootWorkId) {
81
88
  const records = new Map();
82
89
  const visiting = new Set();
83
90
  const visit = (workId) => {
84
91
  if (records.has(workId))
85
92
  return;
86
93
  if (visiting.has(workId))
87
- throw new Error(`supervisor work graph contains a cycle at ${workId}`);
94
+ throw new Error(`governor work graph contains a cycle at ${workId}`);
88
95
  visiting.add(workId);
89
96
  const record = readWorkItem(coordRoot, workId);
90
97
  for (const dependency of record.intent.dependencies)
@@ -95,17 +102,17 @@ export function collectSupervisorWork(coordRoot, rootWorkId) {
95
102
  visit(rootWorkId);
96
103
  return Array.from(records.values());
97
104
  }
98
- export function assertSupervisorId(goalId) {
105
+ export function assertGovernorId(goalId) {
99
106
  if (!GOAL_ID.test(goalId))
100
- throw new Error(`invalid supervisor id ${JSON.stringify(goalId)}`);
107
+ throw new Error(`invalid governor id ${JSON.stringify(goalId)}`);
101
108
  }
102
- export function newSupervisorId() {
109
+ export function newGovernorId() {
103
110
  return `goal-${new Date().toISOString().replace(/[:.]/g, "-")}-${randomBytes(3).toString("hex")}`;
104
111
  }
105
- /** @internal Runner seam; one exclusive crash-recoverable supervisor lease. */
106
- export function acquireSupervisorLease(coordRoot, goalId) {
107
- readSupervisorIntent(coordRoot, goalId);
108
- const path = join(supervisorDir(coordRoot, goalId), "lease.json");
112
+ /** @internal Runner seam; one exclusive crash-recoverable governor lease. */
113
+ export function acquireGovernorLease(coordRoot, goalId) {
114
+ readGovernorIntent(coordRoot, goalId);
115
+ const path = join(governorDir(coordRoot, goalId), "lease.json");
109
116
  const owner = {
110
117
  pid: process.pid,
111
118
  host: hostname(),
@@ -133,11 +140,11 @@ export function acquireSupervisorLease(coordRoot, goalId) {
133
140
  if (!acquire()) {
134
141
  const existing = readLease(path);
135
142
  if (existing && leaseIsLive(existing)) {
136
- throw new Error(`supervisor ${goalId} is already running under pid ${existing.pid} on ${existing.host}`);
143
+ throw new Error(`governor ${goalId} is already running under pid ${existing.pid} on ${existing.host}`);
137
144
  }
138
145
  unlinkSync(path);
139
146
  if (!acquire())
140
- throw new Error(`supervisor ${goalId} lease raced with another process`);
147
+ throw new Error(`governor ${goalId} lease raced with another process`);
141
148
  }
142
149
  return () => {
143
150
  try {
@@ -150,15 +157,15 @@ export function acquireSupervisorLease(coordRoot, goalId) {
150
157
  }
151
158
  };
152
159
  }
153
- function readSupervisorInternal(coordRootRaw, goalId, ignoreLease) {
160
+ function readGovernorInternal(coordRootRaw, goalId, ignoreLease) {
154
161
  const coordRoot = resolve(coordRootRaw);
155
- const intent = readSupervisorIntent(coordRoot, goalId);
156
- const plans = readSupervisorPlans(coordRoot, intent.id, intent.root_work_id);
162
+ const intent = readGovernorIntent(coordRoot, goalId);
163
+ const plans = readGovernorPlans(coordRoot, intent.id, intent.root_work_id);
157
164
  const activeRootExists = workIntentExists(coordRoot, plans.active_root_work_id);
158
165
  if (!activeRootExists && (!intent.mission || plans.generation > 0)) {
159
- throw new Error(`supervisor ${intent.id} root work is missing`);
166
+ throw new Error(`governor ${intent.id} root work is missing`);
160
167
  }
161
- const work = activeRootExists ? collectSupervisorWork(coordRoot, plans.active_root_work_id) : [];
168
+ const work = activeRootExists ? collectGovernorWork(coordRoot, plans.active_root_work_id) : [];
162
169
  const governed = collectGovernedWork(coordRoot, intent.root_work_id, plans, work);
163
170
  return {
164
171
  intent,
@@ -170,6 +177,20 @@ function readSupervisorInternal(coordRootRaw, goalId, ignoreLease) {
170
177
  function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease) {
171
178
  const root = work.find((record) => record.intent.id === plans.active_root_work_id);
172
179
  const attemptsUsed = governed.reduce((sum, record) => sum + record.projection.attempts_used, 0);
180
+ // The goal budget, like the per-item budget, counts only charged attempts
181
+ // (ADR 0046): an uncharged environment/upstream attempt on any child does not
182
+ // spend the goal's total. attempts_used stays the raw count for display.
183
+ const chargedUsed = governed.reduce((sum, record) => sum + record.projection.charged_attempts, 0);
184
+ // Replans, like per-item attempts (ADR 0046), are budgeted by the CHARGED
185
+ // count: an uncharged planner failure (environment/upstream) does not spend
186
+ // max_replans. replans_used stays the raw count for display.
187
+ const unchargedReplans = plans.plans.filter((plan) => plan.status === "failed" && isUnchargedPlanClass(plan.class)).length;
188
+ const chargedReplans = plans.plans.length - unchargedReplans;
189
+ // Attribute the consumed replans that did not advance the graph so the
190
+ // projection can distinguish planner no-proposal exhaustion from reviewer
191
+ // rejection through existing plan seams (review receipt presence), rather than
192
+ // reporting both as a single undifferentiated replan exhaustion.
193
+ const replanConsumption = classifyReplanConsumption(plans);
173
194
  const readyWork = work
174
195
  .filter((record) => record.projection.state === "ready")
175
196
  .map((record) => record.intent.id);
@@ -193,6 +214,15 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
193
214
  const terminalBlocked = work
194
215
  .filter((record) => record.projection.state === "blocked" && record.projection.next_action === "none")
195
216
  .map((record) => record.intent.id);
217
+ // Work stopped on a person, kept apart from the rest of terminalBlocked. Every
218
+ // other terminal block is something an agent could in principle clear; this one
219
+ // can only be cleared by a ruling, so it is the thing worth saying out loud.
220
+ const decisionBlocked = work
221
+ .filter((record) => record.projection.blocked_on_decision !== undefined)
222
+ .map((record) => ({
223
+ work_id: record.intent.id,
224
+ decision_id: record.projection.blocked_on_decision || undefined,
225
+ }));
196
226
  const attentionWork = unique([
197
227
  ...pendingApproval,
198
228
  ...(intent.automation.accept_passing_proof ? [] : reviews),
@@ -204,6 +234,12 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
204
234
  const initialRootAccepted = intent.mission !== undefined &&
205
235
  governed.some((record) => record.intent.id === intent.root_work_id && record.projection.state === "succeeded");
206
236
  const milestonesCompleted = plans.milestones_completed + (initialRootAccepted ? 1 : 0);
237
+ const resumableDispatchable = intent.automation.resume_approved ? resumableWork : [];
238
+ const attemptDispatchable = [
239
+ ...readyWork,
240
+ ...(intent.automation.retry_blocked ? retryableWork : []),
241
+ ];
242
+ const dispatchable = [...resumableDispatchable, ...attemptDispatchable];
207
243
  const base = {
208
244
  id: intent.id,
209
245
  title: intent.title,
@@ -214,23 +250,25 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
214
250
  resumable_work: resumableWork,
215
251
  retryable_work: retryableWork,
216
252
  attention_work: attentionWork,
253
+ decision_blocked_work: decisionBlocked,
217
254
  attempts_used: attemptsUsed,
218
- attempts_remaining: Math.max(0, intent.limits.max_total_attempts - attemptsUsed),
255
+ attempts_remaining: Math.max(0, intent.limits.max_total_attempts - chargedUsed),
219
256
  specialists: Object.keys(intent.specialists),
220
257
  plan_generation: plans.generation,
221
258
  replans_used: plans.plans.length,
222
- replans_remaining: Math.max(0, (intent.replanning?.max_replans ?? 0) - plans.plans.length),
259
+ replans_remaining: Math.max(0, (intent.replanning?.max_replans ?? 0) - chargedReplans),
223
260
  milestones_completed: milestonesCompleted,
224
261
  milestones_remaining: Math.max(0, (intent.mission?.max_milestones ?? 0) - milestonesCompleted),
225
262
  pending_plan_id: plans.latest?.status === "proposed" ? plans.latest.request.id : undefined,
226
263
  latest_plan_status: plans.latest?.status,
264
+ ...(replanConsumption.planner_no_proposal > 0 ? { replan_consumption: replanConsumption } : {}),
227
265
  governed_work_ids: governed.map((record) => record.intent.id),
228
266
  };
229
- if (!ignoreLease && supervisorLeaseIsLive(coordRoot, intent.id)) {
267
+ if (!ignoreLease && governorLeaseIsLive(coordRoot, intent.id)) {
230
268
  return {
231
269
  ...base,
232
270
  state: "running",
233
- reason: "the foreground supervisor holds the goal lease",
271
+ reason: "the foreground governor holds the goal lease",
234
272
  next_action: "wait_for_run",
235
273
  };
236
274
  }
@@ -242,6 +280,19 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
242
280
  next_action: "none",
243
281
  };
244
282
  }
283
+ // ADR 0050: a mission whose completion was reopened dispatches the reopened work
284
+ // before anything else. Without this the goal falls through to the milestone
285
+ // branch below, which still sees a succeeded root when the reopened item is one
286
+ // of its children, and would spend a replan reassessing a mission whose real
287
+ // remaining work is already sitting in ready_work.
288
+ if (intent.mission && plans.latest?.status === "reopened" && dispatchable.length > 0) {
289
+ return {
290
+ ...base,
291
+ state: "ready",
292
+ reason: `mission completion was reopened; ${dispatchable.length} work item${dispatchable.length === 1 ? " is" : "s are"} dispatchable`,
293
+ next_action: "run",
294
+ };
295
+ }
245
296
  if (plans.latest?.status === "proposed") {
246
297
  return {
247
298
  ...base,
@@ -266,7 +317,58 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
266
317
  next_action: "replan",
267
318
  };
268
319
  }
269
- const triggerFingerprint = supervisorGraphFingerprint({
320
+ // ADR 0046: a planner failure that never touched the plan is handled before
321
+ // the replan path. Otherwise a "failed" plan falls through to canReplan and
322
+ // the runner replans an unchanged environment on every tick — the failure mode
323
+ // that burned the measured 19 "codex not found" replans.
324
+ if (plans.latest?.status === "failed" && plans.latest.class === "environment") {
325
+ // A missing precondition (the planner binary was absent). Retrying an
326
+ // unchanged environment cannot help, so the goal STOPS and names it. A human
327
+ // who installs the binary can re-run; the failure was uncharged, so the
328
+ // replan budget is intact.
329
+ return {
330
+ ...base,
331
+ state: "blocked",
332
+ reason: `planning could not start; a required precondition is missing: ${plans.latest.reason ?? "the planner binary was absent"}`,
333
+ next_action: "none",
334
+ };
335
+ }
336
+ if (plans.latest?.status === "failed" && plans.latest.class === "decision") {
337
+ // The planner concluded that a human must rule before this can be planned.
338
+ // Stop and say so. Replanning would re-ask a question the planner already
339
+ // answered correctly, which is how a goal spins without a person noticing.
340
+ return {
341
+ ...base,
342
+ state: "blocked",
343
+ reason: `planning is waiting on a human decision: ${plans.latest.reason ?? "the planner did not say which"}`,
344
+ next_action: "none",
345
+ };
346
+ }
347
+ if (plans.latest?.status === "failed" && plans.latest.class === "upstream") {
348
+ // The vendor refused. Uncharged replans do not spend max_replans, so the
349
+ // only brake on an unending outage is this consecutive bound; at the limit
350
+ // the goal stops and names the outside service, distinct from work-blocked.
351
+ let trailingUncharged = 0;
352
+ for (let index = plans.plans.length - 1; index >= 0; index--) {
353
+ const plan = plans.plans[index];
354
+ if (plan.status !== "failed" || !isUnchargedPlanClass(plan.class)) {
355
+ break;
356
+ }
357
+ trailingUncharged++;
358
+ }
359
+ if (trailingUncharged >= MAX_UNCHARGED_REPLANS) {
360
+ return {
361
+ ...base,
362
+ state: "blocked",
363
+ reason: `planning is blocked waiting on an outside service after ${trailingUncharged} consecutive uncharged attempt(s): ${plans.latest.reason ?? "the vendor refused"}`,
364
+ next_action: "none",
365
+ };
366
+ }
367
+ // Under the bound: fall through so the goal replans when nothing else is
368
+ // dispatchable — the vendor may have recovered. canReplan reads
369
+ // chargedReplans, so these uncharged attempts do not exhaust max_replans.
370
+ }
371
+ const triggerFingerprint = governorGraphFingerprint({
270
372
  rootWorkId: plans.active_root_work_id,
271
373
  generation: plans.generation,
272
374
  work,
@@ -275,22 +377,23 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
275
377
  plans.latest.request.prior_root_work_id === plans.active_root_work_id &&
276
378
  plans.latest.status === "attention";
277
379
  if (latestHandledSameGraph && plans.latest) {
380
+ const canRetry = intent.replanning !== undefined && chargedReplans < intent.replanning.max_replans;
278
381
  return {
279
382
  ...base,
280
383
  state: "awaiting_attention",
281
- reason: plans.latest.reason ?? `plan ${plans.latest.request.id} requires attention`,
384
+ reason: canRetry
385
+ ? (plans.latest.reason ?? `plan ${plans.latest.request.id} requires attention`)
386
+ : exhaustedAttentionReason(plans.latest, replanConsumption),
282
387
  attention_plan_id: plans.latest.request.id,
283
- next_action: intent.replanning && plans.plans.length < intent.replanning.max_replans
284
- ? "retry_plan"
285
- : "none",
388
+ next_action: canRetry ? "retry_plan" : "none",
286
389
  };
287
390
  }
288
391
  if (!root && intent.mission) {
289
- if (!intent.replanning || plans.plans.length >= intent.replanning.max_replans) {
392
+ if (!intent.replanning || chargedReplans >= intent.replanning.max_replans) {
290
393
  return {
291
394
  ...base,
292
395
  state: "budget_exhausted",
293
- reason: "mission exhausted its planning budget before creating an initial milestone",
396
+ reason: replanBudgetReason("mission exhausted its planning budget before creating an initial milestone", replanConsumption),
294
397
  next_action: "none",
295
398
  };
296
399
  }
@@ -302,13 +405,13 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
302
405
  };
303
406
  }
304
407
  if (!root)
305
- throw new Error(`supervisor ${intent.id} root work is missing`);
408
+ throw new Error(`governor ${intent.id} root work is missing`);
306
409
  if (root.projection.state === "succeeded" && intent.mission) {
307
- if (!intent.replanning || plans.plans.length >= intent.replanning.max_replans) {
410
+ if (!intent.replanning || chargedReplans >= intent.replanning.max_replans) {
308
411
  return {
309
412
  ...base,
310
413
  state: "budget_exhausted",
311
- reason: "mission exhausted its planning budget at a milestone boundary",
414
+ reason: replanBudgetReason("mission exhausted its planning budget at a milestone boundary", replanConsumption),
312
415
  next_action: "none",
313
416
  };
314
417
  }
@@ -327,12 +430,6 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
327
430
  next_action: "none",
328
431
  };
329
432
  }
330
- const resumableDispatchable = intent.automation.resume_approved ? resumableWork : [];
331
- const attemptDispatchable = [
332
- ...readyWork,
333
- ...(intent.automation.retry_blocked ? retryableWork : []),
334
- ];
335
- const dispatchable = [...resumableDispatchable, ...attemptDispatchable];
336
433
  if (intent.automation.accept_passing_proof && reviews.length > 0) {
337
434
  return {
338
435
  ...base,
@@ -349,7 +446,7 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
349
446
  next_action: "run",
350
447
  };
351
448
  }
352
- if (attemptsUsed >= intent.limits.max_total_attempts && attemptDispatchable.length > 0) {
449
+ if (chargedUsed >= intent.limits.max_total_attempts && attemptDispatchable.length > 0) {
353
450
  return {
354
451
  ...base,
355
452
  state: "budget_exhausted",
@@ -397,7 +494,7 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
397
494
  next_action: "retry",
398
495
  };
399
496
  }
400
- if (attemptsUsed >= intent.limits.max_total_attempts && cancelled.length === 0) {
497
+ if (chargedUsed >= intent.limits.max_total_attempts && cancelled.length === 0) {
401
498
  return {
402
499
  ...base,
403
500
  state: "budget_exhausted",
@@ -406,7 +503,7 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
406
503
  };
407
504
  }
408
505
  const canReplan = intent.replanning !== undefined &&
409
- plans.plans.length < intent.replanning.max_replans &&
506
+ chargedReplans < intent.replanning.max_replans &&
410
507
  cancelled.length === 0 &&
411
508
  !latestHandledSameGraph;
412
509
  if (canReplan) {
@@ -420,50 +517,127 @@ function deriveProjection(coordRoot, intent, work, governed, plans, ignoreLease)
420
517
  };
421
518
  }
422
519
  if (intent.replanning &&
423
- plans.plans.length >= intent.replanning.max_replans &&
520
+ chargedReplans >= intent.replanning.max_replans &&
424
521
  cancelled.length === 0) {
425
522
  return {
426
523
  ...base,
427
524
  state: "budget_exhausted",
428
- reason: `goal exhausted its ${intent.replanning.max_replans} replans`,
525
+ reason: replanBudgetReason(`goal exhausted its ${intent.replanning.max_replans} replans`, replanConsumption),
429
526
  next_action: "none",
430
527
  };
431
528
  }
432
529
  return {
433
530
  ...base,
434
531
  state: "blocked",
435
- reason: attentionWork.length > 0
436
- ? `${attentionWork.length} work item${attentionWork.length === 1 ? " needs" : "s need"} intervention`
437
- : "goal graph has no legal progress action",
532
+ // Lead with the decisions when there are any. "3 work items need
533
+ // intervention" reads as a queue an agent will get to; "waiting on you to
534
+ // rule on X" is the only phrasing that reaches the person who can clear it.
535
+ reason: decisionBlocked.length > 0
536
+ ? `${decisionBlocked.length} work item${decisionBlocked.length === 1 ? " is" : "s are"} waiting on a human decision: ${describeDecisionBlocks(decisionBlocked)}`
537
+ : attentionWork.length > 0
538
+ ? `${attentionWork.length} work item${attentionWork.length === 1 ? " needs" : "s need"} intervention`
539
+ : "goal graph has no legal progress action",
438
540
  next_action: "none",
439
541
  };
440
542
  }
441
- function readSupervisorIntent(coordRoot, goalId) {
442
- assertSupervisorId(goalId);
443
- const path = supervisorIntentPath(coordRoot, goalId);
543
+ /** Bounded, operator-readable list of what is waiting on a ruling. */
544
+ function describeDecisionBlocks(blocks) {
545
+ const shown = blocks
546
+ .slice(0, 3)
547
+ .map((b) => (b.decision_id ? `${b.work_id} (${b.decision_id})` : b.work_id))
548
+ .join(", ");
549
+ return blocks.length > 3 ? `${shown}, +${blocks.length - 3} more` : shown;
550
+ }
551
+ /**
552
+ * Classify each consumed replan that did not advance the graph, using existing
553
+ * plan seams only. A plan carries a review receipt exactly when a proposal was
554
+ * produced and independently reviewed, so its presence separates a reviewer
555
+ * rejection from a planner run that produced no reviewable proposal. Uncharged
556
+ * environment/upstream planner failures (ADR 0046) do not spend the replan
557
+ * budget and are attributed to their outside precondition, not counted here.
558
+ */
559
+ /** Whether a failed plan told us nothing about the plan, and so must not spend
560
+ * a replan (ADR 0046). All three classes mean "replanning this cannot help":
561
+ * the binary is missing, the vendor is down, or a person has to rule. */
562
+ function isUnchargedPlanClass(value) {
563
+ return value === "environment" || value === "upstream" || value === "decision";
564
+ }
565
+ function classifyReplanConsumption(plans) {
566
+ let reviewerRejection = 0;
567
+ let plannerNoProposal = 0;
568
+ for (const plan of plans.plans) {
569
+ if (plan.status === "failed" && isUnchargedPlanClass(plan.class)) {
570
+ continue;
571
+ }
572
+ if (plan.review && plan.review.status !== "passed") {
573
+ reviewerRejection++;
574
+ }
575
+ else if (!plan.review &&
576
+ (plan.status === "attention" ||
577
+ plan.status === "interrupted" ||
578
+ plan.status === "failed" ||
579
+ plan.status === "retry_requested")) {
580
+ // `retry_requested` is a planner no-proposal attention the operator asked to
581
+ // replan: the original run still produced no reviewable proposal and still
582
+ // spent a charged replan, so it belongs in this bucket even though a later
583
+ // plan superseded it. Omitting it would misattribute a retried no-proposal
584
+ // to nothing and let the reason read as pure review exhaustion.
585
+ plannerNoProposal++;
586
+ }
587
+ }
588
+ return { reviewer_rejection: reviewerRejection, planner_no_proposal: plannerNoProposal };
589
+ }
590
+ /**
591
+ * Reason for a goal held at `awaiting_attention/none` because its latest plan is
592
+ * an unresolved attention and no replan slot remains. The latest plan's own
593
+ * per-plan reason always leads (a reviewed-and-rejected latest reports its
594
+ * review-round exhaustion verbatim), then `replanBudgetReason` names the planner
595
+ * no-proposal share of the consumed budget. This keeps the `projection.reason`
596
+ * field carrying the same truth the operator-visible row does: a goal whose
597
+ * budget was mostly spent by planner no-proposal runs is not attributed wholesale
598
+ * to review just because its final, reviewed plan happened to be rejected.
599
+ */
600
+ function exhaustedAttentionReason(latest, consumption) {
601
+ const fallback = latest.reason ?? `plan ${latest.request.id} requires attention`;
602
+ return replanBudgetReason(fallback, consumption);
603
+ }
604
+ /**
605
+ * Append planner no-proposal attribution to a replan-exhaustion reason. Returns
606
+ * the base reason unchanged when no consumed replan was a planner no-proposal
607
+ * outcome, so goals without that history project exactly as before.
608
+ */
609
+ function replanBudgetReason(base, consumption) {
610
+ if (consumption.planner_no_proposal <= 0)
611
+ return base;
612
+ const count = consumption.planner_no_proposal;
613
+ return `${base}; ${count} replan${count === 1 ? "" : "s"} ended with the planner producing no proposal`;
614
+ }
615
+ function readGovernorIntent(coordRoot, goalId) {
616
+ assertGovernorId(goalId);
617
+ const path = governorIntentPath(coordRoot, goalId);
444
618
  if (!existsSync(path))
445
- throw new Error(`supervisor ${goalId} does not exist`);
619
+ throw new Error(`governor ${goalId} does not exist`);
446
620
  const size = statSync(path).size;
447
621
  if (size <= 0 || size > MAX_INTENT_BYTES) {
448
- throw new Error(`supervisor intent has invalid size ${size}`);
622
+ throw new Error(`governor intent has invalid size ${size}`);
449
623
  }
450
624
  let intent;
451
625
  try {
452
626
  intent = JSON.parse(readFileSync(path, "utf8"));
453
627
  }
454
628
  catch (error) {
455
- throw new Error(`cannot parse supervisor intent ${goalId}: ${error.message}`);
629
+ throw new Error(`cannot parse governor intent ${goalId}: ${error.message}`);
456
630
  }
457
631
  validateIntent(intent, goalId);
458
632
  return intent;
459
633
  }
460
634
  function validateIntent(intent, goalId) {
461
- if (intent.schema_version !== SUPERVISOR_INTENT_SCHEMA_VERSION ||
635
+ if (intent.schema_version !== GOVERNOR_INTENT_SCHEMA_VERSION ||
462
636
  intent.id !== goalId ||
463
637
  !validTimestamp(intent.created_at)) {
464
- throw new Error(`supervisor intent ${goalId} has an unsupported or mismatched schema`);
638
+ throw new Error(`governor intent ${goalId} has an unsupported or mismatched schema`);
465
639
  }
466
- bounded(intent.title, "supervisor title", MAX_TITLE);
640
+ bounded(intent.title, "governor title", MAX_TITLE);
467
641
  assertWorkId(intent.root_work_id);
468
642
  if (intent.mission) {
469
643
  const normalizedMission = normalizeMission({
@@ -472,40 +646,40 @@ function validateIntent(intent, goalId) {
472
646
  maxMilestones: intent.mission.max_milestones,
473
647
  });
474
648
  if (JSON.stringify(normalizedMission) !== JSON.stringify(intent.mission)) {
475
- throw new Error(`supervisor intent ${goalId} mission is not canonical`);
649
+ throw new Error(`governor intent ${goalId} mission is not canonical`);
476
650
  }
477
651
  if (!intent.replanning) {
478
- throw new Error(`supervisor intent ${goalId} mission requires replanning`);
652
+ throw new Error(`governor intent ${goalId} mission requires replanning`);
479
653
  }
480
654
  }
481
655
  const specialists = normalizeWorkflowSpecialists(intent.specialists);
482
656
  if (JSON.stringify(specialists) !== JSON.stringify(intent.specialists)) {
483
- throw new Error(`supervisor intent ${goalId} specialists are not canonical`);
657
+ throw new Error(`governor intent ${goalId} specialists are not canonical`);
484
658
  }
485
659
  if (JSON.stringify(normalizeLimits(intent.limits)) !== JSON.stringify(intent.limits)) {
486
- throw new Error(`supervisor intent ${goalId} limits are not canonical`);
660
+ throw new Error(`governor intent ${goalId} limits are not canonical`);
487
661
  }
488
662
  if (JSON.stringify(normalizeAutomation(intent.automation)) !== JSON.stringify(intent.automation)) {
489
- throw new Error(`supervisor intent ${goalId} automation policy is not canonical`);
663
+ throw new Error(`governor intent ${goalId} automation policy is not canonical`);
490
664
  }
491
665
  if (intent.replanning)
492
666
  validateReplanning(intent.replanning, specialists, intent.limits, goalId);
493
667
  }
494
668
  function normalizeMission(input) {
495
669
  if (!Array.isArray(input.acceptance)) {
496
- throw new Error("supervisor mission acceptance must be an array");
670
+ throw new Error("governor mission acceptance must be an array");
497
671
  }
498
672
  if (input.acceptance.length < 1 || input.acceptance.length > MAX_ACCEPTANCE) {
499
- throw new Error(`supervisor mission acceptance must contain 1 to ${MAX_ACCEPTANCE} criteria`);
673
+ throw new Error(`governor mission acceptance must contain 1 to ${MAX_ACCEPTANCE} criteria`);
500
674
  }
501
- const acceptance = input.acceptance.map((criterion, index) => bounded(criterion, `supervisor mission acceptance[${index}]`, 500));
675
+ const acceptance = input.acceptance.map((criterion, index) => bounded(criterion, `governor mission acceptance[${index}]`, 500));
502
676
  if (new Set(acceptance).size !== acceptance.length) {
503
- throw new Error("supervisor mission acceptance criteria must be unique");
677
+ throw new Error("governor mission acceptance criteria must be unique");
504
678
  }
505
679
  return {
506
- objective: bounded(input.objective, "supervisor mission objective", MAX_OBJECTIVE),
680
+ objective: bounded(input.objective, "governor mission objective", MAX_OBJECTIVE),
507
681
  acceptance,
508
- max_milestones: positive(input.maxMilestones ?? 4, "supervisor mission max_milestones", 20),
682
+ max_milestones: positive(input.maxMilestones ?? 4, "governor mission max_milestones", 20),
509
683
  };
510
684
  }
511
685
  function missionTitle(mission) {
@@ -515,12 +689,12 @@ function missionTitle(mission) {
515
689
  }
516
690
  function normalizeLimits(input) {
517
691
  return {
518
- max_cycles: positive(input?.max_cycles ?? 50, "supervisor max_cycles", 1_000),
519
- max_runtime_ms: positive(input?.max_runtime_ms ?? 4 * 60 * 60 * 1_000, "supervisor max_runtime_ms", 7 * 24 * 60 * 60 * 1_000),
520
- max_parallel_work: positive(input?.max_parallel_work ?? 1, "supervisor max_parallel_work", 20),
521
- max_total_attempts: positive(input?.max_total_attempts ?? 100, "supervisor max_total_attempts", 10_000),
522
- max_agents_per_work: positive(input?.max_agents_per_work ?? 20, "supervisor max_agents_per_work", 1_000),
523
- agent_concurrency: positive(input?.agent_concurrency ?? 4, "supervisor agent_concurrency", 100),
692
+ max_cycles: positive(input?.max_cycles ?? 50, "governor max_cycles", 1_000),
693
+ max_runtime_ms: positive(input?.max_runtime_ms ?? 4 * 60 * 60 * 1_000, "governor max_runtime_ms", 7 * 24 * 60 * 60 * 1_000),
694
+ max_parallel_work: positive(input?.max_parallel_work ?? 1, "governor max_parallel_work", 20),
695
+ max_total_attempts: positive(input?.max_total_attempts ?? 100, "governor max_total_attempts", 10_000),
696
+ max_agents_per_work: positive(input?.max_agents_per_work ?? 20, "governor max_agents_per_work", 1_000),
697
+ agent_concurrency: positive(input?.agent_concurrency ?? 4, "governor agent_concurrency", 100),
524
698
  };
525
699
  }
526
700
  function normalizeAutomation(input) {
@@ -583,8 +757,8 @@ function normalizeReviewPolicy(input, specialists, plannerSpecialist, limits) {
583
757
  if (!Array.isArray(input.reviewerSpecialists) || input.reviewerSpecialists.length < 1) {
584
758
  throw new Error("replanning review requires at least one reviewer specialist");
585
759
  }
586
- if (input.reviewerSpecialists.length > MAX_SUPERVISOR_PLAN_REVIEWERS) {
587
- throw new Error(`replanning review cannot exceed ${MAX_SUPERVISOR_PLAN_REVIEWERS} reviewer specialists`);
760
+ if (input.reviewerSpecialists.length > MAX_GOVERNOR_PLAN_REVIEWERS) {
761
+ throw new Error(`replanning review cannot exceed ${MAX_GOVERNOR_PLAN_REVIEWERS} reviewer specialists`);
588
762
  }
589
763
  const reviewerSpecialists = input.reviewerSpecialists.map((specialist, index) => bounded(specialist, `reviewer specialist[${index}]`, 100));
590
764
  if (new Set(reviewerSpecialists).size !== reviewerSpecialists.length) {
@@ -598,7 +772,7 @@ function normalizeReviewPolicy(input, specialists, plannerSpecialist, limits) {
598
772
  throw new Error("reviewer specialist cannot be the planner specialist");
599
773
  }
600
774
  }
601
- const maxRevisionRounds = nonNegative(input.maxRevisionRounds, "replanning review max_revision_rounds", MAX_SUPERVISOR_PLAN_REVISION_ROUNDS);
775
+ const maxRevisionRounds = nonNegative(input.maxRevisionRounds, "replanning review max_revision_rounds", MAX_GOVERNOR_PLAN_REVISION_ROUNDS);
602
776
  const worstCaseAgents = 1 + reviewerSpecialists.length * (maxRevisionRounds + 1) + maxRevisionRounds;
603
777
  if (worstCaseAgents > limits.max_agents_per_work) {
604
778
  throw new Error(`replanning review worst-case ${worstCaseAgents} agents exceeds max_agents_per_work ${limits.max_agents_per_work}`);
@@ -610,18 +784,18 @@ function normalizeReviewPolicy(input, specialists, plannerSpecialist, limits) {
610
784
  }
611
785
  function validateReplanning(policy, specialists, limits, goalId) {
612
786
  if (!specialists[policy.planner_specialist]) {
613
- throw new Error(`supervisor ${goalId} planner specialist is not in the frozen team`);
787
+ throw new Error(`governor ${goalId} planner specialist is not in the frozen team`);
614
788
  }
615
789
  boolean(policy.auto_apply, "replanning auto_apply");
616
790
  positive(policy.max_replans, "replanning max_replans", 100);
617
791
  positive(policy.max_work_items_per_plan, "replanning max_work_items_per_plan", 25);
618
792
  positive(policy.max_total_work_items, "replanning max_total_work_items", 100);
619
793
  if (policy.max_work_items_per_plan > policy.max_total_work_items) {
620
- throw new Error(`supervisor ${goalId} replanning work-item bounds are inconsistent`);
794
+ throw new Error(`governor ${goalId} replanning work-item bounds are inconsistent`);
621
795
  }
622
796
  const entries = Object.entries(policy.templates ?? {});
623
797
  if (entries.length < 1 || entries.length > MAX_TEMPLATES) {
624
- throw new Error(`supervisor ${goalId} has invalid replanning templates`);
798
+ throw new Error(`governor ${goalId} has invalid replanning templates`);
625
799
  }
626
800
  let rootCapable = false;
627
801
  for (const [id, template] of entries) {
@@ -632,45 +806,45 @@ function validateReplanning(policy, specialists, limits, goalId) {
632
806
  template.max_attempts < 1 ||
633
807
  template.max_attempts > 100 ||
634
808
  typeof template.root !== "boolean") {
635
- throw new Error(`supervisor ${goalId} replanning template ${id} is invalid`);
809
+ throw new Error(`governor ${goalId} replanning template ${id} is invalid`);
636
810
  }
637
811
  rootCapable ||= template.root;
638
812
  }
639
813
  if (!rootCapable)
640
- throw new Error(`supervisor ${goalId} has no root-capable replanning template`);
814
+ throw new Error(`governor ${goalId} has no root-capable replanning template`);
641
815
  if (policy.review !== undefined) {
642
816
  const review = policy.review;
643
817
  if (!Array.isArray(review.reviewer_specialists) ||
644
818
  review.reviewer_specialists.length < 1 ||
645
- review.reviewer_specialists.length > MAX_SUPERVISOR_PLAN_REVIEWERS ||
819
+ review.reviewer_specialists.length > MAX_GOVERNOR_PLAN_REVIEWERS ||
646
820
  !Number.isSafeInteger(review.max_revision_rounds) ||
647
821
  review.max_revision_rounds < 0 ||
648
- review.max_revision_rounds > MAX_SUPERVISOR_PLAN_REVISION_ROUNDS) {
649
- throw new Error(`supervisor ${goalId} replanning review policy is invalid`);
822
+ review.max_revision_rounds > MAX_GOVERNOR_PLAN_REVISION_ROUNDS) {
823
+ throw new Error(`governor ${goalId} replanning review policy is invalid`);
650
824
  }
651
825
  if (new Set(review.reviewer_specialists).size !== review.reviewer_specialists.length) {
652
- throw new Error(`supervisor ${goalId} replanning reviewers are not unique`);
826
+ throw new Error(`governor ${goalId} replanning reviewers are not unique`);
653
827
  }
654
828
  for (const specialist of review.reviewer_specialists) {
655
829
  if (!specialists[specialist]) {
656
- throw new Error(`supervisor ${goalId} reviewer specialist is not in the frozen team`);
830
+ throw new Error(`governor ${goalId} reviewer specialist is not in the frozen team`);
657
831
  }
658
832
  if (specialist === policy.planner_specialist) {
659
- throw new Error(`supervisor ${goalId} reviewer specialist cannot be planner`);
833
+ throw new Error(`governor ${goalId} reviewer specialist cannot be planner`);
660
834
  }
661
835
  }
662
836
  const worstCaseAgents = 1 +
663
837
  review.reviewer_specialists.length * (review.max_revision_rounds + 1) +
664
838
  review.max_revision_rounds;
665
839
  if (worstCaseAgents > limits.max_agents_per_work) {
666
- throw new Error(`supervisor ${goalId} review policy exceeds the agent budget`);
840
+ throw new Error(`governor ${goalId} review policy exceeds the agent budget`);
667
841
  }
668
842
  }
669
843
  }
670
844
  function collectGovernedWork(coordRoot, originalRootWorkId, plans, active) {
671
845
  const governed = new Map();
672
846
  if (workIntentExists(coordRoot, originalRootWorkId)) {
673
- for (const record of collectSupervisorWork(coordRoot, originalRootWorkId)) {
847
+ for (const record of collectGovernorWork(coordRoot, originalRootWorkId)) {
674
848
  governed.set(record.intent.id, record);
675
849
  }
676
850
  }
@@ -686,15 +860,15 @@ function workIntentExists(coordRoot, workId) {
686
860
  function missionRootId(goalId) {
687
861
  return `${goalId.slice(0, 87)}-mission-root`;
688
862
  }
689
- function supervisorDir(coordRoot, goalId) {
690
- assertSupervisorId(goalId);
691
- return join(resolve(coordRoot), ".harnery", "supervisors", goalId);
863
+ function governorDir(coordRoot, goalId) {
864
+ assertGovernorId(goalId);
865
+ return join(resolve(coordRoot), ".harnery", "governors", goalId);
692
866
  }
693
- function supervisorIntentPath(coordRoot, goalId) {
694
- return join(supervisorDir(coordRoot, goalId), "intent.json");
867
+ function governorIntentPath(coordRoot, goalId) {
868
+ return join(governorDir(coordRoot, goalId), "intent.json");
695
869
  }
696
- function supervisorLeaseIsLive(coordRoot, goalId) {
697
- const lease = readLease(join(supervisorDir(coordRoot, goalId), "lease.json"));
870
+ function governorLeaseIsLive(coordRoot, goalId) {
871
+ const lease = readLease(join(governorDir(coordRoot, goalId), "lease.json"));
698
872
  return lease ? leaseIsLive(lease) : false;
699
873
  }
700
874
  function readLease(path) {
@@ -733,7 +907,7 @@ function leaseIsLive(lease) {
733
907
  function writePrivateJson(path, value) {
734
908
  const body = `${JSON.stringify(value, null, 2)}\n`;
735
909
  if (Buffer.byteLength(body) > MAX_INTENT_BYTES) {
736
- throw new Error(`supervisor intent exceeds ${MAX_INTENT_BYTES} bytes`);
910
+ throw new Error(`governor intent exceeds ${MAX_INTENT_BYTES} bytes`);
737
911
  }
738
912
  writeFileSync(path, body, { encoding: "utf8", flag: "wx", mode: 0o600 });
739
913
  chmodSync(path, 0o600);
@@ -762,7 +936,7 @@ function nonNegative(value, field, max) {
762
936
  }
763
937
  function boolean(value, field) {
764
938
  if (typeof value !== "boolean")
765
- throw new Error(`supervisor ${field} must be boolean`);
939
+ throw new Error(`governor ${field} must be boolean`);
766
940
  return value;
767
941
  }
768
942
  function validTimestamp(value) {