harnery 0.40.0 → 0.42.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 (595) hide show
  1. package/README.md +1 -1
  2. package/dist/commander.js +4 -0
  3. package/dist/commands/agents.d.ts.map +1 -1
  4. package/dist/commands/agents.js +34 -20
  5. package/dist/commands/artifacts.d.ts.map +1 -1
  6. package/dist/commands/artifacts.js +113 -12
  7. package/dist/commands/browse-ai.d.ts.map +1 -1
  8. package/dist/commands/browse-ai.js +4 -0
  9. package/dist/commands/browse.d.ts +164 -0
  10. package/dist/commands/browse.d.ts.map +1 -1
  11. package/dist/commands/browse.js +388 -45
  12. package/dist/commands/checkpoint.js +8 -12
  13. package/dist/commands/claude-desktop.d.ts.map +1 -1
  14. package/dist/commands/claude-desktop.js +52 -0
  15. package/dist/commands/deinit.d.ts +1 -1
  16. package/dist/commands/deinit.d.ts.map +1 -1
  17. package/dist/commands/deinit.js +8 -4
  18. package/dist/commands/disk.d.ts +6 -0
  19. package/dist/commands/disk.d.ts.map +1 -0
  20. package/dist/commands/disk.js +80 -0
  21. package/dist/commands/docs.d.ts.map +1 -1
  22. package/dist/commands/docs.js +2 -0
  23. package/dist/commands/doctor.d.ts +8 -0
  24. package/dist/commands/doctor.d.ts.map +1 -1
  25. package/dist/commands/doctor.js +58 -3
  26. package/dist/commands/fetch.d.ts.map +1 -1
  27. package/dist/commands/fetch.js +10 -0
  28. package/dist/commands/files.d.ts +16 -0
  29. package/dist/commands/files.d.ts.map +1 -1
  30. package/dist/commands/files.js +54 -2
  31. package/dist/commands/init.d.ts +21 -5
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +271 -109
  34. package/dist/commands/instructions.js +5 -4
  35. package/dist/commands/ledger-v3.d.ts.map +1 -1
  36. package/dist/commands/ledger-v3.js +2 -1
  37. package/dist/commands/rm.d.ts +4 -0
  38. package/dist/commands/rm.d.ts.map +1 -0
  39. package/dist/commands/rm.js +87 -0
  40. package/dist/commands/servers.d.ts +7 -0
  41. package/dist/commands/servers.d.ts.map +1 -0
  42. package/dist/commands/servers.js +394 -0
  43. package/dist/commands/tunnel.d.ts.map +1 -1
  44. package/dist/commands/tunnel.js +82 -2
  45. package/dist/commands/webview.d.ts +4 -0
  46. package/dist/commands/webview.d.ts.map +1 -0
  47. package/dist/commands/webview.js +94 -0
  48. package/dist/core/adapter.d.ts +50 -1
  49. package/dist/core/adapter.d.ts.map +1 -1
  50. package/dist/core/adapter.js +59 -1
  51. package/dist/core/adapters/attestation.d.ts.map +1 -1
  52. package/dist/core/adapters/attestation.js +3 -2
  53. package/dist/core/adapters/profiles.d.ts +29 -3
  54. package/dist/core/adapters/profiles.d.ts.map +1 -1
  55. package/dist/core/adapters/profiles.js +53 -1
  56. package/dist/core/adapters/registry.d.ts.map +1 -1
  57. package/dist/core/adapters/registry.js +33 -0
  58. package/dist/core/adapters/types.d.ts +9 -0
  59. package/dist/core/adapters/types.d.ts.map +1 -1
  60. package/dist/core/agents/canonical-emit.d.ts +1 -1
  61. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  62. package/dist/core/agents/canonical-emit.js +2 -7
  63. package/dist/core/agents/cli.js +25 -16
  64. package/dist/core/agents/coord-client.d.ts.map +1 -1
  65. package/dist/core/agents/coord-client.js +7 -2
  66. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  67. package/dist/core/agents/render/session-context.js +2 -0
  68. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  69. package/dist/core/agents/rules/claim-conflict.js +3 -9
  70. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  71. package/dist/core/agents/rules/commit-conflict.js +2 -8
  72. package/dist/core/agents/rules/stop-hook.d.ts +2 -0
  73. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  74. package/dist/core/agents/rules/stop-hook.js +1 -1
  75. package/dist/core/agents/session-events.d.ts +6 -2
  76. package/dist/core/agents/session-events.d.ts.map +1 -1
  77. package/dist/core/agents/session-events.js +105 -26
  78. package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -1
  79. package/dist/core/agents/session-finalization-state-v3.js +2 -1
  80. package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
  81. package/dist/core/agents/session-finalizer-v3.js +5 -4
  82. package/dist/core/agents/session-name-display.d.ts +28 -0
  83. package/dist/core/agents/session-name-display.d.ts.map +1 -1
  84. package/dist/core/agents/session-name-display.js +43 -0
  85. package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
  86. package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
  87. package/dist/core/agents/state/heartbeat-writer.d.ts +10 -0
  88. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  89. package/dist/core/agents/state/heartbeat-writer.js +21 -2
  90. package/dist/core/agents/state/live-coordination-view.d.ts +20 -0
  91. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  92. package/dist/core/agents/state/live-coordination-view.js +61 -0
  93. package/dist/core/agents/state/live-coordination-writer.js +3 -0
  94. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  95. package/dist/core/agents/state/stale-sweep.js +2 -10
  96. package/dist/core/agents/turn-changes.d.ts +17 -0
  97. package/dist/core/agents/turn-changes.d.ts.map +1 -0
  98. package/dist/core/agents/turn-changes.js +76 -0
  99. package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
  100. package/dist/core/artifacts/delivery-card.js +11 -3
  101. package/dist/core/artifacts/index.d.ts +140 -4
  102. package/dist/core/artifacts/index.d.ts.map +1 -1
  103. package/dist/core/artifacts/index.js +526 -52
  104. package/dist/core/config.d.ts +73 -11
  105. package/dist/core/config.d.ts.map +1 -1
  106. package/dist/core/config.js +142 -3
  107. package/dist/core/context/index.d.ts.map +1 -1
  108. package/dist/core/context/index.js +2 -1
  109. package/dist/core/conversations/archive.d.ts.map +1 -1
  110. package/dist/core/conversations/archive.js +4 -3
  111. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  112. package/dist/core/diagnostics/bundle.js +5 -4
  113. package/dist/core/events/legacy-storage/canary.d.ts.map +1 -1
  114. package/dist/core/events/legacy-storage/canary.js +5 -4
  115. package/dist/core/events/legacy-storage/compression.d.ts.map +1 -1
  116. package/dist/core/events/legacy-storage/compression.js +2 -1
  117. package/dist/core/events/v3/adapter-id.d.ts +10 -2
  118. package/dist/core/events/v3/adapter-id.d.ts.map +1 -1
  119. package/dist/core/events/v3/adapter-id.js +16 -0
  120. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  121. package/dist/core/events/v3/authority-outbox.js +2 -1
  122. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  123. package/dist/core/events/v3/bootstrap.js +5 -4
  124. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  125. package/dist/core/events/v3/capabilities.js +17 -0
  126. package/dist/core/events/v3/contract.d.ts +5 -0
  127. package/dist/core/events/v3/contract.d.ts.map +1 -1
  128. package/dist/core/events/v3/contract.js +7 -1
  129. package/dist/core/events/v3/control-witness.d.ts.map +1 -1
  130. package/dist/core/events/v3/control-witness.js +3 -2
  131. package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -1
  132. package/dist/core/events/v3/coordination-transaction-recovery.js +4 -3
  133. package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -1
  134. package/dist/core/events/v3/fingerprint-keys.js +7 -6
  135. package/dist/core/events/v3/generated.d.ts +1 -1
  136. package/dist/core/events/v3/generated.js +1 -1
  137. package/dist/core/events/v3/live-feed.d.ts.map +1 -1
  138. package/dist/core/events/v3/live-feed.js +5 -4
  139. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
  140. package/dist/core/events/v3/producers/command-recorder.js +8 -7
  141. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  142. package/dist/core/events/v3/producers/coordination-recorder.js +8 -7
  143. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -1
  144. package/dist/core/events/v3/producers/diagnostic-summaries.js +5 -4
  145. package/dist/core/events/v3/producers/hook-base.d.ts +1 -0
  146. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  147. package/dist/core/events/v3/producers/hook-base.js +10 -4
  148. package/dist/core/events/v3/producers/hook.d.ts +2 -0
  149. package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
  150. package/dist/core/events/v3/producers/hook.js +16 -1
  151. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  152. package/dist/core/events/v3/producers/intake.js +16 -6
  153. package/dist/core/events/v3/producers/recorder.d.ts +2 -4
  154. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  155. package/dist/core/events/v3/producers/recorder.js +125 -101
  156. package/dist/core/events/v3/projection.js +9 -1
  157. package/dist/core/events/v3/recovery.d.ts.map +1 -1
  158. package/dist/core/events/v3/recovery.js +4 -3
  159. package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -1
  160. package/dist/core/events/v3/support-storage/inventory.js +2 -1
  161. package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -1
  162. package/dist/core/events/v3/support-storage/maintenance.js +4 -3
  163. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
  164. package/dist/core/events/v3/support-storage/pack-reader.js +4 -3
  165. package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -1
  166. package/dist/core/events/v3/support-storage/pack-writer.js +6 -5
  167. package/dist/core/events/v3/tool-line-changes.d.ts +8 -0
  168. package/dist/core/events/v3/tool-line-changes.d.ts.map +1 -0
  169. package/dist/core/events/v3/tool-line-changes.js +135 -0
  170. package/dist/core/events/v3/writer.d.ts.map +1 -1
  171. package/dist/core/events/v3/writer.js +8 -7
  172. package/dist/core/governor/planning.d.ts.map +1 -1
  173. package/dist/core/governor/planning.js +6 -5
  174. package/dist/core/governor/service.d.ts.map +1 -1
  175. package/dist/core/governor/service.js +12 -11
  176. package/dist/core/governor/state.d.ts.map +1 -1
  177. package/dist/core/governor/state.js +7 -6
  178. package/dist/core/guard/evaluator.js +1 -0
  179. package/dist/core/guard/storage.d.ts.map +1 -1
  180. package/dist/core/guard/storage.js +3 -2
  181. package/dist/core/hooks/adapter/behaviors/claude-code.d.ts +4 -0
  182. package/dist/core/hooks/adapter/behaviors/claude-code.d.ts.map +1 -0
  183. package/dist/core/hooks/adapter/behaviors/claude-code.js +31 -0
  184. package/dist/core/hooks/adapter/behaviors/codex.d.ts +15 -0
  185. package/dist/core/hooks/adapter/behaviors/codex.d.ts.map +1 -0
  186. package/dist/core/hooks/adapter/behaviors/codex.js +82 -0
  187. package/dist/core/hooks/adapter/behaviors/cursor.d.ts +7 -0
  188. package/dist/core/hooks/adapter/behaviors/cursor.d.ts.map +1 -0
  189. package/dist/core/hooks/adapter/behaviors/cursor.js +35 -0
  190. package/dist/core/hooks/adapter/behaviors/index.d.ts +11 -0
  191. package/dist/core/hooks/adapter/behaviors/index.d.ts.map +1 -0
  192. package/dist/core/hooks/adapter/behaviors/index.js +20 -0
  193. package/dist/core/hooks/adapter/behaviors/openclaw.d.ts +7 -0
  194. package/dist/core/hooks/adapter/behaviors/openclaw.d.ts.map +1 -0
  195. package/dist/core/hooks/adapter/behaviors/openclaw.js +34 -0
  196. package/dist/core/hooks/adapter/behaviors/opencode.d.ts +7 -0
  197. package/dist/core/hooks/adapter/behaviors/opencode.d.ts.map +1 -0
  198. package/dist/core/hooks/adapter/behaviors/opencode.js +34 -0
  199. package/dist/core/hooks/adapter/behaviors/types.d.ts +89 -0
  200. package/dist/core/hooks/adapter/behaviors/types.d.ts.map +1 -0
  201. package/dist/core/hooks/adapter/behaviors/types.js +1 -0
  202. package/dist/core/hooks/adapter/detect.d.ts +1 -1
  203. package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
  204. package/dist/core/hooks/adapter/detect.js +2 -3
  205. package/dist/core/hooks/adapter/events.d.ts +46 -1
  206. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  207. package/dist/core/hooks/adapter/events.js +36 -0
  208. package/dist/core/hooks/adapter/opencode-plugin.d.ts +60 -0
  209. package/dist/core/hooks/adapter/opencode-plugin.d.ts.map +1 -0
  210. package/dist/core/hooks/adapter/opencode-plugin.js +129 -0
  211. package/dist/core/hooks/adapter/output.d.ts +7 -0
  212. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  213. package/dist/core/hooks/adapter/output.js +8 -1
  214. package/dist/core/hooks/adapter/runtime-telemetry.js +3 -1
  215. package/dist/core/hooks/adapter/wiring.d.ts +52 -8
  216. package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
  217. package/dist/core/hooks/adapter/wiring.js +133 -12
  218. package/dist/core/hooks/cli.js +676 -531
  219. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  220. package/dist/core/hooks/effects/image-capture.js +2 -1
  221. package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -1
  222. package/dist/core/hooks/prompt-context/contract.js +1 -0
  223. package/dist/core/hooks/resolve/transcript.d.ts +1 -1
  224. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  225. package/dist/core/hooks/resolve/transcript.js +35 -4
  226. package/dist/core/hooks/run-markers.d.ts +37 -0
  227. package/dist/core/hooks/run-markers.d.ts.map +1 -0
  228. package/dist/core/hooks/run-markers.js +109 -0
  229. package/dist/core/hooks/session-name-presence.d.ts +3 -1
  230. package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
  231. package/dist/core/hooks/session-name-presence.js +7 -2
  232. package/dist/core/hooks/shell-waiter.d.ts +2 -0
  233. package/dist/core/hooks/shell-waiter.d.ts.map +1 -0
  234. package/dist/core/hooks/shell-waiter.js +173 -0
  235. package/dist/core/resources/service.d.ts.map +1 -1
  236. package/dist/core/resources/service.js +5 -4
  237. package/dist/core/semantic/review.d.ts.map +1 -1
  238. package/dist/core/semantic/review.js +5 -4
  239. package/dist/core/semantic/service.d.ts.map +1 -1
  240. package/dist/core/semantic/service.js +15 -14
  241. package/dist/core/semantic/storage.d.ts.map +1 -1
  242. package/dist/core/semantic/storage.js +5 -4
  243. package/dist/core/servers/index.d.ts +211 -0
  244. package/dist/core/servers/index.d.ts.map +1 -0
  245. package/dist/core/servers/index.js +560 -0
  246. package/dist/core/servers/net.d.ts +58 -0
  247. package/dist/core/servers/net.d.ts.map +1 -0
  248. package/dist/core/servers/net.js +270 -0
  249. package/dist/core/servers/tunnels.d.ts +14 -0
  250. package/dist/core/servers/tunnels.d.ts.map +1 -0
  251. package/dist/core/servers/tunnels.js +33 -0
  252. package/dist/core/storage/atomic-json.d.ts.map +1 -1
  253. package/dist/core/storage/atomic-json.js +7 -3
  254. package/dist/core/storage/builtins.js +1 -0
  255. package/dist/core/storage/durable-history.d.ts.map +1 -1
  256. package/dist/core/storage/durable-history.js +6 -5
  257. package/dist/core/storage/maintenance-providers.d.ts.map +1 -1
  258. package/dist/core/storage/maintenance-providers.js +2 -1
  259. package/dist/core/storage/maintenance.d.ts.map +1 -1
  260. package/dist/core/storage/maintenance.js +7 -6
  261. package/dist/core/storage/metrics.d.ts.map +1 -1
  262. package/dist/core/storage/metrics.js +5 -1
  263. package/dist/core/storage/modes.d.ts +17 -0
  264. package/dist/core/storage/modes.d.ts.map +1 -0
  265. package/dist/core/storage/modes.js +47 -0
  266. package/dist/core/storage/process-log.d.ts.map +1 -1
  267. package/dist/core/storage/process-log.js +3 -2
  268. package/dist/core/storage/receipts.d.ts.map +1 -1
  269. package/dist/core/storage/receipts.js +4 -3
  270. package/dist/core/storage/segments.d.ts.map +1 -1
  271. package/dist/core/storage/segments.js +7 -6
  272. package/dist/core/supervisor/hook-health.d.ts +2 -1
  273. package/dist/core/supervisor/hook-health.d.ts.map +1 -1
  274. package/dist/core/supervisor/hook-health.js +4 -3
  275. package/dist/core/supervisor/service.d.ts.map +1 -1
  276. package/dist/core/supervisor/service.js +7 -6
  277. package/dist/core/work/state.d.ts.map +1 -1
  278. package/dist/core/work/state.js +8 -7
  279. package/dist/core/workflow/adapters.d.ts +7 -0
  280. package/dist/core/workflow/adapters.d.ts.map +1 -1
  281. package/dist/core/workflow/adapters.js +9 -0
  282. package/dist/core/workflow/approvals.d.ts.map +1 -1
  283. package/dist/core/workflow/approvals.js +6 -5
  284. package/dist/core/workflow/billing.d.ts.map +1 -1
  285. package/dist/core/workflow/billing.js +33 -4
  286. package/dist/core/workflow/durable-record.d.ts.map +1 -1
  287. package/dist/core/workflow/durable-record.js +4 -3
  288. package/dist/core/workflow/engine.d.ts.map +1 -1
  289. package/dist/core/workflow/engine.js +30 -1
  290. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  291. package/dist/core/workflow/live-session-v3.js +2 -3
  292. package/dist/core/workflow/run-state.d.ts.map +1 -1
  293. package/dist/core/workflow/run-state.js +3 -2
  294. package/dist/core/workflow/sandbox-projection.d.ts +13 -2
  295. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  296. package/dist/core/workflow/sandbox-projection.js +23 -0
  297. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  298. package/dist/core/workflow/spawn-claude.js +6 -1
  299. package/dist/core/workflow/spawn-codex.d.ts +2 -0
  300. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  301. package/dist/core/workflow/spawn-codex.js +20 -1
  302. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  303. package/dist/core/workflow/spawn-cursor.js +6 -1
  304. package/dist/core/workflow/spawn-opencode.d.ts +36 -0
  305. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -0
  306. package/dist/core/workflow/spawn-opencode.js +135 -0
  307. package/dist/core/workflow/transcript.d.ts.map +1 -1
  308. package/dist/core/workflow/transcript.js +3 -2
  309. package/dist/core/workflow/types.d.ts +47 -2
  310. package/dist/core/workflow/types.d.ts.map +1 -1
  311. package/dist/core/workflow/worker-access.d.ts +92 -0
  312. package/dist/core/workflow/worker-access.d.ts.map +1 -0
  313. package/dist/core/workflow/worker-access.js +450 -0
  314. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  315. package/dist/core/workflow/workspaces/leases.js +5 -4
  316. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  317. package/dist/core/workflow/workspaces/local-git.js +3 -2
  318. package/dist/core/workflow/workspaces/paths.d.ts.map +1 -1
  319. package/dist/core/workflow/workspaces/paths.js +2 -1
  320. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  321. package/dist/core/workflow/workspaces/state.js +10 -9
  322. package/dist/lazy-commands.js +8 -1
  323. package/dist/lib/agent-browser/client.d.ts +9 -0
  324. package/dist/lib/agent-browser/client.d.ts.map +1 -1
  325. package/dist/lib/agent-browser/client.js +13 -0
  326. package/dist/lib/browser/batch-steps.d.ts +18 -0
  327. package/dist/lib/browser/batch-steps.d.ts.map +1 -0
  328. package/dist/lib/browser/batch-steps.js +82 -0
  329. package/dist/lib/browser/client.d.ts +35 -1
  330. package/dist/lib/browser/client.d.ts.map +1 -1
  331. package/dist/lib/browser/client.js +117 -8
  332. package/dist/lib/browser/collect/collector.d.ts +99 -0
  333. package/dist/lib/browser/collect/collector.d.ts.map +1 -0
  334. package/dist/lib/browser/collect/collector.js +202 -0
  335. package/dist/lib/browser/collect/fields.d.ts +31 -0
  336. package/dist/lib/browser/collect/fields.d.ts.map +1 -0
  337. package/dist/lib/browser/collect/fields.js +75 -0
  338. package/dist/lib/browser/collect/index.d.ts +6 -0
  339. package/dist/lib/browser/collect/index.d.ts.map +1 -0
  340. package/dist/lib/browser/collect/index.js +5 -0
  341. package/dist/lib/browser/collect/page-driver.d.ts +14 -0
  342. package/dist/lib/browser/collect/page-driver.d.ts.map +1 -0
  343. package/dist/lib/browser/collect/page-driver.js +306 -0
  344. package/dist/lib/browser/collect/presets.d.ts +52 -0
  345. package/dist/lib/browser/collect/presets.d.ts.map +1 -0
  346. package/dist/lib/browser/collect/presets.js +176 -0
  347. package/dist/lib/browser/collect/scroll-plan.d.ts +85 -0
  348. package/dist/lib/browser/collect/scroll-plan.d.ts.map +1 -0
  349. package/dist/lib/browser/collect/scroll-plan.js +118 -0
  350. package/dist/lib/browser/identity.d.ts +25 -0
  351. package/dist/lib/browser/identity.d.ts.map +1 -0
  352. package/dist/lib/browser/identity.js +66 -0
  353. package/dist/lib/browser/index.d.ts +3 -2
  354. package/dist/lib/browser/index.d.ts.map +1 -1
  355. package/dist/lib/browser/index.js +2 -1
  356. package/dist/lib/browser/launch-args.d.ts +26 -0
  357. package/dist/lib/browser/launch-args.d.ts.map +1 -1
  358. package/dist/lib/browser/launch-args.js +41 -1
  359. package/dist/lib/browser/page-review-judge.d.ts +2 -0
  360. package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
  361. package/dist/lib/browser/page-review-judge.js +13 -0
  362. package/dist/lib/browser/qa-run-contracts.d.ts +10 -0
  363. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
  364. package/dist/lib/browser/qa-run.d.ts.map +1 -1
  365. package/dist/lib/browser/qa-run.js +1 -0
  366. package/dist/lib/browser/user-agent.d.ts +53 -0
  367. package/dist/lib/browser/user-agent.d.ts.map +1 -0
  368. package/dist/lib/browser/user-agent.js +79 -0
  369. package/dist/lib/browser/windows-chrome.d.ts +59 -0
  370. package/dist/lib/browser/windows-chrome.d.ts.map +1 -0
  371. package/dist/lib/browser/windows-chrome.js +179 -0
  372. package/dist/lib/claude-desktop-share.d.ts +136 -0
  373. package/dist/lib/claude-desktop-share.d.ts.map +1 -0
  374. package/dist/lib/claude-desktop-share.js +394 -0
  375. package/dist/lib/disk-usage.d.ts +50 -0
  376. package/dist/lib/disk-usage.d.ts.map +1 -0
  377. package/dist/lib/disk-usage.js +303 -0
  378. package/dist/lib/docs-lint.d.ts +6 -0
  379. package/dist/lib/docs-lint.d.ts.map +1 -1
  380. package/dist/lib/docs-lint.js +8 -3
  381. package/dist/lib/docs-metadata-managed.d.ts +1 -0
  382. package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
  383. package/dist/lib/docs-metadata-managed.js +17 -1
  384. package/dist/lib/guarded-remove.d.ts +34 -0
  385. package/dist/lib/guarded-remove.d.ts.map +1 -0
  386. package/dist/lib/guarded-remove.js +310 -0
  387. package/dist/lib/identities/assume.d.ts.map +1 -1
  388. package/dist/lib/identities/assume.js +4 -9
  389. package/dist/lib/instructions/apply.d.ts.map +1 -1
  390. package/dist/lib/instructions/apply.js +2 -0
  391. package/dist/lib/instructions/templates.js +8 -8
  392. package/dist/lib/pace/index.d.ts +2 -0
  393. package/dist/lib/pace/index.d.ts.map +1 -0
  394. package/dist/lib/pace/index.js +1 -0
  395. package/dist/lib/pace/pace.d.ts +95 -0
  396. package/dist/lib/pace/pace.d.ts.map +1 -0
  397. package/dist/lib/pace/pace.js +313 -0
  398. package/dist/lib/tunnel/error-page.d.ts +1 -1
  399. package/dist/lib/tunnel/error-page.d.ts.map +1 -1
  400. package/dist/lib/tunnel/error-page.js +19 -8
  401. package/dist/lib/tunnel/forward-headers.d.ts +11 -0
  402. package/dist/lib/tunnel/forward-headers.d.ts.map +1 -0
  403. package/dist/lib/tunnel/forward-headers.js +17 -0
  404. package/dist/lib/tunnel/gate.js +34 -10
  405. package/dist/lib/tunnel/path-scope.d.ts +22 -0
  406. package/dist/lib/tunnel/path-scope.d.ts.map +1 -0
  407. package/dist/lib/tunnel/path-scope.js +62 -0
  408. package/dist/lib/tunnel/state.d.ts +5 -0
  409. package/dist/lib/tunnel/state.d.ts.map +1 -1
  410. package/dist/lib/tunnel/state.js +17 -3
  411. package/dist/lib/webview/index.d.ts +2 -0
  412. package/dist/lib/webview/index.d.ts.map +1 -0
  413. package/dist/lib/webview/index.js +1 -0
  414. package/dist/lib/webview/webview.d.ts +116 -0
  415. package/dist/lib/webview/webview.d.ts.map +1 -0
  416. package/dist/lib/webview/webview.js +289 -0
  417. package/opencode-plugin/package.json +19 -0
  418. package/opencode-plugin/src/index.ts +791 -0
  419. package/package.json +16 -4
  420. package/schemas/config.schema.json +104 -0
  421. package/schemas/event-v3.schema.json +164 -0
  422. package/src/commander.ts +26 -0
  423. package/src/commands/agents.ts +47 -18
  424. package/src/commands/artifacts.ts +171 -19
  425. package/src/commands/browse-ai.ts +8 -0
  426. package/src/commands/browse.ts +570 -48
  427. package/src/commands/checkpoint.ts +7 -9
  428. package/src/commands/claude-desktop.ts +61 -0
  429. package/src/commands/deinit.ts +9 -4
  430. package/src/commands/disk.ts +114 -0
  431. package/src/commands/docs.ts +2 -0
  432. package/src/commands/doctor.ts +63 -3
  433. package/src/commands/fetch.ts +14 -0
  434. package/src/commands/files.ts +93 -2
  435. package/src/commands/init.ts +334 -122
  436. package/src/commands/instructions.ts +8 -4
  437. package/src/commands/ledger-v3.ts +2 -1
  438. package/src/commands/rm.ts +115 -0
  439. package/src/commands/servers.ts +506 -0
  440. package/src/commands/tunnel.ts +102 -2
  441. package/src/commands/webview.ts +159 -0
  442. package/src/core/adapter.ts +102 -1
  443. package/src/core/adapters/attestation.ts +3 -2
  444. package/src/core/adapters/profiles.ts +63 -1
  445. package/src/core/adapters/registry.ts +37 -0
  446. package/src/core/adapters/types.ts +10 -0
  447. package/src/core/agents/canonical-emit.ts +2 -5
  448. package/src/core/agents/cli.ts +26 -17
  449. package/src/core/agents/coord-client.ts +9 -3
  450. package/src/core/agents/render/session-context.ts +1 -0
  451. package/src/core/agents/rules/claim-conflict.ts +3 -8
  452. package/src/core/agents/rules/commit-conflict.ts +2 -7
  453. package/src/core/agents/rules/stop-hook.ts +3 -1
  454. package/src/core/agents/session-events.ts +120 -26
  455. package/src/core/agents/session-finalization-state-v3.ts +2 -1
  456. package/src/core/agents/session-finalizer-v3.ts +5 -4
  457. package/src/core/agents/session-name-display.ts +48 -0
  458. package/src/core/agents/state/heartbeat-reader.ts +7 -0
  459. package/src/core/agents/state/heartbeat-writer.ts +24 -2
  460. package/src/core/agents/state/live-coordination-view.ts +74 -0
  461. package/src/core/agents/state/live-coordination-writer.ts +3 -0
  462. package/src/core/agents/state/stale-sweep.ts +2 -9
  463. package/src/core/agents/turn-changes.ts +97 -0
  464. package/src/core/artifacts/delivery-card.ts +12 -3
  465. package/src/core/artifacts/index.ts +701 -47
  466. package/src/core/config.ts +206 -4
  467. package/src/core/context/index.ts +2 -1
  468. package/src/core/conversations/archive.ts +4 -3
  469. package/src/core/diagnostics/bundle.ts +5 -3
  470. package/src/core/events/legacy-storage/canary.ts +5 -4
  471. package/src/core/events/legacy-storage/compression.ts +2 -1
  472. package/src/core/events/v3/adapter-id.ts +29 -1
  473. package/src/core/events/v3/authority-outbox.ts +2 -1
  474. package/src/core/events/v3/bootstrap.ts +5 -4
  475. package/src/core/events/v3/capabilities.ts +17 -0
  476. package/src/core/events/v3/contract.ts +9 -1
  477. package/src/core/events/v3/control-witness.ts +3 -2
  478. package/src/core/events/v3/coordination-transaction-recovery.ts +4 -3
  479. package/src/core/events/v3/fingerprint-keys.ts +7 -6
  480. package/src/core/events/v3/generated.ts +1 -1
  481. package/src/core/events/v3/live-feed.ts +5 -4
  482. package/src/core/events/v3/producers/command-recorder.ts +8 -6
  483. package/src/core/events/v3/producers/coordination-recorder.ts +8 -7
  484. package/src/core/events/v3/producers/diagnostic-summaries.ts +5 -4
  485. package/src/core/events/v3/producers/hook-base.ts +11 -4
  486. package/src/core/events/v3/producers/hook.ts +19 -1
  487. package/src/core/events/v3/producers/intake.ts +18 -6
  488. package/src/core/events/v3/producers/recorder.ts +139 -114
  489. package/src/core/events/v3/projection.ts +11 -1
  490. package/src/core/events/v3/recovery.ts +4 -3
  491. package/src/core/events/v3/support-storage/inventory.ts +2 -1
  492. package/src/core/events/v3/support-storage/maintenance.ts +8 -3
  493. package/src/core/events/v3/support-storage/pack-reader.ts +4 -3
  494. package/src/core/events/v3/support-storage/pack-writer.ts +6 -5
  495. package/src/core/events/v3/tool-line-changes.ts +139 -0
  496. package/src/core/events/v3/writer.ts +8 -7
  497. package/src/core/governor/planning.ts +6 -5
  498. package/src/core/governor/service.ts +12 -11
  499. package/src/core/governor/state.ts +7 -6
  500. package/src/core/guard/evaluator.ts +1 -0
  501. package/src/core/guard/storage.ts +3 -2
  502. package/src/core/hooks/adapter/behaviors/claude-code.ts +33 -0
  503. package/src/core/hooks/adapter/behaviors/codex.ts +96 -0
  504. package/src/core/hooks/adapter/behaviors/cursor.ts +37 -0
  505. package/src/core/hooks/adapter/behaviors/index.ts +31 -0
  506. package/src/core/hooks/adapter/behaviors/openclaw.ts +36 -0
  507. package/src/core/hooks/adapter/behaviors/opencode.ts +36 -0
  508. package/src/core/hooks/adapter/behaviors/types.ts +110 -0
  509. package/src/core/hooks/adapter/detect.ts +2 -3
  510. package/src/core/hooks/adapter/events.ts +72 -1
  511. package/src/core/hooks/adapter/opencode-plugin.ts +177 -0
  512. package/src/core/hooks/adapter/output.ts +8 -1
  513. package/src/core/hooks/adapter/runtime-telemetry.ts +3 -1
  514. package/src/core/hooks/adapter/wiring.ts +198 -16
  515. package/src/core/hooks/cli.ts +776 -539
  516. package/src/core/hooks/effects/image-capture.ts +2 -1
  517. package/src/core/hooks/prompt-context/contract.ts +1 -0
  518. package/src/core/hooks/resolve/transcript.ts +42 -5
  519. package/src/core/hooks/run-markers.ts +132 -0
  520. package/src/core/hooks/session-name-presence.ts +10 -3
  521. package/src/core/hooks/shell-waiter.ts +166 -0
  522. package/src/core/resources/service.ts +5 -4
  523. package/src/core/semantic/review.ts +5 -4
  524. package/src/core/semantic/service.ts +15 -14
  525. package/src/core/semantic/storage.ts +5 -4
  526. package/src/core/servers/index.ts +712 -0
  527. package/src/core/servers/net.ts +283 -0
  528. package/src/core/servers/tunnels.ts +39 -0
  529. package/src/core/storage/atomic-json.ts +7 -3
  530. package/src/core/storage/builtins.ts +1 -0
  531. package/src/core/storage/durable-history.ts +6 -5
  532. package/src/core/storage/maintenance-providers.ts +2 -1
  533. package/src/core/storage/maintenance.ts +7 -6
  534. package/src/core/storage/metrics.ts +5 -1
  535. package/src/core/storage/modes.ts +53 -0
  536. package/src/core/storage/process-log.ts +3 -2
  537. package/src/core/storage/receipts.ts +4 -3
  538. package/src/core/storage/segments.ts +7 -6
  539. package/src/core/supervisor/hook-health.ts +4 -4
  540. package/src/core/supervisor/service.ts +7 -6
  541. package/src/core/work/state.ts +8 -7
  542. package/src/core/workflow/adapters.ts +15 -0
  543. package/src/core/workflow/approvals.ts +6 -5
  544. package/src/core/workflow/billing.ts +34 -4
  545. package/src/core/workflow/durable-record.ts +4 -3
  546. package/src/core/workflow/engine.ts +38 -1
  547. package/src/core/workflow/live-session-v3.ts +2 -3
  548. package/src/core/workflow/run-state.ts +3 -2
  549. package/src/core/workflow/sandbox-projection.ts +38 -2
  550. package/src/core/workflow/spawn-claude.ts +5 -1
  551. package/src/core/workflow/spawn-codex.ts +18 -1
  552. package/src/core/workflow/spawn-cursor.ts +5 -1
  553. package/src/core/workflow/spawn-opencode.ts +153 -0
  554. package/src/core/workflow/transcript.ts +3 -2
  555. package/src/core/workflow/types.ts +62 -2
  556. package/src/core/workflow/worker-access.ts +525 -0
  557. package/src/core/workflow/workspaces/leases.ts +5 -4
  558. package/src/core/workflow/workspaces/local-git.ts +3 -2
  559. package/src/core/workflow/workspaces/paths.ts +2 -1
  560. package/src/core/workflow/workspaces/state.ts +10 -9
  561. package/src/lazy-commands.ts +11 -1
  562. package/src/lib/agent-browser/client.ts +18 -0
  563. package/src/lib/browser/batch-steps.ts +79 -0
  564. package/src/lib/browser/client.ts +147 -9
  565. package/src/lib/browser/collect/collector.ts +306 -0
  566. package/src/lib/browser/collect/fields.ts +87 -0
  567. package/src/lib/browser/collect/index.ts +47 -0
  568. package/src/lib/browser/collect/page-driver.ts +327 -0
  569. package/src/lib/browser/collect/presets.ts +237 -0
  570. package/src/lib/browser/collect/scroll-plan.ts +179 -0
  571. package/src/lib/browser/identity.ts +64 -0
  572. package/src/lib/browser/index.ts +16 -1
  573. package/src/lib/browser/launch-args.ts +53 -1
  574. package/src/lib/browser/page-review-judge.ts +16 -0
  575. package/src/lib/browser/qa-run-contracts.ts +11 -0
  576. package/src/lib/browser/qa-run.ts +1 -0
  577. package/src/lib/browser/user-agent.ts +130 -0
  578. package/src/lib/browser/windows-chrome.ts +227 -0
  579. package/src/lib/claude-desktop-share.ts +511 -0
  580. package/src/lib/disk-usage.ts +347 -0
  581. package/src/lib/docs-lint.ts +8 -3
  582. package/src/lib/docs-metadata-managed.ts +21 -0
  583. package/src/lib/guarded-remove.ts +376 -0
  584. package/src/lib/identities/assume.ts +7 -7
  585. package/src/lib/instructions/apply.ts +2 -0
  586. package/src/lib/instructions/templates.ts +8 -8
  587. package/src/lib/pace/index.ts +14 -0
  588. package/src/lib/pace/pace.ts +370 -0
  589. package/src/lib/tunnel/error-page.ts +25 -9
  590. package/src/lib/tunnel/forward-headers.ts +16 -0
  591. package/src/lib/tunnel/gate.ts +39 -10
  592. package/src/lib/tunnel/path-scope.ts +73 -0
  593. package/src/lib/tunnel/state.ts +20 -3
  594. package/src/lib/webview/index.ts +13 -0
  595. package/src/lib/webview/webview.ts +457 -0
