harnery 0.29.0 → 0.31.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 (512) hide show
  1. package/README.md +4 -4
  2. package/dist/commander.d.ts +8 -0
  3. package/dist/commander.d.ts.map +1 -1
  4. package/dist/commander.js +14 -13
  5. package/dist/commands/adapter.d.ts +12 -0
  6. package/dist/commands/adapter.d.ts.map +1 -0
  7. package/dist/commands/{harness.js → adapter.js} +35 -35
  8. package/dist/commands/agents.d.ts +3 -2
  9. package/dist/commands/agents.d.ts.map +1 -1
  10. package/dist/commands/agents.js +61 -60
  11. package/dist/commands/artifacts.d.ts +4 -0
  12. package/dist/commands/artifacts.d.ts.map +1 -0
  13. package/dist/commands/artifacts.js +143 -0
  14. package/dist/commands/backup.d.ts +1 -1
  15. package/dist/commands/backup.d.ts.map +1 -1
  16. package/dist/commands/backup.js +5 -2
  17. package/dist/commands/browse.d.ts.map +1 -1
  18. package/dist/commands/browse.js +310 -7
  19. package/dist/commands/checkpoint.d.ts +12 -0
  20. package/dist/commands/checkpoint.d.ts.map +1 -0
  21. package/dist/commands/checkpoint.js +162 -0
  22. package/dist/commands/context.d.ts +2 -2
  23. package/dist/commands/context.d.ts.map +1 -1
  24. package/dist/commands/context.js +3 -151
  25. package/dist/commands/decision.d.ts.map +1 -1
  26. package/dist/commands/decision.js +31 -7
  27. package/dist/commands/deinit.d.ts +2 -2
  28. package/dist/commands/deinit.js +15 -15
  29. package/dist/commands/doctor.js +23 -23
  30. package/dist/commands/governor.d.ts +4 -0
  31. package/dist/commands/governor.d.ts.map +1 -0
  32. package/dist/commands/{supervisor.js → governor.js} +133 -108
  33. package/dist/commands/init.d.ts +12 -12
  34. package/dist/commands/init.d.ts.map +1 -1
  35. package/dist/commands/init.js +44 -30
  36. package/dist/commands/{session.d.ts → journal.d.ts} +2 -2
  37. package/dist/commands/journal.d.ts.map +1 -0
  38. package/dist/commands/{scratch.js → journal.js} +47 -47
  39. package/dist/commands/policy.js +1 -1
  40. package/dist/commands/presence.js +2 -2
  41. package/dist/commands/sync.d.ts +1 -1
  42. package/dist/commands/sync.js +3 -3
  43. package/dist/commands/tunnel.d.ts +16 -0
  44. package/dist/commands/tunnel.d.ts.map +1 -1
  45. package/dist/commands/tunnel.js +193 -23
  46. package/dist/commands/web-fetch.js +1 -1
  47. package/dist/commands/web.d.ts +19 -0
  48. package/dist/commands/web.d.ts.map +1 -1
  49. package/dist/commands/web.js +51 -0
  50. package/dist/commands/work.d.ts +2 -1
  51. package/dist/commands/work.d.ts.map +1 -1
  52. package/dist/commands/work.js +55 -25
  53. package/dist/commands/workflow.d.ts.map +1 -1
  54. package/dist/commands/workflow.js +35 -28
  55. package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
  56. package/dist/core/adapters/attest-projection.d.ts.map +1 -0
  57. package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
  58. package/dist/core/adapters/attest.d.ts.map +1 -0
  59. package/dist/core/{harnesses → adapters}/attest.js +9 -9
  60. package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
  61. package/dist/core/adapters/attestation.d.ts.map +1 -0
  62. package/dist/core/{harnesses → adapters}/attestation.js +20 -20
  63. package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
  64. package/dist/core/adapters/bench.d.ts.map +1 -0
  65. package/dist/core/{harnesses → adapters}/bench.js +12 -12
  66. package/dist/core/adapters/index.d.ts +13 -0
  67. package/dist/core/adapters/index.d.ts.map +1 -0
  68. package/dist/core/adapters/index.js +6 -0
  69. package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
  70. package/dist/core/adapters/profiles.d.ts.map +1 -0
  71. package/dist/core/{harnesses → adapters}/profiles.js +11 -11
  72. package/dist/core/adapters/registry.d.ts +15 -0
  73. package/dist/core/adapters/registry.d.ts.map +1 -0
  74. package/dist/core/{harnesses → adapters}/registry.js +11 -11
  75. package/dist/core/{harnesses → adapters}/types.d.ts +28 -23
  76. package/dist/core/adapters/types.d.ts.map +1 -0
  77. package/dist/core/{harnesses → adapters}/types.js +1 -1
  78. package/dist/core/agents/canonical-emit.d.ts +4 -4
  79. package/dist/core/agents/canonical-emit.js +5 -5
  80. package/dist/core/agents/cli-emit.js +1 -1
  81. package/dist/core/agents/cli.js +30 -26
  82. package/dist/core/agents/codex-replay.d.ts +1 -1
  83. package/dist/core/agents/codex-replay.js +6 -6
  84. package/dist/core/agents/coord-client.d.ts +21 -2
  85. package/dist/core/agents/coord-client.d.ts.map +1 -1
  86. package/dist/core/agents/coord-client.js +122 -27
  87. package/dist/core/agents/events/consume.d.ts +1 -1
  88. package/dist/core/agents/events/emit.d.ts +5 -6
  89. package/dist/core/agents/events/emit.d.ts.map +1 -1
  90. package/dist/core/agents/events/emit.js +2 -2
  91. package/dist/core/agents/render/prompt-context.d.ts +21 -9
  92. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  93. package/dist/core/agents/render/prompt-context.js +82 -30
  94. package/dist/core/agents/render/session-context.d.ts +1 -1
  95. package/dist/core/agents/render/session-context.js +5 -5
  96. package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
  97. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  98. package/dist/core/agents/rules/claim-conflict.js +1 -1
  99. package/dist/core/agents/rules/commit-conflict.js +98 -22
  100. package/dist/core/agents/rules/stop-hook.d.ts +9 -9
  101. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  102. package/dist/core/agents/rules/stop-hook.js +23 -5
  103. package/dist/core/agents/rules/verdict.d.ts +14 -0
  104. package/dist/core/agents/rules/verdict.d.ts.map +1 -0
  105. package/dist/core/agents/rules/verdict.js +1 -0
  106. package/dist/core/agents/session-events.js +3 -3
  107. package/dist/core/agents/state/council.d.ts +1 -1
  108. package/dist/core/agents/state/council.js +1 -1
  109. package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
  110. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
  111. package/dist/core/agents/state/heartbeat-projector.js +14 -10
  112. package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
  113. package/dist/core/agents/state/heartbeat-writer.js +12 -12
  114. package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
  115. package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
  116. package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
  117. package/dist/core/agents/state/pidmap.d.ts +28 -4
  118. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  119. package/dist/core/agents/state/pidmap.js +130 -15
  120. package/dist/core/agents/state/proc-start.d.ts +95 -0
  121. package/dist/core/agents/state/proc-start.d.ts.map +1 -0
  122. package/dist/core/agents/state/proc-start.js +199 -0
  123. package/dist/core/agents/state/shell-mutation.d.ts +1 -1
  124. package/dist/core/agents/state/shell-mutation.js +1 -1
  125. package/dist/core/agents/state/stale-sweep.js +7 -7
  126. package/dist/core/artifacts/index.d.ts +86 -0
  127. package/dist/core/artifacts/index.d.ts.map +1 -0
  128. package/dist/core/artifacts/index.js +421 -0
  129. package/dist/core/config.d.ts +9 -2
  130. package/dist/core/config.d.ts.map +1 -1
  131. package/dist/core/config.js +26 -2
  132. package/dist/core/context/index.d.ts +12 -12
  133. package/dist/core/context/index.js +10 -10
  134. package/dist/core/governor/adapter-spread.d.ts +52 -0
  135. package/dist/core/governor/adapter-spread.d.ts.map +1 -0
  136. package/dist/core/governor/adapter-spread.js +52 -0
  137. package/dist/core/governor/index.d.ts +7 -0
  138. package/dist/core/governor/index.d.ts.map +1 -0
  139. package/dist/core/governor/index.js +6 -0
  140. package/dist/core/governor/plan-api.d.ts +38 -0
  141. package/dist/core/governor/plan-api.d.ts.map +1 -0
  142. package/dist/core/governor/plan-api.js +83 -0
  143. package/dist/core/governor/plan-read.d.ts +5 -0
  144. package/dist/core/governor/plan-read.d.ts.map +1 -0
  145. package/dist/core/{supervisor → governor}/plan-read.js +71 -51
  146. package/dist/core/governor/plan-types.d.ts +181 -0
  147. package/dist/core/governor/plan-types.d.ts.map +1 -0
  148. package/dist/core/{supervisor → governor}/plan-types.js +4 -4
  149. package/dist/core/governor/planning.d.ts +48 -0
  150. package/dist/core/governor/planning.d.ts.map +1 -0
  151. package/dist/core/{supervisor → governor}/planning.js +143 -94
  152. package/dist/core/governor/read.d.ts +6 -0
  153. package/dist/core/governor/read.d.ts.map +1 -0
  154. package/dist/core/governor/read.js +4 -0
  155. package/dist/core/governor/runner.d.ts +37 -0
  156. package/dist/core/governor/runner.d.ts.map +1 -0
  157. package/dist/core/{supervisor → governor}/runner.js +15 -15
  158. package/dist/core/governor/service-read.d.ts +6 -0
  159. package/dist/core/governor/service-read.d.ts.map +1 -0
  160. package/dist/core/{supervisor → governor}/service-read.js +12 -12
  161. package/dist/core/governor/service.d.ts +114 -0
  162. package/dist/core/governor/service.d.ts.map +1 -0
  163. package/dist/core/{supervisor → governor}/service.js +57 -57
  164. package/dist/core/governor/state.d.ts +116 -0
  165. package/dist/core/governor/state.d.ts.map +1 -0
  166. package/dist/core/{supervisor → governor}/state.js +290 -116
  167. package/dist/core/hooks/adapter/detect.d.ts +9 -0
  168. package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
  169. package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
  170. package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
  171. package/dist/core/hooks/adapter/events.d.ts.map +1 -0
  172. package/dist/core/hooks/{harness → adapter}/events.js +5 -5
  173. package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
  174. package/dist/core/hooks/adapter/output.d.ts.map +1 -0
  175. package/dist/core/hooks/{harness → adapter}/output.js +30 -22
  176. package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
  177. package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
  178. package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
  179. package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
  180. package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
  181. package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
  182. package/dist/core/hooks/cli.d.ts +3 -3
  183. package/dist/core/hooks/cli.js +175 -151
  184. package/dist/core/hooks/effects/image-capture.d.ts +5 -5
  185. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  186. package/dist/core/hooks/effects/image-capture.js +3 -3
  187. package/dist/core/hooks/effects/index.d.ts +12 -12
  188. package/dist/core/hooks/effects/index.d.ts.map +1 -1
  189. package/dist/core/hooks/effects/index.js +17 -17
  190. package/dist/core/hooks/events/emit.d.ts +2 -2
  191. package/dist/core/hooks/events/emit.d.ts.map +1 -1
  192. package/dist/core/hooks/events/emit.js +1 -1
  193. package/dist/core/hooks/events/rotate.js +1 -1
  194. package/dist/core/hooks/events/schema.d.ts +13 -5
  195. package/dist/core/hooks/events/schema.d.ts.map +1 -1
  196. package/dist/core/hooks/guard-path.d.ts +2 -2
  197. package/dist/core/hooks/guard-path.js +2 -2
  198. package/dist/core/hooks/index.d.ts +1 -1
  199. package/dist/core/hooks/index.d.ts.map +1 -1
  200. package/dist/core/hooks/resolve/anchor.d.ts +14 -5
  201. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
  202. package/dist/core/hooks/resolve/anchor.js +64 -7
  203. package/dist/core/hooks/resolve/coord-root.d.ts +3 -3
  204. package/dist/core/hooks/resolve/coord-root.js +4 -4
  205. package/dist/core/hooks/resolve/intent.js +1 -1
  206. package/dist/core/hooks/resolve/owner.d.ts +1 -1
  207. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  208. package/dist/core/hooks/resolve/owner.js +11 -5
  209. package/dist/core/{scratch → journal}/index.d.ts +25 -25
  210. package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
  211. package/dist/core/{scratch → journal}/index.js +38 -38
  212. package/dist/core/policy/evaluate.d.ts +1 -1
  213. package/dist/core/policy/evaluate.d.ts.map +1 -1
  214. package/dist/core/policy/evaluate.js +7 -7
  215. package/dist/core/policy/types.d.ts +3 -3
  216. package/dist/core/policy/types.d.ts.map +1 -1
  217. package/dist/core/work/runner.d.ts.map +1 -1
  218. package/dist/core/work/runner.js +11 -2
  219. package/dist/core/work/state.d.ts +28 -3
  220. package/dist/core/work/state.d.ts.map +1 -1
  221. package/dist/core/work/state.js +148 -16
  222. package/dist/core/workflow/adapters.d.ts +17 -0
  223. package/dist/core/workflow/adapters.d.ts.map +1 -0
  224. package/dist/core/workflow/adapters.js +21 -0
  225. package/dist/core/workflow/approvals.js +6 -6
  226. package/dist/core/workflow/billing.d.ts +9 -9
  227. package/dist/core/workflow/billing.js +9 -9
  228. package/dist/core/workflow/child-env.d.ts +10 -2
  229. package/dist/core/workflow/child-env.d.ts.map +1 -1
  230. package/dist/core/workflow/child-env.js +12 -4
  231. package/dist/core/workflow/engine.d.ts +15 -5
  232. package/dist/core/workflow/engine.d.ts.map +1 -1
  233. package/dist/core/workflow/engine.js +151 -83
  234. package/dist/core/workflow/evidence-preflight.d.ts +24 -0
  235. package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
  236. package/dist/core/workflow/evidence-preflight.js +134 -0
  237. package/dist/core/workflow/index.d.ts +3 -2
  238. package/dist/core/workflow/index.d.ts.map +1 -1
  239. package/dist/core/workflow/index.js +2 -1
  240. package/dist/core/workflow/proof.d.ts +28 -5
  241. package/dist/core/workflow/proof.d.ts.map +1 -1
  242. package/dist/core/workflow/proof.js +77 -34
  243. package/dist/core/workflow/run-state.d.ts +1 -1
  244. package/dist/core/workflow/run-state.js +7 -7
  245. package/dist/core/workflow/sandbox-projection.d.ts +6 -6
  246. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  247. package/dist/core/workflow/sandbox-projection.js +11 -11
  248. package/dist/core/workflow/spawn-claude.d.ts +3 -3
  249. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  250. package/dist/core/workflow/spawn-claude.js +28 -8
  251. package/dist/core/workflow/spawn-codex.d.ts +4 -4
  252. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  253. package/dist/core/workflow/spawn-codex.js +26 -8
  254. package/dist/core/workflow/spawn-cursor.d.ts +4 -4
  255. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  256. package/dist/core/workflow/spawn-cursor.js +27 -8
  257. package/dist/core/workflow/spawn-failure.d.ts +15 -1
  258. package/dist/core/workflow/spawn-failure.d.ts.map +1 -1
  259. package/dist/core/workflow/spawn-failure.js +35 -1
  260. package/dist/core/workflow/specialists.js +2 -2
  261. package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
  262. package/dist/core/workflow/transcript.d.ts.map +1 -0
  263. package/dist/core/workflow/{journal.js → transcript.js} +14 -14
  264. package/dist/core/workflow/types.d.ts +119 -46
  265. package/dist/core/workflow/types.d.ts.map +1 -1
  266. package/dist/core/workflow/types.js +11 -1
  267. package/dist/core/workflow/validate.d.ts +1 -1
  268. package/dist/core/workflow/validate.js +1 -1
  269. package/dist/core/workflow/workspaces/cancellation.js +2 -2
  270. package/dist/core/workflow/workspaces/cleanup.js +2 -2
  271. package/dist/core/workflow/workspaces/execution.js +6 -6
  272. package/dist/core/workflow/workspaces/inspect.js +9 -9
  273. package/dist/core/workflow/workspaces/integration.js +14 -14
  274. package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
  275. package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
  276. package/dist/core/workflow/workspaces/lifecycle.js +9 -9
  277. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  278. package/dist/core/workflow/workspaces/local-git.js +39 -5
  279. package/dist/core/workflow/workspaces/recovery.js +3 -3
  280. package/dist/core/workflow/workspaces/state.d.ts +1 -1
  281. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  282. package/dist/core/workflow/workspaces/state.js +3 -3
  283. package/dist/core/workflow/workspaces/types.d.ts +1 -1
  284. package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
  285. package/dist/lib/browser/asserts.d.ts +28 -0
  286. package/dist/lib/browser/asserts.d.ts.map +1 -0
  287. package/dist/lib/browser/asserts.js +152 -0
  288. package/dist/lib/browser/client.d.ts +49 -0
  289. package/dist/lib/browser/client.d.ts.map +1 -1
  290. package/dist/lib/browser/client.js +155 -14
  291. package/dist/lib/browser/content-checks.d.ts +108 -0
  292. package/dist/lib/browser/content-checks.d.ts.map +1 -0
  293. package/dist/lib/browser/content-checks.js +474 -0
  294. package/dist/lib/browser/critique.d.ts +91 -0
  295. package/dist/lib/browser/critique.d.ts.map +1 -0
  296. package/dist/lib/browser/critique.js +167 -0
  297. package/dist/lib/browser/geometry.d.ts +32 -0
  298. package/dist/lib/browser/geometry.d.ts.map +1 -1
  299. package/dist/lib/browser/geometry.js +244 -1
  300. package/dist/lib/browser/index.d.ts +4 -1
  301. package/dist/lib/browser/index.d.ts.map +1 -1
  302. package/dist/lib/browser/index.js +2 -0
  303. package/dist/lib/claude-desktop.d.ts.map +1 -1
  304. package/dist/lib/claude-desktop.js +4 -1
  305. package/dist/lib/council/index.d.ts +6 -6
  306. package/dist/lib/council/index.d.ts.map +1 -1
  307. package/dist/lib/council/index.js +8 -8
  308. package/dist/lib/exec.d.ts +7 -0
  309. package/dist/lib/exec.d.ts.map +1 -1
  310. package/dist/lib/exec.js +6 -3
  311. package/dist/lib/identities/assume.d.ts +2 -2
  312. package/dist/lib/identities/assume.js +7 -7
  313. package/dist/lib/instructions/apply.d.ts +3 -3
  314. package/dist/lib/instructions/apply.d.ts.map +1 -1
  315. package/dist/lib/instructions/apply.js +75 -27
  316. package/dist/lib/instructions/host-addendum.d.ts +54 -0
  317. package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
  318. package/dist/lib/instructions/host-addendum.js +107 -0
  319. package/dist/lib/instructions/templates.d.ts +10 -3
  320. package/dist/lib/instructions/templates.d.ts.map +1 -1
  321. package/dist/lib/instructions/templates.js +41 -12
  322. package/dist/lib/machine.d.ts +2 -2
  323. package/dist/lib/machine.js +2 -2
  324. package/package.json +26 -21
  325. package/schemas/config.schema.json +26 -1
  326. package/src/commander.ts +22 -13
  327. package/src/commands/{harness.ts → adapter.ts} +46 -46
  328. package/src/commands/agents.ts +71 -64
  329. package/src/commands/artifacts.ts +168 -0
  330. package/src/commands/backup.ts +47 -33
  331. package/src/commands/browse.ts +438 -2
  332. package/src/commands/checkpoint.ts +196 -0
  333. package/src/commands/context.ts +3 -176
  334. package/src/commands/decision.ts +41 -7
  335. package/src/commands/deinit.ts +16 -16
  336. package/src/commands/doctor.ts +28 -28
  337. package/src/commands/{supervisor.ts → governor.ts} +184 -154
  338. package/src/commands/init.ts +50 -34
  339. package/src/commands/{scratch.ts → journal.ts} +60 -60
  340. package/src/commands/policy.ts +1 -1
  341. package/src/commands/presence.ts +2 -2
  342. package/src/commands/sync.ts +3 -3
  343. package/src/commands/tunnel.ts +237 -34
  344. package/src/commands/web-fetch.ts +1 -1
  345. package/src/commands/web.ts +56 -1
  346. package/src/commands/work.ts +72 -38
  347. package/src/commands/workflow.ts +43 -34
  348. package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
  349. package/src/core/{harnesses → adapters}/attest.ts +27 -27
  350. package/src/core/{harnesses → adapters}/attestation.ts +41 -41
  351. package/src/core/{harnesses → adapters}/bench.ts +34 -43
  352. package/src/core/adapters/index.ts +56 -0
  353. package/src/core/{harnesses → adapters}/profiles.ts +16 -16
  354. package/src/core/{harnesses → adapters}/registry.ts +23 -23
  355. package/src/core/{harnesses → adapters}/types.ts +28 -23
  356. package/src/core/agents/canonical-emit.ts +6 -6
  357. package/src/core/agents/cli-emit.ts +1 -1
  358. package/src/core/agents/cli.ts +30 -28
  359. package/src/core/agents/codex-replay.ts +6 -6
  360. package/src/core/agents/coord-client.ts +119 -28
  361. package/src/core/agents/events/consume.ts +1 -1
  362. package/src/core/agents/events/emit.ts +7 -6
  363. package/src/core/agents/render/prompt-context.ts +107 -31
  364. package/src/core/agents/render/session-context.ts +6 -6
  365. package/src/core/agents/rules/claim-conflict.ts +4 -7
  366. package/src/core/agents/rules/commit-conflict.ts +103 -22
  367. package/src/core/agents/rules/stop-hook.ts +33 -17
  368. package/src/core/agents/rules/verdict.ts +13 -0
  369. package/src/core/agents/session-events.ts +4 -4
  370. package/src/core/agents/state/council.ts +1 -1
  371. package/src/core/agents/state/heartbeat-projector.ts +16 -12
  372. package/src/core/agents/state/heartbeat-writer.ts +12 -12
  373. package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
  374. package/src/core/agents/state/pidmap.ts +130 -15
  375. package/src/core/agents/state/proc-start.ts +208 -0
  376. package/src/core/agents/state/shell-mutation.ts +1 -1
  377. package/src/core/agents/state/stale-sweep.ts +7 -7
  378. package/src/core/artifacts/index.ts +557 -0
  379. package/src/core/config.ts +30 -2
  380. package/src/core/context/index.ts +15 -15
  381. package/src/core/governor/adapter-spread.ts +82 -0
  382. package/src/core/governor/index.ts +91 -0
  383. package/src/core/governor/plan-api.ts +115 -0
  384. package/src/core/{supervisor → governor}/plan-read.ts +120 -96
  385. package/src/core/{supervisor → governor}/plan-types.ts +64 -50
  386. package/src/core/{supervisor → governor}/planning.ts +240 -188
  387. package/src/core/governor/read.ts +59 -0
  388. package/src/core/{supervisor → governor}/runner.ts +39 -39
  389. package/src/core/{supervisor → governor}/service-read.ts +22 -22
  390. package/src/core/{supervisor → governor}/service.ts +117 -119
  391. package/src/core/{supervisor → governor}/state.ts +389 -174
  392. package/src/core/hooks/adapter/detect.ts +30 -0
  393. package/src/core/hooks/{harness → adapter}/events.ts +16 -14
  394. package/src/core/hooks/{harness → adapter}/output.ts +31 -23
  395. package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
  396. package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
  397. package/src/core/hooks/cli.ts +185 -162
  398. package/src/core/hooks/effects/image-capture.ts +6 -6
  399. package/src/core/hooks/effects/index.ts +17 -17
  400. package/src/core/hooks/events/emit.ts +3 -3
  401. package/src/core/hooks/events/rotate.ts +1 -1
  402. package/src/core/hooks/events/schema.ts +15 -7
  403. package/src/core/hooks/guard-path.ts +2 -2
  404. package/src/core/hooks/index.ts +1 -1
  405. package/src/core/hooks/resolve/anchor.ts +63 -8
  406. package/src/core/hooks/resolve/coord-root.ts +4 -4
  407. package/src/core/hooks/resolve/intent.ts +1 -1
  408. package/src/core/hooks/resolve/owner.ts +11 -5
  409. package/src/core/{scratch → journal}/index.ts +53 -53
  410. package/src/core/policy/evaluate.ts +8 -8
  411. package/src/core/policy/types.ts +3 -3
  412. package/src/core/work/runner.ts +11 -2
  413. package/src/core/work/state.ts +185 -21
  414. package/src/core/workflow/adapters.ts +33 -0
  415. package/src/core/workflow/approvals.ts +7 -7
  416. package/src/core/workflow/billing.ts +12 -12
  417. package/src/core/workflow/child-env.ts +13 -4
  418. package/src/core/workflow/engine.ts +166 -90
  419. package/src/core/workflow/evidence-preflight.ts +165 -0
  420. package/src/core/workflow/index.ts +6 -3
  421. package/src/core/workflow/proof.ts +94 -48
  422. package/src/core/workflow/run-state.ts +7 -7
  423. package/src/core/workflow/sandbox-projection.ts +16 -16
  424. package/src/core/workflow/spawn-claude.ts +34 -12
  425. package/src/core/workflow/spawn-codex.ts +30 -12
  426. package/src/core/workflow/spawn-cursor.ts +31 -12
  427. package/src/core/workflow/spawn-failure.ts +41 -1
  428. package/src/core/workflow/specialists.ts +2 -2
  429. package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
  430. package/src/core/workflow/types.ts +130 -46
  431. package/src/core/workflow/validate.ts +1 -1
  432. package/src/core/workflow/workspaces/cancellation.ts +2 -2
  433. package/src/core/workflow/workspaces/cleanup.ts +2 -2
  434. package/src/core/workflow/workspaces/execution.ts +6 -6
  435. package/src/core/workflow/workspaces/inspect.ts +14 -11
  436. package/src/core/workflow/workspaces/integration.ts +18 -14
  437. package/src/core/workflow/workspaces/lifecycle.ts +10 -10
  438. package/src/core/workflow/workspaces/local-git.ts +47 -5
  439. package/src/core/workflow/workspaces/recovery.ts +3 -3
  440. package/src/core/workflow/workspaces/state.ts +4 -3
  441. package/src/core/workflow/workspaces/types.ts +1 -1
  442. package/src/lib/browser/asserts.ts +177 -0
  443. package/src/lib/browser/client.ts +189 -14
  444. package/src/lib/browser/content-checks.ts +571 -0
  445. package/src/lib/browser/critique.ts +231 -0
  446. package/src/lib/browser/geometry.ts +297 -1
  447. package/src/lib/browser/index.ts +34 -0
  448. package/src/lib/claude-desktop.ts +4 -1
  449. package/src/lib/council/index.ts +9 -9
  450. package/src/lib/exec.ts +13 -3
  451. package/src/lib/identities/assume.ts +7 -7
  452. package/src/lib/instructions/apply.ts +87 -25
  453. package/src/lib/instructions/host-addendum.ts +126 -0
  454. package/src/lib/instructions/templates.ts +44 -15
  455. package/src/lib/machine.ts +2 -2
  456. package/dist/commands/harness.d.ts +0 -12
  457. package/dist/commands/harness.d.ts.map +0 -1
  458. package/dist/commands/scratch.d.ts +0 -4
  459. package/dist/commands/scratch.d.ts.map +0 -1
  460. package/dist/commands/session.d.ts.map +0 -1
  461. package/dist/commands/session.js +0 -162
  462. package/dist/commands/supervisor.d.ts +0 -4
  463. package/dist/commands/supervisor.d.ts.map +0 -1
  464. package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
  465. package/dist/core/harnesses/attest.d.ts.map +0 -1
  466. package/dist/core/harnesses/attestation.d.ts.map +0 -1
  467. package/dist/core/harnesses/bench.d.ts.map +0 -1
  468. package/dist/core/harnesses/index.d.ts +0 -13
  469. package/dist/core/harnesses/index.d.ts.map +0 -1
  470. package/dist/core/harnesses/index.js +0 -6
  471. package/dist/core/harnesses/profiles.d.ts.map +0 -1
  472. package/dist/core/harnesses/registry.d.ts +0 -15
  473. package/dist/core/harnesses/registry.d.ts.map +0 -1
  474. package/dist/core/harnesses/types.d.ts.map +0 -1
  475. package/dist/core/hooks/harness/detect.d.ts +0 -9
  476. package/dist/core/hooks/harness/events.d.ts.map +0 -1
  477. package/dist/core/hooks/harness/output.d.ts.map +0 -1
  478. package/dist/core/supervisor/index.d.ts +0 -7
  479. package/dist/core/supervisor/index.d.ts.map +0 -1
  480. package/dist/core/supervisor/index.js +0 -6
  481. package/dist/core/supervisor/plan-api.d.ts +0 -23
  482. package/dist/core/supervisor/plan-api.d.ts.map +0 -1
  483. package/dist/core/supervisor/plan-api.js +0 -50
  484. package/dist/core/supervisor/plan-read.d.ts +0 -5
  485. package/dist/core/supervisor/plan-read.d.ts.map +0 -1
  486. package/dist/core/supervisor/plan-types.d.ts +0 -170
  487. package/dist/core/supervisor/plan-types.d.ts.map +0 -1
  488. package/dist/core/supervisor/planning.d.ts +0 -33
  489. package/dist/core/supervisor/planning.d.ts.map +0 -1
  490. package/dist/core/supervisor/read.d.ts +0 -6
  491. package/dist/core/supervisor/read.d.ts.map +0 -1
  492. package/dist/core/supervisor/read.js +0 -4
  493. package/dist/core/supervisor/runner.d.ts +0 -37
  494. package/dist/core/supervisor/runner.d.ts.map +0 -1
  495. package/dist/core/supervisor/service-read.d.ts +0 -6
  496. package/dist/core/supervisor/service-read.d.ts.map +0 -1
  497. package/dist/core/supervisor/service.d.ts +0 -114
  498. package/dist/core/supervisor/service.d.ts.map +0 -1
  499. package/dist/core/supervisor/state.d.ts +0 -95
  500. package/dist/core/supervisor/state.d.ts.map +0 -1
  501. package/dist/core/workflow/harnesses.d.ts +0 -17
  502. package/dist/core/workflow/harnesses.d.ts.map +0 -1
  503. package/dist/core/workflow/harnesses.js +0 -21
  504. package/dist/core/workflow/journal.d.ts.map +0 -1
  505. package/src/commands/session.ts +0 -187
  506. package/src/core/harnesses/index.ts +0 -56
  507. package/src/core/hooks/harness/detect.ts +0 -30
  508. package/src/core/supervisor/index.ts +0 -89
  509. package/src/core/supervisor/plan-api.ts +0 -73
  510. package/src/core/supervisor/read.ts +0 -59
  511. package/src/core/workflow/harnesses.ts +0 -33
  512. /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Repository-local working artifacts.
