harnery 0.35.0 → 0.36.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 (616) hide show
  1. package/dist/commander.d.ts +30 -5
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +124 -96
  4. package/dist/commands/agents.d.ts +23 -3
  5. package/dist/commands/agents.d.ts.map +1 -1
  6. package/dist/commands/agents.js +379 -198
  7. package/dist/commands/backup.d.ts.map +1 -1
  8. package/dist/commands/backup.js +10 -10
  9. package/dist/commands/browse-session.d.ts.map +1 -1
  10. package/dist/commands/browse-session.js +12 -0
  11. package/dist/commands/browse.d.ts +1 -1
  12. package/dist/commands/browse.d.ts.map +1 -1
  13. package/dist/commands/browse.js +5 -4
  14. package/dist/commands/conversations.d.ts +10 -0
  15. package/dist/commands/conversations.d.ts.map +1 -0
  16. package/dist/commands/conversations.js +201 -0
  17. package/dist/commands/deinit.d.ts.map +1 -1
  18. package/dist/commands/deinit.js +5 -0
  19. package/dist/commands/docs.d.ts.map +1 -1
  20. package/dist/commands/docs.js +13 -2
  21. package/dist/commands/doctor.d.ts +5 -0
  22. package/dist/commands/doctor.d.ts.map +1 -1
  23. package/dist/commands/doctor.js +51 -7
  24. package/dist/commands/fetch.js +6 -5
  25. package/dist/commands/files.d.ts +22 -0
  26. package/dist/commands/files.d.ts.map +1 -0
  27. package/dist/commands/files.js +113 -0
  28. package/dist/commands/governor.js +14 -12
  29. package/dist/commands/inbox.d.ts +5 -0
  30. package/dist/commands/inbox.d.ts.map +1 -0
  31. package/dist/commands/inbox.js +57 -0
  32. package/dist/commands/init.d.ts +4 -5
  33. package/dist/commands/init.d.ts.map +1 -1
  34. package/dist/commands/init.js +63 -13
  35. package/dist/commands/ledger-v3.d.ts.map +1 -1
  36. package/dist/commands/ledger-v3.js +347 -1
  37. package/dist/commands/logs.d.ts +4 -0
  38. package/dist/commands/logs.d.ts.map +1 -0
  39. package/dist/commands/logs.js +169 -0
  40. package/dist/commands/messages.d.ts +5 -0
  41. package/dist/commands/messages.d.ts.map +1 -0
  42. package/dist/commands/messages.js +45 -0
  43. package/dist/commands/outline.d.ts +1 -1
  44. package/dist/commands/outline.d.ts.map +1 -1
  45. package/dist/commands/outline.js +2 -2
  46. package/dist/commands/read.d.ts +1 -1
  47. package/dist/commands/read.d.ts.map +1 -1
  48. package/dist/commands/read.js +2 -2
  49. package/dist/commands/semantic.d.ts.map +1 -1
  50. package/dist/commands/semantic.js +54 -2
  51. package/dist/commands/storage.d.ts +4 -0
  52. package/dist/commands/storage.d.ts.map +1 -0
  53. package/dist/commands/storage.js +238 -0
  54. package/dist/commands/tunnel.d.ts +5 -1
  55. package/dist/commands/tunnel.d.ts.map +1 -1
  56. package/dist/commands/tunnel.js +44 -31
  57. package/dist/commands/web.d.ts +3 -0
  58. package/dist/commands/web.d.ts.map +1 -1
  59. package/dist/commands/web.js +67 -7
  60. package/dist/commands/work.js +3 -3
  61. package/dist/commands/workflow.js +13 -13
  62. package/dist/core/adapters/profiles.d.ts +1 -1
  63. package/dist/core/agents/cli.js +209 -39
  64. package/dist/core/agents/live-authority-v3.d.ts +47 -1
  65. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  66. package/dist/core/agents/live-authority-v3.js +244 -10
  67. package/dist/core/agents/live-lifecycle-v3.js +6 -1
  68. package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
  69. package/dist/core/agents/live-observation-v3.js +6 -1
  70. package/dist/core/agents/render/prompt-context.d.ts +9 -3
  71. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  72. package/dist/core/agents/render/prompt-context.js +24 -7
  73. package/dist/core/agents/rules/stop-hook.d.ts +2 -0
  74. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  75. package/dist/core/agents/rules/stop-hook.js +94 -13
  76. package/dist/core/agents/rules/verdict.d.ts +1 -0
  77. package/dist/core/agents/rules/verdict.d.ts.map +1 -1
  78. package/dist/core/agents/session-events.d.ts.map +1 -1
  79. package/dist/core/agents/session-events.js +4 -0
  80. package/dist/core/agents/session-finalization-state-v3.js +1 -1
  81. package/dist/core/agents/session-finalizer-v3.js +5 -1
  82. package/dist/core/agents/state/activity-log.d.ts +3 -0
  83. package/dist/core/agents/state/activity-log.d.ts.map +1 -1
  84. package/dist/core/agents/state/activity-log.js +6 -3
  85. package/dist/core/agents/state/heartbeat-writer.d.ts +6 -0
  86. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  87. package/dist/core/agents/state/heartbeat-writer.js +18 -0
  88. package/dist/core/agents/state/live-coordination-view.d.ts +5 -7
  89. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  90. package/dist/core/agents/state/live-coordination-view.js +15 -90
  91. package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
  92. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
  93. package/dist/core/agents/state/live-coordination-writer.js +92 -0
  94. package/dist/core/artifacts/index.d.ts +21 -0
  95. package/dist/core/artifacts/index.d.ts.map +1 -1
  96. package/dist/core/artifacts/index.js +46 -1
  97. package/dist/core/config.d.ts +62 -4
  98. package/dist/core/config.d.ts.map +1 -1
  99. package/dist/core/config.js +98 -4
  100. package/dist/core/conversations/archive.d.ts +49 -0
  101. package/dist/core/conversations/archive.d.ts.map +1 -0
  102. package/dist/core/conversations/archive.js +136 -0
  103. package/dist/core/conversations/catalog.d.ts +10 -0
  104. package/dist/core/conversations/catalog.d.ts.map +1 -0
  105. package/dist/core/conversations/catalog.js +72 -0
  106. package/dist/core/conversations/context-pack.d.ts +6 -0
  107. package/dist/core/conversations/context-pack.d.ts.map +1 -0
  108. package/dist/core/conversations/context-pack.js +60 -0
  109. package/dist/core/conversations/contract.d.ts +155 -0
  110. package/dist/core/conversations/contract.d.ts.map +1 -0
  111. package/dist/core/conversations/contract.js +1 -0
  112. package/dist/core/conversations/evaluation.d.ts +16 -0
  113. package/dist/core/conversations/evaluation.d.ts.map +1 -0
  114. package/dist/core/conversations/evaluation.js +9 -0
  115. package/dist/core/conversations/index.d.ts +10 -0
  116. package/dist/core/conversations/index.d.ts.map +1 -0
  117. package/dist/core/conversations/index.js +9 -0
  118. package/dist/core/conversations/lifecycle.d.ts +28 -0
  119. package/dist/core/conversations/lifecycle.d.ts.map +1 -0
  120. package/dist/core/conversations/lifecycle.js +29 -0
  121. package/dist/core/conversations/normalize.d.ts +14 -0
  122. package/dist/core/conversations/normalize.d.ts.map +1 -0
  123. package/dist/core/conversations/normalize.js +82 -0
  124. package/dist/core/conversations/query.d.ts +8 -0
  125. package/dist/core/conversations/query.d.ts.map +1 -0
  126. package/dist/core/conversations/query.js +280 -0
  127. package/dist/core/conversations/search-index.d.ts +9 -0
  128. package/dist/core/conversations/search-index.d.ts.map +1 -0
  129. package/dist/core/conversations/search-index.js +29 -0
  130. package/dist/core/events/legacy-storage/canary.d.ts +18 -0
  131. package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
  132. package/dist/core/events/legacy-storage/canary.js +150 -0
  133. package/dist/core/events/legacy-storage/fence.d.ts +15 -0
  134. package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
  135. package/dist/core/events/legacy-storage/fence.js +115 -0
  136. package/dist/core/events/legacy-storage/index.d.ts +6 -0
  137. package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
  138. package/dist/core/events/legacy-storage/index.js +5 -0
  139. package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
  140. package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
  141. package/dist/core/events/legacy-storage/inventory.js +40 -0
  142. package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
  143. package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
  144. package/dist/core/events/legacy-storage/manifest.js +108 -0
  145. package/dist/core/events/legacy-storage/reader.d.ts +15 -0
  146. package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
  147. package/dist/core/events/legacy-storage/reader.js +154 -0
  148. package/dist/core/events/v3/authority-outbox.d.ts +7 -2
  149. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  150. package/dist/core/events/v3/authority-outbox.js +16 -3
  151. package/dist/core/events/v3/base-contract.d.ts +81 -41
  152. package/dist/core/events/v3/base-contract.d.ts.map +1 -1
  153. package/dist/core/events/v3/base-contract.js +17 -7
  154. package/dist/core/events/v3/bootstrap.d.ts +39 -0
  155. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  156. package/dist/core/events/v3/bootstrap.js +167 -3
  157. package/dist/core/events/v3/capabilities.js +3 -3
  158. package/dist/core/events/v3/control-witness.d.ts +44 -0
  159. package/dist/core/events/v3/control-witness.d.ts.map +1 -0
  160. package/dist/core/events/v3/control-witness.js +233 -0
  161. package/dist/core/events/v3/control-writer.d.ts +4 -0
  162. package/dist/core/events/v3/control-writer.d.ts.map +1 -0
  163. package/dist/core/events/v3/control-writer.js +16 -0
  164. package/dist/core/events/v3/control.d.ts +8 -2
  165. package/dist/core/events/v3/control.d.ts.map +1 -1
  166. package/dist/core/events/v3/control.js +46 -18
  167. package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
  168. package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
  169. package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
  170. package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
  171. package/dist/core/events/v3/coordination-view.js +16 -1
  172. package/dist/core/events/v3/generated.d.ts +1 -1
  173. package/dist/core/events/v3/generated.js +1 -1
  174. package/dist/core/events/v3/index.d.ts +4 -2
  175. package/dist/core/events/v3/index.d.ts.map +1 -1
  176. package/dist/core/events/v3/index.js +3 -1
  177. package/dist/core/events/v3/live-route-observer.d.ts +31 -0
  178. package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
  179. package/dist/core/events/v3/live-route-observer.js +58 -0
  180. package/dist/core/events/v3/live-routing.d.ts +13 -21
  181. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  182. package/dist/core/events/v3/live-routing.js +45 -41
  183. package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
  184. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  185. package/dist/core/events/v3/producers/coordination-recorder.js +76 -10
  186. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
  187. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
  188. package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
  189. package/dist/core/events/v3/producers/hook-base.js +1 -1
  190. package/dist/core/events/v3/producers/intake.d.ts +7 -0
  191. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  192. package/dist/core/events/v3/producers/intake.js +25 -2
  193. package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
  194. package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
  195. package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
  196. package/dist/core/events/v3/producers/recorder.d.ts +55 -1
  197. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  198. package/dist/core/events/v3/producers/recorder.js +353 -24
  199. package/dist/core/events/v3/reader.d.ts +51 -0
  200. package/dist/core/events/v3/reader.d.ts.map +1 -1
  201. package/dist/core/events/v3/reader.js +181 -1
  202. package/dist/core/events/v3/rotation-config.d.ts +9 -0
  203. package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
  204. package/dist/core/events/v3/rotation-config.js +91 -0
  205. package/dist/core/events/v3/runtime-build.d.ts +11 -0
  206. package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
  207. package/dist/core/events/v3/runtime-build.js +39 -0
  208. package/dist/core/events/v3/runtime-identity.d.ts +5 -0
  209. package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
  210. package/dist/core/events/v3/runtime-identity.js +18 -0
  211. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +6 -5
  212. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
  213. package/dist/core/events/v3/runtime-telemetry-capabilities.js +1 -1
  214. package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
  215. package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
  216. package/dist/core/events/v3/support-storage/classify.js +149 -0
  217. package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
  218. package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
  219. package/dist/core/events/v3/support-storage/eligibility.js +35 -0
  220. package/dist/core/events/v3/support-storage/index.d.ts +10 -0
  221. package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
  222. package/dist/core/events/v3/support-storage/index.js +9 -0
  223. package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
  224. package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
  225. package/dist/core/events/v3/support-storage/inventory.js +94 -0
  226. package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
  227. package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
  228. package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
  229. package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
  230. package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
  231. package/dist/core/events/v3/support-storage/maintenance.js +352 -0
  232. package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
  233. package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
  234. package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
  235. package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
  236. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
  237. package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
  238. package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
  239. package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
  240. package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
  241. package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
  242. package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
  243. package/dist/core/events/v3/support-storage/recovery.js +22 -0
  244. package/dist/core/events/v3/turn-telemetry.d.ts +14 -8
  245. package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
  246. package/dist/core/events/v3/turn-telemetry.js +32 -2
  247. package/dist/core/events/v3/writer.d.ts +13 -1
  248. package/dist/core/events/v3/writer.d.ts.map +1 -1
  249. package/dist/core/events/v3/writer.js +126 -12
  250. package/dist/core/governor/plan-read.d.ts.map +1 -1
  251. package/dist/core/governor/plan-read.js +5 -21
  252. package/dist/core/governor/planning.js +6 -8
  253. package/dist/core/governor/service-read.d.ts +12 -0
  254. package/dist/core/governor/service-read.d.ts.map +1 -1
  255. package/dist/core/governor/service-read.js +266 -2
  256. package/dist/core/governor/service.d.ts +1 -0
  257. package/dist/core/governor/service.d.ts.map +1 -1
  258. package/dist/core/governor/service.js +53 -18
  259. package/dist/core/guard/evidence-v3.d.ts.map +1 -1
  260. package/dist/core/guard/evidence-v3.js +2 -0
  261. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  262. package/dist/core/hooks/adapter/events.js +1 -0
  263. package/dist/core/hooks/adapter/output.d.ts +4 -2
  264. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  265. package/dist/core/hooks/adapter/output.js +13 -5
  266. package/dist/core/hooks/adapter/runtime-telemetry.d.ts +27 -4
  267. package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -1
  268. package/dist/core/hooks/adapter/runtime-telemetry.js +307 -6
  269. package/dist/core/hooks/cli.js +212 -30
  270. package/dist/core/hooks/effects/image-capture.d.ts +1 -1
  271. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  272. package/dist/core/hooks/effects/image-capture.js +4 -2
  273. package/dist/core/hooks/remediation-cap.d.ts +8 -3
  274. package/dist/core/hooks/remediation-cap.d.ts.map +1 -1
  275. package/dist/core/hooks/remediation-cap.js +3 -11
  276. package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
  277. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
  278. package/dist/core/hooks/resolve/coord-root.js +92 -11
  279. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  280. package/dist/core/hooks/resolve/owner.js +5 -0
  281. package/dist/core/hooks/resolve/transcript.d.ts +8 -0
  282. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  283. package/dist/core/hooks/resolve/transcript.js +11 -0
  284. package/dist/core/inbox/contract.d.ts +64 -0
  285. package/dist/core/inbox/contract.d.ts.map +1 -0
  286. package/dist/core/inbox/contract.js +13 -0
  287. package/dist/core/inbox/index.d.ts +5 -0
  288. package/dist/core/inbox/index.d.ts.map +1 -0
  289. package/dist/core/inbox/index.js +4 -0
  290. package/dist/core/inbox/lifecycle.d.ts +22 -0
  291. package/dist/core/inbox/lifecycle.d.ts.map +1 -0
  292. package/dist/core/inbox/lifecycle.js +41 -0
  293. package/dist/core/inbox/service.d.ts +36 -0
  294. package/dist/core/inbox/service.d.ts.map +1 -0
  295. package/dist/core/inbox/service.js +210 -0
  296. package/dist/core/inbox/watcher.d.ts +7 -0
  297. package/dist/core/inbox/watcher.d.ts.map +1 -0
  298. package/dist/core/inbox/watcher.js +26 -0
  299. package/dist/core/presence/codec-digest.d.ts.map +1 -1
  300. package/dist/core/presence/codec-digest.js +14 -3
  301. package/dist/core/presence/relay-client.d.ts +1 -0
  302. package/dist/core/presence/relay-client.d.ts.map +1 -1
  303. package/dist/core/presence/relay-client.js +52 -8
  304. package/dist/core/semantic/adapters.d.ts +11 -8
  305. package/dist/core/semantic/adapters.d.ts.map +1 -1
  306. package/dist/core/semantic/adapters.js +169 -31
  307. package/dist/core/semantic/contract.d.ts +532 -48
  308. package/dist/core/semantic/contract.d.ts.map +1 -1
  309. package/dist/core/semantic/contract.js +104 -3
  310. package/dist/core/semantic/index.d.ts +7 -3
  311. package/dist/core/semantic/index.d.ts.map +1 -1
  312. package/dist/core/semantic/index.js +7 -3
  313. package/dist/core/semantic/once.d.ts +6 -1
  314. package/dist/core/semantic/once.d.ts.map +1 -1
  315. package/dist/core/semantic/once.js +80 -9
  316. package/dist/core/semantic/prompt.d.ts.map +1 -1
  317. package/dist/core/semantic/prompt.js +14 -1
  318. package/dist/core/semantic/review.d.ts +144 -0
  319. package/dist/core/semantic/review.d.ts.map +1 -0
  320. package/dist/core/semantic/review.js +544 -0
  321. package/dist/core/semantic/routes.d.ts +10 -0
  322. package/dist/core/semantic/routes.d.ts.map +1 -0
  323. package/dist/core/semantic/routes.js +21 -0
  324. package/dist/core/semantic/scheduler.d.ts +14 -3
  325. package/dist/core/semantic/scheduler.d.ts.map +1 -1
  326. package/dist/core/semantic/scheduler.js +30 -6
  327. package/dist/core/semantic/service-status.d.ts +20 -0
  328. package/dist/core/semantic/service-status.d.ts.map +1 -1
  329. package/dist/core/semantic/service-status.js +60 -4
  330. package/dist/core/semantic/service.d.ts +1 -0
  331. package/dist/core/semantic/service.d.ts.map +1 -1
  332. package/dist/core/semantic/service.js +104 -15
  333. package/dist/core/semantic/soak.d.ts +75 -0
  334. package/dist/core/semantic/soak.d.ts.map +1 -0
  335. package/dist/core/semantic/soak.js +476 -0
  336. package/dist/core/semantic/storage.d.ts +11 -1
  337. package/dist/core/semantic/storage.d.ts.map +1 -1
  338. package/dist/core/semantic/storage.js +4 -3
  339. package/dist/core/semantic/usage.d.ts +43 -0
  340. package/dist/core/semantic/usage.d.ts.map +1 -0
  341. package/dist/core/semantic/usage.js +193 -0
  342. package/dist/core/semantic/validate.d.ts +3 -1
  343. package/dist/core/semantic/validate.d.ts.map +1 -1
  344. package/dist/core/semantic/validate.js +34 -1
  345. package/dist/core/storage/buffer.d.ts +28 -0
  346. package/dist/core/storage/buffer.d.ts.map +1 -0
  347. package/dist/core/storage/buffer.js +101 -0
  348. package/dist/core/storage/builtins.d.ts +3 -0
  349. package/dist/core/storage/builtins.d.ts.map +1 -0
  350. package/dist/core/storage/builtins.js +683 -0
  351. package/dist/core/storage/catalog.d.ts +19 -0
  352. package/dist/core/storage/catalog.d.ts.map +1 -0
  353. package/dist/core/storage/catalog.js +365 -0
  354. package/dist/core/storage/config.d.ts +16 -0
  355. package/dist/core/storage/config.d.ts.map +1 -0
  356. package/dist/core/storage/config.js +311 -0
  357. package/dist/core/storage/contract.d.ts +275 -0
  358. package/dist/core/storage/contract.d.ts.map +1 -0
  359. package/dist/core/storage/contract.js +3 -0
  360. package/dist/core/storage/durable-history.d.ts +36 -0
  361. package/dist/core/storage/durable-history.d.ts.map +1 -0
  362. package/dist/core/storage/durable-history.js +606 -0
  363. package/dist/core/storage/health.d.ts +4 -0
  364. package/dist/core/storage/health.d.ts.map +1 -0
  365. package/dist/core/storage/health.js +65 -0
  366. package/dist/core/storage/index.d.ts +16 -0
  367. package/dist/core/storage/index.d.ts.map +1 -0
  368. package/dist/core/storage/index.js +15 -0
  369. package/dist/core/storage/inventory.d.ts +25 -0
  370. package/dist/core/storage/inventory.d.ts.map +1 -0
  371. package/dist/core/storage/inventory.js +666 -0
  372. package/dist/core/storage/jsonl.d.ts +52 -0
  373. package/dist/core/storage/jsonl.d.ts.map +1 -0
  374. package/dist/core/storage/jsonl.js +156 -0
  375. package/dist/core/storage/log-retention.d.ts +52 -0
  376. package/dist/core/storage/log-retention.d.ts.map +1 -0
  377. package/dist/core/storage/log-retention.js +419 -0
  378. package/dist/core/storage/logger.d.ts +82 -0
  379. package/dist/core/storage/logger.d.ts.map +1 -0
  380. package/dist/core/storage/logger.js +411 -0
  381. package/dist/core/storage/maintenance-providers.d.ts +26 -0
  382. package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
  383. package/dist/core/storage/maintenance-providers.js +141 -0
  384. package/dist/core/storage/maintenance.d.ts +125 -0
  385. package/dist/core/storage/maintenance.d.ts.map +1 -0
  386. package/dist/core/storage/maintenance.js +609 -0
  387. package/dist/core/storage/metrics.d.ts +60 -0
  388. package/dist/core/storage/metrics.d.ts.map +1 -0
  389. package/dist/core/storage/metrics.js +134 -0
  390. package/dist/core/storage/policy.d.ts +7 -0
  391. package/dist/core/storage/policy.d.ts.map +1 -0
  392. package/dist/core/storage/policy.js +110 -0
  393. package/dist/core/storage/process-log.d.ts +38 -0
  394. package/dist/core/storage/process-log.d.ts.map +1 -0
  395. package/dist/core/storage/process-log.js +165 -0
  396. package/dist/core/storage/query.d.ts +34 -0
  397. package/dist/core/storage/query.d.ts.map +1 -0
  398. package/dist/core/storage/query.js +295 -0
  399. package/dist/core/storage/receipts.d.ts +23 -0
  400. package/dist/core/storage/receipts.d.ts.map +1 -0
  401. package/dist/core/storage/receipts.js +117 -0
  402. package/dist/core/storage/segments.d.ts +84 -0
  403. package/dist/core/storage/segments.d.ts.map +1 -0
  404. package/dist/core/storage/segments.js +542 -0
  405. package/dist/core/storage/sink-graph.d.ts +65 -0
  406. package/dist/core/storage/sink-graph.d.ts.map +1 -0
  407. package/dist/core/storage/sink-graph.js +213 -0
  408. package/dist/core/storage/storm-control.d.ts +23 -0
  409. package/dist/core/storage/storm-control.d.ts.map +1 -0
  410. package/dist/core/storage/storm-control.js +59 -0
  411. package/dist/core/work/state.d.ts.map +1 -1
  412. package/dist/core/work/state.js +10 -14
  413. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  414. package/dist/core/workflow/live-session-v3.js +2 -1
  415. package/dist/index.d.ts +2 -0
  416. package/dist/index.d.ts.map +1 -1
  417. package/dist/index.js +2 -0
  418. package/dist/lazy-commands.d.ts +26 -0
  419. package/dist/lazy-commands.d.ts.map +1 -0
  420. package/dist/lazy-commands.js +210 -0
  421. package/dist/lib/docs-lint.d.ts +2 -0
  422. package/dist/lib/docs-lint.d.ts.map +1 -1
  423. package/dist/lib/docs-lint.js +45 -80
  424. package/dist/lib/docs-metadata-audit.d.ts +3 -0
  425. package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
  426. package/dist/lib/docs-metadata-audit.js +13 -23
  427. package/dist/lib/docs-metadata-sync.d.ts +1 -0
  428. package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
  429. package/dist/lib/docs-metadata-sync.js +28 -10
  430. package/dist/lib/docs-repository-view.d.ts +22 -0
  431. package/dist/lib/docs-repository-view.d.ts.map +1 -0
  432. package/dist/lib/docs-repository-view.js +185 -0
  433. package/dist/lib/http/client.d.ts +11 -5
  434. package/dist/lib/http/client.d.ts.map +1 -1
  435. package/dist/lib/http/client.js +22 -4
  436. package/dist/lib/http/index.d.ts +1 -1
  437. package/dist/lib/http/index.d.ts.map +1 -1
  438. package/dist/lib/http/index.js +1 -1
  439. package/dist/lib/indexer-exclusions.d.ts +27 -0
  440. package/dist/lib/indexer-exclusions.d.ts.map +1 -0
  441. package/dist/lib/indexer-exclusions.js +176 -0
  442. package/dist/lib/instructions/templates.d.ts.map +1 -1
  443. package/dist/lib/instructions/templates.js +5 -0
  444. package/dist/lib/local-file-url.d.ts +9 -0
  445. package/dist/lib/local-file-url.d.ts.map +1 -0
  446. package/dist/lib/local-file-url.js +20 -0
  447. package/dist/lib/web-performance.d.ts +118 -0
  448. package/dist/lib/web-performance.d.ts.map +1 -0
  449. package/dist/lib/web-performance.js +192 -0
  450. package/package.json +29 -2
  451. package/schemas/config.schema.json +58 -0
  452. package/schemas/event-v3.schema.json +324 -112
  453. package/src/commander.ts +462 -95
  454. package/src/commands/agents.ts +517 -190
  455. package/src/commands/backup.ts +18 -14
  456. package/src/commands/browse-session.ts +12 -0
  457. package/src/commands/browse.ts +6 -7
  458. package/src/commands/conversations.ts +279 -0
  459. package/src/commands/deinit.ts +6 -0
  460. package/src/commands/docs.ts +25 -6
  461. package/src/commands/doctor.ts +75 -9
  462. package/src/commands/fetch.ts +7 -6
  463. package/src/commands/files.ts +143 -0
  464. package/src/commands/governor.ts +13 -12
  465. package/src/commands/inbox.ts +61 -0
  466. package/src/commands/init.ts +78 -16
  467. package/src/commands/ledger-v3.ts +421 -1
  468. package/src/commands/logs.ts +224 -0
  469. package/src/commands/messages.ts +61 -0
  470. package/src/commands/outline.ts +6 -2
  471. package/src/commands/read.ts +6 -2
  472. package/src/commands/semantic.ts +66 -1
  473. package/src/commands/storage.ts +310 -0
  474. package/src/commands/tunnel.ts +66 -52
  475. package/src/commands/web.ts +77 -7
  476. package/src/commands/work.ts +3 -3
  477. package/src/commands/workflow.ts +13 -13
  478. package/src/core/agents/cli.ts +259 -53
  479. package/src/core/agents/live-authority-v3.ts +341 -10
  480. package/src/core/agents/live-lifecycle-v3.ts +6 -1
  481. package/src/core/agents/live-observation-v3.ts +6 -1
  482. package/src/core/agents/render/prompt-context.ts +27 -6
  483. package/src/core/agents/rules/stop-hook.ts +107 -16
  484. package/src/core/agents/rules/verdict.ts +1 -0
  485. package/src/core/agents/session-events.ts +4 -0
  486. package/src/core/agents/session-finalization-state-v3.ts +1 -1
  487. package/src/core/agents/session-finalizer-v3.ts +4 -1
  488. package/src/core/agents/state/activity-log.ts +7 -2
  489. package/src/core/agents/state/heartbeat-writer.ts +27 -0
  490. package/src/core/agents/state/live-coordination-view.ts +16 -105
  491. package/src/core/agents/state/live-coordination-writer.ts +141 -0
  492. package/src/core/artifacts/index.ts +64 -1
  493. package/src/core/config.ts +126 -5
  494. package/src/core/conversations/archive.ts +237 -0
  495. package/src/core/conversations/catalog.ts +79 -0
  496. package/src/core/conversations/context-pack.ts +72 -0
  497. package/src/core/conversations/contract.ts +178 -0
  498. package/src/core/conversations/evaluation.ts +30 -0
  499. package/src/core/conversations/index.ts +9 -0
  500. package/src/core/conversations/lifecycle.ts +63 -0
  501. package/src/core/conversations/normalize.ts +105 -0
  502. package/src/core/conversations/query.ts +318 -0
  503. package/src/core/conversations/search-index.ts +48 -0
  504. package/src/core/events/legacy-storage/canary.ts +177 -0
  505. package/src/core/events/legacy-storage/fence.ts +129 -0
  506. package/src/core/events/legacy-storage/index.ts +5 -0
  507. package/src/core/events/legacy-storage/inventory.ts +51 -0
  508. package/src/core/events/legacy-storage/manifest.ts +136 -0
  509. package/src/core/events/legacy-storage/reader.ts +178 -0
  510. package/src/core/events/v3/authority-outbox.ts +22 -1
  511. package/src/core/events/v3/base-contract.ts +17 -7
  512. package/src/core/events/v3/bootstrap.ts +195 -2
  513. package/src/core/events/v3/capabilities.ts +3 -3
  514. package/src/core/events/v3/control-witness.ts +339 -0
  515. package/src/core/events/v3/control-writer.ts +16 -0
  516. package/src/core/events/v3/control.ts +54 -18
  517. package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
  518. package/src/core/events/v3/coordination-view.ts +17 -1
  519. package/src/core/events/v3/generated.ts +1 -1
  520. package/src/core/events/v3/index.ts +5 -2
  521. package/src/core/events/v3/live-route-observer.ts +80 -0
  522. package/src/core/events/v3/live-routing.ts +64 -46
  523. package/src/core/events/v3/producers/coordination-recorder.ts +95 -10
  524. package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
  525. package/src/core/events/v3/producers/hook-base.ts +1 -1
  526. package/src/core/events/v3/producers/intake.ts +30 -2
  527. package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
  528. package/src/core/events/v3/producers/recorder.ts +571 -33
  529. package/src/core/events/v3/reader.ts +243 -2
  530. package/src/core/events/v3/rotation-config.ts +98 -0
  531. package/src/core/events/v3/runtime-build.ts +41 -0
  532. package/src/core/events/v3/runtime-identity.ts +16 -0
  533. package/src/core/events/v3/runtime-telemetry-capabilities.ts +14 -8
  534. package/src/core/events/v3/support-storage/classify.ts +209 -0
  535. package/src/core/events/v3/support-storage/eligibility.ts +58 -0
  536. package/src/core/events/v3/support-storage/index.ts +9 -0
  537. package/src/core/events/v3/support-storage/inventory.ts +135 -0
  538. package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
  539. package/src/core/events/v3/support-storage/maintenance.ts +501 -0
  540. package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
  541. package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
  542. package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
  543. package/src/core/events/v3/support-storage/recovery.ts +43 -0
  544. package/src/core/events/v3/turn-telemetry.ts +58 -7
  545. package/src/core/events/v3/writer.ts +168 -16
  546. package/src/core/governor/plan-read.ts +5 -18
  547. package/src/core/governor/planning.ts +5 -8
  548. package/src/core/governor/service-read.ts +320 -2
  549. package/src/core/governor/service.ts +49 -22
  550. package/src/core/guard/evidence-v3.ts +1 -0
  551. package/src/core/hooks/adapter/events.ts +1 -0
  552. package/src/core/hooks/adapter/output.ts +12 -5
  553. package/src/core/hooks/adapter/runtime-telemetry.ts +408 -13
  554. package/src/core/hooks/cli.ts +226 -32
  555. package/src/core/hooks/effects/image-capture.ts +4 -1
  556. package/src/core/hooks/remediation-cap.ts +12 -6
  557. package/src/core/hooks/resolve/coord-root.ts +91 -11
  558. package/src/core/hooks/resolve/owner.ts +4 -0
  559. package/src/core/hooks/resolve/transcript.ts +18 -0
  560. package/src/core/inbox/contract.ts +81 -0
  561. package/src/core/inbox/index.ts +4 -0
  562. package/src/core/inbox/lifecycle.ts +104 -0
  563. package/src/core/inbox/service.ts +305 -0
  564. package/src/core/inbox/watcher.ts +36 -0
  565. package/src/core/presence/codec-digest.ts +15 -9
  566. package/src/core/presence/relay-client.ts +55 -7
  567. package/src/core/semantic/adapters.ts +200 -41
  568. package/src/core/semantic/contract.ts +135 -3
  569. package/src/core/semantic/index.ts +76 -2
  570. package/src/core/semantic/once.ts +93 -7
  571. package/src/core/semantic/prompt.ts +13 -1
  572. package/src/core/semantic/review.ts +803 -0
  573. package/src/core/semantic/routes.ts +30 -0
  574. package/src/core/semantic/scheduler.ts +49 -5
  575. package/src/core/semantic/service-status.ts +99 -5
  576. package/src/core/semantic/service.ts +116 -15
  577. package/src/core/semantic/soak.ts +638 -0
  578. package/src/core/semantic/storage.ts +20 -6
  579. package/src/core/semantic/usage.ts +272 -0
  580. package/src/core/semantic/validate.ts +31 -0
  581. package/src/core/storage/buffer.ts +124 -0
  582. package/src/core/storage/builtins.ts +916 -0
  583. package/src/core/storage/catalog.ts +467 -0
  584. package/src/core/storage/config.ts +423 -0
  585. package/src/core/storage/contract.ts +342 -0
  586. package/src/core/storage/durable-history.ts +738 -0
  587. package/src/core/storage/health.ts +76 -0
  588. package/src/core/storage/index.ts +15 -0
  589. package/src/core/storage/inventory.ts +859 -0
  590. package/src/core/storage/jsonl.ts +213 -0
  591. package/src/core/storage/log-retention.ts +555 -0
  592. package/src/core/storage/logger.ts +546 -0
  593. package/src/core/storage/maintenance-providers.ts +200 -0
  594. package/src/core/storage/maintenance.ts +929 -0
  595. package/src/core/storage/metrics.ts +199 -0
  596. package/src/core/storage/policy.ts +141 -0
  597. package/src/core/storage/process-log.ts +203 -0
  598. package/src/core/storage/query.ts +360 -0
  599. package/src/core/storage/receipts.ts +162 -0
  600. package/src/core/storage/segments.ts +721 -0
  601. package/src/core/storage/sink-graph.ts +343 -0
  602. package/src/core/storage/storm-control.ts +91 -0
  603. package/src/core/work/state.ts +12 -21
  604. package/src/core/workflow/live-session-v3.ts +2 -4
  605. package/src/index.ts +2 -0
  606. package/src/lazy-commands.ts +294 -0
  607. package/src/lib/docs-lint.ts +58 -77
  608. package/src/lib/docs-metadata-audit.ts +26 -21
  609. package/src/lib/docs-metadata-sync.ts +32 -9
  610. package/src/lib/docs-repository-view.ts +220 -0
  611. package/src/lib/http/client.ts +44 -8
  612. package/src/lib/http/index.ts +6 -1
  613. package/src/lib/indexer-exclusions.ts +173 -0
  614. package/src/lib/instructions/templates.ts +5 -0
  615. package/src/lib/local-file-url.ts +31 -0
  616. package/src/lib/web-performance.ts +335 -0