@@ -13,6 +13,11 @@ import {
13
13
  cursorSpawner,
14
14
  normalizeCursorResult,
15
15
  } from "../workflow/spawn-cursor.ts";
16
+ import {
17
+ buildOpenCodeInvocation,
18
+ normalizeOpenCodeResult,
19
+ openCodeSpawner,
20
+ } from "../workflow/spawn-opencode.ts";
16
21
  import {
17
22
  BUILTIN_ADAPTER_IDS,
18
23
  BUILTIN_ADAPTER_PROFILES,
@@ -85,6 +90,38 @@ const BUILTIN_ADAPTERS: Record<BuiltinAdapterId, Adapter> = {
85
90
  },
86
91
  },
87
92
  },
93
+ opencode: {
94
+ profile: BUILTIN_ADAPTER_PROFILES.opencode,
95
+ spawn: openCodeSpawner,
96
+ buildInvocation: buildOpenCodeInvocation,
97
+ normalizeResult: normalizeOpenCodeResult,
98
+ fixture: {
99
+ // `opencode run --format json` streams NDJSON: a step-start line then one
100
+ // or more text parts, each carrying the same sessionID.
101
+ raw: {
102
+ stdout: [
103
+ JSON.stringify({
104
+ type: "step_start",
105
+ sessionID: "opencode-bench-session",
106
+ part: { type: "step-start" },
107
+ }),
108
+ JSON.stringify({
109
+ type: "text",
110
+ sessionID: "opencode-bench-session",
111
+ part: { type: "text", text: "HARNERY_BENCH_OK" },
112
+ }),
113
+ ].join("\n"),
114
+ stderr: "",
115
+ exitCode: 0,
116
+ durationMs: 11,
117
+ },
118
+ expected: {
119
+ ok: true,
120
+ text: "HARNERY_BENCH_OK",
121
+ sessionId: "opencode-bench-session",
122
+ },
123
+ },
124
+ },
88
125
  };
