harnery 0.32.0 → 0.34.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 (665) hide show
  1. package/README.md +2 -0
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +7 -1
  4. package/dist/commands/adapter.js +2 -2
  5. package/dist/commands/agents.d.ts +144 -1
  6. package/dist/commands/agents.d.ts.map +1 -1
  7. package/dist/commands/agents.js +1408 -565
  8. package/dist/commands/artifacts.d.ts.map +1 -1
  9. package/dist/commands/artifacts.js +7 -6
  10. package/dist/commands/backup.d.ts +1 -1
  11. package/dist/commands/backup.d.ts.map +1 -1
  12. package/dist/commands/backup.js +29 -16
  13. package/dist/commands/browse.d.ts.map +1 -1
  14. package/dist/commands/browse.js +234 -12
  15. package/dist/commands/checkpoint.d.ts.map +1 -1
  16. package/dist/commands/checkpoint.js +3 -2
  17. package/dist/commands/claude-desktop.d.ts +2 -2
  18. package/dist/commands/claude-desktop.d.ts.map +1 -1
  19. package/dist/commands/claude-desktop.js +2 -2
  20. package/dist/commands/context.js +1 -6
  21. package/dist/commands/decision.d.ts.map +1 -1
  22. package/dist/commands/decision.js +22 -38
  23. package/dist/commands/docs.d.ts.map +1 -1
  24. package/dist/commands/docs.js +91 -28
  25. package/dist/commands/doctor.d.ts +4 -2
  26. package/dist/commands/doctor.d.ts.map +1 -1
  27. package/dist/commands/doctor.js +55 -7
  28. package/dist/commands/events.d.ts +5 -0
  29. package/dist/commands/events.d.ts.map +1 -0
  30. package/dist/commands/events.js +189 -0
  31. package/dist/commands/governor.d.ts.map +1 -1
  32. package/dist/commands/governor.js +13 -4
  33. package/dist/commands/init.d.ts +10 -2
  34. package/dist/commands/init.d.ts.map +1 -1
  35. package/dist/commands/init.js +233 -51
  36. package/dist/commands/instructions.d.ts +4 -0
  37. package/dist/commands/instructions.d.ts.map +1 -0
  38. package/dist/commands/instructions.js +100 -0
  39. package/dist/commands/journal.d.ts.map +1 -1
  40. package/dist/commands/journal.js +4 -13
  41. package/dist/commands/ledger-v3.d.ts +5 -0
  42. package/dist/commands/ledger-v3.d.ts.map +1 -0
  43. package/dist/commands/ledger-v3.js +91 -0
  44. package/dist/commands/presence.d.ts.map +1 -1
  45. package/dist/commands/presence.js +15 -6
  46. package/dist/commands/sync.d.ts +1 -1
  47. package/dist/commands/sync.js +1 -1
  48. package/dist/commands/web.d.ts +6 -0
  49. package/dist/commands/web.d.ts.map +1 -1
  50. package/dist/commands/web.js +67 -7
  51. package/dist/commands/work.d.ts.map +1 -1
  52. package/dist/commands/work.js +22 -5
  53. package/dist/core/adapter.d.ts +5 -0
  54. package/dist/core/adapter.d.ts.map +1 -0
  55. package/dist/core/adapter.js +1 -0
  56. package/dist/core/adapters/attest.d.ts +5 -2
  57. package/dist/core/adapters/attest.d.ts.map +1 -1
  58. package/dist/core/adapters/attest.js +8 -3
  59. package/dist/core/adapters/profiles.d.ts +6 -6
  60. package/dist/core/adapters/profiles.d.ts.map +1 -1
  61. package/dist/core/adapters/profiles.js +4 -4
  62. package/dist/core/agents/canonical-emit.d.ts +17 -15
  63. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  64. package/dist/core/agents/canonical-emit.js +27 -25
  65. package/dist/core/agents/cli.js +212 -235
  66. package/dist/core/agents/codex-archive-v3.d.ts +14 -0
  67. package/dist/core/agents/codex-archive-v3.d.ts.map +1 -0
  68. package/dist/core/agents/codex-archive-v3.js +110 -0
  69. package/dist/core/agents/coord-client.d.ts +19 -70
  70. package/dist/core/agents/coord-client.d.ts.map +1 -1
  71. package/dist/core/agents/coord-client.js +65 -155
  72. package/dist/core/agents/finalization.d.ts +4 -1
  73. package/dist/core/agents/finalization.d.ts.map +1 -1
  74. package/dist/core/agents/finalization.js +89 -32
  75. package/dist/core/agents/index.d.ts +5 -5
  76. package/dist/core/agents/index.d.ts.map +1 -1
  77. package/dist/core/agents/index.js +5 -5
  78. package/dist/core/agents/live-authority-v3.d.ts +59 -0
  79. package/dist/core/agents/live-authority-v3.d.ts.map +1 -0
  80. package/dist/core/agents/live-authority-v3.js +233 -0
  81. package/dist/core/agents/live-lifecycle-v3.d.ts +20 -0
  82. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -0
  83. package/dist/core/agents/live-lifecycle-v3.js +91 -0
  84. package/dist/core/agents/live-observation-v3.d.ts +25 -0
  85. package/dist/core/agents/live-observation-v3.d.ts.map +1 -0
  86. package/dist/core/agents/live-observation-v3.js +157 -0
  87. package/dist/core/agents/render/prompt-context.d.ts +10 -4
  88. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  89. package/dist/core/agents/render/prompt-context.js +61 -55
  90. package/dist/core/agents/render/session-context.d.ts +1 -1
  91. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  92. package/dist/core/agents/render/session-context.js +15 -33
  93. package/dist/core/agents/rules/claim-conflict.d.ts +3 -3
  94. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  95. package/dist/core/agents/rules/claim-conflict.js +79 -127
  96. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  97. package/dist/core/agents/rules/commit-conflict.js +3 -18
  98. package/dist/core/agents/rules/stop-hook.d.ts +9 -50
  99. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  100. package/dist/core/agents/rules/stop-hook.js +193 -236
  101. package/dist/core/agents/session-events.d.ts +5 -7
  102. package/dist/core/agents/session-events.d.ts.map +1 -1
  103. package/dist/core/agents/session-events.js +127 -95
  104. package/dist/core/agents/session-finalization-state-v3.d.ts +30 -0
  105. package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -0
  106. package/dist/core/agents/session-finalization-state-v3.js +40 -0
  107. package/dist/core/agents/session-finalizer-v3.d.ts +107 -0
  108. package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -0
  109. package/dist/core/agents/session-finalizer-v3.js +734 -0
  110. package/dist/core/agents/session-name-display.d.ts +40 -0
  111. package/dist/core/agents/session-name-display.d.ts.map +1 -0
  112. package/dist/core/agents/session-name-display.js +119 -0
  113. package/dist/core/agents/state/activity-log.d.ts +3 -3
  114. package/dist/core/agents/state/activity-log.d.ts.map +1 -1
  115. package/dist/core/agents/state/activity-log.js +7 -16
  116. package/dist/core/agents/state/heartbeat-writer.d.ts +29 -46
  117. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  118. package/dist/core/agents/state/heartbeat-writer.js +59 -199
  119. package/dist/core/agents/state/live-coordination-view.d.ts +31 -0
  120. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -0
  121. package/dist/core/agents/state/live-coordination-view.js +209 -0
  122. package/dist/core/agents/state/session-state.d.ts +45 -0
  123. package/dist/core/agents/state/session-state.d.ts.map +1 -0
  124. package/dist/core/agents/state/session-state.js +90 -0
  125. package/dist/core/agents/state/stale-sweep.d.ts +1 -1
  126. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  127. package/dist/core/agents/state/stale-sweep.js +26 -15
  128. package/dist/core/artifacts/index.d.ts.map +1 -1
  129. package/dist/core/artifacts/index.js +5 -7
  130. package/dist/core/config.d.ts +33 -2
  131. package/dist/core/config.d.ts.map +1 -1
  132. package/dist/core/config.js +98 -2
  133. package/dist/core/context/index.d.ts +1 -4
  134. package/dist/core/context/index.d.ts.map +1 -1
  135. package/dist/core/context/index.js +9 -9
  136. package/dist/core/events/span-parent.d.ts +15 -0
  137. package/dist/core/events/span-parent.d.ts.map +1 -0
  138. package/dist/core/events/span-parent.js +34 -0
  139. package/dist/core/events/v3/advance.d.ts +14 -0
  140. package/dist/core/events/v3/advance.d.ts.map +1 -0
  141. package/dist/core/events/v3/advance.js +134 -0
  142. package/dist/core/events/v3/authority-outbox.d.ts +78 -0
  143. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -0
  144. package/dist/core/events/v3/authority-outbox.js +399 -0
  145. package/dist/core/events/v3/base-builder.d.ts +20 -0
  146. package/dist/core/events/v3/base-builder.d.ts.map +1 -0
  147. package/dist/core/events/v3/base-builder.js +29 -0
  148. package/dist/core/events/v3/base-contract.d.ts +7576 -0
  149. package/dist/core/events/v3/base-contract.d.ts.map +1 -0
  150. package/dist/core/events/v3/base-contract.js +647 -0
  151. package/dist/core/events/v3/bootstrap.d.ts +34 -0
  152. package/dist/core/events/v3/bootstrap.d.ts.map +1 -0
  153. package/dist/core/events/v3/bootstrap.js +175 -0
  154. package/dist/core/events/v3/builder.d.ts +20 -0
  155. package/dist/core/events/v3/builder.d.ts.map +1 -0
  156. package/dist/core/events/v3/builder.js +28 -0
  157. package/dist/core/events/v3/canonical.d.ts +31 -0
  158. package/dist/core/events/v3/canonical.d.ts.map +1 -0
  159. package/dist/core/events/v3/canonical.js +100 -0
  160. package/dist/core/events/v3/capabilities.d.ts +31 -0
  161. package/dist/core/events/v3/capabilities.d.ts.map +1 -0
  162. package/dist/core/events/v3/capabilities.js +107 -0
  163. package/dist/core/events/v3/capability-drift.d.ts +22 -0
  164. package/dist/core/events/v3/capability-drift.d.ts.map +1 -0
  165. package/dist/core/events/v3/capability-drift.js +134 -0
  166. package/dist/core/events/v3/catalog.d.ts +38 -0
  167. package/dist/core/events/v3/catalog.d.ts.map +1 -0
  168. package/dist/core/events/v3/catalog.js +135 -0
  169. package/dist/core/events/v3/clock-order.d.ts +34 -0
  170. package/dist/core/events/v3/clock-order.d.ts.map +1 -0
  171. package/dist/core/events/v3/clock-order.js +35 -0
  172. package/dist/core/events/v3/contract.d.ts +171 -0
  173. package/dist/core/events/v3/contract.d.ts.map +1 -0
  174. package/dist/core/events/v3/contract.js +180 -0
  175. package/dist/core/events/v3/control.d.ts +111 -0
  176. package/dist/core/events/v3/control.d.ts.map +1 -0
  177. package/dist/core/events/v3/control.js +419 -0
  178. package/dist/core/events/v3/coordination-view.d.ts +69 -0
  179. package/dist/core/events/v3/coordination-view.d.ts.map +1 -0
  180. package/dist/core/events/v3/coordination-view.js +119 -0
  181. package/dist/core/events/v3/economics.d.ts +77 -0
  182. package/dist/core/events/v3/economics.d.ts.map +1 -0
  183. package/dist/core/events/v3/economics.js +274 -0
  184. package/dist/core/events/v3/finalization-view.d.ts +26 -0
  185. package/dist/core/events/v3/finalization-view.d.ts.map +1 -0
  186. package/dist/core/events/v3/finalization-view.js +37 -0
  187. package/dist/core/events/v3/fingerprint-keys.d.ts +25 -0
  188. package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -0
  189. package/dist/core/events/v3/fingerprint-keys.js +217 -0
  190. package/dist/core/events/v3/generated.d.ts +4 -0
  191. package/dist/core/events/v3/generated.d.ts.map +1 -0
  192. package/dist/core/events/v3/generated.js +47 -0
  193. package/dist/core/events/v3/ids.d.ts +9 -0
  194. package/dist/core/events/v3/ids.d.ts.map +1 -0
  195. package/dist/core/events/v3/ids.js +25 -0
  196. package/dist/core/events/v3/index.d.ts +35 -0
  197. package/dist/core/events/v3/index.d.ts.map +1 -0
  198. package/dist/core/events/v3/index.js +33 -0
  199. package/dist/core/events/v3/latency.d.ts +63 -0
  200. package/dist/core/events/v3/latency.d.ts.map +1 -0
  201. package/dist/core/events/v3/latency.js +412 -0
  202. package/dist/core/events/v3/live-feed.d.ts +45 -0
  203. package/dist/core/events/v3/live-feed.d.ts.map +1 -0
  204. package/dist/core/events/v3/live-feed.js +246 -0
  205. package/dist/core/events/v3/live-observation.d.ts +35 -0
  206. package/dist/core/events/v3/live-observation.d.ts.map +1 -0
  207. package/dist/core/events/v3/live-observation.js +1 -0
  208. package/dist/core/events/v3/live-routing.d.ts +57 -0
  209. package/dist/core/events/v3/live-routing.d.ts.map +1 -0
  210. package/dist/core/events/v3/live-routing.js +107 -0
  211. package/dist/core/events/v3/producers/command-recorder.d.ts +67 -0
  212. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -0
  213. package/dist/core/events/v3/producers/command-recorder.js +477 -0
  214. package/dist/core/events/v3/producers/command.d.ts +50 -0
  215. package/dist/core/events/v3/producers/command.d.ts.map +1 -0
  216. package/dist/core/events/v3/producers/command.js +135 -0
  217. package/dist/core/events/v3/producers/coordination-recorder.d.ts +53 -0
  218. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -0
  219. package/dist/core/events/v3/producers/coordination-recorder.js +376 -0
  220. package/dist/core/events/v3/producers/coordination.d.ts +90 -0
  221. package/dist/core/events/v3/producers/coordination.d.ts.map +1 -0
  222. package/dist/core/events/v3/producers/coordination.js +229 -0
  223. package/dist/core/events/v3/producers/hook-base.d.ts +54 -0
  224. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -0
  225. package/dist/core/events/v3/producers/hook-base.js +424 -0
  226. package/dist/core/events/v3/producers/hook.d.ts +29 -0
  227. package/dist/core/events/v3/producers/hook.d.ts.map +1 -0
  228. package/dist/core/events/v3/producers/hook.js +71 -0
  229. package/dist/core/events/v3/producers/intake.d.ts +65 -0
  230. package/dist/core/events/v3/producers/intake.d.ts.map +1 -0
  231. package/dist/core/events/v3/producers/intake.js +244 -0
  232. package/dist/core/events/v3/producers/recorder.d.ts +240 -0
  233. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -0
  234. package/dist/core/events/v3/producers/recorder.js +2176 -0
  235. package/dist/core/events/v3/projection.d.ts +101 -0
  236. package/dist/core/events/v3/projection.d.ts.map +1 -0
  237. package/dist/core/events/v3/projection.js +479 -0
  238. package/dist/core/events/v3/reader.d.ts +75 -0
  239. package/dist/core/events/v3/reader.d.ts.map +1 -0
  240. package/dist/core/events/v3/reader.js +778 -0
  241. package/dist/core/events/v3/recovery-record.d.ts +47 -0
  242. package/dist/core/events/v3/recovery-record.d.ts.map +1 -0
  243. package/dist/core/events/v3/recovery-record.js +167 -0
  244. package/dist/core/events/v3/recovery.d.ts +22 -0
  245. package/dist/core/events/v3/recovery.d.ts.map +1 -0
  246. package/dist/core/events/v3/recovery.js +227 -0
  247. package/dist/core/events/v3/span-state.d.ts +52 -0
  248. package/dist/core/events/v3/span-state.d.ts.map +1 -0
  249. package/dist/core/events/v3/span-state.js +142 -0
  250. package/dist/core/events/v3/targets.d.ts +23 -0
  251. package/dist/core/events/v3/targets.d.ts.map +1 -0
  252. package/dist/core/events/v3/targets.js +134 -0
  253. package/dist/core/events/v3/turn-telemetry.d.ts +41 -0
  254. package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -0
  255. package/dist/core/events/v3/turn-telemetry.js +168 -0
  256. package/dist/core/events/v3/validate.d.ts +9 -0
  257. package/dist/core/events/v3/validate.d.ts.map +1 -0
  258. package/dist/core/events/v3/validate.js +281 -0
  259. package/dist/core/events/v3/writer.d.ts +56 -0
  260. package/dist/core/events/v3/writer.d.ts.map +1 -0
  261. package/dist/core/events/v3/writer.js +335 -0
  262. package/dist/core/governor/index.d.ts +1 -1
  263. package/dist/core/governor/index.d.ts.map +1 -1
  264. package/dist/core/governor/index.js +1 -1
  265. package/dist/core/governor/plan-api.d.ts +2 -1
  266. package/dist/core/governor/plan-api.d.ts.map +1 -1
  267. package/dist/core/governor/plan-api.js +6 -3
  268. package/dist/core/governor/read.d.ts +1 -1
  269. package/dist/core/governor/read.d.ts.map +1 -1
  270. package/dist/core/governor/read.js +1 -1
  271. package/dist/core/governor/state.d.ts +9 -0
  272. package/dist/core/governor/state.d.ts.map +1 -1
  273. package/dist/core/governor/state.js +40 -3
  274. package/dist/core/guard/config.d.ts +5 -0
  275. package/dist/core/guard/config.d.ts.map +1 -0
  276. package/dist/core/guard/config.js +157 -0
  277. package/dist/core/guard/coordinator.d.ts +14 -0
  278. package/dist/core/guard/coordinator.d.ts.map +1 -0
  279. package/dist/core/guard/coordinator.js +173 -0
  280. package/dist/core/guard/evaluator.d.ts +4 -0
  281. package/dist/core/guard/evaluator.d.ts.map +1 -0
  282. package/dist/core/guard/evaluator.js +242 -0
  283. package/dist/core/guard/evidence-v3.d.ts +15 -0
  284. package/dist/core/guard/evidence-v3.d.ts.map +1 -0
  285. package/dist/core/guard/evidence-v3.js +171 -0
  286. package/dist/core/guard/index.d.ts +10 -0
  287. package/dist/core/guard/index.d.ts.map +1 -0
  288. package/dist/core/guard/index.js +6 -0
  289. package/dist/core/guard/live-source-v3.d.ts +40 -0
  290. package/dist/core/guard/live-source-v3.d.ts.map +1 -0
  291. package/dist/core/guard/live-source-v3.js +128 -0
  292. package/dist/core/guard/storage.d.ts +27 -0
  293. package/dist/core/guard/storage.d.ts.map +1 -0
  294. package/dist/core/guard/storage.js +140 -0
  295. package/dist/core/guard/types.d.ts +119 -0
  296. package/dist/core/guard/types.d.ts.map +1 -0
  297. package/dist/core/guard/types.js +1 -0
  298. package/dist/core/hooks/adapter/detect.d.ts +18 -1
  299. package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
  300. package/dist/core/hooks/adapter/detect.js +29 -0
  301. package/dist/core/hooks/adapter/events.d.ts +7 -4
  302. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  303. package/dist/core/hooks/adapter/events.js +13 -4
  304. package/dist/core/hooks/adapter/output.d.ts +2 -2
  305. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  306. package/dist/core/hooks/adapter/parse.d.ts +7 -4
  307. package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
  308. package/dist/core/hooks/adapter/parse.js +64 -24
  309. package/dist/core/hooks/adapter/wiring.d.ts +30 -4
  310. package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
  311. package/dist/core/hooks/adapter/wiring.js +89 -11
  312. package/dist/core/hooks/cli.d.ts +1 -1
  313. package/dist/core/hooks/cli.js +345 -400
  314. package/dist/core/hooks/codex-authorization.d.ts +30 -0
  315. package/dist/core/hooks/codex-authorization.d.ts.map +1 -0
  316. package/dist/core/hooks/codex-authorization.js +199 -0
  317. package/dist/core/hooks/effects/image-capture.d.ts +20 -34
  318. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  319. package/dist/core/hooks/effects/image-capture.js +212 -221
  320. package/dist/core/hooks/effects/index.d.ts +1 -9
  321. package/dist/core/hooks/effects/index.d.ts.map +1 -1
  322. package/dist/core/hooks/effects/index.js +1 -24
  323. package/dist/core/hooks/events/input-hash.d.ts +7 -0
  324. package/dist/core/hooks/events/input-hash.d.ts.map +1 -0
  325. package/dist/core/hooks/events/input-hash.js +43 -0
  326. package/dist/core/hooks/index.d.ts +4 -3
  327. package/dist/core/hooks/index.d.ts.map +1 -1
  328. package/dist/core/hooks/index.js +2 -3
  329. package/dist/core/hooks/resolve/coord-root.d.ts +1 -1
  330. package/dist/core/hooks/resolve/coord-root.js +1 -1
  331. package/dist/core/hooks/resolve/owner.d.ts +16 -15
  332. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  333. package/dist/core/hooks/resolve/owner.js +51 -42
  334. package/dist/core/hooks/resolve/transcript.d.ts +33 -3
  335. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  336. package/dist/core/hooks/resolve/transcript.js +155 -14
  337. package/dist/core/hooks/session-name-presence.d.ts +9 -10
  338. package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
  339. package/dist/core/hooks/session-name-presence.js +15 -15
  340. package/dist/core/hooks/unsafe-cross-shell.d.ts +1 -1
  341. package/dist/core/hooks/unsafe-cross-shell.d.ts.map +1 -1
  342. package/dist/core/journal/index.d.ts +2 -2
  343. package/dist/core/journal/index.d.ts.map +1 -1
  344. package/dist/core/journal/index.js +9 -22
  345. package/dist/core/presence/blob.d.ts +8 -3
  346. package/dist/core/presence/blob.d.ts.map +1 -1
  347. package/dist/core/presence/blob.js +54 -41
  348. package/dist/core/presence/codec-digest.d.ts +29 -0
  349. package/dist/core/presence/codec-digest.d.ts.map +1 -0
  350. package/dist/core/presence/codec-digest.js +170 -0
  351. package/dist/core/presence/index.js +15 -1
  352. package/dist/core/presence/relay-client.d.ts +1 -1
  353. package/dist/core/presence/relay-client.d.ts.map +1 -1
  354. package/dist/core/presence/relay-client.js +5 -5
  355. package/dist/core/work/index.d.ts +1 -1
  356. package/dist/core/work/index.d.ts.map +1 -1
  357. package/dist/core/work/index.js +1 -1
  358. package/dist/core/work/read.d.ts +1 -1
  359. package/dist/core/work/read.d.ts.map +1 -1
  360. package/dist/core/work/read.js +1 -1
  361. package/dist/core/work/runner.d.ts.map +1 -1
  362. package/dist/core/work/runner.js +6 -0
  363. package/dist/core/work/state.d.ts +9 -0
  364. package/dist/core/work/state.d.ts.map +1 -1
  365. package/dist/core/work/state.js +17 -3
  366. package/dist/core/workflow/engine.js +24 -25
  367. package/dist/core/workflow/live-session-v3.d.ts +19 -0
  368. package/dist/core/workflow/live-session-v3.d.ts.map +1 -0
  369. package/dist/core/workflow/live-session-v3.js +86 -0
  370. package/dist/core/workflow/scope-id.d.ts +3 -0
  371. package/dist/core/workflow/scope-id.d.ts.map +1 -0
  372. package/dist/core/workflow/scope-id.js +5 -0
  373. package/dist/core/workflow/workspaces/leases.d.ts +4 -0
  374. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  375. package/dist/core/workflow/workspaces/leases.js +53 -19
  376. package/dist/index.d.ts +1 -1
  377. package/dist/index.js +1 -1
  378. package/dist/lib/browser/client.d.ts +41 -0
  379. package/dist/lib/browser/client.d.ts.map +1 -1
  380. package/dist/lib/browser/client.js +203 -0
  381. package/dist/lib/browser/critique.d.ts +28 -2
  382. package/dist/lib/browser/critique.d.ts.map +1 -1
  383. package/dist/lib/browser/critique.js +74 -18
  384. package/dist/lib/browser/geometry.d.ts +1 -1
  385. package/dist/lib/browser/geometry.d.ts.map +1 -1
  386. package/dist/lib/browser/geometry.js +130 -6
  387. package/dist/lib/browser/index.d.ts +3 -0
  388. package/dist/lib/browser/index.d.ts.map +1 -1
  389. package/dist/lib/browser/index.js +3 -0
  390. package/dist/lib/browser/qa-plan.d.ts +174 -0
  391. package/dist/lib/browser/qa-plan.d.ts.map +1 -0
  392. package/dist/lib/browser/qa-plan.js +321 -0
  393. package/dist/lib/browser/qa-reuse.d.ts +99 -0
  394. package/dist/lib/browser/qa-reuse.d.ts.map +1 -0
  395. package/dist/lib/browser/qa-reuse.js +222 -0
  396. package/dist/lib/browser/qa-snapshot.d.ts +64 -0
  397. package/dist/lib/browser/qa-snapshot.d.ts.map +1 -0
  398. package/dist/lib/browser/qa-snapshot.js +171 -0
  399. package/dist/lib/browser/runts.d.ts.map +1 -1
  400. package/dist/lib/browser/runts.js +22 -1
  401. package/dist/lib/browser/tiling.d.ts +71 -0
  402. package/dist/lib/browser/tiling.d.ts.map +1 -0
  403. package/dist/lib/browser/tiling.js +118 -0
  404. package/dist/lib/context/index.d.ts +0 -3
  405. package/dist/lib/context/index.d.ts.map +1 -1
  406. package/dist/lib/context/index.js +20 -42
  407. package/dist/lib/council/index.d.ts +2 -2
  408. package/dist/lib/council/index.d.ts.map +1 -1
  409. package/dist/lib/council/index.js +9 -20
  410. package/dist/lib/docs-frontmatter.d.ts +1 -6
  411. package/dist/lib/docs-frontmatter.d.ts.map +1 -1
  412. package/dist/lib/docs-frontmatter.js +12 -78
  413. package/dist/lib/docs-index.d.ts +9 -0
  414. package/dist/lib/docs-index.d.ts.map +1 -1
  415. package/dist/lib/docs-index.js +32 -3
  416. package/dist/lib/docs-lint.d.ts.map +1 -1
  417. package/dist/lib/docs-lint.js +14 -30
  418. package/dist/lib/docs-metadata-audit.d.ts +19 -0
  419. package/dist/lib/docs-metadata-audit.d.ts.map +1 -0
  420. package/dist/lib/docs-metadata-audit.js +132 -0
  421. package/dist/lib/docs-metadata-managed.d.ts +23 -0
  422. package/dist/lib/docs-metadata-managed.d.ts.map +1 -0
  423. package/dist/lib/docs-metadata-managed.js +78 -0
  424. package/dist/lib/docs-metadata-sync.d.ts +20 -0
  425. package/dist/lib/docs-metadata-sync.d.ts.map +1 -0
  426. package/dist/lib/docs-metadata-sync.js +222 -0
  427. package/dist/lib/docs-metadata-v2-schema.d.ts +273 -0
  428. package/dist/lib/docs-metadata-v2-schema.d.ts.map +1 -0
  429. package/dist/lib/docs-metadata-v2-schema.js +134 -0
  430. package/dist/lib/docs-metadata-v2.d.ts +21 -0
  431. package/dist/lib/docs-metadata-v2.d.ts.map +1 -0
  432. package/dist/lib/docs-metadata-v2.js +424 -0
  433. package/dist/lib/docs-new.d.ts +11 -0
  434. package/dist/lib/docs-new.d.ts.map +1 -0
  435. package/dist/lib/docs-new.js +52 -0
  436. package/dist/lib/docs-sweep.d.ts.map +1 -1
  437. package/dist/lib/docs-sweep.js +45 -29
  438. package/dist/lib/headless/index.d.ts +98 -0
  439. package/dist/lib/headless/index.d.ts.map +1 -0
  440. package/dist/lib/headless/index.js +211 -0
  441. package/dist/lib/identities/assume.d.ts +4 -4
  442. package/dist/lib/identities/assume.d.ts.map +1 -1
  443. package/dist/lib/identities/assume.js +52 -68
  444. package/dist/lib/instructions/apply.d.ts +5 -4
  445. package/dist/lib/instructions/apply.d.ts.map +1 -1
  446. package/dist/lib/instructions/apply.js +32 -20
  447. package/dist/lib/instructions/bundle.d.ts +33 -0
  448. package/dist/lib/instructions/bundle.d.ts.map +1 -0
  449. package/dist/lib/instructions/bundle.js +149 -0
  450. package/dist/lib/instructions/splice.d.ts +0 -1
  451. package/dist/lib/instructions/splice.d.ts.map +1 -1
  452. package/dist/lib/instructions/splice.js +22 -6
  453. package/dist/lib/instructions/templates.d.ts +7 -5
  454. package/dist/lib/instructions/templates.d.ts.map +1 -1
  455. package/dist/lib/instructions/templates.js +79 -9
  456. package/package.json +27 -6
  457. package/schemas/config.schema.json +120 -2
  458. package/schemas/docs-metadata-v2.schema.json +441 -0
  459. package/schemas/event-v3.schema.json +24472 -0
  460. package/src/commander.ts +7 -1
  461. package/src/commands/adapter.ts +2 -2
  462. package/src/commands/agents.ts +1737 -570
  463. package/src/commands/artifacts.ts +7 -6
  464. package/src/commands/backup.ts +29 -21
  465. package/src/commands/browse.ts +349 -8
  466. package/src/commands/checkpoint.ts +4 -3
  467. package/src/commands/claude-desktop.ts +7 -5
  468. package/src/commands/context.ts +1 -6
  469. package/src/commands/decision.ts +27 -44
  470. package/src/commands/docs.ts +100 -33
  471. package/src/commands/doctor.ts +73 -8
  472. package/src/commands/events.ts +256 -0
  473. package/src/commands/governor.ts +18 -4
  474. package/src/commands/init.ts +264 -57
  475. package/src/commands/instructions.ts +129 -0
  476. package/src/commands/journal.ts +4 -13
  477. package/src/commands/ledger-v3.ts +111 -0
  478. package/src/commands/presence.ts +18 -11
  479. package/src/commands/sync.ts +1 -1
  480. package/src/commands/web.ts +67 -8
  481. package/src/commands/work.ts +28 -5
  482. package/src/core/adapter.ts +5 -0
  483. package/src/core/adapters/attest.ts +8 -3
  484. package/src/core/adapters/profiles.ts +4 -6
  485. package/src/core/agents/canonical-emit.ts +39 -28
  486. package/src/core/agents/cli.ts +242 -263
  487. package/src/core/agents/codex-archive-v3.ts +138 -0
  488. package/src/core/agents/coord-client.ts +75 -177
  489. package/src/core/agents/finalization.ts +120 -38
  490. package/src/core/agents/index.ts +5 -5
  491. package/src/core/agents/live-authority-v3.ts +375 -0
  492. package/src/core/agents/live-lifecycle-v3.ts +140 -0
  493. package/src/core/agents/live-observation-v3.ts +216 -0
  494. package/src/core/agents/render/prompt-context.ts +89 -55
  495. package/src/core/agents/render/session-context.ts +23 -32
  496. package/src/core/agents/rules/claim-conflict.ts +85 -126
  497. package/src/core/agents/rules/commit-conflict.ts +3 -14
  498. package/src/core/agents/rules/stop-hook.ts +239 -293
  499. package/src/core/agents/session-events.ts +137 -104
  500. package/src/core/agents/session-finalization-state-v3.ts +90 -0
  501. package/src/core/agents/session-finalizer-v3.ts +953 -0
  502. package/src/core/agents/session-name-display.ts +149 -0
  503. package/src/core/agents/state/activity-log.ts +6 -14
  504. package/src/core/agents/state/heartbeat-writer.ts +98 -242
  505. package/src/core/agents/state/live-coordination-view.ts +290 -0
  506. package/src/core/agents/state/session-state.ts +143 -0
  507. package/src/core/agents/state/stale-sweep.ts +40 -17
  508. package/src/core/artifacts/index.ts +4 -5
  509. package/src/core/config.ts +148 -3
  510. package/src/core/context/index.ts +9 -17
  511. package/src/core/events/span-parent.ts +46 -0
  512. package/src/core/events/v3/advance.ts +168 -0
  513. package/src/core/events/v3/authority-outbox.ts +548 -0
  514. package/src/core/events/v3/base-builder.ts +60 -0
  515. package/src/core/events/v3/base-contract.ts +882 -0
  516. package/src/core/events/v3/bootstrap.ts +226 -0
  517. package/src/core/events/v3/builder.ts +59 -0
  518. package/src/core/events/v3/canonical.ts +153 -0
  519. package/src/core/events/v3/capabilities.ts +171 -0
  520. package/src/core/events/v3/capability-drift.ts +177 -0
  521. package/src/core/events/v3/catalog.ts +202 -0
  522. package/src/core/events/v3/clock-order.ts +41 -0
  523. package/src/core/events/v3/contract.ts +365 -0
  524. package/src/core/events/v3/control.ts +576 -0
  525. package/src/core/events/v3/coordination-view.ts +193 -0
  526. package/src/core/events/v3/economics.ts +384 -0
  527. package/src/core/events/v3/finalization-view.ts +67 -0
  528. package/src/core/events/v3/fingerprint-keys.ts +260 -0
  529. package/src/core/events/v3/generated.ts +48 -0
  530. package/src/core/events/v3/ids.ts +33 -0
  531. package/src/core/events/v3/index.ts +322 -0
  532. package/src/core/events/v3/latency.ts +551 -0
  533. package/src/core/events/v3/live-feed.ts +319 -0
  534. package/src/core/events/v3/live-observation.ts +39 -0
  535. package/src/core/events/v3/live-routing.ts +135 -0
  536. package/src/core/events/v3/producers/command-recorder.ts +631 -0
  537. package/src/core/events/v3/producers/command.ts +201 -0
  538. package/src/core/events/v3/producers/coordination-recorder.ts +538 -0
  539. package/src/core/events/v3/producers/coordination.ts +355 -0
  540. package/src/core/events/v3/producers/hook-base.ts +578 -0
  541. package/src/core/events/v3/producers/hook.ts +119 -0
  542. package/src/core/events/v3/producers/intake.ts +319 -0
  543. package/src/core/events/v3/producers/recorder.ts +2805 -0
  544. package/src/core/events/v3/projection.ts +653 -0
  545. package/src/core/events/v3/reader.ts +1127 -0
  546. package/src/core/events/v3/recovery-record.ts +244 -0
  547. package/src/core/events/v3/recovery.ts +271 -0
  548. package/src/core/events/v3/span-state.ts +187 -0
  549. package/src/core/events/v3/targets.ts +182 -0
  550. package/src/core/events/v3/turn-telemetry.ts +259 -0
  551. package/src/core/events/v3/validate.ts +361 -0
  552. package/src/core/events/v3/writer.ts +419 -0
  553. package/src/core/governor/index.ts +3 -0
  554. package/src/core/governor/plan-api.ts +10 -2
  555. package/src/core/governor/read.ts +3 -0
  556. package/src/core/governor/state.ts +52 -5
  557. package/src/core/guard/config.ts +206 -0
  558. package/src/core/guard/coordinator.ts +227 -0
  559. package/src/core/guard/evaluator.ts +343 -0
  560. package/src/core/guard/evidence-v3.ts +227 -0
  561. package/src/core/guard/index.ts +35 -0
  562. package/src/core/guard/live-source-v3.ts +204 -0
  563. package/src/core/guard/storage.ts +188 -0
  564. package/src/core/guard/types.ts +152 -0
  565. package/src/core/hooks/adapter/detect.ts +28 -1
  566. package/src/core/hooks/adapter/events.ts +15 -6
  567. package/src/core/hooks/adapter/output.ts +7 -2
  568. package/src/core/hooks/adapter/parse.ts +81 -36
  569. package/src/core/hooks/adapter/wiring.ts +119 -13
  570. package/src/core/hooks/cli.ts +398 -422
  571. package/src/core/hooks/codex-authorization.ts +253 -0
  572. package/src/core/hooks/effects/image-capture.ts +228 -238
  573. package/src/core/hooks/effects/index.ts +1 -36
  574. package/src/core/hooks/events/input-hash.ts +47 -0
  575. package/src/core/hooks/index.ts +4 -11
  576. package/src/core/hooks/resolve/coord-root.ts +1 -1
  577. package/src/core/hooks/resolve/owner.ts +52 -45
  578. package/src/core/hooks/resolve/transcript.ts +165 -14
  579. package/src/core/hooks/session-name-presence.ts +14 -15
  580. package/src/core/hooks/unsafe-cross-shell.ts +1 -1
  581. package/src/core/journal/index.ts +15 -22
  582. package/src/core/presence/blob.ts +63 -38
  583. package/src/core/presence/codec-digest.ts +215 -0
  584. package/src/core/presence/index.ts +18 -1
  585. package/src/core/presence/relay-client.ts +5 -5
  586. package/src/core/work/index.ts +3 -0
  587. package/src/core/work/read.ts +3 -0
  588. package/src/core/work/runner.ts +6 -0
  589. package/src/core/work/state.ts +27 -3
  590. package/src/core/workflow/engine.ts +24 -24
  591. package/src/core/workflow/live-session-v3.ts +126 -0
  592. package/src/core/workflow/scope-id.ts +6 -0
  593. package/src/core/workflow/workspaces/leases.ts +56 -19
  594. package/src/index.ts +1 -1
  595. package/src/lib/browser/client.ts +230 -0
  596. package/src/lib/browser/critique.ts +104 -27
  597. package/src/lib/browser/geometry.ts +143 -14
  598. package/src/lib/browser/index.ts +34 -0
  599. package/src/lib/browser/qa-plan.ts +501 -0
  600. package/src/lib/browser/qa-reuse.ts +306 -0
  601. package/src/lib/browser/qa-snapshot.ts +223 -0
  602. package/src/lib/browser/runts.ts +27 -2
  603. package/src/lib/browser/tiling.ts +164 -0
  604. package/src/lib/context/index.ts +22 -46
  605. package/src/lib/council/index.ts +9 -21
  606. package/src/lib/docs-frontmatter.ts +8 -79
  607. package/src/lib/docs-index.ts +33 -3
  608. package/src/lib/docs-lint.ts +15 -29
  609. package/src/lib/docs-metadata-audit.ts +166 -0
  610. package/src/lib/docs-metadata-managed.ts +83 -0
  611. package/src/lib/docs-metadata-sync.ts +262 -0
  612. package/src/lib/docs-metadata-v2-schema.ts +138 -0
  613. package/src/lib/docs-metadata-v2.ts +646 -0
  614. package/src/lib/docs-new.ts +63 -0
  615. package/src/lib/docs-sweep.ts +42 -28
  616. package/src/lib/headless/index.ts +287 -0
  617. package/src/lib/identities/assume.ts +67 -86
  618. package/src/lib/instructions/apply.ts +33 -20
  619. package/src/lib/instructions/bundle.ts +199 -0
  620. package/src/lib/instructions/splice.ts +21 -7
  621. package/src/lib/instructions/templates.ts +85 -13
  622. package/dist/core/agents/cli-emit.d.ts +0 -27
  623. package/dist/core/agents/cli-emit.d.ts.map +0 -1
  624. package/dist/core/agents/cli-emit.js +0 -57
  625. package/dist/core/agents/codex-replay.d.ts +0 -29
  626. package/dist/core/agents/codex-replay.d.ts.map +0 -1
  627. package/dist/core/agents/codex-replay.js +0 -138
  628. package/dist/core/agents/events/consume.d.ts +0 -82
  629. package/dist/core/agents/events/consume.d.ts.map +0 -1
  630. package/dist/core/agents/events/consume.js +0 -195
  631. package/dist/core/agents/events/emit.d.ts +0 -42
  632. package/dist/core/agents/events/emit.d.ts.map +0 -1
  633. package/dist/core/agents/events/emit.js +0 -75
  634. package/dist/core/agents/events/ulid.d.ts +0 -11
  635. package/dist/core/agents/events/ulid.d.ts.map +0 -1
  636. package/dist/core/agents/events/ulid.js +0 -47
  637. package/dist/core/agents/state/heartbeat-projector.d.ts +0 -65
  638. package/dist/core/agents/state/heartbeat-projector.d.ts.map +0 -1
  639. package/dist/core/agents/state/heartbeat-projector.js +0 -527
  640. package/dist/core/hooks/events/emit.d.ts +0 -31
  641. package/dist/core/hooks/events/emit.d.ts.map +0 -1
  642. package/dist/core/hooks/events/emit.js +0 -93
  643. package/dist/core/hooks/events/rotate.d.ts +0 -43
  644. package/dist/core/hooks/events/rotate.d.ts.map +0 -1
  645. package/dist/core/hooks/events/rotate.js +0 -142
  646. package/dist/core/hooks/events/schema.d.ts +0 -312
  647. package/dist/core/hooks/events/schema.d.ts.map +0 -1
  648. package/dist/core/hooks/events/schema.js +0 -12
  649. package/dist/core/hooks/events/ulid.d.ts +0 -10
  650. package/dist/core/hooks/events/ulid.d.ts.map +0 -1
  651. package/dist/core/hooks/events/ulid.js +0 -47
  652. package/dist/lib/docs-frontmatter-migrate.d.ts +0 -33
  653. package/dist/lib/docs-frontmatter-migrate.d.ts.map +0 -1
  654. package/dist/lib/docs-frontmatter-migrate.js +0 -364
  655. package/src/core/agents/cli-emit.ts +0 -64
  656. package/src/core/agents/codex-replay.ts +0 -163
  657. package/src/core/agents/events/consume.ts +0 -254
  658. package/src/core/agents/events/emit.ts +0 -115
  659. package/src/core/agents/events/ulid.ts +0 -51
  660. package/src/core/agents/state/heartbeat-projector.ts +0 -582
  661. package/src/core/hooks/events/emit.ts +0 -125
  662. package/src/core/hooks/events/rotate.ts +0 -151
  663. package/src/core/hooks/events/schema.ts +0 -538
  664. package/src/core/hooks/events/ulid.ts +0 -51
  665. package/src/lib/docs-frontmatter-migrate.ts +0 -427
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The suggested session name is a small display protocol, not ordinary prose.
3
+ * Keep its exact block and pending-state rules in one adapter-neutral module so
4
+ * prompt context, PostToolUse injection, and PreToolUse enforcement cannot
5
+ * drift apart.
6
+ */
7
+
8
+ export interface SessionNameDisplayState {
9
+ suggested_session_name?: string;
10
+ session_name_seen_for?: string;
11
+ }
12
+
13
+ export const SESSION_NAME_DISPLAY_NOTE =
14
+ "Next, before any prose or another tool call, send suggested_session_name verbatim by itself in a fenced code block.";
15
+
16
+ export function sessionNameDisplayPending(
17
+ row: SessionNameDisplayState | null | undefined,
18
+ ): string | null {
19
+ const name = row?.suggested_session_name;
20
+ if (!name || row?.session_name_seen_for === name) return null;
21
+ return name;
22
+ }
23
+
24
+ export function sessionNameDisplayBlock(name: string): string {
25
+ return `\`\`\`\n${name}\n\`\`\``;
26
+ }
27
+
28
+ export function sessionNameDisplayInstruction(name: string): string {
29
+ return [
30
+ "Session name display required.",
31
+ "Before any prose or another tool call, send this exact fenced block as your next assistant text:",
32
+ "",
33
+ sessionNameDisplayBlock(name),
34
+ "",
35
+ "Do not put commentary before the block. Harnery will reject tool calls until it is shown.",
36
+ ].join("\n");
37
+ }
38
+
39
+ /**
40
+ * A PostToolUse result should announce the display protocol only when that
41
+ * exact tool call minted the current suggestion. The coordination row keeps
42
+ * the suggestion pending until transcript evidence catches up, so checking
43
+ * the row alone would re-announce the same name after every later tool.
44
+ *
45
+ * Adapter responses vary between a direct command envelope and wrapper
46
+ * objects whose `output`/content field contains the JSON as one line. Walk
47
+ * both shapes, but require the command's explicit mint flag as well as the
48
+ * exact current name. Ordinary status output can carry the name without
49
+ * activating the display ritual.
50
+ */
51
+ export function toolResponseMintedSessionName(response: unknown, name: string): boolean {
52
+ if (!name) return false;
53
+ return responseContainsSessionNameMint(response, name, new Set<object>(), 0);
54
+ }
55
+
56
+ function responseContainsSessionNameMint(
57
+ value: unknown,
58
+ name: string,
59
+ seen: Set<object>,
60
+ depth: number,
61
+ ): boolean {
62
+ if (depth > 8 || value === null || value === undefined) return false;
63
+
64
+ if (typeof value === "string") {
65
+ const candidates = [value.trim(), ...value.split(/\r?\n/).map((line) => line.trim())];
66
+ for (const candidate of candidates) {
67
+ if (!candidate.startsWith("{") && !candidate.startsWith("[")) continue;
68
+ try {
69
+ if (
70
+ responseContainsSessionNameMint(JSON.parse(candidate) as unknown, name, seen, depth + 1)
71
+ ) {
72
+ return true;
73
+ }
74
+ } catch {
75
+ // Wrapper prose and partial JSON are not authoritative mint evidence.
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+
81
+ if (typeof value !== "object") return false;
82
+ if (seen.has(value)) return false;
83
+ seen.add(value);
84
+
85
+ if (Array.isArray(value)) {
86
+ return value.some((item) => responseContainsSessionNameMint(item, name, seen, depth + 1));
87
+ }
88
+
89
+ const row = value as Record<string, unknown>;
90
+ if (
91
+ row.suggested_session_name === name &&
92
+ (row.first_of_session === true || row.name_reminted === true)
93
+ ) {
94
+ return true;
95
+ }
96
+
97
+ return Object.values(row).some((item) =>
98
+ responseContainsSessionNameMint(item, name, seen, depth + 1),
99
+ );
100
+ }
101
+
102
+ /**
103
+ * Accept the exact unlabelled block Harnery requests. `text` and `plaintext`
104
+ * are tolerated for older prompts, but the code block may contain only the
105
+ * suggested name and must be the first non-whitespace user-facing content.
106
+ */
107
+ export function assistantTextStartsWithSessionNameBlock(text: string, name: string): boolean {
108
+ if (!text || !name) return false;
109
+ const normalized = text.replace(/\r\n?/g, "\n").trimStart();
110
+ const match = /^```(?:text|plaintext)?[ \t]*\n([^\n]*)\n```(?:[ \t]*(?:\n|$))/.exec(normalized);
111
+ return match?.[1] === name;
112
+ }
113
+
114
+ /**
115
+ * A trailing stream redirect to `/dev/null` or another descriptor. Agents append
116
+ * these habitually when capturing output, and unlike a pipe or `&&` they cannot
117
+ * smuggle a second command, so they must not disable the remediation exemption
118
+ * below. Deliberately excludes redirects to a named file.
119
+ */
120
+ const BENIGN_REDIRECT_SUFFIX = /\s*[012]?>>?\s*(?:&[012]|\/dev\/null)\s*$/;
121
+
122
+ /**
123
+ * The display latch must not block the two coordination commands that can
124
+ * repair a turn or close it cleanly. Keep this intentionally narrower than
125
+ * "any harn command" and reject shell control syntax before matching.
126
+ */
127
+ export function isSessionNameRemediationCommand(
128
+ command: string | undefined,
129
+ binName: string,
130
+ ): boolean {
131
+ if (!command || !binName) return false;
132
+ let body = command.replace(/^(?:[ \t]*#\s*intent:[^\n]*\n)+/i, "").trim();
133
+
134
+ // Strip benign trailing redirects before the control-syntax check. Without
135
+ // this, `<bin> agents status --end-turn 2>&1` fails the `&` test, which
136
+ // disables the one exemption that can close a latched turn and leaves the
137
+ // session unable to satisfy either the latch or the end-of-turn rule.
138
+ for (let next = body.replace(BENIGN_REDIRECT_SUFFIX, "").trim(); next !== body; ) {
139
+ body = next;
140
+ next = body.replace(BENIGN_REDIRECT_SUFFIX, "").trim();
141
+ }
142
+
143
+ if (!body || /[\n;&|<>`$]/.test(body)) return false;
144
+ const escapedBin = binName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
145
+ const pattern = new RegExp(
146
+ `^(?:codex-wsl\\s+--\\s+)?${escapedBin}\\s+agents\\s+(?:set-task|status)(?:\\s+.*)?$`,
147
+ );
148
+ return pattern.test(body);
149
+ }
@@ -2,32 +2,24 @@
2
2
  * Display-name resolution for the coord layer.
3
3
  *
4
4
  * This module once housed `coordLog`, the writer for a human-readable
5
- * activity log. That log has been retired; the canonical
6
- * `.harnery/events.ndjson` stream is the single source of truth, and the
5
+ * activity log. That log has been retired; the canonical V3 ledger is the
6
+ * single source of truth, and the
7
7
  * per-event telemetry that had consumers (heals → health.*, councils →
8
8
  * council.*, shell-mutation candidates → decision.warn) is emitted there
9
9
  * directly. `coordLog` and its call sites are gone; only `resolveShortName`
10
10
  * remains (still used for display-name resolution).
11
11
  */
12
12
 
13
- import { existsSync, readFileSync } from "node:fs";
14
- import { join } from "node:path";
13
+ import { readLiveCoordinationRow } from "./live-coordination-view.ts";
15
14
 
16
15
  /**
17
- * Resolve `agent-<name>` display string. Looks up the heartbeat's `name`
16
+ * Resolve `agent-<name>` display string. Looks up the V3 projection's `name`
18
17
  * field; falls back to `agent-<8-char-hex>` if name is empty (mirrors bash
19
18
  * coord_owner_short). Returns `agent-unknown` when instanceId is null.
20
19
  */
21
20
  export function resolveShortName(coordRoot: string, instanceId: string | null): string {
22
21
  if (!instanceId) return "agent-unknown";
23
- const path = join(coordRoot, ".harnery", "active", `${instanceId}.json`);
24
- if (existsSync(path)) {
25
- try {
26
- const hb = JSON.parse(readFileSync(path, "utf8")) as { name?: string };
27
- if (hb.name && hb.name.length > 0) return `agent-${hb.name}`;
28
- } catch {
29
- /* fall through to short-id */
30
- }
31
- }
22
+ const row = readLiveCoordinationRow(coordRoot, instanceId);
23
+ if (row?.name) return `agent-${row.name}`;
32
24
  return `agent-${instanceId.slice(0, 8)}`;
33
25
  }
@@ -9,7 +9,8 @@
9
9
  * half-written intermediate. Concurrent writers serialize via the rename
10
10
  * (last write wins).
11
11
  *
12
- * Owner identity invariant: every action operates on `.harnery/active/<instance_id>.json`
12
+ * Cache identity invariant: every action operates on the generation-bound row at
13
+ * `.harnery/active/<instance_id>.json`; the canonical V3 ledger remains authoritative.
13
14
  * (the file IS the heartbeat). No mutations happen elsewhere.
14
15
  */
15
16
 
@@ -22,54 +23,9 @@ import {
22
23
  unlinkSync,
23
24
  writeFileSync,
24
25
  } from "node:fs";
25
- import { dirname, join } from "node:path";
26
- import { emit } from "../events/emit.ts";
27
-
28
- /** Inline adapter normalizer (mirrors canonical-emit.normalizeAdapter), kept
29
- * local so the writer's only cross-module dep is the in-process emit(). */
30
- function adapterOf(platform: string | undefined): "claude-code" | "cursor" | "codex" {
31
- if (platform === "cursor") return "cursor";
32
- if (platform === "codex") return "codex";
33
- return "claude-code";
34
- }
35
-
36
- /** Preserve the canonical adapter id in heartbeat state. Mirrors
37
- * heartbeat-projector.adapterToPlatform so a healed heartbeat carries the same
38
- * platform value projection would have written. */
39
- function adapterToPlatform(adapter: string | undefined): string {
40
- if (adapter === "cursor") return "cursor";
41
- if (adapter === "codex") return "codex";
42
- return "claude-code";
43
- }
44
-
45
- /**
46
- * Emit a canonical `health.*` event for an actual self-heal write. This is the
47
- * single source of truth for heal telemetry across BOTH the live auto-heal
48
- * (the pre-tool-use hook → agent-coord heal-heartbeat) and the manual `harn agents
49
- * heal` path. Write-only by construction (callers only invoke it after a real
50
- * write), so an already-correct heal records nothing.
51
- * Best-effort: never throws into the heal path.
52
- */
53
- function emitHealthHeal(
54
- coordRoot: string,
55
- type: "health.pidmap_heal" | "health.heartbeat_heal",
56
- instanceId: string,
57
- hb: Heartbeat | null,
58
- data: Record<string, unknown>,
59
- ): void {
60
- try {
61
- emit(coordRoot, {
62
- event_type: type,
63
- instance_id: instanceId,
64
- session_id: hb?.session_id ?? instanceId,
65
- adapter: adapterOf(hb?.platform),
66
- source: "agent-coord",
67
- data,
68
- });
69
- } catch {
70
- /* telemetry only, never break a heal */
71
- }
72
- }
26
+ import { basename, dirname, join } from "node:path";
27
+ import { assertSafeInstanceId, resolveContainedFile } from "../coord-client.ts";
28
+ import type { AgentActivity, TaskState } from "./session-state.ts";
73
29
 
74
30
  export interface Heartbeat {
75
31
  schema_version?: number;
@@ -78,6 +34,8 @@ export interface Heartbeat {
78
34
  kind?: string;
79
35
  agent_id?: string;
80
36
  session_id: string;
37
+ /** Native adapter session ID retained only in a generation-bound local projection. */
38
+ native_session_id?: string;
81
39
  subagent_call_id?: string;
82
40
  model?: string;
83
41
  platform?: string;
@@ -86,11 +44,17 @@ export interface Heartbeat {
86
44
  files_touched: string[];
87
45
  task?: string;
88
46
  task_updated_at?: string | null;
47
+ activity?: AgentActivity;
48
+ activity_updated_at?: string;
49
+ activity_source?: string;
50
+ task_state?: TaskState;
51
+ task_state_updated_at?: string;
52
+ task_state_reason?: string;
89
53
  /** Session name built on the first non-empty set-task (never rebuilt). Its
90
54
  * presence is the "this session has been named" signal the prompt-context
91
55
  * nudge and the Stop-hook naming rule key on. */
92
56
  suggested_session_name?: string;
93
- /** Stamped by turn.stop once the suggested name is seen in assistant reply
57
+ /** Stamped by turn.completed once the suggested name is seen in assistant reply
94
58
  * text, ending the per-turn transcript scan. */
95
59
  session_name_seen_at?: string;
96
60
  /** WHICH name that sighting was for. The scan is skipped only while this
@@ -98,19 +62,25 @@ export interface Heartbeat {
98
62
  * again rather than being suppressed by the earlier sighting. */
99
63
  session_name_seen_for?: string;
100
64
  last_status_at?: string;
101
- turn_summary?: string | null;
102
- turn_summary_updated_at?: string | null;
103
- last_tool?: string;
104
- last_tool_target?: string;
105
- last_tool_at?: string;
106
65
  current_turn_id?: string;
107
66
  parent_instance_id?: string;
108
67
  workflow_run_id?: string;
68
+ workflow_agent_id?: string;
69
+ /** Disposable-cache bindings that prove a row belongs to the current V3 generation. */
70
+ v3_instance_id?: `inst_${string}`;
71
+ v3_generation_id?: `gen_${string}`;
72
+ v3_projection_event_id?: string;
73
+ v3_task_state?: "set" | "cleared";
109
74
  [extra: string]: unknown;
110
75
  }
111
76
 
112
77
  function heartbeatPath(coordRoot: string, instanceId: string): string {
113
- return join(coordRoot, ".harnery", "active", `${instanceId}.json`);
78
+ assertSafeInstanceId(instanceId);
79
+ const safeInstanceId = basename(instanceId);
80
+ if (safeInstanceId !== instanceId) {
81
+ throw new Error("instance_id must be a direct-child coordination basename");
82
+ }
83
+ return resolveContainedFile(join(coordRoot, ".harnery", "active"), `${safeInstanceId}.json`);
114
84
  }
115
85
 
116
86
  function nowIsoSeconds(): string {
@@ -134,6 +104,23 @@ export function readHeartbeat(coordRoot: string, instanceId: string): Heartbeat
134
104
  }
135
105
  }
136
106
 
107
+ /** Persist operator-facing lifecycle prose in the generation-bound cache only. */
108
+ export function setLifecycleCache(
109
+ coordRoot: string,
110
+ instanceId: string,
111
+ state: TaskState,
112
+ reason?: string,
113
+ suggestedSessionName?: string,
114
+ ): Heartbeat | null {
115
+ return mutate(coordRoot, instanceId, (heartbeat) => ({
116
+ ...heartbeat,
117
+ task_state: state,
118
+ task_state_updated_at: nowIsoSeconds(),
119
+ task_state_reason: state === "active" ? undefined : reason,
120
+ ...(suggestedSessionName ? { suggested_session_name: suggestedSessionName } : {}),
121
+ }));
122
+ }
123
+
137
124
  function mutate(
138
125
  coordRoot: string,
139
126
  instanceId: string,
@@ -163,11 +150,27 @@ export function setTask(coordRoot: string, instanceId: string, task: string): He
163
150
  ...hb,
164
151
  task: cleared ? undefined : task,
165
152
  task_updated_at: nowIsoSeconds(),
153
+ ...(hb.schema_version === 2 ? { v3_task_state: cleared ? "cleared" : "set" } : {}),
166
154
  ...(built ? { suggested_session_name: built.suggestedName } : {}),
167
155
  };
168
156
  });
169
157
  }
170
158
 
159
+ /** Update the disposable identity cache after a canonical V3 attestation. */
160
+ export function setIdentityCache(
161
+ coordRoot: string,
162
+ instanceId: string,
163
+ name: string,
164
+ agentId: string,
165
+ ): Heartbeat | null {
166
+ const heartbeat = readHeartbeat(coordRoot, instanceId);
167
+ if (!heartbeat) return null;
168
+ heartbeat.name = name;
169
+ heartbeat.agent_id = agentId;
170
+ atomicWrite(heartbeatPath(coordRoot, instanceId), JSON.stringify(heartbeat, null, 2));
171
+ return heartbeat;
172
+ }
173
+
171
174
  /**
172
175
  * Build the copy-pasteable session name from the coord identity + the agent's
173
176
  * description parts. Pure (no coord-state reads) so it's unit-testable; collapses
@@ -183,6 +186,19 @@ export function buildSuggestedName(
183
186
  return { suggestedName: `Agent ${name} - ${description}`, description };
184
187
  }
185
188
 
189
+ /** Build the sole lifecycle-driven title: the terminal done projection. */
190
+ export function buildLifecycleSuggestedName(
191
+ currentSessionName: string | undefined,
192
+ state: TaskState,
193
+ ): string | null {
194
+ if (state !== "done" || !currentSessionName?.trim()) return null;
195
+ const baseName = currentSessionName
196
+ .trim()
197
+ .replace(/^\[DONE\]\s+/, "")
198
+ .replace(/^\[BLOCKED\]\s*-\s*/, "");
199
+ return baseName ? `[DONE] ${baseName}` : null;
200
+ }
201
+
186
202
  /** Stamp the sighting once the suggested name has been observed in assistant
187
203
  * reply text; later turns skip the transcript scan. Records WHICH name was seen,
188
204
  * because the skip is only valid for that one: if a later set-task mints a
@@ -200,33 +216,36 @@ export function stampSessionNameSeen(
200
216
  }));
201
217
  }
202
218
 
203
- export function setTurnSummary(
219
+ export function releaseClaim(
204
220
  coordRoot: string,
205
221
  instanceId: string,
206
- summary: string,
222
+ path: string,
207
223
  ): Heartbeat | null {
224
+ // files_touched can hold either absolute-under-coordRoot or canonical
225
+ // monorepo-relative entries; normalize both sides so release matches
226
+ // regardless of the form the caller passes (the old exact-string filter
227
+ // silently no-op'd on a form mismatch).
228
+ const norm = (p: string): string =>
229
+ p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
230
+ const target = norm(path);
208
231
  return mutate(coordRoot, instanceId, (hb) => ({
209
232
  ...hb,
210
- turn_summary: summary,
211
- turn_summary_updated_at: nowIsoSeconds(),
233
+ files_touched: (hb.files_touched ?? []).filter((p) => norm(p) !== target),
212
234
  }));
213
235
  }
214
236
 
215
- export function releaseClaim(
237
+ /** Materialize one V3 write-claim authority transition into the heartbeat cache. */
238
+ export function acquireClaim(
216
239
  coordRoot: string,
217
240
  instanceId: string,
218
241
  path: string,
219
242
  ): Heartbeat | null {
220
- // files_touched can hold either absolute-under-coordRoot or canonical
221
- // monorepo-relative entries; normalize both sides so release matches
222
- // regardless of the form the caller passes (the old exact-string filter
223
- // silently no-op'd on a form mismatch).
224
243
  const norm = (p: string): string =>
225
244
  p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
226
245
  const target = norm(path);
227
246
  return mutate(coordRoot, instanceId, (hb) => ({
228
247
  ...hb,
229
- files_touched: (hb.files_touched ?? []).filter((p) => norm(p) !== target),
248
+ files_touched: [...new Set([...(hb.files_touched ?? []).map(norm), target])].sort(),
230
249
  }));
231
250
  }
232
251
 
@@ -243,7 +262,7 @@ export interface GroupUnclaimHit {
243
262
  * subagents inherit it) and removes the path from each one's files_touched.
244
263
  * Idempotent: heartbeats that don't hold the path are untouched. Returns the
245
264
  * heartbeats that actually dropped the path so the caller can emit the
246
- * durable `claim.release` events — a file-only prune is silently reverted by
265
+ * durable `coord.claim_changed` release events; a file-only prune is silently reverted by
247
266
  * the next projector replay.
248
267
  *
249
268
  * Tool payloads and release calls can supply either absolute-under-coordRoot or
@@ -254,7 +273,11 @@ export interface GroupUnclaimHit {
254
273
  * subagent-held claim that doesn't live on the parent's heartbeat still gets
255
274
  * pruned because the walk covers the whole group.
256
275
  */
257
- export function groupUnclaim(coordRoot: string, groupId: string, path: string): GroupUnclaimHit[] {
276
+ export function findGroupClaims(
277
+ coordRoot: string,
278
+ groupId: string,
279
+ path: string,
280
+ ): GroupUnclaimHit[] {
258
281
  const hits: GroupUnclaimHit[] = [];
259
282
  if (!groupId || !path) return hits;
260
283
  const activeDir = join(coordRoot, ".harnery", "active");
@@ -275,26 +298,17 @@ export function groupUnclaim(coordRoot: string, groupId: string, path: string):
275
298
  (body.session_id as string | undefined) ?? (body.instance_id as string | undefined);
276
299
  if (peerSession !== groupId) continue;
277
300
  const files = (body.files_touched as string[] | undefined) ?? [];
278
- const next = files.filter((p) => norm(p) !== target);
279
- if (next.length === files.length) continue;
280
- body.files_touched = next;
281
- try {
282
- const tmp = `${hbPath}.tmp.${process.pid}`;
283
- writeFileSync(tmp, JSON.stringify(body, null, 2), "utf8");
284
- renameSync(tmp, hbPath);
285
- hits.push({
286
- instance_id: (body.instance_id as string | undefined) ?? f.replace(/\.json$/, ""),
287
- session_id: body.session_id as string | undefined,
288
- platform: body.platform as string | undefined,
289
- });
290
- } catch {
291
- /* silent */
292
- }
301
+ if (!files.some((candidate) => norm(candidate) === target)) continue;
302
+ hits.push({
303
+ instance_id: (body.instance_id as string | undefined) ?? f.replace(/\.json$/, ""),
304
+ session_id: body.session_id as string | undefined,
305
+ platform: body.platform as string | undefined,
306
+ });
293
307
  }
294
308
  return hits;
295
309
  }
296
310
 
297
- export function killHeartbeat(coordRoot: string, instanceId: string): boolean {
311
+ export function clearCoordinationCache(coordRoot: string, instanceId: string): boolean {
298
312
  const path = heartbeatPath(coordRoot, instanceId);
299
313
  if (!existsSync(path)) return false;
300
314
  try {
@@ -322,162 +336,4 @@ export function healPidmap(coordRoot: string, instanceId: string, pid: number):
322
336
  }
323
337
  if (existingOwner === instanceId) return;
324
338
  atomicWrite(pmPath, `${instanceId}\t${platform}`);
325
- emitHealthHeal(coordRoot, "health.pidmap_heal", instanceId, hb, {
326
- reason: existingOwner ? "stale" : "missing",
327
- pid,
328
- kind: "pidmap",
329
- ...(existingOwner ? { prior: existingOwner.slice(0, 8) } : {}),
330
- });
331
- }
332
-
333
- export function healHeartbeat(
334
- coordRoot: string,
335
- instanceId: string,
336
- sessionId?: string,
337
- model?: string,
338
- adapter?: string,
339
- opts?: { forkedFrom?: string },
340
- ): Heartbeat | null {
341
- const path = heartbeatPath(coordRoot, instanceId);
342
- if (existsSync(path)) {
343
- // Already alive, return it.
344
- return readHeartbeat(coordRoot, instanceId);
345
- }
346
- const now = nowIsoSeconds();
347
-
348
- // Recover name + kind from .name-history if present (idempotent across
349
- // sweeps: same instance_id always gets the same name).
350
- let name = "";
351
- let kind = "session";
352
- let agentId = "";
353
- try {
354
- // eslint-disable-next-line @typescript-eslint/no-require-imports
355
- const names = require("./names.ts") as typeof import("./names.ts");
356
- const resolved = names.resolveName(coordRoot, instanceId, sessionId);
357
- if (resolved) {
358
- name = resolved.name;
359
- kind = resolved.kind;
360
- // An explicitly assumed session carries its durable persona UUID in
361
- // name-history. Native subagents continue to use instance_id.
362
- agentId = resolved.agent_id ?? (resolved.kind === "subagent" ? instanceId : "");
363
- } else if (!sessionId || sessionId === instanceId) {
364
- // A main session with NO history at all never fired session.start —
365
- // the CC fork flow (SessionStart fires under the parent's id before
366
- // the fork id is minted), or a partially-wired adapter. Mint its pool
367
- // name here instead of leaving a nameless heartbeat, and stamp the
368
- // detected fork lineage while we're at it. A sessionId that differs
369
- // from instanceId is left alone: that shape is a subagent whose parent
370
- // is also unknown, and guessing "session" would be wrong.
371
- name = names.assignName(
372
- coordRoot,
373
- instanceId,
374
- "session",
375
- opts?.forkedFrom ? { forkedFrom: opts.forkedFrom } : undefined,
376
- );
377
- }
378
- } catch {
379
- /* names module unavailable, fall back to empty */
380
- }
381
-
382
- const hb: Heartbeat = {
383
- schema_version: 1,
384
- instance_id: instanceId,
385
- session_id: sessionId ?? instanceId,
386
- name,
387
- kind,
388
- agent_id: agentId,
389
- model: model ?? "",
390
- started_at: now,
391
- last_heartbeat: now,
392
- files_touched: [],
393
- // Default to claude-code only when the caller can't tell us the adapter
394
- // (e.g. manual `harn agents heal`). The live tool.pre_use heal threads the
395
- // detected adapter so a pruned Cursor/Codex heartbeat is recreated with
396
- // the correct platform instead of being mislabeled claude-code.
397
- platform: adapterToPlatform(adapter),
398
- };
399
- atomicWrite(path, JSON.stringify(hb, null, 2));
400
- // Write-only telemetry: only the actual-recreate branch reaches here (the
401
- // already-alive case returned above), so this records exactly the heals that
402
- // happened. Recorded fork lineage rides the event too, so derived readers
403
- // rebuilding from the ledger converge with .name-history.
404
- emitHealthHeal(coordRoot, "health.heartbeat_heal", instanceId, hb, {
405
- reason: "missing",
406
- kind: "heartbeat",
407
- ...(opts?.forkedFrom ? { forked_from: opts.forkedFrom } : {}),
408
- });
409
- return hb;
410
- }
411
-
412
- /**
413
- * Register a workflow child in the coordination layer from the ENGINE side.
414
- *
415
- * Previously a spawned child was visible only if its adapter fired Harnery's
416
- * hooks, which made coordination visibility a property of the vendor CLI
417
- * rather than of the engine. Headless `codex exec` fires no hooks, so codex
418
- * children never appeared in `harn agents list` and rendered as "no live
419
- * session" on the run page while actively working — for the entire length of
420
- * a multi-minute stage.
421
- *
422
- * The engine already knows every fact a heartbeat needs at spawn time, so it
423
- * writes one itself. Hook-firing adapters keep enriching the same file
424
- * (last_tool, files_touched); non-hook adapters at least become visible and
425
- * attributable. Pair with `killHeartbeat` when the child ends.
426
- *
427
- * Idempotent: re-registering refreshes in place and preserves `started_at`
428
- * and any claims a hook already recorded.
429
- */
430
- export function registerWorkflowChild(
431
- coordRoot: string,
432
- opts: {
433
- instanceId: string;
434
- runId: string;
435
- agentId: string;
436
- sessionId?: string;
437
- adapter?: string;
438
- label?: string;
439
- model?: string;
440
- },
441
- ): Heartbeat {
442
- const now = nowIsoSeconds();
443
- const prior = readHeartbeat(coordRoot, opts.instanceId);
444
- const hb: Heartbeat = {
445
- ...(prior ?? {}),
446
- schema_version: 1,
447
- instance_id: opts.instanceId,
448
- // The reader keys children by session_id and skips any heartbeat missing
449
- // one, so it must always be set even before the adapter mints a real id.
450
- session_id: prior?.session_id ?? opts.sessionId ?? opts.instanceId,
451
- name: opts.label || opts.agentId,
452
- kind: "workflow-child",
453
- agent_id: opts.agentId,
454
- model: opts.model ?? prior?.model ?? "",
455
- platform: adapterToPlatform(opts.adapter),
456
- started_at: prior?.started_at ?? now,
457
- last_heartbeat: now,
458
- files_touched: prior?.files_touched ?? [],
459
- task: opts.label ?? "",
460
- workflow_run_id: opts.runId,
461
- workflow_agent_id: opts.agentId,
462
- };
463
- atomicWrite(heartbeatPath(coordRoot, opts.instanceId), JSON.stringify(hb, null, 2));
464
- return hb;
465
- }
466
-
467
- /**
468
- * Stamp the heartbeat with the most-recent tool name + target. Written from
469
- * the post-tool-use hook.
470
- */
471
- export function stampToolActivity(
472
- coordRoot: string,
473
- instanceId: string,
474
- toolName: string,
475
- target: string,
476
- ): Heartbeat | null {
477
- return mutate(coordRoot, instanceId, (hb) => ({
478
- ...hb,
479
- last_tool: toolName,
480
- last_tool_target: target,
481
- last_tool_at: nowIsoSeconds(),
482
- }));
483
339
  }