harnery 0.30.0 → 0.31.1

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 (517) 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 +185 -74
  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/grep.d.ts +1 -1
  34. package/dist/commands/grep.d.ts.map +1 -1
  35. package/dist/commands/grep.js +19 -2
  36. package/dist/commands/init.d.ts +12 -12
  37. package/dist/commands/init.d.ts.map +1 -1
  38. package/dist/commands/init.js +44 -30
  39. package/dist/commands/{session.d.ts → journal.d.ts} +2 -2
  40. package/dist/commands/journal.d.ts.map +1 -0
  41. package/dist/commands/{scratch.js → journal.js} +47 -47
  42. package/dist/commands/policy.js +1 -1
  43. package/dist/commands/presence.js +2 -2
  44. package/dist/commands/sync.d.ts +1 -1
  45. package/dist/commands/sync.js +3 -3
  46. package/dist/commands/tunnel.d.ts +16 -0
  47. package/dist/commands/tunnel.d.ts.map +1 -1
  48. package/dist/commands/tunnel.js +213 -27
  49. package/dist/commands/web-fetch.js +1 -1
  50. package/dist/commands/web.d.ts +19 -0
  51. package/dist/commands/web.d.ts.map +1 -1
  52. package/dist/commands/web.js +51 -0
  53. package/dist/commands/work.d.ts.map +1 -1
  54. package/dist/commands/work.js +38 -22
  55. package/dist/commands/workflow.d.ts.map +1 -1
  56. package/dist/commands/workflow.js +35 -28
  57. package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
  58. package/dist/core/adapters/attest-projection.d.ts.map +1 -0
  59. package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
  60. package/dist/core/adapters/attest.d.ts.map +1 -0
  61. package/dist/core/{harnesses → adapters}/attest.js +9 -9
  62. package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
  63. package/dist/core/adapters/attestation.d.ts.map +1 -0
  64. package/dist/core/{harnesses → adapters}/attestation.js +20 -20
  65. package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
  66. package/dist/core/adapters/bench.d.ts.map +1 -0
  67. package/dist/core/{harnesses → adapters}/bench.js +12 -12
  68. package/dist/core/adapters/index.d.ts +13 -0
  69. package/dist/core/adapters/index.d.ts.map +1 -0
  70. package/dist/core/adapters/index.js +6 -0
  71. package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
  72. package/dist/core/adapters/profiles.d.ts.map +1 -0
  73. package/dist/core/{harnesses → adapters}/profiles.js +11 -11
  74. package/dist/core/adapters/registry.d.ts +15 -0
  75. package/dist/core/adapters/registry.d.ts.map +1 -0
  76. package/dist/core/{harnesses → adapters}/registry.js +11 -11
  77. package/dist/core/{harnesses → adapters}/types.d.ts +23 -23
  78. package/dist/core/adapters/types.d.ts.map +1 -0
  79. package/dist/core/{harnesses → adapters}/types.js +1 -1
  80. package/dist/core/agents/canonical-emit.d.ts +9 -14
  81. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  82. package/dist/core/agents/canonical-emit.js +15 -44
  83. package/dist/core/agents/cli-emit.js +1 -1
  84. package/dist/core/agents/cli.js +30 -26
  85. package/dist/core/agents/codex-replay.d.ts +1 -1
  86. package/dist/core/agents/codex-replay.js +6 -6
  87. package/dist/core/agents/coord-bin.d.ts +33 -0
  88. package/dist/core/agents/coord-bin.d.ts.map +1 -0
  89. package/dist/core/agents/coord-bin.js +89 -0
  90. package/dist/core/agents/coord-client.d.ts +78 -8
  91. package/dist/core/agents/coord-client.d.ts.map +1 -1
  92. package/dist/core/agents/coord-client.js +303 -75
  93. package/dist/core/agents/events/consume.d.ts +1 -1
  94. package/dist/core/agents/events/emit.d.ts +5 -6
  95. package/dist/core/agents/events/emit.d.ts.map +1 -1
  96. package/dist/core/agents/events/emit.js +2 -2
  97. package/dist/core/agents/paths.d.ts +5 -2
  98. package/dist/core/agents/paths.d.ts.map +1 -1
  99. package/dist/core/agents/paths.js +7 -13
  100. package/dist/core/agents/render/prompt-context.d.ts +21 -9
  101. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  102. package/dist/core/agents/render/prompt-context.js +82 -30
  103. package/dist/core/agents/render/session-context.d.ts +1 -1
  104. package/dist/core/agents/render/session-context.js +5 -5
  105. package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
  106. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  107. package/dist/core/agents/rules/claim-conflict.js +1 -1
  108. package/dist/core/agents/rules/commit-conflict.js +98 -22
  109. package/dist/core/agents/rules/stop-hook.d.ts +9 -9
  110. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  111. package/dist/core/agents/rules/stop-hook.js +23 -5
  112. package/dist/core/agents/rules/verdict.d.ts +14 -0
  113. package/dist/core/agents/rules/verdict.d.ts.map +1 -0
  114. package/dist/core/agents/rules/verdict.js +1 -0
  115. package/dist/core/agents/session-events.js +3 -3
  116. package/dist/core/agents/state/council.d.ts +1 -1
  117. package/dist/core/agents/state/council.js +1 -1
  118. package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
  119. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
  120. package/dist/core/agents/state/heartbeat-projector.js +14 -10
  121. package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
  122. package/dist/core/agents/state/heartbeat-writer.js +12 -12
  123. package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
  124. package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
  125. package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
  126. package/dist/core/agents/state/pidmap.d.ts +28 -4
  127. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  128. package/dist/core/agents/state/pidmap.js +130 -15
  129. package/dist/core/agents/state/proc-start.d.ts +95 -0
  130. package/dist/core/agents/state/proc-start.d.ts.map +1 -0
  131. package/dist/core/agents/state/proc-start.js +199 -0
  132. package/dist/core/agents/state/shell-mutation.d.ts +1 -1
  133. package/dist/core/agents/state/shell-mutation.js +1 -1
  134. package/dist/core/agents/state/stale-sweep.js +7 -7
  135. package/dist/core/artifacts/index.d.ts +86 -0
  136. package/dist/core/artifacts/index.d.ts.map +1 -0
  137. package/dist/core/artifacts/index.js +421 -0
  138. package/dist/core/config.d.ts +9 -2
  139. package/dist/core/config.d.ts.map +1 -1
  140. package/dist/core/config.js +26 -2
  141. package/dist/core/context/index.d.ts +12 -12
  142. package/dist/core/context/index.js +10 -10
  143. package/dist/core/governor/adapter-spread.d.ts +52 -0
  144. package/dist/core/governor/adapter-spread.d.ts.map +1 -0
  145. package/dist/core/governor/adapter-spread.js +52 -0
  146. package/dist/core/governor/index.d.ts +7 -0
  147. package/dist/core/governor/index.d.ts.map +1 -0
  148. package/dist/core/governor/index.js +6 -0
  149. package/dist/core/governor/plan-api.d.ts +38 -0
  150. package/dist/core/governor/plan-api.d.ts.map +1 -0
  151. package/dist/core/governor/plan-api.js +83 -0
  152. package/dist/core/governor/plan-read.d.ts +5 -0
  153. package/dist/core/governor/plan-read.d.ts.map +1 -0
  154. package/dist/core/{supervisor → governor}/plan-read.js +66 -52
  155. package/dist/core/{supervisor → governor}/plan-types.d.ts +57 -56
  156. package/dist/core/governor/plan-types.d.ts.map +1 -0
  157. package/dist/core/{supervisor → governor}/plan-types.js +4 -4
  158. package/dist/core/governor/planning.d.ts +48 -0
  159. package/dist/core/governor/planning.d.ts.map +1 -0
  160. package/dist/core/{supervisor → governor}/planning.js +125 -94
  161. package/dist/core/governor/read.d.ts +6 -0
  162. package/dist/core/governor/read.d.ts.map +1 -0
  163. package/dist/core/governor/read.js +4 -0
  164. package/dist/core/governor/runner.d.ts +37 -0
  165. package/dist/core/governor/runner.d.ts.map +1 -0
  166. package/dist/core/{supervisor → governor}/runner.js +15 -15
  167. package/dist/core/governor/service-read.d.ts +6 -0
  168. package/dist/core/governor/service-read.d.ts.map +1 -0
  169. package/dist/core/{supervisor → governor}/service-read.js +12 -12
  170. package/dist/core/governor/service.d.ts +114 -0
  171. package/dist/core/governor/service.d.ts.map +1 -0
  172. package/dist/core/{supervisor → governor}/service.js +57 -57
  173. package/dist/core/governor/state.d.ts +116 -0
  174. package/dist/core/governor/state.d.ts.map +1 -0
  175. package/dist/core/{supervisor → governor}/state.js +228 -108
  176. package/dist/core/hooks/adapter/detect.d.ts +9 -0
  177. package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
  178. package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
  179. package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
  180. package/dist/core/hooks/adapter/events.d.ts.map +1 -0
  181. package/dist/core/hooks/{harness → adapter}/events.js +5 -5
  182. package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
  183. package/dist/core/hooks/adapter/output.d.ts.map +1 -0
  184. package/dist/core/hooks/{harness → adapter}/output.js +30 -22
  185. package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
  186. package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
  187. package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
  188. package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
  189. package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
  190. package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
  191. package/dist/core/hooks/cli.d.ts +3 -3
  192. package/dist/core/hooks/cli.js +187 -162
  193. package/dist/core/hooks/effects/image-capture.d.ts +5 -5
  194. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  195. package/dist/core/hooks/effects/image-capture.js +3 -3
  196. package/dist/core/hooks/effects/index.d.ts +12 -12
  197. package/dist/core/hooks/effects/index.d.ts.map +1 -1
  198. package/dist/core/hooks/effects/index.js +19 -19
  199. package/dist/core/hooks/events/emit.d.ts +2 -2
  200. package/dist/core/hooks/events/emit.d.ts.map +1 -1
  201. package/dist/core/hooks/events/emit.js +1 -1
  202. package/dist/core/hooks/events/rotate.js +1 -1
  203. package/dist/core/hooks/events/schema.d.ts +13 -5
  204. package/dist/core/hooks/events/schema.d.ts.map +1 -1
  205. package/dist/core/hooks/guard-path.d.ts +2 -2
  206. package/dist/core/hooks/guard-path.js +2 -2
  207. package/dist/core/hooks/index.d.ts +1 -1
  208. package/dist/core/hooks/index.d.ts.map +1 -1
  209. package/dist/core/hooks/resolve/anchor.d.ts +14 -5
  210. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
  211. package/dist/core/hooks/resolve/anchor.js +64 -7
  212. package/dist/core/hooks/resolve/coord-root.d.ts +16 -11
  213. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
  214. package/dist/core/hooks/resolve/coord-root.js +18 -43
  215. package/dist/core/hooks/resolve/intent.js +1 -1
  216. package/dist/core/hooks/resolve/owner.d.ts +1 -1
  217. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  218. package/dist/core/hooks/resolve/owner.js +11 -5
  219. package/dist/core/{scratch → journal}/index.d.ts +25 -25
  220. package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
  221. package/dist/core/{scratch → journal}/index.js +38 -38
  222. package/dist/core/policy/evaluate.d.ts +1 -1
  223. package/dist/core/policy/evaluate.d.ts.map +1 -1
  224. package/dist/core/policy/evaluate.js +7 -7
  225. package/dist/core/policy/types.d.ts +3 -3
  226. package/dist/core/policy/types.d.ts.map +1 -1
  227. package/dist/core/work/state.d.ts +12 -4
  228. package/dist/core/work/state.d.ts.map +1 -1
  229. package/dist/core/work/state.js +50 -17
  230. package/dist/core/workflow/adapters.d.ts +17 -0
  231. package/dist/core/workflow/adapters.d.ts.map +1 -0
  232. package/dist/core/workflow/adapters.js +21 -0
  233. package/dist/core/workflow/approvals.js +6 -6
  234. package/dist/core/workflow/billing.d.ts +9 -9
  235. package/dist/core/workflow/billing.js +9 -9
  236. package/dist/core/workflow/child-env.d.ts +10 -2
  237. package/dist/core/workflow/child-env.d.ts.map +1 -1
  238. package/dist/core/workflow/child-env.js +12 -4
  239. package/dist/core/workflow/engine.d.ts +15 -5
  240. package/dist/core/workflow/engine.d.ts.map +1 -1
  241. package/dist/core/workflow/engine.js +138 -83
  242. package/dist/core/workflow/evidence-preflight.d.ts +24 -0
  243. package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
  244. package/dist/core/workflow/evidence-preflight.js +134 -0
  245. package/dist/core/workflow/index.d.ts +1 -1
  246. package/dist/core/workflow/index.d.ts.map +1 -1
  247. package/dist/core/workflow/proof.d.ts +11 -5
  248. package/dist/core/workflow/proof.d.ts.map +1 -1
  249. package/dist/core/workflow/proof.js +45 -36
  250. package/dist/core/workflow/run-state.d.ts +1 -1
  251. package/dist/core/workflow/run-state.js +7 -7
  252. package/dist/core/workflow/sandbox-projection.d.ts +6 -6
  253. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  254. package/dist/core/workflow/sandbox-projection.js +11 -11
  255. package/dist/core/workflow/spawn-claude.d.ts +3 -3
  256. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  257. package/dist/core/workflow/spawn-claude.js +9 -6
  258. package/dist/core/workflow/spawn-codex.d.ts +4 -4
  259. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  260. package/dist/core/workflow/spawn-codex.js +9 -6
  261. package/dist/core/workflow/spawn-cursor.d.ts +4 -4
  262. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  263. package/dist/core/workflow/spawn-cursor.js +9 -6
  264. package/dist/core/workflow/spawn-failure.d.ts +1 -1
  265. package/dist/core/workflow/spawn-failure.js +1 -1
  266. package/dist/core/workflow/specialists.js +2 -2
  267. package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
  268. package/dist/core/workflow/transcript.d.ts.map +1 -0
  269. package/dist/core/workflow/{journal.js → transcript.js} +14 -14
  270. package/dist/core/workflow/types.d.ts +98 -51
  271. package/dist/core/workflow/types.d.ts.map +1 -1
  272. package/dist/core/workflow/types.js +11 -1
  273. package/dist/core/workflow/validate.d.ts +1 -1
  274. package/dist/core/workflow/validate.js +1 -1
  275. package/dist/core/workflow/workspaces/cancellation.js +2 -2
  276. package/dist/core/workflow/workspaces/cleanup.js +2 -2
  277. package/dist/core/workflow/workspaces/execution.js +6 -6
  278. package/dist/core/workflow/workspaces/inspect.js +9 -9
  279. package/dist/core/workflow/workspaces/integration.js +14 -14
  280. package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
  281. package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
  282. package/dist/core/workflow/workspaces/lifecycle.js +9 -9
  283. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  284. package/dist/core/workflow/workspaces/local-git.js +39 -5
  285. package/dist/core/workflow/workspaces/recovery.js +3 -3
  286. package/dist/core/workflow/workspaces/state.d.ts +1 -1
  287. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  288. package/dist/core/workflow/workspaces/state.js +3 -3
  289. package/dist/core/workflow/workspaces/types.d.ts +1 -1
  290. package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
  291. package/dist/lib/browser/asserts.d.ts +28 -0
  292. package/dist/lib/browser/asserts.d.ts.map +1 -0
  293. package/dist/lib/browser/asserts.js +152 -0
  294. package/dist/lib/browser/client.d.ts +49 -0
  295. package/dist/lib/browser/client.d.ts.map +1 -1
  296. package/dist/lib/browser/client.js +155 -14
  297. package/dist/lib/browser/content-checks.d.ts +108 -0
  298. package/dist/lib/browser/content-checks.d.ts.map +1 -0
  299. package/dist/lib/browser/content-checks.js +474 -0
  300. package/dist/lib/browser/critique.d.ts +91 -0
  301. package/dist/lib/browser/critique.d.ts.map +1 -0
  302. package/dist/lib/browser/critique.js +167 -0
  303. package/dist/lib/browser/geometry.d.ts +32 -0
  304. package/dist/lib/browser/geometry.d.ts.map +1 -1
  305. package/dist/lib/browser/geometry.js +244 -1
  306. package/dist/lib/browser/index.d.ts +4 -1
  307. package/dist/lib/browser/index.d.ts.map +1 -1
  308. package/dist/lib/browser/index.js +2 -0
  309. package/dist/lib/claude-desktop.d.ts.map +1 -1
  310. package/dist/lib/claude-desktop.js +4 -1
  311. package/dist/lib/context/index.js +9 -2
  312. package/dist/lib/council/index.d.ts +6 -6
  313. package/dist/lib/council/index.d.ts.map +1 -1
  314. package/dist/lib/council/index.js +8 -8
  315. package/dist/lib/identities/assume.d.ts +2 -2
  316. package/dist/lib/identities/assume.js +7 -7
  317. package/dist/lib/instructions/apply.d.ts +3 -3
  318. package/dist/lib/instructions/apply.d.ts.map +1 -1
  319. package/dist/lib/instructions/apply.js +75 -27
  320. package/dist/lib/instructions/host-addendum.d.ts +54 -0
  321. package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
  322. package/dist/lib/instructions/host-addendum.js +107 -0
  323. package/dist/lib/instructions/templates.d.ts +10 -3
  324. package/dist/lib/instructions/templates.d.ts.map +1 -1
  325. package/dist/lib/instructions/templates.js +41 -12
  326. package/dist/lib/machine.d.ts +2 -2
  327. package/dist/lib/machine.js +2 -2
  328. package/package.json +26 -21
  329. package/schemas/config.schema.json +26 -1
  330. package/src/commander.ts +22 -13
  331. package/src/commands/{harness.ts → adapter.ts} +46 -46
  332. package/src/commands/agents.ts +200 -78
  333. package/src/commands/artifacts.ts +168 -0
  334. package/src/commands/backup.ts +47 -33
  335. package/src/commands/browse.ts +438 -2
  336. package/src/commands/checkpoint.ts +196 -0
  337. package/src/commands/context.ts +3 -176
  338. package/src/commands/decision.ts +41 -7
  339. package/src/commands/deinit.ts +16 -16
  340. package/src/commands/doctor.ts +28 -28
  341. package/src/commands/{supervisor.ts → governor.ts} +184 -154
  342. package/src/commands/grep.ts +19 -2
  343. package/src/commands/init.ts +50 -34
  344. package/src/commands/{scratch.ts → journal.ts} +60 -60
  345. package/src/commands/policy.ts +1 -1
  346. package/src/commands/presence.ts +2 -2
  347. package/src/commands/sync.ts +3 -3
  348. package/src/commands/tunnel.ts +256 -38
  349. package/src/commands/web-fetch.ts +1 -1
  350. package/src/commands/web.ts +56 -1
  351. package/src/commands/work.ts +50 -35
  352. package/src/commands/workflow.ts +43 -34
  353. package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
  354. package/src/core/{harnesses → adapters}/attest.ts +27 -27
  355. package/src/core/{harnesses → adapters}/attestation.ts +41 -41
  356. package/src/core/{harnesses → adapters}/bench.ts +34 -43
  357. package/src/core/adapters/index.ts +56 -0
  358. package/src/core/{harnesses → adapters}/profiles.ts +16 -16
  359. package/src/core/{harnesses → adapters}/registry.ts +23 -23
  360. package/src/core/{harnesses → adapters}/types.ts +23 -23
  361. package/src/core/agents/canonical-emit.ts +16 -43
  362. package/src/core/agents/cli-emit.ts +1 -1
  363. package/src/core/agents/cli.ts +30 -28
  364. package/src/core/agents/codex-replay.ts +6 -6
  365. package/src/core/agents/coord-bin.ts +92 -0
  366. package/src/core/agents/coord-client.ts +302 -78
  367. package/src/core/agents/events/consume.ts +1 -1
  368. package/src/core/agents/events/emit.ts +7 -6
  369. package/src/core/agents/paths.ts +7 -11
  370. package/src/core/agents/render/prompt-context.ts +107 -31
  371. package/src/core/agents/render/session-context.ts +6 -6
  372. package/src/core/agents/rules/claim-conflict.ts +4 -7
  373. package/src/core/agents/rules/commit-conflict.ts +103 -22
  374. package/src/core/agents/rules/stop-hook.ts +33 -17
  375. package/src/core/agents/rules/verdict.ts +13 -0
  376. package/src/core/agents/session-events.ts +4 -4
  377. package/src/core/agents/state/council.ts +1 -1
  378. package/src/core/agents/state/heartbeat-projector.ts +16 -12
  379. package/src/core/agents/state/heartbeat-writer.ts +12 -12
  380. package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
  381. package/src/core/agents/state/pidmap.ts +130 -15
  382. package/src/core/agents/state/proc-start.ts +208 -0
  383. package/src/core/agents/state/shell-mutation.ts +1 -1
  384. package/src/core/agents/state/stale-sweep.ts +7 -7
  385. package/src/core/artifacts/index.ts +557 -0
  386. package/src/core/config.ts +30 -2
  387. package/src/core/context/index.ts +15 -15
  388. package/src/core/governor/adapter-spread.ts +82 -0
  389. package/src/core/governor/index.ts +91 -0
  390. package/src/core/governor/plan-api.ts +115 -0
  391. package/src/core/{supervisor → governor}/plan-read.ts +112 -97
  392. package/src/core/{supervisor → governor}/plan-types.ts +59 -56
  393. package/src/core/{supervisor → governor}/planning.ts +223 -192
  394. package/src/core/governor/read.ts +59 -0
  395. package/src/core/{supervisor → governor}/runner.ts +39 -39
  396. package/src/core/{supervisor → governor}/service-read.ts +22 -22
  397. package/src/core/{supervisor → governor}/service.ts +117 -119
  398. package/src/core/{supervisor → governor}/state.ts +325 -167
  399. package/src/core/hooks/adapter/detect.ts +30 -0
  400. package/src/core/hooks/{harness → adapter}/events.ts +16 -14
  401. package/src/core/hooks/{harness → adapter}/output.ts +31 -23
  402. package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
  403. package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
  404. package/src/core/hooks/cli.ts +197 -173
  405. package/src/core/hooks/effects/image-capture.ts +6 -6
  406. package/src/core/hooks/effects/index.ts +19 -19
  407. package/src/core/hooks/events/emit.ts +3 -3
  408. package/src/core/hooks/events/rotate.ts +1 -1
  409. package/src/core/hooks/events/schema.ts +15 -7
  410. package/src/core/hooks/guard-path.ts +2 -2
  411. package/src/core/hooks/index.ts +1 -1
  412. package/src/core/hooks/resolve/anchor.ts +63 -8
  413. package/src/core/hooks/resolve/coord-root.ts +18 -40
  414. package/src/core/hooks/resolve/intent.ts +1 -1
  415. package/src/core/hooks/resolve/owner.ts +11 -5
  416. package/src/core/{scratch → journal}/index.ts +53 -53
  417. package/src/core/policy/evaluate.ts +8 -8
  418. package/src/core/policy/types.ts +3 -3
  419. package/src/core/work/state.ts +65 -23
  420. package/src/core/workflow/adapters.ts +33 -0
  421. package/src/core/workflow/approvals.ts +7 -7
  422. package/src/core/workflow/billing.ts +12 -12
  423. package/src/core/workflow/child-env.ts +13 -4
  424. package/src/core/workflow/engine.ts +155 -90
  425. package/src/core/workflow/evidence-preflight.ts +165 -0
  426. package/src/core/workflow/index.ts +3 -3
  427. package/src/core/workflow/proof.ts +60 -50
  428. package/src/core/workflow/run-state.ts +7 -7
  429. package/src/core/workflow/sandbox-projection.ts +16 -16
  430. package/src/core/workflow/spawn-claude.ts +13 -10
  431. package/src/core/workflow/spawn-codex.ts +13 -10
  432. package/src/core/workflow/spawn-cursor.ts +13 -10
  433. package/src/core/workflow/spawn-failure.ts +1 -1
  434. package/src/core/workflow/specialists.ts +2 -2
  435. package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
  436. package/src/core/workflow/types.ts +108 -51
  437. package/src/core/workflow/validate.ts +1 -1
  438. package/src/core/workflow/workspaces/cancellation.ts +2 -2
  439. package/src/core/workflow/workspaces/cleanup.ts +2 -2
  440. package/src/core/workflow/workspaces/execution.ts +6 -6
  441. package/src/core/workflow/workspaces/inspect.ts +14 -11
  442. package/src/core/workflow/workspaces/integration.ts +18 -14
  443. package/src/core/workflow/workspaces/lifecycle.ts +10 -10
  444. package/src/core/workflow/workspaces/local-git.ts +47 -5
  445. package/src/core/workflow/workspaces/recovery.ts +3 -3
  446. package/src/core/workflow/workspaces/state.ts +4 -3
  447. package/src/core/workflow/workspaces/types.ts +1 -1
  448. package/src/lib/browser/asserts.ts +177 -0
  449. package/src/lib/browser/client.ts +189 -14
  450. package/src/lib/browser/content-checks.ts +571 -0
  451. package/src/lib/browser/critique.ts +231 -0
  452. package/src/lib/browser/geometry.ts +297 -1
  453. package/src/lib/browser/index.ts +34 -0
  454. package/src/lib/claude-desktop.ts +4 -1
  455. package/src/lib/context/index.ts +11 -1
  456. package/src/lib/council/index.ts +9 -9
  457. package/src/lib/identities/assume.ts +7 -7
  458. package/src/lib/instructions/apply.ts +87 -25
  459. package/src/lib/instructions/host-addendum.ts +126 -0
  460. package/src/lib/instructions/templates.ts +44 -15
  461. package/src/lib/machine.ts +2 -2
  462. package/dist/commands/harness.d.ts +0 -12
  463. package/dist/commands/harness.d.ts.map +0 -1
  464. package/dist/commands/scratch.d.ts +0 -4
  465. package/dist/commands/scratch.d.ts.map +0 -1
  466. package/dist/commands/session.d.ts.map +0 -1
  467. package/dist/commands/session.js +0 -162
  468. package/dist/commands/supervisor.d.ts +0 -4
  469. package/dist/commands/supervisor.d.ts.map +0 -1
  470. package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
  471. package/dist/core/harnesses/attest.d.ts.map +0 -1
  472. package/dist/core/harnesses/attestation.d.ts.map +0 -1
  473. package/dist/core/harnesses/bench.d.ts.map +0 -1
  474. package/dist/core/harnesses/index.d.ts +0 -13
  475. package/dist/core/harnesses/index.d.ts.map +0 -1
  476. package/dist/core/harnesses/index.js +0 -6
  477. package/dist/core/harnesses/profiles.d.ts.map +0 -1
  478. package/dist/core/harnesses/registry.d.ts +0 -15
  479. package/dist/core/harnesses/registry.d.ts.map +0 -1
  480. package/dist/core/harnesses/types.d.ts.map +0 -1
  481. package/dist/core/hooks/harness/detect.d.ts +0 -9
  482. package/dist/core/hooks/harness/events.d.ts.map +0 -1
  483. package/dist/core/hooks/harness/output.d.ts.map +0 -1
  484. package/dist/core/supervisor/index.d.ts +0 -7
  485. package/dist/core/supervisor/index.d.ts.map +0 -1
  486. package/dist/core/supervisor/index.js +0 -6
  487. package/dist/core/supervisor/plan-api.d.ts +0 -23
  488. package/dist/core/supervisor/plan-api.d.ts.map +0 -1
  489. package/dist/core/supervisor/plan-api.js +0 -50
  490. package/dist/core/supervisor/plan-read.d.ts +0 -5
  491. package/dist/core/supervisor/plan-read.d.ts.map +0 -1
  492. package/dist/core/supervisor/plan-types.d.ts.map +0 -1
  493. package/dist/core/supervisor/planning.d.ts +0 -33
  494. package/dist/core/supervisor/planning.d.ts.map +0 -1
  495. package/dist/core/supervisor/read.d.ts +0 -6
  496. package/dist/core/supervisor/read.d.ts.map +0 -1
  497. package/dist/core/supervisor/read.js +0 -4
  498. package/dist/core/supervisor/runner.d.ts +0 -37
  499. package/dist/core/supervisor/runner.d.ts.map +0 -1
  500. package/dist/core/supervisor/service-read.d.ts +0 -6
  501. package/dist/core/supervisor/service-read.d.ts.map +0 -1
  502. package/dist/core/supervisor/service.d.ts +0 -114
  503. package/dist/core/supervisor/service.d.ts.map +0 -1
  504. package/dist/core/supervisor/state.d.ts +0 -95
  505. package/dist/core/supervisor/state.d.ts.map +0 -1
  506. package/dist/core/workflow/harnesses.d.ts +0 -17
  507. package/dist/core/workflow/harnesses.d.ts.map +0 -1
  508. package/dist/core/workflow/harnesses.js +0 -21
  509. package/dist/core/workflow/journal.d.ts.map +0 -1
  510. package/src/commands/session.ts +0 -187
  511. package/src/core/harnesses/index.ts +0 -56
  512. package/src/core/hooks/harness/detect.ts +0 -30
  513. package/src/core/supervisor/index.ts +0 -89
  514. package/src/core/supervisor/plan-api.ts +0 -73
  515. package/src/core/supervisor/read.ts +0 -59
  516. package/src/core/workflow/harnesses.ts +0 -33
  517. /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
