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
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Install-side owner of the OpenCode plugin files: what `harn init --adapter
3
+ * opencode` writes, what `--check`/`doctor` compare against, and what `deinit`
4
+ * removes. The plugin itself lives in `opencode-plugin/src/index.ts` and is
5
+ * copied verbatim under a hash-stamped ownership header, the same fully-owned
6
+ * file contract as the shipped skills (`lib/instructions/splice.ts`).
7
+ *
8
+ * Layout under the project root (`ADAPTER_SPECS.opencode.settingsFile` names
9
+ * the entry file):
10
+ *
11
+ * .opencode/plugins/harnery/index.ts # the plugin, header + verbatim source
12
+ * .opencode/plugins/harnery/harnery.json # { schema, agentHook } written by init
13
+ *
14
+ * OpenCode auto-discovers every directory under `.opencode/plugins/`, so no
15
+ * `opencode.json` edit is needed and a configured-plugin entry is never
16
+ * written (OpenCode also refuses a configured local *file*; only directories
17
+ * load that way).
18
+ */
19
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
20
+ import { dirname, resolve } from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+ import { shortHash } from "../../../lib/instructions/splice.js";
23
+ import { ADAPTER_SPECS } from "./events.js";
24
+ export const OPENCODE_PLUGIN_ENTRY = ADAPTER_SPECS.opencode.settingsFile;
25
+ export const OPENCODE_PLUGIN_DIR = dirname(OPENCODE_PLUGIN_ENTRY);
26
+ export const OPENCODE_PLUGIN_CONFIG = `${OPENCODE_PLUGIN_DIR}/harnery.json`;
27
+ export const OPENCODE_PLUGIN_CONFIG_SCHEMA = "harnery-opencode-plugin/v1";
28
+ const HEADER_RE = /^\/\/ harnery:generated opencode-plugin v=([0-9a-f]{8});[^\n]*\n/;
29
+ /** Package-relative path of the shipped plugin source (also listed in `files`). */
30
+ const PLUGIN_SOURCE = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..", "opencode-plugin", "src", "index.ts");
31
+ /** The plugin source as shipped, trimmed so header + body hashing is stable. */
32
+ export function openCodePluginSource() {
33
+ return readFileSync(PLUGIN_SOURCE, "utf8").trim();
34
+ }
35
+ /** Render the installed entry file: ownership header, then the verbatim source. */
36
+ export function renderOpenCodePluginEntry(binName, source = openCodePluginSource()) {
37
+ const body = source.trim();
38
+ const header = `// harnery:generated opencode-plugin v=${shortHash(body)}; machine-owned; ` +
39
+ `regenerated by \`${binName} init --adapter opencode\`, removed by \`${binName} deinit --adapter opencode\`. ` +
40
+ "Edit harnery's opencode-plugin/src/index.ts, not this file.";
41
+ return `${header}\n${body}\n`;
42
+ }
43
+ /** Render the sibling config the plugin reads to find the `agent-hook` launcher. */
44
+ export function renderOpenCodePluginConfig(agentHook) {
45
+ return `${JSON.stringify({ schema: OPENCODE_PLUGIN_CONFIG_SCHEMA, agentHook }, null, 2)}\n`;
46
+ }
47
+ /** True when the content carries harnery's plugin ownership header. */
48
+ export function isOwnedOpenCodePlugin(content) {
49
+ return HEADER_RE.test(content);
50
+ }
51
+ /**
52
+ * Compare the installed plugin files with what init would write now. Pure
53
+ * except for reads; never writes. `foreign` means an entry file exists at the
54
+ * harnery path without harnery's header, which init refuses to overwrite.
55
+ */
56
+ export function checkOpenCodePlugin(projectRoot, expected) {
57
+ const entryPath = resolve(projectRoot, OPENCODE_PLUGIN_ENTRY);
58
+ const configPath = resolve(projectRoot, OPENCODE_PLUGIN_CONFIG);
59
+ if (!existsSync(entryPath))
60
+ return { status: "missing", issues: [] };
61
+ const content = readFileSync(entryPath, "utf8");
62
+ const match = HEADER_RE.exec(content);
63
+ if (!match) {
64
+ return {
65
+ status: "foreign",
66
+ issues: [`${OPENCODE_PLUGIN_ENTRY}: exists without harnery's ownership header`],
67
+ };
68
+ }
69
+ const issues = [];
70
+ const body = content.slice(match[0].length).trim();
71
+ const fresh = (expected.source ?? openCodePluginSource()).trim();
72
+ if (match[1] !== shortHash(fresh) || body !== fresh) {
73
+ issues.push(`${OPENCODE_PLUGIN_ENTRY}: plugin source is stale (re-run init)`);
74
+ }
75
+ if (!existsSync(configPath)) {
76
+ issues.push(`${OPENCODE_PLUGIN_CONFIG}: missing`);
77
+ }
78
+ else if (readFileSync(configPath, "utf8") !== renderOpenCodePluginConfig(expected.agentHook)) {
79
+ issues.push(`${OPENCODE_PLUGIN_CONFIG}: stale agent-hook launcher (re-run init)`);
80
+ }
81
+ return { status: issues.length === 0 ? "fresh" : "stale", issues };
82
+ }
83
+ /** Write (or refresh) the plugin directory. Idempotent; a fresh install is a no-op. */
84
+ export function installOpenCodePlugin(projectRoot, opts) {
85
+ const check = checkOpenCodePlugin(projectRoot, opts);
86
+ if (check.status === "foreign") {
87
+ return {
88
+ actions: [],
89
+ error: `✗ ${OPENCODE_PLUGIN_ENTRY} exists but is not harnery's plugin; refusing to overwrite. ` +
90
+ "Move it aside and re-run.",
91
+ };
92
+ }
93
+ if (check.status === "fresh") {
94
+ return { actions: [`· opencode plugin already installed at ${OPENCODE_PLUGIN_DIR}/`] };
95
+ }
96
+ const verb = check.status === "missing" ? "install" : "refresh";
97
+ if (opts.dryRun) {
98
+ return {
99
+ actions: [
100
+ `+ would ${verb} the opencode plugin at ${OPENCODE_PLUGIN_DIR}/ (index.ts + harnery.json)`,
101
+ ...check.issues.map((issue) => ` · ${issue}`),
102
+ ],
103
+ };
104
+ }
105
+ const dir = resolve(projectRoot, OPENCODE_PLUGIN_DIR);
106
+ mkdirSync(dir, { recursive: true });
107
+ writeFileSync(resolve(projectRoot, OPENCODE_PLUGIN_ENTRY), renderOpenCodePluginEntry(opts.binName));
108
+ writeFileSync(resolve(projectRoot, OPENCODE_PLUGIN_CONFIG), renderOpenCodePluginConfig(opts.agentHook));
109
+ return {
110
+ actions: [
111
+ `+ ${verb === "install" ? "installed" : "refreshed"} the opencode plugin at ${OPENCODE_PLUGIN_DIR}/ (index.ts + harnery.json)`,
112
+ ],
113
+ };
114
+ }
115
+ /** Remove the plugin directory when harnery owns it. Leaves a foreign file alone. */
116
+ export function removeOpenCodePlugin(projectRoot, dryRun) {
117
+ const dir = resolve(projectRoot, OPENCODE_PLUGIN_DIR);
118
+ const entryPath = resolve(projectRoot, OPENCODE_PLUGIN_ENTRY);
119
+ if (!existsSync(entryPath)) {
120
+ return [`· ${OPENCODE_PLUGIN_DIR}/ doesn't exist; no plugin to remove`];
121
+ }
122
+ if (!isOwnedOpenCodePlugin(readFileSync(entryPath, "utf8"))) {
123
+ return [`· ${OPENCODE_PLUGIN_ENTRY} is not harnery's plugin; left in place`];
124
+ }
125
+ if (dryRun)
126
+ return [`+ would remove ${OPENCODE_PLUGIN_DIR}/ (harnery-owned plugin)`];
127
+ rmSync(dir, { recursive: true, force: true });
128
+ return [`+ removed ${OPENCODE_PLUGIN_DIR}/ (harnery-owned plugin)`];
129
+ }
@@ -14,6 +14,9 @@
14
14
  * - **Codex**: structurally identical to Claude Code for context and tool
