harnery 0.30.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 (501) 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.map +1 -1
  51. package/dist/commands/work.js +38 -22
  52. package/dist/commands/workflow.d.ts.map +1 -1
  53. package/dist/commands/workflow.js +35 -28
  54. package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
  55. package/dist/core/adapters/attest-projection.d.ts.map +1 -0
  56. package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
  57. package/dist/core/adapters/attest.d.ts.map +1 -0
  58. package/dist/core/{harnesses → adapters}/attest.js +9 -9
  59. package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
  60. package/dist/core/adapters/attestation.d.ts.map +1 -0
  61. package/dist/core/{harnesses → adapters}/attestation.js +20 -20
  62. package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
  63. package/dist/core/adapters/bench.d.ts.map +1 -0
  64. package/dist/core/{harnesses → adapters}/bench.js +12 -12
  65. package/dist/core/adapters/index.d.ts +13 -0
  66. package/dist/core/adapters/index.d.ts.map +1 -0
  67. package/dist/core/adapters/index.js +6 -0
  68. package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
  69. package/dist/core/adapters/profiles.d.ts.map +1 -0
  70. package/dist/core/{harnesses → adapters}/profiles.js +11 -11
  71. package/dist/core/adapters/registry.d.ts +15 -0
  72. package/dist/core/adapters/registry.d.ts.map +1 -0
  73. package/dist/core/{harnesses → adapters}/registry.js +11 -11
  74. package/dist/core/{harnesses → adapters}/types.d.ts +23 -23
  75. package/dist/core/adapters/types.d.ts.map +1 -0
  76. package/dist/core/{harnesses → adapters}/types.js +1 -1
  77. package/dist/core/agents/canonical-emit.d.ts +4 -4
  78. package/dist/core/agents/canonical-emit.js +5 -5
  79. package/dist/core/agents/cli-emit.js +1 -1
  80. package/dist/core/agents/cli.js +30 -26
  81. package/dist/core/agents/codex-replay.d.ts +1 -1
  82. package/dist/core/agents/codex-replay.js +6 -6
  83. package/dist/core/agents/coord-client.d.ts +21 -2
  84. package/dist/core/agents/coord-client.d.ts.map +1 -1
  85. package/dist/core/agents/coord-client.js +122 -27
  86. package/dist/core/agents/events/consume.d.ts +1 -1
  87. package/dist/core/agents/events/emit.d.ts +5 -6
  88. package/dist/core/agents/events/emit.d.ts.map +1 -1
  89. package/dist/core/agents/events/emit.js +2 -2
  90. package/dist/core/agents/render/prompt-context.d.ts +21 -9
  91. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  92. package/dist/core/agents/render/prompt-context.js +82 -30
  93. package/dist/core/agents/render/session-context.d.ts +1 -1
  94. package/dist/core/agents/render/session-context.js +5 -5
  95. package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
  96. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  97. package/dist/core/agents/rules/claim-conflict.js +1 -1
  98. package/dist/core/agents/rules/commit-conflict.js +98 -22
  99. package/dist/core/agents/rules/stop-hook.d.ts +9 -9
  100. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  101. package/dist/core/agents/rules/stop-hook.js +23 -5
  102. package/dist/core/agents/rules/verdict.d.ts +14 -0
  103. package/dist/core/agents/rules/verdict.d.ts.map +1 -0
  104. package/dist/core/agents/rules/verdict.js +1 -0
  105. package/dist/core/agents/session-events.js +3 -3
  106. package/dist/core/agents/state/council.d.ts +1 -1
  107. package/dist/core/agents/state/council.js +1 -1
  108. package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
  109. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
  110. package/dist/core/agents/state/heartbeat-projector.js +14 -10
  111. package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
  112. package/dist/core/agents/state/heartbeat-writer.js +12 -12
  113. package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
  114. package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
  115. package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
  116. package/dist/core/agents/state/pidmap.d.ts +28 -4
  117. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  118. package/dist/core/agents/state/pidmap.js +130 -15
  119. package/dist/core/agents/state/proc-start.d.ts +95 -0
  120. package/dist/core/agents/state/proc-start.d.ts.map +1 -0
  121. package/dist/core/agents/state/proc-start.js +199 -0
  122. package/dist/core/agents/state/shell-mutation.d.ts +1 -1
  123. package/dist/core/agents/state/shell-mutation.js +1 -1
  124. package/dist/core/agents/state/stale-sweep.js +7 -7
  125. package/dist/core/artifacts/index.d.ts +86 -0
  126. package/dist/core/artifacts/index.d.ts.map +1 -0
  127. package/dist/core/artifacts/index.js +421 -0
  128. package/dist/core/config.d.ts +9 -2
  129. package/dist/core/config.d.ts.map +1 -1
  130. package/dist/core/config.js +26 -2
  131. package/dist/core/context/index.d.ts +12 -12
  132. package/dist/core/context/index.js +10 -10
  133. package/dist/core/governor/adapter-spread.d.ts +52 -0
  134. package/dist/core/governor/adapter-spread.d.ts.map +1 -0
  135. package/dist/core/governor/adapter-spread.js +52 -0
  136. package/dist/core/governor/index.d.ts +7 -0
  137. package/dist/core/governor/index.d.ts.map +1 -0
  138. package/dist/core/governor/index.js +6 -0
  139. package/dist/core/governor/plan-api.d.ts +38 -0
  140. package/dist/core/governor/plan-api.d.ts.map +1 -0
  141. package/dist/core/governor/plan-api.js +83 -0
  142. package/dist/core/governor/plan-read.d.ts +5 -0
  143. package/dist/core/governor/plan-read.d.ts.map +1 -0
  144. package/dist/core/{supervisor → governor}/plan-read.js +66 -52
  145. package/dist/core/{supervisor → governor}/plan-types.d.ts +57 -56
  146. package/dist/core/governor/plan-types.d.ts.map +1 -0
  147. package/dist/core/{supervisor → governor}/plan-types.js +4 -4
  148. package/dist/core/governor/planning.d.ts +48 -0
  149. package/dist/core/governor/planning.d.ts.map +1 -0
  150. package/dist/core/{supervisor → governor}/planning.js +125 -94
  151. package/dist/core/governor/read.d.ts +6 -0
  152. package/dist/core/governor/read.d.ts.map +1 -0
  153. package/dist/core/governor/read.js +4 -0
  154. package/dist/core/governor/runner.d.ts +37 -0
  155. package/dist/core/governor/runner.d.ts.map +1 -0
  156. package/dist/core/{supervisor → governor}/runner.js +15 -15
  157. package/dist/core/governor/service-read.d.ts +6 -0
  158. package/dist/core/governor/service-read.d.ts.map +1 -0
  159. package/dist/core/{supervisor → governor}/service-read.js +12 -12
  160. package/dist/core/governor/service.d.ts +114 -0
  161. package/dist/core/governor/service.d.ts.map +1 -0
  162. package/dist/core/{supervisor → governor}/service.js +57 -57
  163. package/dist/core/governor/state.d.ts +116 -0
  164. package/dist/core/governor/state.d.ts.map +1 -0
  165. package/dist/core/{supervisor → governor}/state.js +228 -108
  166. package/dist/core/hooks/adapter/detect.d.ts +9 -0
  167. package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
  168. package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
  169. package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
  170. package/dist/core/hooks/adapter/events.d.ts.map +1 -0
  171. package/dist/core/hooks/{harness → adapter}/events.js +5 -5
  172. package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
  173. package/dist/core/hooks/adapter/output.d.ts.map +1 -0
  174. package/dist/core/hooks/{harness → adapter}/output.js +30 -22
  175. package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
  176. package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
  177. package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
  178. package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
  179. package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
  180. package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
  181. package/dist/core/hooks/cli.d.ts +3 -3
  182. package/dist/core/hooks/cli.js +175 -151
  183. package/dist/core/hooks/effects/image-capture.d.ts +5 -5
  184. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  185. package/dist/core/hooks/effects/image-capture.js +3 -3
  186. package/dist/core/hooks/effects/index.d.ts +12 -12
  187. package/dist/core/hooks/effects/index.d.ts.map +1 -1
  188. package/dist/core/hooks/effects/index.js +17 -17
  189. package/dist/core/hooks/events/emit.d.ts +2 -2
  190. package/dist/core/hooks/events/emit.d.ts.map +1 -1
  191. package/dist/core/hooks/events/emit.js +1 -1
  192. package/dist/core/hooks/events/rotate.js +1 -1
  193. package/dist/core/hooks/events/schema.d.ts +13 -5
  194. package/dist/core/hooks/events/schema.d.ts.map +1 -1
  195. package/dist/core/hooks/guard-path.d.ts +2 -2
  196. package/dist/core/hooks/guard-path.js +2 -2
  197. package/dist/core/hooks/index.d.ts +1 -1
  198. package/dist/core/hooks/index.d.ts.map +1 -1
  199. package/dist/core/hooks/resolve/anchor.d.ts +14 -5
  200. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
  201. package/dist/core/hooks/resolve/anchor.js +64 -7
  202. package/dist/core/hooks/resolve/coord-root.d.ts +3 -3
  203. package/dist/core/hooks/resolve/coord-root.js +4 -4
  204. package/dist/core/hooks/resolve/intent.js +1 -1
  205. package/dist/core/hooks/resolve/owner.d.ts +1 -1
  206. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  207. package/dist/core/hooks/resolve/owner.js +11 -5
  208. package/dist/core/{scratch → journal}/index.d.ts +25 -25
  209. package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
  210. package/dist/core/{scratch → journal}/index.js +38 -38
  211. package/dist/core/policy/evaluate.d.ts +1 -1
  212. package/dist/core/policy/evaluate.d.ts.map +1 -1
  213. package/dist/core/policy/evaluate.js +7 -7
  214. package/dist/core/policy/types.d.ts +3 -3
  215. package/dist/core/policy/types.d.ts.map +1 -1
  216. package/dist/core/work/state.d.ts +12 -4
  217. package/dist/core/work/state.d.ts.map +1 -1
  218. package/dist/core/work/state.js +50 -17
  219. package/dist/core/workflow/adapters.d.ts +17 -0
  220. package/dist/core/workflow/adapters.d.ts.map +1 -0
  221. package/dist/core/workflow/adapters.js +21 -0
  222. package/dist/core/workflow/approvals.js +6 -6
  223. package/dist/core/workflow/billing.d.ts +9 -9
  224. package/dist/core/workflow/billing.js +9 -9
  225. package/dist/core/workflow/child-env.d.ts +10 -2
  226. package/dist/core/workflow/child-env.d.ts.map +1 -1
  227. package/dist/core/workflow/child-env.js +12 -4
  228. package/dist/core/workflow/engine.d.ts +15 -5
  229. package/dist/core/workflow/engine.d.ts.map +1 -1
  230. package/dist/core/workflow/engine.js +138 -83
  231. package/dist/core/workflow/evidence-preflight.d.ts +24 -0
  232. package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
  233. package/dist/core/workflow/evidence-preflight.js +134 -0
  234. package/dist/core/workflow/index.d.ts +1 -1
  235. package/dist/core/workflow/index.d.ts.map +1 -1
  236. package/dist/core/workflow/proof.d.ts +11 -5
  237. package/dist/core/workflow/proof.d.ts.map +1 -1
  238. package/dist/core/workflow/proof.js +45 -36
  239. package/dist/core/workflow/run-state.d.ts +1 -1
  240. package/dist/core/workflow/run-state.js +7 -7
  241. package/dist/core/workflow/sandbox-projection.d.ts +6 -6
  242. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  243. package/dist/core/workflow/sandbox-projection.js +11 -11
  244. package/dist/core/workflow/spawn-claude.d.ts +3 -3
  245. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  246. package/dist/core/workflow/spawn-claude.js +9 -6
  247. package/dist/core/workflow/spawn-codex.d.ts +4 -4
  248. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  249. package/dist/core/workflow/spawn-codex.js +9 -6
  250. package/dist/core/workflow/spawn-cursor.d.ts +4 -4
  251. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  252. package/dist/core/workflow/spawn-cursor.js +9 -6
  253. package/dist/core/workflow/spawn-failure.d.ts +1 -1
  254. package/dist/core/workflow/spawn-failure.js +1 -1
  255. package/dist/core/workflow/specialists.js +2 -2
  256. package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
  257. package/dist/core/workflow/transcript.d.ts.map +1 -0
  258. package/dist/core/workflow/{journal.js → transcript.js} +14 -14
  259. package/dist/core/workflow/types.d.ts +98 -51
  260. package/dist/core/workflow/types.d.ts.map +1 -1
  261. package/dist/core/workflow/types.js +11 -1
  262. package/dist/core/workflow/validate.d.ts +1 -1
  263. package/dist/core/workflow/validate.js +1 -1
  264. package/dist/core/workflow/workspaces/cancellation.js +2 -2
  265. package/dist/core/workflow/workspaces/cleanup.js +2 -2
  266. package/dist/core/workflow/workspaces/execution.js +6 -6
  267. package/dist/core/workflow/workspaces/inspect.js +9 -9
  268. package/dist/core/workflow/workspaces/integration.js +14 -14
  269. package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
  270. package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
  271. package/dist/core/workflow/workspaces/lifecycle.js +9 -9
  272. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  273. package/dist/core/workflow/workspaces/local-git.js +39 -5
  274. package/dist/core/workflow/workspaces/recovery.js +3 -3
  275. package/dist/core/workflow/workspaces/state.d.ts +1 -1
  276. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  277. package/dist/core/workflow/workspaces/state.js +3 -3
  278. package/dist/core/workflow/workspaces/types.d.ts +1 -1
  279. package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
  280. package/dist/lib/browser/asserts.d.ts +28 -0
  281. package/dist/lib/browser/asserts.d.ts.map +1 -0
  282. package/dist/lib/browser/asserts.js +152 -0
  283. package/dist/lib/browser/client.d.ts +49 -0
  284. package/dist/lib/browser/client.d.ts.map +1 -1
  285. package/dist/lib/browser/client.js +155 -14
  286. package/dist/lib/browser/content-checks.d.ts +108 -0
  287. package/dist/lib/browser/content-checks.d.ts.map +1 -0
  288. package/dist/lib/browser/content-checks.js +474 -0
  289. package/dist/lib/browser/critique.d.ts +91 -0
  290. package/dist/lib/browser/critique.d.ts.map +1 -0
  291. package/dist/lib/browser/critique.js +167 -0
  292. package/dist/lib/browser/geometry.d.ts +32 -0
  293. package/dist/lib/browser/geometry.d.ts.map +1 -1
  294. package/dist/lib/browser/geometry.js +244 -1
  295. package/dist/lib/browser/index.d.ts +4 -1
  296. package/dist/lib/browser/index.d.ts.map +1 -1
  297. package/dist/lib/browser/index.js +2 -0
  298. package/dist/lib/claude-desktop.d.ts.map +1 -1
  299. package/dist/lib/claude-desktop.js +4 -1
  300. package/dist/lib/council/index.d.ts +6 -6
  301. package/dist/lib/council/index.d.ts.map +1 -1
  302. package/dist/lib/council/index.js +8 -8
  303. package/dist/lib/identities/assume.d.ts +2 -2
  304. package/dist/lib/identities/assume.js +7 -7
  305. package/dist/lib/instructions/apply.d.ts +3 -3
  306. package/dist/lib/instructions/apply.d.ts.map +1 -1
  307. package/dist/lib/instructions/apply.js +75 -27
  308. package/dist/lib/instructions/host-addendum.d.ts +54 -0
  309. package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
  310. package/dist/lib/instructions/host-addendum.js +107 -0
  311. package/dist/lib/instructions/templates.d.ts +10 -3
  312. package/dist/lib/instructions/templates.d.ts.map +1 -1
  313. package/dist/lib/instructions/templates.js +41 -12
  314. package/dist/lib/machine.d.ts +2 -2
  315. package/dist/lib/machine.js +2 -2
  316. package/package.json +26 -21
  317. package/schemas/config.schema.json +26 -1
  318. package/src/commander.ts +22 -13
  319. package/src/commands/{harness.ts → adapter.ts} +46 -46
  320. package/src/commands/agents.ts +71 -64
  321. package/src/commands/artifacts.ts +168 -0
  322. package/src/commands/backup.ts +47 -33
  323. package/src/commands/browse.ts +438 -2
  324. package/src/commands/checkpoint.ts +196 -0
  325. package/src/commands/context.ts +3 -176
  326. package/src/commands/decision.ts +41 -7
  327. package/src/commands/deinit.ts +16 -16
  328. package/src/commands/doctor.ts +28 -28
  329. package/src/commands/{supervisor.ts → governor.ts} +184 -154
  330. package/src/commands/init.ts +50 -34
  331. package/src/commands/{scratch.ts → journal.ts} +60 -60
  332. package/src/commands/policy.ts +1 -1
  333. package/src/commands/presence.ts +2 -2
  334. package/src/commands/sync.ts +3 -3
  335. package/src/commands/tunnel.ts +237 -34
  336. package/src/commands/web-fetch.ts +1 -1
  337. package/src/commands/web.ts +56 -1
  338. package/src/commands/work.ts +50 -35
  339. package/src/commands/workflow.ts +43 -34
  340. package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
  341. package/src/core/{harnesses → adapters}/attest.ts +27 -27
  342. package/src/core/{harnesses → adapters}/attestation.ts +41 -41
  343. package/src/core/{harnesses → adapters}/bench.ts +34 -43
  344. package/src/core/adapters/index.ts +56 -0
  345. package/src/core/{harnesses → adapters}/profiles.ts +16 -16
  346. package/src/core/{harnesses → adapters}/registry.ts +23 -23
  347. package/src/core/{harnesses → adapters}/types.ts +23 -23
  348. package/src/core/agents/canonical-emit.ts +6 -6
  349. package/src/core/agents/cli-emit.ts +1 -1
  350. package/src/core/agents/cli.ts +30 -28
  351. package/src/core/agents/codex-replay.ts +6 -6
  352. package/src/core/agents/coord-client.ts +119 -28
  353. package/src/core/agents/events/consume.ts +1 -1
  354. package/src/core/agents/events/emit.ts +7 -6
  355. package/src/core/agents/render/prompt-context.ts +107 -31
  356. package/src/core/agents/render/session-context.ts +6 -6
  357. package/src/core/agents/rules/claim-conflict.ts +4 -7
  358. package/src/core/agents/rules/commit-conflict.ts +103 -22
  359. package/src/core/agents/rules/stop-hook.ts +33 -17
  360. package/src/core/agents/rules/verdict.ts +13 -0
  361. package/src/core/agents/session-events.ts +4 -4
  362. package/src/core/agents/state/council.ts +1 -1
  363. package/src/core/agents/state/heartbeat-projector.ts +16 -12
  364. package/src/core/agents/state/heartbeat-writer.ts +12 -12
  365. package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
  366. package/src/core/agents/state/pidmap.ts +130 -15
  367. package/src/core/agents/state/proc-start.ts +208 -0
  368. package/src/core/agents/state/shell-mutation.ts +1 -1
  369. package/src/core/agents/state/stale-sweep.ts +7 -7
  370. package/src/core/artifacts/index.ts +557 -0
  371. package/src/core/config.ts +30 -2
  372. package/src/core/context/index.ts +15 -15
  373. package/src/core/governor/adapter-spread.ts +82 -0
  374. package/src/core/governor/index.ts +91 -0
  375. package/src/core/governor/plan-api.ts +115 -0
  376. package/src/core/{supervisor → governor}/plan-read.ts +112 -97
  377. package/src/core/{supervisor → governor}/plan-types.ts +59 -56
  378. package/src/core/{supervisor → governor}/planning.ts +223 -192
  379. package/src/core/governor/read.ts +59 -0
  380. package/src/core/{supervisor → governor}/runner.ts +39 -39
  381. package/src/core/{supervisor → governor}/service-read.ts +22 -22
  382. package/src/core/{supervisor → governor}/service.ts +117 -119
  383. package/src/core/{supervisor → governor}/state.ts +325 -167
  384. package/src/core/hooks/adapter/detect.ts +30 -0
  385. package/src/core/hooks/{harness → adapter}/events.ts +16 -14
  386. package/src/core/hooks/{harness → adapter}/output.ts +31 -23
  387. package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
  388. package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
  389. package/src/core/hooks/cli.ts +185 -162
  390. package/src/core/hooks/effects/image-capture.ts +6 -6
  391. package/src/core/hooks/effects/index.ts +17 -17
  392. package/src/core/hooks/events/emit.ts +3 -3
  393. package/src/core/hooks/events/rotate.ts +1 -1
  394. package/src/core/hooks/events/schema.ts +15 -7
  395. package/src/core/hooks/guard-path.ts +2 -2
  396. package/src/core/hooks/index.ts +1 -1
  397. package/src/core/hooks/resolve/anchor.ts +63 -8
  398. package/src/core/hooks/resolve/coord-root.ts +4 -4
  399. package/src/core/hooks/resolve/intent.ts +1 -1
  400. package/src/core/hooks/resolve/owner.ts +11 -5
  401. package/src/core/{scratch → journal}/index.ts +53 -53
  402. package/src/core/policy/evaluate.ts +8 -8
  403. package/src/core/policy/types.ts +3 -3
  404. package/src/core/work/state.ts +65 -23
  405. package/src/core/workflow/adapters.ts +33 -0
  406. package/src/core/workflow/approvals.ts +7 -7
  407. package/src/core/workflow/billing.ts +12 -12
  408. package/src/core/workflow/child-env.ts +13 -4
  409. package/src/core/workflow/engine.ts +155 -90
  410. package/src/core/workflow/evidence-preflight.ts +165 -0
  411. package/src/core/workflow/index.ts +3 -3
  412. package/src/core/workflow/proof.ts +60 -50
  413. package/src/core/workflow/run-state.ts +7 -7
  414. package/src/core/workflow/sandbox-projection.ts +16 -16
  415. package/src/core/workflow/spawn-claude.ts +13 -10
  416. package/src/core/workflow/spawn-codex.ts +13 -10
  417. package/src/core/workflow/spawn-cursor.ts +13 -10
  418. package/src/core/workflow/spawn-failure.ts +1 -1
  419. package/src/core/workflow/specialists.ts +2 -2
  420. package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
  421. package/src/core/workflow/types.ts +108 -51
  422. package/src/core/workflow/validate.ts +1 -1
  423. package/src/core/workflow/workspaces/cancellation.ts +2 -2
  424. package/src/core/workflow/workspaces/cleanup.ts +2 -2
  425. package/src/core/workflow/workspaces/execution.ts +6 -6
  426. package/src/core/workflow/workspaces/inspect.ts +14 -11
  427. package/src/core/workflow/workspaces/integration.ts +18 -14
  428. package/src/core/workflow/workspaces/lifecycle.ts +10 -10
  429. package/src/core/workflow/workspaces/local-git.ts +47 -5
  430. package/src/core/workflow/workspaces/recovery.ts +3 -3
  431. package/src/core/workflow/workspaces/state.ts +4 -3
  432. package/src/core/workflow/workspaces/types.ts +1 -1
  433. package/src/lib/browser/asserts.ts +177 -0
  434. package/src/lib/browser/client.ts +189 -14
  435. package/src/lib/browser/content-checks.ts +571 -0
  436. package/src/lib/browser/critique.ts +231 -0
  437. package/src/lib/browser/geometry.ts +297 -1
  438. package/src/lib/browser/index.ts +34 -0
  439. package/src/lib/claude-desktop.ts +4 -1
  440. package/src/lib/council/index.ts +9 -9
  441. package/src/lib/identities/assume.ts +7 -7
  442. package/src/lib/instructions/apply.ts +87 -25
  443. package/src/lib/instructions/host-addendum.ts +126 -0
  444. package/src/lib/instructions/templates.ts +44 -15
  445. package/src/lib/machine.ts +2 -2
  446. package/dist/commands/harness.d.ts +0 -12
  447. package/dist/commands/harness.d.ts.map +0 -1
  448. package/dist/commands/scratch.d.ts +0 -4
  449. package/dist/commands/scratch.d.ts.map +0 -1
  450. package/dist/commands/session.d.ts.map +0 -1
  451. package/dist/commands/session.js +0 -162
  452. package/dist/commands/supervisor.d.ts +0 -4
  453. package/dist/commands/supervisor.d.ts.map +0 -1
  454. package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
  455. package/dist/core/harnesses/attest.d.ts.map +0 -1
  456. package/dist/core/harnesses/attestation.d.ts.map +0 -1
  457. package/dist/core/harnesses/bench.d.ts.map +0 -1
  458. package/dist/core/harnesses/index.d.ts +0 -13
  459. package/dist/core/harnesses/index.d.ts.map +0 -1
  460. package/dist/core/harnesses/index.js +0 -6
  461. package/dist/core/harnesses/profiles.d.ts.map +0 -1
  462. package/dist/core/harnesses/registry.d.ts +0 -15
  463. package/dist/core/harnesses/registry.d.ts.map +0 -1
  464. package/dist/core/harnesses/types.d.ts.map +0 -1
  465. package/dist/core/hooks/harness/detect.d.ts +0 -9
  466. package/dist/core/hooks/harness/events.d.ts.map +0 -1
  467. package/dist/core/hooks/harness/output.d.ts.map +0 -1
  468. package/dist/core/supervisor/index.d.ts +0 -7
  469. package/dist/core/supervisor/index.d.ts.map +0 -1
  470. package/dist/core/supervisor/index.js +0 -6
  471. package/dist/core/supervisor/plan-api.d.ts +0 -23
  472. package/dist/core/supervisor/plan-api.d.ts.map +0 -1
  473. package/dist/core/supervisor/plan-api.js +0 -50
  474. package/dist/core/supervisor/plan-read.d.ts +0 -5
  475. package/dist/core/supervisor/plan-read.d.ts.map +0 -1
  476. package/dist/core/supervisor/plan-types.d.ts.map +0 -1
  477. package/dist/core/supervisor/planning.d.ts +0 -33
  478. package/dist/core/supervisor/planning.d.ts.map +0 -1
  479. package/dist/core/supervisor/read.d.ts +0 -6
  480. package/dist/core/supervisor/read.d.ts.map +0 -1
  481. package/dist/core/supervisor/read.js +0 -4
  482. package/dist/core/supervisor/runner.d.ts +0 -37
  483. package/dist/core/supervisor/runner.d.ts.map +0 -1
  484. package/dist/core/supervisor/service-read.d.ts +0 -6
  485. package/dist/core/supervisor/service-read.d.ts.map +0 -1
  486. package/dist/core/supervisor/service.d.ts +0 -114
  487. package/dist/core/supervisor/service.d.ts.map +0 -1
  488. package/dist/core/supervisor/state.d.ts +0 -95
  489. package/dist/core/supervisor/state.d.ts.map +0 -1
  490. package/dist/core/workflow/harnesses.d.ts +0 -17
  491. package/dist/core/workflow/harnesses.d.ts.map +0 -1
  492. package/dist/core/workflow/harnesses.js +0 -21
  493. package/dist/core/workflow/journal.d.ts.map +0 -1
  494. package/src/commands/session.ts +0 -187
  495. package/src/core/harnesses/index.ts +0 -56
  496. package/src/core/hooks/harness/detect.ts +0 -30
  497. package/src/core/supervisor/index.ts +0 -89
  498. package/src/core/supervisor/plan-api.ts +0 -73
  499. package/src/core/supervisor/read.ts +0 -59
  500. package/src/core/workflow/harnesses.ts +0 -33
  501. /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