3
+ *
4
+ * Artifacts are file trees that should survive an agent session but should not
5
+ * become project records: screenshots, exports, audit dumps, rollback inputs,
6
+ * and similar material. Each direct child of `.harnery/artifacts/` is one
7
+ * managed unit with a small manifest. Cleanup fails closed: only a valid,
8
+ * expired, inactive, untracked managed unit is deletable.
9
+ */
10
+ import { spawnSync } from "node:child_process";
11
+ import { randomUUID } from "node:crypto";
12
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
13
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
14
+ import { artifactDefaultRetentionDays } from "../config.js";
15
+ export const ARTIFACTS_DIR = join(".harnery", "artifacts");
16
+ export const ARTIFACT_MANIFEST = ".harnery-artifact.json";
17
+ export const ARTIFACT_SCHEMA_VERSION = 1;
18
+ export function artifactsRoot(repoRoot) {
19
+ return join(resolve(repoRoot), ARTIFACTS_DIR);
20
+ }
21
+ /** Public config-aware default for embedding hosts that create artifact units. */
22
+ export function configuredArtifactRetentionDays(repoRoot) {
23
+ return artifactDefaultRetentionDays(repoRoot);
24
+ }
25
+ export function createArtifact(repoRoot, input) {
26
+ const now = input.now ?? new Date();
27
+ assertValidDate(now, "now");
28
+ const slug = normalizeSlug(input.slug);
29
+ if (!slug)
30
+ throw new Error("slug must contain at least one ASCII letter or digit");
31
+ const purpose = input.purpose.trim();
32
+ if (!purpose)
33
+ throw new Error("purpose must not be empty");
34
+ const retentionDays = positiveDays(input.retentionDays);
35
+ const artifactId = input.id ?? randomUUID();
36
+ if (!isSafeId(artifactId)) {
37
+ throw new Error("artifact id must use ASCII letters, digits, hyphens, or underscores");
38
+ }
39
+ const root = artifactsRoot(repoRoot);
40
+ mkdirSync(root, { recursive: true });
41
+ const date = now.toISOString().slice(0, 10);
42
+ const path = join(root, `${date}_${slug}_${artifactId.slice(0, 8)}`);
43
+ mkdirSync(path);
44
+ const manifest = {
45
+ schema_version: ARTIFACT_SCHEMA_VERSION,
46
+ artifact_id: artifactId,
47
+ slug,
48
+ purpose,
49
+ created_at: now.toISOString(),
50
+ created_by: input.actor,
51
+ retention: {
52
+ expires_at: addDays(now, retentionDays).toISOString(),
53
+ },
54
+ };
55
+ atomicWriteManifest(path, manifest);
56
+ return { path, manifest };
57
+ }
58
+ export function inventoryArtifacts(repoRoot, opts = {}) {
59
+ const root = artifactsRoot(repoRoot);
60
+ if (!existsSync(root))
61
+ return [];
62
+ const now = opts.now ?? new Date();
63
+ assertValidDate(now, "now");
64
+ const freshnessSeconds = opts.freshnessSeconds ?? 600;
65
+ const rows = [];
66
+ let names;
67
+ try {
68
+ names = readdirSync(root).sort();
69
+ }
70
+ catch (error) {
71
+ return [
72
+ rowFor(root, basename(root), repoRoot, "unknown", errorMessage("cannot read artifact root", error)),
73
+ ];
74
+ }
75
+ for (const name of names) {
76
+ rows.push(classifyArtifactPath(repoRoot, join(root, name), now, freshnessSeconds));
77
+ }
78
+ return rows;
79
+ }
80
+ export function showArtifact(repoRoot, ref, opts = {}) {
81
+ const path = resolveArtifactRef(repoRoot, ref);
82
+ const entry = classifyArtifactPath(repoRoot, path, opts.now ?? new Date(), opts.freshnessSeconds ?? 600);
83
+ const parsed = readManifest(path);
84
+ if (!parsed.ok)
85
+ throw new Error(parsed.reason);
86
+ return { entry, manifest: parsed.manifest };
87
+ }
88
+ export function renewArtifact(repoRoot, ref, days, reason, input = {}) {
89
+ const now = input.now ?? new Date();
90
+ assertValidDate(now, "now");
91
+ const retentionDays = positiveDays(days);
92
+ const why = reason.trim();
93
+ if (!why)
94
+ throw new Error("renewal reason must not be empty");
95
+ const path = resolveArtifactRef(repoRoot, ref);
96
+ const parsed = readManifest(path);
97
+ if (!parsed.ok)
98
+ throw new Error(parsed.reason);
99
+ const manifest = {
100
+ ...parsed.manifest,
101
+ retention: {
102
+ expires_at: addDays(now, retentionDays).toISOString(),
103
+ renewed_at: now.toISOString(),
104
+ reason: why,
105
+ },
106
+ };
107
+ atomicWriteManifest(path, manifest);
108
+ return manifest;
109
+ }
110
+ export function releaseArtifact(repoRoot, ref, input = {}) {
111
+ const now = input.now ?? new Date();
112
+ assertValidDate(now, "now");
113
+ const path = resolveArtifactRef(repoRoot, ref);
114
+ const parsed = readManifest(path);
115
+ if (!parsed.ok)
116
+ throw new Error(parsed.reason);
117
+ const manifest = {
118
+ ...parsed.manifest,
119
+ released_at: now.toISOString(),
120
+ released_by: input.actor,
121
+ };
122
+ atomicWriteManifest(path, manifest);
123
+ return manifest;
124
+ }
125
+ export function cleanArtifacts(repoRoot, opts = {}) {
126
+ const now = opts.now ?? new Date();
127
+ const freshnessSeconds = opts.freshnessSeconds ?? 600;
128
+ const rows = inventoryArtifacts(repoRoot, { now, freshnessSeconds });
129
+ if (!opts.yes)
130
+ return rows;
131
+ return rows.map((entry) => {
132
+ if (entry.classification !== "managed-expired")
133
+ return entry;
134
+ // Reclassify immediately before removal. A renewal, release-state change,
135
+ // heartbeat, symlink swap, or tracked file added since inventory must win.
136
+ const current = classifyArtifactPath(repoRoot, entry.path, now, freshnessSeconds);
137
+ if (current.classification !== "managed-expired")
138
+ return current;
139
+ try {
140
+ const top = lstatSync(current.path);
141
+ if (!top.isDirectory() || top.isSymbolicLink()) {
142
+ return {
143
+ ...current,
144
+ classification: "unknown",
145
+ reason: "entry changed before deletion",
146
+ action: "keep",
147
+ };
148
+ }
149
+ rmSync(current.path, { recursive: true, force: false });
150
+ return { ...current, action: "deleted" };
151
+ }
152
+ catch (error) {
153
+ return {
154
+ ...current,
155
+ classification: "unknown",
156
+ reason: errorMessage("entry changed or could not be deleted", error),
157
+ action: "keep",
158
+ };
159
+ }
160
+ });
161
+ }
162
+ export function resolveArtifactRef(repoRoot, ref) {
163
+ const root = artifactsRoot(repoRoot);
164
+ const candidate = isAbsolute(ref) ? resolve(ref) : resolve(root, ref);
165
+ if (candidate === root || !candidate.startsWith(`${root}${sep}`) || dirname(candidate) !== root) {
166
+ // A bare artifact id is the only non-path lookup. It must match exactly,
167
+ // never by prefix, so two UUIDs cannot make a command ambiguous.
168
+ const matches = inventoryArtifacts(repoRoot)
169
+ .filter((entry) => entry.artifact_id === ref)
170
+ .map((entry) => entry.path);
171
+ if (matches.length === 1)
172
+ return matches[0];
173
+ throw new Error(`artifact "${ref}" was not found`);
174
+ }
175
+ if (!existsSync(candidate)) {
176
+ const matches = inventoryArtifacts(repoRoot)
177
+ .filter((entry) => entry.artifact_id === ref)
178
+ .map((entry) => entry.path);
179
+ if (matches.length === 1)
180
+ return matches[0];
181
+ throw new Error(`artifact "${ref}" was not found`);
182
+ }
183
+ return candidate;
184
+ }
185
+ function classifyArtifactPath(repoRoot, path, now, freshnessSeconds) {
186
+ const name = basename(path);
187
+ let st;
188
+ try {
189
+ st = lstatSync(path);
190
+ }
191
+ catch (error) {
192
+ return rowFor(path, name, repoRoot, "unknown", errorMessage("cannot inspect entry", error));
193
+ }
194
+ if (st.isSymbolicLink()) {
195
+ return rowFor(path, name, repoRoot, "symlink", "symlinks are never traversed or deleted");
196
+ }
197
+ if (!st.isDirectory()) {
198
+ return rowFor(path, name, repoRoot, "unmanaged", "workspace entries must be directories");
199
+ }
200
+ const parsed = readManifest(path);
201
+ if (!parsed.ok) {
202
+ const classification = existsSync(join(path, ARTIFACT_MANIFEST))
203
+ ? "invalid-manifest"
204
+ : "unmanaged";
205
+ return rowFor(path, name, repoRoot, classification, parsed.reason);
206
+ }
207
+ const manifest = parsed.manifest;
208
+ const bytes = safeTreeSize(path);
209
+ const base = rowFor(path, name, repoRoot, "managed-current", "retention has not expired", bytes);
210
+ Object.assign(base, {
211
+ artifact_id: manifest.artifact_id,
212
+ slug: manifest.slug,
213
+ created_at: manifest.created_at,
214
+ expires_at: manifest.retention.expires_at,
215
+ owner_instance_id: manifest.created_by?.instance_id ?? null,
216
+ });
217
+ if (base.bytes === null) {
218
+ return {
219
+ ...base,
220
+ classification: "unknown",
221
+ reason: "one or more artifact paths are unreadable",
222
+ action: "keep",
223
+ };
224
+ }
225
+ if (containsTrackedPath(repoRoot, path)) {
226
+ return {
227
+ ...base,
228
+ classification: "managed-tracked",
229
+ reason: "Git tracks one or more paths inside this artifact",
230
+ action: "keep",
231
+ };
232
+ }
233
+ if (!manifest.released_at && manifest.created_by?.instance_id) {
234
+ const live = ownerLiveness(repoRoot, manifest.created_by.instance_id, now, freshnessSeconds);
235
+ if (live === "live") {
236
+ return {
237
+ ...base,
238
+ classification: "managed-active",
239
+ reason: `owner ${manifest.created_by.instance_id} has a fresh heartbeat`,
240
+ action: "keep",
241
+ };
242
+ }
243
+ if (live === "unknown") {
244
+ return {
245
+ ...base,
246
+ classification: "unknown",
247
+ reason: `owner ${manifest.created_by.instance_id} heartbeat is unreadable`,
248
+ action: "keep",
249
+ };
250
+ }
251
+ }
252
+ if (Date.parse(manifest.retention.expires_at) > now.getTime())
253
+ return base;
254
+ return {
255
+ ...base,
256
+ classification: "managed-expired",
257
+ reason: `retention expired at ${manifest.retention.expires_at}`,
258
+ action: "would-delete",
259
+ };
260
+ }
261
+ function readManifest(path) {
262
+ const manifestPath = join(path, ARTIFACT_MANIFEST);
263
+ if (!existsSync(manifestPath)) {
264
+ return { ok: false, reason: `missing ${ARTIFACT_MANIFEST}` };
265
+ }
266
+ let value;
267
+ try {
268
+ value = JSON.parse(readFileSync(manifestPath, "utf8"));
269
+ }
270
+ catch (error) {
271
+ return { ok: false, reason: errorMessage("manifest is unreadable", error) };
272
+ }
273
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
274
+ return { ok: false, reason: "manifest must be a JSON object" };
275
+ }
276
+ const m = value;
277
+ if (m.schema_version !== ARTIFACT_SCHEMA_VERSION) {
278
+ return { ok: false, reason: `unsupported schema_version ${String(m.schema_version)}` };
279
+ }
280
+ if (!isSafeId(m.artifact_id))
281
+ return { ok: false, reason: "invalid artifact_id" };
282
+ if (typeof m.slug !== "string" || !m.slug || normalizeSlug(m.slug) !== m.slug) {
283
+ return { ok: false, reason: "invalid slug" };
284
+ }
285
+ if (typeof m.purpose !== "string" || !m.purpose.trim()) {
286
+ return { ok: false, reason: "invalid purpose" };
287
+ }
288
+ if (!validIso(m.created_at))
289
+ return { ok: false, reason: "invalid created_at" };
290
+ if (!m.retention || typeof m.retention !== "object" || !validIso(m.retention.expires_at)) {
291
+ return { ok: false, reason: "invalid retention.expires_at" };
292
+ }
293
+ if (m.released_at !== undefined && !validIso(m.released_at)) {
294
+ return { ok: false, reason: "invalid released_at" };
295
+ }
296
+ if (m.created_by !== undefined && !validActor(m.created_by)) {
297
+ return { ok: false, reason: "invalid created_by" };
298
+ }
299
+ if (m.released_by !== undefined && !validActor(m.released_by)) {
300
+ return { ok: false, reason: "invalid released_by" };
301
+ }
302
+ return { ok: true, manifest: m };
303
+ }
304
+ function atomicWriteManifest(path, manifest) {
305
+ const target = join(path, ARTIFACT_MANIFEST);
306
+ const tmp = `${target}.tmp.${process.pid}.${randomUUID().slice(0, 8)}`;
307
+ writeFileSync(tmp, `${JSON.stringify(manifest, null, 2)}\n`, {
308
+ encoding: "utf8",
309
+ mode: 0o600,
310
+ });
311
+ renameSync(tmp, target);
312
+ }
313
+ function ownerLiveness(repoRoot, instanceId, now, freshnessSeconds) {
314
+ const path = join(repoRoot, ".harnery", "active", `${instanceId}.json`);
315
+ if (!existsSync(path))
316
+ return "stale";
317
+ try {
318
+ const hb = JSON.parse(readFileSync(path, "utf8"));
319
+ if (typeof hb.last_heartbeat !== "string")
320
+ return "unknown";
321
+ const ts = Date.parse(hb.last_heartbeat);
322
+ if (!Number.isFinite(ts))
323
+ return "unknown";
324
+ return now.getTime() - ts <= freshnessSeconds * 1000 ? "live" : "stale";
325
+ }
326
+ catch {
327
+ return "unknown";
328
+ }
329
+ }
330
+ function containsTrackedPath(repoRoot, path) {
331
+ const rel = relative(repoRoot, path);
332
+ if (rel.startsWith("..") || isAbsolute(rel))
333
+ return true;
334
+ const result = spawnSync("git", ["ls-files", "-z", "--", rel], {
335
+ cwd: repoRoot,
336
+ encoding: "utf8",
337
+ });
338
+ // If Git itself cannot answer, fail closed.
339
+ return result.status !== 0 || result.stdout.length > 0;
340
+ }
341
+ function safeTreeSize(path) {
342
+ try {
343
+ const st = lstatSync(path);
344
+ if (st.isSymbolicLink())
345
+ return st.size;
346
+ if (st.isFile())
347
+ return st.size;
348
+ if (!st.isDirectory())
349
+ return 0;
350
+ let total = st.size;
351
+ for (const child of readdirSync(path)) {
352
+ const size = safeTreeSize(join(path, child));
353
+ if (size === null)
354
+ return null;
355
+ total += size;
356
+ }
357
+ return total;
358
+ }
359
+ catch {
360
+ return null;
361
+ }
362
+ }
363
+ function rowFor(path, name, repoRoot, classification, reason, bytes = safeTreeSize(path)) {
364
+ return {
365
+ name,
366
+ path,
367
+ relative_path: relative(repoRoot, path),
368
+ classification,
369
+ reason,
370
+ action: classification === "managed-expired" ? "would-delete" : "keep",
371
+ bytes,
372
+ artifact_id: null,
373
+ slug: null,
374
+ created_at: null,
375
+ expires_at: null,
376
+ owner_instance_id: null,
377
+ };
378
+ }
379
+ function normalizeSlug(value) {
380
+ // Collapsing every non-alphanumeric run to a single "-" leaves no two
381
+ // adjacent dashes, so trimming the edges needs fixed-length patterns rather
382
+ // than "-+", whose backtracking is polynomial on a long run of dashes.
383
+ const collapsed = value
384
+ .trim()
385
+ .toLowerCase()
386
+ .replace(/[^a-z0-9]+/g, "-");
387
+ return collapsed.replace(/^-/, "").replace(/-$/, "").slice(0, 64);
388
+ }
389
+ function positiveDays(value) {
390
+ if (!Number.isInteger(value) || value <= 0 || value > 3650) {
391
+ throw new Error("retention days must be between 1 and 3650");
392
+ }
393
+ return value;
394
+ }
395
+ function addDays(date, days) {
396
+ return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
397
+ }
398
+ function isSafeId(value) {
399
+ return (typeof value === "string" &&
400
+ value.length >= 8 &&
401
+ value.length <= 128 &&
402
+ /^[A-Za-z0-9_-]+$/.test(value));
403
+ }
404
+ function validActor(value) {
405
+ if (!value || typeof value !== "object" || Array.isArray(value))
406
+ return false;
407
+ const actor = value;
408
+ return (isSafeId(actor.instance_id) &&
409
+ (actor.session_id === undefined || isSafeId(actor.session_id)) &&
410
+ (actor.name === undefined || (typeof actor.name === "string" && actor.name.length <= 128)));
411
+ }
412
+ function validIso(value) {
413
+ return typeof value === "string" && Number.isFinite(Date.parse(value));
414
+ }
415
+ function assertValidDate(value, label) {
416
+ if (!Number.isFinite(value.getTime()))
417
+ throw new Error(`${label} must be a valid date`);
418
+ }
419
+ function errorMessage(prefix, error) {
420
+ return `${prefix}: ${error instanceof Error ? error.message : String(error)}`;
421
+ }
@@ -8,8 +8,9 @@
8
8
  *