15
15
  * denials. Stop blocks are deliberately suppressed because their automatic
16
16
  * continuation can replace a completed user-facing answer.
17
+ * - **OpenCode**: the Harnery OpenCode plugin reads the Claude Code envelope
18
+ * (`hookSpecificOutput.additionalContext` / `permissionDecision`) and feeds
19
+ * it back through OpenCode's own channels. Stop blocks are suppressed.
17
20
  *
18
21
  * Every helper writes to process.stdout + newline-terminates so callers can
19
22
  * fire-and-forget. Empty text is a no-op.
@@ -46,6 +49,10 @@ export declare function emitDeny(adapter: Adapter, reason: string): void;
46
49
  * answer in clients that retain only the final continuation response. Return
47
50
  * success without output as a defense in depth behind the observe-only
48
51
  * verdict in `agents/rules/stop-hook.ts`.
52
+ * - **OpenCode** has no blocking Stop channel at all: the plugin observes
53
+ * `session.execution.succeeded` after the turn has already completed, so a
54
+ * block could only arrive as a new message. Return success without output;
55
+ * the verdict is still recorded in the ledger.
49
56
  * - **Cursor** ignores stop-hook exit codes (non-zero = fail-open, the turn
50
57
  * proceeds) and re-prompts ONLY via a `followup_message` field in stdout