89
126
 
90
127
  /** Mutable registry for embedders, initialized empty unless adapters are
@@ -67,6 +67,16 @@ export interface AdapterProfile {
67
67
  /** How this adapter projects host filesystem policy into the vendor's own
68
68
  * sandbox (ADR 0039). Absent means it cannot project any of it. */
69
69
  sandboxProjection?: AdapterSandboxProjection;
70
+ /** Vendor-native arguments that launch a worker with no vendor sandbox
71
+ * (ADR 0192). Absent means the adapter has no distinguishable full-access
72
+ * mode, so a worker on it never qualifies for one. */
73
+ fullAccess?: AdapterFullAccessRendering;
74
+ }
75
+
76
+ /** How an adapter renders an unsandboxed launch (ADR 0192). The spawner emits
77
+ * exactly these arguments, so the declaration and the argv cannot drift. */
78
+ export interface AdapterFullAccessRendering {
79
+ argv: readonly string[];
70
80
  }
71
81
 
72
82
  /** Fully planned child invocation. `resultFile` is used by adapters such as
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import { spawnSync } from "node:child_process";
14
- import type { EventAdapterIdV3 } from "../events/v3/adapter-id.ts";
14
+ import { type EventAdapterIdV3, eventAdapterIdV3FromPlatform } from "../events/v3/adapter-id.ts";
15
15
  import type { LiveCoordinationObservationV3 } from "../events/v3/live-observation.ts";
16
16
  import { coordBinPath } from "./coord-bin.ts";
17
17
  import { resolveCoordRoot } from "./coord-client.ts";
@@ -94,10 +94,7 @@ export function emitEventV3(input: EventV3EmitInput): boolean {
94
94
  * Normalize the heartbeat's `platform` field to the canonical Adapter type.
95
95
  */
