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
@@ -1,4 +1,6 @@
1
1
  import { applyMirror, findDesktopDataDirs, listAccounts, planMirror, readCliAccount, } from "../lib/claude-desktop.js";
2
+ import { applyShare, defaultShareDir, planShare, shareSummary, } from "../lib/claude-desktop-share.js";
3
+ import { resolveMachineLabel } from "../lib/machine.js";
2
4
  /**
3
5
  * `claude-desktop`: make Claude desktop-app sessions survive account
4
6
  * switches.
@@ -141,6 +143,56 @@ export function registerClaudeDesktopCommand(program, emit, _context) {
141
143
  });
142
144
  }
143
145
  });
146
+ cmd
147
+ .command("share")
148
+ .description("Share sessions with your other computers through a synced folder (iCloud Drive by default): " +
149
+ "publish this machine's recent sessions and list + resume every other machine's here. " +
150
+ "Dry-run by default; --yes applies. Restart the desktop app afterward to see new entries.")
151
+ .option("--dir <path>", "Shared folder (default: iCloud Drive/Harnery/claude-sessions)")
152
+ .option("--days <n>", "Only sessions active in the last N days", "14")
153
+ .option("--data-dir <path>", "Explicit desktop-app data directory")
154
+ .option("--yes", "Apply the plan (default is dry-run)")
155
+ .action((opts) => {
156
+ const shareDir = opts.dir ?? process.env.HARNERY_SESSION_SHARE_DIR ?? defaultShareDir();
157
+ if (!shareDir) {
158
+ emit.error({
159
+ code: "no_share_dir",
160
+ message: "no shared folder: pass --dir <path> or set HARNERY_SESSION_SHARE_DIR",
161
+ });
162
+ process.exit(2);
163
+ }
164
+ const cli = readCliAccount();
165
+ if (!cli) {
166
+ emit.error({
167
+ code: "no_account",
168
+ message: "cannot read the signed-in account from ~/.claude.json",
169
+ });
170
+ process.exit(2);
171
+ }
172
+ const [dataDir] = requireDataDirs(emit, opts.dataDir);
173
+ const shareOpts = {
174
+ shareDir,
175
+ machine: resolveMachineLabel(),
176
+ days: Number(opts.days) || 14,
177
+ dataDir: dataDir,
178
+ targetAccountUuid: cli.accountUuid,
179
+ };
180
+ const plan = planShare(shareOpts);
181
+ const summary = { share_dir: shareDir, machine: shareOpts.machine, ...shareSummary(plan) };
182
+ if (!opts.yes) {
183
+ emit.data({ dry_run: true, ...summary, hint: "re-run with --yes to apply" });
184
+ return;
185
+ }
186
+ const result = applyShare(plan, shareOpts);
187
+ emit.data({
188
+ dry_run: false,
189
+ ...summary,
190
+ ...result,
191
+ hint: result.imported > 0
192
+ ? "quit the Claude desktop app fully (Cmd+Q) and reopen it to see the new sessions"
193
+ : "sidebar already current",
194
+ });
195
+ });
144
196
  }
145
197
  function collect(value, previous) {
146
198
  return previous.concat([value]);
@@ -4,7 +4,7 @@
4
4
  * `init` makes two kinds of change outside the harnery package:
5
5
  * 1. Merges `agent-hook` entries into the adapter settings file
6
6
  * (Claude Code `.claude/settings.json`, Cursor `.cursor/hooks.json`, or
7
- * Codex `.codex/hooks.json`).
7
+ * Codex `.codex/hooks.json`), or installs the OpenCode plugin directory.
8
8
  * 2. Creates the `.harnery/` coord root (runtime state: events, councils,
9
9
  * identities, journal) and stamps the host bin name into
10
10
  * `.harnery/config.jsonc`.
@@ -1 +1 @@
1
- {"version":3,"file":"deinit.d.ts","sourceRoot":"","sources":["../../src/commands/deinit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAgBnD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAwHjG;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IACtC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAEV;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C"}
1
+ {"version":3,"file":"deinit.d.ts","sourceRoot":"","sources":["../../src/commands/deinit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAiBnD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CA4HjG;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IACtC,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAEV;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C"}
@@ -4,7 +4,7 @@
4
4
  * `init` makes two kinds of change outside the harnery package:
5
5
  * 1. Merges `agent-hook` entries into the adapter settings file
6
6
  * (Claude Code `.claude/settings.json`, Cursor `.cursor/hooks.json`, or
7
- * Codex `.codex/hooks.json`).
7
+ * Codex `.codex/hooks.json`), or installs the OpenCode plugin directory.
8
8
  * 2. Creates the `.harnery/` coord root (runtime state: events, councils,
9
9
  * identities, journal) and stamps the host bin name into
10
10
  * `.harnery/config.jsonc`.
@@ -31,6 +31,7 @@ import { relative, resolve } from "node:path";
31
31
  import { createInterface } from "node:readline";
32
32
  import { DEFAULT_BIN_NAME } from "../core/config.js";
33
33
  import { ADAPTER_SPECS } from "../core/hooks/adapter/events.js";
34
+ import { removeOpenCodePlugin } from "../core/hooks/adapter/opencode-plugin.js";
34
35
  import { removeIndexerExclusions } from "../lib/indexer-exclusions.js";
35
36
  import { removeInstructions } from "../lib/instructions/apply.js";
36
37
  import { removeGitHooks } from "../lib/instructions/git-hooks.js";
@@ -47,7 +48,7 @@ export function registerDeinitCommand(program, emit, binName) {
47
48
  "settings file (keeps any others). Pass --purge-state to also delete the " +
48
49
  ".harnery/ coord root (on a terminal it asks first). Idempotent; use " +
49
50
  "--dry-run to preview.")
50
- .option("--adapter <id>", "claude-code | cursor | codex", "claude-code")
51
+ .option("--adapter <id>", "claude-code | cursor | codex | opencode", "claude-code")
51
52
  .option("--dry-run", "Show what would change without writing")
52
53
  .option("--project-root <path>", "Project root (default: git toplevel, else cwd)")
53
54
  .option("--purge-state", "Also delete the .harnery/ coord root (runtime state, destructive)")
@@ -55,7 +56,7 @@ export function registerDeinitCommand(program, emit, binName) {
55
56
  const adapter = opts.adapter;
56
57
  const spec = ADAPTER_SPECS[adapter];
57
58
  if (!spec) {
58
- emit.text(`Unknown adapter '${opts.adapter}'. Expected: claude-code | cursor | codex.`);
59
+ emit.text(`Unknown adapter '${opts.adapter}'. Expected: claude-code | cursor | codex | opencode.`);
59
60
  emit.setExitCode(1);
60
61
  return;
61
62
  }
@@ -77,7 +78,10 @@ export function registerDeinitCommand(program, emit, binName) {
77
78
  }
78
79
  // ── 1. unwire adapter hooks ────────────────────────────────────────────
79
80
  const settingsPath = resolve(projectRoot, spec.settingsFile);
80
- if (!existsSync(settingsPath)) {
81
+ if (spec.installMode === "opencode-plugin") {
82
+ actions.push(...removeOpenCodePlugin(projectRoot, dryRun));
83
+ }
84
+ else if (!existsSync(settingsPath)) {
81
85
  actions.push(`· ${rel(projectRoot, settingsPath)} doesn't exist; no hooks to remove`);
82
86
  }
83
87
  else {
@@ -0,0 +1,6 @@
1
+ import { type Command } from "commander";
2
+ import type { EmitContext } from "../commander.js";
3
+ import { type DiskReport } from "../lib/disk-usage.js";
4
+ export declare function registerDiskCommand(program: Command, emit: EmitContext): void;
5
+ export declare function renderDiskUsage(report: DiskReport): string;
6
+ //# sourceMappingURL=disk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../src/commands/disk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAwB,MAAM,WAAW,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAGL,KAAK,UAAU,EAGhB,MAAM,sBAAsB,CAAC;AAQ9B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA+C7E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAgD1D"}
@@ -0,0 +1,80 @@
1
+ import { InvalidArgumentError } from "commander";
2
+ import { diskUsage, parseDiskSize, } from "../lib/disk-usage.js";
3
+ function positive(value) {
4
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(Number(value)) || Number(value) < 1)
5
+ throw new InvalidArgumentError("requires a positive integer");
6
+ return Number(value);
7
+ }
8
+ export function registerDiskCommand(program, emit) {
9
+ program
10
+ .command("disk [path]")
11
+ .description("Measure checkout disk usage, including nested repositories and ignored files")
12
+ .option("--git <states>", "Filter: tracked, untracked, ignored, git-metadata, non-repository, unknown (comma-separated)")
13
+ .option("--type <types>", "File extensions or video, audio, image, media, archive (comma-separated)")
14
+ .option("--exclude <paths>", "Skip directory names at any depth or root-relative paths; repeatable, comma-separated", (value, previous) => [...previous, value], [])
15
+ .option("--group <by>", "Group by directory, repository, extension, git, or files", "directory")
16
+ .option("--depth <n>", "Directory grouping depth; does not limit the scan", positive, 1)
17
+ .option("--top <n>", "Maximum groups and largest files to display", positive, 20)
18
+ .option("--min-size <size>", "Include individual files at least this size (e.g. 10MB, 1GiB)", parseDiskSize)
19
+ .option("--apparent", "Rank and filter by file lengths instead of allocated blocks")
20
+ .option("--json", "Emit the versioned disk usage report")
21
+ .action((path, options) => {
22
+ try {
23
+ const { json, ...filters } = options;
24
+ const report = diskUsage(path, filters);
25
+ if (json) {
26
+ emit.config({ format: "json" });
27
+ emit.data(report);
28
+ }
29
+ else
30
+ emit.text(renderDiskUsage(report));
31
+ if (!report.complete)
32
+ emit.setExitCode(1);
33
+ }
34
+ catch (error) {
35
+ emit.error({
36
+ code: "disk_usage_failed",
37
+ message: error instanceof Error ? error.message : String(error),
38
+ });
39
+ emit.setExitCode(1);
40
+ }
41
+ });
42
+ }
43
+ export function renderDiskUsage(report) {
44
+ const bytes = (value) => value >= 1e9
45
+ ? `${(value / 1e9).toFixed(2)} GB`
46
+ : value >= 1e6
47
+ ? `${(value / 1e6).toFixed(2)} MB`
48
+ : value >= 1e3
49
+ ? `${(value / 1e3).toFixed(2)} KB`
50
+ : `${value} B`;
51
+ const size = (row) => bytes(report.measurement === "allocated"
52
+ ? (row.allocated_bytes ?? row.apparent_bytes)
53
+ : row.apparent_bytes);
54
+ const lines = [
55
+ `Disk usage: ${report.root}`,
56
+ `${size(report.totals)} in ${report.totals.files.toLocaleString()} regular files (${report.measurement})`,
57
+ `File lengths: ${bytes(report.totals.apparent_bytes)}. Directory metadata and symlinks are excluded.`,
58
+ "",
59
+ "Git state:",
60
+ ];
61
+ for (const [state, totals] of Object.entries(report.git))
62
+ if (totals.files)
63
+ lines.push(`${size(totals).padStart(12)} ${String(totals.files).padStart(8)} files ${state}`);
64
+ lines.push("", `Largest ${report.filters.group} groups (${report.groups.length} of ${report.group_count}):`);
65
+ for (const row of report.groups)
66
+ lines.push(`${size(row).padStart(12)} ${String(row.files).padStart(8)} files ${row.path}`);
67
+ if (report.filters.group !== "files") {
68
+ lines.push("", "Largest files:");
69
+ for (const row of report.largest_files)
70
+ lines.push(`${size(row).padStart(12)} ${row.git.padEnd(14)} ${row.path}`);
71
+ }
72
+ if (report.skipped.symlinks || report.skipped.special_files || report.skipped.excluded)
73
+ lines.push("", `Skipped: ${report.skipped.symlinks} symlinks, ${report.skipped.special_files} special files, ${report.skipped.excluded} excluded entries.`);
74
+ if (report.issues.length) {
75
+ lines.push("", "Incomplete scan:");
76
+ for (const issue of report.issues)
77
+ lines.push(`${issue.path}: ${issue.message}`);
78
+ }
79
+ return `${lines.join("\n")}\n`;
80
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAmC1E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CA2ON"}
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAqC1E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CA2ON"}
@@ -4,6 +4,7 @@ import { initDocsContext as initDocsLinks, runLinks } from "../lib/docs-links.js
4
4
  import { initDocsContext as initDocsLint, runLint } from "../lib/docs-lint.js";
5
5
  import { readDocsMetadata, readDocsMetadataKey } from "../lib/docs-meta.js";
6
6
  import { initDocsMetadataAuditContext, runDocsMetadataAudit } from "../lib/docs-metadata-audit.js";
7
+ import { initDocsMetadataExclusions } from "../lib/docs-metadata-managed.js";
7
8
  import { initDocsMetadataSyncContext, runDocsMetadataSync } from "../lib/docs-metadata-sync.js";
8
9
  import { createDocsFile } from "../lib/docs-new.js";
9
10
  import { countColdHandoffs, initDocsContext as initDocsSweep, runSweep, } from "../lib/docs-sweep.js";
@@ -20,6 +21,7 @@ function ensureContext(context) {
20
21
  docsRootAllowlist: context.docsRootAllowlist,
21
22
  });
22
23
  initDocsLinks({ ...opts, extraExcludedPrefixes: context.extraDocsExcludedPrefixes });
24
+ initDocsMetadataExclusions(context.extraDocsExcludedPrefixes);
23
25
  initDocsMetadataAuditContext(opts);
24
26
  initDocsMetadataSyncContext(opts);
25
27
  initDocsSweep(opts);
@@ -24,6 +24,14 @@ export interface Check {
24
24
  export declare function registerDoctorCommand(program: Command, emit: EmitContext): void;
25
25
  export declare function runChecks(): Promise<Check[]>;
26
26
  export declare function codexWslBridgeCheck(status: CodexWslBridgeStatus | null, recentMidFlightCount?: number): Check | null;
27
+ /**
28
+ * Hook runs that started but never finished (ADR 0197). Codex kills a hook at
29
+ * its timeout and the tool proceeds without that hook's checks; the start
30
+ * marker is the only trace such a run leaves.
31
+ */
32
+ export declare function codexHookRunsCheck(coordRoot: string | null, nowMs?: number, isAlive?: (pid: number) => boolean): Check | null;
33
+ /** Report the per-project Windows bridge opt-in, or an invalid value init ignored. */
34
+ export declare function codexWindowsBridgeCheck(coordRoot: string | null): Check | null;
27
35
  /** Count bounded, privacy-safe recovery diagnostics so a healthy environment
28
36
  * now does not hide an intermittent Codex-to-WSL identity drop. */
