harnery 0.42.0 → 0.44.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 (343) hide show
  1. package/README.md +3 -3
  2. package/dist/commander.d.ts +16 -0
  3. package/dist/commander.d.ts.map +1 -1
  4. package/dist/commander.js +18 -0
  5. package/dist/commands/agents.d.ts.map +1 -1
  6. package/dist/commands/agents.js +95 -52
  7. package/dist/commands/browse.d.ts.map +1 -1
  8. package/dist/commands/browse.js +38 -11
  9. package/dist/commands/diagnostics.d.ts.map +1 -1
  10. package/dist/commands/diagnostics.js +10 -0
  11. package/dist/commands/doctor.d.ts +12 -0
  12. package/dist/commands/doctor.d.ts.map +1 -1
  13. package/dist/commands/doctor.js +22 -7
  14. package/dist/commands/governor.js +22 -10
  15. package/dist/commands/inbox.d.ts +1 -1
  16. package/dist/commands/inbox.d.ts.map +1 -1
  17. package/dist/commands/inbox.js +55 -2
  18. package/dist/commands/rm.d.ts.map +1 -1
  19. package/dist/commands/rm.js +28 -4
  20. package/dist/commands/servers.d.ts.map +1 -1
  21. package/dist/commands/servers.js +16 -1
  22. package/dist/commands/supervisor.d.ts.map +1 -1
  23. package/dist/commands/supervisor.js +7 -2
  24. package/dist/commands/toc.d.ts +14 -0
  25. package/dist/commands/toc.d.ts.map +1 -1
  26. package/dist/commands/toc.js +7 -4
  27. package/dist/commands/tunnel.d.ts +65 -0
  28. package/dist/commands/tunnel.d.ts.map +1 -1
  29. package/dist/commands/tunnel.js +290 -101
  30. package/dist/commands/web-fetch.d.ts +3 -2
  31. package/dist/commands/web-fetch.d.ts.map +1 -1
  32. package/dist/commands/web-fetch.js +25 -19
  33. package/dist/commands/web.d.ts +7 -1
  34. package/dist/commands/web.d.ts.map +1 -1
  35. package/dist/commands/web.js +9 -3
  36. package/dist/commands/workflow.js +24 -30
  37. package/dist/core/agents/live-authority-v3.d.ts +1 -0
  38. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  39. package/dist/core/agents/live-authority-v3.js +11 -0
  40. package/dist/core/agents/live-lifecycle-v3.d.ts +4 -2
  41. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
  42. package/dist/core/agents/live-lifecycle-v3.js +28 -7
  43. package/dist/core/agents/mailbox.d.ts +9 -8
  44. package/dist/core/agents/mailbox.d.ts.map +1 -1
  45. package/dist/core/agents/mailbox.js +24 -17
  46. package/dist/core/agents/render/prompt-context.d.ts +2 -0
  47. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  48. package/dist/core/agents/render/prompt-context.js +19 -17
  49. package/dist/core/agents/render/session-context.d.ts +2 -8
  50. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  51. package/dist/core/agents/render/session-context.js +64 -43
  52. package/dist/core/agents/rules/stop-hook.js +3 -3
  53. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  54. package/dist/core/agents/state/heartbeat-writer.js +25 -14
  55. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
  56. package/dist/core/agents/state/live-coordination-writer.js +5 -0
  57. package/dist/core/agents/state/names.d.ts +43 -3
  58. package/dist/core/agents/state/names.d.ts.map +1 -1
  59. package/dist/core/agents/state/names.js +87 -3
  60. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  61. package/dist/core/agents/state/pidmap.js +5 -0
  62. package/dist/core/agents/state/proc-start.d.ts +19 -0
  63. package/dist/core/agents/state/proc-start.d.ts.map +1 -1
  64. package/dist/core/agents/state/proc-start.js +41 -0
  65. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  66. package/dist/core/agents/state/stale-sweep.js +180 -70
  67. package/dist/core/agents/state/unchanged-file.d.ts +44 -0
  68. package/dist/core/agents/state/unchanged-file.d.ts.map +1 -0
  69. package/dist/core/agents/state/unchanged-file.js +390 -0
  70. package/dist/core/context/index.d.ts +22 -10
  71. package/dist/core/context/index.d.ts.map +1 -1
  72. package/dist/core/context/index.js +381 -119
  73. package/dist/core/context/observation.d.ts +26 -0
  74. package/dist/core/context/observation.d.ts.map +1 -0
  75. package/dist/core/context/observation.js +11 -0
  76. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  77. package/dist/core/diagnostics/bundle.js +25 -14
  78. package/dist/core/diagnostics/path-identity.d.ts +3 -0
  79. package/dist/core/diagnostics/path-identity.d.ts.map +1 -0
  80. package/dist/core/diagnostics/path-identity.js +12 -0
  81. package/dist/core/diagnostics/sanitize.d.ts.map +1 -1
  82. package/dist/core/diagnostics/sanitize.js +4 -3
  83. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  84. package/dist/core/events/v3/authority-outbox.js +29 -0
  85. package/dist/core/events/v3/generation-custody.d.ts +5 -0
  86. package/dist/core/events/v3/generation-custody.d.ts.map +1 -0
  87. package/dist/core/events/v3/generation-custody.js +50 -0
  88. package/dist/core/events/v3/producers/coordination-recorder.d.ts +1 -0
  89. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  90. package/dist/core/events/v3/producers/coordination-recorder.js +7 -0
  91. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  92. package/dist/core/events/v3/producers/recorder.js +77 -64
  93. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
  94. package/dist/core/events/v3/support-storage/pack-reader.js +42 -16
  95. package/dist/core/governor/planning.d.ts.map +1 -1
  96. package/dist/core/governor/planning.js +14 -1
  97. package/dist/core/governor/service-read.d.ts +10 -2
  98. package/dist/core/governor/service-read.d.ts.map +1 -1
  99. package/dist/core/governor/service-read.js +105 -22
  100. package/dist/core/governor/service.d.ts +20 -2
  101. package/dist/core/governor/service.d.ts.map +1 -1
  102. package/dist/core/governor/service.js +72 -47
  103. package/dist/core/hooks/cli.js +120 -23
  104. package/dist/core/hooks/fork-lineage.d.ts +40 -0
  105. package/dist/core/hooks/fork-lineage.d.ts.map +1 -0
  106. package/dist/core/hooks/fork-lineage.js +62 -0
  107. package/dist/core/hooks/resolve/transcript.d.ts +16 -0
  108. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  109. package/dist/core/hooks/resolve/transcript.js +84 -0
  110. package/dist/core/hooks/shell-rm.d.ts +2 -0
  111. package/dist/core/hooks/shell-rm.d.ts.map +1 -0
  112. package/dist/core/hooks/shell-rm.js +105 -0
  113. package/dist/core/hooks/shell-tokens.d.ts +12 -0
  114. package/dist/core/hooks/shell-tokens.d.ts.map +1 -0
  115. package/dist/core/hooks/shell-tokens.js +97 -0
  116. package/dist/core/hooks/shell-waiter.d.ts.map +1 -1
  117. package/dist/core/hooks/shell-waiter.js +3 -93
  118. package/dist/core/inbox/contract.d.ts +2 -1
  119. package/dist/core/inbox/contract.d.ts.map +1 -1
  120. package/dist/core/inbox/index.d.ts +2 -0
  121. package/dist/core/inbox/index.d.ts.map +1 -1
  122. package/dist/core/inbox/index.js +2 -0
  123. package/dist/core/inbox/peer-messages.d.ts +37 -0
  124. package/dist/core/inbox/peer-messages.d.ts.map +1 -0
  125. package/dist/core/inbox/peer-messages.js +72 -0
  126. package/dist/core/inbox/service.d.ts +8 -1
  127. package/dist/core/inbox/service.d.ts.map +1 -1
  128. package/dist/core/inbox/service.js +67 -21
  129. package/dist/core/inbox/targets.d.ts +22 -0
  130. package/dist/core/inbox/targets.d.ts.map +1 -0
  131. package/dist/core/inbox/targets.js +108 -0
  132. package/dist/core/inbox/watcher.js +7 -3
  133. package/dist/core/journal/index.d.ts.map +1 -1
  134. package/dist/core/journal/index.js +17 -2
  135. package/dist/core/resources/contract.d.ts +3 -0
  136. package/dist/core/resources/contract.d.ts.map +1 -1
  137. package/dist/core/resources/service-status.d.ts +14 -1
  138. package/dist/core/resources/service-status.d.ts.map +1 -1
  139. package/dist/core/resources/service-status.js +23 -13
  140. package/dist/core/resources/service.d.ts +9 -1
  141. package/dist/core/resources/service.d.ts.map +1 -1
  142. package/dist/core/resources/service.js +47 -27
  143. package/dist/core/resources/status.d.ts +2 -5
  144. package/dist/core/resources/status.d.ts.map +1 -1
  145. package/dist/core/resources/status.js +36 -7
  146. package/dist/core/semantic/contract.d.ts +5 -5
  147. package/dist/core/servers/index.d.ts +24 -13
  148. package/dist/core/servers/index.d.ts.map +1 -1
  149. package/dist/core/servers/index.js +132 -92
  150. package/dist/core/servers/tunnels.d.ts +3 -5
  151. package/dist/core/servers/tunnels.d.ts.map +1 -1
  152. package/dist/core/servers/tunnels.js +3 -9
  153. package/dist/core/storage/process-log.d.ts +12 -0
  154. package/dist/core/storage/process-log.d.ts.map +1 -1
  155. package/dist/core/storage/process-log.js +10 -2
  156. package/dist/core/supervisor/contract.d.ts +12 -0
  157. package/dist/core/supervisor/contract.d.ts.map +1 -1
  158. package/dist/core/supervisor/explanations.d.ts.map +1 -1
  159. package/dist/core/supervisor/explanations.js +2 -1
  160. package/dist/core/supervisor/findings.d.ts.map +1 -1
  161. package/dist/core/supervisor/findings.js +54 -9
  162. package/dist/core/supervisor/service.d.ts +9 -1
  163. package/dist/core/supervisor/service.d.ts.map +1 -1
  164. package/dist/core/supervisor/service.js +59 -29
  165. package/dist/core/supervisor/services.d.ts.map +1 -1
  166. package/dist/core/supervisor/services.js +22 -1
  167. package/dist/core/supervisor/status.d.ts +17 -2
  168. package/dist/core/supervisor/status.d.ts.map +1 -1
  169. package/dist/core/supervisor/status.js +70 -12
  170. package/dist/core/supervisor/timeline.d.ts.map +1 -1
  171. package/dist/core/supervisor/timeline.js +2 -1
  172. package/dist/core/work/state.js +7 -7
  173. package/dist/core/workflow/engine.d.ts.map +1 -1
  174. package/dist/core/workflow/engine.js +105 -32
  175. package/dist/core/workflow/failure-evidence.d.ts +16 -0
  176. package/dist/core/workflow/failure-evidence.d.ts.map +1 -0
  177. package/dist/core/workflow/failure-evidence.js +114 -0
  178. package/dist/core/workflow/index.d.ts +1 -1
  179. package/dist/core/workflow/index.d.ts.map +1 -1
  180. package/dist/core/workflow/index.js +1 -1
  181. package/dist/core/workflow/live-session-v3.d.ts +6 -0
  182. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  183. package/dist/core/workflow/live-session-v3.js +126 -5
  184. package/dist/core/workflow/proof.d.ts +5 -5
  185. package/dist/core/workflow/proof.d.ts.map +1 -1
  186. package/dist/core/workflow/proof.js +115 -20
  187. package/dist/core/workflow/run-state.d.ts +3 -1
  188. package/dist/core/workflow/run-state.d.ts.map +1 -1
  189. package/dist/core/workflow/run-state.js +31 -27
  190. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  191. package/dist/core/workflow/spawn-claude.js +19 -0
  192. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  193. package/dist/core/workflow/spawn-codex.js +13 -0
  194. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  195. package/dist/core/workflow/spawn-cursor.js +19 -0
  196. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
  197. package/dist/core/workflow/spawn-opencode.js +14 -0
  198. package/dist/core/workflow/types.d.ts +64 -17
  199. package/dist/core/workflow/types.d.ts.map +1 -1
  200. package/dist/core/workflow/workspaces/index.d.ts +0 -1
  201. package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
  202. package/dist/core/workflow/workspaces/index.js +0 -1
  203. package/dist/core/workflow/workspaces/leases.d.ts +3 -1
  204. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  205. package/dist/core/workflow/workspaces/leases.js +30 -16
  206. package/dist/core/workflow/workspaces/local-git.d.ts +6 -2
  207. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  208. package/dist/core/workflow/workspaces/local-git.js +270 -6
  209. package/dist/core/workflow/workspaces/ownership.d.ts +11 -0
  210. package/dist/core/workflow/workspaces/ownership.d.ts.map +1 -0
  211. package/dist/core/workflow/workspaces/ownership.js +194 -0
  212. package/dist/core/workflow/workspaces/reclaim.d.ts +35 -0
  213. package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -1
  214. package/dist/core/workflow/workspaces/reclaim.js +14 -0
  215. package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
  216. package/dist/core/workflow/workspaces/recovery.js +21 -13
  217. package/dist/core/workflow/workspaces/state.d.ts +1 -0
  218. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  219. package/dist/core/workflow/workspaces/state.js +21 -1
  220. package/dist/lib/browser/windows-chrome.d.ts +100 -12
  221. package/dist/lib/browser/windows-chrome.d.ts.map +1 -1
  222. package/dist/lib/browser/windows-chrome.js +262 -73
  223. package/dist/lib/docs-links.d.ts.map +1 -1
  224. package/dist/lib/docs-links.js +45 -2
  225. package/dist/lib/guarded-remove.d.ts +7 -0
  226. package/dist/lib/guarded-remove.d.ts.map +1 -1
  227. package/dist/lib/guarded-remove.js +106 -12
  228. package/dist/lib/identities/assume.d.ts.map +1 -1
  229. package/dist/lib/identities/assume.js +4 -0
  230. package/dist/lib/tunnel/allowlist.d.ts +44 -0
  231. package/dist/lib/tunnel/allowlist.d.ts.map +1 -0
  232. package/dist/lib/tunnel/allowlist.js +204 -0
  233. package/dist/lib/tunnel/current-address.d.ts +41 -0
  234. package/dist/lib/tunnel/current-address.d.ts.map +1 -0
  235. package/dist/lib/tunnel/current-address.js +123 -0
  236. package/dist/lib/tunnel/gate.js +13 -6
  237. package/dist/lib/tunnel/processes.d.ts +39 -0
  238. package/dist/lib/tunnel/processes.d.ts.map +1 -0
  239. package/dist/lib/tunnel/processes.js +121 -0
  240. package/dist/lib/tunnel/state.d.ts +28 -3
  241. package/dist/lib/tunnel/state.d.ts.map +1 -1
  242. package/dist/lib/tunnel/state.js +98 -27
  243. package/dist/lib/zip/index.d.ts +41 -0
  244. package/dist/lib/zip/index.d.ts.map +1 -0
  245. package/dist/lib/zip/index.js +398 -0
  246. package/package.json +8 -1
  247. package/src/commander.ts +32 -0
  248. package/src/commands/agents.ts +151 -74
  249. package/src/commands/browse.ts +50 -14
  250. package/src/commands/diagnostics.ts +10 -0
  251. package/src/commands/doctor.ts +26 -7
  252. package/src/commands/governor.ts +23 -10
  253. package/src/commands/inbox.ts +52 -2
  254. package/src/commands/rm.ts +43 -4
  255. package/src/commands/servers.ts +16 -4
  256. package/src/commands/supervisor.ts +7 -2
  257. package/src/commands/toc.ts +14 -6
  258. package/src/commands/tunnel.ts +394 -116
  259. package/src/commands/web-fetch.ts +30 -19
  260. package/src/commands/web.ts +9 -3
  261. package/src/commands/workflow.ts +30 -30
  262. package/src/core/agents/live-authority-v3.ts +17 -0
  263. package/src/core/agents/live-lifecycle-v3.ts +52 -14
  264. package/src/core/agents/mailbox.ts +26 -17
  265. package/src/core/agents/render/prompt-context.ts +35 -20
  266. package/src/core/agents/render/session-context.ts +92 -48
  267. package/src/core/agents/rules/stop-hook.ts +3 -3
  268. package/src/core/agents/state/heartbeat-writer.ts +29 -12
  269. package/src/core/agents/state/live-coordination-writer.ts +29 -0
  270. package/src/core/agents/state/names.ts +117 -6
  271. package/src/core/agents/state/pidmap.ts +13 -0
  272. package/src/core/agents/state/proc-start.ts +57 -0
  273. package/src/core/agents/state/stale-sweep.ts +247 -82
  274. package/src/core/agents/state/unchanged-file.ts +456 -0
  275. package/src/core/context/index.ts +446 -136
  276. package/src/core/context/observation.ts +29 -0
  277. package/src/core/diagnostics/bundle.ts +23 -18
  278. package/src/core/diagnostics/path-identity.ts +15 -0
  279. package/src/core/diagnostics/sanitize.ts +4 -3
  280. package/src/core/events/v3/authority-outbox.ts +56 -0
  281. package/src/core/events/v3/generation-custody.ts +59 -0
  282. package/src/core/events/v3/producers/coordination-recorder.ts +15 -0
  283. package/src/core/events/v3/producers/recorder.ts +94 -68
  284. package/src/core/events/v3/support-storage/pack-reader.ts +45 -19
  285. package/src/core/governor/planning.ts +20 -8
  286. package/src/core/governor/service-read.ts +128 -20
  287. package/src/core/governor/service.ts +119 -42
  288. package/src/core/hooks/cli.ts +139 -22
  289. package/src/core/hooks/fork-lineage.ts +82 -0
  290. package/src/core/hooks/resolve/transcript.ts +88 -0
  291. package/src/core/hooks/shell-rm.ts +103 -0
  292. package/src/core/hooks/shell-tokens.ts +96 -0
  293. package/src/core/hooks/shell-waiter.ts +4 -91
  294. package/src/core/inbox/contract.ts +2 -1
  295. package/src/core/inbox/index.ts +2 -0
  296. package/src/core/inbox/peer-messages.ts +94 -0
  297. package/src/core/inbox/service.ts +88 -22
  298. package/src/core/inbox/targets.ts +148 -0
  299. package/src/core/inbox/watcher.ts +8 -9
  300. package/src/core/journal/index.ts +19 -2
  301. package/src/core/resources/contract.ts +4 -0
  302. package/src/core/resources/service-status.ts +35 -12
  303. package/src/core/resources/service.ts +71 -24
  304. package/src/core/resources/status.ts +57 -8
  305. package/src/core/servers/index.ts +177 -91
  306. package/src/core/servers/tunnels.ts +3 -11
  307. package/src/core/storage/process-log.ts +17 -2
  308. package/src/core/supervisor/contract.ts +13 -0
  309. package/src/core/supervisor/explanations.ts +4 -1
  310. package/src/core/supervisor/findings.ts +68 -10
  311. package/src/core/supervisor/service.ts +88 -26
  312. package/src/core/supervisor/services.ts +26 -8
  313. package/src/core/supervisor/status.ts +89 -12
  314. package/src/core/supervisor/timeline.ts +2 -1
  315. package/src/core/work/state.ts +7 -7
  316. package/src/core/workflow/engine.ts +131 -49
  317. package/src/core/workflow/failure-evidence.ts +141 -0
  318. package/src/core/workflow/index.ts +0 -1
  319. package/src/core/workflow/live-session-v3.ts +146 -5
  320. package/src/core/workflow/proof.ts +134 -26
  321. package/src/core/workflow/run-state.ts +31 -29
  322. package/src/core/workflow/spawn-claude.ts +18 -0
  323. package/src/core/workflow/spawn-codex.ts +13 -0
  324. package/src/core/workflow/spawn-cursor.ts +18 -0
  325. package/src/core/workflow/spawn-opencode.ts +14 -0
  326. package/src/core/workflow/types.ts +51 -17
  327. package/src/core/workflow/workspaces/index.ts +0 -1
  328. package/src/core/workflow/workspaces/leases.ts +48 -17
  329. package/src/core/workflow/workspaces/local-git.ts +315 -5
  330. package/src/core/workflow/workspaces/ownership.ts +232 -0
  331. package/src/core/workflow/workspaces/reclaim.ts +58 -0
  332. package/src/core/workflow/workspaces/recovery.ts +25 -13
  333. package/src/core/workflow/workspaces/state.ts +20 -0
  334. package/src/lib/browser/windows-chrome.ts +346 -86
  335. package/src/lib/docs-links.ts +49 -2
  336. package/src/lib/guarded-remove.ts +132 -14
  337. package/src/lib/identities/assume.ts +4 -0
  338. package/src/lib/tunnel/allowlist.ts +208 -0
  339. package/src/lib/tunnel/current-address.ts +158 -0
  340. package/src/lib/tunnel/gate.ts +16 -8
  341. package/src/lib/tunnel/processes.ts +149 -0
  342. package/src/lib/tunnel/state.ts +123 -27
  343. package/src/lib/zip/index.ts +483 -0
