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
@@ -80,6 +80,8 @@ interface HarneryConfig {
80
80
  /** Optional host prompt-context extension. Project config only. */
81
81
  hooks?: {
82
82
  promptContext?: unknown;
83
+ /** Project-only opt-in; read via `codexWindowsBridgeConfig()`. */
84
+ codexWindowsBridge?: unknown;
83
85
  };
84
86
  /**
85
87
  * Agent-ritual policy owned by the host project. Git finalization is opt-in:
@@ -107,7 +109,7 @@ interface HarneryConfig {
107
109
  * `workflow run` in this repo to subscription billing (API-key vars are
108
110
  * scrubbed from child envs) without anyone having to remember the flag.
109
111
  */
110
- workflow?: { subscriptionOnly?: boolean };
112
+ workflow?: { subscriptionOnly?: boolean; workerFullAccess?: unknown };
111
113
  /**
112
114
  * Cross-machine presence (ADR 0016). `{ enabled: false }` opts a repo out of
113
115
  * the git-refs transport (publishing `refs/harnery/presence/<machine>` to
@@ -152,15 +154,36 @@ interface HarneryConfig {
152
154
  archive_keep_min?: number;
153
155
  archive_auto_clean?: boolean;
154
156
  };
157
+ /**
158
+ * Who can use this project's `.harnery/` state. `private` (the default) keeps every state
159
+ * directory 0700 and every state file 0600, owned by whoever wrote it. `group` makes them 0770 and
160
+ * 0660 so several Unix users who share the project directory's group can coordinate in one
161
+ * project. It never grants access to other users. The project directory must be setgid to that
162
+ * group so new state inherits it. Read via `storageSharing()`.
163
+ */
164
+ storage?: {
165
+ sharing?: "private" | "group";
166
+ };
155
167
  /**
156
168
  * Managed working-artifact defaults. `default_retention_days` is the
157
169
  * create-time TTL when the caller does not pass `artifacts create --days`.
158
170
  */
171
+ /** Local server registry (`servers` command, `harnery/core/servers`). */
172
+ servers?: {
173
+ /** Inclusive port range per server type, e.g. `"preview": [3100, 3199]`. */
174
+ port_ranges?: Record<string, unknown>;
175
+ idle_hours?: number;
176
+ owner_stale_hours?: number;
177
+ };
159
178
  artifacts?: {
160
179
  default_retention_days?: number;
161
180
  auto_clean?: boolean;
162
181
  max_bytes?: number;
163
182
  max_unit_bytes?: number;
183
+ idle_grace_hours?: number;
184
+ hold_days?: number;
185
+ max_held_bytes?: number;
186
+ min_free_bytes?: number;
164
187
  };
165
188
  /**
166
189
  * Page review packs. `auto_clean` lets `qa-run` and `review-pack create`
@@ -484,6 +507,42 @@ export function resolveHooksSetupHint(coordRoot?: string | null): string | null
484
507
  * values fail closed to no reminder so a malformed optional setting cannot
485
508
  * break the prompt hook.
486
509
  */
510
+ /** A plain Windows command name, so it is safe to splice into a PowerShell hook command. */
511
+ const CODEX_WINDOWS_BRIDGE_ENTRY_POINT = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
512
+
513
+ export interface CodexWindowsBridgeConfig {
514
+ /** Command name Windows-native Codex hooks hand off to, or null when not opted in. */
515
+ entryPoint: string | null;
516
+ /** Why the configured value was ignored, when it was. */
517
+ error: string | null;
518
+ }
519
+
520
+ /**
521
+ * Per-project opt-in that routes Windows-native Codex hooks through a resident
522
+ * WSL bridge (ADR 0197). Read from the project config only: the value is
523
+ * written into the committed `.codex/hooks.json`, so a user-level setting
524
+ * would make `init` output differ between machines. An invalid value is
525
+ * ignored and reported rather than spliced into a shell command.
526
+ */
527
+ export function codexWindowsBridgeConfig(projectRoot: string): CodexWindowsBridgeConfig {
528
+ const raw = readProjectConfig(projectRoot).hooks?.codexWindowsBridge;
529
+ if (raw === undefined) return { entryPoint: null, error: null };
530
+ const entryPoint = isPlainObject(raw) ? raw.entryPoint : undefined;
531
+ if (typeof entryPoint !== "string") {
532
+ return {
533
+ entryPoint: null,
534
+ error: "hooks.codexWindowsBridge.entryPoint must be a command name",
535
+ };
536
+ }
537
+ if (!CODEX_WINDOWS_BRIDGE_ENTRY_POINT.test(entryPoint)) {
538
+ return {
539
+ entryPoint: null,
540
+ error: `hooks.codexWindowsBridge.entryPoint ${JSON.stringify(entryPoint)} is not a plain command name`,
541
+ };
542
+ }
543
+ return { entryPoint, error: null };
544
+ }
545
+
487
546
  export function hostPromptReminder(coordRoot?: string | null): string | null {
488
547
  const root = coordRoot ?? findCoordRoot();
489
548
  if (!root) return null;
@@ -591,6 +650,40 @@ export function workflowSubscriptionOnly(coordRoot?: string | null): boolean {
591
650
  return readConfig(root).workflow?.subscriptionOnly === true;
592
651
  }
593
652
 
653
+ /**
654
+ * The host's raw worker full-access policy (ADR 0192), validated by
655
+ * `parseWorkerFullAccessPolicy` in the workflow layer, which knows each
656
+ * adapter's effort scale.
657
+ *
658
+ * `.harnery/config.jsonc`:
659
+ * `{ "workflow": { "workerFullAccess": { "enabled": true, "floors": { ... } } } }`
660
+ *
661
+ * This is a trust boundary, so it comes only from the project config, like
662
+ * `agents.finalizationRoots`: a user-global file cannot remove the sandbox from
663
+ * one project's workers. `HARNERY_WORKFLOW_WORKER_FULL_ACCESS=0` turns it off
664
+ * for one process. There is deliberately no `=1`: an environment variable can
665
+ * withdraw the grant but never supply it.
666
+ */
667
+ export function workflowWorkerFullAccessConfig(coordRoot?: string | null): unknown {
668
+ if (coordEnv("WORKFLOW_WORKER_FULL_ACCESS") === "0") return { enabled: false };
669
+ const root = coordRoot ?? findCoordRoot();
670
+ if (!root) return undefined;
671
+ return readProjectConfig(root).workflow?.workerFullAccess;
672
+ }
673
+
674
+ /**
675
+ * How this project's `.harnery/` state is shared: `private` or `group`. `HARNERY_STORAGE_SHARING`
676
+ * overrides per process; an unrecognized value falls back to `private`, the safer reading.
677
+ */
678
+ export function storageSharing(coordRoot?: string | null): "private" | "group" {
679
+ const env = coordEnv("STORAGE_SHARING");
680
+ if (env === "group" || env === "private") return env;
681
+ const root = coordRoot ?? findCoordRoot();
682
+ if (!root) return "private";
683
+ // Project file only: a user-global "group" would loosen every project that user touches.
684
+ return readProjectConfig(root).storage?.sharing === "group" ? "group" : "private";
685
+ }
686
+
594
687
  /**
595
688
  * Whether cross-machine presence (ADR 0016) is enabled for this repo.
596
689
  * Default ON — the transport itself additionally gates on an origin remote
@@ -742,6 +835,46 @@ export function resolveWebPort(explicitPort?: string, coordRoot?: string | null)
742
835
  return DEFAULT_WEB_PORT;
743
836
  }
744
837
 
838
+ /** The configured inclusive port range for one server type, or null. */
839
+ export function serverPortRange(type: string, coordRoot?: string | null): [number, number] | null {
840
+ const root = coordRoot ?? findCoordRoot();
841
+ const value = root ? readConfig(root).servers?.port_ranges?.[type] : undefined;
842
+ if (!Array.isArray(value) || value.length !== 2) return null;
843
+ const [low, high] = value as unknown[];
844
+ const valid = (n: unknown): n is number =>
845
+ Number.isInteger(n) && (n as number) > 0 && (n as number) < 65536;
846
+ return valid(low) && valid(high) && low <= high ? [low, high] : null;
847
+ }
848
+
849
+ /** Every configured server port range, keyed by type (invalid entries dropped). */
850
+ export function serverPortRanges(coordRoot?: string | null): Record<string, [number, number]> {
851
+ const root = coordRoot ?? findCoordRoot();
852
+ const ranges = root ? readConfig(root).servers?.port_ranges : undefined;
853
+ const out: Record<string, [number, number]> = {};
854
+ for (const type of Object.keys(ranges ?? {})) {
855
+ const range = serverPortRange(type, root);
856
+ if (range) out[type] = range;
857
+ }
858
+ return out;
859
+ }
860
+
861
+ /** Configured `servers gc` windows; undefined fields use the built-in defaults. */
862
+ export function serverGcConfig(coordRoot?: string | null): {
863
+ idle_hours?: number;
864
+ owner_stale_hours?: number;
865
+ } {
866
+ const root = coordRoot ?? findCoordRoot();
867
+ const configured = root ? readConfig(root).servers : undefined;
868
+ const positive = (n: unknown): n is number =>
869
+ typeof n === "number" && Number.isFinite(n) && n > 0;
870
+ return {
871
+ ...(positive(configured?.idle_hours) ? { idle_hours: configured.idle_hours } : {}),
872
+ ...(positive(configured?.owner_stale_hours)
873
+ ? { owner_stale_hours: configured.owner_stale_hours }
874
+ : {}),
875
+ };
876
+ }
877
+
745
878
  /** Policy for converging independent termination signals on one finalizer. */
746
879
  export function sessionFinalizationConfig(coordRoot?: string | null): SessionFinalizationConfig {
747
880
  const root = coordRoot ?? findCoordRoot();
@@ -820,12 +953,81 @@ export function artifactMaxUnitBytes(coordRoot?: string | null): number {
820
953
  );
821
954
  }
822
955
 
956
+ /**
957
+ * How long an unexpired workspace must sit idle before a size rule (the
958
+ * per-bundle ceiling or the repository budget) may delete it. Idle means no
959
+ * change inside the workspace and no heartbeat from its owner. An agent waiting
960
+ * on a human reply looks idle, so a short window deletes work someone is still
961
+ * reviewing. Precedence: `HARNERY_ARTIFACT_IDLE_GRACE_HOURS` ->
962
+ * `artifacts.idle_grace_hours` -> 24. Expiry never waits for this grace.
963
+ */
964
+ export function artifactIdleGraceHours(coordRoot?: string | null): number {
965
+ const root = coordRoot ?? findCoordRoot();
966
+ return integerSetting(
967
+ coordEnv("ARTIFACT_IDLE_GRACE_HOURS"),
968
+ root ? readConfig(root).artifacts?.idle_grace_hours : undefined,
969
+ 1,
970
+ 24 * 365,
971
+ 24,
972
+ );
973
+ }
974
+
975
+ /**
976
+ * Default lifetime of an artifact hold. A hold that is not renewed lapses after
977
+ * this many days and the workspace returns to ordinary retention. Precedence:
978
+ * `HARNERY_ARTIFACT_HOLD_DAYS` -> `artifacts.hold_days` -> 14.
979
+ */
980
+ export function artifactHoldDays(coordRoot?: string | null): number {
981
+ const root = coordRoot ?? findCoordRoot();
982
+ return integerSetting(
983
+ coordEnv("ARTIFACT_HOLD_DAYS"),
984
+ root ? readConfig(root).artifacts?.hold_days : undefined,
985
+ 1,
986
+ 365,
987
+ 14,
988
+ );
989
+ }
990
+
991
+ /**
992
+ * Advisory budget for held artifact bytes. Exceeding it produces warnings
993
+ * only: holds record owner intent, so cleanup never deletes held work.
994
+ * Precedence: `HARNERY_ARTIFACT_MAX_HELD_BYTES` -> `artifacts.max_held_bytes`
995
+ * -> 20 GiB.
996
+ */
997
+ export function artifactMaxHeldBytes(coordRoot?: string | null): number {
998
+ const root = coordRoot ?? findCoordRoot();
999
+ return integerSetting(
1000
+ coordEnv("ARTIFACT_MAX_HELD_BYTES"),
1001
+ root ? readConfig(root).artifacts?.max_held_bytes : undefined,
1002
+ 64 * 1024 * 1024,
1003
+ 1024 * 1024 * 1024 * 1024,
1004
+ DEFAULT_ARTIFACT_MAX_BYTES,
1005
+ );
1006
+ }
1007
+
1008
+ /**
1009
+ * Free-disk floor for the artifact store. Below it, artifact commands warn and
1010
+ * `artifacts create --big` refuses unless `--allow-low-disk` is passed.
1011
+ * Precedence: `HARNERY_ARTIFACT_MIN_FREE_BYTES` -> `artifacts.min_free_bytes`
1012
+ * -> 20 GiB. Zero disables the floor.
1013
+ */
1014
+ export function artifactMinFreeBytes(coordRoot?: string | null): number {
1015
+ const root = coordRoot ?? findCoordRoot();
1016
+ return integerSetting(
1017
+ coordEnv("ARTIFACT_MIN_FREE_BYTES"),
1018
+ root ? readConfig(root).artifacts?.min_free_bytes : undefined,
1019
+ 0,
1020
+ 1024 * 1024 * 1024 * 1024 * 1024,
1021
+ 20 * 1024 * 1024 * 1024,
1022
+ );
1023
+ }
1024
+
823
1025
  /**
824
1026
  * Whether opportunistic cleanup of expired artifact workspaces runs.
825
1027
  * Precedence: `HARNERY_ARTIFACT_AUTO_CLEAN` (0/false disables) ->
826
- * `artifacts.auto_clean` -> enabled. The sweep only ever deletes
827
- * `managed-expired` entries via the same guarded classifier as
828
- * `artifacts clean --yes`.
1028
+ * `artifacts.auto_clean` -> enabled. The sweep deletes the same
1029
+ * `managed-expired`, `managed-oversize`, and `managed-over-budget` entries as
1030
+ * `artifacts clean --yes`, through the same guarded classifier.
829
1031
  */
830
1032
  export function artifactAutoCleanEnabled(coordRoot?: string | null): boolean {
831
1033
  const env = coordEnv("ARTIFACT_AUTO_CLEAN");
@@ -11,6 +11,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "
11
11
  import { dirname, join } from "node:path";
12
12
  import type { Adapter } from "../adapter.ts";
13
13
  import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.ts";
14
+ import { stateFileMode } from "../storage/modes.ts";
14
15
 
15
16
  export const CONTEXT_SCHEMA_VERSION = 1 as const;
16
17
  export const MAX_CAPSULE_BYTES = 32 * 1024;
@@ -499,7 +500,7 @@ function writeBoundedJson(path: string, value: unknown, maxBytes: number): void
499
500
  }
500
501
  mkdirSync(dirname(path), { recursive: true });
501
502
  const temp = `${path}.tmp.${process.pid}.${randomUUID()}`;
502
- writeFileSync(temp, text, { encoding: "utf8", mode: 0o600 });
503
+ writeFileSync(temp, text, { encoding: "utf8", mode: stateFileMode() });
503
504
  renameSync(temp, path);
504
505
  }
505
506
 
@@ -5,6 +5,7 @@ import {
5
5
  type DurableHistoryFaultBoundary,
6
6
  readDurableHistorySync,
7
7
  } from "../storage/durable-history.ts";
8
+ import { stateDirMode, stateFileMode } from "../storage/modes.ts";
8
9
  import type {
9
10
  HarneryConversationAccessMode,
10
11
  HarneryConversationArchiveAuthorityMode,
@@ -69,10 +70,10 @@ export async function captureProviderConversation(
69
70
  provider.capabilities.provider_id,
70
71
  options.conversation_id,
71
72
  );
72
- mkdirSync(objectDir, { recursive: true, mode: 0o700 });
73
+ mkdirSync(objectDir, { recursive: true, mode: stateDirMode() });
73
74
  const lease = join(objectDir, ".capture.lease");
74
75
  try {
75
- mkdirSync(lease, { mode: 0o700 });
76
+ mkdirSync(lease, { mode: stateDirMode() });
76
77
  } catch {
77
78
  throw new Error(`conversation capture lease busy: ${options.conversation_id}`);
78
79
  }
@@ -223,7 +224,7 @@ function manifestFor(
223
224
  function publishManifest(objectDir: string, manifest: HarneryConversationArchiveManifest): void {
224
225
  const path = join(objectDir, "manifest.json");
225
226
  const temp = `${path}.tmp-${process.pid}`;
226
- writeFileSync(temp, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
227
+ writeFileSync(temp, `${JSON.stringify(manifest, null, 2)}\n`, { mode: stateFileMode() });
227
228
  renameSync(temp, path);
228
229
  }
229
230
 
@@ -15,6 +15,7 @@ import type {
15
15
  } from "../artifacts/index.ts";
16
16
  import {
17
17
  ARTIFACT_MANIFEST,
18
+ artifactHoldState,
18
19
  artifactsRoot,
19
20
  configuredArtifactRetentionDays,
20
21
  createArtifact,
@@ -25,6 +26,7 @@ import {
25
26
  } from "../artifacts/index.ts";
26
27
  import { currentHarneryRuntimeBuild } from "../events/v3/runtime-build.ts";
27
28
  import { writePrivateJsonAtomic } from "../storage/atomic-json.ts";
29
+ import { stateDirMode } from "../storage/modes.ts";
28
30
  import {
29
31
  SUPERVISOR_DIAGNOSTIC_LIMITS,
30
32
  SUPERVISOR_EXPLANATION_SCHEMA_VERSION,
@@ -171,8 +173,8 @@ export function captureDiagnosticBundle(
171
173
  now,
172
174
  });
173
175
  const inputsPath = join(created.path, "inputs");
174
- mkdirSync(inputsPath, { recursive: true, mode: 0o700 });
175
- tryChmod(inputsPath, 0o700);
176
+ mkdirSync(inputsPath, { recursive: true, mode: stateDirMode() });
177
+ tryChmod(inputsPath, stateDirMode());
176
178
 
177
179
  const payloads: Record<(typeof PAYLOAD_FILES)[number], unknown> = {
178
180
  "inputs/observations.json": observations,
@@ -411,7 +413,7 @@ function candidateArtifactId(artifactPath: string): string | undefined {
411
413
  function candidateClassification(
412
414
  manifest: ArtifactManifestV2,
413
415
  ): ArtifactInventoryEntry["classification"] {
414
- if (manifest.holds.length > 0) return "managed-held";
416
+ if (artifactHoldState(manifest).active.length > 0) return "managed-held";
415
417
  if (!manifest.released_at) return "managed-active";
416
418
  return Date.parse(manifest.retention.expires_at) <= Date.now()
417
419
  ? "managed-expired"
@@ -4,6 +4,7 @@ import { chmod, lstat, mkdir, open, rename, rm } from "node:fs/promises";
4
4
  import { basename, join, resolve } from "node:path";
5
5
  import { pipeline } from "node:stream/promises";
6
6
  import { createGzip } from "node:zlib";
7
+ import { stateDirMode, stateFileMode } from "../../storage/modes.ts";
7
8
  import { canonicalJsonV3 } from "../v3/canonical.ts";
8
9
  import { verifyLegacyV1HardFence } from "./fence.ts";
9
10
  import { type LegacyV1SegmentManifest, validateLegacyV1SegmentManifest } from "./manifest.ts";
@@ -46,8 +47,8 @@ export async function writeLegacyV1Canary(input: {
46
47
  .digest("hex")
47
48
  .slice(0, 32)}` as const;
48
49
  const outputDirectory = resolve(input.output_directory);
49
- await mkdir(outputDirectory, { recursive: true, mode: 0o700 });
50
- await chmod(outputDirectory, 0o700);
50
+ await mkdir(outputDirectory, { recursive: true, mode: stateDirMode() });
51
+ await chmod(outputDirectory, stateDirMode());
51
52
  const payloadPath = join(outputDirectory, `${segmentId}.ndjson.gz`);
52
53
  const manifestPath = join(outputDirectory, `${segmentId}.manifest.json`);
53
54
  const partialPayload = `${payloadPath}.partial`;
@@ -57,7 +58,7 @@ export async function writeLegacyV1Canary(input: {
57
58
  await pipeline(
58
59
  createReadStream(source),
59
60
  createGzip({ level: 9 }),
60
- createWriteStream(partialPayload, { flags: "wx", mode: 0o600 }),
61
+ createWriteStream(partialPayload, { flags: "wx", mode: stateFileMode() }),
61
62
  );
62
63
  await rename(partialPayload, payloadPath);
63
64
  const payloadStat = await lstat(payloadPath);
@@ -85,7 +86,7 @@ export async function writeLegacyV1Canary(input: {
85
86
  const handle = await open(
86
87
  partialManifest,
87
88
  constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL,
88
- 0o600,
89
+ stateFileMode(),
89
90
  );
90
91
  try {
91
92
  await handle.writeFile(`${canonicalJsonV3(manifest)}\n`, "utf8");
@@ -5,6 +5,7 @@ import { chmod, lstat, rename, rm } from "node:fs/promises";
5
5
  import { basename } from "node:path";
6
6
  import { pipeline } from "node:stream/promises";
7
7
  import { createGzip } from "node:zlib";
8
+ import { stateFileMode } from "../../storage/modes.ts";
8
9
  import { verifyLegacyV1HardFence } from "./fence.ts";
9
10
  import { inventoryLegacyV1Segments } from "./inventory.ts";
10
11
  import { streamLegacyV1Rows } from "./reader.ts";
@@ -84,7 +85,7 @@ export async function compressSealedLegacyV1Segments(
84
85
  await pipeline(
85
86
  createReadStream(row.path),
86
87
  createGzip({ level: 9 }),
87
- createWriteStream(temporary, { flags: "wx", mode: 0o600 }),
88
+ createWriteStream(temporary, { flags: "wx", mode: stateFileMode() }),
88
89
  );
89
90
  await proveRowParity(row.path, temporary);
90
91
  const unchanged = (await inventoryLegacyV1Segments(coordRoot)).find(
@@ -1,4 +1,10 @@
1
- import type { Adapter } from "../../adapter.ts";
1
+ import {
2
+ type Adapter,
3
+ type AdapterFallbackOptions,
4
+ DEFAULT_ADAPTER,
5
+ normalizeAdapterId,
6
+ resolveAdapterId,
7
+ } from "../../adapter.ts";
2
8
 
3
9
  /** Harness identities that may produce or describe Event Ledger V3 evidence. */
4
10
  export type EventAdapterIdV3 = Adapter | "openclaw";
@@ -8,5 +14,27 @@ export const EVENT_ADAPTER_IDS_V3 = [
8
14
  "claude-code",
9
15
  "codex",
10
16
  "cursor",
17
+ "opencode",
11
18
  "openclaw",
12
19
  ] as const satisfies readonly EventAdapterIdV3[];
20
+
21
+ type MissingEventAdapterId = Exclude<EventAdapterIdV3, (typeof EVENT_ADAPTER_IDS_V3)[number]>;
22
+ const eventAdapterIdsComplete: [MissingEventAdapterId] extends [never] ? true : never = true;
23
+ void eventAdapterIdsComplete;
24
+
25
+ /** Strict event-adapter normalizer: a known id or `null`. */
26
+ export function normalizeEventAdapterIdV3(value: unknown): EventAdapterIdV3 | null {
27
+ return normalizeAdapterId(value, EVENT_ADAPTER_IDS_V3);
28
+ }
29
+
30
+ /**
31
+ * Heartbeat `platform` to an event adapter id, substituting `DEFAULT_ADAPTER`
32
+ * and reporting the substitution. Use this wherever a row must be attributed
33
+ * to some adapter; use `normalizeEventAdapterIdV3` when `null` is acceptable.
34
+ */
35
+ export function eventAdapterIdV3FromPlatform(
36
+ value: unknown,
37
+ options?: AdapterFallbackOptions,
38
+ ): EventAdapterIdV3 {
39
+ return resolveAdapterId(value, EVENT_ADAPTER_IDS_V3, DEFAULT_ADAPTER, options);
40
+ }
@@ -11,6 +11,7 @@ import {
11
11
  writeFileSync,
12
12
  } from "node:fs";
13
13
  import { join } from "node:path";
14
+ import { stateFileMode } from "../../storage/modes.ts";
14
15
  import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
15
16
  import { canonicalJsonV3, sha256V3 } from "./canonical.ts";
16
17
  import type { EventV3 } from "./contract.ts";
@@ -540,7 +541,7 @@ function publishExclusive(path: string, serialized: string): void {
540
541
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
541
542
  let fd: number | undefined;
542
543
  try {
543
- fd = openSync(temporary, "wx", 0o600);
544
+ fd = openSync(temporary, "wx", stateFileMode());
544
545
  writeFileSync(fd, serialized, "utf8");
545
546
  fsyncSync(fd);
546
547
  closeSync(fd);
@@ -16,6 +16,7 @@ import {
16
16
  import { hostname } from "node:os";
17
17
  import { dirname, join, resolve } from "node:path";
18
18
  import { fileURLToPath } from "node:url";
19
+ import { stateDirMode, stateFileMode } from "../../storage/modes.ts";
19
20
  import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
20
21
  import { acquireNoClobberLease } from "../../workflow/workspaces/leases.ts";
21
22
  import { canonicalJsonV3, sha256V3 } from "./canonical.ts";
@@ -524,7 +525,7 @@ function archiveCurrentEpoch(root: string, createdAt: string): string | undefine
524
525
  const current = join(root, ".harnery", "ledgers", "v3");
525
526
  if (!existsSync(current)) return undefined;
526
527
  const archives = join(root, ".harnery", "ledgers", "v3-archives");
527
- mkdirSync(archives, { recursive: true, mode: 0o700 });
528
+ mkdirSync(archives, { recursive: true, mode: stateDirMode() });
528
529
  const stamp = createdAt.replace(/[^0-9]/g, "");
529
530
  let target = join(archives, `epoch-${stamp}`);
530
531
  let suffix = 0;
@@ -535,20 +536,20 @@ function archiveCurrentEpoch(root: string, createdAt: string): string | undefine
535
536
  }
536
537
 
537
538
  function publishControlFile(path: string, value: unknown): void {
538
- mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
539
+ mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
539
540
  const temp = `${path}.tmp.${process.pid}`;
540
541
  // A prior failed publish by this same pid would otherwise make every retry
541
542
  // fail on the exclusive create, which is exactly how one transient error
542
543
  // turns into a permanently stranded epoch.
543
544
  if (existsSync(temp)) unlinkSync(temp);
544
- const fd = openSync(temp, "wx", 0o600);
545
+ const fd = openSync(temp, "wx", stateFileMode());
545
546
  try {
546
547
  writeFileSync(fd, `${canonicalJsonV3(value)}\n`, "utf8");
547
548
  fsyncSync(fd);
548
549
  } finally {
549
550
  closeSync(fd);
550
551
  }
551
- chmodSync(temp, 0o600);
552
+ chmodSync(temp, stateFileMode());
552
553
  renameSync(temp, path);
553
554
  fsyncParentDirectory(path);
554
555
  }
@@ -115,6 +115,19 @@ const BASE_SIGNAL_SUPPORT: Record<
115
115
  post_compaction: "unsupported",
116
116
  context_usage: "conditional",
117
117
  },
118
+ opencode: {
119
+ ...SHARED_SIGNAL_SUPPORT,
120
+ // OpenCode sessions are persistent server objects; the plugin observes a
121
+ // turn boundary (session.idle) rather than a clean session close, so end is
122
+ // conditional. Turns group by messageID without a first-class turn id.
123
+ session_end: "conditional",
124
+ turn_id: "conditional",
125
+ permission: "native",
126
+ // Compaction is intercepted (session.hook("compaction")); post-compaction
127
+ // recovery and SQLite-backed context usage are not yet certified.
128
+ post_compaction: "unsupported",
129
+ context_usage: "unsupported",
130
+ },
118
131
  openclaw: {
119
132
  session_start: "conditional",
120
133
  session_end: "native",
@@ -169,6 +182,10 @@ export const ADAPTER_CAPABILITY_PROFILES_V3: Record<EventAdapterIdV3, AdapterCap
169
182
  model_usage: "unsupported",
170
183
  inference_timing: "unsupported",
171
184
  }),
185
+ opencode: profile("opencode", {
186
+ model_usage: "conditional",
187
+ inference_timing: "unsupported",
188
+ }),
172
189
  openclaw: profile(
173
190
  "openclaw",
174
191
  {
@@ -123,8 +123,15 @@ export const TurnCompletedV3Schema = eventV3("turn.completed", {
123
123
  }),
124
124
  });
125
125
 
126
+ export const ToolLineChangesV3Schema = StrictObject({
127
+ added: Type.Integer({ minimum: 0 }),
128
+ removed: Type.Integer({ minimum: 0 }),
129
+ });
130
+
126
131
  export const ToolCompletedV3Schema = eventV3("tool.completed", {
127
- payload: terminalPayloadV3("tool.completed"),
132
+ payload: terminalPayloadV3("tool.completed", {
133
+ line_changes: Type.Optional(ObservationV3Schema(ToolLineChangesV3Schema)),
134
+ }),
128
135
  });
129
136
 
130
137
  export const CommandCompletedV3Schema = eventV3("command.completed", {
@@ -260,6 +267,7 @@ type ToolCompletedEventV3 = ReplaceEventV3<
260
267
  Omit<EventOfTypeV3Base<"tool.completed">["payload"], "duration_ms"> & {
261
268
  duration_ms: SpanSummaryValueV3["duration_ms"];
262
269
  span: SpanSummaryValueV3;
270
+ line_changes?: Static<ReturnType<typeof ObservationV3Schema<typeof ToolLineChangesV3Schema>>>;
263
271
  }
264
272
  >;
265
273
  type CommandCompletedEventV3 = ReplaceEventV3<
@@ -10,6 +10,7 @@ import {
10
10
  unlinkSync,
11
11
  writeFileSync,
12
12
  } from "node:fs";
13
+ import { stateFileMode } from "../../storage/modes.ts";
13
14
  import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
14
15
  import { canonicalJsonV3, type FingerprintV3, fingerprintV3, sha256V3 } from "./canonical.ts";
15
16
  import type { ActivationManifestV3, CandidateGenesisManifestV3 } from "./control.ts";
@@ -332,12 +333,12 @@ function publishCanonicalFileV3(path: string, value: unknown): boolean {
332
333
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
333
334
  let fd: number | undefined;
334
335
  try {
335
- fd = openSync(temporary, "wx", 0o600);
336
+ fd = openSync(temporary, "wx", stateFileMode());
336
337
  writeFileSync(fd, `${canonicalJsonV3(value)}\n`, "utf8");
337
338
  fsyncSync(fd);
338
339
  closeSync(fd);
339
340
  fd = undefined;
340
- chmodSync(temporary, 0o600);
341
+ chmodSync(temporary, stateFileMode());
341
342
  renameSync(temporary, path);
342
343
  fsyncParentDirectory(path);
343
344
  return true;
@@ -13,6 +13,7 @@ import {
13
13
  writeFileSync,
14
14
  } from "node:fs";
15
15
  import { join } from "node:path";
16
+ import { stateDirMode, stateFileMode } from "../../storage/modes.ts";
16
17
  import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
17
18
  import {
18
19
  type AuthorityTransactionV3,
@@ -306,8 +307,8 @@ function recoveryPaths(coordRoot: string, transactionId: string) {
306
307
 
307
308
  function ensureRecoveryLayout(paths: ReturnType<typeof recoveryPaths>): void {
308
309
  for (const path of [paths.root, paths.quarantineRoot]) {
309
- mkdirSync(path, { recursive: true, mode: 0o700 });
310
- chmodSync(path, 0o700);
310
+ mkdirSync(path, { recursive: true, mode: stateDirMode() });
311
+ chmodSync(path, stateDirMode());
311
312
  }
312
313
  }
313
314
 
@@ -325,7 +326,7 @@ function publishSerializedExclusive(path: string, serialized: string): void {
325
326
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
326
327
  let fd: number | undefined;
327
328
  try {
328
- fd = openSync(temporary, "wx", 0o600);
329
+ fd = openSync(temporary, "wx", stateFileMode());
329
330
  writeFileSync(fd, serialized, "utf8");
330
331
  fsyncSync(fd);
331
332
  closeSync(fd);
@@ -14,6 +14,7 @@ import {
14
14
  } from "node:fs";
15
15
  import { hostname } from "node:os";
16
16
  import { join, resolve } from "node:path";
17
+ import { stateDirMode, stateFileMode, stateModeTooOpen } from "../../storage/modes.ts";
17
18
  import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
18
19
  import { acquireNoClobberLease } from "../../workflow/workspaces/leases.ts";
19
20
  import type { FingerprintContextV3 } from "./canonical.ts";
@@ -78,8 +79,8 @@ export function readFingerprintKeyStoreV3(coordRoot: string): FingerprintKeyStor
78
79
 
79
80
  function readKeyStoreValue(path: string): unknown {
80
81
  const mode = statSync(path).mode & 0o777;
81
- if ((mode & 0o077) !== 0) {
82
- throw new Error("fingerprint key store permissions are not owner-only");
82
+ if (stateModeTooOpen(mode)) {
83
+ throw new Error("fingerprint key store is open to other users");
83
84
  }
84
85
  let parsed: unknown;
85
86
  try {
@@ -135,8 +136,8 @@ export function fingerprintContextV3(
135
136
 
136
137
  function withKeyStoreLock<T>(coordRoot: string, operation: () => T): T {
137
138
  const privateDir = join(resolve(coordRoot), ".harnery/private");
138
- mkdirSync(privateDir, { recursive: true, mode: 0o700 });
139
- chmodSync(privateDir, 0o700);
139
+ mkdirSync(privateDir, { recursive: true, mode: stateDirMode() });
140
+ chmodSync(privateDir, stateDirMode());
140
141
  const leasePath = join(privateDir, "fingerprint-key-lease");
141
142
  const authority = createHash("sha256").update(resolve(coordRoot)).digest("hex");
142
143
  let lease: ReturnType<typeof acquireNoClobberLease> | undefined;
@@ -178,12 +179,12 @@ function publishKeyStore(path: string, store: FingerprintKeyStoreV3, replacing:
178
179
  const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
179
180
  let fd: number | undefined;
180
181
  try {
181
- fd = openSync(temporary, "wx", 0o600);
182
+ fd = openSync(temporary, "wx", stateFileMode());
182
183
  writeFileSync(fd, `${JSON.stringify(store)}\n`, "utf8");
183
184
  fsyncSync(fd);
184
185
  closeSync(fd);
185
186
  fd = undefined;
186
- chmodSync(temporary, 0o600);
187
+ chmodSync(temporary, stateFileMode());
187
188
  if (!replacing && existsSync(path)) throw new Error("fingerprint key store already exists");
188
189
  renameSync(temporary, path);
189
190
  fsyncParentDirectory(path);
@@ -1,6 +1,6 @@
1
1
  /** Generated by scripts/generate-event-v3-contract.ts. Do not edit. */
2
2
  export const EVENT_V3_SCHEMA_DIGEST =
3
- "sha256:bdcee8d7839add0c786740ba9d5cfd0b6573f0ad4974bf53272737468734aa36" as const;
3
+ "sha256:07137e2cdf5eaed58d55a34e4036c87aa1f375d45c88274d07ad1cc69a6fe6f7" as const;
4
4
  export const EVENT_V3_GENERATED_CORE_TYPES = [
5
5
  "ledger.genesis",
6
6
  "ledger.activated",