96
96
  export function normalizeAdapter(platform: string | undefined): EventAdapterIdV3 {
97
- if (platform === "cursor") return "cursor";
98
- if (platform === "codex") return "codex";
99
- if (platform === "openclaw") return "openclaw";
100
- return "claude-code";
97
+ return eventAdapterIdV3FromPlatform(platform, { context: "canonical-emit" });
101
98
  }
102
99
 
103
100
  /** Producer joins use the private native session ID, never its V3 fingerprint. */
@@ -13,6 +13,8 @@ import { appendFile, mkdir } from "node:fs/promises";
13
13
  import { hostname } from "node:os";
14
14
  import { dirname, join, resolve } from "node:path";
15
15
  import { coordEnv } from "../../lib/env.ts";
16
+ import { normalizeAdapter, adapterFromPlatform as sharedAdapterFromPlatform } from "../adapter.ts";
17
+ import { resolveBinName } from "../config.ts";
16
18
  import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.ts";
17
19
  import { acquireNoClobberLease } from "../workflow/workspaces/leases.ts";
18
20
 
@@ -166,12 +168,6 @@ async function handleProject(root: string, rest: string[]): Promise<number> {
166
168
  return view.authority_safe ? 0 : 1;
167
169
  }
168
170
 
169
- function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "codex" {
170
- if (platform === "cursor") return "cursor";
171
- if (platform === "codex") return "codex";
172
- return "claude-code";
173
- }
174
-
175
171
  const coordinationRetryCell = new Int32Array(new SharedArrayBuffer(4));