@@ -3,8 +3,8 @@
3
3
  * alongside the legacy stream.
4
4
  *
5
5
  * Flow:
6
- * 1. Parse argv → event-name + harness.
7
- * 2. Read stdin → harness payload (JSON or empty).
6
+ * 1. Parse argv → event-name + adapter.
7
+ * 2. Read stdin → adapter payload (JSON or empty).
8
8
  * 3. Find coord root (walk up for .harnery/).
9
9
  * 4. Resolve instance_id (env → payload → pid-map walk).
10
10
  * 5. Map event-name → canonical event_type.
@@ -15,7 +15,7 @@
15
15
  * Phase 2 ship criterion: confirms parser correctness across thousands of
16
16
  * real events without affecting behavior. Always exits 0. Failures land in
17
17
  * `.harnery/debug/agent-hook.errors.ndjson` for audit but never break the
18
- * harness flow.
18
+ * adapter flow.
19
19
  */
20
20
  import { spawnSync } from "node:child_process";
21
21
  import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
@@ -25,15 +25,16 @@ import { replayCodexJsonl } from "../agents/codex-replay.js";
25
25
  import { consumeSince, writeCursor } from "../agents/events/consume.js";
26
26
  import { evaluateStopHook } from "../agents/rules/stop-hook.js";