29
37
  export declare function countRecentCodexMidFlightOnboardings(coordRoot: string, nowMs?: number, windowMs?: number): number;
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AASnD,OAAO,EACL,KAAK,4BAA4B,EAElC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,mCAAmC,CAAC;AAW3C,KAAK,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAOD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAmD/E;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CA2BlD;AAgCD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,oBAAoB,GAAG,IAAI,EACnC,oBAAoB,SAAI,GACvB,KAAK,GAAG,IAAI,CAed;AAID;mEACmE;AACnE,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,EAClB,QAAQ,SAAqC,GAC5C,MAAM,CA0CR;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,4BAA4B,GAAG,KAAK,CAoBnF"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AASnD,OAAO,EACL,KAAK,4BAA4B,EAElC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,mCAAmC,CAAC;AAY3C,KAAK,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAOD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAmD/E;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CA+BlD;AAgCD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,oBAAoB,GAAG,IAAI,EACnC,oBAAoB,SAAI,GACvB,KAAK,GAAG,IAAI,CAed;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,SAAa,EAClB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GACjC,KAAK,GAAG,IAAI,CAad;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAmB9E;AAID;mEACmE;AACnE,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,EAClB,QAAQ,SAAqC,GAC5C,MAAM,CA0CR;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,4BAA4B,GAAG,KAAK,CAoBnF"}
@@ -15,12 +15,13 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
15
15
  import os from "node:os";