176
172
  const COORDINATION_RETRY_ATTEMPTS = 240;
177
173
  const COORDINATION_RETRY_DELAY_MS = 25;
@@ -281,7 +277,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
281
277
  coordRoot: root,
282
278
  owner,
283
279
  nativeSessionId: before?.session_id ?? owner,
284
- adapter: adapterFromPlatform(before?.platform),
280
+ adapter: sharedAdapterFromPlatform(before?.platform, { context: "agent-coord" }),
285
281
  task,
286
282
  });
287
283
  break;
@@ -312,9 +308,22 @@ async function handleStateAction(root: string, action: string, rest: string[]):
312
308
  hb = writer.setAssignedNameCache(root, owner, name, "session");
313
309
  }
314
310
  } catch (error) {
315
- process.stderr.write(
316
- `agent-coord set-task: V3 authority refused (${error instanceof Error ? error.message : String(error)})\n`,
317
- );
311
+ const detail = error instanceof Error ? error.message : String(error);
312
+ // A missing heartbeat usually means the session's generation ended
313
+ // while its process lived on, so name the reopen command (ADR 0088).
314
+ // A still-live generation whose authority the ledger withholds looks
315
+ // the same here; name its diagnostics instead, since reopen cannot apply.
316
+ const { describeLiveAuthorityBlockV3, liveAuthorityBlockHintV3, liveAuthorityBlockV3 } =
317
+ await import("./state/live-coordination-view.ts");
318
+ const block = detail.includes("heartbeat_missing:")
319
+ ? liveAuthorityBlockV3(root, owner)
320
+ : null;
321
+ const hint = block
322
+ ? `; ${describeLiveAuthorityBlockV3(block)}; ${liveAuthorityBlockHintV3(resolveBinName(root))}`
323
+ : detail.includes("heartbeat_missing:")
324
+ ? `; run \`${resolveBinName(root)} agents lifecycle active\` to open a fresh generation for this continuing session`
325
+ : "";
326
+ process.stderr.write(`agent-coord set-task: V3 authority refused (${detail})${hint}\n`);
318
327
  return 1;
319
328
  }