27
27
  import { projectHeartbeats } from "../agents/state/heartbeat-projector.js";
28
+ import { writePidmapRow } from "../agents/state/pidmap.js";
28
29
  import { shellMutationPaths } from "../agents/state/shell-mutation.js";
29
30
  import { checkpointContext, completeContextRecovery, extractContextSample, markContextCompactionCompleted, prepareContextRecovery, readContextState, recordContextSample, } from "../context/index.js";
30
31
  import { ensureRelayDaemon, fetchPresence, publishPresence } from "../presence/index.js";
31
- import { captureImages, detectPresence, imageJanitor, playSound, resetSoundCounters, runSessionSyncExtension, runTurnSummary, scratchArchive, scratchJanitor, scratchRecoveryCue, soundForEvent, } from "./effects/index.js";
32
+ import { detectAdapter } from "./adapter/detect.js";
33
+ import { extractBashCommand, extractToolDescription, normalizeEventName, parsePayload, } from "./adapter/parse.js";
34
+ import { captureImages, detectPresence, imageJanitor, journalArchive, journalJanitor, journalRecoveryCue, playSound, resetSoundCounters, runSessionSyncExtension, runTurnSummary, soundForEvent, } from "./effects/index.js";
32
35
  import { emit } from "./events/emit.js";