@@ -17,19 +17,21 @@
17
17
  * adapter flow.
18
18
  */
19
19
 
20
- import { spawnSync } from "node:child_process";
20
+ import { spawn, spawnSync } from "node:child_process";
21
21
  import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
22
22
  import { dirname, join } from "node:path";
23
23
  import { coordEnv } from "../../lib/env.ts";
24
24
  import { buildInstructionBundle } from "../../lib/instructions/bundle.ts";
25
25
  import type { Adapter } from "../adapter.ts";
26
26
  import { coordBinPath } from "../agents/coord-bin.ts";
27
+ import { resolveCoordRoot } from "../agents/coord-client.ts";
27
28
  import {
28
29
  type ClaimFinalizationDecision,
29
30
  type ClaimFinalizationDescriptor,
30
31
  classifyWriteClaimFinalization,
31
32
  formatWriteClaimFinalizationDenial,
32
33
  } from "../agents/finalization.ts";
34
+ import { restoreLiveCoordinationStateAfterEpochV3 } from "../agents/live-authority-v3.ts";
33
35
  import { evaluateStopHook, STOP_REMEDIATION_MARKER } from "../agents/rules/stop-hook.ts";
34
36
  import {
35
37
  assistantTextStartsWithSessionNameBlock,
@@ -39,11 +41,10 @@ import {
39
41
  sessionNameDisplayRecoveryInstruction,
40
42
  toolResponseMintedSessionName,
41
43
  } from "../agents/session-name-display.ts";
42
- import { stampSessionNameSeen } from "../agents/state/heartbeat-writer.ts";
43
- import {
44
- ensureLiveCoordinationHeartbeat,
45
- readLiveCoordinationRow,
46
- } from "../agents/state/live-coordination-view.ts";
44
+ import type { Heartbeat } from "../agents/state/heartbeat-reader.ts";
45
+ import { readHeartbeat, stampSessionNameSeen } from "../agents/state/heartbeat-writer.ts";
46
+ import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.ts";
47
+ import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.ts";
47
48
  import { writePidmapRow } from "../agents/state/pidmap.ts";
48
49
  import { agentsRequireGitFinalization, resolveBinName } from "../config.ts";
49
50
  import {
@@ -59,12 +60,14 @@ import {
59
60
  import { tryWriteLiveDisplayV3 } from "../events/v3/live-feed.ts";
60
61
  import {
61
62
  liveHookSignalDefersDrainV3,
63
+ reconcileLivePendingRuntimeContextV3,
62
64
  recordLiveDelegatedChildSessionV3,
63
65
  recordLiveHookSignalV3,
64
66
  resolveLiveEventLedgerRouteV3,
65
67
  } from "../events/v3/live-routing.ts";
66
68
  import { captureSpanClockV3 } from "../events/v3/span-state.ts";
67
- import { fetchPresence } from "../presence/index.ts";
69
+ import { ensureRelayDaemon, fetchPresence, publishPresence } from "../presence/index.ts";
70
+ import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.ts";
68
71
  import { stableScopeId } from "../workflow/scope-id.ts";
69
72
  import { detectAdapter, shouldSkipHookAdapter } from "./adapter/detect.ts";
70
73
  import {
@@ -98,12 +101,11 @@ import {
98
101
  import { toolInputHash, toolTargetHash } from "./events/input-hash.ts";
99
102
  import { canonicalize } from "./guard-path.ts";
100
103
  import { adapterPidFromEnv, parsePsChainLine, selectAnchorPid } from "./resolve/anchor.ts";
101
- import { findCoordRoot } from "./resolve/coord-root.ts";
102
104
  import { extractIntentComment, resolveIntent } from "./resolve/intent.ts";
103
105
  import { resolveOwner } from "./resolve/owner.ts";
104
106
  import {
105
107
  inspectSessionNameDisplayImmediately,
106
- scanAssistantTextIncludes,
108
+ scanAssistantStatusBoxPresent,
107
109
  scanSessionNameDisplayedImmediately,
108
110
  scanStatusBoxPresent,
109
111
  scanTranscriptRuntime,
@@ -134,6 +136,11 @@ function parseArgv(argv: string[]): Argv {
134
136
  return out;
135
137
  }
136
138
 
139
+ function extraArg(extra: string[], name: string): string | undefined {
140
+ const index = extra.indexOf(name);
141
+ return index >= 0 ? extra[index + 1] : undefined;
142
+ }
143
+
137
144
  async function readStdin(): Promise<string> {
138
145
  if (process.stdin.isTTY) return "";
139
146
  try {
@@ -159,6 +166,14 @@ function childEnv(coordRoot: string): NodeJS.ProcessEnv {
159
166
  }
160
167
 
161
168
  function appendDebug(coordRoot: string, entry: Record<string, unknown>): void {
169
+ if (coordEnv("SHARED_LOGS") !== "0") {
170
+ try {
171
+ processLogger(coordRoot, "agent-hook").debug("agent_hook.diagnostic", legacyLogFields(entry));
172
+ return;
173
+ } catch {
174
+ /* fall through to the rollback writer */
175
+ }
176
+ }
162
177
  const path = join(coordRoot, ".harnery", "debug", "agent-hook.ndjson");
163
178
  try {
164
179
  mkdirSync(dirname(path), { recursive: true });
@@ -170,6 +185,18 @@ function appendDebug(coordRoot: string, entry: Record<string, unknown>): void {
170
185
 
171
186
  function logError(coordRoot: string | null, err: unknown, context: Record<string, unknown>): void {
172
187
  if (!coordRoot) return;
188
+ if (coordEnv("SHARED_LOGS") !== "0") {
189
+ try {
190
+ processLogger(coordRoot, "agent-hook").error(
191
+ "agent_hook.error",
192
+ legacyLogFields(context),
193
+ err,
194
+ );
195
+ return;
196
+ } catch {
197
+ /* fall through to the rollback writer */
198
+ }
199
+ }
173
200
  const path = join(coordRoot, ".harnery", "debug", "agent-hook.errors.ndjson");
174
201
  try {
175
202
  mkdirSync(dirname(path), { recursive: true });
@@ -408,9 +435,10 @@ function buildEventData(
408
435
  // assistant text only (same window, same scanner as the session-name
409
436
  // detection). The Stop verdict enforces this field; the loose field is
410
437
  // retained as diagnostic telemetry for the measured detector divergence.
411
- status_box_present_strict:
412
- scanAssistantTextIncludes(p?.transcript_path, "┌─ agent-") ||
413
- lastAssistantMessage.includes("┌─ agent-"),
438
+ status_box_present_strict: scanAssistantStatusBoxPresent(
439
+ p?.transcript_path,
440
+ lastAssistantMessage,
441
+ ),
414
442
  // Whether the session's suggested name is satisfied as of this turn,
415
443
  // and which name that refers to. Reported on every stop while a name
416
444
  // exists (the stop-hook.session_name verdict reads it per turn); the
@@ -582,7 +610,7 @@ async function main(): Promise<number> {
582
610
  // `--adapter cursor` dispatch of the same payload carries the session.
583
611
  if (shouldSkipHookAdapter(adapter, raw)) {
584
612
  if (coordEnv("AGENT_COORD_OFF") !== "1") {
585
- const coordRoot = findCoordRoot(process.cwd());
613
+ const coordRoot = resolveCoordRoot(process.cwd());
586
614
  if (coordRoot) {
587
615
  appendDebug(coordRoot, {
588
616
  ts: new Date().toISOString(),
@@ -607,7 +635,7 @@ async function main(): Promise<number> {
607
635
  if (adapter === "claude-code" && eventName) {
608
636
  const s = soundForEvent(eventName);
609
637
  if (s) {
610
- const repoRoot = findCoordRoot(process.cwd());
638
+ const repoRoot = resolveCoordRoot(process.cwd());
611
639
  if (repoRoot) {
612
640
  let sid = "";
613
641
  let stopContinuation = false;
@@ -638,8 +666,11 @@ async function main(): Promise<number> {
638
666
  // bypass during incident triage.
639
667
  if (coordEnv("AGENT_COORD_OFF") === "1") return 0;
640
668
 
641
- const coordRoot = findCoordRoot(process.cwd());
669
+ const coordRoot = resolveCoordRoot(process.cwd());
642
670
  if (!coordRoot) return 0;
671
+ if (eventName === "runtime-context-retry") {
672
+ return runRuntimeContextRetryWorker(coordRoot, adapter, extra);
673
+ }
643
674
  const ledgerRoute = resolveLiveEventLedgerRouteV3(coordRoot);
644
675
 
645
676
  // Always log a breadcrumb, useful when an event_type maps to null or owner
@@ -661,6 +692,30 @@ async function main(): Promise<number> {
661
692
  return 0;
662
693
  }
663
694
 
695
+ // Cursor's preToolUse `agent_message` is only the current narration before
696
+ // that tool. It is not a transcript and therefore cannot prove that an
697
+ // earlier assistant response omitted the required session-name block.
698
+ // afterAgentResponse is the one native boundary that carries the completed
699
+ // assistant text, so stamp a positive sighting here without retaining or
700
+ // emitting the response body into V3.
701
+ if (adapter === "cursor" && eventName === "after-agent-response") {
702
+ const payload = parsePayload(raw, adapter);
703
+ const owner = resolveOwner({ payload: payload?.raw ?? null, coordRoot });
704
+ if (!owner) {
705
+ appendDebug(coordRoot, { ...debugBase, skipped: "no-owner-resolved" });
706
+ return 0;
707
+ }
708
+ const name = sessionNameDisplayPending(readLiveCoordinationRow(coordRoot, owner.instance_id));
709
+ const text = typeof payload?.raw.text === "string" ? payload.raw.text : "";
710
+ if (name && assistantTextStartsWithSessionNameBlock(text, name)) {
711
+ stampSessionNameSeen(coordRoot, owner.instance_id, name);
712
+ appendDebug(coordRoot, { ...debugBase, effect: "session-name-display-stamped" });
713
+ } else {
714
+ appendDebug(coordRoot, { ...debugBase, skipped: "no-session-name-sighting" });
715
+ }
716
+ return 0;
717
+ }
718
+
664
719
  const norm = normalizeEventName(eventName);
665
720
  if (!norm) {
666
721
  appendDebug(coordRoot, { ...debugBase, skipped: "non-canonical-event" });
@@ -682,6 +737,7 @@ async function main(): Promise<number> {
682
737
  }
683
738
 
684
739
  const sessionId = payload?.session_id ?? payload?.conversation_id ?? owner.instance_id;
740
+ const priorCoordination = readHeartbeat(coordRoot, owner.instance_id);
685
741
 
686
742
  const data = buildEventData(norm.event_type, {
687
743
  coordRoot,
@@ -756,6 +812,24 @@ async function main(): Promise<number> {
756
812
  ...(turnRitual ? { turn_ritual: turnRitual } : {}),
757
813
  ...(deferV3Drain ? { defer_drain: true } : {}),
758
814
  });
815
+ const recordedGenerationId =
816
+ v3Result && "event" in v3Result && "generation_id" in v3Result.event.scope
817
+ ? (v3Result.event.scope.generation_id as `gen_${string}`)
818
+ : undefined;
819
+ if (v3Result?.state === "recorded" || v3Result?.state === "already_started") {
820
+ try {
821
+ restoreLiveCoordinationStateAfterEpochV3({
822
+ coordRoot,
823
+ owner: owner.instance_id,
824
+ nativeSessionId: sessionId,
825
+ adapter,
826
+ prior: priorCoordination,
827
+ currentGenerationId: recordedGenerationId,
828
+ });
829
+ } catch (error) {
830
+ logError(coordRoot, error, { phase: "epoch-coordination-restore" });
831
+ }
832
+ }
759
833
  const v3EventId =
760
834
  v3Result && "event" in v3Result
761
835
  ? v3Result.event.event_id
@@ -795,7 +869,7 @@ async function main(): Promise<number> {
795
869
 
796
870
  if (v3Result?.state === "recorded" && capturedImages.length > 0) {
797
871
  try {
798
- recordImageArtifactsV3(coordRoot, v3Result.event, capturedImages);
872
+ recordImageArtifactsV3(coordRoot, v3Result.event, capturedImages, ledgerRoute.genesis_id);
799
873
  } catch (err) {
800
874
  logError(coordRoot, err, { phase: "image-artifact-observation" });
801
875
  }
@@ -889,6 +963,36 @@ async function main(): Promise<number> {
889
963
  // session-start additionalContext inside emitSessionStartSystemMessage.
890
964
  if (adapter === "claude-code") journalJanitor(coordRoot);
891
965
  imageJanitor(coordRoot);
966
+ // Session start is the only caller of the artifact janitor and the storage
967
+ // maintenance pass, so both load here instead of on every tool call.
968
+ const { autoCleanArtifacts } = await import("../artifacts/index.ts");
969
+ const { createAutomaticMaintenanceComposition, runAutomaticMaintenancePass } = await import(
970
+ "../storage/maintenance-providers.ts"
971
+ );
972
+ // Effect: throttled daily sweep of expired artifact workspaces (guarded,
973
+ // managed-expired only; see autoCleanArtifacts). Best-effort like every
974
+ // janitor here: a failure logs and never blocks session start.
975
+ try {
976
+ autoCleanArtifacts(coordRoot);
977
+ } catch (err) {
978
+ logError(coordRoot, err, { phase: "artifact-auto-clean" });
979
+ }
980
+ // Plan one bounded, claim-first global slice from cached pressure only.
981
+ // Existing owner janitors above remain the only active executors until
982
+ // each provider receives a separate production activation.
983
+ try {
984
+ await runAutomaticMaintenancePass(
985
+ createAutomaticMaintenanceComposition(coordRoot, {
986
+ journal: () => {
987
+ if (adapter === "claude-code") journalJanitor(coordRoot);
988
+ },
989
+ images: () => imageJanitor(coordRoot),
990
+ artifacts: () => autoCleanArtifacts(coordRoot),
991
+ }),
992
+ );
993
+ } catch (err) {
994
+ logError(coordRoot, err, { phase: "storage-maintenance-auto" });
995
+ }
892
996
  let recovery: PreparedContextRecovery | null = null;
893
997
  if (payload?.source === "compact") {
894
998
  try {
@@ -920,10 +1024,13 @@ async function main(): Promise<number> {
920
1024
  } catch (err) {
921
1025
  logError(coordRoot, err, { phase: "session-start-systemMessage" });
922
1026
  }
923
- // Pull advisory cross-machine presence. V3 never publishes from the
924
- // disposable heartbeat cache.
1027
+ // Cross-machine presence is derived from the authority-safe V3 projection,
1028
+ // not the disposable heartbeat cache. Announce this session, pull peers,
1029
+ // and keep the optional live relay connected.
925
1030
  try {
1031
+ publishPresence(coordRoot);
926
1032
  fetchPresence(coordRoot);
1033
+ ensureRelayDaemon(coordRoot);
927
1034
  } catch (err) {
928
1035
  logError(coordRoot, err, { phase: "session-start-presence" });
929
1036
  }
@@ -943,6 +1050,13 @@ async function main(): Promise<number> {
943
1050
  journalArchive(coordRoot, owner.instance_id);
944
1051
  runSessionSyncExtension(coordRoot, true);
945
1052
  }
1053
+ // Publish the post-cleanup V3 projection so remote machines see this
1054
+ // session disappear without waiting for the stale window.
1055
+ try {
1056
+ publishPresence(coordRoot);
1057
+ } catch (err) {
1058
+ logError(coordRoot, err, { phase: "session-end-presence" });
1059
+ }
946
1060
  }
947
1061
 
948
1062
  // Phase 8: SubagentStart: the child generation was opened above from the
@@ -1061,6 +1175,16 @@ async function main(): Promise<number> {
1061
1175
  runSessionSyncExtension(coordRoot, false);
1062
1176
  }
1063
1177
 
1178
+ // Publish after the canonical turn event has landed so the blob carries
1179
+ // current task, activity, and claim state. Re-ensure the relay here because
1180
+ // its daemon intentionally exits when a machine has no live sessions.
1181
+ try {
1182
+ publishPresence(coordRoot);
1183
+ ensureRelayDaemon(coordRoot);
1184
+ } catch (err) {
1185
+ logError(coordRoot, err, { phase: "stop-presence" });
1186
+ }
1187
+
1064
1188
  // Stop verdict (V3 ritual + task/status gate). Direct in-process call: the
1065
1189
  // rule lives in Harnery. agent-hook already emitted this turn.completed
1066
1190
  // with privacy-safe ritual observations, so the evidence is in the stream.
@@ -1069,6 +1193,8 @@ async function main(): Promise<number> {
1069
1193
  instance_id: owner.instance_id,
1070
1194
  session_id: sessionId,
1071
1195
  adapter,
1196
+ stop_hook_active: payload?.stop_hook_active === true,
1197
+ status_box_present_strict: data.status_box_present_strict === true,
1072
1198
  bypass: coordEnv("AGENT_COORD_BYPASS_STOP") === "1",
1073
1199
  workflow_child: coordEnv("WORKFLOW_CHILD") === "1",
1074
1200
  });
@@ -1078,13 +1204,16 @@ async function main(): Promise<number> {
1078
1204
  // `cap` consecutive blocked stops in one cycle, allow the stop instead
1079
1205
  // of bouncing the model forever. Cycle boundaries come from the
1080
1206
  // adapter's continuation flag, so adapters without one are unaffected.
1081
- const { remediationCapExceeded } = await import("./remediation-cap.ts");
1082
- if (remediationCapExceeded(sessionId, payload?.stop_hook_active === true)) {
1207
+ const { recordRemediationBlock } = await import("./remediation-cap.ts");
1208
+ const remediation = recordRemediationBlock(sessionId, payload?.stop_hook_active === true);
1209
+ if (remediation.exceeded) {
1083
1210
  appendDebug(coordRoot, {
1084
1211
  ...debugBase,
1085
1212
  skipped: "stop-remediation-cap-exhausted",
1086
1213
  blocked_rule: verdict.rule,
1214
+ blocked_count: remediation.count,
1087
1215
  session_id: sessionId,
1216
+ remediation_cycle_anchor: verdict.remediation_cycle_anchor,
1088
1217
  });
1089
1218
  } else {
1090
1219
  // Adapter-aware enforcement channel: Claude Code honors exit-2 + stderr
@@ -1113,6 +1242,7 @@ async function main(): Promise<number> {
1113
1242
  } catch (err) {
1114
1243
  logError(coordRoot, err, { phase: "stop-explicit-session-finalization" });
1115
1244
  }
1245
+ if (adapter === "codex") scheduleCodexRuntimeContextRetry(coordRoot, sessionId);
1116
1246
  }
1117
1247
 
1118
1248
  // Phase 7: PreToolUse: heartbeat + pid-map self-heal on every tool call.
@@ -1141,14 +1271,18 @@ async function main(): Promise<number> {
1141
1271
  // runs before a name exists; every later tool waits until the exact block
1142
1272
  // is the first assistant text after the mint result. Cursor supplies
1143
1273
  // agent_message directly; Claude Code and Codex are resolved from their
1144
- // JSONL transcripts. Later commentary must not erase an already-correct
1145
- // display, and an unreadable transcript must not deadlock every tool.
1274
+ // JSONL transcripts. Cursor's current narration can provide positive
1275
+ // evidence, but cannot disprove an earlier response; afterAgentResponse
1276
+ // stamps that durable sighting. Later commentary must not erase an
1277
+ // already-correct display, and unavailable evidence must not deadlock
1278
+ // every tool.
1146
1279
  try {
1147
1280
  const displayAllowed = await enforcePendingSessionNameDisplay(
1148
1281
  coordRoot,
1149
1282
  owner.instance_id,
1150
1283
  adapter,
1151
1284
  payload,
1285
+ generationBoundHeartbeat(readHeartbeat(coordRoot, owner.instance_id), recordedGenerationId),
1152
1286
  );
1153
1287
  if (!displayAllowed) return 0;
1154
1288
  } catch (err) {
@@ -1225,13 +1359,56 @@ async function main(): Promise<number> {
1225
1359
  return 0;
1226
1360
  }
1227
1361
 
1362
+ function scheduleCodexRuntimeContextRetry(coordRoot: string, nativeSessionId: string): void {
1363
+ const modulePath = process.argv[1];
1364
+ if (!modulePath) return;
1365
+ try {
1366
+ const child = spawn(
1367
+ process.execPath,
1368
+ [modulePath, "runtime-context-retry", "--adapter", "codex", "--session-id", nativeSessionId],
1369
+ {
1370
+ cwd: coordRoot,
1371
+ detached: true,
1372
+ stdio: "ignore",
1373
+ env: childEnv(coordRoot),
1374
+ },
1375
+ );
1376
+ child.unref();
1377
+ } catch (err) {
1378
+ logError(coordRoot, err, { phase: "runtime-context-retry-spawn" });
1379
+ }
1380
+ }
1381
+
1382
+ async function runRuntimeContextRetryWorker(
1383
+ coordRoot: string,
1384
+ adapter: Adapter | null,
1385
+ extra: string[],
1386
+ ): Promise<number> {
1387
+ const nativeSessionId = extraArg(extra, "--session-id");
1388
+ if (adapter !== "codex" || !nativeSessionId) return 0;
1389
+ for (const [index, delayMs] of [400, 1_000].entries()) {
1390
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
1391
+ const route = resolveLiveEventLedgerRouteV3(coordRoot);
1392
+ if (route.state !== "v3") return 0;
1393
+ const result = reconcileLivePendingRuntimeContextV3({
1394
+ coordRoot,
1395
+ route,
1396
+ nativeSessionId,
1397
+ finalAttempt: index === 1,
1398
+ });
1399
+ if (result.state !== "pending" && result.state !== "busy") return 0;
1400
+ }
1401
+ return 0;
1402
+ }
1403
+
1228
1404
  async function enforcePendingSessionNameDisplay(
1229
1405
  coordRoot: string,
1230
1406
  instanceId: string,
1231
1407
  adapter: Adapter,
1232
1408
  payload: ParsedPayload | null,
1409
+ coordination: Heartbeat | null,
1233
1410
  ): Promise<boolean> {
1234
- const name = sessionNameDisplayPending(readLiveCoordinationRow(coordRoot, instanceId));
1411
+ const name = sessionNameDisplayPending(coordination);
1235
1412
  if (!name) return true;
1236
1413
 
1237
1414
  const command = extractBashCommand(payload?.tool_name, payload?.tool_input);
@@ -1242,7 +1419,7 @@ async function enforcePendingSessionNameDisplay(
1242
1419
  ? {
1243
1420
  state: assistantTextStartsWithSessionNameBlock(payload.agent_message, name)
1244
1421
  ? ("present" as const)
1245
- : ("absent" as const),
1422
+ : ("unavailable" as const),
1246
1423
  }
1247
1424
  : inspectSessionNameDisplayImmediately(
1248
1425
  // Codex hook payloads omit transcript_path on every event, which
@@ -1275,6 +1452,13 @@ async function enforcePendingSessionNameDisplay(
1275
1452
  return false;
1276
1453
  }
1277
1454
 
1455
+ function generationBoundHeartbeat(
1456
+ heartbeat: Heartbeat | null,
1457
+ generationId: `gen_${string}` | undefined,
1458
+ ): Heartbeat | null {
1459
+ return generationId && heartbeat?.v3_generation_id === generationId ? heartbeat : null;
1460
+ }
1461
+
1278
1462
  async function runPreToolUseGuard(
1279
1463
  coordRoot: string,
1280
1464
  instanceId: string,
@@ -1622,16 +1806,22 @@ async function emitUserPromptSubmitSystemMessage(
1622
1806
  // Every human-facing adapter gets the first-session naming reminder from
1623
1807
  // the shared hook path. Cursor + Codex additionally get ongoing set-task
1624
1808
  // staleness nudges; Claude Code enforces those via its Stop transcript.
1809
+ // Codex also gets the optional project-owned prompt reminder. Claude Code
1810
+ // already has native output-style reminders, so duplicating it would add
1811
+ // noise. Cursor's current beforeSubmitPrompt output can allow or block but
1812
+ // cannot inject model context; an Always Apply rule is its durable carrier.
1813
+ // Only the boolean route travels through argv, never the host's text.
1814
+ if (adapter === "codex") args.push("--host-prompt-reminder");
1625
1815
  // Codex gets a fresh status-footer reminder on every prompt. Its Stop hook
1626
1816
  // stays observe-only, so missing the footer never replaces the answer.
1627
- // Claude Code + Cursor (the Stop-ENFORCING adapters) get a fresh per-turn
1628
- // ritual reminder: satisfying the contract up front is far cheaper than
1629
- // the bounce-and-retry the Stop hook otherwise forces.
1817
+ // Claude Code gets a fresh per-turn ritual reminder: satisfying the
1818
+ // contract up front is far cheaper than the bounce-and-retry the Stop hook
1819
+ // otherwise forces. Cursor's beforeSubmitPrompt cannot inject context, so
1820
+ // its Stop follow-up remains the supported enforcement channel.
1630
1821
  args.push("--session-name-nudge");
1631
1822
  if (adapter === "cursor" || adapter === "codex") args.push("--task-nudge");
1632
1823
  if (adapter === "codex") args.push("--status-footer-nudge");
1633
- if (adapter === "claude-code" || adapter === "cursor")
1634
- args.push("--turn-ritual-nudge", adapter);
1824
+ if (adapter === "claude-code") args.push("--turn-ritual-nudge", adapter);
1635
1825
  const result = spawnSync(agentCoordBin, args, { encoding: "utf8", timeout: 3000 });
1636
1826
  if (result.status === 0 && result.stdout) additionalContext = result.stdout.trim();
1637
1827
  }
@@ -1796,11 +1986,15 @@ function completeRecoveryInjection(
1796
1986
  }
1797
1987
 
1798
1988
  main()
1799
- .then((code) => process.exit(code))
1800
- .catch((err) => {
1801
- logError(findCoordRoot(process.cwd()), err, {
1989
+ .then(async (code) => {
1990
+ await closeProcessLoggers();
1991
+ process.exit(code);
1992
+ })
1993
+ .catch(async (err) => {
1994
+ logError(resolveCoordRoot(process.cwd()), err, {
1802
1995
  argv: process.argv.slice(2),
1803
1996
  pid: process.pid,
1804
1997
  });
1998
+ await closeProcessLoggers();
1805
1999
  process.exit(0);
1806
2000
  });
@@ -94,10 +94,13 @@ export function recordImageArtifactsV3(
94
94
  coordRoot: string,
95
95
  sourceEvent: EventV3,
96
96
  artifacts: readonly CapturedImageArtifact[],
97
+ expectedGenesisId?: `gex_${string}`,
97
98
  ): void {
98
99
  if (!("generation_id" in sourceEvent.scope) || !sourceEvent.attestation_id) return;
99
100
  for (const artifact of artifacts) {
100
- writeEventV3(coordRoot, buildImageArtifactEventV3(sourceEvent, artifact));
101
+ writeEventV3(coordRoot, buildImageArtifactEventV3(sourceEvent, artifact), {
102
+ ...(expectedGenesisId ? { expectedGenesisId } : {}),
103
+ });
101
104
  }
102
105
  }
103
106
 
@@ -36,14 +36,20 @@ function counterPath(sessionId: string): string {
36
36
  *
37
37
  * Call only when the Stop verdict blocked. `continuation` is the adapter's
38
38
  * "this stop follows a stop-hook block" flag; false starts a fresh cycle.
39
- * Returns true when this cycle has already been blocked `cap` times, meaning
40
- * the caller should allow the stop instead of blocking again.
39
+ * Returns the retained block count and whether this cycle has already been
40
+ * blocked `cap` times, meaning the caller should allow the stop instead of
41
+ * blocking again.
41
42
  */
42
- export function remediationCapExceeded(
43
+ export interface RemediationBlockRecord {
44
+ count: number;
45
+ exceeded: boolean;
46
+ }
47
+
48
+ export function recordRemediationBlock(
43
49
  sessionId: string,
44
50
  continuation: boolean,
45
51
  cap = DEFAULT_STOP_REMEDIATION_CAP,
46
- ): boolean {
52
+ ): RemediationBlockRecord {
47
53
  const path = counterPath(sessionId);
48
54
  let count = 1;
49
55
  if (continuation) {
@@ -62,9 +68,9 @@ export function remediationCapExceeded(
62
68
  writeFileSync(path, String(count), "utf8");
63
69
  } catch {
64
70
  // Counter IO must never turn into a block or a crash; fail open (no cap).
65
- return false;
71
+ return { count, exceeded: false };
66
72
  }
67
- return count > cap;
73
+ return { count, exceeded: count > cap };
68
74
  }
69
75
 
70
76
  /** Clear the cycle counter after an allowed stop. */
@@ -1,14 +1,16 @@
1
- import { resolveCoordRoot } from "../../agents/coord-client.ts";
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
2
4
 
3
5
  /**
4
- * The hooks-side name for THE coordination-root resolution.
6
+ * Resolve the coordination root from path evidence only.
5
7
  *
6
- * Delegates to `resolveCoordRoot()` so the hooks and the CLI cannot resolve
7
- * different roots. They used to: this walked up from `CLAUDE_PROJECT_DIR` or
8
- * cwd while the CLI's `monorepoRoot()` asked git for the superproject first, so
9
- * with a shell inside a submodule that carries its own `.harnery/`, the CLI's
10
- * `coord.status_observed` landed in a stream this side never read and rule 1/3
11
- * blocked every turn.
8
+ * This path-only resolver deliberately does not inspect live producer state.
9
+ * Code that reads or writes coordination authority must use
10
+ * `resolveCoordRoot()` from `agents/coord-client.ts`, which disambiguates
11
+ * nested coordination roots through the registered session. Keeping the two
12
+ * responsibilities separate lets configuration and other path-only consumers
13
+ * avoid loading the event recorder and its contract graph.
12
14
  *
13
15
  * Resolution precedence (see `resolveCoordRoot` for the full rationale):
14
16
  * 1. HARNERY_COORD_ROOT_OVERRIDE — explicit pin (tests, git hooks).
@@ -17,9 +19,87 @@ import { resolveCoordRoot } from "../../agents/coord-client.ts";
17
19
  * submodules that may carry a `.harnery/` of their own (or none at all,
18
20
  * e.g. a journal dir under /tmp). The session's coordination home is the
19
21
  * project the adapter opened, not wherever the shell happens to sit.
20
- * 3. The root that already holds this session's heartbeat.
21
- * 4. The nearest enclosing `.harnery/`, then a git-derived root.
22
+ * 3. The nearest enclosing `.harnery/`.
23
+ * 4. A git-derived root when no `.harnery/` exists yet.
22
24
  */
23
25
  export function findCoordRoot(start: string = process.cwd()): string | null {
24
- return resolveCoordRoot(start);
26
+ const rootOverride = process.env.HARNERY_COORD_ROOT_OVERRIDE;
27
+ if (rootOverride) return rootOverride;
28
+
29
+ const projectDir = process.env.CLAUDE_PROJECT_DIR;
30
+ if (projectDir) {
31
+ const fromProject = nearestCoordRoot(projectDir);
32
+ if (fromProject) return fromProject;
33
+ }
34
+
35
+ const nearest = nearestCoordRoot(start);
36
+ if (nearest) return nearest;
37
+ return gitCoordRoots(start)[0] ?? gitToplevel(start);
25
38
  }
39
+
40
+ /** Nearest enclosing directory carrying `.harnery/`, or null. */
41
+ export function nearestCoordRoot(start: string): string | null {
42
+ return ancestorCoordRoots(start)[0] ?? null;
43
+ }
44
+
45
+ /** Every enclosing directory carrying `.harnery/`, nearest first. */
46
+ export function ancestorCoordRoots(start: string): string[] {
47
+ const found: string[] = [];
48
+ let dir = resolve(start);
49
+ while (true) {
50
+ if (existsSync(join(dir, ".harnery"))) found.push(dir);
51
+ const parent = dirname(dir);
52
+ if (parent === dir) break;
53
+ dir = parent;
54
+ }
55
+ return found;
56
+ }
57
+
58
+ /**
59
+ * Git-derived roots carrying `.harnery/`, in superproject-first order.
60
+ *
61
+ * Spawns use `start` as cwd so a call about another checkout cannot inherit
62
+ * this process's repository. The common-dir fallback recovers a superproject
63
+ * from a submodule worktree, where Git reports no direct superproject path.
64
+ */
65
+ export function gitCoordRoots(start: string): string[] {
66
+ const roots: string[] = [];
67
+ const push = (value: string | null) => {
68
+ if (value && existsSync(join(value, ".harnery")) && !roots.includes(value)) roots.push(value);
69
+ };
70
+
71
+ push(gitRevParse(start, "--show-superproject-working-tree"));
72
+ const common = gitRevParse(start, "--git-common-dir");
73
+ if (common) {
74
+ const index = common.indexOf("/.git/modules/");
75
+ if (index !== -1) push(common.substring(0, index));
76
+ }
77
+ push(gitToplevel(start));
78
+ return roots;
79
+ }
80
+
81
+ export function gitToplevel(start: string): string | null {
82
+ return gitRevParse(start, "--show-toplevel");
83
+ }
84
+
85
+ function gitRevParse(start: string, flag: string): string | null {
86
+ const key = `${start}\0${flag}`;
87
+ const cached = gitRevParseCache.get(key);
88
+ if (cached !== undefined) return cached;
89
+ let value: string | null = null;
90
+ try {
91
+ // A stale adapter project directory may no longer exist. Treat spawn
92
+ // failure as no path evidence instead of turning discovery into an error.
93
+ const result = spawnSync("git", ["rev-parse", flag], {
94
+ cwd: start,
95
+ encoding: "utf8",
96
+ });
97
+ if (result.status === 0) value = result.stdout.trim() || null;
98
+ } catch {
99
+ value = null;
100
+ }
101
+ gitRevParseCache.set(key, value);
102
+ return value;
103
+ }
104
+
105
+ const gitRevParseCache = new Map<string, string | null>();
@@ -45,6 +45,10 @@ export function resolveOwner(opts: {
45
45
  };
46
46
  const childId = value("subagent_id") ?? value("agent_id");
47
47
  const sessionId = value("session_id") ?? value("conversation_id");
48
+ // A payload with one unambiguous session identity needs no projection
49
+ // lookup. Live-authority tie-breaking matters only when the adapter also
50
+ // supplies a child candidate that could be stale or belong to the parent.
51
+ if (sessionId && !childId) return { instance_id: sessionId, source: "payload" };
48
52
  const child = childId ? readLiveCoordinationRow(opts.coordRoot, childId) : null;
49
53
  const session = sessionId ? readLiveCoordinationRow(opts.coordRoot, sessionId) : null;
50
54