320
329
  if (!hb) {
@@ -347,7 +356,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
347
356
  coordRoot: root,
348
357
  owner,
349
358
  nativeSessionId: before?.session_id ?? owner,
350
- adapter: adapterFromPlatform(before?.platform),
359
+ adapter: sharedAdapterFromPlatform(before?.platform, { context: "agent-coord" }),
351
360
  operation: "released",
352
361
  path,
353
362
  access: "write",
@@ -408,7 +417,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
408
417
  coordRoot: root,
409
418
  owner,
410
419
  nativeSessionId: sessionId ?? owner,
411
- adapter: adapterFromPlatform(adapter),
420
+ adapter: sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
412
421
  });
413
422
  }
414
423
  const { repairLiveCoordinationHeartbeat } = await import(
@@ -418,7 +427,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
418
427
  root,
419
428
  owner,
420
429
  sessionId ?? owner,
421
- adapterFromPlatform(adapter),
430
+ sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
422
431
  model,
423
432
  );
424
433
  } catch (error) {
@@ -453,7 +462,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
453
462
  root,
454
463
  owner,
455
464
  sessionId ?? owner,
456
- adapterFromPlatform(adapter),
465
+ sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
457
466
  );
458
467
  if (!heartbeat) {
459
468
  throw new Error("authoritative coordination cache could not be materialized");
@@ -471,7 +480,7 @@ async function handleStateAction(root: string, action: string, rest: string[]):
471
480
  root,
472
481
  owner,
473
482
  sessionId ?? owner,
474
- adapterFromPlatform(adapter),
483
+ sharedAdapterFromPlatform(adapter, { context: "agent-coord" }),
475
484
  );
