harnery 0.0.1 → 0.2.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 (445) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -2
  3. package/bin/agent-coord +42 -0
  4. package/bin/agent-hook +44 -0
  5. package/bin/harn +40 -0
  6. package/dist/cli.d.ts +9 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +18 -0
  9. package/dist/commander.d.ts +128 -0
  10. package/dist/commander.d.ts.map +1 -0
  11. package/dist/commander.js +126 -0
  12. package/dist/commands/agents.d.ts +18 -0
  13. package/dist/commands/agents.d.ts.map +1 -0
  14. package/dist/commands/agents.js +3946 -0
  15. package/dist/commands/backup.d.ts +22 -0
  16. package/dist/commands/backup.d.ts.map +1 -0
  17. package/dist/commands/backup.js +262 -0
  18. package/dist/commands/browse-ai.d.ts +4 -0
  19. package/dist/commands/browse-ai.d.ts.map +1 -0
  20. package/dist/commands/browse-ai.js +156 -0
  21. package/dist/commands/browse.d.ts +4 -0
  22. package/dist/commands/browse.d.ts.map +1 -0
  23. package/dist/commands/browse.js +590 -0
  24. package/dist/commands/callers.d.ts +4 -0
  25. package/dist/commands/callers.d.ts.map +1 -0
  26. package/dist/commands/callers.js +276 -0
  27. package/dist/commands/completion.d.ts +17 -0
  28. package/dist/commands/completion.d.ts.map +1 -0
  29. package/dist/commands/completion.js +158 -0
  30. package/dist/commands/config-get.d.ts +4 -0
  31. package/dist/commands/config-get.d.ts.map +1 -0
  32. package/dist/commands/config-get.js +131 -0
  33. package/dist/commands/context.d.ts +11 -0
  34. package/dist/commands/context.d.ts.map +1 -0
  35. package/dist/commands/context.js +185 -0
  36. package/dist/commands/cookies.d.ts +4 -0
  37. package/dist/commands/cookies.d.ts.map +1 -0
  38. package/dist/commands/cookies.js +140 -0
  39. package/dist/commands/docs.d.ts +4 -0
  40. package/dist/commands/docs.d.ts.map +1 -0
  41. package/dist/commands/docs.js +137 -0
  42. package/dist/commands/doctor.d.ts +25 -0
  43. package/dist/commands/doctor.d.ts.map +1 -0
  44. package/dist/commands/doctor.js +200 -0
  45. package/dist/commands/edit-batch.d.ts +18 -0
  46. package/dist/commands/edit-batch.d.ts.map +1 -0
  47. package/dist/commands/edit-batch.js +172 -0
  48. package/dist/commands/eml.d.ts +4 -0
  49. package/dist/commands/eml.d.ts.map +1 -0
  50. package/dist/commands/eml.js +428 -0
  51. package/dist/commands/env.d.ts +4 -0
  52. package/dist/commands/env.d.ts.map +1 -0
  53. package/dist/commands/env.js +201 -0
  54. package/dist/commands/fetch.d.ts +4 -0
  55. package/dist/commands/fetch.d.ts.map +1 -0
  56. package/dist/commands/fetch.js +99 -0
  57. package/dist/commands/file-history.d.ts +4 -0
  58. package/dist/commands/file-history.d.ts.map +1 -0
  59. package/dist/commands/file-history.js +152 -0
  60. package/dist/commands/grep.d.ts +4 -0
  61. package/dist/commands/grep.d.ts.map +1 -0
  62. package/dist/commands/grep.js +317 -0
  63. package/dist/commands/init.d.ts +82 -0
  64. package/dist/commands/init.d.ts.map +1 -0
  65. package/dist/commands/init.js +288 -0
  66. package/dist/commands/outline.d.ts +4 -0
  67. package/dist/commands/outline.d.ts.map +1 -0
  68. package/dist/commands/outline.js +494 -0
  69. package/dist/commands/presence.d.ts +12 -0
  70. package/dist/commands/presence.d.ts.map +1 -0
  71. package/dist/commands/presence.js +123 -0
  72. package/dist/commands/read.d.ts +7 -0
  73. package/dist/commands/read.d.ts.map +1 -0
  74. package/dist/commands/read.js +46 -0
  75. package/dist/commands/scratch.d.ts +4 -0
  76. package/dist/commands/scratch.d.ts.map +1 -0
  77. package/dist/commands/scratch.js +426 -0
  78. package/dist/commands/session.d.ts +4 -0
  79. package/dist/commands/session.d.ts.map +1 -0
  80. package/dist/commands/session.js +162 -0
  81. package/dist/commands/sync.d.ts +24 -0
  82. package/dist/commands/sync.d.ts.map +1 -0
  83. package/dist/commands/sync.js +275 -0
  84. package/dist/commands/toc.d.ts +5 -0
  85. package/dist/commands/toc.d.ts.map +1 -0
  86. package/dist/commands/toc.js +153 -0
  87. package/dist/commands/tokens.d.ts +4 -0
  88. package/dist/commands/tokens.d.ts.map +1 -0
  89. package/dist/commands/tokens.js +48 -0
  90. package/dist/commands/tunnel.d.ts +4 -0
  91. package/dist/commands/tunnel.d.ts.map +1 -0
  92. package/dist/commands/tunnel.js +513 -0
  93. package/dist/commands/uninstall.d.ts +22 -0
  94. package/dist/commands/uninstall.d.ts.map +1 -0
  95. package/dist/commands/uninstall.js +126 -0
  96. package/dist/commands/web.d.ts +4 -0
  97. package/dist/commands/web.d.ts.map +1 -0
  98. package/dist/commands/web.js +165 -0
  99. package/dist/core/agents/canonical-emit.d.ts +27 -0
  100. package/dist/core/agents/canonical-emit.d.ts.map +1 -0
  101. package/dist/core/agents/canonical-emit.js +72 -0
  102. package/dist/core/agents/cli-emit.d.ts +27 -0
  103. package/dist/core/agents/cli-emit.d.ts.map +1 -0
  104. package/dist/core/agents/cli-emit.js +57 -0
  105. package/dist/core/agents/cli.d.ts +10 -0
  106. package/dist/core/agents/cli.d.ts.map +1 -0
  107. package/dist/core/agents/cli.js +757 -0
  108. package/dist/core/agents/codex-replay.d.ts +29 -0
  109. package/dist/core/agents/codex-replay.d.ts.map +1 -0
  110. package/dist/core/agents/codex-replay.js +138 -0
  111. package/dist/core/agents/coord-client.d.ts +98 -0
  112. package/dist/core/agents/coord-client.d.ts.map +1 -0
  113. package/dist/core/agents/coord-client.js +212 -0
  114. package/dist/core/agents/events/consume.d.ts +59 -0
  115. package/dist/core/agents/events/consume.d.ts.map +1 -0
  116. package/dist/core/agents/events/consume.js +147 -0
  117. package/dist/core/agents/events/emit.d.ts +42 -0
  118. package/dist/core/agents/events/emit.d.ts.map +1 -0
  119. package/dist/core/agents/events/emit.js +70 -0
  120. package/dist/core/agents/events/ulid.d.ts +11 -0
  121. package/dist/core/agents/events/ulid.d.ts.map +1 -0
  122. package/dist/core/agents/events/ulid.js +47 -0
  123. package/dist/core/agents/index.d.ts +14 -0
  124. package/dist/core/agents/index.d.ts.map +1 -0
  125. package/dist/core/agents/index.js +13 -0
  126. package/dist/core/agents/paths.d.ts +6 -0
  127. package/dist/core/agents/paths.d.ts.map +1 -0
  128. package/dist/core/agents/paths.js +17 -0
  129. package/dist/core/agents/render/prompt-context.d.ts +43 -0
  130. package/dist/core/agents/render/prompt-context.d.ts.map +1 -0
  131. package/dist/core/agents/render/prompt-context.js +335 -0
  132. package/dist/core/agents/render/session-context.d.ts +39 -0
  133. package/dist/core/agents/render/session-context.d.ts.map +1 -0
  134. package/dist/core/agents/render/session-context.js +283 -0
  135. package/dist/core/agents/rules/claim-conflict.d.ts +35 -0
  136. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -0
  137. package/dist/core/agents/rules/claim-conflict.js +244 -0
  138. package/dist/core/agents/rules/commit-conflict.d.ts +59 -0
  139. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -0
  140. package/dist/core/agents/rules/commit-conflict.js +244 -0
  141. package/dist/core/agents/rules/stop-hook.d.ts +44 -0
  142. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -0
  143. package/dist/core/agents/rules/stop-hook.js +161 -0
  144. package/dist/core/agents/session-events.d.ts +41 -0
  145. package/dist/core/agents/session-events.d.ts.map +1 -0
  146. package/dist/core/agents/session-events.js +205 -0
  147. package/dist/core/agents/state/activity-log.d.ts +18 -0
  148. package/dist/core/agents/state/activity-log.d.ts.map +1 -0
  149. package/dist/core/agents/state/activity-log.js +34 -0
  150. package/dist/core/agents/state/council.d.ts +39 -0
  151. package/dist/core/agents/state/council.d.ts.map +1 -0
  152. package/dist/core/agents/state/council.js +216 -0
  153. package/dist/core/agents/state/heartbeat-projector.d.ts +59 -0
  154. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -0
  155. package/dist/core/agents/state/heartbeat-projector.js +436 -0
  156. package/dist/core/agents/state/heartbeat-writer.d.ts +64 -0
  157. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -0
  158. package/dist/core/agents/state/heartbeat-writer.js +271 -0
  159. package/dist/core/agents/state/names.d.ts +35 -0
  160. package/dist/core/agents/state/names.d.ts.map +1 -0
  161. package/dist/core/agents/state/names.js +376 -0
  162. package/dist/core/agents/state/pidmap.d.ts +11 -0
  163. package/dist/core/agents/state/pidmap.d.ts.map +1 -0
  164. package/dist/core/agents/state/pidmap.js +32 -0
  165. package/dist/core/agents/state/scratch.d.ts +27 -0
  166. package/dist/core/agents/state/scratch.d.ts.map +1 -0
  167. package/dist/core/agents/state/scratch.js +90 -0
  168. package/dist/core/agents/state/shell-mutation.d.ts +17 -0
  169. package/dist/core/agents/state/shell-mutation.d.ts.map +1 -0
  170. package/dist/core/agents/state/shell-mutation.js +41 -0
  171. package/dist/core/agents/state/stale-sweep.d.ts +16 -0
  172. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -0
  173. package/dist/core/agents/state/stale-sweep.js +166 -0
  174. package/dist/core/config.d.ts +29 -0
  175. package/dist/core/config.d.ts.map +1 -0
  176. package/dist/core/config.js +108 -0
  177. package/dist/core/hooks/cli.d.ts +21 -0
  178. package/dist/core/hooks/cli.d.ts.map +1 -0
  179. package/dist/core/hooks/cli.js +1123 -0
  180. package/dist/core/hooks/effects/image-capture.d.ts +43 -0
  181. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -0
  182. package/dist/core/hooks/effects/image-capture.js +288 -0
  183. package/dist/core/hooks/effects/index.d.ts +64 -0
  184. package/dist/core/hooks/effects/index.d.ts.map +1 -0
  185. package/dist/core/hooks/effects/index.js +197 -0
  186. package/dist/core/hooks/events/emit.d.ts +31 -0
  187. package/dist/core/hooks/events/emit.d.ts.map +1 -0
  188. package/dist/core/hooks/events/emit.js +89 -0
  189. package/dist/core/hooks/events/schema.d.ts +235 -0
  190. package/dist/core/hooks/events/schema.d.ts.map +1 -0
  191. package/dist/core/hooks/events/schema.js +12 -0
  192. package/dist/core/hooks/events/ulid.d.ts +10 -0
  193. package/dist/core/hooks/events/ulid.d.ts.map +1 -0
  194. package/dist/core/hooks/events/ulid.js +47 -0
  195. package/dist/core/hooks/harness/detect.d.ts +9 -0
  196. package/dist/core/hooks/harness/detect.d.ts.map +1 -0
  197. package/dist/core/hooks/harness/detect.js +29 -0
  198. package/dist/core/hooks/harness/events.d.ts +45 -0
  199. package/dist/core/hooks/harness/events.d.ts.map +1 -0
  200. package/dist/core/hooks/harness/events.js +71 -0
  201. package/dist/core/hooks/harness/output.d.ts +46 -0
  202. package/dist/core/hooks/harness/output.d.ts.map +1 -0
  203. package/dist/core/hooks/harness/output.js +87 -0
  204. package/dist/core/hooks/harness/parse.d.ts +67 -0
  205. package/dist/core/hooks/harness/parse.d.ts.map +1 -0
  206. package/dist/core/hooks/harness/parse.js +132 -0
  207. package/dist/core/hooks/index.d.ts +8 -0
  208. package/dist/core/hooks/index.d.ts.map +1 -0
  209. package/dist/core/hooks/index.js +7 -0
  210. package/dist/core/hooks/resolve/anchor.d.ts +37 -0
  211. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -0
  212. package/dist/core/hooks/resolve/anchor.js +48 -0
  213. package/dist/core/hooks/resolve/coord-root.d.ts +6 -0
  214. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -0
  215. package/dist/core/hooks/resolve/coord-root.js +27 -0
  216. package/dist/core/hooks/resolve/intent.d.ts +33 -0
  217. package/dist/core/hooks/resolve/intent.d.ts.map +1 -0
  218. package/dist/core/hooks/resolve/intent.js +79 -0
  219. package/dist/core/hooks/resolve/owner.d.ts +42 -0
  220. package/dist/core/hooks/resolve/owner.d.ts.map +1 -0
  221. package/dist/core/hooks/resolve/owner.js +140 -0
  222. package/dist/core/hooks/resolve/transcript.d.ts +26 -0
  223. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -0
  224. package/dist/core/hooks/resolve/transcript.js +73 -0
  225. package/dist/index.d.ts +15 -0
  226. package/dist/index.d.ts.map +1 -0
  227. package/dist/index.js +13 -0
  228. package/dist/lib/agent-browser/client.d.ts +99 -0
  229. package/dist/lib/agent-browser/client.d.ts.map +1 -0
  230. package/dist/lib/agent-browser/client.js +177 -0
  231. package/dist/lib/agent-browser/index.d.ts +2 -0
  232. package/dist/lib/agent-browser/index.d.ts.map +1 -0
  233. package/dist/lib/agent-browser/index.js +1 -0
  234. package/dist/lib/browser/client.d.ts +193 -0
  235. package/dist/lib/browser/client.d.ts.map +1 -0
  236. package/dist/lib/browser/client.js +325 -0
  237. package/dist/lib/browser/dev-overlay.d.ts +23 -0
  238. package/dist/lib/browser/dev-overlay.d.ts.map +1 -0
  239. package/dist/lib/browser/dev-overlay.js +153 -0
  240. package/dist/lib/browser/index.d.ts +5 -0
  241. package/dist/lib/browser/index.d.ts.map +1 -0
  242. package/dist/lib/browser/index.js +2 -0
  243. package/dist/lib/browser/layout.d.ts +79 -0
  244. package/dist/lib/browser/layout.d.ts.map +1 -0
  245. package/dist/lib/browser/layout.js +220 -0
  246. package/dist/lib/browser/visibility.d.ts +86 -0
  247. package/dist/lib/browser/visibility.d.ts.map +1 -0
  248. package/dist/lib/browser/visibility.js +333 -0
  249. package/dist/lib/browser/visual-diff.d.ts +38 -0
  250. package/dist/lib/browser/visual-diff.d.ts.map +1 -0
  251. package/dist/lib/browser/visual-diff.js +107 -0
  252. package/dist/lib/completion/bash.d.ts +25 -0
  253. package/dist/lib/completion/bash.d.ts.map +1 -0
  254. package/dist/lib/completion/bash.js +284 -0
  255. package/dist/lib/completion/fish.d.ts +16 -0
  256. package/dist/lib/completion/fish.d.ts.map +1 -0
  257. package/dist/lib/completion/fish.js +118 -0
  258. package/dist/lib/completion/index.d.ts +5 -0
  259. package/dist/lib/completion/index.d.ts.map +1 -0
  260. package/dist/lib/completion/index.js +4 -0
  261. package/dist/lib/completion/walk.d.ts +68 -0
  262. package/dist/lib/completion/walk.d.ts.map +1 -0
  263. package/dist/lib/completion/walk.js +102 -0
  264. package/dist/lib/completion/zsh.d.ts +13 -0
  265. package/dist/lib/completion/zsh.d.ts.map +1 -0
  266. package/dist/lib/completion/zsh.js +249 -0
  267. package/dist/lib/context/index.d.ts +107 -0
  268. package/dist/lib/context/index.d.ts.map +1 -0
  269. package/dist/lib/context/index.js +275 -0
  270. package/dist/lib/cookies/client.d.ts +131 -0
  271. package/dist/lib/cookies/client.d.ts.map +1 -0
  272. package/dist/lib/cookies/client.js +239 -0
  273. package/dist/lib/cookies/index.d.ts +2 -0
  274. package/dist/lib/cookies/index.d.ts.map +1 -0
  275. package/dist/lib/cookies/index.js +1 -0
  276. package/dist/lib/council/index.d.ts +266 -0
  277. package/dist/lib/council/index.d.ts.map +1 -0
  278. package/dist/lib/council/index.js +674 -0
  279. package/dist/lib/docs-index.d.ts +28 -0
  280. package/dist/lib/docs-index.d.ts.map +1 -0
  281. package/dist/lib/docs-index.js +169 -0
  282. package/dist/lib/docs-lint.d.ts +26 -0
  283. package/dist/lib/docs-lint.d.ts.map +1 -0
  284. package/dist/lib/docs-lint.js +378 -0
  285. package/dist/lib/docs-sweep.d.ts +34 -0
  286. package/dist/lib/docs-sweep.d.ts.map +1 -0
  287. package/dist/lib/docs-sweep.js +304 -0
  288. package/dist/lib/docs.d.ts +27 -0
  289. package/dist/lib/docs.d.ts.map +1 -0
  290. package/dist/lib/docs.js +142 -0
  291. package/dist/lib/env.d.ts +11 -0
  292. package/dist/lib/env.d.ts.map +1 -0
  293. package/dist/lib/env.js +12 -0
  294. package/dist/lib/exec.d.ts +32 -0
  295. package/dist/lib/exec.d.ts.map +1 -0
  296. package/dist/lib/exec.js +54 -0
  297. package/dist/lib/format.d.ts +29 -0
  298. package/dist/lib/format.d.ts.map +1 -0
  299. package/dist/lib/format.js +139 -0
  300. package/dist/lib/http/client.d.ts +56 -0
  301. package/dist/lib/http/client.d.ts.map +1 -0
  302. package/dist/lib/http/client.js +160 -0
  303. package/dist/lib/http/index.d.ts +2 -0
  304. package/dist/lib/http/index.d.ts.map +1 -0
  305. package/dist/lib/http/index.js +1 -0
  306. package/dist/lib/identities/index.d.ts +77 -0
  307. package/dist/lib/identities/index.d.ts.map +1 -0
  308. package/dist/lib/identities/index.js +190 -0
  309. package/dist/lib/machine.d.ts +19 -0
  310. package/dist/lib/machine.d.ts.map +1 -0
  311. package/dist/lib/machine.js +61 -0
  312. package/dist/lib/presence.d.ts +48 -0
  313. package/dist/lib/presence.d.ts.map +1 -0
  314. package/dist/lib/presence.js +123 -0
  315. package/dist/lib/readability/client.d.ts +32 -0
  316. package/dist/lib/readability/client.d.ts.map +1 -0
  317. package/dist/lib/readability/client.js +119 -0
  318. package/dist/lib/readability/index.d.ts +2 -0
  319. package/dist/lib/readability/index.d.ts.map +1 -0
  320. package/dist/lib/readability/index.js +1 -0
  321. package/dist/lib/scratch/index.d.ts +74 -0
  322. package/dist/lib/scratch/index.d.ts.map +1 -0
  323. package/dist/lib/scratch/index.js +393 -0
  324. package/dist/lib/tunnel/gate.d.ts +12 -0
  325. package/dist/lib/tunnel/gate.d.ts.map +1 -0
  326. package/dist/lib/tunnel/gate.js +101 -0
  327. package/dist/lib/tunnel/state.d.ts +34 -0
  328. package/dist/lib/tunnel/state.d.ts.map +1 -0
  329. package/dist/lib/tunnel/state.js +132 -0
  330. package/package.json +160 -8
  331. package/schemas/.gitkeep +0 -0
  332. package/schemas/config.schema.json +109 -0
  333. package/src/cli.ts +22 -0
  334. package/src/commander.ts +242 -0
  335. package/src/commands/.gitkeep +0 -0
  336. package/src/commands/agents.ts +4567 -0
  337. package/src/commands/backup.ts +305 -0
  338. package/src/commands/browse-ai.ts +198 -0
  339. package/src/commands/browse.ts +849 -0
  340. package/src/commands/callers.ts +363 -0
  341. package/src/commands/completion.ts +193 -0
  342. package/src/commands/config-get.ts +161 -0
  343. package/src/commands/context.ts +209 -0
  344. package/src/commands/cookies.ts +198 -0
  345. package/src/commands/docs.ts +174 -0
  346. package/src/commands/doctor.ts +231 -0
  347. package/src/commands/edit-batch.ts +233 -0
  348. package/src/commands/eml.ts +519 -0
  349. package/src/commands/env.ts +254 -0
  350. package/src/commands/fetch.ts +136 -0
  351. package/src/commands/file-history.ts +202 -0
  352. package/src/commands/grep.ts +371 -0
  353. package/src/commands/init.ts +335 -0
  354. package/src/commands/outline.ts +564 -0
  355. package/src/commands/presence.ts +152 -0
  356. package/src/commands/read.ts +64 -0
  357. package/src/commands/scratch.ts +445 -0
  358. package/src/commands/session.ts +187 -0
  359. package/src/commands/sync.ts +306 -0
  360. package/src/commands/toc.ts +218 -0
  361. package/src/commands/tokens.ts +79 -0
  362. package/src/commands/tunnel.ts +633 -0
  363. package/src/commands/uninstall.ts +144 -0
  364. package/src/commands/web.ts +193 -0
  365. package/src/core/agents/canonical-emit.ts +77 -0
  366. package/src/core/agents/cli-emit.ts +64 -0
  367. package/src/core/agents/cli.ts +838 -0
  368. package/src/core/agents/codex-replay.ts +163 -0
  369. package/src/core/agents/coord-client.ts +249 -0
  370. package/src/core/agents/events/consume.ts +196 -0
  371. package/src/core/agents/events/emit.ts +108 -0
  372. package/src/core/agents/events/ulid.ts +51 -0
  373. package/src/core/agents/index.ts +14 -0
  374. package/src/core/agents/paths.ts +16 -0
  375. package/src/core/agents/render/prompt-context.ts +401 -0
  376. package/src/core/agents/render/session-context.ts +341 -0
  377. package/src/core/agents/rules/claim-conflict.ts +282 -0
  378. package/src/core/agents/rules/commit-conflict.ts +303 -0
  379. package/src/core/agents/rules/stop-hook.ts +229 -0
  380. package/src/core/agents/session-events.ts +228 -0
  381. package/src/core/agents/state/activity-log.ts +33 -0
  382. package/src/core/agents/state/council.ts +265 -0
  383. package/src/core/agents/state/heartbeat-projector.ts +488 -0
  384. package/src/core/agents/state/heartbeat-writer.ts +333 -0
  385. package/src/core/agents/state/names.ts +399 -0
  386. package/src/core/agents/state/pidmap.ts +38 -0
  387. package/src/core/agents/state/scratch.ts +121 -0
  388. package/src/core/agents/state/shell-mutation.ts +44 -0
  389. package/src/core/agents/state/stale-sweep.ts +190 -0
  390. package/src/core/config.ts +111 -0
  391. package/src/core/hooks/cli.ts +1247 -0
  392. package/src/core/hooks/effects/image-capture.ts +330 -0
  393. package/src/core/hooks/effects/index.ts +210 -0
  394. package/src/core/hooks/events/emit.ts +120 -0
  395. package/src/core/hooks/events/schema.ts +430 -0
  396. package/src/core/hooks/events/ulid.ts +51 -0
  397. package/src/core/hooks/harness/detect.ts +30 -0
  398. package/src/core/hooks/harness/events.ts +102 -0
  399. package/src/core/hooks/harness/output.ts +100 -0
  400. package/src/core/hooks/harness/parse.ts +180 -0
  401. package/src/core/hooks/index.ts +16 -0
  402. package/src/core/hooks/resolve/anchor.ts +51 -0
  403. package/src/core/hooks/resolve/coord-root.ts +25 -0
  404. package/src/core/hooks/resolve/intent.ts +89 -0
  405. package/src/core/hooks/resolve/owner.ts +140 -0
  406. package/src/core/hooks/resolve/transcript.ts +72 -0
  407. package/src/hooks/.gitkeep +0 -0
  408. package/src/index.ts +15 -0
  409. package/src/lib/agent-browser/client.ts +239 -0
  410. package/src/lib/agent-browser/index.ts +1 -0
  411. package/src/lib/browser/client.ts +449 -0
  412. package/src/lib/browser/dev-overlay.ts +207 -0
  413. package/src/lib/browser/index.ts +24 -0
  414. package/src/lib/browser/layout.ts +288 -0
  415. package/src/lib/browser/visibility.ts +419 -0
  416. package/src/lib/browser/visual-diff.ts +150 -0
  417. package/src/lib/completion/bash.ts +291 -0
  418. package/src/lib/completion/fish.ts +134 -0
  419. package/src/lib/completion/index.ts +10 -0
  420. package/src/lib/completion/walk.ts +184 -0
  421. package/src/lib/completion/zsh.ts +262 -0
  422. package/src/lib/context/index.ts +386 -0
  423. package/src/lib/cookies/client.ts +301 -0
  424. package/src/lib/cookies/index.ts +13 -0
  425. package/src/lib/council/index.ts +803 -0
  426. package/src/lib/docs-index.ts +216 -0
  427. package/src/lib/docs-lint.ts +413 -0
  428. package/src/lib/docs-sweep.ts +348 -0
  429. package/src/lib/docs.ts +199 -0
  430. package/src/lib/env.ts +12 -0
  431. package/src/lib/exec.ts +74 -0
  432. package/src/lib/format.ts +147 -0
  433. package/src/lib/http/client.ts +211 -0
  434. package/src/lib/http/index.ts +1 -0
  435. package/src/lib/identities/index.ts +210 -0
  436. package/src/lib/machine.ts +61 -0
  437. package/src/lib/presence.ts +154 -0
  438. package/src/lib/readability/client.ts +156 -0
  439. package/src/lib/readability/index.ts +5 -0
  440. package/src/lib/readability/turndown-plugin-gfm.d.ts +10 -0
  441. package/src/lib/scratch/index.ts +470 -0
  442. package/src/lib/tunnel/gate.ts +113 -0
  443. package/src/lib/tunnel/state.ts +167 -0
  444. package/src/web/.gitkeep +0 -0
  445. package/index.js +0 -1