33
36
  import { canonicalize } from "./guard-path.js";
34
- import { detectHarness } from "./harness/detect.js";
35
- import { extractBashCommand, extractToolDescription, normalizeEventName, parsePayload, } from "./harness/parse.js";
36
- import { parsePsChainLine, selectAnchorPid } from "./resolve/anchor.js";
37
+ import { adapterPidFromEnv, parsePsChainLine, selectAnchorPid } from "./resolve/anchor.js";
37
38
  import { findCoordRoot } from "./resolve/coord-root.js";
38
39
  import { extractIntentComment, resolveIntent } from "./resolve/intent.js";
39
40
  import { resolveOwner } from "./resolve/owner.js";
@@ -42,11 +43,11 @@ function parseArgv(argv) {
42
43
  const out = { eventName: null, extra: [] };
43
44
  for (let i = 0; i < argv.length; i++) {
44
45
  const arg = argv[i];
45
- if (arg === "--harness") {
46
- i++; // detectHarness will re-parse; just consume the value here.
46
+ if (arg === "--adapter") {
47
+ i++; // detectAdapter will re-parse; just consume the value here.
47
48
  continue;
48
49
  }
49
- if (arg.startsWith("--harness="))
50
+ if (arg.startsWith("--adapter="))
50
51
  continue;
51
52
  if (!out.eventName && !arg.startsWith("--")) {
52
53
  out.eventName = arg;
@@ -74,7 +75,7 @@ async function readStdin() {
74
75
  /**
75
76
  * Env for child agent-coord spawns, with the coord root pinned. The hook
76
77
  * process may be running with the session shell's cwd (inside a submodule or
77
- * scratch dir), and agent-coord resolves its root from cwd unless overridden —
78
+ * journal dir), and agent-coord resolves its root from cwd unless overridden —
78
79
  * without the pin a child could write state to a different .harnery than the
79
80
  * one this hook resolved.
80
81
  */
@@ -111,7 +112,7 @@ function logError(coordRoot, err, context) {
111
112
  /**
112
113
  * Spawn `agent-coord assign-name <owner> <kind>` to mint or recover the
113
114
  * hurricane-style name for this owner. Returns null on any failure so
114
- * session.start emission never breaks the harness flow.
115
+ * session.start emission never breaks the adapter flow.
115
116
  *
116
117
  * Lives at agent-hooks side (not agent-coord) to keep emitter/consumer
117
118
  * separation: we spawn rather than import.
@@ -139,35 +140,22 @@ function assignNameViaAgentCoord(coordRoot, instanceId, kind) {
139
140
  }
140
141
  }
141
142
  /**
142
- * Direct (in-process) pidmap write, avoids the spawn overhead of going via
143
- * the agent-coord CLI for every session.start / subagent.start. Pid-map
144
- * rows are essential for `harn agents whoami` ppid resolution.
143
+ * Direct (in-process) pidmap write, avoiding the spawn overhead of going via
144
+ * the agent-coord CLI for every session.start / subagent.start. Pid-map rows
145
+ * are essential for `harn agents whoami` ppid resolution.
146
+ *
147
+ * This used to inline its own copy of the write to keep this module's
148
+ * dependencies narrow, which quietly mattered: the shared writer is where row
149
+ * hygiene lives, so the duplicate meant the only hot write path in the system
150
+ * never swept dead rows, and the map grew unbounded. It calls the shared writer
151
+ * now, and this module already imports from that directory anyway.
145
152
  */
146
153
  function writePidmapViaAgentCoord(coordRoot, pid, instanceId, platform) {
147
154
  try {
148
- // Inline write: same atomic temp+rename pattern as
149
- // agent-coord/src/state/pidmap.ts but skips importing across module
150
- // boundaries to keep agent-hooks's deps explicit.
151
- const dir = join(coordRoot, ".harnery", "pid-map");
152
- const path = join(dir, String(pid));
153
- const row = `${instanceId}\t${platform}`;
154
- if (existsSync(path)) {
155
- try {
156
- const current = require("node:fs").readFileSync(path, "utf8");
157
- if (current === row)
158
- return;
159
- }
160
- catch {
161
- /* fall through */
162
- }
163
- }
164
- mkdirSync(dir, { recursive: true });
165
- const tmp = `${path}.tmp.${process.pid}`;
166
- require("node:fs").writeFileSync(tmp, row, "utf8");
167
- require("node:fs").renameSync(tmp, path);
155
+ writePidmapRow(coordRoot, pid, instanceId, platform);
168
156
  }
169
157
  catch {
170
- /* never break the harness flow */
158
+ /* never break the adapter flow */
171
159
  }
172
160
  }
173
161
  function clampString(s, max) {
@@ -188,23 +176,23 @@ function buildEventData(eventType, ctx) {
188
176
  const p = ctx.payload;
189
177
  switch (eventType) {
190
178
  case "session.start": {
191
- const harnessPlatform = ctx.harness === "claude-code"
179
+ const adapterPlatform = ctx.adapter === "claude-code"
192
180
  ? "claude_code"
193
- : ctx.harness === "cursor"
181
+ : ctx.adapter === "cursor"
194
182
  ? "cursor"
195
183
  : "codex";
196
184
  // Assign (or recover) name + kind via agent-coord. Idempotent: resume
197
185
  // returns the original name; new owner consumes a counter slot.
198
186
  const assigned = assignNameViaAgentCoord(ctx.coordRoot, ctx.instanceId, "session");
199
- // Write the harness pid-map row so `harn agents whoami` ppid-walks find
187
+ // Write the adapter pid-map row so `harn agents whoami` ppid-walks find
200
188
  // this owner. Prefer the payload pid (the actual claude binary), then the
201
189
  // anchor walk (the `node` ancestor for Cursor, which has no payload pid),
202
190
  // then our own process.ppid. Without the anchor, Cursor anchored on the
203
191
  // ephemeral hook bash parent, a PID that dies before the agent's next
204
192
  // shell tool call, so the ppid walk found nothing (no_pidmap_entry).
205
- const harnessPid = p?.pid ?? findHarnessAnchorPid(ctx.harness) ?? process.ppid;
206
- if (harnessPid) {
207
- writePidmapViaAgentCoord(ctx.coordRoot, harnessPid, ctx.instanceId, harnessPlatform);
193
+ const adapterPid = p?.pid ?? findAdapterAnchorPid(ctx.adapter) ?? process.ppid;
194
+ if (adapterPid) {
195
+ writePidmapViaAgentCoord(ctx.coordRoot, adapterPid, ctx.instanceId, adapterPlatform);
208
196
  }
209
197
  return {
210
198
  started_at: new Date().toISOString(),
@@ -213,17 +201,25 @@ function buildEventData(eventType, ctx) {
213
201
  // supply it). Fall back to the transcript, populated on `resume`, and
214
202
  // backfilled later by `turn.stop` for a fresh `startup` session.
215
203
  model: p?.model ?? scanTranscriptModel(p?.transcript_path),
216
- pid: harnessPid,
204
+ pid: adapterPid,
217
205
  source: p?.source,
218
- platform: harnessPlatform,
206
+ platform: adapterPlatform,
219
207
  name: assigned?.name,
220
208
  kind: "session",
221
209
  agent_id: ctx.instanceId,
222
210
  // Workflow-child linkage: `workflow run` children carry the run id in
223
211
  // env (spawn adapters set it via buildChildEnv), so their sessions and
224
- // heartbeats join back to the run journal + /workflows web view.
212
+ // heartbeats join back to the run transcript + /workflows web view.
225
213
  ...(coordEnv("WORKFLOW_CHILD") === "1" && coordEnv("WORKFLOW_RUN_ID")
226
- ? { workflow_run_id: coordEnv("WORKFLOW_RUN_ID") }
214
+ ? {
215
+ workflow_run_id: coordEnv("WORKFLOW_RUN_ID"),
216
+ // Which agent row of that run this session is. The orchestrator
217
+ // stamps it on the way in, because the adapter does not report a
218
+ // session id until the agent has already finished.
219
+ ...(coordEnv("WORKFLOW_AGENT_ID")
220
+ ? { workflow_agent_id: coordEnv("WORKFLOW_AGENT_ID") }
221
+ : {}),
222
+ }
227
223
  : {}),
228
224
  };
229
225
  }
@@ -239,7 +235,7 @@ function buildEventData(eventType, ctx) {
239
235
  }
240
236
  case "turn.stop": {
241
237
  return {
242
- // Backfill the model for harnesses that omit it at session.start
238
+ // Backfill the model for adapters that omit it at session.start
243
239
  // (Claude Code). The transcript is populated with assistant turns by
244
240
  // Stop-hook time, so this resolves even for fresh `startup` sessions.
245
241
  model: p?.model ?? scanTranscriptModel(p?.transcript_path),
@@ -363,13 +359,13 @@ function numberField(value) {
363
359
  }
364
360
  async function main() {
365
361
  const { eventName, extra } = parseArgv(process.argv.slice(2));
366
- const harness = detectHarness(process.argv.slice(2));
362
+ const adapter = detectAdapter(process.argv.slice(2));
367
363
  const raw = await readStdin();
368
364
  // Kill-switch-INDEPENDENT effects: notification sounds fire BEFORE the
369
365
  // HARNERY_AGENT_COORD_OFF gate so audible feedback survives incident-triage
370
366
  // bypass: sound playback happens before the kill-switch bailout.
371
367
  // Claude-Code-only; stop-failure → error, sub-agent-start → subagent-start.
372
- if (harness === "claude-code" && eventName) {
368
+ if (adapter === "claude-code" && eventName) {
373
369
  const s = soundForEvent(eventName);
374
370
  if (s) {
375
371
  const repoRoot = findCoordRoot(process.cwd());
@@ -401,15 +397,15 @@ async function main() {
401
397
  const debugBase = {
402
398
  ts: new Date().toISOString(),
403
399
  event_name: eventName,
404
- harness,
400
+ adapter,
405
401
  extra_argv: extra,
406
402
  payload_bytes: raw.length,
407
403
  cwd: process.cwd(),
408
404
  pid: process.pid,
409
405
  ppid: process.ppid,
410
406
  };
411
- if (!eventName || !harness) {
412
- appendDebug(coordRoot, { ...debugBase, skipped: "missing-event-or-harness" });
407
+ if (!eventName || !adapter) {
408
+ appendDebug(coordRoot, { ...debugBase, skipped: "missing-event-or-adapter" });
413
409
  return 0;
414
410
  }
415
411
  const norm = normalizeEventName(eventName);
@@ -417,7 +413,7 @@ async function main() {
417
413
  appendDebug(coordRoot, { ...debugBase, skipped: "non-canonical-event" });
418
414
  return 0;
419
415
  }
420
- const payload = parsePayload(raw, harness);
416
+ const payload = parsePayload(raw, adapter);
421
417
  const owner = resolveOwner({ payload: payload?.raw ?? null, coordRoot });
422
418
  if (!owner) {
423
419
  appendDebug(coordRoot, {
@@ -432,7 +428,7 @@ async function main() {
432
428
  coordRoot,
433
429
  payload,
434
430
  raw,
435
- harness,
431
+ adapter,
436
432
  instanceId: owner.instance_id,
437
433
  });
438
434
  const envelope = emit(coordRoot, {
@@ -442,7 +438,7 @@ async function main() {
442
438
  parent_session_id: payload?.parent_session_id,
443
439
  turn_id: payload?.turn_id,
444
440
  parent_turn_id: payload?.parent_turn_id,
445
- harness,
441
+ adapter,
446
442
  data,
447
443
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
448
444
  });
@@ -453,13 +449,13 @@ async function main() {
453
449
  event_id: envelope.event_id,
454
450
  });
455
451
  // Context telemetry is opportunistic and truthful: only persist a sample
456
- // when the harness payload actually exposes usage/window data. Identical
452
+ // when the adapter payload actually exposes usage/window data. Identical
457
453
  // measurements are de-duplicated before they reach the canonical stream.
458
454
  if (payload?.raw) {
459
455
  try {
460
456
  const sample = extractContextSample(payload.raw, {
461
457
  sessionId,
462
- harness,
458
+ adapter,
463
459
  model: payload.model,
464
460
  source: "hook",
465
461
  confidence: "reported",
@@ -471,7 +467,7 @@ async function main() {
471
467
  event_type: "context.sampled",
472
468
  instance_id: owner.instance_id,
473
469
  session_id: sessionId,
474
- harness,
470
+ adapter,
475
471
  data: {
476
472
  model: sample.model,
477
473
  used_tokens: sample.used_tokens,
@@ -490,13 +486,13 @@ async function main() {
490
486
  }
491
487
  // A native pre-compaction signal is the safest available point to capture
492
488
  // external work state. The operation is idempotent until recovery, so a
493
- // harness retry cannot create a storm of near-identical capsules.
489
+ // adapter retry cannot create a storm of near-identical capsules.
494
490
  if (norm.event_type === "context.compaction.started") {
495
491
  try {
496
492
  const checkpoint = checkpointContext(coordRoot, {
497
493
  sessionId,
498
494
  instanceId: owner.instance_id,
499
- harness,
495
+ adapter,
500
496
  cwd: payload?.cwd ?? process.cwd(),
501
497
  reason: "pre_compact",
502
498
  model: payload?.model,
@@ -505,7 +501,7 @@ async function main() {
505
501
  event_type: "context.checkpoint.created",
506
502
  instance_id: owner.instance_id,
507
503
  session_id: sessionId,
508
- harness,
504
+ adapter,
509
505
  data: {
510
506
  capsule_id: checkpoint.capsule.capsule_id,
511
507
  generation: checkpoint.capsule.generation,
@@ -531,18 +527,18 @@ async function main() {
531
527
  }
532
528
  }
533
529
  // Phase 8: SessionStart post-emit: project the event so the heartbeat
534
- // lands synchronously, run stale-sweep, and emit the harness-shaped
530
+ // lands synchronously, run stale-sweep, and emit the adapter-shaped
535
531
  // systemMessage JSON (peer table + wiring check + council invites).
536
- // Harness-agnostic since v0.5.0; replaces the previous bash UX layer
537
- // and the equivalent per-harness bash session_start handlers.
532
+ // Adapter-agnostic since v0.5.0; replaces the previous bash UX layer
533
+ // and the equivalent per-adapter bash session_start handlers.
538
534
  if (norm.event_type === "session.start") {
539
- // Effect (claude-code): prune stale scratch archives + sweep orphans.
535
+ // Effect (claude-code): prune stale journal archives + sweep orphans.
540
536
  // The recovery-cue is merged into the
541
537
  // session-start additionalContext inside emitSessionStartSystemMessage.
542
- if (harness === "claude-code")
543
- scratchJanitor(coordRoot);
544
- // Image-feed retention sweep (size + age cap on .harnery/images/). Harness-
545
- // agnostic, cheap (one readdir), fail-soft. Paired with scratchJanitor as a
538
+ if (adapter === "claude-code")
539
+ journalJanitor(coordRoot);
540
+ // Image-feed retention sweep (size + age cap on .harnery/images/). Adapter-
541
+ // agnostic, cheap (one readdir), fail-soft. Paired with journalJanitor as a
546
542
  // session-start "tidy the coord layer" step.
547
543
  try {
548
544
  imageJanitor(coordRoot);
@@ -557,7 +553,7 @@ async function main() {
557
553
  event_type: "context.compaction.completed",
558
554
  instance_id: owner.instance_id,
559
555
  session_id: sessionId,
560
- harness,
556
+ adapter,
561
557
  data: { trigger: "auto" },
562
558
  });
563
559
  markContextCompactionCompleted(coordRoot, {
@@ -575,9 +571,9 @@ async function main() {
575
571
  }
576
572
  }
577
573
  try {
578
- const injected = await emitSessionStartSystemMessage(coordRoot, owner.instance_id, sessionId, data, harness, recovery?.briefing ?? "");
574
+ const injected = await emitSessionStartSystemMessage(coordRoot, owner.instance_id, sessionId, data, adapter, recovery?.briefing ?? "");
579
575
  if (injected && recovery) {
580
- completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, harness, recovery, "SessionStart");
576
+ completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, adapter, recovery, "SessionStart");
581
577
  }
582
578
  }
583
579
  catch (err) {
@@ -595,7 +591,7 @@ async function main() {
595
591
  logError(coordRoot, err, { phase: "session-start-presence" });
596
592
  }
597
593
  }
598
- // Phase 8: SessionEnd cleanup: delete heartbeat + pid-map rows. Harness-
594
+ // Phase 8: SessionEnd cleanup: delete heartbeat + pid-map rows. Adapter-
599
595
  // agnostic since v0.5.0.
600
596
  if (norm.event_type === "session.end") {
601
597
  try {
@@ -604,10 +600,10 @@ async function main() {
604
600
  catch (err) {
605
601
  logError(coordRoot, err, { phase: "session-end-cleanup" });
606
602
  }
607
- // Effects (claude-code): archive the ending agent's scratchpad + force a
603
+ // Effects (claude-code): archive the ending agent's journal + force a
608
604
  // session-telemetry sync (via HARNERY_CLAUDE_SESSIONS_FORCE=1).
609
- if (harness === "claude-code") {
610
- scratchArchive(coordRoot, owner.instance_id);
605
+ if (adapter === "claude-code") {
606
+ journalArchive(coordRoot, owner.instance_id);
611
607
  runSessionSyncExtension(coordRoot, true);
612
608
  }
613
609
  // Presence: publish the post-cleanup state so peers see this session gone
@@ -633,12 +629,12 @@ async function main() {
633
629
  });
634
630
  spawnSync(agentCoordBin, [
635
631
  "log",
636
- `SUBAGENT_START agent_type=${data.agent_type ?? "unknown"} agent_id=${owner.instance_id.slice(0, 8)} platform=${harnessPlatform(harness)}`,
632
+ `SUBAGENT_START agent_type=${data.agent_type ?? "unknown"} agent_id=${owner.instance_id.slice(0, 8)} platform=${adapterPlatform(adapter)}`,
637
633
  "--instance",
638
634
  owner.instance_id,
639
635
  ], { encoding: "utf8", timeout: 2000, env: childEnv(coordRoot) });
640
636
  }
641
- emitSubagentStartContext(coordRoot, owner.instance_id, sessionId, data, harness);
637
+ emitSubagentStartContext(coordRoot, owner.instance_id, sessionId, data, adapter);
642
638
  }
643
639
  catch (err) {
644
640
  logError(coordRoot, err, { phase: "subagent-start-project" });
@@ -652,7 +648,7 @@ async function main() {
652
648
  if (existsSync(agentCoordBin)) {
653
649
  spawnSync(agentCoordBin, [
654
650
  "log",
655
- `SUBAGENT_STOP agent_id=${owner.instance_id.slice(0, 8)} platform=${harnessPlatform(harness)}`,
651
+ `SUBAGENT_STOP agent_id=${owner.instance_id.slice(0, 8)} platform=${adapterPlatform(adapter)}`,
656
652
  "--instance",
657
653
  owner.instance_id,
658
654
  ], { encoding: "utf8", timeout: 2000, env: childEnv(coordRoot) });
@@ -663,11 +659,11 @@ async function main() {
663
659
  }
664
660
  }
665
661
  // Phase 8: UserPromptSubmit: render dedup'd peer table + council pending
666
- // and emit the harness-shaped systemMessage JSON. Harness-agnostic since v0.5.0.
662
+ // and emit the adapter-shaped systemMessage JSON. Adapter-agnostic since v0.5.0.
667
663
  if (norm.event_type === "user_prompt.submit") {
668
664
  // Effects (claude-code): reset per-turn sound rate-limit counters + run
669
665
  // presence detection on the prompt.
670
- if (harness === "claude-code") {
666
+ if (adapter === "claude-code") {
671
667
  resetSoundCounters(sessionId);
672
668
  const prompt = payload?.raw?.prompt ?? "";
673
669
  if (prompt)
@@ -697,9 +693,9 @@ async function main() {
697
693
  }
698
694
  }
699
695
  try {
700
- const injected = await emitUserPromptSubmitSystemMessage(coordRoot, owner.instance_id, sessionId, harness, recovery?.briefing ?? "");
696
+ const injected = await emitUserPromptSubmitSystemMessage(coordRoot, owner.instance_id, sessionId, adapter, recovery?.briefing ?? "");
701
697
  if (injected && recovery) {
702
- completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, harness, recovery, "UserPromptSubmit");
698
+ completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, adapter, recovery, "UserPromptSubmit");
703
699
  }
704
700
  }
705
701
  catch (err) {
@@ -707,7 +703,7 @@ async function main() {
707
703
  }
708
704
  }
709
705
  // turn.stop: telemetry + turn-summary effects, then the stop verdict. The
710
- // verdict + codex-replay previously lived in the per-harness shell adapters;
706
+ // verdict + codex-replay previously lived in the per-adapter shell adapters;
711
707
  // agent-hook owns them now. Runs on the normal "stop" event only;
712
708
  // "stop-failure" (API error) gets no gate, matching the previous
713
709
  // stop vs stop-failure split.
@@ -716,7 +712,7 @@ async function main() {
716
712
  // the status_checked / task_set / status_box_present evidence (codex
717
713
  // doesn't emit those live; this re-emits turn.stop after agent-hook's own,
718
714
  // so the verdict reads the replay's box signal as the latest).
719
- if (harness === "codex" && payload?.transcript_path && existsSync(payload.transcript_path)) {
715
+ if (adapter === "codex" && payload?.transcript_path && existsSync(payload.transcript_path)) {
720
716
  try {
721
717
  replayCodexJsonl({
722
718
  coordRoot,
@@ -732,14 +728,14 @@ async function main() {
732
728
  }
733
729
  // CC effects: rate-limited session-telemetry sync + turn-summary Haiku
734
730
  // auto-summary.
735
- if (harness === "claude-code") {
731
+ if (adapter === "claude-code") {
736
732
  runSessionSyncExtension(coordRoot, false);
737
733
  runTurnSummary(coordRoot, owner.instance_id, sessionId, payload?.transcript_path);
738
734
  }
739
735
  // Master-state heartbeat projection. Drains events.ndjson since the last
740
736
  // cursor → per-owner heartbeats. Was a SECOND binary (`agent-coord project`)
741
737
  // pinned to Claude Code Stop only; folded in here so it (a) is one
742
- // entry per event like everything else and (b) fires on EVERY harness's stop,
738
+ // entry per event like everything else and (b) fires on EVERY adapter's stop,
743
739
  // not just CC. Runs unconditionally before the verdict's possible exit-2 return
744
740
  // (the events are real regardless of whether the agent gets nagged), and after
745
741
  // codex-replay above so codex's replayed events are included in the drain.
@@ -771,21 +767,21 @@ async function main() {
771
767
  rule: "stop-hook",
772
768
  instance_id: owner.instance_id,
773
769
  session_id: sessionId,
774
- harness,
770
+ adapter,
775
771
  bypass: coordEnv("AGENT_COORD_BYPASS_STOP") === "1",
776
772
  workflow_child: coordEnv("WORKFLOW_CHILD") === "1",
777
773
  });
778
774
  if (!verdict.allow) {
779
- // Harness-aware enforcement channel: Claude Code / Codex honor exit-2 +
775
+ // Adapter-aware enforcement channel: Claude Code / Codex honor exit-2 +
780
776
  // stderr as a turn block; Cursor ignores exit codes (fail-open) and
781
777
  // re-prompts only via a `followup_message` it auto-submits. emitStopBlock
782
778
  // writes the right shape and returns the exit code to use.
783
- const { emitStopBlock } = await import("./harness/output.js");
784
- return emitStopBlock(harness, verdict);
779
+ const { emitStopBlock } = await import("./adapter/output.js");
780
+ return emitStopBlock(adapter, verdict);
785
781
  }
786
782
  }
787
783
  // Phase 7: PreToolUse: heartbeat + pid-map self-heal on every tool call.
788
- // Harness-agnostic: both writes have the same shape regardless of who fired.
784
+ // Adapter-agnostic: both writes have the same shape regardless of who fired.
789
785
  // Cursor/Codex bash dispatchers still fire their own G-guard logic, but the
790
786
  // heals here keep the agent-coord layer's view of liveness fresh.
791
787
  //
@@ -795,8 +791,8 @@ async function main() {
795
791
  // call was restored here afterward.
796
792
  if (norm.event_type === "tool.pre_use") {
797
793
  try {
798
- healHeartbeatViaCli(coordRoot, owner.instance_id, sessionId, harness);
799
- refreshPidmap(coordRoot, owner.instance_id, harness, payload?.pid);
794
+ healHeartbeatViaCli(coordRoot, owner.instance_id, sessionId, adapter);
795
+ refreshPidmap(coordRoot, owner.instance_id, adapter, payload?.pid);
800
796
  }
801
797
  catch (err) {
802
798
  logError(coordRoot, err, { phase: "pre-tool-use-heal" });
@@ -810,49 +806,49 @@ async function main() {
810
806
  payload,
811
807
  instanceId: owner.instance_id,
812
808
  sessionId,
813
- harness,
809
+ adapter,
814
810
  });
815
811
  }
816
812
  catch (err) {
817
813
  logError(coordRoot, err, { phase: "pre-tool-use-image-capture" });
818
814
  }
819
- // G-guard for ALL harnesses. Claude Code previously ran this via a
815
+ // G-guard for ALL adapters. Claude Code previously ran this via a
820
816
  // pre-tool-use bash adapter (which called `agent-coord verdict --rule=claim`);
821
- // that adapter is now deleted, so agent-hook owns the deny for every harness.
822
- // emitDeny() inside emits the harness-shaped permission JSON (claude-code +
817
+ // that adapter is now deleted, so agent-hook owns the deny for every adapter.
818
+ // emitDeny() inside emits the adapter-shaped permission JSON (claude-code +
823
819
  // codex use hookSpecificOutput.permissionDecision; cursor uses .permission).
824
820
  // apply_patch (codex) parses paths from the patch body and runs verdict
825
821
  // per-path; Edit/Write/NotebookEdit resolve a single target. Non-write tools
826
822
  // (incl. Agent) yield no targets and pass through with no deny.
827
823
  try {
828
- await runPreToolUseGuard(coordRoot, owner.instance_id, sessionId, data, harness);
824
+ await runPreToolUseGuard(coordRoot, owner.instance_id, sessionId, data, adapter);
829
825
  }
830
826
  catch (err) {
831
827
  logError(coordRoot, err, { phase: "pre-tool-use-guard" });
832
828
  }
833
829
  // Shell-mutation warn (warn-only, never blocks). Was the cursor
834
830
  // beforeShellExecution + codex preToolUse-Bash shell-mutation-claim-log in
835
- // the per-harness shell adapters. Cursor sends the command at payload.command;
831
+ // the per-adapter shell adapters. Cursor sends the command at payload.command;
836
832
  // codex Bash at tool_input.command. Emits a decision.warn per candidate-mutated
837
833
  // path so a peer sees the write in events.ndjson. (CC never did this,
838
834
  // preserved; it emits with its own hooks-side emitter per the
839
835
  // independent-emitter rule.)
840
836
  const shellCmd = eventName === "before-shell-execution"
841
837
  ? (payload?.raw.command ?? "")
842
- : harness === "codex" && data.tool_name === "Bash"
838
+ : adapter === "codex" && data.tool_name === "Bash"
843
839
  ? (payload?.raw.tool_input?.command ?? "")
844
840
  : "";
845
841
  if (shellCmd) {
846
842
  try {
847
843
  const paths = shellMutationPaths(shellCmd, coordRoot);
848
844
  const truncated = shellCmd.length > 80 ? shellCmd.slice(0, 80) : shellCmd;
849
- const platform = harnessPlatform(harness);
845
+ const platform = adapterPlatform(adapter);
850
846
  for (const p of paths) {
851
847
  emit(coordRoot, {
852
848
  event_type: "decision.warn",
853
849
  instance_id: owner.instance_id,
854
850
  session_id: sessionId,
855
- harness,
851
+ adapter,
856
852
  data: {
857
853
  rule: "shell_mutation_candidate",
858
854
  reason: `path=${p} cmd=${truncated} platform=${platform}`,
@@ -867,7 +863,7 @@ async function main() {
867
863
  }
868
864
  }
869
865
  // Phase 7: PostToolUse: stamp last_tool + last_tool_target on heartbeat.
870
- // Harness-agnostic for the same reason as tool.pre_use above.
866
+ // Adapter-agnostic for the same reason as tool.pre_use above.
871
867
  if (norm.event_type === "tool.post_use") {
872
868
  try {
873
869
  stampToolActivity(coordRoot, owner.instance_id, data);
@@ -885,7 +881,7 @@ async function main() {
885
881
  payload,
886
882
  instanceId: owner.instance_id,
887
883
  sessionId,
888
- harness,
884
+ adapter,
889
885
  });
890
886
  }
891
887
  catch (err) {
@@ -893,7 +889,7 @@ async function main() {
893
889
  }
894
890
  }
895
891
  // Phase 7: PostToolUseFailure: release claim on failed Edit (the file
896
- // never landed; the claim is stale). Harness-agnostic.
892
+ // never landed; the claim is stale). Adapter-agnostic.
897
893
  if (norm.event_type === "tool.post_use_failure") {
898
894
  try {
899
895
  releaseClaimOnFailure(coordRoot, owner.instance_id, data, payload?.raw);
@@ -904,7 +900,7 @@ async function main() {
904
900
  }
905
901
  return 0;
906
902
  }
907
- async function runPreToolUseGuard(coordRoot, instanceId, sessionId, data, harness) {
903
+ async function runPreToolUseGuard(coordRoot, instanceId, sessionId, data, adapter) {
908
904
  const toolName = data.tool_name ?? "";
909
905
  const targets = collectGuardTargets(toolName, data)
910
906
  .map((p) => canonicalize(coordRoot, p))
@@ -949,8 +945,8 @@ async function runPreToolUseGuard(coordRoot, instanceId, sessionId, data, harnes
949
945
  reason += ` The patch also touched: ${siblings}: pick a different file or wait.`;
950
946
  }
951
947
  }
952
- const { emitDeny } = await import("./harness/output.js");
953
- emitDeny(harness, reason);
948
+ const { emitDeny } = await import("./adapter/output.js");
949
+ emitDeny(adapter, reason);
954
950
  return;
955
951
  }
956
952
  }
@@ -1011,45 +1007,60 @@ function parseApplyPatchPaths(data) {
1011
1007
  }
1012
1008
  return out;
1013
1009
  }
1014
- function healHeartbeatViaCli(coordRoot, instanceId, sessionId, harness) {
1010
+ function healHeartbeatViaCli(coordRoot, instanceId, sessionId, adapter) {
1015
1011
  const agentCoordBin = join(coordRoot, "harnery", "bin", "agent-coord");
1016
1012
  if (!existsSync(agentCoordBin))
1017
1013
  return;
1018
- // Pass the detected harness so a pruned Cursor/Codex heartbeat is recreated
1014
+ // Pass the detected adapter so a pruned Cursor/Codex heartbeat is recreated
1019
1015
  // with the correct platform; without it, healHeartbeat defaults to
1020
1016
  // claude_code and the dashboard mislabels the agent. See
1021
1017
  // heartbeat-writer.healHeartbeat.
1022
- spawnSync(agentCoordBin, ["heal-heartbeat", instanceId, sessionId, `--harness=${harness}`], {
1018
+ spawnSync(agentCoordBin, ["heal-heartbeat", instanceId, sessionId, `--adapter=${adapter}`], {
1023
1019
  encoding: "utf8",
1024
1020
  timeout: 2000,
1025
1021
  env: childEnv(coordRoot),
1026
1022
  });
1027
1023
  }
1028
1024
  /**
1029
- * Walk up the ppid chain on Linux/WSL looking for the harness anchor PID,
1025
+ * Walk up the ppid chain on Linux/WSL looking for the adapter anchor PID,
1030
1026
  * the PID of the claude / cursor / codex binary. Finds the agent PID. Used by
1031
- * `tool.pre_use`'s pid-map self-heal so a re-parented harness binary (the
1027
+ * `tool.pre_use`'s pid-map self-heal so a re-parented adapter binary (the
1032
1028
  * VS Code 2.1.x sibling-claude spawn case) gets its pid-map row rewritten on
1033
1029
  * the next tool call rather than going invisible until SessionStart fires
1034
1030
  * again, which it may never do.
1035
1031
  *
1036
1032
  * Returns undefined only when no anchor is found; callers fall back to
1037
- * `process.ppid` (the bash wrapper's parent, which is usually the harness binary
1033
+ * `process.ppid` (the bash wrapper's parent, which is usually the adapter binary
1038
1034
  * itself). `HARNERY_AGENT_COORD_TEST_ANCHOR_PID` overrides everything so the
1039
1035
  * test sandbox can pin a deterministic PID.
1040
1036
  */
1041
- function findHarnessAnchorPid(harness) {
1037
+ function findAdapterAnchorPid(adapter) {
1042
1038
  const override = coordEnv("AGENT_COORD_TEST_ANCHOR_PID");
1043
1039
  if (override) {
1044
1040
  const n = Number(override);
1045
1041
  if (Number.isFinite(n) && n > 0)
1046
1042
  return n;
1047
1043
  }
1044
+ // A adapter that states its own pid ends the search. Nothing inferred from the
1045
+ // process tree beats the adapter naming itself, and the inference is the part
1046
+ // that has been failing: comm matching wants a binary called after its
1047
+ // adapter, and one Claude Code build ships its CLI under a version-numbered
1048
+ // filename, so the walk found nothing and the caller fell back to the hook's
1049
+ // own shell. That row was dead within seconds, leaving every session in this
1050
+ // environment unattributed.
1051
+ const fromEnv = adapterPidFromEnv();
1052
+ if (fromEnv)
1053
+ return fromEnv;
1048
1054
  // Build the ppid chain (nearest → root, up to 20 hops), then hand it to the
1049
1055
  // pure selector. Linux/WSL reads /proc; macOS/BSD (no /proc) falls back to
1050
1056
  // `ps -o ppid=,comm=` parsed by the unit-tested `parsePsChainLine`. Splitting
1051
- // the walk (untestable off a live box) from the comm-matching keeps the
1052
- // cursor `node`-fallback logic verifiable.
1057
+ // the walk (untestable off a live box) from the matching keeps the selector
1058
+ // logic verifiable.
1059
+ //
1060
+ // Only the /proc branch carries an executable path for the selector's
1061
+ // path-based pass. Asking `ps` for one means either a second spawn per hop or
1062
+ // splitting `comm` from `args` on a line where comm may itself contain spaces,
1063
+ // and the adapter that needs the path pass states its pid in the env anyway.
1053
1064
  const chain = [];
1054
1065
  let pid = process.pid;
1055
1066
  for (let hops = 0; hops < 20; hops++) {
@@ -1058,7 +1069,15 @@ function findHarnessAnchorPid(harness) {
1058
1069
  const comm = readFileSync(`/proc/${pid}/comm`, "utf8").trim();
1059
1070
  const status = readFileSync(`/proc/${pid}/status`, "utf8");
1060
1071
  const m = status.match(/^PPid:\s+(\d+)/m);
1061
- hop = { comm, ppid: m ? Number(m[1]) : 0 };
1072
+ // argv[0], for the path-based second pass. cmdline is NUL-separated.
1073
+ let exe;
1074
+ try {
1075
+ exe = readFileSync(`/proc/${pid}/cmdline`, "utf8").split("\0")[0] || undefined;
1076
+ }
1077
+ catch {
1078
+ /* exe is optional */
1079
+ }
1080
+ hop = { comm, ppid: m ? Number(m[1]) : 0, exe };
1062
1081
  }
1063
1082
  catch {
1064
1083
  // no /proc (macOS/BSD) — fall through to ps
@@ -1070,12 +1089,12 @@ function findHarnessAnchorPid(harness) {
1070
1089
  }
1071
1090
  if (!hop)
1072
1091
  break;
1073
- chain.push({ pid, comm: hop.comm });
1092
+ chain.push({ pid, comm: hop.comm, exe: hop.exe });
1074
1093
  if (!Number.isFinite(hop.ppid) || hop.ppid === 0 || hop.ppid === 1)
1075
1094
  break;
1076
1095
  pid = hop.ppid;
1077
1096
  }
1078
- return selectAnchorPid(chain, harness);
1097
+ return selectAnchorPid(chain, adapter);
1079
1098
  }
1080
1099
  /**
1081
1100
  * Pid-map self-heal for `tool.pre_use`. Symmetric counterpart to
@@ -1084,7 +1103,7 @@ function findHarnessAnchorPid(harness) {
1084
1103
  *
1085
1104
  * The pid argument prefers the payload's `pid` (CC populates it on
1086
1105
  * SessionStart and may also send it on PreToolUse), then
1087
- * `findHarnessAnchorPid`, then `process.ppid`. Writes go through the same
1106
+ * `findAdapterAnchorPid`, then `process.ppid`. Writes go through the same
1088
1107
  * idempotent `writePidmapViaAgentCoord` helper that SessionStart uses: no
1089
1108
  * disk I/O on no-op heals (when the row already points at us).
1090
1109
  *
@@ -1092,11 +1111,11 @@ function findHarnessAnchorPid(harness) {
1092
1111
  * `harn agents heal-events` pidmap counts meaningful. The inline helper does
1093
1112
  * not yet.
1094
1113
  */
1095
- function refreshPidmap(coordRoot, instanceId, harness, payloadPid) {
1096
- const pid = payloadPid ?? findHarnessAnchorPid(harness) ?? process.ppid;
1114
+ function refreshPidmap(coordRoot, instanceId, adapter, payloadPid) {
1115
+ const pid = payloadPid ?? findAdapterAnchorPid(adapter) ?? process.ppid;
1097
1116
  if (!Number.isFinite(pid) || pid <= 0)
1098
1117
  return;
1099
- writePidmapViaAgentCoord(coordRoot, pid, instanceId, harnessPlatform(harness));
1118
+ writePidmapViaAgentCoord(coordRoot, pid, instanceId, adapterPlatform(adapter));
1100
1119
  }
1101
1120
  function stampToolActivity(coordRoot, instanceId, data) {
1102
1121
  const agentCoordBin = join(coordRoot, "harnery", "bin", "agent-coord");
@@ -1218,7 +1237,7 @@ function cleanupSessionEnd(coordRoot, instanceId, reason) {
1218
1237
  spawnSync(agentCoordBin, ["log", `SESSION_END reason=${reason}`, "--instance", instanceId], { encoding: "utf8", timeout: 2000 });
1219
1238
  }
1220
1239
  }
1221
- async function emitUserPromptSubmitSystemMessage(coordRoot, instanceId, sessionId, harness, recoveryBriefing = "") {
1240
+ async function emitUserPromptSubmitSystemMessage(coordRoot, instanceId, sessionId, adapter, recoveryBriefing = "") {
1222
1241
  const agentCoordBin = join(coordRoot, "harnery", "bin", "agent-coord");
1223
1242
  let additionalContext = "";
1224
1243
  if (existsSync(agentCoordBin)) {
@@ -1238,11 +1257,16 @@ async function emitUserPromptSubmitSystemMessage(coordRoot, instanceId, sessionI
1238
1257
  const args = ["prompt-context", "--instance", instanceId, "--session", sessionId];
1239
1258
  if (agentName)
1240
1259
  args.push("--name", agentName);
1241
- // Cursor + Codex sessions get the set-task staleness nudge. CC enforces it
1242
- // via the Stop-hook transcript scan; the nudge replaces that for harnesses
1243
- // that don't reliably expose a transcript_path during stop.
1244
- if (harness === "cursor" || harness === "codex")
1260
+ // Every human-facing adapter gets the first-session naming reminder from
1261
+ // the shared hook path. Cursor + Codex additionally get ongoing set-task
1262
+ // staleness nudges; Claude Code enforces those via its Stop transcript.
1263
+ // Codex gets a fresh status-footer reminder on every prompt. Its Stop hook
1264
+ // stays observe-only, so missing the footer never replaces the answer.
1265
+ args.push("--session-name-nudge");
1266
+ if (adapter === "cursor" || adapter === "codex")
1245
1267
  args.push("--task-nudge");
1268
+ if (adapter === "codex")
1269
+ args.push("--status-footer-nudge");
1246
1270
  const result = spawnSync(agentCoordBin, args, { encoding: "utf8", timeout: 3000 });
1247
1271
  if (result.status === 0 && result.stdout)
1248
1272
  additionalContext = result.stdout.trim();
@@ -1252,18 +1276,18 @@ async function emitUserPromptSubmitSystemMessage(coordRoot, instanceId, sessionI
1252
1276
  }
1253
1277
  if (!additionalContext)
1254
1278
  return false;
1255
- const { emitContext } = await import("./harness/output.js");
1256
- emitContext(harness, "UserPromptSubmit", additionalContext);
1279
+ const { emitContext } = await import("./adapter/output.js");
1280
+ emitContext(adapter, "UserPromptSubmit", additionalContext);
1257
1281
  return true;
1258
1282
  }
1259
- function emitSubagentStartContext(coordRoot, instanceId, sessionId, data, harness) {
1283
+ function emitSubagentStartContext(coordRoot, instanceId, sessionId, data, adapter) {
1260
1284
  // Look up the subagent's assigned name (just-written by agent-coord assignName
1261
1285
  // in session.start data) + the parent's short id for the "you are a subagent
1262
1286
  // of X" framing.
1263
1287
  const subagentName = data.name ?? "";
1264
1288
  if (!subagentName)
1265
1289
  return;
1266
- const platformLabel = harnessPlatform(harness);
1290
+ const platformLabel = adapterPlatform(adapter);
1267
1291
  const parentShort = sessionId && sessionId !== instanceId ? `agent-${sessionId.slice(0, 8)}` : "the parent session";
1268
1292
  const message = `You are agent-${subagentName} (${platformLabel} subagent). You're a subagent of ${parentShort}.`;
1269
1293
  // Render peer table inline since the subagent might want to know who else
@@ -1279,16 +1303,16 @@ function emitSubagentStartContext(coordRoot, instanceId, sessionId, data, harnes
1279
1303
  }
1280
1304
  // Use SubagentStart event-name in CC's hookSpecificOutput shape; cursor's
1281
1305
  // flat `additional_context` works the same way.
1282
- void import("./harness/output.js").then(({ emitContext }) => {
1283
- emitContext(harness, "SubagentStart", combined);
1306
+ void import("./adapter/output.js").then(({ emitContext }) => {
1307
+ emitContext(adapter, "SubagentStart", combined);
1284
1308
  });
1285
1309
  }
1286
- function harnessPlatform(harness) {
1287
- if (harness === "claude-code")
1310
+ function adapterPlatform(adapter) {
1311
+ if (adapter === "claude-code")
1288
1312
  return "claude_code";
1289
- return harness;
1313
+ return adapter;
1290
1314
  }
1291
- async function emitSessionStartSystemMessage(coordRoot, instanceId, sessionId, emittedData, harness, recoveryBriefing = "") {
1315
+ async function emitSessionStartSystemMessage(coordRoot, instanceId, sessionId, emittedData, adapter, recoveryBriefing = "") {
1292
1316
  const agentCoordBin = join(coordRoot, "harnery", "bin", "agent-coord");
1293
1317
  let additionalContext = "";
1294
1318
  if (existsSync(agentCoordBin)) {
@@ -1297,10 +1321,10 @@ async function emitSessionStartSystemMessage(coordRoot, instanceId, sessionId, e
1297
1321
  spawnSync(agentCoordBin, ["project"], { encoding: "utf8", timeout: 3000 });
1298
1322
  // Stale-sweep dead peers before rendering peer table.
1299
1323
  spawnSync(agentCoordBin, ["stale-sweep"], { encoding: "utf8", timeout: 3000 });
1300
- // SESSION_START activity log line, fired across all harnesses.
1324
+ // SESSION_START activity log line, fired across all adapters.
1301
1325
  const model = emittedData.model ?? "unknown";
1302
1326
  const source = emittedData.source ?? "startup";
1303
- const platform = harnessPlatform(harness);
1327
+ const platform = adapterPlatform(adapter);
1304
1328
  spawnSync(agentCoordBin, [
1305
1329
  "log",
1306
1330
  `SESSION_START model=${model} source=${source} platform=${platform}`,
@@ -1315,19 +1339,19 @@ async function emitSessionStartSystemMessage(coordRoot, instanceId, sessionId, e
1315
1339
  // The "You are agent-X." prefix in session-context renders unqualified by
1316
1340
  // default (claude-code-style). For cursor/codex the bash dispatchers add
1317
1341
  // a "(Cursor)" / "(Codex)" suffix; pass it through as --platform-label.
1318
- if (harness !== "claude-code") {
1342
+ if (adapter !== "claude-code") {
1319
1343
  args.push("--platform-label", platform === "cursor" ? "Cursor" : "Codex");
1320
1344
  }
1321
1345
  const result = spawnSync(agentCoordBin, args, { encoding: "utf8", timeout: 3000 });
1322
1346
  if (result.status === 0 && result.stdout)
1323
1347
  additionalContext = result.stdout.trim();
1324
1348
  }
1325
- // Effect (claude-code): merge the scratch recovery cue into the session-start
1349
+ // Effect (claude-code): merge the journal recovery cue into the session-start
1326
1350
  // context. Was a standalone additionalContext emission from the previous
1327
- // scratch-on-start adapter; now that agent-hook is the single SessionStart
1351
+ // journal-on-start adapter; now that agent-hook is the single SessionStart
1328
1352
  // entry, it folds in here.
1329
- if (harness === "claude-code") {
1330
- const cue = scratchRecoveryCue(coordRoot);
1353
+ if (adapter === "claude-code") {
1354
+ const cue = journalRecoveryCue(coordRoot);
1331
1355
  if (cue)
1332
1356
  additionalContext = [additionalContext, cue].filter(Boolean).join("\n\n");
1333
1357
  }
@@ -1336,17 +1360,17 @@ async function emitSessionStartSystemMessage(coordRoot, instanceId, sessionId, e
1336
1360
  }
1337
1361
  if (!additionalContext)
1338
1362
  return false;
1339
- const { emitContext } = await import("./harness/output.js");
1340
- emitContext(harness, "SessionStart", additionalContext);
1363
+ const { emitContext } = await import("./adapter/output.js");
1364
+ emitContext(adapter, "SessionStart", additionalContext);
1341
1365
  return true;
1342
1366
  }
1343
- function completeRecoveryInjection(coordRoot, instanceId, sessionId, harness, recovery, injectionEvent) {
1367
+ function completeRecoveryInjection(coordRoot, instanceId, sessionId, adapter, recovery, injectionEvent) {
1344
1368
  completeContextRecovery(coordRoot, { sessionId, instanceId });
1345
1369
  emit(coordRoot, {
1346
1370
  event_type: "context.recovery.injected",
1347
1371
  instance_id: instanceId,
1348
1372
  session_id: sessionId,
1349
- harness,
1373
+ adapter,
1350
1374
  data: {
1351
1375
  capsule_id: recovery.capsule.capsule_id,
1352
1376
  generation: recovery.capsule.generation,