16
16
  import path from "node:path";
17
17
  import { BUILTIN_ADAPTER_IDS } from "../core/adapters/index.js";
18
- import { resolveBinName, ripgrepAutoInstall } from "../core/config.js";
18
+ import { codexWindowsBridgeConfig, resolveBinName, ripgrepAutoInstall } from "../core/config.js";
19
19
  import { countSummarizedSinceV3, listDiagnosticSummariesV3, } from "../core/events/v3/producers/diagnostic-summaries.js";
20
20
  import { ADAPTER_SPECS } from "../core/hooks/adapter/events.js";
21
21
  import { loadAdapterWiring, summarizeAdapterWiring } from "../core/hooks/adapter/wiring.js";
22
22
  import { probeCodexHookAuthorization, } from "../core/hooks/codex-authorization.js";
23
23
  import { inspectCodexWslBridge, } from "../core/hooks/codex-wsl-bridge.js";
24
+ import { findUnfinishedHookRuns } from "../core/hooks/run-markers.js";
24
25
  import { ADAPTER_BINARIES, ADAPTER_INSTALL_HINTS, ADAPTER_LOGIN_HINTS, } from "../core/workflow/adapters.js";
25
26
  import { probeBilling } from "../core/workflow/billing.js";
26
27
  import { checkGitHooks, gitHooksInstalled } from "../lib/instructions/git-hooks.js";
