harnery 0.35.0 → 0.36.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 (616) hide show
  1. package/dist/commander.d.ts +30 -5
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +124 -96
  4. package/dist/commands/agents.d.ts +23 -3
  5. package/dist/commands/agents.d.ts.map +1 -1
  6. package/dist/commands/agents.js +379 -198
  7. package/dist/commands/backup.d.ts.map +1 -1
  8. package/dist/commands/backup.js +10 -10
  9. package/dist/commands/browse-session.d.ts.map +1 -1
  10. package/dist/commands/browse-session.js +12 -0
  11. package/dist/commands/browse.d.ts +1 -1
  12. package/dist/commands/browse.d.ts.map +1 -1
  13. package/dist/commands/browse.js +5 -4
  14. package/dist/commands/conversations.d.ts +10 -0
  15. package/dist/commands/conversations.d.ts.map +1 -0
  16. package/dist/commands/conversations.js +201 -0
  17. package/dist/commands/deinit.d.ts.map +1 -1
  18. package/dist/commands/deinit.js +5 -0
  19. package/dist/commands/docs.d.ts.map +1 -1
  20. package/dist/commands/docs.js +13 -2
  21. package/dist/commands/doctor.d.ts +5 -0
  22. package/dist/commands/doctor.d.ts.map +1 -1
  23. package/dist/commands/doctor.js +51 -7
  24. package/dist/commands/fetch.js +6 -5
  25. package/dist/commands/files.d.ts +22 -0
  26. package/dist/commands/files.d.ts.map +1 -0
  27. package/dist/commands/files.js +113 -0
  28. package/dist/commands/governor.js +14 -12
  29. package/dist/commands/inbox.d.ts +5 -0
  30. package/dist/commands/inbox.d.ts.map +1 -0
  31. package/dist/commands/inbox.js +57 -0
  32. package/dist/commands/init.d.ts +4 -5
  33. package/dist/commands/init.d.ts.map +1 -1
  34. package/dist/commands/init.js +63 -13
  35. package/dist/commands/ledger-v3.d.ts.map +1 -1
  36. package/dist/commands/ledger-v3.js +347 -1
  37. package/dist/commands/logs.d.ts +4 -0
  38. package/dist/commands/logs.d.ts.map +1 -0
  39. package/dist/commands/logs.js +169 -0
  40. package/dist/commands/messages.d.ts +5 -0
  41. package/dist/commands/messages.d.ts.map +1 -0
  42. package/dist/commands/messages.js +45 -0
  43. package/dist/commands/outline.d.ts +1 -1
  44. package/dist/commands/outline.d.ts.map +1 -1
  45. package/dist/commands/outline.js +2 -2
  46. package/dist/commands/read.d.ts +1 -1
  47. package/dist/commands/read.d.ts.map +1 -1
  48. package/dist/commands/read.js +2 -2
  49. package/dist/commands/semantic.d.ts.map +1 -1
  50. package/dist/commands/semantic.js +54 -2
  51. package/dist/commands/storage.d.ts +4 -0
  52. package/dist/commands/storage.d.ts.map +1 -0
  53. package/dist/commands/storage.js +238 -0
  54. package/dist/commands/tunnel.d.ts +5 -1
  55. package/dist/commands/tunnel.d.ts.map +1 -1
  56. package/dist/commands/tunnel.js +44 -31
  57. package/dist/commands/web.d.ts +3 -0
  58. package/dist/commands/web.d.ts.map +1 -1
  59. package/dist/commands/web.js +67 -7
  60. package/dist/commands/work.js +3 -3
  61. package/dist/commands/workflow.js +13 -13
  62. package/dist/core/adapters/profiles.d.ts +1 -1
  63. package/dist/core/agents/cli.js +209 -39
  64. package/dist/core/agents/live-authority-v3.d.ts +47 -1
  65. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  66. package/dist/core/agents/live-authority-v3.js +244 -10
  67. package/dist/core/agents/live-lifecycle-v3.js +6 -1
  68. package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
  69. package/dist/core/agents/live-observation-v3.js +6 -1
  70. package/dist/core/agents/render/prompt-context.d.ts +9 -3
  71. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  72. package/dist/core/agents/render/prompt-context.js +24 -7
  73. package/dist/core/agents/rules/stop-hook.d.ts +2 -0
  74. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  75. package/dist/core/agents/rules/stop-hook.js +94 -13
  76. package/dist/core/agents/rules/verdict.d.ts +1 -0
  77. package/dist/core/agents/rules/verdict.d.ts.map +1 -1
  78. package/dist/core/agents/session-events.d.ts.map +1 -1
  79. package/dist/core/agents/session-events.js +4 -0
  80. package/dist/core/agents/session-finalization-state-v3.js +1 -1
  81. package/dist/core/agents/session-finalizer-v3.js +5 -1
  82. package/dist/core/agents/state/activity-log.d.ts +3 -0
  83. package/dist/core/agents/state/activity-log.d.ts.map +1 -1
  84. package/dist/core/agents/state/activity-log.js +6 -3
  85. package/dist/core/agents/state/heartbeat-writer.d.ts +6 -0
  86. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  87. package/dist/core/agents/state/heartbeat-writer.js +18 -0
  88. package/dist/core/agents/state/live-coordination-view.d.ts +5 -7
  89. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  90. package/dist/core/agents/state/live-coordination-view.js +15 -90
  91. package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
  92. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
  93. package/dist/core/agents/state/live-coordination-writer.js +92 -0
  94. package/dist/core/artifacts/index.d.ts +21 -0
  95. package/dist/core/artifacts/index.d.ts.map +1 -1
  96. package/dist/core/artifacts/index.js +46 -1
  97. package/dist/core/config.d.ts +62 -4
  98. package/dist/core/config.d.ts.map +1 -1
  99. package/dist/core/config.js +98 -4
  100. package/dist/core/conversations/archive.d.ts +49 -0
  101. package/dist/core/conversations/archive.d.ts.map +1 -0
  102. package/dist/core/conversations/archive.js +136 -0
  103. package/dist/core/conversations/catalog.d.ts +10 -0
  104. package/dist/core/conversations/catalog.d.ts.map +1 -0
  105. package/dist/core/conversations/catalog.js +72 -0
  106. package/dist/core/conversations/context-pack.d.ts +6 -0
  107. package/dist/core/conversations/context-pack.d.ts.map +1 -0
  108. package/dist/core/conversations/context-pack.js +60 -0
  109. package/dist/core/conversations/contract.d.ts +155 -0
  110. package/dist/core/conversations/contract.d.ts.map +1 -0
  111. package/dist/core/conversations/contract.js +1 -0
  112. package/dist/core/conversations/evaluation.d.ts +16 -0
  113. package/dist/core/conversations/evaluation.d.ts.map +1 -0
  114. package/dist/core/conversations/evaluation.js +9 -0
  115. package/dist/core/conversations/index.d.ts +10 -0
  116. package/dist/core/conversations/index.d.ts.map +1 -0
  117. package/dist/core/conversations/index.js +9 -0
  118. package/dist/core/conversations/lifecycle.d.ts +28 -0
  119. package/dist/core/conversations/lifecycle.d.ts.map +1 -0
  120. package/dist/core/conversations/lifecycle.js +29 -0
  121. package/dist/core/conversations/normalize.d.ts +14 -0
  122. package/dist/core/conversations/normalize.d.ts.map +1 -0
  123. package/dist/core/conversations/normalize.js +82 -0
  124. package/dist/core/conversations/query.d.ts +8 -0
  125. package/dist/core/conversations/query.d.ts.map +1 -0
  126. package/dist/core/conversations/query.js +280 -0
  127. package/dist/core/conversations/search-index.d.ts +9 -0
  128. package/dist/core/conversations/search-index.d.ts.map +1 -0
  129. package/dist/core/conversations/search-index.js +29 -0
  130. package/dist/core/events/legacy-storage/canary.d.ts +18 -0
  131. package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
  132. package/dist/core/events/legacy-storage/canary.js +150 -0
  133. package/dist/core/events/legacy-storage/fence.d.ts +15 -0
  134. package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
  135. package/dist/core/events/legacy-storage/fence.js +115 -0
  136. package/dist/core/events/legacy-storage/index.d.ts +6 -0
  137. package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
  138. package/dist/core/events/legacy-storage/index.js +5 -0
  139. package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
  140. package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
  141. package/dist/core/events/legacy-storage/inventory.js +40 -0
  142. package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
  143. package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
  144. package/dist/core/events/legacy-storage/manifest.js +108 -0
  145. package/dist/core/events/legacy-storage/reader.d.ts +15 -0
  146. package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
  147. package/dist/core/events/legacy-storage/reader.js +154 -0
  148. package/dist/core/events/v3/authority-outbox.d.ts +7 -2
  149. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  150. package/dist/core/events/v3/authority-outbox.js +16 -3
  151. package/dist/core/events/v3/base-contract.d.ts +81 -41
  152. package/dist/core/events/v3/base-contract.d.ts.map +1 -1
  153. package/dist/core/events/v3/base-contract.js +17 -7
  154. package/dist/core/events/v3/bootstrap.d.ts +39 -0
  155. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  156. package/dist/core/events/v3/bootstrap.js +167 -3
  157. package/dist/core/events/v3/capabilities.js +3 -3
  158. package/dist/core/events/v3/control-witness.d.ts +44 -0
  159. package/dist/core/events/v3/control-witness.d.ts.map +1 -0
  160. package/dist/core/events/v3/control-witness.js +233 -0
  161. package/dist/core/events/v3/control-writer.d.ts +4 -0
  162. package/dist/core/events/v3/control-writer.d.ts.map +1 -0
  163. package/dist/core/events/v3/control-writer.js +16 -0
  164. package/dist/core/events/v3/control.d.ts +8 -2
  165. package/dist/core/events/v3/control.d.ts.map +1 -1
  166. package/dist/core/events/v3/control.js +46 -18
  167. package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
  168. package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
  169. package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
  170. package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
  171. package/dist/core/events/v3/coordination-view.js +16 -1
  172. package/dist/core/events/v3/generated.d.ts +1 -1
  173. package/dist/core/events/v3/generated.js +1 -1
  174. package/dist/core/events/v3/index.d.ts +4 -2
  175. package/dist/core/events/v3/index.d.ts.map +1 -1
  176. package/dist/core/events/v3/index.js +3 -1
  177. package/dist/core/events/v3/live-route-observer.d.ts +31 -0
  178. package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
  179. package/dist/core/events/v3/live-route-observer.js +58 -0
  180. package/dist/core/events/v3/live-routing.d.ts +13 -21
  181. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  182. package/dist/core/events/v3/live-routing.js +45 -41
  183. package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
  184. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  185. package/dist/core/events/v3/producers/coordination-recorder.js +76 -10
  186. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
  187. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
  188. package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
  189. package/dist/core/events/v3/producers/hook-base.js +1 -1
  190. package/dist/core/events/v3/producers/intake.d.ts +7 -0
  191. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  192. package/dist/core/events/v3/producers/intake.js +25 -2
  193. package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
  194. package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
  195. package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
  196. package/dist/core/events/v3/producers/recorder.d.ts +55 -1
  197. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  198. package/dist/core/events/v3/producers/recorder.js +353 -24
  199. package/dist/core/events/v3/reader.d.ts +51 -0
  200. package/dist/core/events/v3/reader.d.ts.map +1 -1
  201. package/dist/core/events/v3/reader.js +181 -1
  202. package/dist/core/events/v3/rotation-config.d.ts +9 -0
  203. package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
  204. package/dist/core/events/v3/rotation-config.js +91 -0
  205. package/dist/core/events/v3/runtime-build.d.ts +11 -0
  206. package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
  207. package/dist/core/events/v3/runtime-build.js +39 -0
  208. package/dist/core/events/v3/runtime-identity.d.ts +5 -0
  209. package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
  210. package/dist/core/events/v3/runtime-identity.js +18 -0
  211. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +6 -5
  212. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
  213. package/dist/core/events/v3/runtime-telemetry-capabilities.js +1 -1
  214. package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
  215. package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
  216. package/dist/core/events/v3/support-storage/classify.js +149 -0
  217. package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
  218. package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
  219. package/dist/core/events/v3/support-storage/eligibility.js +35 -0
  220. package/dist/core/events/v3/support-storage/index.d.ts +10 -0
  221. package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
  222. package/dist/core/events/v3/support-storage/index.js +9 -0
  223. package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
  224. package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
  225. package/dist/core/events/v3/support-storage/inventory.js +94 -0
  226. package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
  227. package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
  228. package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
  229. package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
  230. package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
  231. package/dist/core/events/v3/support-storage/maintenance.js +352 -0
  232. package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
  233. package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
  234. package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
  235. package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
  236. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
  237. package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
  238. package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
  239. package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
  240. package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
  241. package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
  242. package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
  243. package/dist/core/events/v3/support-storage/recovery.js +22 -0
  244. package/dist/core/events/v3/turn-telemetry.d.ts +14 -8
  245. package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
  246. package/dist/core/events/v3/turn-telemetry.js +32 -2
  247. package/dist/core/events/v3/writer.d.ts +13 -1
  248. package/dist/core/events/v3/writer.d.ts.map +1 -1
  249. package/dist/core/events/v3/writer.js +126 -12
  250. package/dist/core/governor/plan-read.d.ts.map +1 -1
  251. package/dist/core/governor/plan-read.js +5 -21
  252. package/dist/core/governor/planning.js +6 -8
  253. package/dist/core/governor/service-read.d.ts +12 -0
  254. package/dist/core/governor/service-read.d.ts.map +1 -1
  255. package/dist/core/governor/service-read.js +266 -2
  256. package/dist/core/governor/service.d.ts +1 -0
  257. package/dist/core/governor/service.d.ts.map +1 -1
  258. package/dist/core/governor/service.js +53 -18
  259. package/dist/core/guard/evidence-v3.d.ts.map +1 -1
  260. package/dist/core/guard/evidence-v3.js +2 -0
  261. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  262. package/dist/core/hooks/adapter/events.js +1 -0
  263. package/dist/core/hooks/adapter/output.d.ts +4 -2
  264. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  265. package/dist/core/hooks/adapter/output.js +13 -5
  266. package/dist/core/hooks/adapter/runtime-telemetry.d.ts +27 -4
  267. package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -1
  268. package/dist/core/hooks/adapter/runtime-telemetry.js +307 -6
  269. package/dist/core/hooks/cli.js +212 -30
  270. package/dist/core/hooks/effects/image-capture.d.ts +1 -1
  271. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  272. package/dist/core/hooks/effects/image-capture.js +4 -2
  273. package/dist/core/hooks/remediation-cap.d.ts +8 -3
  274. package/dist/core/hooks/remediation-cap.d.ts.map +1 -1
  275. package/dist/core/hooks/remediation-cap.js +3 -11
  276. package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
  277. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
  278. package/dist/core/hooks/resolve/coord-root.js +92 -11
  279. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  280. package/dist/core/hooks/resolve/owner.js +5 -0
  281. package/dist/core/hooks/resolve/transcript.d.ts +8 -0
  282. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  283. package/dist/core/hooks/resolve/transcript.js +11 -0
  284. package/dist/core/inbox/contract.d.ts +64 -0
  285. package/dist/core/inbox/contract.d.ts.map +1 -0
  286. package/dist/core/inbox/contract.js +13 -0
  287. package/dist/core/inbox/index.d.ts +5 -0
  288. package/dist/core/inbox/index.d.ts.map +1 -0
  289. package/dist/core/inbox/index.js +4 -0
  290. package/dist/core/inbox/lifecycle.d.ts +22 -0
  291. package/dist/core/inbox/lifecycle.d.ts.map +1 -0
  292. package/dist/core/inbox/lifecycle.js +41 -0
  293. package/dist/core/inbox/service.d.ts +36 -0
  294. package/dist/core/inbox/service.d.ts.map +1 -0
  295. package/dist/core/inbox/service.js +210 -0
  296. package/dist/core/inbox/watcher.d.ts +7 -0
  297. package/dist/core/inbox/watcher.d.ts.map +1 -0
  298. package/dist/core/inbox/watcher.js +26 -0
  299. package/dist/core/presence/codec-digest.d.ts.map +1 -1
  300. package/dist/core/presence/codec-digest.js +14 -3
  301. package/dist/core/presence/relay-client.d.ts +1 -0
  302. package/dist/core/presence/relay-client.d.ts.map +1 -1
  303. package/dist/core/presence/relay-client.js +52 -8
  304. package/dist/core/semantic/adapters.d.ts +11 -8
  305. package/dist/core/semantic/adapters.d.ts.map +1 -1
  306. package/dist/core/semantic/adapters.js +169 -31
  307. package/dist/core/semantic/contract.d.ts +532 -48
  308. package/dist/core/semantic/contract.d.ts.map +1 -1
  309. package/dist/core/semantic/contract.js +104 -3
  310. package/dist/core/semantic/index.d.ts +7 -3
  311. package/dist/core/semantic/index.d.ts.map +1 -1
  312. package/dist/core/semantic/index.js +7 -3
  313. package/dist/core/semantic/once.d.ts +6 -1
  314. package/dist/core/semantic/once.d.ts.map +1 -1
  315. package/dist/core/semantic/once.js +80 -9
  316. package/dist/core/semantic/prompt.d.ts.map +1 -1
  317. package/dist/core/semantic/prompt.js +14 -1
  318. package/dist/core/semantic/review.d.ts +144 -0
  319. package/dist/core/semantic/review.d.ts.map +1 -0
  320. package/dist/core/semantic/review.js +544 -0
  321. package/dist/core/semantic/routes.d.ts +10 -0
  322. package/dist/core/semantic/routes.d.ts.map +1 -0
  323. package/dist/core/semantic/routes.js +21 -0
  324. package/dist/core/semantic/scheduler.d.ts +14 -3
  325. package/dist/core/semantic/scheduler.d.ts.map +1 -1
  326. package/dist/core/semantic/scheduler.js +30 -6
  327. package/dist/core/semantic/service-status.d.ts +20 -0
  328. package/dist/core/semantic/service-status.d.ts.map +1 -1
  329. package/dist/core/semantic/service-status.js +60 -4
  330. package/dist/core/semantic/service.d.ts +1 -0
  331. package/dist/core/semantic/service.d.ts.map +1 -1
  332. package/dist/core/semantic/service.js +104 -15
  333. package/dist/core/semantic/soak.d.ts +75 -0
  334. package/dist/core/semantic/soak.d.ts.map +1 -0
  335. package/dist/core/semantic/soak.js +476 -0
  336. package/dist/core/semantic/storage.d.ts +11 -1
  337. package/dist/core/semantic/storage.d.ts.map +1 -1
  338. package/dist/core/semantic/storage.js +4 -3
  339. package/dist/core/semantic/usage.d.ts +43 -0
  340. package/dist/core/semantic/usage.d.ts.map +1 -0
  341. package/dist/core/semantic/usage.js +193 -0
  342. package/dist/core/semantic/validate.d.ts +3 -1
  343. package/dist/core/semantic/validate.d.ts.map +1 -1
  344. package/dist/core/semantic/validate.js +34 -1
  345. package/dist/core/storage/buffer.d.ts +28 -0
  346. package/dist/core/storage/buffer.d.ts.map +1 -0
  347. package/dist/core/storage/buffer.js +101 -0
  348. package/dist/core/storage/builtins.d.ts +3 -0
  349. package/dist/core/storage/builtins.d.ts.map +1 -0
  350. package/dist/core/storage/builtins.js +683 -0
  351. package/dist/core/storage/catalog.d.ts +19 -0
  352. package/dist/core/storage/catalog.d.ts.map +1 -0
  353. package/dist/core/storage/catalog.js +365 -0
  354. package/dist/core/storage/config.d.ts +16 -0
  355. package/dist/core/storage/config.d.ts.map +1 -0
  356. package/dist/core/storage/config.js +311 -0
  357. package/dist/core/storage/contract.d.ts +275 -0
  358. package/dist/core/storage/contract.d.ts.map +1 -0
  359. package/dist/core/storage/contract.js +3 -0
  360. package/dist/core/storage/durable-history.d.ts +36 -0
  361. package/dist/core/storage/durable-history.d.ts.map +1 -0
  362. package/dist/core/storage/durable-history.js +606 -0
  363. package/dist/core/storage/health.d.ts +4 -0
  364. package/dist/core/storage/health.d.ts.map +1 -0
  365. package/dist/core/storage/health.js +65 -0
  366. package/dist/core/storage/index.d.ts +16 -0
  367. package/dist/core/storage/index.d.ts.map +1 -0
  368. package/dist/core/storage/index.js +15 -0
  369. package/dist/core/storage/inventory.d.ts +25 -0
  370. package/dist/core/storage/inventory.d.ts.map +1 -0
  371. package/dist/core/storage/inventory.js +666 -0
  372. package/dist/core/storage/jsonl.d.ts +52 -0
  373. package/dist/core/storage/jsonl.d.ts.map +1 -0
  374. package/dist/core/storage/jsonl.js +156 -0
  375. package/dist/core/storage/log-retention.d.ts +52 -0
  376. package/dist/core/storage/log-retention.d.ts.map +1 -0
  377. package/dist/core/storage/log-retention.js +419 -0
  378. package/dist/core/storage/logger.d.ts +82 -0
  379. package/dist/core/storage/logger.d.ts.map +1 -0
  380. package/dist/core/storage/logger.js +411 -0
  381. package/dist/core/storage/maintenance-providers.d.ts +26 -0
  382. package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
  383. package/dist/core/storage/maintenance-providers.js +141 -0
  384. package/dist/core/storage/maintenance.d.ts +125 -0
  385. package/dist/core/storage/maintenance.d.ts.map +1 -0
  386. package/dist/core/storage/maintenance.js +609 -0
  387. package/dist/core/storage/metrics.d.ts +60 -0
  388. package/dist/core/storage/metrics.d.ts.map +1 -0
  389. package/dist/core/storage/metrics.js +134 -0
  390. package/dist/core/storage/policy.d.ts +7 -0
  391. package/dist/core/storage/policy.d.ts.map +1 -0
  392. package/dist/core/storage/policy.js +110 -0
  393. package/dist/core/storage/process-log.d.ts +38 -0
  394. package/dist/core/storage/process-log.d.ts.map +1 -0
  395. package/dist/core/storage/process-log.js +165 -0
  396. package/dist/core/storage/query.d.ts +34 -0
  397. package/dist/core/storage/query.d.ts.map +1 -0
  398. package/dist/core/storage/query.js +295 -0
  399. package/dist/core/storage/receipts.d.ts +23 -0
  400. package/dist/core/storage/receipts.d.ts.map +1 -0
  401. package/dist/core/storage/receipts.js +117 -0
  402. package/dist/core/storage/segments.d.ts +84 -0
  403. package/dist/core/storage/segments.d.ts.map +1 -0
  404. package/dist/core/storage/segments.js +542 -0
  405. package/dist/core/storage/sink-graph.d.ts +65 -0
  406. package/dist/core/storage/sink-graph.d.ts.map +1 -0
  407. package/dist/core/storage/sink-graph.js +213 -0
  408. package/dist/core/storage/storm-control.d.ts +23 -0
  409. package/dist/core/storage/storm-control.d.ts.map +1 -0
  410. package/dist/core/storage/storm-control.js +59 -0
  411. package/dist/core/work/state.d.ts.map +1 -1
  412. package/dist/core/work/state.js +10 -14
  413. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  414. package/dist/core/workflow/live-session-v3.js +2 -1
  415. package/dist/index.d.ts +2 -0
  416. package/dist/index.d.ts.map +1 -1
  417. package/dist/index.js +2 -0
  418. package/dist/lazy-commands.d.ts +26 -0
  419. package/dist/lazy-commands.d.ts.map +1 -0
  420. package/dist/lazy-commands.js +210 -0
  421. package/dist/lib/docs-lint.d.ts +2 -0
  422. package/dist/lib/docs-lint.d.ts.map +1 -1
  423. package/dist/lib/docs-lint.js +45 -80
  424. package/dist/lib/docs-metadata-audit.d.ts +3 -0
  425. package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
  426. package/dist/lib/docs-metadata-audit.js +13 -23
  427. package/dist/lib/docs-metadata-sync.d.ts +1 -0
  428. package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
  429. package/dist/lib/docs-metadata-sync.js +28 -10
  430. package/dist/lib/docs-repository-view.d.ts +22 -0
  431. package/dist/lib/docs-repository-view.d.ts.map +1 -0
  432. package/dist/lib/docs-repository-view.js +185 -0
  433. package/dist/lib/http/client.d.ts +11 -5
  434. package/dist/lib/http/client.d.ts.map +1 -1
  435. package/dist/lib/http/client.js +22 -4
  436. package/dist/lib/http/index.d.ts +1 -1
  437. package/dist/lib/http/index.d.ts.map +1 -1
  438. package/dist/lib/http/index.js +1 -1
  439. package/dist/lib/indexer-exclusions.d.ts +27 -0
  440. package/dist/lib/indexer-exclusions.d.ts.map +1 -0
  441. package/dist/lib/indexer-exclusions.js +176 -0
  442. package/dist/lib/instructions/templates.d.ts.map +1 -1
  443. package/dist/lib/instructions/templates.js +5 -0
  444. package/dist/lib/local-file-url.d.ts +9 -0
  445. package/dist/lib/local-file-url.d.ts.map +1 -0
  446. package/dist/lib/local-file-url.js +20 -0
  447. package/dist/lib/web-performance.d.ts +118 -0
  448. package/dist/lib/web-performance.d.ts.map +1 -0
  449. package/dist/lib/web-performance.js +192 -0
  450. package/package.json +29 -2
  451. package/schemas/config.schema.json +58 -0
  452. package/schemas/event-v3.schema.json +324 -112
  453. package/src/commander.ts +462 -95
  454. package/src/commands/agents.ts +517 -190
  455. package/src/commands/backup.ts +18 -14
  456. package/src/commands/browse-session.ts +12 -0
  457. package/src/commands/browse.ts +6 -7
  458. package/src/commands/conversations.ts +279 -0
  459. package/src/commands/deinit.ts +6 -0
  460. package/src/commands/docs.ts +25 -6
  461. package/src/commands/doctor.ts +75 -9
  462. package/src/commands/fetch.ts +7 -6
  463. package/src/commands/files.ts +143 -0
  464. package/src/commands/governor.ts +13 -12
  465. package/src/commands/inbox.ts +61 -0
  466. package/src/commands/init.ts +78 -16
  467. package/src/commands/ledger-v3.ts +421 -1
  468. package/src/commands/logs.ts +224 -0
  469. package/src/commands/messages.ts +61 -0
  470. package/src/commands/outline.ts +6 -2
  471. package/src/commands/read.ts +6 -2
  472. package/src/commands/semantic.ts +66 -1
  473. package/src/commands/storage.ts +310 -0
  474. package/src/commands/tunnel.ts +66 -52
  475. package/src/commands/web.ts +77 -7
  476. package/src/commands/work.ts +3 -3
  477. package/src/commands/workflow.ts +13 -13
  478. package/src/core/agents/cli.ts +259 -53
  479. package/src/core/agents/live-authority-v3.ts +341 -10
  480. package/src/core/agents/live-lifecycle-v3.ts +6 -1
  481. package/src/core/agents/live-observation-v3.ts +6 -1
  482. package/src/core/agents/render/prompt-context.ts +27 -6
  483. package/src/core/agents/rules/stop-hook.ts +107 -16
  484. package/src/core/agents/rules/verdict.ts +1 -0
  485. package/src/core/agents/session-events.ts +4 -0
  486. package/src/core/agents/session-finalization-state-v3.ts +1 -1
  487. package/src/core/agents/session-finalizer-v3.ts +4 -1
  488. package/src/core/agents/state/activity-log.ts +7 -2
  489. package/src/core/agents/state/heartbeat-writer.ts +27 -0
  490. package/src/core/agents/state/live-coordination-view.ts +16 -105
  491. package/src/core/agents/state/live-coordination-writer.ts +141 -0
  492. package/src/core/artifacts/index.ts +64 -1
  493. package/src/core/config.ts +126 -5
  494. package/src/core/conversations/archive.ts +237 -0
  495. package/src/core/conversations/catalog.ts +79 -0
  496. package/src/core/conversations/context-pack.ts +72 -0
  497. package/src/core/conversations/contract.ts +178 -0
  498. package/src/core/conversations/evaluation.ts +30 -0
  499. package/src/core/conversations/index.ts +9 -0
  500. package/src/core/conversations/lifecycle.ts +63 -0
  501. package/src/core/conversations/normalize.ts +105 -0
  502. package/src/core/conversations/query.ts +318 -0
  503. package/src/core/conversations/search-index.ts +48 -0
  504. package/src/core/events/legacy-storage/canary.ts +177 -0
  505. package/src/core/events/legacy-storage/fence.ts +129 -0
  506. package/src/core/events/legacy-storage/index.ts +5 -0
  507. package/src/core/events/legacy-storage/inventory.ts +51 -0
  508. package/src/core/events/legacy-storage/manifest.ts +136 -0
  509. package/src/core/events/legacy-storage/reader.ts +178 -0
  510. package/src/core/events/v3/authority-outbox.ts +22 -1
  511. package/src/core/events/v3/base-contract.ts +17 -7
  512. package/src/core/events/v3/bootstrap.ts +195 -2
  513. package/src/core/events/v3/capabilities.ts +3 -3
  514. package/src/core/events/v3/control-witness.ts +339 -0
  515. package/src/core/events/v3/control-writer.ts +16 -0
  516. package/src/core/events/v3/control.ts +54 -18
  517. package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
  518. package/src/core/events/v3/coordination-view.ts +17 -1
  519. package/src/core/events/v3/generated.ts +1 -1
  520. package/src/core/events/v3/index.ts +5 -2
  521. package/src/core/events/v3/live-route-observer.ts +80 -0
  522. package/src/core/events/v3/live-routing.ts +64 -46
  523. package/src/core/events/v3/producers/coordination-recorder.ts +95 -10
  524. package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
  525. package/src/core/events/v3/producers/hook-base.ts +1 -1
  526. package/src/core/events/v3/producers/intake.ts +30 -2
  527. package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
  528. package/src/core/events/v3/producers/recorder.ts +571 -33
  529. package/src/core/events/v3/reader.ts +243 -2
  530. package/src/core/events/v3/rotation-config.ts +98 -0
  531. package/src/core/events/v3/runtime-build.ts +41 -0
  532. package/src/core/events/v3/runtime-identity.ts +16 -0
  533. package/src/core/events/v3/runtime-telemetry-capabilities.ts +14 -8
  534. package/src/core/events/v3/support-storage/classify.ts +209 -0
  535. package/src/core/events/v3/support-storage/eligibility.ts +58 -0
  536. package/src/core/events/v3/support-storage/index.ts +9 -0
  537. package/src/core/events/v3/support-storage/inventory.ts +135 -0
  538. package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
  539. package/src/core/events/v3/support-storage/maintenance.ts +501 -0
  540. package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
  541. package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
  542. package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
  543. package/src/core/events/v3/support-storage/recovery.ts +43 -0
  544. package/src/core/events/v3/turn-telemetry.ts +58 -7
  545. package/src/core/events/v3/writer.ts +168 -16
  546. package/src/core/governor/plan-read.ts +5 -18
  547. package/src/core/governor/planning.ts +5 -8
  548. package/src/core/governor/service-read.ts +320 -2
  549. package/src/core/governor/service.ts +49 -22
  550. package/src/core/guard/evidence-v3.ts +1 -0
  551. package/src/core/hooks/adapter/events.ts +1 -0
  552. package/src/core/hooks/adapter/output.ts +12 -5
  553. package/src/core/hooks/adapter/runtime-telemetry.ts +408 -13
  554. package/src/core/hooks/cli.ts +226 -32
  555. package/src/core/hooks/effects/image-capture.ts +4 -1
  556. package/src/core/hooks/remediation-cap.ts +12 -6
  557. package/src/core/hooks/resolve/coord-root.ts +91 -11
  558. package/src/core/hooks/resolve/owner.ts +4 -0
  559. package/src/core/hooks/resolve/transcript.ts +18 -0
  560. package/src/core/inbox/contract.ts +81 -0
  561. package/src/core/inbox/index.ts +4 -0
  562. package/src/core/inbox/lifecycle.ts +104 -0
  563. package/src/core/inbox/service.ts +305 -0
  564. package/src/core/inbox/watcher.ts +36 -0
  565. package/src/core/presence/codec-digest.ts +15 -9
  566. package/src/core/presence/relay-client.ts +55 -7
  567. package/src/core/semantic/adapters.ts +200 -41
  568. package/src/core/semantic/contract.ts +135 -3
  569. package/src/core/semantic/index.ts +76 -2
  570. package/src/core/semantic/once.ts +93 -7
  571. package/src/core/semantic/prompt.ts +13 -1
  572. package/src/core/semantic/review.ts +803 -0
  573. package/src/core/semantic/routes.ts +30 -0
  574. package/src/core/semantic/scheduler.ts +49 -5
  575. package/src/core/semantic/service-status.ts +99 -5
  576. package/src/core/semantic/service.ts +116 -15
  577. package/src/core/semantic/soak.ts +638 -0
  578. package/src/core/semantic/storage.ts +20 -6
  579. package/src/core/semantic/usage.ts +272 -0
  580. package/src/core/semantic/validate.ts +31 -0
  581. package/src/core/storage/buffer.ts +124 -0
  582. package/src/core/storage/builtins.ts +916 -0
  583. package/src/core/storage/catalog.ts +467 -0
  584. package/src/core/storage/config.ts +423 -0
  585. package/src/core/storage/contract.ts +342 -0
  586. package/src/core/storage/durable-history.ts +738 -0
  587. package/src/core/storage/health.ts +76 -0
  588. package/src/core/storage/index.ts +15 -0
  589. package/src/core/storage/inventory.ts +859 -0
  590. package/src/core/storage/jsonl.ts +213 -0
  591. package/src/core/storage/log-retention.ts +555 -0
  592. package/src/core/storage/logger.ts +546 -0
  593. package/src/core/storage/maintenance-providers.ts +200 -0
  594. package/src/core/storage/maintenance.ts +929 -0
  595. package/src/core/storage/metrics.ts +199 -0
  596. package/src/core/storage/policy.ts +141 -0
  597. package/src/core/storage/process-log.ts +203 -0
  598. package/src/core/storage/query.ts +360 -0
  599. package/src/core/storage/receipts.ts +162 -0
  600. package/src/core/storage/segments.ts +721 -0
  601. package/src/core/storage/sink-graph.ts +343 -0
  602. package/src/core/storage/storm-control.ts +91 -0
  603. package/src/core/work/state.ts +12 -21
  604. package/src/core/workflow/live-session-v3.ts +2 -4
  605. package/src/index.ts +2 -0
  606. package/src/lazy-commands.ts +294 -0
  607. package/src/lib/docs-lint.ts +58 -77
  608. package/src/lib/docs-metadata-audit.ts +26 -21
  609. package/src/lib/docs-metadata-sync.ts +32 -9
  610. package/src/lib/docs-repository-view.ts +220 -0
  611. package/src/lib/http/client.ts +44 -8
  612. package/src/lib/http/index.ts +6 -1
  613. package/src/lib/indexer-exclusions.ts +173 -0
  614. package/src/lib/instructions/templates.ts +5 -0
  615. package/src/lib/local-file-url.ts +31 -0
  616. package/src/lib/web-performance.ts +335 -0