@@ -0,0 +1,139 @@
1
+ /** ANSI color helpers, minimal, no dependencies */
2
+ const isColor = process.stdout.isTTY !== false;
3
+ const code = (n) => (isColor ? `\x1b[${n}m` : "");
4
+ const reset = code(0);
5
+ export const c = {
6
+ bold: (s) => `${code(1)}${s}${reset}`,
7
+ dim: (s) => `${code(2)}${s}${reset}`,
8
+ green: (s) => `${code(32)}${s}${reset}`,
9
+ red: (s) => `${code(31)}${s}${reset}`,
10
+ yellow: (s) => `${code(33)}${s}${reset}`,
11
+ cyan: (s) => `${code(36)}${s}${reset}`,
12
+ gray: (s) => `${code(90)}${s}${reset}`,
13
+ magenta: (s) => `${code(35)}${s}${reset}`,
14
+ };
15
+ /** Placeholder shown when a value is missing (null/empty), e.g. an unknown branch or age. */
16
+ export const NO_DATA = "—";
17
+ /**
18
+ * Pretty-print + ANSI-colorize a JSON value. 2-space indent. TTY-aware: when
19
+ * stdout is not a TTY, the underlying `c.*` helpers emit no ANSI codes, so
20
+ * output is plain text. Use this for `--pretty` flags on JSON-emitting commands.
21
+ *
22
+ * Colors: keys=cyan, strings=green, numbers=magenta, booleans=yellow, null=dim.
23
+ */
24
+ export function colorJson(value, indent = 0) {
25
+ const seen = new WeakSet();
26
+ const step = " ";
27
+ function fmt(v, depth) {
28
+ if (v === null)
29
+ return c.dim("null");
30
+ if (typeof v === "boolean")
31
+ return c.yellow(String(v));
32
+ if (typeof v === "number")
33
+ return c.magenta(String(v));
34
+ if (typeof v === "string")
35
+ return c.green(JSON.stringify(v));
36
+ if (typeof v === "bigint")
37
+ return c.magenta(`${v}n`);
38
+ if (Array.isArray(v)) {
39
+ if (v.length === 0)
40
+ return "[]";
41
+ if (seen.has(v))
42
+ return c.dim('"[Circular]"');
43
+ seen.add(v);
44
+ const pad = step.repeat(depth + 1);
45
+ const close = step.repeat(depth);
46
+ const items = v.map((x) => pad + fmt(x, depth + 1)).join(",\n");
47
+ return `[\n${items}\n${close}]`;
48
+ }
49
+ if (typeof v === "object") {
50
+ // Class instances that define toJSON() (Big.js, Decimal.js, Date, etc.)
51
+ // would render as their raw internal shape if we walked Object.keys
52
+ // directly. Unwrap once so callers see the intended representation
53
+ // (Big.js → "1.97" instead of {s,e,c} from BigQuery NUMERIC fields).
54
+ const maybeJsonable = v;
55
+ if (typeof maybeJsonable.toJSON === "function") {
56
+ return fmt(maybeJsonable.toJSON(), depth);
57
+ }
58
+ const obj = v;
59
+ const keys = Object.keys(obj);
60
+ if (keys.length === 0)
61
+ return "{}";
62
+ if (seen.has(obj))
63
+ return c.dim('"[Circular]"');
64
+ seen.add(obj);
65
+ const pad = step.repeat(depth + 1);
66
+ const close = step.repeat(depth);
67
+ const items = keys
68
+ .map((k) => `${pad}${c.cyan(JSON.stringify(k))}: ${fmt(obj[k], depth + 1)}`)
69
+ .join(",\n");
70
+ return `{\n${items}\n${close}}`;
71
+ }
72
+ return JSON.stringify(v) ?? "null";
73
+ }
74
+ return fmt(value, indent);
75
+ }
76
+ /** Render a table from rows of objects */
77
+ export function table(rows, opts = {}) {
78
+ if (rows.length === 0)
79
+ return c.dim("(no rows)");
80
+ const maxCol = opts.maxColWidth ?? 60;
81
+ const keys = Object.keys(rows[0]);
82
+ // Compute column widths
83
+ const widths = new Map();
84
+ for (const key of keys) {
85
+ let max = key.length;
86
+ for (const row of rows) {
87
+ const val = stringify(row[key]);
88
+ max = Math.max(max, Math.min(val.length, maxCol));
89
+ }
90
+ widths.set(key, max);
91
+ }
92
+ // Header
93
+ const header = keys.map((k) => c.bold(k.padEnd(widths.get(k)))).join(" ");
94
+ const separator = keys.map((k) => "─".repeat(widths.get(k))).join("──");
95
+ // Rows
96
+ const lines = rows.map((row) => keys
97
+ .map((k) => {
98
+ const val = stringify(row[k]);
99
+ const display = val.length > maxCol ? `${val.slice(0, maxCol - 1)}…` : val;
100
+ return display.padEnd(widths.get(k));
101
+ })
102
+ .join(" "));
103
+ return [header, separator, ...lines].join("\n");
104
+ }
105
+ /** Convert a value to a display string */
106
+ function stringify(val) {
107
+ if (val === null || val === undefined)
108
+ return "NULL";
109
+ if (typeof val === "object") {
110
+ if (val instanceof Date)
111
+ return val.toISOString();
112
+ // BigQuery returns { value: "..." } for some types
113
+ if ("value" in val && Object.keys(val).length === 1) {
114
+ return String(val.value);
115
+ }
116
+ return JSON.stringify(val);
117
+ }
118
+ return String(val);
119
+ }
120
+ /** Format rows as CSV */
121
+ export function csv(rows) {
122
+ if (rows.length === 0)
123
+ return "";
124
+ const keys = Object.keys(rows[0]);
125
+ const header = keys.map(csvEscape).join(",");
126
+ const lines = rows.map((row) => keys.map((k) => csvEscape(stringify(row[k]))).join(","));
127
+ return [header, ...lines].join("\n");
128
+ }
129
+ function csvEscape(val) {
130
+ if (val.includes(",") || val.includes('"') || val.includes("\n")) {
131
+ return `"${val.replace(/"/g, '""')}"`;
132
+ }
133
+ return val;
134
+ }
135
+ /** Print a labeled key-value section */
136
+ export function kvLine(label, value, color) {
137
+ const colorFn = color ?? ((s) => s);
138
+ return ` ${c.dim(label.padEnd(14))} ${colorFn(value)}`;
139
+ }
@@ -0,0 +1,56 @@
1
+ import type { CookieJar } from "../cookies/index.js";
2
+ /**
3
+ * Simple cookie-aware HTTP client.
4
+ *
5
+ * Wraps the global `fetch` (Bun's native one) with two extras:
6
+ * - Attaches a `Cookie:` header from a CookieJar before the request.
7
+ * - Persists `Set-Cookie` responses back into the same jar.
8
+ *
9
+ * Used by the `fetch` command and other tooling that wants to share session
10
+ * state with `browse`.
11
+ */
12
+ export interface FetchOptions {
13
+ /** HTTP method. Default GET. */
14
+ method?: string;
15
+ /** Request body. Strings/Buffers/Streams pass through to fetch directly. */
16
+ body?: BodyInit | null;
17
+ /** Extra headers (merged with auto-added Cookie). */
18
+ headers?: Record<string, string>;
19
+ /**
20
+ * Optional CookieJar. When provided:
21
+ * - Matching cookies become a Cookie header.
22
+ * - Set-Cookie response headers are parsed and merged into the jar.
23
+ * Pass `null` (or omit) to disable.
24
+ */
25
+ jar?: CookieJar | null;
26
+ /** Optional override for redirect handling. Default `'follow'`. */
27
+ redirect?: RequestRedirect;
28
+ /** AbortSignal for timeout/cancel control. */
29
+ signal?: AbortSignal;
30
+ /**
31
+ * Optional callback that returns extra headers to attach based on the
32
+ * target URL. Consumers can inject extra HTTP headers per-URL via this
33
+ * callback (e.g., a Cloudflare-bypass header for specific zones).
34
+ * Caller-provided explicit headers always win; auto-attached values
35
+ * only land when the key isn't already set.
36
+ */
37
+ extraHeaders?: (url: string) => Record<string, string>;
38
+ }
39
+ export interface FetchResult {
40
+ status: number;
41
+ statusText: string;
42
+ url: string;
43
+ headers: Record<string, string>;
44
+ body: string;
45
+ /** Number of cookies persisted back into the jar (0 if no jar passed). */
46
+ cookiesSaved: number;
47
+ }
48
+ /**
49
+ * Fetch a URL with optional cookie-jar attach + persist.
50
+ *
51
+ * Returns the response body as a string (callers handle JSON parsing).
52
+ * Streams aren't supported; this is a CLI helper, not a streaming HTTP
53
+ * client. Use Bun's `fetch` directly for streaming workloads.
54
+ */
55
+ export declare function fetchWithJar(url: string, opts?: FetchOptions): Promise<FetchResult>;
56
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/http/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;;;;;GASG;AAEH,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAsD7F"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Fetch a URL with optional cookie-jar attach + persist.
3
+ *
4
+ * Returns the response body as a string (callers handle JSON parsing).
5
+ * Streams aren't supported; this is a CLI helper, not a streaming HTTP
6
+ * client. Use Bun's `fetch` directly for streaming workloads.
7
+ */
8
+ export async function fetchWithJar(url, opts = {}) {
9
+ const headers = { ...(opts.headers ?? {}) };
10
+ if (opts.jar) {
11
+ const cookieHeader = opts.jar.header(url);
12
+ if (cookieHeader && !headers.Cookie && !headers.cookie) {
13
+ headers.Cookie = cookieHeader;
14
+ }
15
+ }
16
+ // Caller-provided extraHeaders callback (e.g., for Cloudflare-bypass or
17
+ // custom auth headers). Caller-supplied explicit headers always win.
18
+ if (opts.extraHeaders) {
19
+ for (const [k, v] of Object.entries(opts.extraHeaders(url))) {
20
+ if (!(k in headers) && !(k.toLowerCase() in headers))
21
+ headers[k] = v;
22
+ }
23
+ }
24
+ const response = await fetch(url, {
25
+ method: opts.method ?? "GET",
26
+ body: opts.body,
27
+ headers,
28
+ redirect: opts.redirect ?? "follow",
29
+ signal: opts.signal,
30
+ });
31
+ let cookiesSaved = 0;
32
+ if (opts.jar) {
33
+ const setCookieHeaders = collectSetCookie(response.headers);
34
+ if (setCookieHeaders.length > 0) {
35
+ const parsedHost = new URL(response.url).hostname;
36
+ const cookies = setCookieHeaders
37
+ .map((sc) => parseSetCookie(sc, parsedHost))
38
+ .filter((c) => c !== null);
39
+ for (const cookie of cookies) {
40
+ opts.jar.set(cookie);
41
+ }
42
+ cookiesSaved = cookies.length;
43
+ }
44
+ }
45
+ const headerObj = {};
46
+ response.headers.forEach((value, key) => {
47
+ headerObj[key] = value;
48
+ });
49
+ return {
50
+ status: response.status,
51
+ statusText: response.statusText,
52
+ url: response.url,
53
+ headers: headerObj,
54
+ body: await response.text(),
55
+ cookiesSaved,
56
+ };
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Set-Cookie parsing
60
+ // ---------------------------------------------------------------------------
61
+ //
62
+ // `fetch` joins multiple Set-Cookie headers with `, ` per the spec, but that
63
+ // collides with the comma-separated date format in `Expires=`. We use the
64
+ // dual-mode approach: prefer the `getSetCookie()` method when available
65
+ // (Node 20+, Bun 1.0+) and fall back to manual splitting otherwise.
66
+ function collectSetCookie(headers) {
67
+ const h = headers;
68
+ if (typeof h.getSetCookie === "function") {
69
+ return h.getSetCookie();
70
+ }
71
+ const raw = headers.get("set-cookie");
72
+ return raw ? splitSetCookieHeader(raw) : [];
73
+ }
74
+ function splitSetCookieHeader(raw) {
75
+ // Splits on ", " that precedes a new cookie (heuristic: a token followed
76
+ // by `=`), avoiding date-internal commas like `Expires=Wed, 21 Oct …`.
77
+ const parts = [];
78
+ let depth = 0;
79
+ let buf = "";
80
+ for (let i = 0; i < raw.length; i++) {
81
+ const ch = raw[i];
82
+ if (ch === "," && depth === 0) {
83
+ const ahead = raw.slice(i + 1).trimStart();
84
+ if (/^[A-Za-z0-9_!#$%&'*+\-.^`|~]+=/.test(ahead)) {
85
+ parts.push(buf.trim());
86
+ buf = "";
87
+ continue;
88
+ }
89
+ }
90
+ if (ch === "=")
91
+ depth++;
92
+ if (ch === ";")
93
+ depth = 0;
94
+ buf += ch;
95
+ }
96
+ if (buf.trim())
97
+ parts.push(buf.trim());
98
+ return parts;
99
+ }
100
+ function parseSetCookie(raw, defaultDomain) {
101
+ const parts = raw.split(";").map((p) => p.trim());
102
+ if (parts.length === 0)
103
+ return null;
104
+ const first = parts[0];
105
+ if (!first)
106
+ return null;
107
+ const eq = first.indexOf("=");
108
+ if (eq < 0)
109
+ return null;
110
+ const name = first.slice(0, eq).trim();
111
+ const value = first.slice(eq + 1).trim();
112
+ if (!name)
113
+ return null;
114
+ const cookie = {
115
+ name,
116
+ value,
117
+ domain: defaultDomain,
118
+ path: "/",
119
+ expires: -1,
120
+ httpOnly: false,
121
+ secure: false,
122
+ session: true,
123
+ size: name.length + value.length,
124
+ };
125
+ for (const attr of parts.slice(1)) {
126
+ const lower = attr.toLowerCase();
127
+ if (lower.startsWith("domain=")) {
128
+ const d = attr.slice(7).trim();
129
+ cookie.domain = d.startsWith(".") ? d : `.${d}`;
130
+ }
131
+ else if (lower.startsWith("path=")) {
132
+ cookie.path = attr.slice(5).trim() || "/";
133
+ }
134
+ else if (lower.startsWith("expires=")) {
135
+ const ts = Date.parse(attr.slice(8).trim());
136
+ if (!Number.isNaN(ts)) {
137
+ cookie.expires = Math.floor(ts / 1000);
138
+ cookie.session = false;
139
+ }
140
+ }
141
+ else if (lower.startsWith("max-age=")) {
142
+ const seconds = Number.parseInt(attr.slice(8).trim(), 10);
143
+ if (!Number.isNaN(seconds)) {
144
+ cookie.expires = Math.floor(Date.now() / 1000) + seconds;
145
+ cookie.session = false;
146
+ }
147
+ }
148
+ else if (lower === "secure") {
149
+ cookie.secure = true;
150
+ }
151
+ else if (lower === "httponly") {
152
+ cookie.httpOnly = true;
153
+ }
154
+ else if (lower.startsWith("samesite=")) {
155
+ const v = attr.slice(9).trim();
156
+ cookie.sameSite = v.charAt(0).toUpperCase() + v.slice(1).toLowerCase();
157
+ }
158
+ }
159
+ return cookie;
160
+ }
@@ -0,0 +1,2 @@
1
+ export { type FetchOptions, type FetchResult, fetchWithJar } from "./client.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/http/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ export { fetchWithJar } from "./client.js";
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Agent persona identity registry: per-agent durable UUIDs.
3
+ *
4
+ * The coord layer has two id concepts that get confused:
5
+ * - `instance_id`: Claude Code session UUID (fresh per session). Lives at
6
+ * `.harnery/active/<instance_id>.json` as the heartbeat filename.
7
+ * - `agent_id` (this module): durable per-AGENT-PERSONA UUID. Stable
8
+ * across sessions; same UUID for every Maya session, regardless of
9
+ * how many times she restarts Claude Code.
10
+ *
11
+ * Storage: `.harnery/identities/<agent_id>.json`, one file per persona.
12
+ * The filename IS the id so reverse lookup is O(1) by id; forward lookup
13
+ * by name is a scan (small directory, ~100 personas tops in practice).
14
+ *
15
+ * Used as the canonical identifier in:
16
+ * - Council manifests (`created_by_id`, `steward_id`, `member_ids[]`)
17
+ * - Council body filenames (`<agent_id>.md` not `<name>.md`)
18
+ * - Session events ndjson (new `agent_id` field alongside `agent_name`)
19
+ * - Heartbeats (new `agent_id` field; existing CC subagent-call id
20
+ * renamed to `subagent_call_id`)
21
+ */
22
+ export declare const IDENTITY_SCHEMA_VERSION: 1;
23
+ export interface AgentIdentity {
24
+ schema_version: 1;
25
+ /** Persistent persona UUID. v4. */
26
+ agent_id: string;
27
+ /** Current display name (e.g. "Maya", without the "agent-" prefix). */
28
+ name: string;
29
+ /** Prior names this identity has been known by. Updated by renameIdentity(). */
30
+ aliases: Array<{
31
+ name: string;
32
+ retired_at: string;
33
+ }>;
34
+ /** UTC ISO-8601 timestamp of first mint. */
35
+ created_at: string;
36
+ }
37
+ /** Strip an "agent-" prefix if present. The registry stores bare names. */
38
+ export declare function bareName(raw: string): string;
39
+ /** Re-add the "agent-" prefix for display contexts. */
40
+ export declare function displayName(name: string): string;
41
+ /** Read one identity by id. Null if missing. */
42
+ export declare function lookupById(agentId: string): AgentIdentity | null;
43
+ /** Read one identity by display name (case-insensitive on bare name).
44
+ * Scans the directory; O(N) on identity count. */
45
+ export declare function lookupByName(name: string): AgentIdentity | null;
46
+ /** All known identities, sorted by created_at ascending. */
47
+ export declare function listIdentities(): AgentIdentity[];
48
+ /**
49
+ * Find an identity by name, or mint one. Returns the resolved identity.
50
+ * Idempotent: calling twice with the same name returns the same record.
51
+ *
52
+ * Mint path: generates a fresh uuid v4, writes the file atomically (tmp +
53
+ * rename), returns the new identity. Race-safe: if two processes mint
54
+ * simultaneously, both files land (different ids), but lookupByName will
55
+ * surface whichever happened to be read first; the second is orphaned.
56
+ * For agent personas (added at human cadence) this race is theoretical.
57
+ */
58
+ export declare function ensureIdentity(name: string): AgentIdentity;
59
+ /** Persist an identity (tmp + rename). Creates the dir if missing. */
60
+ export declare function writeIdentity(id: AgentIdentity): void;
61
+ /**
62
+ * Rename an existing identity. The prior name lands in aliases[] so name
63
+ * lookup still resolves correctly. The agent_id is stable across renames,
64
+ * which is the whole point of the registry.
65
+ */
66
+ export declare function renameIdentity(agentId: string, newName: string): AgentIdentity;
67
+ /**
68
+ * Resolve a string to an agent_id. Accepts:
69
+ * - A UUID (already an id), verified to exist in registry
70
+ * - A display name (e.g. "agent-Maya" or "Maya"), resolved via lookupByName
71
+ * Returns null when the input is neither a known id nor a known name.
72
+ *
73
+ * Does NOT mint. Callers that want mint-on-miss should call ensureIdentity()
74
+ * with a name, then use the returned agent_id.
75
+ */
76
+ export declare function resolveAgentId(input: string): string | null;
77
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/identities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAeH,eAAO,MAAM,uBAAuB,EAAG,CAAU,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,CAAC,CAAC;IAClB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;CACpB;AAqCD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAMhE;AAED;kDACkD;AAClD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAc/D;AAED,4DAA4D;AAC5D,wBAAgB,cAAc,IAAI,aAAa,EAAE,CAWhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAY1D;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI,CAMrD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAc9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU3D"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Agent persona identity registry: per-agent durable UUIDs.
3
+ *
4
+ * The coord layer has two id concepts that get confused:
5
+ * - `instance_id`: Claude Code session UUID (fresh per session). Lives at
6
+ * `.harnery/active/<instance_id>.json` as the heartbeat filename.
7
+ * - `agent_id` (this module): durable per-AGENT-PERSONA UUID. Stable
8
+ * across sessions; same UUID for every Maya session, regardless of
9
+ * how many times she restarts Claude Code.
10
+ *
11
+ * Storage: `.harnery/identities/<agent_id>.json`, one file per persona.
12
+ * The filename IS the id so reverse lookup is O(1) by id; forward lookup
13
+ * by name is a scan (small directory, ~100 personas tops in practice).
14
+ *
15
+ * Used as the canonical identifier in:
16
+ * - Council manifests (`created_by_id`, `steward_id`, `member_ids[]`)
17
+ * - Council body filenames (`<agent_id>.md` not `<name>.md`)
18
+ * - Session events ndjson (new `agent_id` field alongside `agent_name`)
19
+ * - Heartbeats (new `agent_id` field; existing CC subagent-call id
20
+ * renamed to `subagent_call_id`)
21
+ */
22
+ import { randomUUID } from "node:crypto";
23
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
24
+ import { resolve } from "node:path";
25
+ import { monorepoRoot } from "../../core/agents/index.js";
26
+ export const IDENTITY_SCHEMA_VERSION = 1;
27
+ function identitiesDir() {
28
+ const root = monorepoRoot();
29
+ if (!root)
30
+ return null;
31
+ return resolve(root, ".harnery", "identities");
32
+ }
33
+ function ensureDir() {
34
+ const dir = identitiesDir();
35
+ if (!dir)
36
+ throw new Error("not in an agent session; no monorepo root");
37
+ if (!existsSync(dir))
38
+ mkdirSync(dir, { recursive: true });
39
+ return dir;
40
+ }
41
+ function identityPath(agentId) {
42
+ return resolve(ensureDir(), `${agentId}.json`);
43
+ }
44
+ function nowIso() {
45
+ return new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
46
+ }
47
+ function readIdentityFile(path) {
48
+ try {
49
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
50
+ if (parsed.schema_version !== IDENTITY_SCHEMA_VERSION) {
51
+ throw new Error(`identity ${path}: unsupported schema_version=${parsed.schema_version} (expected ${IDENTITY_SCHEMA_VERSION})`);
52
+ }
53
+ return parsed;
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ /** Strip an "agent-" prefix if present. The registry stores bare names. */
60
+ export function bareName(raw) {
61
+ const trimmed = raw.trim();
62
+ return trimmed.startsWith("agent-") ? trimmed.slice("agent-".length) : trimmed;
63
+ }
64
+ /** Re-add the "agent-" prefix for display contexts. */
65
+ export function displayName(name) {
66
+ return name.startsWith("agent-") ? name : `agent-${name}`;
67
+ }
68
+ /** Read one identity by id. Null if missing. */
69
+ export function lookupById(agentId) {
70
+ const dir = identitiesDir();
71
+ if (!dir)
72
+ return null;
73
+ const fp = resolve(dir, `${agentId}.json`);
74
+ if (!existsSync(fp))
75
+ return null;
76
+ return readIdentityFile(fp);
77
+ }
78
+ /** Read one identity by display name (case-insensitive on bare name).
79
+ * Scans the directory; O(N) on identity count. */
80
+ export function lookupByName(name) {
81
+ const dir = identitiesDir();
82
+ if (!dir || !existsSync(dir))
83
+ return null;
84
+ const wanted = bareName(name).toLowerCase();
85
+ for (const f of readdirSync(dir)) {
86
+ if (!f.endsWith(".json"))
87
+ continue;
88
+ const id = readIdentityFile(resolve(dir, f));
89
+ if (!id)
90
+ continue;
91
+ if (id.name.toLowerCase() === wanted)
92
+ return id;
93
+ for (const alias of id.aliases) {
94
+ if (alias.name.toLowerCase() === wanted)
95
+ return id;
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+ /** All known identities, sorted by created_at ascending. */
101
+ export function listIdentities() {
102
+ const dir = identitiesDir();
103
+ if (!dir || !existsSync(dir))
104
+ return [];
105
+ const out = [];
106
+ for (const f of readdirSync(dir)) {
107
+ if (!f.endsWith(".json"))
108
+ continue;
109
+ const id = readIdentityFile(resolve(dir, f));
110
+ if (id)
111
+ out.push(id);
112
+ }
113
+ out.sort((a, b) => a.created_at.localeCompare(b.created_at));
114
+ return out;
115
+ }
116
+ /**
117
+ * Find an identity by name, or mint one. Returns the resolved identity.
118
+ * Idempotent: calling twice with the same name returns the same record.
119
+ *
120
+ * Mint path: generates a fresh uuid v4, writes the file atomically (tmp +
121
+ * rename), returns the new identity. Race-safe: if two processes mint
122
+ * simultaneously, both files land (different ids), but lookupByName will
123
+ * surface whichever happened to be read first; the second is orphaned.
124
+ * For agent personas (added at human cadence) this race is theoretical.
125
+ */
126
+ export function ensureIdentity(name) {
127
+ const existing = lookupByName(name);
128
+ if (existing)
129
+ return existing;
130
+ const id = {
131
+ schema_version: IDENTITY_SCHEMA_VERSION,
132
+ agent_id: randomUUID(),
133
+ name: bareName(name),
134
+ aliases: [],
135
+ created_at: nowIso(),
136
+ };
137
+ writeIdentity(id);
138
+ return id;
139
+ }
140
+ /** Persist an identity (tmp + rename). Creates the dir if missing. */
141
+ export function writeIdentity(id) {
142
+ ensureDir();
143
+ const fp = identityPath(id.agent_id);
144
+ const tmp = `${fp}.tmp.${process.pid}`;
145
+ writeFileSync(tmp, `${JSON.stringify(id, null, 2)}\n`, "utf8");
146
+ renameSync(tmp, fp);
147
+ }
148
+ /**
149
+ * Rename an existing identity. The prior name lands in aliases[] so name
150
+ * lookup still resolves correctly. The agent_id is stable across renames,
151
+ * which is the whole point of the registry.
152
+ */
153
+ export function renameIdentity(agentId, newName) {
154
+ const existing = lookupById(agentId);
155
+ if (!existing) {
156
+ throw new Error(`renameIdentity: no identity matching '${agentId}'`);
157
+ }
158
+ const bare = bareName(newName);
159
+ if (existing.name === bare)
160
+ return existing;
161
+ const next = {
162
+ ...existing,
163
+ name: bare,
164
+ aliases: [...existing.aliases, { name: existing.name, retired_at: nowIso() }],
165
+ };
166
+ writeIdentity(next);
167
+ return next;
168
+ }
169
+ /**
170
+ * Resolve a string to an agent_id. Accepts:
171
+ * - A UUID (already an id), verified to exist in registry
172
+ * - A display name (e.g. "agent-Maya" or "Maya"), resolved via lookupByName
173
+ * Returns null when the input is neither a known id nor a known name.
174
+ *
175
+ * Does NOT mint. Callers that want mint-on-miss should call ensureIdentity()
176
+ * with a name, then use the returned agent_id.
177
+ */
178
+ export function resolveAgentId(input) {
179
+ const trimmed = input.trim();
180
+ if (!trimmed)
181
+ return null;
182
+ // UUID shape check, relaxed; we only need the lookupById to confirm.
183
+ if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(trimmed)) {
184
+ const byId = lookupById(trimmed);
185
+ if (byId)
186
+ return byId.agent_id;
187
+ }
188
+ const byName = lookupByName(trimmed);
189
+ return byName ? byName.agent_id : null;
190
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Resolve a human-friendly label for the current machine. Used to tag
3
+ * coordination artifacts (scratch-doc headers, session telemetry) by the host
4
+ * they originated on.
5
+ *
6
+ * Precedence (first non-empty wins):
7
+ * 1. HARNERY_MACHINE env var: transient / per-launch / CI override
8
+ * 2. ~/.config/harnery/machine file: persistent, harness-neutral identity
9
+ * 3. os.hostname() (normalized): automatic floor; never empty
10
+ *
11
+ * The env var sits on top for ad-hoc overrides; the file is the durable home for
12
+ * a machine's name (it survives across Claude Code / Cursor / Codex and GUI
13
+ * launches that don't inherit a shell rc); hostname guarantees a real answer
14
+ * with zero configuration.
15
+ */
16
+ export declare function resolveMachineLabel(): string;
17
+ /** Absolute path of the machine-label file, honoring XDG_CONFIG_HOME. */
18
+ export declare function machineFilePath(): string | null;
19
+ //# sourceMappingURL=machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../src/lib/machine.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAQ5C;AAED,yEAAyE;AACzE,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAK/C"}