@@ -74,6 +75,8 @@ export async function runChecks() {
74
75
  const codexWslStatus = inspectCodexWslBridge();
75
76
  const recentCodexMidFlightCount = root ? countRecentCodexMidFlightOnboardings(root) : 0;
76
77
  const codexWslBridge = codexWslBridgeCheck(codexWslStatus, recentCodexMidFlightCount);
78
+ const codexHookRuns = codexHookRunsCheck(root);
79
+ const codexWindowsRoute = codexWindowsBridgeCheck(root);
77
80
  // Probe the adapter CLIs before the hook check runs, not in output order:
78
81
  // an unwired adapter only matters if its CLI is actually installed, and
79
82
  // probing once here keeps that join to one spawn per CLI.
@@ -90,6 +93,8 @@ export async function runChecks() {
90
93
  ...(codexAuthorization ? [codexAuthorization] : []),
91
94
  checkGitHookRegions(),
92
95
  ...(codexWslBridge ? [codexWslBridge] : []),
96
+ ...(codexWindowsRoute ? [codexWindowsRoute] : []),
97
+ ...(codexHookRuns ? [codexHookRuns] : []),
93
98
  ...workflow.map((w) => w.check),
94
99
  checkRestic(),
95
100
  checkRclone(),
@@ -141,6 +146,48 @@ export function codexWslBridgeCheck(status, recentMidFlightCount = 0) {
141
146
  : "forward CODEX_THREAD_ID through WSLENV in the Codex shell environment policy, then start a fresh task",
142
147
  };
143
148
  }
149
+ /**
150
+ * Hook runs that started but never finished (ADR 0197). Codex kills a hook at
151
+ * its timeout and the tool proceeds without that hook's checks; the start
152
+ * marker is the only trace such a run leaves.
153
+ */
154
+ export function codexHookRunsCheck(coordRoot, nowMs = Date.now(), isAlive) {
155
+ if (!coordRoot)
156
+ return null;
157
+ const runs = findUnfinishedHookRuns(coordRoot, nowMs, undefined, isAlive);
158
+ if (runs.count === 0)
159
+ return null;
160
+ const events = runs.events.map((e) => `${e.event} ×${e.count}`).join(", ");
161
+ return {
162
+ name: "codex:hook runs",
163
+ severity: "warn",
164
+ detail: `${runs.count} hook run${runs.count === 1 ? "" : "s"} started but never finished in the last 24h ` +
165
+ `(${events}; latest ${runs.latest}); their tools proceeded without those hooks' checks`,
166
+ hint: "a hook that outlives its timeout is killed; look for a stalled WSL session or a slow hook",
167
+ };
168
+ }
169
+ /** Report the per-project Windows bridge opt-in, or an invalid value init ignored. */
170
+ export function codexWindowsBridgeCheck(coordRoot) {
171
+ if (!coordRoot)
172
+ return null;
173
+ const bridge = codexWindowsBridgeConfig(coordRoot);
174
+ if (bridge.error) {
175
+ return {
176
+ name: "codex:Windows hook route",
177
+ severity: "warn",
178
+ detail: `${bridge.error}; Codex hooks are wired without commandWindows`,
179
+ hint: "set hooks.codexWindowsBridge.entryPoint to a plain command name in .harnery/config.jsonc, then re-run init",
180
+ };
181
+ }
182
+ if (!bridge.entryPoint)
183
+ return null;
184
+ return {
185
+ name: "codex:Windows hook route",
186
+ severity: "ok",
187
+ detail: `opted in: Windows-native Codex hooks hand off to \`${bridge.entryPoint}\` from WSL paths ` +
188
+ `when it is on PATH, otherwise run the usual command; bridge health is reported by the bridge itself`,
189
+ };
190
+ }
144
191
  const CODEX_MID_FLIGHT_HISTORY_WINDOW_MS = 48 * 60 * 60 * 1000;
145
192
  /** Count bounded, privacy-safe recovery diagnostics so a healthy environment
146
193
  * now does not hide an intermittent Codex-to-WSL identity drop. */
@@ -476,12 +523,20 @@ function checkAdapterHooks(installedAdapters = []) {
476
523
  if (d.invalidEventKeys.length > 0) {
477
524
  bits.push(`unsupported events (${d.invalidEventKeys.join(", ")})`);
478
525
  }
526
+ if (d.pluginIssues && d.pluginIssues.length > 0) {
527
+ // Plugin issues already name their file; render them as-is.
528
+ return d.pluginIssues.join("; ");
529
+ }
479
530
  return `${d.settingsFile}: ${bits.join("; ")}`;
480
531
  });