@@ -17,18 +17,18 @@ import { assertWorkId, readWorkItem, type WorkRecord } from "../work/read.ts";
17
17
  import { workflowScriptDigest } from "../workflow/run-state.ts";
18
18
  import { normalizeWorkflowSpecialists } from "../workflow/specialists.ts";
19
19
  import type { WorkflowSpecialistProfile } from "../workflow/types.ts";
20
- import { readSupervisorPlans } from "./plan-read.ts";
20
+ import { readGovernorPlans } from "./plan-read.ts";
21
21
  import {
22
- type CreateSupervisorReplanningInput,
23
- MAX_SUPERVISOR_PLAN_REVIEWERS,
24
- MAX_SUPERVISOR_PLAN_REVISION_ROUNDS,
25
- type SupervisorPlanHistory,
26
- type SupervisorPlanRecord,
27
- type SupervisorReplanningPolicy,
28
- supervisorGraphFingerprint,
22
+ type CreateGovernorReplanningInput,
23
+ type GovernorPlanHistory,
24
+ type GovernorPlanRecord,
25
+ type GovernorReplanningPolicy,
26
+ governorGraphFingerprint,
27
+ MAX_GOVERNOR_PLAN_REVIEWERS,
28
+ MAX_GOVERNOR_PLAN_REVISION_ROUNDS,
29
29
  } from "./plan-types.ts";