@@ -4,6 +4,7 @@ import { dump as dumpYaml, JSON_SCHEMA } from "js-yaml";
4
4
  import { parseFrontmatter } from "./docs-frontmatter.ts";
5
5
  import { managedDocsMetadataType } from "./docs-metadata-managed.ts";
6
6
  import { isDocsMetadataV2, validateDocsMetadataV2 } from "./docs-metadata-v2.ts";
7
+ import { createDocsRepositoryView } from "./docs-repository-view.ts";
7
8
  import { sh } from "./exec.ts";
8
9
 
9
10
  let REPO_ROOT = "";
@@ -21,6 +22,7 @@ export interface DocsMetadataSyncOpts {
21
22
  repo?: string;
22
23
  files?: string[];
23
24
  check?: boolean;
25
+ cached?: boolean;
24
26
  reviewed?: boolean;
25
27
  now?: string;
26
28
  }
@@ -49,15 +51,27 @@ function targets(repo?: string): Target[] {
49
51
  return selected;
50
52
  }
51
53
 
52
- async function changedFiles(target: Target, explicit: string[]): Promise<string[]> {
53
- if (explicit.length > 0) return explicit;
54
- const result = await sh("git diff --cached --name-only --diff-filter=ACMR -- '*.md'", {
55
- cwd: target.path,
56
- });
57
- if (result.exitCode !== 0) throw new Error(result.stderr || "git diff failed");
54
+ async function gitMarkdownPaths(target: Target, command: string): Promise<string[]> {
55
+ const result = await sh(command, { cwd: target.path });
56
+ if (result.exitCode !== 0) throw new Error(result.stderr || `${command} failed`);
58
57
  return result.stdout.split("\n").filter(Boolean);
59
58
  }
60
59
 
60
+ async function changedFiles(target: Target, explicit: string[], check: boolean): Promise<string[]> {
61
+ if (explicit.length > 0) return explicit;
62
+ const staged = await gitMarkdownPaths(
63
+ target,
64
+ "git diff --cached --name-only --diff-filter=ACMR -- '*.md'",
65
+ );
66
+ if (check) return staged;
67
+
68
+ const [unstaged, untracked] = await Promise.all([
69
+ gitMarkdownPaths(target, "git diff --name-only --diff-filter=ACMR -- '*.md'"),
70
+ gitMarkdownPaths(target, "git ls-files --others --exclude-standard -- '*.md'"),
71
+ ]);
72
+ return [...new Set([...staged, ...unstaged, ...untracked])];
73
+ }
74
+
61
75
  async function headContent(target: Target, path: string): Promise<string | null> {
62
76
  const result = await sh(`git show HEAD:${JSON.stringify(path)}`, { cwd: target.path });
63
77
  return result.exitCode === 0 ? result.stdout : null;
@@ -107,13 +121,22 @@ function addDays(value: string, days: number): string {
107
121
  export async function runDocsMetadataSync(
108
122
  opts: DocsMetadataSyncOpts,
109
123
  ): Promise<DocsMetadataSyncRow[]> {
124
+ if (opts.cached && !opts.check) {
125
+ throw new Error("--cached requires --check because Git index validation is read-only");
126
+ }
110
127
  const now = opts.now ?? new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
111
128
  const rows: DocsMetadataSyncRow[] = [];
112
129
  for (const target of targets(opts.repo)) {
113
- for (const path of await changedFiles(target, opts.files ?? [])) {
130
+ const paths = await changedFiles(target, opts.files ?? [], opts.check ?? false);
131
+ const cachedView = opts.cached ? await createDocsRepositoryView(target.path, "index") : null;
132
+ const cachedTexts = cachedView ? await cachedView.readTexts(paths) : null;
133
+ for (const path of paths) {
114
134
  const full = join(target.path, path);
115
- if (!existsSync(full)) continue;
116
- const currentText = readFileSync(full, "utf8");
135
+ if (cachedView ? !cachedView.has(path) : !existsSync(full)) continue;
136
+ const currentText = cachedView ? cachedTexts?.get(path) : readFileSync(full, "utf8");
137
+ if (currentText === undefined) {
138
+ throw new Error(`Git index content could not be read for ${path}`);
139
+ }
117
140
  const current = parseFrontmatter(currentText);
118
141
  if (!managedDocsMetadataType(path, current.data, current.raw !== null)) continue;
119
142
  if (!isDocsMetadataV2(current.data)) {
@@ -0,0 +1,220 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
3
+ import { basename, dirname, join } from "node:path";
4
+ import { exec } from "./exec.ts";
5
+
6
+ export type DocsRepositorySource = "worktree" | "index";
7
+
8
+ interface IndexEntry {
9
+ oid: string;
10
+ stage: number;
11
+ }
12
+
13
+ /**
14
+ * One coherent repository view for documentation commands.
15
+ *
16
+ * Worktree mode preserves the interactive commands' existing behavior. Index
17
+ * mode reads both path membership and file bytes through Git, so a pre-commit
18
+ * hook validates the exact index Git handed to it. During a path-scoped commit,
19
+ * Git exposes its temporary partial-commit index through GIT_INDEX_FILE; the
20
+ * view deliberately inherits that environment instead of rediscovering the
21
+ * shared working tree.
22
+ */
23
+ export interface DocsRepositoryView {
24
+ readonly root: string;
25
+ readonly source: DocsRepositorySource;
26
+ readonly trackedPaths: readonly string[];
27
+ has(path: string): boolean;
28
+ directFileNames(directory: string): string[];
29
+ readTexts(paths: readonly string[]): Promise<Map<string, string>>;
30
+ byteLength(path: string): Promise<number | null>;
31
+ }
32
+
33
+ function normalize(path: string): string {
34
+ return path.replaceAll("\\", "/").replace(/^\.\//, "");
35
+ }
36
+
37
+ function trackedPathList(stdout: string): string[] {
38
+ return stdout.split("\0").map(normalize).filter(Boolean);
39
+ }
40
+
41
+ async function worktreePaths(root: string): Promise<string[]> {
42
+ const result = await exec(["git", "ls-files", "--cached", "-z"], { cwd: root, trim: false });
43
+ if (result.exitCode !== 0) {
44
+ // Worktree lint historically supports non-repository fixtures and simply
45
+ // has no tracked-file checks to run there. Index mode remains strict.
46
+ return [];
47
+ }
48
+ return trackedPathList(result.stdout);
49
+ }
50
+
51
+ async function indexEntries(root: string): Promise<Map<string, IndexEntry>> {
52
+ const result = await exec(["git", "ls-files", "--cached", "--stage", "-z"], {
53
+ cwd: root,
54
+ trim: false,
55
+ });
56
+ if (result.exitCode !== 0) {
57
+ throw new Error(result.stderr || "git ls-files --stage failed");
58
+ }
59
+
60
+ const entries = new Map<string, IndexEntry>();
61
+ for (const record of result.stdout.split("\0").filter(Boolean)) {
62
+ const tab = record.indexOf("\t");
63
+ if (tab === -1) throw new Error(`invalid git ls-files --stage record: ${record}`);
64
+ const [mode, oid, stageText] = record.slice(0, tab).split(" ");
65
+ const path = normalize(record.slice(tab + 1));
66
+ const stage = Number.parseInt(stageText ?? "", 10);
67
+ if (!mode || !oid || !Number.isInteger(stage)) {
68
+ throw new Error(`invalid git ls-files --stage record for ${path}`);
69
+ }
70
+ if (stage !== 0) {
71
+ throw new Error(`cannot validate an index with unmerged entry: ${path}`);
72
+ }
73
+ entries.set(path, { oid, stage });
74
+ }
75
+ return entries;
76
+ }
77
+
78
+ function parseBatch(stdout: Buffer, requested: readonly string[]): Map<string, Buffer> {
79
+ const blobs = new Map<string, Buffer>();
80
+ let offset = 0;
81
+ for (const oid of requested) {
82
+ const newline = stdout.indexOf(0x0a, offset);
83
+ if (newline === -1) throw new Error(`git cat-file omitted the header for ${oid}`);
84
+ const header = stdout.subarray(offset, newline).toString("utf8");
85
+ offset = newline + 1;
86
+ const [reportedOid, type, sizeText] = header.split(" ");
87
+ const size = Number.parseInt(sizeText ?? "", 10);
88
+ if (reportedOid !== oid || type !== "blob" || !Number.isInteger(size) || size < 0) {
89
+ throw new Error(`git cat-file returned an invalid blob header for ${oid}: ${header}`);
90
+ }
91
+ const end = offset + size;
92
+ if (end > stdout.length) throw new Error(`git cat-file truncated blob ${oid}`);
93
+ blobs.set(oid, stdout.subarray(offset, end));
94
+ offset = end;
95
+ if (stdout[offset] !== 0x0a) throw new Error(`git cat-file omitted the separator for ${oid}`);
96
+ offset += 1;
97
+ }
98
+ return blobs;
99
+ }
100
+
101
+ function readIndexBlobs(root: string, oids: readonly string[]): Promise<Map<string, Buffer>> {
102
+ const unique = [...new Set(oids)];
103
+ if (unique.length === 0) return Promise.resolve(new Map());
104
+
105
+ return new Promise((resolveResult, rejectResult) => {
106
+ const process = spawn("git", ["cat-file", "--batch"], {
107
+ cwd: root,
108
+ env: { ...globalThis.process.env },
109
+ stdio: ["pipe", "pipe", "pipe"],
110
+ });
111
+ const stdout: Buffer[] = [];
112
+ const stderr: Buffer[] = [];
113
+ const timer = setTimeout(() => process.kill(), 30_000);
114
+ process.stdout.on("data", (chunk: Buffer) => stdout.push(chunk));
115
+ process.stderr.on("data", (chunk: Buffer) => stderr.push(chunk));
116
+ process.on("error", (error) => {
117
+ clearTimeout(timer);
118
+ rejectResult(error);
119
+ });
120
+ process.on("close", (code) => {
121
+ clearTimeout(timer);
122
+ if (code !== 0) {
123
+ rejectResult(
124
+ new Error(Buffer.concat(stderr).toString("utf8").trim() || "git cat-file failed"),
125
+ );
126
+ return;
127
+ }
128
+ try {
129
+ resolveResult(parseBatch(Buffer.concat(stdout), unique));
130
+ } catch (error) {
131
+ rejectResult(error);
132
+ }
133
+ });
134
+ process.stdin.end(`${unique.join("\n")}\n`);
135
+ });
136
+ }
137
+
138
+ function directIndexFiles(paths: readonly string[], directory: string): string[] {
139
+ const normalizedDirectory = normalize(directory).replace(/\/$/, "");
140
+ return paths
141
+ .filter((path) => normalize(dirname(path)) === normalizedDirectory)
142
+ .map((path) => basename(path));
143
+ }
144
+
145
+ export async function createDocsRepositoryView(
146
+ root: string,
147
+ source: DocsRepositorySource = "worktree",
148
+ ): Promise<DocsRepositoryView> {
149
+ if (source === "worktree") {
150
+ const trackedPaths = await worktreePaths(root);
151
+ return {
152
+ root,
153
+ source,
154
+ trackedPaths,
155
+ has: (path) => existsSync(join(root, path)),
156
+ directFileNames: (directory) => {
157
+ try {
158
+ return readdirSync(join(root, directory)).filter((entry) => {
159
+ try {
160
+ return statSync(join(root, directory, entry)).isFile();
161
+ } catch {
162
+ return false;
163
+ }
164
+ });
165
+ } catch {
166
+ return [];
167
+ }
168
+ },
169
+ readTexts: async (paths) => {
170
+ const texts = new Map<string, string>();
171
+ for (const path of paths) {
172
+ try {
173
+ texts.set(path, readFileSync(join(root, path), "utf8"));
174
+ } catch {
175
+ // The caller decides whether a missing tracked path is a finding.
176
+ }
177
+ }
178
+ return texts;
179
+ },
180
+ byteLength: async (path) => {
181
+ try {
182
+ return statSync(join(root, path)).size;
183
+ } catch {
184
+ return null;
185
+ }
186
+ },
187
+ };
188
+ }
189
+
190
+ const entries = await indexEntries(root);
191
+ const trackedPaths = [...entries.keys()];
192
+ const textCache = new Map<string, string>();
193
+ const loadTexts = async (paths: readonly string[]): Promise<Map<string, string>> => {
194
+ const wanted = [...new Set(paths.map(normalize))].filter((path) => entries.has(path));
195
+ const missing = wanted.filter((path) => !textCache.has(path));
196
+ const oids = missing.map((path) => entries.get(path)!.oid);
197
+ const blobs = await readIndexBlobs(root, oids);
198
+ for (const path of missing) {
199
+ const blob = blobs.get(entries.get(path)!.oid);
200
+ if (blob) textCache.set(path, blob.toString("utf8"));
201
+ }
202
+ return new Map(
203
+ wanted.flatMap((path) => (textCache.has(path) ? [[path, textCache.get(path)!]] : [])),
204
+ );
205
+ };
206
+
207
+ return {
208
+ root,
209
+ source,
210
+ trackedPaths,
211
+ has: (path) => entries.has(normalize(path)),
212
+ directFileNames: (directory) => directIndexFiles(trackedPaths, directory),
213
+ readTexts: loadTexts,
214
+ byteLength: async (path) => {
215
+ const normalized = normalize(path);
216
+ const text = (await loadTexts([normalized])).get(normalized);
217
+ return text === undefined ? null : Buffer.byteLength(text, "utf8");
218
+ },
219
+ };
220
+ }
@@ -11,7 +11,9 @@ import type { Cookie, CookieJar } from "../cookies/index.ts";
11
11
  * state with `browse`.
12
12
  */
13
13
 
14
- export interface FetchOptions {
14
+ export type FetchResponseType = "text" | "bytes";
15
+
16
+ export interface FetchOptions<TResponseType extends FetchResponseType = "text"> {
15
17
  /** HTTP method. Default GET. */
16
18
  method?: string;
17
19
  /** Request body. Strings/Buffers/Streams pass through to fetch directly. */
@@ -37,14 +39,20 @@ export interface FetchOptions {
37
39
  * only land when the key isn't already set.
38
40
  */
39
41
  extraHeaders?: (url: string) => Record<string, string>;
42
+ /** Response body representation. Default `text`; use `bytes` for lossless file output. */
43
+ responseType?: TResponseType;
40
44
  }
41
45
 
42
- export interface FetchResult {
46
+ type FetchBody<TResponseType extends FetchResponseType> = TResponseType extends "bytes"
47
+ ? Uint8Array
48
+ : string;
49
+
50
+ export interface FetchResult<TBody = string> {
43
51
  status: number;
44
52
  statusText: string;
45
53
  url: string;
46
54
  headers: Record<string, string>;
47
- body: string;
55
+ body: TBody;
48
56
  /** Number of cookies persisted back into the jar (0 if no jar passed). */
49
57
  cookiesSaved: number;
50
58
  }
@@ -52,11 +60,15 @@ export interface FetchResult {
52
60
  /**
53
61
  * Fetch a URL with optional cookie-jar attach + persist.
54
62
  *
55
- * Returns the response body as a string (callers handle JSON parsing).
63
+ * Returns the response body as text by default (callers handle JSON parsing).
64
+ * Pass `responseType: "bytes"` when the caller must preserve the body exactly.
56
65
  * Streams aren't supported; this is a CLI helper, not a streaming HTTP
57
66
  * client. Use Bun's `fetch` directly for streaming workloads.
58
67
  */
59
- export async function fetchWithJar(url: string, opts: FetchOptions = {}): Promise<FetchResult> {
68
+ export async function fetchWithJar<TResponseType extends FetchResponseType = "text">(
69
+ url: string,
70
+ opts: FetchOptions<TResponseType> = {},
71
+ ): Promise<FetchResult<FetchBody<TResponseType>>> {
60
72
  const headers: Record<string, string> = { ...(opts.headers ?? {}) };
61
73
 
62
74
  if (opts.jar) {
@@ -74,13 +86,32 @@ export async function fetchWithJar(url: string, opts: FetchOptions = {}): Promis
74
86
  }
75
87
  }
76
88
 
77
- const response = await fetch(url, {
89
+ // Byte mode is a download boundary, so keep the HTTP representation bytes
90
+ // aligned with the response headers. Bun otherwise decompresses the body
91
+ // while retaining Content-Encoding and the encoded Content-Length.
92
+ if (opts.responseType === "bytes" && !headers["Accept-Encoding"] && !headers["accept-encoding"]) {
93
+ headers["Accept-Encoding"] = "identity";
94
+ }
95
+ const fetchInit: RequestInit & { decompress?: boolean } = {
78
96
  method: opts.method ?? "GET",
79
97
  body: opts.body,
80
98
  headers,
81
99
  redirect: opts.redirect ?? "follow",
82
100
  signal: opts.signal,
83
- });
101
+ };
102
+ if (opts.responseType === "bytes") fetchInit.decompress = false;
103
+
104
+ const response = await fetch(url, fetchInit);
105
+
106
+ if (
107
+ opts.responseType === "bytes" &&
108
+ typeof Bun === "undefined" &&
109
+ response.headers.has("content-encoding")
110
+ ) {
111
+ throw new Error(
112
+ "cannot preserve a content-encoded response under the Node fallback; install Bun or request identity encoding",
113
+ );
114
+ }
84
115
 
85
116
  let cookiesSaved = 0;
86
117
  if (opts.jar) {
@@ -102,12 +133,17 @@ export async function fetchWithJar(url: string, opts: FetchOptions = {}): Promis
102
133
  headerObj[key] = value;
103
134
  });
104
135
 
136
+ const body =
137
+ opts.responseType === "bytes"
138
+ ? new Uint8Array(await response.arrayBuffer())
139
+ : await response.text();
140
+
105
141
  return {
106
142
  status: response.status,
107
143
  statusText: response.statusText,
108
144
  url: response.url,
109
145
  headers: headerObj,
110
- body: await response.text(),
146
+ body: body as FetchBody<TResponseType>,
111
147
  cookiesSaved,
112
148
  };
113
149
  }
@@ -1,2 +1,7 @@
1
- export { type FetchOptions, type FetchResult, fetchWithJar } from "./client.js";
1
+ export {
2
+ type FetchOptions,
3
+ type FetchResponseType,
4
+ type FetchResult,
5
+ fetchWithJar,
6
+ } from "./client.js";
2
7
  export * from "./request.ts";
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Editor-indexer exclusions for the `.harnery/` coord root.
3
+ *
4
+ * `harn init` already writes `.harnery/.gitignore`, which keeps git-aware
5
+ * tools out of runtime state. Two high-traffic editor surfaces ignore
6
+ * gitignore, though: Cursor's codebase indexer (governed by a repo-root
7
+ * `.cursorindexingignore`) and the VS Code/Cursor file watcher (governed by
8
+ * `files.watcherExclude` in `.vscode/settings.json`). A busy coord root holds
9
+ * tens of thousands of ledger events plus working artifacts, so on
10
+ * session-heavy hosts the missing exclusions turn editor startup into an
11
+ * indexing storm over machine-local state no editor needs to see.
12
+ *
13
+ * `applyIndexerExclusions` is idempotent and non-destructive: it appends a
14
+ * managed entry to `.cursorindexingignore` (or creates the file) and merges a
15
+ * single key into `.vscode/settings.json` (or creates it). A settings file it
16
+ * cannot merge safely (comments, malformed JSON, or a non-object
17
+ * `files.watcherExclude`) is left byte-identical and reported as a manual
18
+ * step. `removeIndexerExclusions` reverses exactly what apply wrote: it never
19
+ * removes a `.harnery/` ignore entry the consumer added themselves (detected
20
+ * by the absence of the managed comment) and never edits a settings file it
21
+ * could not have written into.
22
+ */
23
+
24
+ import { existsSync, mkdirSync, readFileSync, rmdirSync, rmSync, writeFileSync } from "node:fs";
25
+ import { resolve } from "node:path";
26
+
27
+ const CURSOR_IGNORE = ".cursorindexingignore";
28
+ const MANAGED_COMMENT =
29
+ "# .harnery/ is machine-local harnery runtime state (entry managed by init)";
30
+ const MANAGED_ENTRY = ".harnery/";
31
+ const VSCODE_DIR = ".vscode";
32
+ const VSCODE_SETTINGS = ".vscode/settings.json";
33
+ const WATCHER_KEY = "files.watcherExclude";
34
+ const WATCHER_GLOB = "**/.harnery/**";
35
+
36
+ /** True when a `.cursorindexingignore` line already excludes the coord root. */
37
+ function coversCoordRoot(line: string): boolean {
38
+ const t = line.trim();
39
+ return (
40
+ t === ".harnery" ||
41
+ t === ".harnery/" ||
42
+ t === "/.harnery" ||
43
+ t === "/.harnery/" ||
44
+ t === ".harnery/**" ||
45
+ t === "/.harnery/**"
46
+ );
47
+ }
48
+
49
+ function applyCursorIgnore(projectRoot: string, dryRun: boolean): string {
50
+ const path = resolve(projectRoot, CURSOR_IGNORE);
51
+ if (existsSync(path)) {
52
+ const raw = readFileSync(path, "utf8");
53
+ if (raw.split("\n").some(coversCoordRoot)) {
54
+ return `· ${CURSOR_IGNORE} already excludes .harnery/`;
55
+ }
56
+ if (dryRun) return `+ would append .harnery/ to ${CURSOR_IGNORE}`;
57
+ const sep = raw === "" || raw.endsWith("\n") ? "" : "\n";
58
+ writeFileSync(path, `${raw}${sep}${MANAGED_COMMENT}\n${MANAGED_ENTRY}\n`);
59
+ return `+ appended .harnery/ to ${CURSOR_IGNORE}`;
60
+ }
61
+ if (dryRun) return `+ would create ${CURSOR_IGNORE} (excludes .harnery/ from Cursor indexing)`;
62
+ writeFileSync(path, `${MANAGED_COMMENT}\n${MANAGED_ENTRY}\n`);
63
+ return `+ created ${CURSOR_IGNORE} (excludes .harnery/ from Cursor indexing)`;
64
+ }
65
+
66
+ function applyVscodeWatcherExclude(projectRoot: string, dryRun: boolean): string {
67
+ const path = resolve(projectRoot, VSCODE_SETTINGS);
68
+ if (!existsSync(path)) {
69
+ if (dryRun) return `+ would create ${VSCODE_SETTINGS} (file watcher excludes .harnery/)`;
70
+ mkdirSync(resolve(projectRoot, VSCODE_DIR), { recursive: true });
71
+ const body = JSON.stringify({ [WATCHER_KEY]: { [WATCHER_GLOB]: true } }, null, 2);
72
+ writeFileSync(path, `${body}\n`);
73
+ return `+ created ${VSCODE_SETTINGS} (file watcher excludes .harnery/)`;
74
+ }
75
+ const raw = readFileSync(path, "utf8");
76
+ let parsed: unknown;
77
+ try {
78
+ parsed = JSON.parse(raw);
79
+ } catch {
80
+ // JSONC (comments, trailing commas) or malformed. A rewrite would drop the
81
+ // consumer's comments, so leave the file alone and name the one-key merge.
82
+ return `! ${VSCODE_SETTINGS} is not plain JSON; add "${WATCHER_KEY}": {"${WATCHER_GLOB}": true} manually`;
83
+ }
84
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
85
+ return `! ${VSCODE_SETTINGS} is not a settings object; add "${WATCHER_KEY}": {"${WATCHER_GLOB}": true} manually`;
86
+ }
87
+ const settings = parsed as Record<string, unknown>;
88
+ const watcher = settings[WATCHER_KEY];
89
+ if (
90
+ watcher !== undefined &&
91
+ (typeof watcher !== "object" || watcher === null || Array.isArray(watcher))
92
+ ) {
93
+ return `! ${VSCODE_SETTINGS} has a non-object "${WATCHER_KEY}"; add "${WATCHER_GLOB}": true manually`;
94
+ }
95
+ const map = (watcher as Record<string, unknown> | undefined) ?? {};
96
+ if (map[WATCHER_GLOB] === true) {
97
+ return `· ${VSCODE_SETTINGS} file watcher already excludes .harnery/`;
98
+ }
99
+ if (dryRun) return `+ would add ${WATCHER_GLOB} to ${WATCHER_KEY} in ${VSCODE_SETTINGS}`;
100
+ map[WATCHER_GLOB] = true;
101
+ settings[WATCHER_KEY] = map;
102
+ writeFileSync(path, `${JSON.stringify(settings, null, 2)}\n`);
103
+ return `+ added ${WATCHER_GLOB} to ${WATCHER_KEY} in ${VSCODE_SETTINGS}`;
104
+ }
105
+
106
+ function removeCursorIgnore(projectRoot: string, dryRun: boolean): string | null {
107
+ const path = resolve(projectRoot, CURSOR_IGNORE);
108
+ if (!existsSync(path)) return null;
109
+ const raw = readFileSync(path, "utf8");
110
+ const lines = raw.split("\n");
111
+ // Only the managed pair is ours. A bare `.harnery/` line without the managed
112
+ // comment is a consumer's own entry and stays.
113
+ if (!lines.some((line) => line.trim() === MANAGED_COMMENT)) return null;
114
+ if (dryRun) return `+ would remove the managed .harnery/ entry from ${CURSOR_IGNORE}`;
115
+ const kept = lines.filter((line) => {
116
+ const t = line.trim();
117
+ return t !== MANAGED_COMMENT && t !== MANAGED_ENTRY;
118
+ });
119
+ if (kept.every((line) => line.trim() === "")) {
120
+ rmSync(path);
121
+ return `+ removed ${CURSOR_IGNORE} (was harnery-only)`;
122
+ }
123
+ let out = kept.join("\n");
124
+ if (!out.endsWith("\n")) out += "\n";
125
+ writeFileSync(path, out);
126
+ return `+ removed the managed .harnery/ entry from ${CURSOR_IGNORE}`;
127
+ }
128
+
129
+ function removeVscodeWatcherExclude(projectRoot: string, dryRun: boolean): string | null {
130
+ const path = resolve(projectRoot, VSCODE_SETTINGS);
131
+ if (!existsSync(path)) return null;
132
+ let parsed: unknown;
133
+ try {
134
+ parsed = JSON.parse(readFileSync(path, "utf8"));
135
+ } catch {
136
+ // Not plain JSON, so apply never wrote into it.
137
+ return null;
138
+ }
139
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
140
+ const settings = parsed as Record<string, unknown>;
141
+ const watcher = settings[WATCHER_KEY];
142
+ if (typeof watcher !== "object" || watcher === null || Array.isArray(watcher)) return null;
143
+ const map = watcher as Record<string, unknown>;
144
+ if (!(WATCHER_GLOB in map)) return null;
145
+ if (dryRun) return `+ would remove ${WATCHER_GLOB} from ${VSCODE_SETTINGS}`;
146
+ delete map[WATCHER_GLOB];
147
+ if (Object.keys(map).length === 0) delete settings[WATCHER_KEY];
148
+ if (Object.keys(settings).length === 0) {
149
+ rmSync(path);
150
+ try {
151
+ // Drop the .vscode/ directory too when the settings file was all it held.
152
+ rmdirSync(resolve(projectRoot, VSCODE_DIR));
153
+ } catch {
154
+ // Non-empty or shared; leave it.
155
+ }
156
+ return `+ removed ${VSCODE_SETTINGS} (was harnery-only)`;
157
+ }
158
+ writeFileSync(path, `${JSON.stringify(settings, null, 2)}\n`);
159
+ return `+ removed ${WATCHER_GLOB} from ${VSCODE_SETTINGS}`;
160
+ }
161
+
162
+ /** Ensure both editor exclusions exist. Returns init-style action lines. */
163
+ export function applyIndexerExclusions(projectRoot: string, dryRun: boolean): string[] {
164
+ return [applyCursorIgnore(projectRoot, dryRun), applyVscodeWatcherExclude(projectRoot, dryRun)];
165
+ }
166
+
167
+ /** Reverse exactly what apply wrote. Returns action lines; silent when nothing is ours. */
168
+ export function removeIndexerExclusions(projectRoot: string, dryRun: boolean): string[] {
169
+ return [
170
+ removeCursorIgnore(projectRoot, dryRun),
171
+ removeVscodeWatcherExclude(projectRoot, dryRun),
172
+ ].filter((line): line is string => line !== null);
173
+ }
@@ -147,6 +147,11 @@ returned path, then run \`${b} artifacts release <id>\` when active work is done
147
147
  Do not create a repo-root temp directory; \`${b} artifacts clean\` previews
148
148
  expired cleanup and requires \`--yes\` to delete anything.
149
149
 
150
+ **Local file links.** When the operator should open a local repo file, mint the
151
+ URL with \`${b} files url <repo-relative-path>\` instead of guessing it. HTML opens
152
+ as a real page with working scripts and relative assets; other files open in the
153
+ dashboard viewer. Use localhost links only when the operator shares this machine.
154
+
150
155
  **Decision docket.** When you would otherwise stop to ask a human a decision you
151
156
  can't resolve from the repo, file it instead. \`${b} decision file "<question>"\`
152
157
  records it and lets you proceed on a stated default; \`${b} decision search "<terms>"\`
@@ -0,0 +1,31 @@
1
+ /** Mnemonic dashboard port: 4276 spells HARN on a phone keypad. */
2
+ export const DEFAULT_WEB_PORT = 4276;
3
+
4
+ /** Cookie-isolated host for navigable repo files. */
5
+ export const FILES_ORIGIN_HOST = "harnery-files.localhost";
6
+
7
+ /** Encode each repo-path segment while preserving slash-based URL resolution. */
8
+ export function encodedRepoPath(relPath: string): string {
9
+ return relPath
10
+ .replace(/^\/+/, "")
11
+ .split("/")
12
+ .filter(Boolean)
13
+ .map((segment) => encodeURIComponent(segment))
14
+ .join("/");
15
+ }
16
+
17
+ export function localFilesOriginUrl(
18
+ relPath: string,
19
+ port: number | string = DEFAULT_WEB_PORT,
20
+ protocol = "http:",
21
+ ): string {
22
+ const portPart = String(port) === "" ? "" : `:${port}`;
23
+ return `${protocol}//${FILES_ORIGIN_HOST}${portPart}/${encodedRepoPath(relPath)}`;
24
+ }
25
+
26
+ export function localFileViewerUrl(
27
+ relPath: string,
28
+ port: number | string = DEFAULT_WEB_PORT,
29
+ ): string {
30
+ return `http://localhost:${port}/files?path=${encodeURIComponent(relPath)}`;
31
+ }