@@ -1,18 +1,21 @@
1
1
  import type { Command } from "commander";
2
2
  import type { EmitContext } from "../commander.ts";
3
3
  import type { HarneryInboxService } from "../core/inbox/service.ts";
4
+ import { watchInbox } from "../core/inbox/watcher.ts";
4
5
 
5
6
  export function registerInboxCommand(
6
7
  program: Command,
7
8
  emit: EmitContext,
8
9
  service?: HarneryInboxService,
10
+ defaultRecipient?: () => string,
9
11
  ): void {
10
12
  const inbox = program.command("inbox").description("Inspect private coordination inbox state");
11
13
  inbox
12
- .command("list <recipient>")
14
+ .command("list [recipient]")
13
15
  .option("--json", "Emit stable JSON")
14
- .action((recipient: string, options: { json?: boolean }) => {
16
+ .action((recipient: string | undefined, options: { json?: boolean }) => {
15
17
  run(emit, () => {
18
+ recipient = requireRecipient(recipient, defaultRecipient);
16
19
  const rows = requireInboxService(service)
17
20
  .pending(recipient)
18
21
  .map((record) => ({
@@ -22,6 +25,7 @@ export function registerInboxCommand(
22
25
  created_at: record.created_at,
23
26
  body_bytes: record.body_bytes,
24
27
  body: record.body,
28
+ state: "pending",
25
29
  }));
26
30
  if (options.json) {
27
31
  emit.config({ format: "json" });
@@ -41,6 +45,52 @@ export function registerInboxCommand(
41
45
  } else emit.rows([status as unknown as Record<string, unknown>]);
42
46
  });
43
47
  });
48
+ inbox
49
+ .command("watch [recipient]")
50
+ .description("Surface pending messages for this instance; poll history until timeout")
51
+ .option("--timeout <seconds>", "Stop after this many seconds", "60")
52
+ .option("--json", "Emit one JSON record per surfaced message")
53
+ .action(async (recipient: string | undefined, options: { json?: boolean; timeout: string }) => {
54
+ let controller: AbortController | undefined;
55
+ let timer: ReturnType<typeof setTimeout> | undefined;
56
+ try {
57
+ const instanceId = requireRecipient(recipient, defaultRecipient);
58
+ const inboxService = requireInboxService(service);
59
+ const seconds = Number(options.timeout);
60
+ if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 3600)
61
+ throw new Error("--timeout must be greater than 0 and at most 3600 seconds");
62
+ controller = new AbortController();
63
+ timer = setTimeout(() => controller!.abort(), seconds * 1000);
64
+ if (options.json) emit.config({ format: "json" });
65
+ for await (const message of watchInbox(inboxService, instanceId, {
66
+ signal: controller.signal,
67
+ })) {
68
+ const row = { ...message, state: "surfaced" };
69
+ if (options.json) emit.data(row);
70
+ else emit.rows([row]);
71
+ // An output error leaves this ID pending for prompt recovery.
72
+ await new Promise<void>((resolve, reject) =>
73
+ process.stdout.write("", (error) => (error ? reject(error) : resolve())),
74
+ );
75
+ inboxService.acknowledgeSurface(instanceId, [message.message_id]);
76
+ }
77
+ } catch (error) {
78
+ emit.error({
79
+ code: "inbox_failed",
80
+ message: error instanceof Error ? error.message : String(error),
81
+ });
82
+ emit.setExitCode(1);
83
+ } finally {
84
+ if (timer) clearTimeout(timer);
85
+ controller?.abort();
86
+ }
87
+ });
88
+ }
89
+
90
+ function requireRecipient(recipient: string | undefined, fallback?: () => string): string {
91
+ const resolved = recipient ?? fallback?.();
92
+ if (!resolved) throw new Error("recipient instance is required outside an agent session");
93
+ return resolved;
44
94
  }
45
95
 
46
96
  function requireInboxService(service?: HarneryInboxService): HarneryInboxService {
@@ -1,9 +1,10 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import { existsSync } from "node:fs";
3
- import { isAbsolute, relative, resolve, sep } from "node:path";
2
+ import { existsSync, lstatSync, readFileSync, realpathSync } from "node:fs";
3
+ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
4
4
  import type { Command } from "commander";
5
5
  import type { EmitContext, HarneryProgramContext } from "../commander.ts";
6
6
  import { resolveCoordRoot } from "../core/agents/coord-client.ts";
7
+ import { artifactsRoot, parseArtifactManifest } from "../core/artifacts/index.ts";
7
8
  import {
8
9
  readCoordinationViewV3,
9
10
  requireAuthoritySafeCoordinationViewV3,
@@ -25,6 +26,15 @@ export function registerRmCommand(
25
26
  "Allowed directory; each target must be strictly inside it",
26
27
  )
27
28
  .option("-r, --recursive", "Permit directory removal after inspecting its complete contents")
29
+ .option(
30
+ "--clean-clone",
31
+ "Remove only clean standalone clones inside one owned artifact; refuse local-only commits and worktrees",
32
+ )
33
+ .option(
34
+ "--entry-limit <n>",
35
+ "Maximum inspected entries, 1-100000 (default 10000); larger limits require one current caller-owned managed artifact as --root",
36
+ (value: string) => Number(value),
37
+ )
28
38
  .option(
29
39
  "--allow-protected <path>",
30
40
  "Remove this one protected path (Git metadata, credentials, Harnery state, keys) inside a target; repeat per path",
@@ -65,7 +75,34 @@ export function registerRmCommand(
65
75
  const liveRoots = [coordRoot, gitTopLevel(process.cwd())].filter((dir): dir is string =>
66
76
  Boolean(dir),
67
77
  );
68
- const report = guardedRemove(paths, { ...options, liveRoots }, checkClaims);
78
+ const assertOwnedArtifact = (root: string): void => {
79
+ if (!coordRoot || dirname(root) !== realpathSync(artifactsRoot(coordRoot)))
80
+ throw new Error("Copied state requires --root to name one owned managed artifact");
81
+ const view = requireAuthoritySafeCoordinationViewV3(readCoordinationViewV3(coordRoot));
82
+ const owner = resolveOwner({ payload: null, coordRoot });
83
+ const ownId = owner ? liveInstanceIdV3(owner.instance_id) : undefined;
84
+ if (!ownId || !view.instances[ownId]?.authority_eligible)
85
+ throw new Error("Copied state requires an authenticated current artifact owner");
86
+ const record = resolve(root, ".harnery-artifact.json");
87
+ const stat = lstatSync(record);
88
+ if (!stat.isFile() || stat.isSymbolicLink())
89
+ throw new Error("An owned artifact requires a regular manifest file");
90
+ const parsed = parseArtifactManifest(JSON.parse(readFileSync(record, "utf8")));
91
+ if (
92
+ !parsed.ok ||
93
+ parsed.manifest.released_at ||
94
+ !parsed.manifest.created_by?.instance_id ||
95
+ liveInstanceIdV3(parsed.manifest.created_by.instance_id) !== ownId
96
+ )
97
+ throw new Error(
98
+ "Copied state requires a valid unreleased artifact owned by the caller",
99
+ );
100
+ };
101
+ const report = guardedRemove(
102
+ paths,
103
+ { ...options, liveRoots, assertOwnedArtifact },
104
+ checkClaims,
105
+ );
69
106
  if (options.json) {
70
107
  emit.config({ format: "json" });
71
108
  emit.data(report);
@@ -76,7 +113,9 @@ export function registerRmCommand(
76
113
  ];
77
114
  if (report.protected.length)
78
115
  lines.push(
79
- "Protected paths named with --allow-protected:",
116
+ options.cleanClone
117
+ ? "Verified clone metadata:"
118
+ : "Protected paths named with --allow-protected:",
80
119
  ...report.protected.map((path) => ` ${path}`),
81
120
  );
82
121
  if (report.links.length)
@@ -120,6 +120,7 @@ export function registerServersCommand(
120
120
  type: "unregistered",
121
121
  label: stray.command,
122
122
  pid: stray.pid,
123
+ ...(stray.start_token ? { start_token: stray.start_token } : {}),
123
124
  host: hostname(),
124
125
  started_at: new Date().toISOString(),
125
126
  registered_at: new Date().toISOString(),
@@ -207,10 +208,20 @@ export function registerServersCommand(
207
208
  emit.config({ format: "json" });
208
209
  emit.data({ applied: Boolean(options.yes), pruned: report.pruned, decisions, results });
209
210
  } else {
210
- const lines = decisions.map(
211
- (d) =>
212
- `${d.action === "stop" ? (options.yes ? "stopped" : "would stop") : "keep"} ${d.id} ${d.reason}`,
213
- );
211
+ const lines = decisions.map((decision) => {
212
+ const result = results.find((item) => item.id === decision.id);
213
+ const action =
214
+ decision.action === "keep"
215
+ ? "keep"
216
+ : !options.yes
217
+ ? "would stop"
218
+ : result?.stopped
219
+ ? "stopped"
220
+ : result?.method === "not-running"
221
+ ? "already stopped"
222
+ : "could not stop";
223
+ return `${action} ${decision.id} ${result?.detail ?? decision.reason}`;
224
+ });
214
225
  if (report.pruned.length)
215
226
  lines.push(`Removed records of exited servers: ${report.pruned.join(", ")}`);
216
227
  if (!decisions.length) lines.push("No registered servers.");
@@ -218,6 +229,7 @@ export function registerServersCommand(
218
229
  lines.push("Preview only. Re-run with --yes to stop.");
219
230
  emit.text(lines.join("\n"));
220
231
  }
232
+ if (results.some((result) => result.method === "refused")) emit.setExitCode(1);
221
233
  } catch (error) {
222
234
  fail(error);
223
235
  }
@@ -83,11 +83,16 @@ export function registerSupervisorCommand(
83
83
  .action(async (options: { root?: string }) => {
84
84
  try {
85
85
  const root = resolve(options.root ?? coordRoot(context));
86
- let status = requestSupervisorStop(root);
86
+ const requested = requestSupervisorStop(root);
87
+ let status = requested;
87
88
  const deadline = Date.now() + 5_000;
88
89
  while (status.running && Date.now() < deadline) {
89
90
  await new Promise((done) => setTimeout(done, 50));
90
- status = readSupervisorStatus(root);
91
+ status = {
92
+ ...readSupervisorStatus(root),
93
+ signal_sent: requested.signal_sent,
94
+ signal_verdict: requested.signal_verdict,
95
+ };
91
96
  }
92
97
  emit.data(status);
93
98
  } catch (error) {
@@ -172,17 +172,25 @@ function renderToc(r: TocResult): string {
172
172
  return lines.join("\n");
173
173
  }
174
174
 
175
- async function runSection(file: string, query: string, opts: SectionOpts): Promise<SectionResult> {
175
+ export async function runSection(
176
+ file: string,
177
+ query: string,
178
+ opts: SectionOpts,
179
+ ): Promise<SectionResult> {
176
180
  if (!query.trim()) throw new Error("header query required");
177
181
  const tocResult = await runToc(file, {});
178
182
  const absPath = resolve(file);
179
183
  const lines = readFileSync(absPath, "utf8").split("\n");
180
184
 
181
- const matches = tocResult.headers.filter((h) =>
182
- opts.caseSensitive
183
- ? h.text.includes(query)
184
- : h.text.toLowerCase().includes(query.toLowerCase()),
185
- );
185
+ const same = (a: string, b: string) =>
186
+ opts.caseSensitive ? a === b : a.toLowerCase() === b.toLowerCase();
187
+ const contains = (a: string, b: string) =>
188
+ opts.caseSensitive ? a.includes(b) : a.toLowerCase().includes(b.toLowerCase());
189
+ // A header that equals the query wins over headers that merely contain it,
190
+ // so "Media" can still select "## Media" beside "## Media recipes".
191
+ const exact = tocResult.headers.filter((h) => same(h.text, query.trim()));
192
+ const matches =
193
+ exact.length > 0 ? exact : tocResult.headers.filter((h) => contains(h.text, query));
186
194
  if (matches.length === 0) {
187
195
  throw new Error(
188
196
  `no header matching "${query}". Run \`${resolveBinName()} toc ${file}\` to list available headers.`,