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,6 +1,6 @@
1
1
  import type { Command } from "commander";
2
2
  import type { EmitContext, HarneryProgramContext } from "../commander.ts";
3
- import type { Adapter } from "../core/adapter.ts";
3
+ import { ADAPTERS, type Adapter, normalizeAdapter } from "../core/adapter.ts";
4
4
  import { monorepoRoot, resolveOwner } from "../core/agents/index.ts";
5
5
  import { readLiveCoordinationRow } from "../core/agents/state/live-coordination-view.ts";
6
6
  import {
@@ -76,7 +76,7 @@ export function registerCheckpointCommand(
76
76
  .description("Create a durable context-continuity capsule for the current work")
77
77
  .option("--session <id>", "Session id (defaults to the current agent heartbeat)")
78
78
  .option("--instance <id>", "Agent instance id (defaults to the current owner)")
79
- .option("--adapter <id>", "claude-code, codex, or cursor (inferred from heartbeat)")
79
+ .option("--adapter <id>", `${ADAPTERS.join(", ")} (inferred from heartbeat)`)
80
80
  .option("--reason <reason>", "manual, pressure, pre_compact, or session_end", "manual")
81
81
  .option("--note <text>", "Short continuation note for the recovered agent")
82
82
  .option("--json", "Structured JSON output")
@@ -94,7 +94,7 @@ export function registerCheckpointCommand(
94
94
  const reason = parseCheckpointReason(opts.reason);
95
95
  const identity = resolveContinuityIdentity(context, opts);
96
96
  if (!identity.adapter) {
97
- throw new Error("could not infer the adapter; pass --adapter claude-code|codex|cursor");
97
+ throw new Error(`could not infer the adapter; pass --adapter ${ADAPTERS.join("|")}`);
98
98
  }
99
99
  const result = checkpointContext(identity.coordRoot, {
100
100
  sessionId: identity.sessionId,
@@ -166,15 +166,13 @@ function resolveContinuityIdentity(
166
166
  }
167
167
 
168
168
  function adapterFromPlatform(platform: string | undefined): Adapter | null {
169
- if (platform === "claude-code") return "claude-code";
170
- if (platform === "cursor") return "cursor";
171
- if (platform === "codex") return "codex";
172
- return null;
169
+ return normalizeAdapter(platform);
173
170
  }
174
171
 
175
172
  function parseAdapter(value: string): Adapter {
176
- if (value === "claude-code" || value === "codex" || value === "cursor") return value;
177
- throw new Error(`invalid adapter "${value}"; expected claude-code, codex, or cursor`);
173
+ const adapter = normalizeAdapter(value);
174
+ if (adapter) return adapter;
175
+ throw new Error(`invalid adapter "${value}"; expected one of ${ADAPTERS.join(", ")}`);
178
176
  }
179
177
 
180
178
  function parseCheckpointReason(value: string): CheckpointReason {
@@ -8,6 +8,13 @@ import {
8
8
  planMirror,
9
9
  readCliAccount,
10
10
  } from "../lib/claude-desktop.ts";
11
+ import {
12
+ applyShare,
13
+ defaultShareDir,
14
+ planShare,
15
+ shareSummary,
16
+ } from "../lib/claude-desktop-share.ts";
17
+ import { resolveMachineLabel } from "../lib/machine.ts";
11
18
 
12
19
  /**
13
20
  * `claude-desktop`: make Claude desktop-app sessions survive account
@@ -186,6 +193,60 @@ export function registerClaudeDesktopCommand(
186
193
  }
187
194
  },
188
195
  );
196
+
197
+ cmd
198
+ .command("share")
199
+ .description(
200
+ "Share sessions with your other computers through a synced folder (iCloud Drive by default): " +
201
+ "publish this machine's recent sessions and list + resume every other machine's here. " +
202
+ "Dry-run by default; --yes applies. Restart the desktop app afterward to see new entries.",
203
+ )
204
+ .option("--dir <path>", "Shared folder (default: iCloud Drive/Harnery/claude-sessions)")
205
+ .option("--days <n>", "Only sessions active in the last N days", "14")
206
+ .option("--data-dir <path>", "Explicit desktop-app data directory")
207
+ .option("--yes", "Apply the plan (default is dry-run)")
208
+ .action((opts: { dir?: string; days: string; dataDir?: string; yes?: boolean }) => {
209
+ const shareDir = opts.dir ?? process.env.HARNERY_SESSION_SHARE_DIR ?? defaultShareDir();
210
+ if (!shareDir) {
211
+ emit.error({
212
+ code: "no_share_dir",
213
+ message: "no shared folder: pass --dir <path> or set HARNERY_SESSION_SHARE_DIR",
214
+ });
215
+ process.exit(2);
216
+ }
217
+ const cli = readCliAccount();
218
+ if (!cli) {
219
+ emit.error({
220
+ code: "no_account",
221
+ message: "cannot read the signed-in account from ~/.claude.json",
222
+ });
223
+ process.exit(2);
224
+ }
225
+ const [dataDir] = requireDataDirs(emit, opts.dataDir);
226
+ const shareOpts = {
227
+ shareDir,
228
+ machine: resolveMachineLabel(),
229
+ days: Number(opts.days) || 14,
230
+ dataDir: dataDir as string,
231
+ targetAccountUuid: cli.accountUuid,
232
+ };
233
+ const plan = planShare(shareOpts);
234
+ const summary = { share_dir: shareDir, machine: shareOpts.machine, ...shareSummary(plan) };
235
+ if (!opts.yes) {
236
+ emit.data({ dry_run: true, ...summary, hint: "re-run with --yes to apply" });
237
+ return;
238
+ }
239
+ const result = applyShare(plan, shareOpts);
240
+ emit.data({
241
+ dry_run: false,
242
+ ...summary,
243
+ ...result,
244
+ hint:
245
+ result.imported > 0
246
+ ? "quit the Claude desktop app fully (Cmd+Q) and reopen it to see the new sessions"
247
+ : "sidebar already current",
248
+ });
249
+ });
189
250
  }
190
251
 
191
252
  function collect(value: string, previous: string[]): string[] {
@@ -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`.
@@ -34,6 +34,7 @@ import type { Command } from "commander";
34
34
  import type { EmitContext } from "../commander.ts";
35
35
  import { DEFAULT_BIN_NAME } from "../core/config.ts";
36
36
  import { ADAPTER_SPECS, type AdapterId } from "../core/hooks/adapter/events.ts";
37
+ import { removeOpenCodePlugin } from "../core/hooks/adapter/opencode-plugin.ts";
37
38
  import type { SettingsFile } from "../core/hooks/adapter/wiring.ts";
38
39
  import { removeIndexerExclusions } from "../lib/indexer-exclusions.ts";
39
40
  import { removeInstructions } from "../lib/instructions/apply.ts";
@@ -62,7 +63,7 @@ export function registerDeinitCommand(program: Command, emit: EmitContext, binNa
62
63
  ".harnery/ coord root (on a terminal it asks first). Idempotent; use " +
63
64
  "--dry-run to preview.",
64
65
  )
65
- .option("--adapter <id>", "claude-code | cursor | codex", "claude-code")
66
+ .option("--adapter <id>", "claude-code | cursor | codex | opencode", "claude-code")
66
67
  .option("--dry-run", "Show what would change without writing")
67
68
  .option("--project-root <path>", "Project root (default: git toplevel, else cwd)")
68
69
  .option("--purge-state", "Also delete the .harnery/ coord root (runtime state, destructive)")
@@ -70,7 +71,9 @@ export function registerDeinitCommand(program: Command, emit: EmitContext, binNa
70
71
  const adapter = opts.adapter as AdapterId;
71
72
  const spec = ADAPTER_SPECS[adapter];
72
73
  if (!spec) {
73
- emit.text(`Unknown adapter '${opts.adapter}'. Expected: claude-code | cursor | codex.`);
74
+ emit.text(
75
+ `Unknown adapter '${opts.adapter}'. Expected: claude-code | cursor | codex | opencode.`,
76
+ );
74
77
  emit.setExitCode(1);
75
78
  return;
76
79
  }
@@ -97,7 +100,9 @@ export function registerDeinitCommand(program: Command, emit: EmitContext, binNa
97
100
 
98
101
  // ── 1. unwire adapter hooks ────────────────────────────────────────────
99
102
  const settingsPath = resolve(projectRoot, spec.settingsFile);
100
- if (!existsSync(settingsPath)) {
103
+ if (spec.installMode === "opencode-plugin") {
104
+ actions.push(...removeOpenCodePlugin(projectRoot, dryRun));
105
+ } else if (!existsSync(settingsPath)) {
101
106
  actions.push(`· ${rel(projectRoot, settingsPath)} doesn't exist; no hooks to remove`);
102
107
  } else {
103
108
  let settings: SettingsFile;
@@ -0,0 +1,114 @@
1
+ import { type Command, InvalidArgumentError } from "commander";
2
+ import type { EmitContext } from "../commander.ts";
3
+ import {
4
+ type DiskGroup,
5
+ type DiskOptions,
6
+ type DiskReport,
7
+ diskUsage,
8
+ parseDiskSize,
9
+ } from "../lib/disk-usage.ts";
10
+
11
+ function positive(value: string): number {
12
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(Number(value)) || Number(value) < 1)
13
+ throw new InvalidArgumentError("requires a positive integer");
14
+ return Number(value);
15
+ }
16
+
17
+ export function registerDiskCommand(program: Command, emit: EmitContext): void {
18
+ program
19
+ .command("disk [path]")
20
+ .description("Measure checkout disk usage, including nested repositories and ignored files")
21
+ .option(
22
+ "--git <states>",
23
+ "Filter: tracked, untracked, ignored, git-metadata, non-repository, unknown (comma-separated)",
24
+ )
25
+ .option(
26
+ "--type <types>",
27
+ "File extensions or video, audio, image, media, archive (comma-separated)",
28
+ )
29
+ .option(
30
+ "--exclude <paths>",
31
+ "Skip directory names at any depth or root-relative paths; repeatable, comma-separated",
32
+ (value: string, previous: string[]) => [...previous, value],
33
+ [],
34
+ )
35
+ .option("--group <by>", "Group by directory, repository, extension, git, or files", "directory")
36
+ .option("--depth <n>", "Directory grouping depth; does not limit the scan", positive, 1)
37
+ .option("--top <n>", "Maximum groups and largest files to display", positive, 20)
38
+ .option(
39
+ "--min-size <size>",
40
+ "Include individual files at least this size (e.g. 10MB, 1GiB)",
41
+ parseDiskSize,
42
+ )
43
+ .option("--apparent", "Rank and filter by file lengths instead of allocated blocks")
44
+ .option("--json", "Emit the versioned disk usage report")
45
+ .action(
46
+ (path: string | undefined, options: DiskOptions & { group: DiskGroup; json?: boolean }) => {
47
+ try {
48
+ const { json, ...filters } = options;
49
+ const report = diskUsage(path, filters);
50
+ if (json) {
51
+ emit.config({ format: "json" });
52
+ emit.data(report);
53
+ } else emit.text(renderDiskUsage(report));
54
+ if (!report.complete) emit.setExitCode(1);
55
+ } catch (error) {
56
+ emit.error({
57
+ code: "disk_usage_failed",
58
+ message: error instanceof Error ? error.message : String(error),
59
+ });
60
+ emit.setExitCode(1);
61
+ }
62
+ },
63
+ );
64
+ }
65
+
66
+ export function renderDiskUsage(report: DiskReport): string {
67
+ const bytes = (value: number): string =>
68
+ value >= 1e9
69
+ ? `${(value / 1e9).toFixed(2)} GB`
70
+ : value >= 1e6
71
+ ? `${(value / 1e6).toFixed(2)} MB`
72
+ : value >= 1e3
73
+ ? `${(value / 1e3).toFixed(2)} KB`
74
+ : `${value} B`;
75
+ const size = (row: { allocated_bytes: number | null; apparent_bytes: number }): string =>
76
+ bytes(
77
+ report.measurement === "allocated"
78
+ ? (row.allocated_bytes ?? row.apparent_bytes)
79
+ : row.apparent_bytes,
80
+ );
81
+ const lines = [
82
+ `Disk usage: ${report.root}`,
83
+ `${size(report.totals)} in ${report.totals.files.toLocaleString()} regular files (${report.measurement})`,
84
+ `File lengths: ${bytes(report.totals.apparent_bytes)}. Directory metadata and symlinks are excluded.`,
85
+ "",
86
+ "Git state:",
87
+ ];
88
+ for (const [state, totals] of Object.entries(report.git))
89
+ if (totals.files)
90
+ lines.push(
91
+ `${size(totals).padStart(12)} ${String(totals.files).padStart(8)} files ${state}`,
92
+ );
93
+ lines.push(
94
+ "",
95
+ `Largest ${report.filters.group} groups (${report.groups.length} of ${report.group_count}):`,
96
+ );
97
+ for (const row of report.groups)
98
+ lines.push(`${size(row).padStart(12)} ${String(row.files).padStart(8)} files ${row.path}`);
99
+ if (report.filters.group !== "files") {
100
+ lines.push("", "Largest files:");
101
+ for (const row of report.largest_files)
102
+ lines.push(`${size(row).padStart(12)} ${row.git.padEnd(14)} ${row.path}`);
103
+ }
104
+ if (report.skipped.symlinks || report.skipped.special_files || report.skipped.excluded)
105
+ lines.push(
106
+ "",
107
+ `Skipped: ${report.skipped.symlinks} symlinks, ${report.skipped.special_files} special files, ${report.skipped.excluded} excluded entries.`,
108
+ );
109
+ if (report.issues.length) {
110
+ lines.push("", "Incomplete scan:");
111
+ for (const issue of report.issues) lines.push(`${issue.path}: ${issue.message}`);
112
+ }
113
+ return `${lines.join("\n")}\n`;
114
+ }
@@ -6,6 +6,7 @@ import { initDocsContext as initDocsLinks, runLinks } from "../lib/docs-links.ts
6
6
  import { initDocsContext as initDocsLint, runLint } from "../lib/docs-lint.ts";
7
7
  import { readDocsMetadata, readDocsMetadataKey } from "../lib/docs-meta.ts";
8
8
  import { initDocsMetadataAuditContext, runDocsMetadataAudit } from "../lib/docs-metadata-audit.ts";
9
+ import { initDocsMetadataExclusions } from "../lib/docs-metadata-managed.ts";
9
10
  import { initDocsMetadataSyncContext, runDocsMetadataSync } from "../lib/docs-metadata-sync.ts";
10
11
  import { createDocsFile } from "../lib/docs-new.ts";
11
12
  import {
@@ -27,6 +28,7 @@ function ensureContext(context: HarneryProgramContext | undefined): void {
27
28
  docsRootAllowlist: context.docsRootAllowlist,
28
29
  });
29
30
  initDocsLinks({ ...opts, extraExcludedPrefixes: context.extraDocsExcludedPrefixes });
31
+ initDocsMetadataExclusions(context.extraDocsExcludedPrefixes);
30
32
  initDocsMetadataAuditContext(opts);
31
33
  initDocsMetadataSyncContext(opts);
32
34
  initDocsSweep(opts);
@@ -18,7 +18,7 @@ import path from "node:path";
18
18
  import type { Command } from "commander";
19
19
  import type { EmitContext } from "../commander.ts";
20
20
  import { BUILTIN_ADAPTER_IDS } from "../core/adapters/index.ts";
21
- import { resolveBinName, ripgrepAutoInstall } from "../core/config.ts";
21
+ import { codexWindowsBridgeConfig, resolveBinName, ripgrepAutoInstall } from "../core/config.ts";
22
22
  import {
23
23
  countSummarizedSinceV3,
24
24
  listDiagnosticSummariesV3,
@@ -33,6 +33,7 @@ import {
33
33
  type CodexWslBridgeStatus,
34
34
  inspectCodexWslBridge,
35
35
  } from "../core/hooks/codex-wsl-bridge.ts";
36
+ import { findUnfinishedHookRuns } from "../core/hooks/run-markers.ts";
36
37
  import {
37
38
  ADAPTER_BINARIES,
38
39
  ADAPTER_INSTALL_HINTS,
@@ -115,6 +116,8 @@ export async function runChecks(): Promise<Check[]> {
115
116
  const codexWslStatus = inspectCodexWslBridge();
116
117
  const recentCodexMidFlightCount = root ? countRecentCodexMidFlightOnboardings(root) : 0;
117
118
  const codexWslBridge = codexWslBridgeCheck(codexWslStatus, recentCodexMidFlightCount);
119
+ const codexHookRuns = codexHookRunsCheck(root);
120
+ const codexWindowsRoute = codexWindowsBridgeCheck(root);
118
121
  // Probe the adapter CLIs before the hook check runs, not in output order:
119
122
  // an unwired adapter only matters if its CLI is actually installed, and
120
123
  // probing once here keeps that join to one spawn per CLI.
@@ -131,6 +134,8 @@ export async function runChecks(): Promise<Check[]> {
131
134
  ...(codexAuthorization ? [codexAuthorization] : []),
132
135
  checkGitHookRegions(),
133
136
  ...(codexWslBridge ? [codexWslBridge] : []),
137
+ ...(codexWindowsRoute ? [codexWindowsRoute] : []),
138
+ ...(codexHookRuns ? [codexHookRuns] : []),
134
139
  ...workflow.map((w) => w.check),
135
140
  checkRestic(),
136
141
  checkRclone(),
@@ -189,6 +194,52 @@ export function codexWslBridgeCheck(
189
194
  };
190
195
  }
191
196
 
197
+ /**
198
+ * Hook runs that started but never finished (ADR 0197). Codex kills a hook at
199
+ * its timeout and the tool proceeds without that hook's checks; the start
200
+ * marker is the only trace such a run leaves.
201
+ */
202
+ export function codexHookRunsCheck(
203
+ coordRoot: string | null,
204
+ nowMs = Date.now(),
205
+ isAlive?: (pid: number) => boolean,
206
+ ): Check | null {
207
+ if (!coordRoot) return null;
208
+ const runs = findUnfinishedHookRuns(coordRoot, nowMs, undefined, isAlive);
209
+ if (runs.count === 0) return null;
210
+ const events = runs.events.map((e) => `${e.event} ×${e.count}`).join(", ");
211
+ return {
212
+ name: "codex:hook runs",
213
+ severity: "warn",
214
+ detail:
215
+ `${runs.count} hook run${runs.count === 1 ? "" : "s"} started but never finished in the last 24h ` +
216
+ `(${events}; latest ${runs.latest}); their tools proceeded without those hooks' checks`,
217
+ hint: "a hook that outlives its timeout is killed; look for a stalled WSL session or a slow hook",
218
+ };
219
+ }
220
+
221
+ /** Report the per-project Windows bridge opt-in, or an invalid value init ignored. */
222
+ export function codexWindowsBridgeCheck(coordRoot: string | null): Check | null {
223
+ if (!coordRoot) return null;
224
+ const bridge = codexWindowsBridgeConfig(coordRoot);
225
+ if (bridge.error) {
226
+ return {
227
+ name: "codex:Windows hook route",
228
+ severity: "warn",
229
+ detail: `${bridge.error}; Codex hooks are wired without commandWindows`,
230
+ hint: "set hooks.codexWindowsBridge.entryPoint to a plain command name in .harnery/config.jsonc, then re-run init",
231
+ };
232
+ }
233
+ if (!bridge.entryPoint) return null;
234
+ return {
235
+ name: "codex:Windows hook route",
236
+ severity: "ok",
237
+ detail:
238
+ `opted in: Windows-native Codex hooks hand off to \`${bridge.entryPoint}\` from WSL paths ` +
239
+ `when it is on PATH, otherwise run the usual command; bridge health is reported by the bridge itself`,
240
+ };
241
+ }
242
+
192
243
  const CODEX_MID_FLIGHT_HISTORY_WINDOW_MS = 48 * 60 * 60 * 1000;
193
244
 
194
245
  /** Count bounded, privacy-safe recovery diagnostics so a healthy environment
@@ -557,13 +608,22 @@ function checkAdapterHooks(installedAdapters: AdapterId[] = []): Check {
557
608
  if (d.invalidEventKeys.length > 0) {
558
609
  bits.push(`unsupported events (${d.invalidEventKeys.join(", ")})`);
559
610
  }
611
+ if (d.pluginIssues && d.pluginIssues.length > 0) {
612
+ // Plugin issues already name their file; render them as-is.
613
+ return d.pluginIssues.join("; ");
614
+ }
560
615
  return `${d.settingsFile}: ${bits.join("; ")}`;
561
616
  });
562
617
  for (const id of unwired) {
563
- parts.push(`${ADAPTER_SPECS[id].settingsFile}: ${id} CLI installed, no harnery hooks wired`);
618
+ const what = ADAPTER_SPECS[id].installMode === "opencode-plugin" ? "plugin" : "hooks";
619
+ parts.push(`${ADAPTER_SPECS[id].settingsFile}: ${id} CLI installed, no harnery ${what} wired`);
564
620
  }
565
621
  const needsManualRepair = drift.some(
566
- (d) => d.parseError || d.invalidTopLevelKeys.length > 0 || d.invalidEventKeys.length > 0,
622
+ (d) =>
623
+ d.parseError ||
624
+ d.invalidTopLevelKeys.length > 0 ||
625
+ d.invalidEventKeys.length > 0 ||
626
+ d.pluginIssues?.some((issue) => issue.includes("without harnery's ownership header")),
567
627
  );
568
628
  const wireHints = unwired.map((id) => `\`${bin} init --adapter ${id}\``);
569
629
  let hint: string;
@@ -3,8 +3,10 @@ import { homedir } from "node:os";
3
3
  import { resolve } from "node:path";
4
4
  import type { Command } from "commander";
5
5
  import type { EmitContext, HarneryProgramContext } from "../commander.ts";
6
+ import { resolveUserAgent } from "../lib/browser/user-agent.js";
6
7
  import { CookieJar } from "../lib/cookies/index.ts";
7
8
  import { fetchWithJar } from "../lib/http/index.ts";
9
+ import { commandPaceGate } from "../lib/pace/index.ts";
8
10
 
9
11
  /**
10
12
  * `harn fetch`: HTTP request with cookie-jar attach + persist.
@@ -23,6 +25,7 @@ interface FetchOpts {
23
25
  output?: string;
24
26
  store?: string;
25
27
  cookies?: boolean;
28
+ pace?: boolean;
26
29
  redirect: string;
27
30
  timeout: string;
28
31
  status?: boolean;
@@ -47,6 +50,11 @@ export function registerFetchCommand(
47
50
  .option("-o, --output <file>", "Write response body to file (default: stdout)")
48
51
  .option("--store <path>", `Cookie store path (default ${DEFAULT_STORE})`)
49
52
  .option("--no-cookies", "Skip cookie-jar attach + persist")
53
+ .option(
54
+ "--no-pace",
55
+ "Skip the human-pace gap (3 to 9 s) between requests to the same site for this run. " +
56
+ "HARNERY_PACE=off disables it machine-wide; local and private hosts never wait.",
57
+ )
50
58
  .option("--redirect <mode>", "Redirect handling: follow | error | manual", "follow")
51
59
  .option("--timeout <ms>", "Request timeout in milliseconds", "30000")
52
60
  .option("--status", "Print status to stderr")
@@ -70,6 +78,10 @@ async function runFetch(
70
78
  context: HarneryProgramContext | undefined,
71
79
  ): Promise<void> {
72
80
  const headers: Record<string, string> = {};
81
+ {
82
+ const ua = resolveUserAgent({ env: process.env.HARNERY_BROWSER_UA });
83
+ if (ua) headers["User-Agent"] = ua;
84
+ }
73
85
  for (const h of opts.header ?? []) {
74
86
  const idx = h.indexOf(":");
75
87
  if (idx < 0) {
@@ -83,6 +95,8 @@ async function runFetch(
83
95
  ? new CookieJar({ path: opts.store ?? DEFAULT_STORE, source: "harn-fetch" })
84
96
  : null;
85
97
 
98
+ await commandPaceGate(opts.pace !== false, (message) => emit.log(message, "info"))?.before(url);
99
+
86
100
  const timeoutMs = Number.parseInt(opts.timeout, 10);
87
101
  const ac = new AbortController();
88
102
  const timer = setTimeout(() => ac.abort(), timeoutMs);
@@ -5,7 +5,21 @@ import type { EmitContext, HarneryProgramContext } from "../commander.ts";
5
5
  import { resolveCoordRoot } from "../core/agents/coord-client.ts";
6
6
  import { DEFAULT_WEB_PORT, resolveWebPort } from "../core/config.ts";
7
7
  import { coordRootId, localCoordRootIdUrl } from "../lib/coord-root-id.ts";
8
- import { localFilesOriginUrl, localFileViewerUrl } from "../lib/local-file-url.ts";
8
+ import {
9
+ encodedRepoPath,
10
+ encodeLinkSafeComponent,
11
+ FILES_ORIGIN_HOST,
12
+ localFilesOriginUrl,
13
+ localFileViewerUrl,
14
+ } from "../lib/local-file-url.ts";
15
+ import { isPathAllowed } from "../lib/tunnel/path-scope.ts";
16
+ import {
17
+ isTunnelStateLive,
18
+ listStates,
19
+ type ProcessAliveCheck,
20
+ type TunnelState,
21
+ tunnelTargetPort,
22
+ } from "../lib/tunnel/state.ts";
9
23
 
10
24
  export { FILES_ORIGIN_HOST } from "../lib/local-file-url.ts";
11
25
 
@@ -162,6 +176,72 @@ export function mintLocalFileUrl(input: string, options: LocalFileUrlOptions): L
162
176
  return { url, relPath, mode };
163
177
  }
164
178
 
179
+ export class TunnelLinkError extends Error {
180
+ constructor(
181
+ message: string,
182
+ readonly hint: string,
183
+ ) {
184
+ super(message);
185
+ this.name = "TunnelLinkError";
186
+ }
187
+ }
188
+
189
+ function vhostName(vhost: string): string {
190
+ return vhost.replace(/:\d+$/, "").toLowerCase();
191
+ }
192
+
193
+ function newestFirst(states: TunnelState[]): TunnelState[] {
194
+ return [...states].sort((a, b) => b.started_at.localeCompare(a.started_at));
195
+ }
196
+
197
+ /**
198
+ * Turn a minted local URL into the same file's URL on a live tunnel.
199
+ *
200
+ * HTML needs a tunnel in front of the isolated files origin (its vhost is
201
+ * FILES_ORIGIN_HOST), because only that origin renders the page and serves its
202
+ * relative assets; a dashboard tunnel can only show the viewer, which displays
203
+ * HTML as source. Other files need a dashboard tunnel that serves the viewer.
204
+ * In both cases the tunnel's path scope must forward the request, or its gate
205
+ * would refuse the link, so a tunnel that does not cover the file is skipped.
206
+ */
207
+ export function tunnelFileUrl(
208
+ local: LocalFileUrl,
209
+ port: number,
210
+ states: TunnelState[],
211
+ processAlive?: ProcessAliveCheck,
212
+ ): string {
213
+ const live = states.filter(
214
+ (state) => tunnelTargetPort(state) === port && isTunnelStateLive(state, processAlive),
215
+ );
216
+ if (local.mode === "raw") {
217
+ const path = `/${encodedRepoPath(local.relPath)}`;
218
+ const tunnel = newestFirst(live).find(
219
+ (state) =>
220
+ vhostName(state.vhost) === FILES_ORIGIN_HOST && isPathAllowed(path, state.allow_paths),
221
+ );
222
+ if (tunnel) return `${tunnel.url.replace(/\/+$/, "")}${path}`;
223
+ const folder = local.relPath.includes("/")
224
+ ? `/${local.relPath.slice(0, local.relPath.lastIndexOf("/"))}`
225
+ : "/";
226
+ throw new TunnelLinkError(
227
+ `no live tunnel serves the files origin for /${local.relPath}`,
228
+ `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}`,
229
+ );
230
+ }
231
+ const tunnel = newestFirst(live).find(
232
+ (state) =>
233
+ vhostName(state.vhost) !== FILES_ORIGIN_HOST &&
234
+ ["/files", "/api/file", "/_next"].every((path) => isPathAllowed(path, state.allow_paths)),
235
+ );
236
+ if (tunnel) {
237
+ return `${tunnel.url.replace(/\/+$/, "")}/files?path=${encodeLinkSafeComponent(local.relPath)}`;
238
+ }
239
+ throw new TunnelLinkError(
240
+ `no live tunnel serves the dashboard file viewer on port ${port}`,
241
+ `Start one, for example: tunnel up --name files --target 127.0.0.1:${port} --allow-path /files --allow-path /api/file --allow-path /_next`,
242
+ );
243
+ }
244
+
165
245
  export function registerFilesCommand(
166
246
  program: Command,
167
247
  emit: EmitContext,
@@ -180,6 +260,10 @@ export function registerFilesCommand(
180
260
  .option("--raw", "Use the isolated files origin, regardless of extension")
181
261
  .option("--viewer", "Use the dashboard file viewer, regardless of extension")
182
262
  .option("--no-verify", "Mint without checking the running dashboard's repository identity")
263
+ .option(
264
+ "--tunnel",
265
+ "Print the file's URL on a live tunnel instead of localhost (HTML uses a files-origin tunnel)",
266
+ )
183
267
  .action(
184
268
  async (
185
269
  filePath: string,
@@ -189,6 +273,7 @@ export function registerFilesCommand(
189
273
  raw?: boolean;
190
274
  viewer?: boolean;
191
275
  verify?: boolean;
276
+ tunnel?: boolean;
192
277
  },
193
278
  ) => {
194
279
  if (opts.raw && opts.viewer) {
@@ -224,8 +309,14 @@ export function registerFilesCommand(
224
309
  mode: opts.raw ? "raw" : opts.viewer ? "viewer" : "auto",
225
310
  });
226
311
  if (opts.verify !== false) await verifyDashboardRoot(coordRoot, port);
227
- emit.text(`${result.url}\n`);
312
+ const url = opts.tunnel ? tunnelFileUrl(result, port, listStates(coordRoot)) : result.url;
313
+ emit.text(`${url}\n`);
228
314
  } catch (error) {
315
+ if (error instanceof TunnelLinkError) {
316
+ emit.error({ code: "no_tunnel_for_file", message: error.message, hint: error.hint });
317
+ emit.setExitCode(1);
318
+ return;
319
+ }
229
320
  if (error instanceof DashboardRootError) {
230
321
  emit.error({ code: error.code, message: error.message, hint: error.hint });
231
322
  emit.setExitCode(1);