476
485
  process.stdout.write(
477
486
  `${JSON.stringify({
@@ -875,7 +884,7 @@ async function handleEmitEvent(root: string, rest: string[]): Promise<number> {
875
884
  const eventType = args.type;
876
885
  const instanceId = args.owner;
877
886
  const sessionId = args.session;
878
- const adapter = args.adapter as "claude-code" | "cursor" | "codex" | undefined;
887
+ const adapter = normalizeAdapter(args.adapter) ?? undefined;
879
888
  const dataJson = args["data-stdin"] === "true" ? await readStdin() : "";
880
889
 
881
890
  if (!eventType || !instanceId || !sessionId || !adapter || !dataJson) {
@@ -1063,7 +1072,7 @@ async function handleGitHook(fallbackRoot: string, rest: string[]): Promise<numb
1063
1072
  owner,
1064
1073
  subject: hit.instance_id,
1065
1074
  nativeSessionId: hit.session_id ?? owner,
1066
- adapter: adapterFromPlatform(hit.platform),
1075
+ adapter: sharedAdapterFromPlatform(hit.platform, { context: "agent-coord" }),
1067
1076
  operation: "released",
1068
1077
  path,
1069
1078
  access: "write",
@@ -527,6 +527,10 @@ const SESSION_ID_ENV_VARS = [
527
527
  "CURSOR_CONVERSATION_ID",
528
528
  "CODEX_SESSION_ID",
529
529
  "CODEX_THREAD_ID",
530
+ // OpenCode exports no session id into the tool shell; the Harnery OpenCode
531
+ // plugin stamps this via shell.hook("create.before") so a coord CLI run as a
532
+ // Bash tool recovers its identity.
533
+ "OPENCODE_SESSION_ID",
530
534
  ] as const;
531
535
 
532
536
  /** Read normalized candidates from the first non-empty adapter session-id env var. */
@@ -637,10 +641,12 @@ export function resolveSingleActiveOwner(root: string): string | null {
637
641
  return live.size === 1 ? [...live][0]! : null;
638
642
  }
639
643
 
640
- function adapterCandidatesFromEnv(): Array<"claude-code" | "codex" | "cursor"> {
644
+ function adapterCandidatesFromEnv(): Array<"claude-code" | "codex" | "cursor" | "opencode"> {
641
645
  const value = process.env.HARNERY_AGENT_COORD_PLATFORM?.trim();
642
- if (value === "claude-code" || value === "codex" || value === "cursor") return [value];
643
- return ["claude-code", "codex", "cursor"];
646
+ if (value === "claude-code" || value === "codex" || value === "cursor" || value === "opencode") {
647
+ return [value];
648
+ }
649
+ return ["claude-code", "codex", "cursor", "opencode"];
644
650
  }
645
651
 
646
652
  function nativeOwnerForV3Instance(root: string, instanceId: string): string {
@@ -126,6 +126,7 @@ export function renderSessionContext(opts: RenderOpts): string {
126
126
  if (d.missing.length > 0)
127
127
  bits.push(`missing: ${d.missing.map((m) => m.subcommand).join(", ")}`);
128
128
  if (d.orphans.length > 0) bits.push(`orphaned: ${d.orphans.join(", ")}`);
129
+ if (d.stale.length > 0) bits.push(`outdated: ${d.stale.map((m) => m.subcommand).join(", ")}`);
129
130
  return ` - ${d.settingsFile} — ${bits.join("; ")}`;
130
131
  });
131
132
  messages.push(
@@ -17,6 +17,7 @@
17
17
  import { spawnSync } from "node:child_process";
18
18
  import { existsSync } from "node:fs";
19
19
  import { join } from "node:path";
20
+ import { adapterFromPlatform as sharedAdapterFromPlatform } from "../../adapter.ts";
20
21
  import { recordLiveClaimChangeV3 } from "../live-authority-v3.ts";
21
22
  import { readLiveCoordinationRows } from "../state/live-coordination-view.ts";
22
23
 
@@ -248,7 +249,7 @@ function acquireClaimThroughLedger(coordRoot: string, req: ClaimRequest): boolea
248
249
  coordRoot,
249
250
  owner: req.instance_id,
250
251
  nativeSessionId: req.session_id ?? owner?.session_id ?? req.instance_id,
251
- adapter: adapterFromPlatform(owner?.platform),
252
+ adapter: sharedAdapterFromPlatform(owner?.platform, { context: "claim-conflict" }),
252
253
  operation: "acquired",
253
254
  path: req.path,
254
255
  access: "write",
@@ -272,7 +273,7 @@ function releaseClaimThroughLedger(
272
273
  owner: actor.instance_id,
273
274
  subject: subjectInstanceId,
274
275
  nativeSessionId: actor.session_id ?? owner?.session_id ?? actor.instance_id,
275
- adapter: adapterFromPlatform(owner?.platform),
276
+ adapter: sharedAdapterFromPlatform(owner?.platform, { context: "claim-conflict" }),
276
277
  operation: "released",
277
278
  path: relPath,
278
279
  access: "write",
@@ -283,12 +284,6 @@ function releaseClaimThroughLedger(
283
284
  }
284
285
  }
285
286
 
286
- function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "codex" {
287
- if (platform === "cursor") return "cursor";
288
- if (platform === "codex") return "codex";
289
- return "claude-code";
290
- }
291
-
292
287
  function authorityUnavailable(path: string, operation: string): VerdictResult {
293
288
  return {
294
289
  allow: false,
@@ -23,6 +23,7 @@
23
23
  import { spawnSync } from "node:child_process";
24
24
  import { appendFileSync, existsSync } from "node:fs";
25
25
  import { basename, dirname, join } from "node:path";
26
+ import { adapterFromPlatform as sharedAdapterFromPlatform } from "../../adapter.ts";
26
27
  import { coordFreshnessSeconds } from "../../config.ts";
27
28
  import { resolveOwner } from "../../hooks/resolve/owner.ts";
28
29
  import { recordLiveClaimChangeV3 } from "../live-authority-v3.ts";
@@ -232,7 +233,7 @@ function retainBlockedStagedPaths(
232
233
  coordRoot,
233
234
  owner: instanceId,
234
235
  nativeSessionId: self.session_id ?? sessionId,
235
- adapter: adapterFromPlatform(self.platform),
236
+ adapter: sharedAdapterFromPlatform(self.platform, { context: "commit-conflict" }),
236
237
  operation: "acquired",
237
238
  path,
238
239
  access: "write",
@@ -244,12 +245,6 @@ function retainBlockedStagedPaths(
244
245
  }
245
246
  }
246
247
 
247
- function adapterFromPlatform(platform: unknown): "claude-code" | "cursor" | "codex" {
248
- if (platform === "cursor") return "cursor";
249
- if (platform === "codex") return "codex";
250
- return "claude-code";
251
- }
252
-
253
248
  function findOverlap(
254
249
  staged: string,
255
250
  files: readonly string[],
@@ -32,6 +32,8 @@ export interface StopHookRequest {
32
32
  turn_window?: { start_ms: number; end_ms: number };
33
33
  stop_hook_active?: boolean;
34
34
  status_box_present_strict?: boolean;
35
+ /** Current observation overrides an older failed terminal during remediation. */
36
+ session_name_observation_unavailable?: boolean;
35
37
  bypass?: boolean;
36
38
  workflow_child?: boolean;
37
39
  }
@@ -188,7 +190,7 @@ export function evaluateStopHookV3Events(
188
190
 
189
191
  // Claude Code can prove session-name presentation from assistant-only text.
190
192
  // Cursor cannot expose that text and Codex returned observe-only above.
191
- if (req.adapter !== "cursor") {
193
+ if (req.adapter !== "cursor" && !req.session_name_observation_unavailable) {
192
194
  const naming = turnTerminals
193
195
  .map((event) => observedNaming(event.payload.ritual?.session_name))
194
196
  .filter((value): value is { required: boolean; present: boolean } => value !== undefined);
@@ -4,7 +4,7 @@
4
4
  * `writeSessionEvent` records command spans in the canonical V3 ledger.
5
5
  */
6
6
 
7
- import { randomBytes } from "node:crypto";
7
+ import { createHash, type Hash, randomBytes } from "node:crypto";
8
8
  import { existsSync, readFileSync } from "node:fs";
9
9
  import { resolve } from "node:path";
10
10
  // Kept dependency-light: vendored verbatim into a downstream consumer, so no coordEnv import.
@@ -64,18 +64,52 @@ export function readLastIntent(instanceId?: string): string | null {
64
64
  }
65
65
  }
66
66
 
67
- const outputSequence = new Map<string, number>();
67
+ type OutputStream = "stdout" | "stderr" | "combined";
68
+
69
+ interface OutputSummary {
70
+ stream: OutputStream;
71
+ bytes: number;
72
+ lines: number;
73
+ chunks: number;
74
+ hash: Hash;
75
+ }
76
+
77
+ interface PendingCommand {
78
+ coordRoot: string;
79
+ fields: Record<string, unknown>;
80
+ streams: Map<OutputStream, OutputSummary>;
81
+ }
82
+
83
+ const pendingCommands = new Map<string, PendingCommand>();
84
+ let exitFlushInstalled = false;
85
+
86
+ function commandKey(fields: Record<string, unknown>): string | undefined {
87
+ return typeof fields.instance_id === "string" && typeof fields.cmd_id === "string"
88
+ ? JSON.stringify([fields.instance_id, fields.cmd_id])
89
+ : undefined;
90
+ }
91
+
92
+ function flushCommandOutput(command: PendingCommand): void {
93
+ for (const summary of command.streams.values()) {
94
+ recordCommandObservation("command.output_observed", command.fields, command.coordRoot, summary);
95
+ }
96
+ command.streams.clear();
97
+ }
68
98
 
69
99
  /** Emit a command/narration event to the canonical stream. Swallows every
70
100
  * error and skips when identity can't be resolved: telemetry must never break
71
101
  * or slow down a command. */
72
- function recordCommandObservation(type: SessionEventType, fields: Record<string, unknown>): void {
102
+ function recordCommandObservation(
103
+ type: SessionEventType,
104
+ fields: Record<string, unknown>,
105
+ coordRoot: string,
106
+ summary?: OutputSummary,
107
+ ): boolean {
73
108
  const instanceId = typeof fields.instance_id === "string" ? fields.instance_id : undefined;
74
- if (!instanceId) return;
109
+ if (!instanceId) return false;
75
110
  try {
76
- const coordRoot = coordinationRootPath();
77
111
  const route = resolveLiveEventLedgerRouteV3(coordRoot);
78
- if (route.state === "blocked") return;
112
+ if (route.state === "blocked") return false;
79
113
  const liveInstanceId = liveInstanceIdV3(instanceId);
80
114
  const hook = readHookProducerStateByInstanceV3(coordRoot, liveInstanceId);
81
115
  if (!hook) {
@@ -84,10 +118,10 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
84
118
  instance_id: instanceId,
85
119
  reason: "hook_generation_not_found",
86
120
  });
87
- return;
121
+ return false;
88
122
  }
89
- const command = commandSignalAndObservation(type, fields);
90
- if (!command) return;
123
+ const command = commandSignalAndObservation(type, fields, summary);
124
+ if (!command) return false;
91
125
  const result = recordCommandSignalV3({
92
126
  coordRoot,
93
127
  mode: route.mode,
@@ -105,7 +139,7 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
105
139
  const expectedLifecycleReopenGap =
106
140
  result.reason === "turn_not_started" &&
107
141
  hook.session_start_derivation === "approved_lifecycle_reopen";
108
- if (expectedLifecycleReopenGap) return;
142
+ if (expectedLifecycleReopenGap) return false;
109
143
  writeProducerDiagnosticV3(coordRoot, "command_emit_unjoinable", {
110
144
  type,
111
145
  instance_id: instanceId,
@@ -120,10 +154,10 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
120
154
  result_state: result.state,
121
155
  });
122
156
  }
157
+ return result.state === "recorded" || result.state === "already_recorded";
123
158
  } catch (error) {
124
159
  // Telemetry must never break the command, but the loss is preserved.
125
160
  try {
126
- const coordRoot = coordinationRootPath();
127
161
  writeProducerDiagnosticV3(coordRoot, "command_emit_failed", {
128
162
  type,
129
163
  instance_id: instanceId,
@@ -132,17 +166,26 @@ function recordCommandObservation(type: SessionEventType, fields: Record<string,
132
166
  } catch {
133
167
  /* diagnostics are best-effort */
134
168
  }
169
+ return false;
135
170
  }
136
171
  }
137
172
 
173
+ /** Count the non-empty lines in one output chunk; a single event may carry many. */
174
+ export function countOutputLines(text: string): number {
175
+ if (!text) return 0;
176
+ let count = 0;
177
+ for (const line of text.split("\n")) if (line.length > 0) count += 1;
178
+ return count;
179
+ }
180
+
138
181
  function commandSignalAndObservation(
139
182
  type: SessionEventType,
140
183
  fields: Record<string, unknown>,
184
+ summary?: OutputSummary,
141
185
  ): { signal: CommandSignalV3; observation: CommandObservationV3 } | undefined {
142
186
  const commandId = typeof fields.cmd_id === "string" ? fields.cmd_id : undefined;
143
187
  if (!commandId) return undefined;
144
188
  if (type === "command.started") {
145
- outputSequence.set(commandId, 0);
146
189
  const command = typeof fields.cmd === "string" ? fields.cmd : "";
147
190
  const executable = command.trim().split(/\s+/, 1)[0] || "unknown";
148
191
  return {
@@ -161,24 +204,25 @@ function commandSignalAndObservation(
161
204
  };
162
205
  }
163
206
  if (type === "command.output_observed") {
164
- const sequence = (outputSequence.get(commandId) ?? 0) + 1;
165
- outputSequence.set(commandId, sequence);
166
- const line = typeof fields.line === "string" ? fields.line : "";
167
- const stream =
168
- fields.stream === "stdout" || fields.stream === "stderr" ? fields.stream : "combined";
207
+ if (!summary) return undefined;
169
208
  return {
170
209
  signal: "command.output_observed",
171
210
  observation: {
172
211
  native_command_id: commandId,
173
- native_observation_id: `${commandId}:output:${sequence}`,
174
- stream,
175
- output: line,
176
- output_bytes: Buffer.byteLength(line, "utf8"),
177
- output_lines: line ? 1 : 0,
212
+ native_observation_id: `${commandId}:output-summary:${summary.stream}`,
213
+ stream: summary.stream,
214
+ // The normalizer HMACs this bounded descriptor with the generation key.
215
+ // Neither raw output nor its unkeyed digest is written to the ledger.
216
+ output: {
217
+ format: "harnery-output-chunks-v1",
218
+ chunks: summary.chunks,
219
+ sha256: summary.hash.digest("hex"),
220
+ },
221
+ output_bytes: summary.bytes,
222
+ output_lines: summary.lines,
178
223
  },
179
224
  };
180
225
  }
181
- outputSequence.delete(commandId);
182
226
  const exitCode =
183
227
  typeof fields.exit === "number" && Number.isSafeInteger(fields.exit) ? fields.exit : undefined;
184
228
  return {
@@ -197,14 +241,64 @@ function commandSignalAndObservation(
197
241
  }
198
242
 
199
243
  /**
200
- * Record a command event in V3. Best-effort, never throws into the caller;
201
- * telemetry must not break or slow a command.
244
+ * Start/completion use the durable V3 recorder. Output only updates bounded
245
+ * per-stream counters and hashes; summaries flush before completion or at
246
+ * process exit. A forced kill can lose unflushed summaries (ADR 0188).
247
+ * Best-effort: telemetry never throws into the caller.
202
248
  */
203
249
  export function writeSessionEvent(
204
250
  type: SessionEventType,
205
251
  fields: Record<string, unknown> = {},
206
252
  ): void {
207
- recordCommandObservation(type, fields);
253
+ try {
254
+ const key = commandKey(fields);
255
+ if (!key) return;
256
+ if (type === "command.output_observed") {
257
+ const command = pendingCommands.get(key);
258
+ if (!command) return;
259
+ const stream =
260
+ fields.stream === "stdout" || fields.stream === "stderr" ? fields.stream : "combined";
261
+ let summary = command.streams.get(stream);
262
+ if (!summary) {
263
+ summary = { stream, bytes: 0, lines: 0, chunks: 0, hash: createHash("sha256") };
264
+ command.streams.set(stream, summary);
265
+ }
266
+ const line = typeof fields.line === "string" ? fields.line : "";
267
+ const normalized = line.normalize("NFC");
268
+ // Length framing preserves chunk boundaries, including empty chunks.
269
+ summary.hash.update(`${Buffer.byteLength(normalized, "utf8")}:`).update(normalized);
270
+ summary.bytes += Buffer.byteLength(line, "utf8");
271
+ summary.lines += countOutputLines(line);
272
+ summary.chunks += 1;
273
+ return;
274
+ }
275
+ const command = pendingCommands.get(key);
276
+ const coordRoot = command?.coordRoot ?? coordinationRootPath();
277
+ if (type === "command.completed") {
278
+ pendingCommands.delete(key);
279
+ if (command) flushCommandOutput(command);
280
+ recordCommandObservation(type, fields, coordRoot);
281
+ } else if (recordCommandObservation(type, fields, coordRoot) && !command) {
282
+ pendingCommands.set(key, {
283
+ coordRoot,
284
+ fields: {
285
+ instance_id: fields.instance_id,
286
+ cmd_id: fields.cmd_id,
287
+ bridge: fields.bridge,
288
+ },
289
+ streams: new Map(),
290
+ });
291
+ if (!exitFlushInstalled) {
292
+ exitFlushInstalled = true;
293
+ process.once("exit", () => {
294
+ for (const pending of pendingCommands.values()) flushCommandOutput(pending);
295
+ pendingCommands.clear();
296
+ });
297
+ }
298
+ }
299
+ } catch {
300
+ // Root resolution and in-memory bookkeeping must not break the command.
301
+ }
208
302
  }
209
303
 
210
304
  /** Trim long values to keep individual events small. */
@@ -2,6 +2,7 @@ import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
2
2
  import { join, resolve } from "node:path";
3
3
  import type { ApprovedSessionEndReasonV3 } from "../events/v3/producers/recorder.ts";
4
4
  import { EVENT_V3_LEDGER_RELATIVE_ROOT } from "../events/v3/reader.ts";
5
+ import { stateModeTooOpen } from "../storage/modes.ts";
5
6
 
6
7
  export const SESSION_FINALIZATION_REQUEST_FORMAT_V3 =
7
8
  "harnery-v3-session-finalization-request" as const;
@@ -72,7 +73,7 @@ export function listSessionFinalizationRequestsV3(
72
73
 
73
74
  export function readSessionFinalizationRequestV3(filePath: string): SessionFinalizationRequestV3 {
74
75
  const metadata = lstatSync(filePath);
75
- if (!metadata.isFile() || metadata.isSymbolicLink() || (metadata.mode & 0o077) !== 0) {
76
+ if (!metadata.isFile() || metadata.isSymbolicLink() || stateModeTooOpen(metadata.mode)) {
76
77
  throw new Error("V3 session finalization request is unsafe");
77
78
  }
78
79
  const request = JSON.parse(readFileSync(filePath, "utf8")) as SessionFinalizationRequestV3;
@@ -32,6 +32,7 @@ import {
32
32
  import { readLedgerV3 } from "../events/v3/reader.ts";
33
33
  import { assertEventV3 } from "../events/v3/validate.ts";
34
34
  import { EVENT_V3_LEDGER_RELATIVE_ROOT, writeEventV3 } from "../events/v3/writer.ts";
35
+ import { stateDirMode, stateFileMode } from "../storage/modes.ts";
35
36
  import { fsyncParentDirectory } from "../workflow/durable-record.ts";
36
37
  import { acquireNoClobberLease } from "../workflow/workspaces/leases.ts";
37
38
  import { readCodexArchiveObservationsV3 } from "./codex-archive-v3.ts";
@@ -901,20 +902,20 @@ function writeRequest(
901
902
  create = false,
902
903
  ): void {
903
904
  const directory = sessionFinalizationRequestDirectoryV3(coordRoot);
904
- mkdirSync(directory, { recursive: true, mode: 0o700 });
905
- chmodSync(directory, 0o700);
905
+ mkdirSync(directory, { recursive: true, mode: stateDirMode() });
906
+ chmodSync(directory, stateDirMode());
906
907
  const path = sessionFinalizationRequestPathV3(coordRoot, request.request_id);
907
908
  if (create && existsSync(path)) throw new Error("V3 finalization request already exists");
908
909
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
909
910
  let fd: number | undefined;
910
911
  try {
911
- fd = openSync(temporary, "wx", 0o600);
912
+ fd = openSync(temporary, "wx", stateFileMode());
912
913
  writeFileSync(fd, `${JSON.stringify(request)}\n`, "utf8");
913
914
  fsyncSync(fd);
914
915
  closeSync(fd);
915
916
  fd = undefined;
916
917
  renameSync(temporary, path);
917
- chmodSync(path, 0o600);
918
+ chmodSync(path, stateFileMode());
918
919
  fsyncParentDirectory(path);
919
920
  } finally {
920
921
  if (fd !== undefined) closeSync(fd);