30
30
 
31
- export const SUPERVISOR_INTENT_SCHEMA_VERSION = 1 as const;
31
+ export const GOVERNOR_INTENT_SCHEMA_VERSION = 1 as const;
32
32
 
33
33
  const GOAL_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
34
34
  const MAX_TITLE = 200;
@@ -46,7 +46,7 @@ const FOREIGN_LEASE_STALE_MS = 24 * 60 * 60 * 1_000;
46
46
  * environment failure self-bounds at one because it stops immediately. */
47
47
  const MAX_UNCHARGED_REPLANS = 3;
48
48
 
49
- export interface SupervisorLimits {
49
+ export interface GovernorLimits {
50
50
  max_cycles: number;
51
51
  max_runtime_ms: number;
52
52
  max_parallel_work: number;
@@ -55,38 +55,38 @@ export interface SupervisorLimits {
55
55
  agent_concurrency: number;
56
56
  }
57
57
 
58
- export interface SupervisorAutomationPolicy {
58
+ export interface GovernorAutomationPolicy {
59
59
  accept_passing_proof: boolean;
60
60
  resume_approved: boolean;
61
61
  retry_blocked: boolean;
62
62
  }
63
63
 
64
- export interface SupervisorMission {
64
+ export interface GovernorMission {
65
65
  objective: string;
66
66
  acceptance: string[];
67
67
  max_milestones: number;
68
68
  }
69
69
 
70
- export interface CreateSupervisorMissionInput {
70
+ export interface CreateGovernorMissionInput {
71
71
  objective: string;
72
72
  acceptance: readonly string[];
73
73
  maxMilestones?: number;
74
74
  }
75
75
 
76
- export interface SupervisorIntent {
77
- schema_version: typeof SUPERVISOR_INTENT_SCHEMA_VERSION;
76
+ export interface GovernorIntent {
77
+ schema_version: typeof GOVERNOR_INTENT_SCHEMA_VERSION;
78
78
  id: string;
79
79
  title: string;
80
80
  root_work_id: string;
81
81
  specialists: Record<string, WorkflowSpecialistProfile>;
82
- limits: SupervisorLimits;
83
- automation: SupervisorAutomationPolicy;
84
- mission?: SupervisorMission;
85
- replanning?: SupervisorReplanningPolicy;
82
+ limits: GovernorLimits;
83
+ automation: GovernorAutomationPolicy;
84
+ mission?: GovernorMission;
85
+ replanning?: GovernorReplanningPolicy;
86
86
  created_at: string;
87
87
  }
88
88
 
89
- export type SupervisorState =
89
+ export type GovernorState =
90
90
  | "ready"
91
91
  | "running"
92
92
  | "awaiting_attention"
@@ -94,7 +94,7 @@ export type SupervisorState =
94
94
  | "budget_exhausted"
95
95
  | "succeeded";
96
96
 
97
- export type SupervisorNextAction =
97
+ export type GovernorNextAction =
98
98
  | "run"
99
99
  | "wait_for_run"
100
100
  | "resolve_approval"
@@ -107,19 +107,23 @@ export type SupervisorNextAction =
107
107
  | "retry_plan"
108
108
  | "none";
109
109
 
110
- export interface SupervisorProjection {
110
+ export interface GovernorProjection {
111
111
  id: string;
112
112
  title: string;
113
113
  root_work_id: string;
114
114
  root_materialized: boolean;
115
- state: SupervisorState;
115
+ state: GovernorState;
116
116
  reason: string;
117
- next_action: SupervisorNextAction;
117
+ next_action: GovernorNextAction;
118
118
  work_ids: string[];
119
119
  ready_work: string[];
120
120
  resumable_work: string[];
121
121
  retryable_work: string[];
122
122
  attention_work: string[];
123
+ /** Work stopped because a human must rule, with the docket id when the script
124
+ * named one. Empty in the ordinary case. A reader that wants to tell an
125
+ * operator what is actually waiting on them should start here. */
126
+ decision_blocked_work: Array<{ work_id: string; decision_id?: string }>;
123
127
  attempts_used: number;
124
128
  attempts_remaining: number;
125
129
  specialists: string[];
@@ -130,41 +134,53 @@ export interface SupervisorProjection {
130
134
  milestones_remaining: number;
131
135
  pending_plan_id?: string;
132
136
  attention_plan_id?: string;
133
- latest_plan_status?: SupervisorPlanRecord["status"];
137
+ latest_plan_status?: GovernorPlanRecord["status"];
138
+ /**
139
+ * How consumed (charged) replans that did not advance the graph broke down,
140
+ * present only when at least one replan was spent by a planner run that
141
+ * produced no proposal. `reviewer_rejection` counts replans where a proposal
142
+ * was produced and independent review rejected it (review-round exhaustion,
143
+ * reviewer attention, or review failure); `planner_no_proposal` counts replans
144
+ * where the planner run produced no reviewable proposal at all. Absent when a
145
+ * goal has no planner no-proposal history, so goals that only ever reached
146
+ * review project exactly as before this field existed.
147
+ */
148
+ replan_consumption?: {
149
+ reviewer_rejection: number;
150
+ planner_no_proposal: number;
151
+ };
134
152
  governed_work_ids: string[];
135
153
  }
136
154
 
137
- export interface SupervisorRecord {
138
- intent: SupervisorIntent;
139
- projection: SupervisorProjection;
155
+ export interface GovernorRecord {
156
+ intent: GovernorIntent;
157
+ projection: GovernorProjection;
140
158
  work: WorkRecord[];
141
- plans: SupervisorPlanRecord[];
159
+ plans: GovernorPlanRecord[];
142
160
  }
143
161
 
144
- export interface CreateSupervisorInput {
162
+ export interface CreateGovernorInput {
145
163
  coordRoot: string;
146
164
  rootWorkId?: string;
147
165
  specialists: Readonly<Record<string, WorkflowSpecialistProfile>>;
148
166
  title?: string;
149
167
  id?: string;
150
- limits?: Partial<SupervisorLimits>;
151
- automation?: Partial<SupervisorAutomationPolicy>;
152
- mission?: CreateSupervisorMissionInput;
153
- replanning?: CreateSupervisorReplanningInput;
168
+ limits?: Partial<GovernorLimits>;
169
+ automation?: Partial<GovernorAutomationPolicy>;
170
+ mission?: CreateGovernorMissionInput;
171
+ replanning?: CreateGovernorReplanningInput;
154
172
  }
155
173
 
156
- export function createSupervisor(input: CreateSupervisorInput): SupervisorRecord {
174
+ export function createGovernor(input: CreateGovernorInput): GovernorRecord {
157
175
  const coordRoot = resolve(input.coordRoot);
158
- const id = input.id ?? newSupervisorId();
159
- assertSupervisorId(id);
176
+ const id = input.id ?? newGovernorId();
177
+ assertGovernorId(id);
160
178
  const mission = input.mission ? normalizeMission(input.mission) : undefined;
161
179
  if (mission && !input.replanning) {
162
- throw new Error("supervisor mission requires a replanning policy");
180
+ throw new Error("governor mission requires a replanning policy");
163
181
  }
164
182
  if (!input.rootWorkId && !mission) {
165
- throw new Error(
166
- "supervisor creation without root work requires a mission and replanning policy",
167
- );
183
+ throw new Error("governor creation without root work requires a mission and replanning policy");
168
184
  }
169
185
  if (input.rootWorkId) assertWorkId(input.rootWorkId);
170
186
  const root = input.rootWorkId ? readWorkItem(coordRoot, input.rootWorkId) : undefined;
@@ -182,12 +198,12 @@ export function createSupervisor(input: CreateSupervisorInput): SupervisorRecord
182
198
  "objective-first mission max_replans must exceed max_milestones to reserve completion review",
183
199
  );
184
200
  }
185
- const intent: SupervisorIntent = {
186
- schema_version: SUPERVISOR_INTENT_SCHEMA_VERSION,
201
+ const intent: GovernorIntent = {
202
+ schema_version: GOVERNOR_INTENT_SCHEMA_VERSION,
187
203
  id,
188
204
  title: bounded(
189
205
  input.title ?? root?.intent.title ?? missionTitle(mission!),
190
- "supervisor title",
206
+ "governor title",
191
207
  MAX_TITLE,
192
208
  ),
193
209
  root_work_id: input.rootWorkId ?? missionRootId(id),
@@ -198,42 +214,41 @@ export function createSupervisor(input: CreateSupervisorInput): SupervisorRecord
198
214
  ...(replanning ? { replanning } : {}),
199
215
  created_at: new Date().toISOString(),
200
216
  };
201
- const path = supervisorIntentPath(coordRoot, id);
217
+ const path = governorIntentPath(coordRoot, id);
202
218
  mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
203
219
  chmodSync(dirname(path), 0o700);
204
220
  writePrivateJson(path, intent);
205
- return readSupervisor(coordRoot, id);
221
+ return readGovernor(coordRoot, id);
206
222
  }
207
223
 
208
- export function readSupervisor(coordRoot: string, goalId: string): SupervisorRecord {
209
- return readSupervisorInternal(coordRoot, goalId, false);
224
+ export function readGovernor(coordRoot: string, goalId: string): GovernorRecord {
225
+ return readGovernorInternal(coordRoot, goalId, false);
210
226
  }
211
227
 
212
- /** @internal Runner seam; ignores the lease held by this supervisor process. */
213
- export function readSupervisorIgnoringLease(coordRoot: string, goalId: string): SupervisorRecord {
214
- return readSupervisorInternal(coordRoot, goalId, true);
228
+ /** @internal Runner seam; ignores the lease held by this governor process. */
229
+ export function readGovernorIgnoringLease(coordRoot: string, goalId: string): GovernorRecord {
230
+ return readGovernorInternal(coordRoot, goalId, true);
215
231
  }
216
232
 
217
- export function listSupervisors(coordRoot: string): SupervisorRecord[] {
218
- const base = join(resolve(coordRoot), ".harnery", "supervisors");
233
+ export function listGovernors(coordRoot: string): GovernorRecord[] {
234
+ const base = join(resolve(coordRoot), ".harnery", "governors");
219
235
  if (!existsSync(base)) return [];
220
- const records: SupervisorRecord[] = [];
236
+ const records: GovernorRecord[] = [];
221
237
  for (const name of readdirSync(base)) {
222
- if (!GOAL_ID.test(name) || !existsSync(supervisorIntentPath(coordRoot, name))) continue;
223
- records.push(readSupervisor(coordRoot, name));
238
+ if (!GOAL_ID.test(name) || !existsSync(governorIntentPath(coordRoot, name))) continue;
239
+ records.push(readGovernor(coordRoot, name));
224
240
  }
225
241
  return records.sort((left, right) =>
226
242
  right.intent.created_at.localeCompare(left.intent.created_at),
227
243
  );
228
244
  }
229
245
 
230
- export function collectSupervisorWork(coordRoot: string, rootWorkId: string): WorkRecord[] {
246
+ export function collectGovernorWork(coordRoot: string, rootWorkId: string): WorkRecord[] {
231
247
  const records = new Map<string, WorkRecord>();
232
248
  const visiting = new Set<string>();
233
249
  const visit = (workId: string): void => {
234
250
  if (records.has(workId)) return;
235
- if (visiting.has(workId))
236
- throw new Error(`supervisor work graph contains a cycle at ${workId}`);
251
+ if (visiting.has(workId)) throw new Error(`governor work graph contains a cycle at ${workId}`);
237
252
  visiting.add(workId);
238
253
  const record = readWorkItem(coordRoot, workId);
239
254
  for (const dependency of record.intent.dependencies) visit(dependency);
@@ -244,18 +259,18 @@ export function collectSupervisorWork(coordRoot: string, rootWorkId: string): Wo
244
259
  return Array.from(records.values());
245
260
  }
246
261
 
247
- export function assertSupervisorId(goalId: string): void {
248
- if (!GOAL_ID.test(goalId)) throw new Error(`invalid supervisor id ${JSON.stringify(goalId)}`);
262
+ export function assertGovernorId(goalId: string): void {
263
+ if (!GOAL_ID.test(goalId)) throw new Error(`invalid governor id ${JSON.stringify(goalId)}`);
249
264
  }
250
265
 
251
- export function newSupervisorId(): string {
266
+ export function newGovernorId(): string {
252
267
  return `goal-${new Date().toISOString().replace(/[:.]/g, "-")}-${randomBytes(3).toString("hex")}`;
253
268
  }
254
269
 
255
- /** @internal Runner seam; one exclusive crash-recoverable supervisor lease. */
256
- export function acquireSupervisorLease(coordRoot: string, goalId: string): () => void {
257
- readSupervisorIntent(coordRoot, goalId);
258
- const path = join(supervisorDir(coordRoot, goalId), "lease.json");
270
+ /** @internal Runner seam; one exclusive crash-recoverable governor lease. */
271
+ export function acquireGovernorLease(coordRoot: string, goalId: string): () => void {
272
+ readGovernorIntent(coordRoot, goalId);
273
+ const path = join(governorDir(coordRoot, goalId), "lease.json");
259
274
  const owner = {
260
275
  pid: process.pid,
261
276
  host: hostname(),
@@ -281,11 +296,11 @@ export function acquireSupervisorLease(coordRoot: string, goalId: string): () =>
281
296
  const existing = readLease(path);
282
297
  if (existing && leaseIsLive(existing)) {
283
298
  throw new Error(
284
- `supervisor ${goalId} is already running under pid ${existing.pid} on ${existing.host}`,
299
+ `governor ${goalId} is already running under pid ${existing.pid} on ${existing.host}`,
285
300
  );
286
301
  }
287
302
  unlinkSync(path);
288
- if (!acquire()) throw new Error(`supervisor ${goalId} lease raced with another process`);
303
+ if (!acquire()) throw new Error(`governor ${goalId} lease raced with another process`);
289
304
  }
290
305
  return () => {
291
306
  try {
@@ -297,19 +312,19 @@ export function acquireSupervisorLease(coordRoot: string, goalId: string): () =>
297
312
  };
298
313
  }
299
314
 
300
- function readSupervisorInternal(
315
+ function readGovernorInternal(
301
316
  coordRootRaw: string,
302
317
  goalId: string,
303
318
  ignoreLease: boolean,
304
- ): SupervisorRecord {
319
+ ): GovernorRecord {
305
320
  const coordRoot = resolve(coordRootRaw);
306
- const intent = readSupervisorIntent(coordRoot, goalId);
307
- const plans = readSupervisorPlans(coordRoot, intent.id, intent.root_work_id);
321
+ const intent = readGovernorIntent(coordRoot, goalId);
322
+ const plans = readGovernorPlans(coordRoot, intent.id, intent.root_work_id);
308
323
  const activeRootExists = workIntentExists(coordRoot, plans.active_root_work_id);
309
324
  if (!activeRootExists && (!intent.mission || plans.generation > 0)) {
310
- throw new Error(`supervisor ${intent.id} root work is missing`);
325
+ throw new Error(`governor ${intent.id} root work is missing`);
311
326
  }
312
- const work = activeRootExists ? collectSupervisorWork(coordRoot, plans.active_root_work_id) : [];
327
+ const work = activeRootExists ? collectGovernorWork(coordRoot, plans.active_root_work_id) : [];
313
328
  const governed = collectGovernedWork(coordRoot, intent.root_work_id, plans, work);
314
329
  return {
315
330
  intent,
@@ -321,12 +336,12 @@ function readSupervisorInternal(
321
336
 
322
337
  function deriveProjection(
323
338
  coordRoot: string,
324
- intent: SupervisorIntent,
339
+ intent: GovernorIntent,
325
340
  work: WorkRecord[],
326
341
  governed: WorkRecord[],
327
- plans: SupervisorPlanHistory,
342
+ plans: GovernorPlanHistory,
328
343
  ignoreLease: boolean,
329
- ): SupervisorProjection {
344
+ ): GovernorProjection {
330
345
  const root = work.find((record) => record.intent.id === plans.active_root_work_id);
331
346
  const attemptsUsed = governed.reduce((sum, record) => sum + record.projection.attempts_used, 0);
332
347
  // The goal budget, like the per-item budget, counts only charged attempts
@@ -337,10 +352,14 @@ function deriveProjection(
337
352
  // count: an uncharged planner failure (environment/upstream) does not spend
338
353
  // max_replans. replans_used stays the raw count for display.
339
354
  const unchargedReplans = plans.plans.filter(
340
- (plan) =>
341
- plan.status === "failed" && (plan.class === "environment" || plan.class === "upstream"),
355
+ (plan) => plan.status === "failed" && isUnchargedPlanClass(plan.class),
342
356
  ).length;
343
357
  const chargedReplans = plans.plans.length - unchargedReplans;
358
+ // Attribute the consumed replans that did not advance the graph so the
359
+ // projection can distinguish planner no-proposal exhaustion from reviewer
360
+ // rejection through existing plan seams (review receipt presence), rather than
361
+ // reporting both as a single undifferentiated replan exhaustion.
362
+ const replanConsumption = classifyReplanConsumption(plans);
344
363
  const readyWork = work
345
364
  .filter((record) => record.projection.state === "ready")
346
365
  .map((record) => record.intent.id);
@@ -375,6 +394,15 @@ function deriveProjection(
375
394
  (record) => record.projection.state === "blocked" && record.projection.next_action === "none",
376
395
  )
377
396
  .map((record) => record.intent.id);
397
+ // Work stopped on a person, kept apart from the rest of terminalBlocked. Every
398
+ // other terminal block is something an agent could in principle clear; this one
399
+ // can only be cleared by a ruling, so it is the thing worth saying out loud.
400
+ const decisionBlocked = work
401
+ .filter((record) => record.projection.blocked_on_decision !== undefined)
402
+ .map((record) => ({
403
+ work_id: record.intent.id,
404
+ decision_id: record.projection.blocked_on_decision || undefined,
405
+ }));
378
406
  const attentionWork = unique([
379
407
  ...pendingApproval,
380
408
  ...(intent.automation.accept_passing_proof ? [] : reviews),
@@ -390,6 +418,12 @@ function deriveProjection(
390
418
  record.intent.id === intent.root_work_id && record.projection.state === "succeeded",
391
419
  );
392
420
  const milestonesCompleted = plans.milestones_completed + (initialRootAccepted ? 1 : 0);
421
+ const resumableDispatchable = intent.automation.resume_approved ? resumableWork : [];
422
+ const attemptDispatchable = [
423
+ ...readyWork,
424
+ ...(intent.automation.retry_blocked ? retryableWork : []),
425
+ ];
426
+ const dispatchable = [...resumableDispatchable, ...attemptDispatchable];
393
427
  const base = {
394
428
  id: intent.id,
395
429
  title: intent.title,
@@ -400,6 +434,7 @@ function deriveProjection(
400
434
  resumable_work: resumableWork,
401
435
  retryable_work: retryableWork,
402
436
  attention_work: attentionWork,
437
+ decision_blocked_work: decisionBlocked,
403
438
  attempts_used: attemptsUsed,
404
439
  attempts_remaining: Math.max(0, intent.limits.max_total_attempts - chargedUsed),
405
440
  specialists: Object.keys(intent.specialists),
@@ -410,13 +445,14 @@ function deriveProjection(
410
445
  milestones_remaining: Math.max(0, (intent.mission?.max_milestones ?? 0) - milestonesCompleted),
411
446
  pending_plan_id: plans.latest?.status === "proposed" ? plans.latest.request.id : undefined,
412
447
  latest_plan_status: plans.latest?.status,
448
+ ...(replanConsumption.planner_no_proposal > 0 ? { replan_consumption: replanConsumption } : {}),
413
449
  governed_work_ids: governed.map((record) => record.intent.id),
414
450
  };
415
- if (!ignoreLease && supervisorLeaseIsLive(coordRoot, intent.id)) {
451
+ if (!ignoreLease && governorLeaseIsLive(coordRoot, intent.id)) {
416
452
  return {
417
453
  ...base,
418
454
  state: "running",
419
- reason: "the foreground supervisor holds the goal lease",
455
+ reason: "the foreground governor holds the goal lease",
420
456
  next_action: "wait_for_run",
421
457
  };
422
458
  }
@@ -428,6 +464,19 @@ function deriveProjection(
428
464
  next_action: "none",
429
465
  };
430
466
  }
467
+ // ADR 0050: a mission whose completion was reopened dispatches the reopened work
468
+ // before anything else. Without this the goal falls through to the milestone
469
+ // branch below, which still sees a succeeded root when the reopened item is one
470
+ // of its children, and would spend a replan reassessing a mission whose real
471
+ // remaining work is already sitting in ready_work.
472
+ if (intent.mission && plans.latest?.status === "reopened" && dispatchable.length > 0) {
473
+ return {
474
+ ...base,
475
+ state: "ready",
476
+ reason: `mission completion was reopened; ${dispatchable.length} work item${dispatchable.length === 1 ? " is" : "s are"} dispatchable`,
477
+ next_action: "run",
478
+ };
479
+ }
431
480
  if (plans.latest?.status === "proposed") {
432
481
  return {
433
482
  ...base,
@@ -468,6 +517,17 @@ function deriveProjection(
468
517
  next_action: "none",
469
518
  };
470
519
  }
520
+ if (plans.latest?.status === "failed" && plans.latest.class === "decision") {
521
+ // The planner concluded that a human must rule before this can be planned.
522
+ // Stop and say so. Replanning would re-ask a question the planner already
523
+ // answered correctly, which is how a goal spins without a person noticing.
524
+ return {
525
+ ...base,
526
+ state: "blocked",
527
+ reason: `planning is waiting on a human decision: ${plans.latest.reason ?? "the planner did not say which"}`,
528
+ next_action: "none",
529
+ };
530
+ }
471
531
  if (plans.latest?.status === "failed" && plans.latest.class === "upstream") {
472
532
  // The vendor refused. Uncharged replans do not spend max_replans, so the
473
533
  // only brake on an unending outage is this consecutive bound; at the limit
@@ -475,7 +535,7 @@ function deriveProjection(
475
535
  let trailingUncharged = 0;
476
536
  for (let index = plans.plans.length - 1; index >= 0; index--) {
477
537
  const plan = plans.plans[index]!;
478
- if (plan.status !== "failed" || (plan.class !== "environment" && plan.class !== "upstream")) {
538
+ if (plan.status !== "failed" || !isUnchargedPlanClass(plan.class)) {
479
539
  break;
480
540
  }
481
541
  trailingUncharged++;
@@ -492,7 +552,7 @@ function deriveProjection(
492
552
  // dispatchable — the vendor may have recovered. canReplan reads
493
553
  // chargedReplans, so these uncharged attempts do not exhaust max_replans.
494
554
  }
495
- const triggerFingerprint = supervisorGraphFingerprint({
555
+ const triggerFingerprint = governorGraphFingerprint({
496
556
  rootWorkId: plans.active_root_work_id,
497
557
  generation: plans.generation,
498
558
  work,
@@ -502,13 +562,16 @@ function deriveProjection(
502
562
  plans.latest.request.prior_root_work_id === plans.active_root_work_id &&
503
563
  plans.latest.status === "attention";
504
564
  if (latestHandledSameGraph && plans.latest) {
565
+ const canRetry =
566
+ intent.replanning !== undefined && chargedReplans < intent.replanning.max_replans;
505
567
  return {
506
568
  ...base,
507
569
  state: "awaiting_attention",
508
- reason: plans.latest.reason ?? `plan ${plans.latest.request.id} requires attention`,
570
+ reason: canRetry
571
+ ? (plans.latest.reason ?? `plan ${plans.latest.request.id} requires attention`)
572
+ : exhaustedAttentionReason(plans.latest, replanConsumption),
509
573
  attention_plan_id: plans.latest.request.id,
510
- next_action:
511
- intent.replanning && chargedReplans < intent.replanning.max_replans ? "retry_plan" : "none",
574
+ next_action: canRetry ? "retry_plan" : "none",
512
575
  };
513
576
  }
514
577
  if (!root && intent.mission) {
@@ -516,7 +579,10 @@ function deriveProjection(
516
579
  return {
517
580
  ...base,
518
581
  state: "budget_exhausted",
519
- reason: "mission exhausted its planning budget before creating an initial milestone",
582
+ reason: replanBudgetReason(
583
+ "mission exhausted its planning budget before creating an initial milestone",
584
+ replanConsumption,
585
+ ),
520
586
  next_action: "none",
521
587
  };
522
588
  }
@@ -527,13 +593,16 @@ function deriveProjection(
527
593
  next_action: "plan_initial",
528
594
  };
529
595
  }
530
- if (!root) throw new Error(`supervisor ${intent.id} root work is missing`);
596
+ if (!root) throw new Error(`governor ${intent.id} root work is missing`);
531
597
  if (root.projection.state === "succeeded" && intent.mission) {
532
598
  if (!intent.replanning || chargedReplans >= intent.replanning.max_replans) {
533
599
  return {
534
600
  ...base,
535
601
  state: "budget_exhausted",
536
- reason: "mission exhausted its planning budget at a milestone boundary",
602
+ reason: replanBudgetReason(
603
+ "mission exhausted its planning budget at a milestone boundary",
604
+ replanConsumption,
605
+ ),
537
606
  next_action: "none",
538
607
  };
539
608
  }
@@ -552,12 +621,6 @@ function deriveProjection(
552
621
  next_action: "none",
553
622
  };
554
623
  }
555
- const resumableDispatchable = intent.automation.resume_approved ? resumableWork : [];
556
- const attemptDispatchable = [
557
- ...readyWork,
558
- ...(intent.automation.retry_blocked ? retryableWork : []),
559
- ];
560
- const dispatchable = [...resumableDispatchable, ...attemptDispatchable];
561
624
  if (intent.automation.accept_passing_proof && reviews.length > 0) {
562
625
  return {
563
626
  ...base,
@@ -653,48 +716,143 @@ function deriveProjection(
653
716
  return {
654
717
  ...base,
655
718
  state: "budget_exhausted",
656
- reason: `goal exhausted its ${intent.replanning.max_replans} replans`,
719
+ reason: replanBudgetReason(
720
+ `goal exhausted its ${intent.replanning.max_replans} replans`,
721
+ replanConsumption,
722
+ ),
657
723
  next_action: "none",
658
724
  };
659
725
  }
660
726
  return {
661
727
  ...base,
662
728
  state: "blocked",
729
+ // Lead with the decisions when there are any. "3 work items need
730
+ // intervention" reads as a queue an agent will get to; "waiting on you to
731
+ // rule on X" is the only phrasing that reaches the person who can clear it.
663
732
  reason:
664
- attentionWork.length > 0
665
- ? `${attentionWork.length} work item${attentionWork.length === 1 ? " needs" : "s need"} intervention`
666
- : "goal graph has no legal progress action",
733
+ decisionBlocked.length > 0
734
+ ? `${decisionBlocked.length} work item${decisionBlocked.length === 1 ? " is" : "s are"} waiting on a human decision: ${describeDecisionBlocks(decisionBlocked)}`
735
+ : attentionWork.length > 0
736
+ ? `${attentionWork.length} work item${attentionWork.length === 1 ? " needs" : "s need"} intervention`
737
+ : "goal graph has no legal progress action",
667
738
  next_action: "none",
668
739
  };
669
740
  }
670
741
 
671
- function readSupervisorIntent(coordRoot: string, goalId: string): SupervisorIntent {
672
- assertSupervisorId(goalId);
673
- const path = supervisorIntentPath(coordRoot, goalId);
674
- if (!existsSync(path)) throw new Error(`supervisor ${goalId} does not exist`);
742
+ /** Bounded, operator-readable list of what is waiting on a ruling. */
743
+ function describeDecisionBlocks(
744
+ blocks: readonly { work_id: string; decision_id?: string }[],
745
+ ): string {
746
+ const shown = blocks
747
+ .slice(0, 3)
748
+ .map((b) => (b.decision_id ? `${b.work_id} (${b.decision_id})` : b.work_id))
749
+ .join(", ");
750
+ return blocks.length > 3 ? `${shown}, +${blocks.length - 3} more` : shown;
751
+ }
752
+
753
+ interface ReplanConsumption {
754
+ reviewer_rejection: number;
755
+ planner_no_proposal: number;
756
+ }
757
+
758
+ /**
759
+ * Classify each consumed replan that did not advance the graph, using existing
760
+ * plan seams only. A plan carries a review receipt exactly when a proposal was
761
+ * produced and independently reviewed, so its presence separates a reviewer
762
+ * rejection from a planner run that produced no reviewable proposal. Uncharged
763
+ * environment/upstream planner failures (ADR 0046) do not spend the replan
764
+ * budget and are attributed to their outside precondition, not counted here.
765
+ */
766
+ /** Whether a failed plan told us nothing about the plan, and so must not spend
767
+ * a replan (ADR 0046). All three classes mean "replanning this cannot help":
768
+ * the binary is missing, the vendor is down, or a person has to rule. */
769
+ function isUnchargedPlanClass(value: GovernorPlanRecord["class"]): boolean {
770
+ return value === "environment" || value === "upstream" || value === "decision";
771
+ }
772
+
773
+ function classifyReplanConsumption(plans: GovernorPlanHistory): ReplanConsumption {
774
+ let reviewerRejection = 0;
775
+ let plannerNoProposal = 0;
776
+ for (const plan of plans.plans) {
777
+ if (plan.status === "failed" && isUnchargedPlanClass(plan.class)) {
778
+ continue;
779
+ }
780
+ if (plan.review && plan.review.status !== "passed") {
781
+ reviewerRejection++;
782
+ } else if (
783
+ !plan.review &&
784
+ (plan.status === "attention" ||
785
+ plan.status === "interrupted" ||
786
+ plan.status === "failed" ||
787
+ plan.status === "retry_requested")
788
+ ) {
789
+ // `retry_requested` is a planner no-proposal attention the operator asked to
790
+ // replan: the original run still produced no reviewable proposal and still
791
+ // spent a charged replan, so it belongs in this bucket even though a later
792
+ // plan superseded it. Omitting it would misattribute a retried no-proposal
793
+ // to nothing and let the reason read as pure review exhaustion.
794
+ plannerNoProposal++;
795
+ }
796
+ }
797
+ return { reviewer_rejection: reviewerRejection, planner_no_proposal: plannerNoProposal };
798
+ }
799
+
800
+ /**
801
+ * Reason for a goal held at `awaiting_attention/none` because its latest plan is
802
+ * an unresolved attention and no replan slot remains. The latest plan's own
803
+ * per-plan reason always leads (a reviewed-and-rejected latest reports its
804
+ * review-round exhaustion verbatim), then `replanBudgetReason` names the planner
805
+ * no-proposal share of the consumed budget. This keeps the `projection.reason`
806
+ * field carrying the same truth the operator-visible row does: a goal whose
807
+ * budget was mostly spent by planner no-proposal runs is not attributed wholesale
808
+ * to review just because its final, reviewed plan happened to be rejected.
809
+ */
810
+ function exhaustedAttentionReason(
811
+ latest: GovernorPlanRecord,
812
+ consumption: ReplanConsumption,
813
+ ): string {
814
+ const fallback = latest.reason ?? `plan ${latest.request.id} requires attention`;
815
+ return replanBudgetReason(fallback, consumption);
816
+ }
817
+
818
+ /**
819
+ * Append planner no-proposal attribution to a replan-exhaustion reason. Returns
820
+ * the base reason unchanged when no consumed replan was a planner no-proposal
821
+ * outcome, so goals without that history project exactly as before.
822
+ */
823
+ function replanBudgetReason(base: string, consumption: ReplanConsumption): string {
824
+ if (consumption.planner_no_proposal <= 0) return base;
825
+ const count = consumption.planner_no_proposal;
826
+ return `${base}; ${count} replan${count === 1 ? "" : "s"} ended with the planner producing no proposal`;
827
+ }
828
+
829
+ function readGovernorIntent(coordRoot: string, goalId: string): GovernorIntent {
830
+ assertGovernorId(goalId);
831
+ const path = governorIntentPath(coordRoot, goalId);
832
+ if (!existsSync(path)) throw new Error(`governor ${goalId} does not exist`);
675
833
  const size = statSync(path).size;
676
834
  if (size <= 0 || size > MAX_INTENT_BYTES) {
677
- throw new Error(`supervisor intent has invalid size ${size}`);
835
+ throw new Error(`governor intent has invalid size ${size}`);
678
836
  }
679
- let intent: SupervisorIntent;
837
+ let intent: GovernorIntent;
680
838
  try {
681
- intent = JSON.parse(readFileSync(path, "utf8")) as SupervisorIntent;
839
+ intent = JSON.parse(readFileSync(path, "utf8")) as GovernorIntent;
682
840
  } catch (error) {
683
- throw new Error(`cannot parse supervisor intent ${goalId}: ${(error as Error).message}`);
841
+ throw new Error(`cannot parse governor intent ${goalId}: ${(error as Error).message}`);
684
842
  }
685
843
  validateIntent(intent, goalId);
686
844
  return intent;
687
845
  }
688
846
 
689
- function validateIntent(intent: SupervisorIntent, goalId: string): void {
847
+ function validateIntent(intent: GovernorIntent, goalId: string): void {
690
848
  if (
691
- intent.schema_version !== SUPERVISOR_INTENT_SCHEMA_VERSION ||
849
+ intent.schema_version !== GOVERNOR_INTENT_SCHEMA_VERSION ||
692
850
  intent.id !== goalId ||
693
851
  !validTimestamp(intent.created_at)
694
852
  ) {
695
- throw new Error(`supervisor intent ${goalId} has an unsupported or mismatched schema`);
853
+ throw new Error(`governor intent ${goalId} has an unsupported or mismatched schema`);
696
854
  }
697
- bounded(intent.title, "supervisor title", MAX_TITLE);
855
+ bounded(intent.title, "governor title", MAX_TITLE);
698
856
  assertWorkId(intent.root_work_id);
699
857
  if (intent.mission) {
700
858
  const normalizedMission = normalizeMission({
@@ -703,79 +861,79 @@ function validateIntent(intent: SupervisorIntent, goalId: string): void {
703
861
  maxMilestones: intent.mission.max_milestones,
704
862
  });
705
863
  if (JSON.stringify(normalizedMission) !== JSON.stringify(intent.mission)) {
706
- throw new Error(`supervisor intent ${goalId} mission is not canonical`);
864
+ throw new Error(`governor intent ${goalId} mission is not canonical`);
707
865
  }
708
866
  if (!intent.replanning) {
709
- throw new Error(`supervisor intent ${goalId} mission requires replanning`);
867
+ throw new Error(`governor intent ${goalId} mission requires replanning`);
710
868
  }
711
869
  }
712
870
  const specialists = normalizeWorkflowSpecialists(intent.specialists);
713
871
  if (JSON.stringify(specialists) !== JSON.stringify(intent.specialists)) {
714
- throw new Error(`supervisor intent ${goalId} specialists are not canonical`);
872
+ throw new Error(`governor intent ${goalId} specialists are not canonical`);
715
873
  }
716
874
  if (JSON.stringify(normalizeLimits(intent.limits)) !== JSON.stringify(intent.limits)) {
717
- throw new Error(`supervisor intent ${goalId} limits are not canonical`);
875
+ throw new Error(`governor intent ${goalId} limits are not canonical`);
718
876
  }
719
877
  if (
720
878
  JSON.stringify(normalizeAutomation(intent.automation)) !== JSON.stringify(intent.automation)
721
879
  ) {
722
- throw new Error(`supervisor intent ${goalId} automation policy is not canonical`);
880
+ throw new Error(`governor intent ${goalId} automation policy is not canonical`);
723
881
  }
724
882
  if (intent.replanning) validateReplanning(intent.replanning, specialists, intent.limits, goalId);
725
883
  }
726
884
 
727
- function normalizeMission(input: CreateSupervisorMissionInput): SupervisorMission {
885
+ function normalizeMission(input: CreateGovernorMissionInput): GovernorMission {
728
886
  if (!Array.isArray(input.acceptance)) {
729
- throw new Error("supervisor mission acceptance must be an array");
887
+ throw new Error("governor mission acceptance must be an array");
730
888
  }
731
889
  if (input.acceptance.length < 1 || input.acceptance.length > MAX_ACCEPTANCE) {
732
- throw new Error(`supervisor mission acceptance must contain 1 to ${MAX_ACCEPTANCE} criteria`);
890
+ throw new Error(`governor mission acceptance must contain 1 to ${MAX_ACCEPTANCE} criteria`);
733
891
  }
734
892
  const acceptance = input.acceptance.map((criterion, index) =>
735
- bounded(criterion, `supervisor mission acceptance[${index}]`, 500),
893
+ bounded(criterion, `governor mission acceptance[${index}]`, 500),
736
894
  );
737
895
  if (new Set(acceptance).size !== acceptance.length) {
738
- throw new Error("supervisor mission acceptance criteria must be unique");
896
+ throw new Error("governor mission acceptance criteria must be unique");
739
897
  }
740
898
  return {
741
- objective: bounded(input.objective, "supervisor mission objective", MAX_OBJECTIVE),
899
+ objective: bounded(input.objective, "governor mission objective", MAX_OBJECTIVE),
742
900
  acceptance,
743
- max_milestones: positive(input.maxMilestones ?? 4, "supervisor mission max_milestones", 20),
901
+ max_milestones: positive(input.maxMilestones ?? 4, "governor mission max_milestones", 20),
744
902
  };
745
903
  }
746
904
 
747
- function missionTitle(mission: SupervisorMission): string {
905
+ function missionTitle(mission: GovernorMission): string {
748
906
  return mission.objective.length <= MAX_TITLE
749
907
  ? mission.objective
750
908
  : `${mission.objective.slice(0, MAX_TITLE - 1).trimEnd()}…`;
751
909
  }
752
910
 
753
- function normalizeLimits(input: Partial<SupervisorLimits> | undefined): SupervisorLimits {
911
+ function normalizeLimits(input: Partial<GovernorLimits> | undefined): GovernorLimits {
754
912
  return {
755
- max_cycles: positive(input?.max_cycles ?? 50, "supervisor max_cycles", 1_000),
913
+ max_cycles: positive(input?.max_cycles ?? 50, "governor max_cycles", 1_000),
756
914
  max_runtime_ms: positive(
757
915
  input?.max_runtime_ms ?? 4 * 60 * 60 * 1_000,
758
- "supervisor max_runtime_ms",
916
+ "governor max_runtime_ms",
759
917
  7 * 24 * 60 * 60 * 1_000,
760
918
  ),
761
- max_parallel_work: positive(input?.max_parallel_work ?? 1, "supervisor max_parallel_work", 20),
919
+ max_parallel_work: positive(input?.max_parallel_work ?? 1, "governor max_parallel_work", 20),
762
920
  max_total_attempts: positive(
763
921
  input?.max_total_attempts ?? 100,
764
- "supervisor max_total_attempts",
922
+ "governor max_total_attempts",
765
923
  10_000,
766
924
  ),
767
925
  max_agents_per_work: positive(
768
926
  input?.max_agents_per_work ?? 20,
769
- "supervisor max_agents_per_work",
927
+ "governor max_agents_per_work",
770
928
  1_000,
771
929
  ),
772
- agent_concurrency: positive(input?.agent_concurrency ?? 4, "supervisor agent_concurrency", 100),
930
+ agent_concurrency: positive(input?.agent_concurrency ?? 4, "governor agent_concurrency", 100),
773
931
  };
774
932
  }
775
933
 
776
934
  function normalizeAutomation(
777
- input: Partial<SupervisorAutomationPolicy> | undefined,
778
- ): SupervisorAutomationPolicy {
935
+ input: Partial<GovernorAutomationPolicy> | undefined,
936
+ ): GovernorAutomationPolicy {
779
937
  return {
780
938
  accept_passing_proof: boolean(input?.accept_passing_proof ?? false, "accept_passing_proof"),
781
939
  resume_approved: boolean(input?.resume_approved ?? true, "resume_approved"),
@@ -784,10 +942,10 @@ function normalizeAutomation(
784
942
  }
785
943
 
786
944
  function normalizeReplanning(
787
- input: CreateSupervisorReplanningInput,
945
+ input: CreateGovernorReplanningInput,
788
946
  specialistsInput: Readonly<Record<string, WorkflowSpecialistProfile>>,
789
- limits: SupervisorLimits,
790
- ): SupervisorReplanningPolicy {
947
+ limits: GovernorLimits,
948
+ ): GovernorReplanningPolicy {
791
949
  const specialists = normalizeWorkflowSpecialists(specialistsInput);
792
950
  const plannerSpecialist = bounded(input.plannerSpecialist, "planner specialist", 100);
793
951
  if (!specialists[plannerSpecialist]) {
@@ -851,17 +1009,17 @@ function normalizeReplanning(
851
1009
  }
852
1010
 
853
1011
  function normalizeReviewPolicy(
854
- input: NonNullable<CreateSupervisorReplanningInput["review"]>,
1012
+ input: NonNullable<CreateGovernorReplanningInput["review"]>,
855
1013
  specialists: Record<string, WorkflowSpecialistProfile>,
856
1014
  plannerSpecialist: string,
857
- limits: SupervisorLimits,
858
- ): NonNullable<SupervisorReplanningPolicy["review"]> {
1015
+ limits: GovernorLimits,
1016
+ ): NonNullable<GovernorReplanningPolicy["review"]> {
859
1017
  if (!Array.isArray(input.reviewerSpecialists) || input.reviewerSpecialists.length < 1) {
860
1018
  throw new Error("replanning review requires at least one reviewer specialist");
861
1019
  }
862
- if (input.reviewerSpecialists.length > MAX_SUPERVISOR_PLAN_REVIEWERS) {
1020
+ if (input.reviewerSpecialists.length > MAX_GOVERNOR_PLAN_REVIEWERS) {
863
1021
  throw new Error(
864
- `replanning review cannot exceed ${MAX_SUPERVISOR_PLAN_REVIEWERS} reviewer specialists`,
1022
+ `replanning review cannot exceed ${MAX_GOVERNOR_PLAN_REVIEWERS} reviewer specialists`,
865
1023
  );
866
1024
  }
867
1025
  const reviewerSpecialists = input.reviewerSpecialists.map((specialist, index) =>
@@ -881,7 +1039,7 @@ function normalizeReviewPolicy(
881
1039
  const maxRevisionRounds = nonNegative(
882
1040
  input.maxRevisionRounds,
883
1041
  "replanning review max_revision_rounds",
884
- MAX_SUPERVISOR_PLAN_REVISION_ROUNDS,
1042
+ MAX_GOVERNOR_PLAN_REVISION_ROUNDS,
885
1043
  );
886
1044
  const worstCaseAgents =
887
1045
  1 + reviewerSpecialists.length * (maxRevisionRounds + 1) + maxRevisionRounds;
@@ -897,24 +1055,24 @@ function normalizeReviewPolicy(
897
1055
  }
898
1056
 
899
1057
  function validateReplanning(
900
- policy: SupervisorReplanningPolicy,
1058
+ policy: GovernorReplanningPolicy,
901
1059
  specialists: Record<string, WorkflowSpecialistProfile>,
902
- limits: SupervisorLimits,
1060
+ limits: GovernorLimits,
903
1061
  goalId: string,
904
1062
  ): void {
905
1063
  if (!specialists[policy.planner_specialist]) {
906
- throw new Error(`supervisor ${goalId} planner specialist is not in the frozen team`);
1064
+ throw new Error(`governor ${goalId} planner specialist is not in the frozen team`);
907
1065
  }
908
1066
  boolean(policy.auto_apply, "replanning auto_apply");
909
1067
  positive(policy.max_replans, "replanning max_replans", 100);
910
1068
  positive(policy.max_work_items_per_plan, "replanning max_work_items_per_plan", 25);
911
1069
  positive(policy.max_total_work_items, "replanning max_total_work_items", 100);
912
1070
  if (policy.max_work_items_per_plan > policy.max_total_work_items) {
913
- throw new Error(`supervisor ${goalId} replanning work-item bounds are inconsistent`);
1071
+ throw new Error(`governor ${goalId} replanning work-item bounds are inconsistent`);
914
1072
  }
915
1073
  const entries = Object.entries(policy.templates ?? {});
916
1074
  if (entries.length < 1 || entries.length > MAX_TEMPLATES) {
917
- throw new Error(`supervisor ${goalId} has invalid replanning templates`);
1075
+ throw new Error(`governor ${goalId} has invalid replanning templates`);
918
1076
  }
919
1077
  let rootCapable = false;
920
1078
  for (const [id, template] of entries) {
@@ -927,32 +1085,32 @@ function validateReplanning(
927
1085
  template.max_attempts > 100 ||
928
1086
  typeof template.root !== "boolean"
929
1087
  ) {
930
- throw new Error(`supervisor ${goalId} replanning template ${id} is invalid`);
1088
+ throw new Error(`governor ${goalId} replanning template ${id} is invalid`);
931
1089
  }
932
1090
  rootCapable ||= template.root;
933
1091
  }
934
- if (!rootCapable) throw new Error(`supervisor ${goalId} has no root-capable replanning template`);
1092
+ if (!rootCapable) throw new Error(`governor ${goalId} has no root-capable replanning template`);
935
1093
  if (policy.review !== undefined) {
936
1094
  const review = policy.review;
937
1095
  if (
938
1096
  !Array.isArray(review.reviewer_specialists) ||
939
1097
  review.reviewer_specialists.length < 1 ||
940
- review.reviewer_specialists.length > MAX_SUPERVISOR_PLAN_REVIEWERS ||
1098
+ review.reviewer_specialists.length > MAX_GOVERNOR_PLAN_REVIEWERS ||
941
1099
  !Number.isSafeInteger(review.max_revision_rounds) ||
942
1100
  review.max_revision_rounds < 0 ||
943
- review.max_revision_rounds > MAX_SUPERVISOR_PLAN_REVISION_ROUNDS
1101
+ review.max_revision_rounds > MAX_GOVERNOR_PLAN_REVISION_ROUNDS
944
1102
  ) {
945
- throw new Error(`supervisor ${goalId} replanning review policy is invalid`);
1103
+ throw new Error(`governor ${goalId} replanning review policy is invalid`);
946
1104
  }
947
1105
  if (new Set(review.reviewer_specialists).size !== review.reviewer_specialists.length) {
948
- throw new Error(`supervisor ${goalId} replanning reviewers are not unique`);
1106
+ throw new Error(`governor ${goalId} replanning reviewers are not unique`);
949
1107
  }
950
1108
  for (const specialist of review.reviewer_specialists) {
951
1109
  if (!specialists[specialist]) {
952
- throw new Error(`supervisor ${goalId} reviewer specialist is not in the frozen team`);
1110
+ throw new Error(`governor ${goalId} reviewer specialist is not in the frozen team`);
953
1111
  }
954
1112
  if (specialist === policy.planner_specialist) {
955
- throw new Error(`supervisor ${goalId} reviewer specialist cannot be planner`);
1113
+ throw new Error(`governor ${goalId} reviewer specialist cannot be planner`);
956
1114
  }
957
1115
  }
958
1116
  const worstCaseAgents =
@@ -960,7 +1118,7 @@ function validateReplanning(
960
1118
  review.reviewer_specialists.length * (review.max_revision_rounds + 1) +
961
1119
  review.max_revision_rounds;
962
1120
  if (worstCaseAgents > limits.max_agents_per_work) {
963
- throw new Error(`supervisor ${goalId} review policy exceeds the agent budget`);
1121
+ throw new Error(`governor ${goalId} review policy exceeds the agent budget`);
964
1122
  }
965
1123
  }
966
1124
  }
@@ -968,12 +1126,12 @@ function validateReplanning(
968
1126
  function collectGovernedWork(
969
1127
  coordRoot: string,
970
1128
  originalRootWorkId: string,
971
- plans: SupervisorPlanHistory,
1129
+ plans: GovernorPlanHistory,
972
1130
  active: WorkRecord[],
973
1131
  ): WorkRecord[] {
974
1132
  const governed = new Map<string, WorkRecord>();
975
1133
  if (workIntentExists(coordRoot, originalRootWorkId)) {
976
- for (const record of collectSupervisorWork(coordRoot, originalRootWorkId)) {
1134
+ for (const record of collectGovernorWork(coordRoot, originalRootWorkId)) {
977
1135
  governed.set(record.intent.id, record);
978
1136
  }
979
1137
  }
@@ -991,17 +1149,17 @@ function missionRootId(goalId: string): string {
991
1149
  return `${goalId.slice(0, 87)}-mission-root`;
992
1150
  }
993
1151
 
994
- function supervisorDir(coordRoot: string, goalId: string): string {
995
- assertSupervisorId(goalId);
996
- return join(resolve(coordRoot), ".harnery", "supervisors", goalId);
1152
+ function governorDir(coordRoot: string, goalId: string): string {
1153
+ assertGovernorId(goalId);
1154
+ return join(resolve(coordRoot), ".harnery", "governors", goalId);
997
1155
  }
998
1156
 
999
- function supervisorIntentPath(coordRoot: string, goalId: string): string {
1000
- return join(supervisorDir(coordRoot, goalId), "intent.json");
1157
+ function governorIntentPath(coordRoot: string, goalId: string): string {
1158
+ return join(governorDir(coordRoot, goalId), "intent.json");
1001
1159
  }
1002
1160
 
1003
- function supervisorLeaseIsLive(coordRoot: string, goalId: string): boolean {
1004
- const lease = readLease(join(supervisorDir(coordRoot, goalId), "lease.json"));
1161
+ function governorLeaseIsLive(coordRoot: string, goalId: string): boolean {
1162
+ const lease = readLease(join(governorDir(coordRoot, goalId), "lease.json"));
1005
1163
  return lease ? leaseIsLive(lease) : false;
1006
1164
  }
1007
1165
 
@@ -1043,7 +1201,7 @@ function leaseIsLive(lease: { pid: number; host: string; created_at: string }):
1043
1201
  function writePrivateJson(path: string, value: unknown): void {
1044
1202
  const body = `${JSON.stringify(value, null, 2)}\n`;
1045
1203
  if (Buffer.byteLength(body) > MAX_INTENT_BYTES) {
1046
- throw new Error(`supervisor intent exceeds ${MAX_INTENT_BYTES} bytes`);
1204
+ throw new Error(`governor intent exceeds ${MAX_INTENT_BYTES} bytes`);
1047
1205
  }
1048
1206
  writeFileSync(path, body, { encoding: "utf8", flag: "wx", mode: 0o600 });
1049
1207
  chmodSync(path, 0o600);
@@ -1072,7 +1230,7 @@ function nonNegative(value: unknown, field: string, max: number): number {
1072
1230
  }
1073
1231
 
1074
1232
  function boolean(value: unknown, field: string): boolean {
1075
- if (typeof value !== "boolean") throw new Error(`supervisor ${field} must be boolean`);
1233
+ if (typeof value !== "boolean") throw new Error(`governor ${field} must be boolean`);
1076
1234
  return value;
1077
1235
  }
1078
1236