51
58
  * JSON, which it auto-submits as the next user message: the sanctioned
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/adapter/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAIhD,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,aAAa,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKvF;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC1C,SAAS,CAAC,EAAE,MAAM,GACjB,CAAC,GAAG,CAAC,CAEP;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,CAAC,GAAG,CAAC,CAuBP"}
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/adapter/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAIhD,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,aAAa,CAAC;AAElB,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKvF;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC1C,SAAS,CAAC,EAAE,MAAM,GACjB,CAAC,GAAG,CAAC,CAEP;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,CAAC,GAAG,CAAC,CAuBP"}
@@ -14,6 +14,9 @@
14
14
  * - **Codex**: structurally identical to Claude Code for context and tool
15
15
  * denials. Stop blocks are deliberately suppressed because their automatic
16
16
  * continuation can replace a completed user-facing answer.
17
+ * - **OpenCode**: the Harnery OpenCode plugin reads the Claude Code envelope
18
+ * (`hookSpecificOutput.additionalContext` / `permissionDecision`) and feeds
19
+ * it back through OpenCode's own channels. Stop blocks are suppressed.
17
20
  *
18
21
  * Every helper writes to process.stdout + newline-terminates so callers can
19
22
  * fire-and-forget. Empty text is a no-op.
@@ -50,6 +53,10 @@ export function emitDeny(adapter, reason) {
50
53
  * answer in clients that retain only the final continuation response. Return
51
54
  * success without output as a defense in depth behind the observe-only
52
55
  * verdict in `agents/rules/stop-hook.ts`.
56
+ * - **OpenCode** has no blocking Stop channel at all: the plugin observes
57
+ * `session.execution.succeeded` after the turn has already completed, so a
58
+ * block could only arrive as a new message. Return success without output;
59
+ * the verdict is still recorded in the ledger.
53
60
  * - **Cursor** ignores stop-hook exit codes (non-zero = fail-open, the turn
54
61
  * proceeds) and re-prompts ONLY via a `followup_message` field in stdout
55
62
  * JSON, which it auto-submits as the next user message: the sanctioned
@@ -64,7 +71,7 @@ export function emitStopBlock(adapter, verdict, coordRoot) {
64
71
  * Emit the adapter-specific response for one Stop outcome.
65
72
  */
66
73
  export function emitStopOutcome(adapter, options, coordRoot) {
67
- if (adapter === "codex")
74
+ if (adapter === "codex" || adapter === "opencode")
68
75
  return 0;
69
76
  const verdict = options.verdict;
70
77
  if (!verdict)
@@ -409,7 +409,9 @@ function claudeModelContextCapability(model) {
409
409
  const normalized = model.toLowerCase();
410
410
  const oneMillionTokenModels = new Set([
411
411
  "claude-fable-5",
412
+ "claude-opus-5-5",
412
413
  "claude-opus-5",
414
+ "claude-sonnet-5-5",
413
415
  "claude-sonnet-5",
414
416
  "claude-opus-4-8",
415
417
  "claude-opus-4-7",
@@ -417,7 +419,7 @@ function claudeModelContextCapability(model) {
417
419
  "claude-sonnet-4-6",
418
420
  ]);
419
421
  if (oneMillionTokenModels.has(normalized)) {
420
- return { limit_tokens: 1_000_000, authority: "anthropic_model_capabilities_2026_08" };
422
+ return { limit_tokens: 1_000_000, authority: "anthropic_model_capabilities_2026_09" };
421
423
  }
422
424
  if (normalized === "claude-haiku-4-5" || normalized === "claude-haiku-4-5-20251001") {
423
425
  return { limit_tokens: 200_000, authority: "anthropic_model_capabilities_2026_08" };
@@ -11,21 +11,30 @@
11
11
  * — there's exactly one definition of the `agent-hook <subcommand>` match.
12
12
  */
13
13
  import { type AdapterId, type AdapterSpec, type HookEntryShape, type HookEvent } from "./events.js";
14
- /** Claude Code + Codex entry: `{ hooks: [{ type, command }] }`. */
14
+ /** One Claude Code or Codex command handler. */
15
+ export interface ClaudeHookHandler {
16
+ type: string;
17
+ command: string;
18
+ /** Codex: run instead of `command` on Windows. */
19
+ commandWindows?: string;
20
+ timeout?: number;
21
+ }
22
+ /** Claude Code + Codex entry: `{ hooks: [{ type, command, commandWindows?, timeout? }] }`. */
15
23
  export interface ClaudeHookGroup {
16
24
  matcher?: string;
17
- hooks: {
18
- type: string;
19
- command: string;
20
- }[];
25
+ hooks: ClaudeHookHandler[];
21
26
  }
22
27
  /** Cursor entry: a flat `{ command }`. */
23
28
  export interface CursorHookGroup {
24
29
  command: string;
25
30
  type?: string;
26
31
  matcher?: string;
32
+ /** Cursor Stop followup cap. Harnery pins 2; Cursor's own default is 5. */
33
+ loop_limit?: number;
27
34
  }
28
35
  export type HookGroup = ClaudeHookGroup | CursorHookGroup;
36
+ /** Bound Cursor Stop `followup_message` retries so a missed ritual cannot loop 5 times. */
37
+ export declare const CURSOR_STOP_FOLLOWUP_LOOP_LIMIT = 2;
29
38
  export interface SettingsFile {
30
39
  version?: number;
31
40
  description?: string;
@@ -33,7 +42,36 @@ export interface SettingsFile {
33
42
  [k: string]: unknown;
34
43
  }
35
44
  /** Build a hook entry in the adapter's shape. */
36
- export declare function makeEntry(shape: HookEntryShape, command: string): HookGroup;
45
+ export declare function makeEntry(shape: HookEntryShape, command: string, extras?: {
46
+ loop_limit?: number;
47
+ timeout?: number;
48
+ commandWindows?: string;
49
+ }): HookGroup;
50
+ /**
51
+ * Rebuild a handler with Harnery's fields first in a fixed order, dropping
52
+ * undefined ones and keeping any other fields after them.
53
+ */
54
+ export declare function orderHandlerKeys(handler: ClaudeHookHandler): ClaudeHookHandler;
55
+ /**
56
+ * The Windows command for an opted-in project (ADR 0197). It hands the hook to
57
+ * the bridge entry point when that is on PATH and the working directory is a
58
+ * WSL UNC path, and otherwise runs the usual command. `ProviderPath` drops the
59
+ * provider prefix that `Path` carries. The trailing `exit $LASTEXITCODE` is
60
+ * required: without it PowerShell reports any non-zero exit from inside the
61
+ * `if` block as 1, which would turn a hook's blocking exit 2 into a failure.
62
+ */
63
+ export declare function hookCommandWindows(spec: AdapterSpec, agentHookPath: string, subcommand: string, adapter: AdapterId, entryPoint: string): string;
64
+ /** Project-level choices that change what init writes. */
65
+ export interface WiringOptions {
66
+ /** Bridge entry point from `hooks.codexWindowsBridge`, or null when not opted in. */
67
+ windowsBridgeEntryPoint?: string | null;
68
+ }
69
+ /** The `commandWindows` init writes for one event, or undefined for none. */
70
+ export declare function expectedCommandWindows(spec: AdapterSpec, agentHookPath: string, subcommand: string, adapter: AdapterId, options?: WiringOptions): string | undefined;
71
+ /** The `timeout` init writes on one event's Harnery hook, or undefined for none. */
72
+ export declare function hookTimeoutFor(spec: AdapterSpec, subcommand: string): number | undefined;
73
+ /** Pin Cursor Stop followups to Harnery's loop cap. Returns true when the entry changed. */
74
+ export declare function applyCursorStopLoopLimit(group: HookGroup, subcommand: string): boolean;
37
75
  /** Pull every command string out of a hook entry, regardless of shape. */
38
76
  export declare function groupCommands(group: HookGroup): string[];
39
77
  /**
@@ -68,7 +106,7 @@ export interface WiringDiff {
68
106
  duplicates: HookEvent[];
69
107
  /** Spec events wired under an event key other than the canonical one. */
70
108
  misplaced: HookEvent[];
71
- /** Spec events whose correct-key command differs from init's canonical command. */
109
+ /** Spec events whose correct-key command, `commandWindows`, or `timeout` differs from what init writes. */
72
110
  stale: HookEvent[];
73
111
  /** Settings fields rejected by a adapter with a strict top-level schema. */
74
112
  invalidTopLevelKeys: string[];
@@ -82,7 +120,7 @@ export interface WiringDiff {
82
120
  export declare function diffWiring(settings: SettingsFile, spec: AdapterSpec, expected?: {
83
121
  agentHookPath: string;
84
122
  adapter: AdapterId;
85
- }): WiringDiff;
123
+ } & WiringOptions): WiringDiff;
86
124
  export interface AdapterWiringStatus {
87
125
  adapter: AdapterId;
88
126
  /** Settings file path, relative to the project root. */
@@ -95,6 +133,12 @@ export interface AdapterWiringStatus {
95
133
  invalidTopLevelKeys: string[];
96
134
  invalidEventKeys: string[];
97
135
  parseError?: string;
136
+ /**
137
+ * `opencode-plugin` install mode only: why the installed plugin differs from
138
+ * what init writes now (stale source, missing/stale `harnery.json`, or a
139
+ * foreign file at the harnery path). Hook-map fields stay empty for it.
140
+ */
141
+ pluginIssues?: string[];
98
142
  }
99
143
  /**
100
144
  * Inspect every adapter whose settings file exists under `projectRoot` and
@@ -1 +1 @@
1
- {"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/adapter/wiring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/adapter/wiring.ts"],"names":[],"mappings":"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"}
@@ -13,10 +13,78 @@
13
13
  import { existsSync, readFileSync } from "node:fs";
14
14
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
15
15
  import { fileURLToPath } from "node:url";
16
+ import { codexWindowsBridgeConfig, resolveBinName } from "../../config.js";
16
17
  import { ADAPTER_SPECS, } from "./events.js";
18
+ import { checkOpenCodePlugin, isOwnedOpenCodePlugin } from "./opencode-plugin.js";
19
+ /** Bound Cursor Stop `followup_message` retries so a missed ritual cannot loop 5 times. */
20
+ export const CURSOR_STOP_FOLLOWUP_LOOP_LIMIT = 2;
17
21
  /** Build a hook entry in the adapter's shape. */
18
- export function makeEntry(shape, command) {
19
- return shape === "cursor" ? { command } : { hooks: [{ type: "command", command }] };
22
+ export function makeEntry(shape, command, extras) {
23
+ if (shape !== "cursor") {
24
+ return {
25
+ hooks: [
26
+ orderHandlerKeys({
27
+ type: "command",
28
+ command,
29
+ commandWindows: extras?.commandWindows,
30
+ timeout: extras?.timeout,
31
+ }),
32
+ ],
33
+ };
34
+ }
35
+ return extras?.loop_limit !== undefined
36
+ ? { command, loop_limit: extras.loop_limit }
37
+ : { command };
38
+ }
39
+ /**
40
+ * Rebuild a handler with Harnery's fields first in a fixed order, dropping
41
+ * undefined ones and keeping any other fields after them.
42
+ */
43
+ export function orderHandlerKeys(handler) {
44
+ const { type, command, commandWindows, timeout, ...rest } = handler;
45
+ return {
46
+ type,
47
+ command,
48
+ ...(commandWindows !== undefined ? { commandWindows } : {}),
49
+ ...(timeout !== undefined ? { timeout } : {}),
50
+ ...rest,
51
+ };
52
+ }
53
+ /**
54
+ * The Windows command for an opted-in project (ADR 0197). It hands the hook to
55
+ * the bridge entry point when that is on PATH and the working directory is a
56
+ * WSL UNC path, and otherwise runs the usual command. `ProviderPath` drops the
57
+ * provider prefix that `Path` carries. The trailing `exit $LASTEXITCODE` is
58
+ * required: without it PowerShell reports any non-zero exit from inside the
59
+ * `if` block as 1, which would turn a hook's blocking exit 2 into a failure.
60
+ */
61
+ export function hookCommandWindows(spec, agentHookPath, subcommand, adapter, entryPoint) {
62
+ const direct = hookCommand(spec, agentHookPath, subcommand, adapter);
63
+ return (`if ((Get-Command ${entryPoint} -ErrorAction Ignore) -and $PWD.ProviderPath -like '\\\\wsl*') ` +
64
+ `{ ${entryPoint} ${subcommand} --adapter ${adapter} } else { ${direct} }; exit $LASTEXITCODE`);
65
+ }
66
+ /** The `commandWindows` init writes for one event, or undefined for none. */
67
+ export function expectedCommandWindows(spec, agentHookPath, subcommand, adapter, options) {
68
+ if (!spec.windowsBridgeHooks || !options?.windowsBridgeEntryPoint)
69
+ return undefined;
70
+ return hookCommandWindows(spec, agentHookPath, subcommand, adapter, options.windowsBridgeEntryPoint);
71
+ }
72
+ /** The `timeout` init writes on one event's Harnery hook, or undefined for none. */
73
+ export function hookTimeoutFor(spec, subcommand) {
74
+ if (!spec.hookTimeouts)
75
+ return undefined;
76
+ return spec.hookTimeouts.bySubcommand?.[subcommand] ?? spec.hookTimeouts.default;
77
+ }
78
+ /** Pin Cursor Stop followups to Harnery's loop cap. Returns true when the entry changed. */
79
+ export function applyCursorStopLoopLimit(group, subcommand) {
80
+ if (subcommand !== "stop")
81
+ return false;
82
+ if (!("command" in group) || typeof group.command !== "string")
83
+ return false;
84
+ if (group.loop_limit === CURSOR_STOP_FOLLOWUP_LOOP_LIMIT)
85
+ return false;
86
+ group.loop_limit = CURSOR_STOP_FOLLOWUP_LOOP_LIMIT;
87
+ return true;
20
88
  }
21
89
  /** Pull every command string out of a hook entry, regardless of shape. */
22
90
  export function groupCommands(group) {
@@ -88,7 +156,15 @@ export function diffWiring(settings, spec, expected) {
88
156
  duplicates.push(event);
89
157
  if (expected && commands.length > 0) {
90
158
  const canonical = hookCommand(spec, expected.agentHookPath, event.subcommand, expected.adapter);
91
- if (commands.some((command) => command !== canonical))
159
+ const timeout = hookTimeoutFor(spec, event.subcommand);
160
+ const commandWindows = expectedCommandWindows(spec, expected.agentHookPath, event.subcommand, expected.adapter, expected);
161
+ const handlerDrift = groups.some((group) => "hooks" in group &&
162
+ Array.isArray(group.hooks) &&
163
+ group.hooks.some((hook) => typeof hook.command === "string" &&
164
+ commandWiresSubcommand(hook.command, event.subcommand) &&
165
+ ((timeout !== undefined && hook.timeout !== timeout) ||
166
+ (spec.windowsBridgeHooks === true && hook.commandWindows !== commandWindows))));
167
+ if (handlerDrift || commands.some((command) => command !== canonical))
92
168
  stale.push(event);
93
169
  }
94
170
  const wrongKey = Object.entries(hooks).some(([key, otherGroups]) => key !== event.settingsKey &&
@@ -131,6 +207,39 @@ export function diffWiring(settings, spec, expected) {
131
207
  invalidEventKeys,
132
208
  };
133
209
  }
210
+ function emptyWiringStatus(adapter, settingsFile) {
211
+ return {
212
+ adapter,
213
+ settingsFile,
214
+ missing: [],
215
+ orphans: [],
216
+ duplicates: [],
217
+ misplaced: [],
218
+ stale: [],
219
+ invalidTopLevelKeys: [],
220
+ invalidEventKeys: [],
221
+ };
222
+ }
223
+ /**
224
+ * Plugin-mode drift: the installed entry exists but is not what init would
225
+ * write now. Absent entry → not opted in → null (mirrors the hook-map rule).
226
+ * Without a resolvable package root the launcher cannot be compared, so only
227
+ * the source freshness is judged.
228
+ */
229
+ function pluginDrift(projectRoot, id, spec) {
230
+ if (!existsSync(resolve(projectRoot, spec.settingsFile)))
231
+ return null;
232
+ const packageRoot = harneryPackageRoot();
233
+ const check = checkOpenCodePlugin(projectRoot, {
234
+ binName: resolveBinName(projectRoot),
235
+ agentHook: packageRoot ? agentHookPathForProject(projectRoot, packageRoot) : "agent-hook",
236
+ });
237
+ if (check.status === "fresh")
238
+ return null;
239
+ if (check.status === "missing")
240
+ return null;
241
+ return { ...emptyWiringStatus(id, spec.settingsFile), pluginIssues: check.issues };
242
+ }
134
243
  /**
135
244
  * Inspect every adapter whose settings file exists under `projectRoot` and
136
245
  * return only those with *drift*. Read-only; never writes.
@@ -145,6 +254,12 @@ export function diffWiring(settings, spec, expected) {
145
254
  export function loadAdapterWiring(projectRoot) {
146
255
  const out = [];
147
256
  for (const [id, spec] of Object.entries(ADAPTER_SPECS)) {
257
+ if (spec.installMode === "opencode-plugin") {
258
+ const drift = pluginDrift(projectRoot, id, spec);
259
+ if (drift)
260
+ out.push(drift);
261
+ continue;
262
+ }
148
263
  const settingsPath = resolve(projectRoot, spec.settingsFile);
149
264
  if (!existsSync(settingsPath))
150
265
  continue;
@@ -154,15 +269,7 @@ export function loadAdapterWiring(projectRoot) {
154
269
  }
155
270
  catch (error) {
156
271
  out.push({
157
- adapter: id,
158
- settingsFile: spec.settingsFile,
159
- missing: [],
160
- orphans: [],
161
- duplicates: [],
162
- misplaced: [],
163
- stale: [],
164
- invalidTopLevelKeys: [],
165
- invalidEventKeys: [],
272
+ ...emptyWiringStatus(id, spec.settingsFile),
166
273
  parseError: error.message,
167
274
  });
168
275
  continue;
@@ -172,6 +279,7 @@ export function loadAdapterWiring(projectRoot) {
172
279
  ? {
173
280
  agentHookPath: agentHookPathForProject(projectRoot, packageRoot),
174
281
  adapter: id,
282
+ windowsBridgeEntryPoint: codexWindowsBridgeConfig(projectRoot).entryPoint,
175
283
  }
176
284
  : undefined);
177
285
  if (diff.present.length === 0)
@@ -220,6 +328,19 @@ export function summarizeAdapterWiring(projectRoot) {
220
328
  unwired.push(id);
221
329
  continue;
222
330
  }
331
+ if (spec.installMode === "opencode-plugin") {
332
+ // The entry counts as wired only when harnery owns it; a foreign file at
333
+ // that path is drift (surfaced by loadAdapterWiring), not a wiring.
334
+ let content;
335
+ try {
336
+ content = readFileSync(settingsPath, "utf8");
337
+ }
338
+ catch {
339
+ continue;
340
+ }
341
+ (isOwnedOpenCodePlugin(content) ? wired : unwired).push(id);
342
+ continue;
343
+ }
223
344
  let settings;
224
345
  try {
225
346
  settings = JSON.parse(readFileSync(settingsPath, "utf8"));