481
532
  for (const id of unwired) {
482
- parts.push(`${ADAPTER_SPECS[id].settingsFile}: ${id} CLI installed, no harnery hooks wired`);
533
+ const what = ADAPTER_SPECS[id].installMode === "opencode-plugin" ? "plugin" : "hooks";
534
+ parts.push(`${ADAPTER_SPECS[id].settingsFile}: ${id} CLI installed, no harnery ${what} wired`);
483
535
  }
484
- const needsManualRepair = drift.some((d) => d.parseError || d.invalidTopLevelKeys.length > 0 || d.invalidEventKeys.length > 0);
536
+ const needsManualRepair = drift.some((d) => d.parseError ||
537
+ d.invalidTopLevelKeys.length > 0 ||
538
+ d.invalidEventKeys.length > 0 ||
539
+ d.pluginIssues?.some((issue) => issue.includes("without harnery's ownership header")));
485
540
  const wireHints = unwired.map((id) => `\`${bin} init --adapter ${id}\``);
486
541
  let hint;
487
542
  if (needsManualRepair) {
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/commands/fetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA4B1E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CA2BN"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/commands/fetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA+B1E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAgCN"}
@@ -1,8 +1,10 @@
1
1
  import { writeFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { resolve } from "node:path";
4
+ import { resolveUserAgent } from "../lib/browser/user-agent.js";
4
5
  import { CookieJar } from "../lib/cookies/index.js";
5
6
  import { fetchWithJar } from "../lib/http/index.js";
7
+ import { commandPaceGate } from "../lib/pace/index.js";
6
8
  /**
7
9
  * `harn fetch`: HTTP request with cookie-jar attach + persist.
8
10
  *
@@ -22,6 +24,8 @@ export function registerFetchCommand(program, emit, context) {
22
24
  .option("-o, --output <file>", "Write response body to file (default: stdout)")
23
25
  .option("--store <path>", `Cookie store path (default ${DEFAULT_STORE})`)
24
26
  .option("--no-cookies", "Skip cookie-jar attach + persist")
27
+ .option("--no-pace", "Skip the human-pace gap (3 to 9 s) between requests to the same site for this run. " +
28
+ "HARNERY_PACE=off disables it machine-wide; local and private hosts never wait.")
25
29
  .option("--redirect <mode>", "Redirect handling: follow | error | manual", "follow")
26
30
  .option("--timeout <ms>", "Request timeout in milliseconds", "30000")
27
31
  .option("--status", "Print status to stderr")
@@ -40,6 +44,11 @@ export function registerFetchCommand(program, emit, context) {
40
44
  }
41
45
  async function runFetch(url, opts, emit, context) {
42
46
  const headers = {};
47
+ {
48
+ const ua = resolveUserAgent({ env: process.env.HARNERY_BROWSER_UA });
49
+ if (ua)
50
+ headers["User-Agent"] = ua;
51
+ }
43
52
  for (const h of opts.header ?? []) {
44
53
  const idx = h.indexOf(":");
45
54
  if (idx < 0) {
@@ -50,6 +59,7 @@ async function runFetch(url, opts, emit, context) {
50
59
  const jar = opts.cookies !== false
51
60
  ? new CookieJar({ path: opts.store ?? DEFAULT_STORE, source: "harn-fetch" })
52
61
  : null;
62
+ await commandPaceGate(opts.pace !== false, (message) => emit.log(message, "info"))?.before(url);
53
63
  const timeoutMs = Number.parseInt(opts.timeout, 10);
54
64
  const ac = new AbortController();
55
65
  const timer = setTimeout(() => ac.abort(), timeoutMs);
@@ -1,5 +1,6 @@
1
1
  import type { Command } from "commander";
2
2
  import type { EmitContext, HarneryProgramContext } from "../commander.js";
3
+ import { type ProcessAliveCheck, type TunnelState } from "../lib/tunnel/state.js";
3
4
  export { FILES_ORIGIN_HOST } from "../lib/local-file-url.js";
4
5
  export type LocalFileUrlMode = "auto" | "raw" | "viewer";
5
6
  export interface LocalFileUrlOptions {
@@ -30,5 +31,20 @@ export declare function verifyDashboardRoot(coordRoot: string, port: number, fet
30
31
  * work. Other files default to the dashboard viewer.
31
32
  */
32
33
  export declare function mintLocalFileUrl(input: string, options: LocalFileUrlOptions): LocalFileUrl;
34
+ export declare class TunnelLinkError extends Error {
35
+ readonly hint: string;
36
+ constructor(message: string, hint: string);
37
+ }
38
+ /**
39
+ * Turn a minted local URL into the same file's URL on a live tunnel.
40
+ *
41
+ * HTML needs a tunnel in front of the isolated files origin (its vhost is
42
+ * FILES_ORIGIN_HOST), because only that origin renders the page and serves its
43
+ * relative assets; a dashboard tunnel can only show the viewer, which displays
44
+ * HTML as source. Other files need a dashboard tunnel that serves the viewer.
45
+ * In both cases the tunnel's path scope must forward the request, or its gate
46
+ * would refuse the link, so a tunnel that does not cover the file is skipped.
47
+ */
48
+ export declare function tunnelFileUrl(local: LocalFileUrl, port: number, states: TunnelState[], processAlive?: ProcessAliveCheck): string;
33
49
  export declare function registerFilesCommand(program: Command, emit: EmitContext, context?: HarneryProgramContext): void;
34
50
  //# sourceMappingURL=files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAM1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,gCAAgC,GAChC,yBAAyB,CAAC;AAE9B,qBAAa,kBAAmB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;IAErC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAFZ,IAAI,EAAE,sBAAsB,EACrC,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM;CAKxB;AAMD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,kBAA0B,GACpC,OAAO,CAAC,IAAI,CAAC,CAmDf;AAuCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAS1F;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CA0EN"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/commands/files.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAY1E,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,sBAAsB,GAC9B,uBAAuB,GACvB,gCAAgC,GAChC,yBAAyB,CAAC;AAE9B,qBAAa,kBAAmB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;IAErC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAFZ,IAAI,EAAE,sBAAsB,EACrC,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM;CAKxB;AAMD,MAAM,MAAM,kBAAkB,GAAG,CAC/B,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,kBAA0B,GACpC,OAAO,CAAC,IAAI,CAAC,CAmDf;AAuCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAS1F;AAED,qBAAa,eAAgB,SAAQ,KAAK;IAGtC,QAAQ,CAAC,IAAI,EAAE,MAAM;gBADrB,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM;CAKxB;AAUD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EAAE,EACrB,YAAY,CAAC,EAAE,iBAAiB,GAC/B,MAAM,CA+BR;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAqFN"}
@@ -3,7 +3,9 @@ import path from "node:path";
3
3
  import { resolveCoordRoot } from "../core/agents/coord-client.js";
4
4
  import { DEFAULT_WEB_PORT, resolveWebPort } from "../core/config.js";
5
5
  import { coordRootId, localCoordRootIdUrl } from "../lib/coord-root-id.js";
6
- import { localFilesOriginUrl, localFileViewerUrl } from "../lib/local-file-url.js";
6
+ import { encodedRepoPath, encodeLinkSafeComponent, FILES_ORIGIN_HOST, localFilesOriginUrl, localFileViewerUrl, } from "../lib/local-file-url.js";
7
+ import { isPathAllowed } from "../lib/tunnel/path-scope.js";
8
+ import { isTunnelStateLive, listStates, tunnelTargetPort, } from "../lib/tunnel/state.js";
7
9
  export { FILES_ORIGIN_HOST } from "../lib/local-file-url.js";
8
10
  export class DashboardRootError extends Error {
9
11
  code;
@@ -99,6 +101,49 @@ export function mintLocalFileUrl(input, options) {
99
101
  : localFileViewerUrl(relPath, options.port);
100
102
  return { url, relPath, mode };
101
103
  }
104
+ export class TunnelLinkError extends Error {
105
+ hint;
106
+ constructor(message, hint) {
107
+ super(message);
108
+ this.hint = hint;
109
+ this.name = "TunnelLinkError";
110
+ }
111
+ }
112
+ function vhostName(vhost) {
113
+ return vhost.replace(/:\d+$/, "").toLowerCase();
114
+ }
115
+ function newestFirst(states) {
116
+ return [...states].sort((a, b) => b.started_at.localeCompare(a.started_at));
117
+ }
118
+ /**
119
+ * Turn a minted local URL into the same file's URL on a live tunnel.
120
+ *
121
+ * HTML needs a tunnel in front of the isolated files origin (its vhost is
122
+ * FILES_ORIGIN_HOST), because only that origin renders the page and serves its
123
+ * relative assets; a dashboard tunnel can only show the viewer, which displays
124
+ * HTML as source. Other files need a dashboard tunnel that serves the viewer.
125
+ * In both cases the tunnel's path scope must forward the request, or its gate
126
+ * would refuse the link, so a tunnel that does not cover the file is skipped.
127
+ */
128
+ export function tunnelFileUrl(local, port, states, processAlive) {
129
+ const live = states.filter((state) => tunnelTargetPort(state) === port && isTunnelStateLive(state, processAlive));
130
+ if (local.mode === "raw") {
131
+ const path = `/${encodedRepoPath(local.relPath)}`;
132
+ const tunnel = newestFirst(live).find((state) => vhostName(state.vhost) === FILES_ORIGIN_HOST && isPathAllowed(path, state.allow_paths));
133
+ if (tunnel)
134
+ return `${tunnel.url.replace(/\/+$/, "")}${path}`;
135
+ const folder = local.relPath.includes("/")
136
+ ? `/${local.relPath.slice(0, local.relPath.lastIndexOf("/"))}`
137
+ : "/";
138
+ throw new TunnelLinkError(`no live tunnel serves the files origin for /${local.relPath}`, `Start one scoped to the page's folder, for example: tunnel up --name pages --target 127.0.0.1:${port} --vhost ${FILES_ORIGIN_HOST} --allow-path ${folder}`);
139
+ }
140
+ const tunnel = newestFirst(live).find((state) => vhostName(state.vhost) !== FILES_ORIGIN_HOST &&
141
+ ["/files", "/api/file", "/_next"].every((path) => isPathAllowed(path, state.allow_paths)));
142
+ if (tunnel) {
143
+ return `${tunnel.url.replace(/\/+$/, "")}/files?path=${encodeLinkSafeComponent(local.relPath)}`;
144
+ }
145
+ throw new TunnelLinkError(`no live tunnel serves the dashboard file viewer on port ${port}`, `Start one, for example: tunnel up --name files --target 127.0.0.1:${port} --allow-path /files --allow-path /api/file --allow-path /_next`);
146
+ }
102
147
  export function registerFilesCommand(program, emit, context) {
103
148
  const files = program
104
149
  .command("files")
@@ -112,6 +157,7 @@ export function registerFilesCommand(program, emit, context) {
112
157
  .option("--raw", "Use the isolated files origin, regardless of extension")
113
158
  .option("--viewer", "Use the dashboard file viewer, regardless of extension")
114
159
  .option("--no-verify", "Mint without checking the running dashboard's repository identity")
160
+ .option("--tunnel", "Print the file's URL on a live tunnel instead of localhost (HTML uses a files-origin tunnel)")
115
161
  .action(async (filePath, opts) => {
116
162
  if (opts.raw && opts.viewer) {
117
163
  emit.error({
@@ -147,9 +193,15 @@ export function registerFilesCommand(program, emit, context) {
147
193
  });
148
194
  if (opts.verify !== false)
149
195
  await verifyDashboardRoot(coordRoot, port);
150
- emit.text(`${result.url}\n`);
196
+ const url = opts.tunnel ? tunnelFileUrl(result, port, listStates(coordRoot)) : result.url;
197
+ emit.text(`${url}\n`);
151
198
  }
152
199
  catch (error) {
200
+ if (error instanceof TunnelLinkError) {
201
+ emit.error({ code: "no_tunnel_for_file", message: error.message, hint: error.hint });
202
+ emit.setExitCode(1);
203
+ return;
204
+ }
153
205
  if (error instanceof DashboardRootError) {
154
206
  emit.error({ code: error.code, message: error.message, hint: error.hint });
155
207
  emit.setExitCode(1);
@@ -7,9 +7,13 @@
7
7
  * null and every hook no-ops forever.
8
8
  * 2. Register the agent-hook entries in the adapter settings file.
9
9
  *
10
- * Wires whichever adapter `--adapter` names (Claude Code `.claude/settings.json`,
11
- * Cursor `.cursor/hooks.json`, or Codex `.codex/hooks.json`): the per-adapter
12
- * file path, event list, and hook-entry shape all come from ADAPTER_SPECS.
10
+ * Wires every adapter in the resolved set (Claude Code `.claude/settings.json`,
11
+ * Cursor `.cursor/hooks.json`, Codex `.codex/hooks.json`, or the OpenCode plugin
12
+ * directory `.opencode/plugins/harnery/`): the per-adapter file path, event list,
13
+ * and hook-entry shape all come from ADAPTER_SPECS. `--adapter` is repeatable (or
14
+ * comma-separated, or `all`); with no flag, init wires every adapter whose CLI is
15
+ * installed on this machine, plus any adapter the project already has wired, else
16
+ * claude-code.
13
17
  *
14
18
  * `harn init` does both, non-destructively: it merges hook entries into an
15
19
  * existing settings file (preserving any other hooks) and skips entries that are
@@ -19,7 +23,19 @@ import type { Command } from "commander";
19
23
  import type { EmitContext } from "../commander.js";
20
24
  import type { EventV3ControlState } from "../core/events/v3/control.js";
21
25
  import { type AdapterId, type AdapterSpec } from "../core/hooks/adapter/events.js";
22
- import { type SettingsFile } from "../core/hooks/adapter/wiring.js";
26
+ import { type SettingsFile, type WiringOptions } from "../core/hooks/adapter/wiring.js";
27
+ /**
28
+ * Which adapters `init` should wire. An explicit `--adapter` wins. Without one:
29
+ * every adapter whose CLI is installed on this machine, plus every adapter the
30
+ * project already has wired (committed wiring stays current on a box whose CLI is
31
+ * absent, e.g. CI). A machine with neither falls back to the historical
32
+ * claude-code default. `installed` is injectable so tests never key on the host's
33
+ * toolchain.
34
+ */
35
+ export declare function resolveInitAdapters(projectRoot: string, requested: string[], installed?: AdapterId[]): {
36
+ adapters: AdapterId[];
37
+ error?: string;
38
+ };
23
39
  export declare function registerInitCommand(program: Command, emit: EmitContext, binName?: string): void;
24
40
  /**
25
41
  * Runtime contracts bound into an immutable V3 epoch. `init` replaces the
@@ -39,7 +55,7 @@ export declare function codexHookReviewAction(adapter: AdapterId): string | null
39
55
  *
40
56
  * Token-aware matching keeps `stop` from matching `stop-failure`.
41
57
  */
42
- export declare function wireHooks(settings: SettingsFile, spec: AdapterSpec, agentHookPath: string, adapter: AdapterId): {
58
+ export declare function wireHooks(settings: SettingsFile, spec: AdapterSpec, agentHookPath: string, adapter: AdapterId, options?: WiringOptions): {
43
59
  wired: number;
44
60
  already: number;
45
61
  removed: number;
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAInD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAOxE,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAClG,OAAO,EASL,KAAK,YAAY,EAClB,MAAM,iCAAiC,CAAC;AAqBzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAgT/F;AAiBD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAiBjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAOvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,SAAS,GACjB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA8CvE;AAwFD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAa1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAmDhG;AASD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAkCxF"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AASnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAOxE,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAKlG,OAAO,EAcL,KAAK,YAAY,EAEjB,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AA0CzC;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,SAAS,CAAC,EAAE,SAAS,EAAE,GACtB;IAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAM3C;AA6FD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAmU/F;AAiBD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAiBjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAOvE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,WAAW,EACjB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAmEvE;AA2GD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAa1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAmDhG;AASD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAkCxF"}