9
9
  * Fields owned here: `binName` (host CLI name for agent-facing strings),
10
10
  * `hooksSetupHint`, `tools`, `workflow`, `skills`, `presence`, plus the tunable
11
- * `coord` (heartbeat freshness), `backup` (restic repo/password/prune policy),
12
- * and `sync` (rclone remote/prefix) sections. The `files` deny/override section
11
+ * `coord` (heartbeat freshness), `artifacts` (working-file retention),
12
+ * `backup` (restic repo/password/prune policy), and `sync` (rclone
13
+ * remote/prefix) sections. The `files` deny/override section
13
14
  * is parsed separately by `web/lib/files.ts`.
14
15
  *
15
16
  * Env vars and CLI flags override any config value per invocation (each accessor
@@ -91,6 +92,12 @@ export declare function presenceRelayUrl(coordRoot?: string | null): string | nu
91
92
  * `coordRoot` is resolved via `findCoordRoot()` when not passed.
92
93
  */
93
94
  export declare function coordFreshnessSeconds(coordRoot?: string | null): number;
95
+ /**
96
+ * Default retention for a newly-created working artifact. Precedence:
97
+ * `HARNERY_ARTIFACT_RETENTION_DAYS` -> project/user config
98
+ * `artifacts.default_retention_days` -> 3 days.
99
+ */
100
+ export declare function artifactDefaultRetentionDays(coordRoot?: string | null): number;
94
101
  /** Resolved `harn backup` defaults (restic repo/password + prune policy). */
95
102
  export interface BackupConfig {
96
103
  repo: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAQH,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,yFAAyF;AACzF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAiE1C,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqCvD;AAwFD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAShE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK9E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAOrE;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAO3E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAOlE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAWzE;AAQD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CASvE;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,CAmBpE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS3C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,SAAS,CAAC;AAEvC,yFAAyF;AACzF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAsE1C,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqCvD;AAwFD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAShE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK9E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAOrE;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAO3E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAOlE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAWzE;AAQD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CASvE;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAe9E;AAED,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,CAmBpE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS3C"}
@@ -8,8 +8,9 @@
8
8
  *
9
9
  * Fields owned here: `binName` (host CLI name for agent-facing strings),
10
10
  * `hooksSetupHint`, `tools`, `workflow`, `skills`, `presence`, plus the tunable
11
- * `coord` (heartbeat freshness), `backup` (restic repo/password/prune policy),
12
- * and `sync` (rclone remote/prefix) sections. The `files` deny/override section
11
+ * `coord` (heartbeat freshness), `artifacts` (working-file retention),
12
+ * `backup` (restic repo/password/prune policy), and `sync` (rclone
13
+ * remote/prefix) sections. The `files` deny/override section
13
14
  * is parsed separately by `web/lib/files.ts`.
14
15
  *
15
16
  * Env vars and CLI flags override any config value per invocation (each accessor
@@ -294,6 +295,29 @@ export function coordFreshnessSeconds(coordRoot) {
294
295
  return posIntOr(readConfig(root).coord?.freshness_seconds, DEFAULT_FRESHNESS_SECS);
295
296
  return DEFAULT_FRESHNESS_SECS;
296
297
  }
298
+ /**
299
+ * Default retention for a newly-created working artifact. Precedence:
300
+ * `HARNERY_ARTIFACT_RETENTION_DAYS` -> project/user config
301
+ * `artifacts.default_retention_days` -> 3 days.
302
+ */
303
+ export function artifactDefaultRetentionDays(coordRoot) {
304
+ const env = coordEnv("ARTIFACT_RETENTION_DAYS");
305
+ if (env !== undefined) {
306
+ const n = Number(env);
307
+ if (Number.isFinite(n) && n > 0 && n <= 3650)
308
+ return n;
309
+ }
310
+ const root = coordRoot ?? findCoordRoot();
311
+ if (!root)
312
+ return 3;
313
+ const configured = readConfig(root).artifacts?.default_retention_days;
314
+ return typeof configured === "number" &&
315
+ Number.isFinite(configured) &&
316
+ configured > 0 &&
317
+ configured <= 3650
318
+ ? configured
319
+ : 3;
320
+ }
297
321
  /**
298
322
  * `harn backup` (restic) defaults. Per field, precedence is env → config → built-in:
299
323
  * repo: `HARNERY_RESTIC_REPO` → `backup.repo` → `~/.cache/harnery/restic-repo`
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Context continuity: durable, structured state around native harness
3
- * compaction. Harnery does not decide when a harness compacts. It records
4
- * context telemetry when the harness exposes it, checkpoints external work
2
+ * Context continuity: durable, structured state around native adapter
3
+ * compaction. Harnery does not decide when a adapter compacts. It records
4
+ * context telemetry when the adapter exposes it, checkpoints external work
5
5
  * state before compaction, and renders a verified recovery briefing after it.
6
6
  */
7
- import type { Harness } from "../hooks/events/schema.js";
7
+ import type { Adapter } from "../hooks/events/schema.js";
8
8
  export declare const CONTEXT_SCHEMA_VERSION: 1;
9
9
  export declare const MAX_CAPSULE_BYTES: number;
10
10
  export type ContextSampleSource = "hook" | "native_event" | "result" | "transcript" | "estimate";
@@ -13,7 +13,7 @@ export type ContextPhase = "observing" | "checkpointed" | "recovered" | "degrade
13
13
  export type CheckpointReason = "manual" | "pressure" | "pre_compact" | "session_end";
14
14
  export interface ContextSample {
15
15
  session_id: string;
16
- harness: Harness;
16
+ adapter: Adapter;
17
17
  model?: string;
18
18
  used_tokens?: number;
19
19
  window_tokens?: number;
@@ -52,7 +52,7 @@ export interface ContinuityCapsule {
52
52
  session: {
53
53
  session_id: string;
54
54
  instance_id: string;
55
- harness: Harness;
55
+ adapter: Adapter;
56
56
  model?: string;
57
57
  };
58
58
  context?: ContextSample;
@@ -69,7 +69,7 @@ export interface ContinuityCapsule {
69
69
  }
70
70
  export interface ExtractContextSampleOptions {
71
71
  sessionId: string;
72
- harness: Harness;
72
+ adapter: Adapter;
73
73
  model?: string;
74
74
  source?: ContextSampleSource;
75
75
  confidence?: ContextSampleConfidence;
@@ -78,7 +78,7 @@ export interface ExtractContextSampleOptions {
78
78
  export interface CheckpointContextInput {
79
79
  sessionId: string;
80
80
  instanceId: string;
81
- harness: Harness;
81
+ adapter: Adapter;
82
82
  cwd: string;
83
83
  reason: CheckpointReason;
84
84
  model?: string;
@@ -101,7 +101,7 @@ export interface PreparedContextRecovery {
101
101
  capsule: ContinuityCapsule;
102
102
  briefing: string;
103
103
  }
104
- /** Parse the context-window shapes exposed by current harness hook/status data. */
104
+ /** Parse the context-window shapes exposed by current adapter hook/status data. */
105
105
  export declare function extractContextSample(payload: Record<string, unknown>, options: ExtractContextSampleOptions): ContextSample | null;
106
106
  /** Persist a latest context sample. Identical measurements are a no-op. */
107
107
  export declare function recordContextSample(coordRoot: string, instanceId: string, sample: ContextSample): {
@@ -114,18 +114,18 @@ export declare function recordContextSample(coordRoot: string, instanceId: strin
114
114
  * create a new generation.
115
115
  */
116
116
  export declare function checkpointContext(coordRoot: string, input: CheckpointContextInput): CheckpointContextResult;
117
- /** Prepare a briefing without claiming that a harness has accepted it yet. */
117
+ /** Prepare a briefing without claiming that a adapter has accepted it yet. */
118
118
  export declare function prepareContextRecovery(coordRoot: string, input: {
119
119
  sessionId: string;
120
120
  instanceId: string;
121
121
  cwd: string;
122
122
  }): PreparedContextRecovery | null;
123
- /** Advance continuity only after the harness context channel accepted the briefing. */
123
+ /** Advance continuity only after the adapter context channel accepted the briefing. */
124
124
  export declare function completeContextRecovery(coordRoot: string, input: {
125
125
  sessionId: string;
126
126
  instanceId: string;
127
127
  }): ContextContinuityState;
128
- /** Record that the harness, rather than Harnery, reported compaction complete. */
128
+ /** Record that the adapter, rather than Harnery, reported compaction complete. */
129
129
  export declare function markContextCompactionCompleted(coordRoot: string, input: {
130
130
  sessionId: string;
131
131
  instanceId: string;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Context continuity: durable, structured state around native harness
3
- * compaction. Harnery does not decide when a harness compacts. It records
4
- * context telemetry when the harness exposes it, checkpoints external work
2
+ * Context continuity: durable, structured state around native adapter
3
+ * compaction. Harnery does not decide when a adapter compacts. It records
4
+ * context telemetry when the adapter exposes it, checkpoints external work
5
5
  * state before compaction, and renders a verified recovery briefing after it.
6
6
  */
7
7
  import { spawnSync } from "node:child_process";
@@ -12,7 +12,7 @@ export const CONTEXT_SCHEMA_VERSION = 1;
12
12
  export const MAX_CAPSULE_BYTES = 32 * 1024;
13
13
  const MAX_SNAPSHOT_PATHS = 15;
14
14
  const MAX_SNAPSHOT_PATH_CHARS = 500;
15
- /** Parse the context-window shapes exposed by current harness hook/status data. */
15
+ /** Parse the context-window shapes exposed by current adapter hook/status data. */
16
16
  export function extractContextSample(payload, options) {
17
17
  const contextValue = payload.context_window;
18
18
  const context = record(contextValue);
@@ -48,7 +48,7 @@ export function extractContextSample(payload, options) {
48
48
  string(record(payload.model)?.display_name);
49
49
  return {
50
50
  session_id: options.sessionId,
51
- harness: options.harness,
51
+ adapter: options.adapter,
52
52
  model,
53
53
  used_tokens: usedTokens,
54
54
  window_tokens: windowTokens,
@@ -105,7 +105,7 @@ export function checkpointContext(coordRoot, input) {
105
105
  session: {
106
106
  session_id: input.sessionId,
107
107
  instance_id: input.instanceId,
108
- harness: input.harness,
108
+ adapter: input.adapter,
109
109
  model: input.model ?? current.latest_context?.model ?? heartbeat?.model,
110
110
  },
111
111
  context: current.latest_context,
@@ -129,7 +129,7 @@ export function checkpointContext(coordRoot, input) {
129
129
  writeState(coordRoot, next);
130
130
  return { capsule, path: absolutePath, state: next, reused: false };
131
131
  }
132
- /** Prepare a briefing without claiming that a harness has accepted it yet. */
132
+ /** Prepare a briefing without claiming that a adapter has accepted it yet. */
133
133
  export function prepareContextRecovery(coordRoot, input) {
134
134
  const now = new Date().toISOString();
135
135
  const current = readContextState(coordRoot, input.sessionId) ??
@@ -150,7 +150,7 @@ export function prepareContextRecovery(coordRoot, input) {
150
150
  const briefing = renderRecoveryBriefing(capsule, liveRepo);
151
151
  return { state: current, capsule, briefing };
152
152
  }
153
- /** Advance continuity only after the harness context channel accepted the briefing. */
153
+ /** Advance continuity only after the adapter context channel accepted the briefing. */
154
154
  export function completeContextRecovery(coordRoot, input) {
155
155
  const now = new Date().toISOString();
156
156
  const current = readContextState(coordRoot, input.sessionId) ??
@@ -166,7 +166,7 @@ export function completeContextRecovery(coordRoot, input) {
166
166
  writeState(coordRoot, recovered);
167
167
  return recovered;
168
168
  }
169
- /** Record that the harness, rather than Harnery, reported compaction complete. */
169
+ /** Record that the adapter, rather than Harnery, reported compaction complete. */
170
170
  export function markContextCompactionCompleted(coordRoot, input) {
171
171
  const now = input.observedAt ?? new Date().toISOString();
172
172
  const current = readContextState(coordRoot, input.sessionId) ??
@@ -344,7 +344,7 @@ function git(cwd, args) {
344
344
  function sameMeasurement(a, b) {
345
345
  if (!a)
346
346
  return false;
347
- return (a.harness === b.harness &&
347
+ return (a.adapter === b.adapter &&
348
348
  a.model === b.model &&
349
349
  a.used_tokens === b.used_tokens &&
350
350
  a.window_tokens === b.window_tokens &&