@ashlr/hub 2.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 (477) hide show
  1. package/CHANGELOG.md +1158 -0
  2. package/LICENSE +21 -0
  3. package/README.md +833 -0
  4. package/bin/ashlr +8 -0
  5. package/dist/api/core.d.ts +28 -0
  6. package/dist/api/core.js +42 -0
  7. package/dist/api/core.js.map +1 -0
  8. package/dist/api/index.d.ts +9 -0
  9. package/dist/api/index.js +9 -0
  10. package/dist/api/index.js.map +1 -0
  11. package/dist/api/plugin.d.ts +12 -0
  12. package/dist/api/plugin.js +13 -0
  13. package/dist/api/plugin.js.map +1 -0
  14. package/dist/api/types.d.ts +9 -0
  15. package/dist/api/types.js +9 -0
  16. package/dist/api/types.js.map +1 -0
  17. package/dist/cli/args.d.ts +20 -0
  18. package/dist/cli/args.js +23 -0
  19. package/dist/cli/args.js.map +1 -0
  20. package/dist/cli/ask.d.ts +22 -0
  21. package/dist/cli/ask.js +240 -0
  22. package/dist/cli/ask.js.map +1 -0
  23. package/dist/cli/audit.d.ts +26 -0
  24. package/dist/cli/audit.js +199 -0
  25. package/dist/cli/audit.js.map +1 -0
  26. package/dist/cli/backlog.d.ts +26 -0
  27. package/dist/cli/backlog.js +322 -0
  28. package/dist/cli/backlog.js.map +1 -0
  29. package/dist/cli/completions.d.ts +18 -0
  30. package/dist/cli/completions.js +156 -0
  31. package/dist/cli/completions.js.map +1 -0
  32. package/dist/cli/daemon.d.ts +31 -0
  33. package/dist/cli/daemon.js +334 -0
  34. package/dist/cli/daemon.js.map +1 -0
  35. package/dist/cli/demo-sandbox.d.ts +78 -0
  36. package/dist/cli/demo-sandbox.js +227 -0
  37. package/dist/cli/demo-sandbox.js.map +1 -0
  38. package/dist/cli/demo.d.ts +76 -0
  39. package/dist/cli/demo.js +285 -0
  40. package/dist/cli/demo.js.map +1 -0
  41. package/dist/cli/digest.d.ts +46 -0
  42. package/dist/cli/digest.js +352 -0
  43. package/dist/cli/digest.js.map +1 -0
  44. package/dist/cli/doctor-init.d.ts +28 -0
  45. package/dist/cli/doctor-init.js +335 -0
  46. package/dist/cli/doctor-init.js.map +1 -0
  47. package/dist/cli/genome.d.ts +62 -0
  48. package/dist/cli/genome.js +1061 -0
  49. package/dist/cli/genome.js.map +1 -0
  50. package/dist/cli/gh.d.ts +27 -0
  51. package/dist/cli/gh.js +322 -0
  52. package/dist/cli/gh.js.map +1 -0
  53. package/dist/cli/goals.d.ts +55 -0
  54. package/dist/cli/goals.js +667 -0
  55. package/dist/cli/goals.js.map +1 -0
  56. package/dist/cli/health.d.ts +56 -0
  57. package/dist/cli/health.js +407 -0
  58. package/dist/cli/health.js.map +1 -0
  59. package/dist/cli/help.d.ts +51 -0
  60. package/dist/cli/help.js +436 -0
  61. package/dist/cli/help.js.map +1 -0
  62. package/dist/cli/inbox.d.ts +28 -0
  63. package/dist/cli/inbox.js +589 -0
  64. package/dist/cli/inbox.js.map +1 -0
  65. package/dist/cli/index.d.ts +41 -0
  66. package/dist/cli/index.js +1208 -0
  67. package/dist/cli/index.js.map +1 -0
  68. package/dist/cli/knowledge.d.ts +33 -0
  69. package/dist/cli/knowledge.js +575 -0
  70. package/dist/cli/knowledge.js.map +1 -0
  71. package/dist/cli/mcp.d.ts +26 -0
  72. package/dist/cli/mcp.js +487 -0
  73. package/dist/cli/mcp.js.map +1 -0
  74. package/dist/cli/models.d.ts +26 -0
  75. package/dist/cli/models.js +435 -0
  76. package/dist/cli/models.js.map +1 -0
  77. package/dist/cli/new.d.ts +32 -0
  78. package/dist/cli/new.js +565 -0
  79. package/dist/cli/new.js.map +1 -0
  80. package/dist/cli/notify.d.ts +20 -0
  81. package/dist/cli/notify.js +188 -0
  82. package/dist/cli/notify.js.map +1 -0
  83. package/dist/cli/onboard.d.ts +85 -0
  84. package/dist/cli/onboard.js +305 -0
  85. package/dist/cli/onboard.js.map +1 -0
  86. package/dist/cli/open.d.ts +38 -0
  87. package/dist/cli/open.js +86 -0
  88. package/dist/cli/open.js.map +1 -0
  89. package/dist/cli/orient.d.ts +14 -0
  90. package/dist/cli/orient.js +110 -0
  91. package/dist/cli/orient.js.map +1 -0
  92. package/dist/cli/picker.d.ts +21 -0
  93. package/dist/cli/picker.js +177 -0
  94. package/dist/cli/picker.js.map +1 -0
  95. package/dist/cli/plugins.d.ts +21 -0
  96. package/dist/cli/plugins.js +394 -0
  97. package/dist/cli/plugins.js.map +1 -0
  98. package/dist/cli/preflight.d.ts +29 -0
  99. package/dist/cli/preflight.js +131 -0
  100. package/dist/cli/preflight.js.map +1 -0
  101. package/dist/cli/pulse.d.ts +26 -0
  102. package/dist/cli/pulse.js +482 -0
  103. package/dist/cli/pulse.js.map +1 -0
  104. package/dist/cli/reflect.d.ts +42 -0
  105. package/dist/cli/reflect.js +381 -0
  106. package/dist/cli/reflect.js.map +1 -0
  107. package/dist/cli/run.d.ts +29 -0
  108. package/dist/cli/run.js +687 -0
  109. package/dist/cli/run.js.map +1 -0
  110. package/dist/cli/sandbox.d.ts +20 -0
  111. package/dist/cli/sandbox.js +345 -0
  112. package/dist/cli/sandbox.js.map +1 -0
  113. package/dist/cli/seams.d.ts +41 -0
  114. package/dist/cli/seams.js +167 -0
  115. package/dist/cli/seams.js.map +1 -0
  116. package/dist/cli/serve.d.ts +25 -0
  117. package/dist/cli/serve.js +249 -0
  118. package/dist/cli/serve.js.map +1 -0
  119. package/dist/cli/ship.d.ts +33 -0
  120. package/dist/cli/ship.js +433 -0
  121. package/dist/cli/ship.js.map +1 -0
  122. package/dist/cli/spec.d.ts +19 -0
  123. package/dist/cli/spec.js +478 -0
  124. package/dist/cli/spec.js.map +1 -0
  125. package/dist/cli/swarm.d.ts +42 -0
  126. package/dist/cli/swarm.js +1365 -0
  127. package/dist/cli/swarm.js.map +1 -0
  128. package/dist/cli/telemetry.d.ts +26 -0
  129. package/dist/cli/telemetry.js +364 -0
  130. package/dist/cli/telemetry.js.map +1 -0
  131. package/dist/cli/tui.d.ts +17 -0
  132. package/dist/cli/tui.js +52 -0
  133. package/dist/cli/tui.js.map +1 -0
  134. package/dist/cli/ui.d.ts +53 -0
  135. package/dist/cli/ui.js +66 -0
  136. package/dist/cli/ui.js.map +1 -0
  137. package/dist/cli/update.d.ts +38 -0
  138. package/dist/cli/update.js +682 -0
  139. package/dist/cli/update.js.map +1 -0
  140. package/dist/cli/vercel.d.ts +20 -0
  141. package/dist/cli/vercel.js +193 -0
  142. package/dist/cli/vercel.js.map +1 -0
  143. package/dist/cli/verify-safety.d.ts +96 -0
  144. package/dist/cli/verify-safety.js +509 -0
  145. package/dist/cli/verify-safety.js.map +1 -0
  146. package/dist/cli/wire.d.ts +22 -0
  147. package/dist/cli/wire.js +205 -0
  148. package/dist/cli/wire.js.map +1 -0
  149. package/dist/core/classify.d.ts +51 -0
  150. package/dist/core/classify.js +450 -0
  151. package/dist/core/classify.js.map +1 -0
  152. package/dist/core/config.d.ts +63 -0
  153. package/dist/core/config.js +474 -0
  154. package/dist/core/config.js.map +1 -0
  155. package/dist/core/daemon/loop.d.ts +74 -0
  156. package/dist/core/daemon/loop.js +618 -0
  157. package/dist/core/daemon/loop.js.map +1 -0
  158. package/dist/core/daemon/state.d.ts +66 -0
  159. package/dist/core/daemon/state.js +197 -0
  160. package/dist/core/daemon/state.js.map +1 -0
  161. package/dist/core/dashboard.d.ts +40 -0
  162. package/dist/core/dashboard.js +463 -0
  163. package/dist/core/dashboard.js.map +1 -0
  164. package/dist/core/digest/build.d.ts +51 -0
  165. package/dist/core/digest/build.js +230 -0
  166. package/dist/core/digest/build.js.map +1 -0
  167. package/dist/core/digest/deliver.d.ts +47 -0
  168. package/dist/core/digest/deliver.js +230 -0
  169. package/dist/core/digest/deliver.js.map +1 -0
  170. package/dist/core/digest/store.d.ts +57 -0
  171. package/dist/core/digest/store.js +223 -0
  172. package/dist/core/digest/store.js.map +1 -0
  173. package/dist/core/doctor-fix.d.ts +21 -0
  174. package/dist/core/doctor-fix.js +440 -0
  175. package/dist/core/doctor-fix.js.map +1 -0
  176. package/dist/core/doctor.d.ts +18 -0
  177. package/dist/core/doctor.js +806 -0
  178. package/dist/core/doctor.js.map +1 -0
  179. package/dist/core/env-bridge.d.ts +64 -0
  180. package/dist/core/env-bridge.js +103 -0
  181. package/dist/core/env-bridge.js.map +1 -0
  182. package/dist/core/genome/capture.d.ts +49 -0
  183. package/dist/core/genome/capture.js +352 -0
  184. package/dist/core/genome/capture.js.map +1 -0
  185. package/dist/core/genome/consolidate.d.ts +38 -0
  186. package/dist/core/genome/consolidate.js +426 -0
  187. package/dist/core/genome/consolidate.js.map +1 -0
  188. package/dist/core/genome/export.d.ts +29 -0
  189. package/dist/core/genome/export.js +102 -0
  190. package/dist/core/genome/export.js.map +1 -0
  191. package/dist/core/genome/playbook.d.ts +33 -0
  192. package/dist/core/genome/playbook.js +320 -0
  193. package/dist/core/genome/playbook.js.map +1 -0
  194. package/dist/core/genome/recall.d.ts +45 -0
  195. package/dist/core/genome/recall.js +293 -0
  196. package/dist/core/genome/recall.js.map +1 -0
  197. package/dist/core/genome/store.d.ts +62 -0
  198. package/dist/core/genome/store.js +711 -0
  199. package/dist/core/genome/store.js.map +1 -0
  200. package/dist/core/git.d.ts +34 -0
  201. package/dist/core/git.js +115 -0
  202. package/dist/core/git.js.map +1 -0
  203. package/dist/core/goals/advance.d.ts +82 -0
  204. package/dist/core/goals/advance.js +263 -0
  205. package/dist/core/goals/advance.js.map +1 -0
  206. package/dist/core/goals/planner.d.ts +58 -0
  207. package/dist/core/goals/planner.js +233 -0
  208. package/dist/core/goals/planner.js.map +1 -0
  209. package/dist/core/goals/store.d.ts +128 -0
  210. package/dist/core/goals/store.js +442 -0
  211. package/dist/core/goals/store.js.map +1 -0
  212. package/dist/core/inbox/apply.d.ts +36 -0
  213. package/dist/core/inbox/apply.js +407 -0
  214. package/dist/core/inbox/apply.js.map +1 -0
  215. package/dist/core/inbox/notify-proposal.d.ts +13 -0
  216. package/dist/core/inbox/notify-proposal.js +21 -0
  217. package/dist/core/inbox/notify-proposal.js.map +1 -0
  218. package/dist/core/inbox/store.d.ts +67 -0
  219. package/dist/core/inbox/store.js +258 -0
  220. package/dist/core/inbox/store.js.map +1 -0
  221. package/dist/core/index-engine.d.ts +62 -0
  222. package/dist/core/index-engine.js +486 -0
  223. package/dist/core/index-engine.js.map +1 -0
  224. package/dist/core/integrations/desktop-notify.d.ts +18 -0
  225. package/dist/core/integrations/desktop-notify.js +42 -0
  226. package/dist/core/integrations/desktop-notify.js.map +1 -0
  227. package/dist/core/integrations/editors.d.ts +50 -0
  228. package/dist/core/integrations/editors.js +216 -0
  229. package/dist/core/integrations/editors.js.map +1 -0
  230. package/dist/core/integrations/github.d.ts +66 -0
  231. package/dist/core/integrations/github.js +332 -0
  232. package/dist/core/integrations/github.js.map +1 -0
  233. package/dist/core/integrations/identity.d.ts +29 -0
  234. package/dist/core/integrations/identity.js +359 -0
  235. package/dist/core/integrations/identity.js.map +1 -0
  236. package/dist/core/integrations/notify.d.ts +23 -0
  237. package/dist/core/integrations/notify.js +96 -0
  238. package/dist/core/integrations/notify.js.map +1 -0
  239. package/dist/core/integrations/vercel.d.ts +37 -0
  240. package/dist/core/integrations/vercel.js +192 -0
  241. package/dist/core/integrations/vercel.js.map +1 -0
  242. package/dist/core/knowledge/ask.d.ts +34 -0
  243. package/dist/core/knowledge/ask.js +325 -0
  244. package/dist/core/knowledge/ask.js.map +1 -0
  245. package/dist/core/knowledge/graph.d.ts +51 -0
  246. package/dist/core/knowledge/graph.js +564 -0
  247. package/dist/core/knowledge/graph.js.map +1 -0
  248. package/dist/core/knowledge/index.d.ts +74 -0
  249. package/dist/core/knowledge/index.js +586 -0
  250. package/dist/core/knowledge/index.js.map +1 -0
  251. package/dist/core/learn/playbooks.d.ts +84 -0
  252. package/dist/core/learn/playbooks.js +241 -0
  253. package/dist/core/learn/playbooks.js.map +1 -0
  254. package/dist/core/learn/reflect.d.ts +87 -0
  255. package/dist/core/learn/reflect.js +435 -0
  256. package/dist/core/learn/reflect.js.map +1 -0
  257. package/dist/core/learn/store.d.ts +51 -0
  258. package/dist/core/learn/store.js +165 -0
  259. package/dist/core/learn/store.js.map +1 -0
  260. package/dist/core/learn/tuning.d.ts +48 -0
  261. package/dist/core/learn/tuning.js +201 -0
  262. package/dist/core/learn/tuning.js.map +1 -0
  263. package/dist/core/lifecycle/scaffold.d.ts +43 -0
  264. package/dist/core/lifecycle/scaffold.js +260 -0
  265. package/dist/core/lifecycle/scaffold.js.map +1 -0
  266. package/dist/core/lifecycle/ship.d.ts +48 -0
  267. package/dist/core/lifecycle/ship.js +513 -0
  268. package/dist/core/lifecycle/ship.js.map +1 -0
  269. package/dist/core/lifecycle/templates.d.ts +20 -0
  270. package/dist/core/lifecycle/templates.js +605 -0
  271. package/dist/core/lifecycle/templates.js.map +1 -0
  272. package/dist/core/mcp-gateway.d.ts +59 -0
  273. package/dist/core/mcp-gateway.js +385 -0
  274. package/dist/core/mcp-gateway.js.map +1 -0
  275. package/dist/core/mcp-native.d.ts +53 -0
  276. package/dist/core/mcp-native.js +507 -0
  277. package/dist/core/mcp-native.js.map +1 -0
  278. package/dist/core/mcp-registry.d.ts +36 -0
  279. package/dist/core/mcp-registry.js +180 -0
  280. package/dist/core/mcp-registry.js.map +1 -0
  281. package/dist/core/observability/budget-alert.d.ts +18 -0
  282. package/dist/core/observability/budget-alert.js +90 -0
  283. package/dist/core/observability/budget-alert.js.map +1 -0
  284. package/dist/core/observability/estimate.d.ts +27 -0
  285. package/dist/core/observability/estimate.js +188 -0
  286. package/dist/core/observability/estimate.js.map +1 -0
  287. package/dist/core/observability/forecast.d.ts +19 -0
  288. package/dist/core/observability/forecast.js +101 -0
  289. package/dist/core/observability/forecast.js.map +1 -0
  290. package/dist/core/observability/governance.d.ts +28 -0
  291. package/dist/core/observability/governance.js +101 -0
  292. package/dist/core/observability/governance.js.map +1 -0
  293. package/dist/core/observability/otlp.d.ts +88 -0
  294. package/dist/core/observability/otlp.js +217 -0
  295. package/dist/core/observability/otlp.js.map +1 -0
  296. package/dist/core/observability/rollup.d.ts +35 -0
  297. package/dist/core/observability/rollup.js +311 -0
  298. package/dist/core/observability/rollup.js.map +1 -0
  299. package/dist/core/observability/telemetry-sink.d.ts +63 -0
  300. package/dist/core/observability/telemetry-sink.js +350 -0
  301. package/dist/core/observability/telemetry-sink.js.map +1 -0
  302. package/dist/core/observability/usage-source.d.ts +60 -0
  303. package/dist/core/observability/usage-source.js +347 -0
  304. package/dist/core/observability/usage-source.js.map +1 -0
  305. package/dist/core/onboard.d.ts +27 -0
  306. package/dist/core/onboard.js +288 -0
  307. package/dist/core/onboard.js.map +1 -0
  308. package/dist/core/orient.d.ts +23 -0
  309. package/dist/core/orient.js +135 -0
  310. package/dist/core/orient.js.map +1 -0
  311. package/dist/core/phantom.d.ts +23 -0
  312. package/dist/core/phantom.js +279 -0
  313. package/dist/core/phantom.js.map +1 -0
  314. package/dist/core/plugins/host-api.d.ts +29 -0
  315. package/dist/core/plugins/host-api.js +113 -0
  316. package/dist/core/plugins/host-api.js.map +1 -0
  317. package/dist/core/plugins/integrity.d.ts +36 -0
  318. package/dist/core/plugins/integrity.js +73 -0
  319. package/dist/core/plugins/integrity.js.map +1 -0
  320. package/dist/core/plugins/manifest.d.ts +31 -0
  321. package/dist/core/plugins/manifest.js +316 -0
  322. package/dist/core/plugins/manifest.js.map +1 -0
  323. package/dist/core/plugins/registry.d.ts +87 -0
  324. package/dist/core/plugins/registry.js +415 -0
  325. package/dist/core/plugins/registry.js.map +1 -0
  326. package/dist/core/plugins/types.d.ts +182 -0
  327. package/dist/core/plugins/types.js +40 -0
  328. package/dist/core/plugins/types.js.map +1 -0
  329. package/dist/core/plugins/wrappers.d.ts +40 -0
  330. package/dist/core/plugins/wrappers.js +229 -0
  331. package/dist/core/plugins/wrappers.js.map +1 -0
  332. package/dist/core/portfolio/backlog.d.ts +40 -0
  333. package/dist/core/portfolio/backlog.js +177 -0
  334. package/dist/core/portfolio/backlog.js.map +1 -0
  335. package/dist/core/portfolio/scanners.d.ts +21 -0
  336. package/dist/core/portfolio/scanners.js +600 -0
  337. package/dist/core/portfolio/scanners.js.map +1 -0
  338. package/dist/core/providers.d.ts +34 -0
  339. package/dist/core/providers.js +250 -0
  340. package/dist/core/providers.js.map +1 -0
  341. package/dist/core/quality/conventions.d.ts +35 -0
  342. package/dist/core/quality/conventions.js +267 -0
  343. package/dist/core/quality/conventions.js.map +1 -0
  344. package/dist/core/quality/fixes.d.ts +56 -0
  345. package/dist/core/quality/fixes.js +209 -0
  346. package/dist/core/quality/fixes.js.map +1 -0
  347. package/dist/core/quality/health.d.ts +69 -0
  348. package/dist/core/quality/health.js +350 -0
  349. package/dist/core/quality/health.js.map +1 -0
  350. package/dist/core/quality/store.d.ts +56 -0
  351. package/dist/core/quality/store.js +195 -0
  352. package/dist/core/quality/store.js.map +1 -0
  353. package/dist/core/readiness.d.ts +112 -0
  354. package/dist/core/readiness.js +431 -0
  355. package/dist/core/readiness.js.map +1 -0
  356. package/dist/core/run/agent-loop.d.ts +40 -0
  357. package/dist/core/run/agent-loop.js +291 -0
  358. package/dist/core/run/agent-loop.js.map +1 -0
  359. package/dist/core/run/budget.d.ts +47 -0
  360. package/dist/core/run/budget.js +113 -0
  361. package/dist/core/run/budget.js.map +1 -0
  362. package/dist/core/run/engines.d.ts +75 -0
  363. package/dist/core/run/engines.js +199 -0
  364. package/dist/core/run/engines.js.map +1 -0
  365. package/dist/core/run/model-manager.d.ts +64 -0
  366. package/dist/core/run/model-manager.js +339 -0
  367. package/dist/core/run/model-manager.js.map +1 -0
  368. package/dist/core/run/orchestrator.d.ts +100 -0
  369. package/dist/core/run/orchestrator.js +1515 -0
  370. package/dist/core/run/orchestrator.js.map +1 -0
  371. package/dist/core/run/provider-client.d.ts +46 -0
  372. package/dist/core/run/provider-client.js +796 -0
  373. package/dist/core/run/provider-client.js.map +1 -0
  374. package/dist/core/run/retry.d.ts +19 -0
  375. package/dist/core/run/retry.js +68 -0
  376. package/dist/core/run/retry.js.map +1 -0
  377. package/dist/core/run/router.d.ts +50 -0
  378. package/dist/core/run/router.js +257 -0
  379. package/dist/core/run/router.js.map +1 -0
  380. package/dist/core/run/self-heal.d.ts +52 -0
  381. package/dist/core/run/self-heal.js +181 -0
  382. package/dist/core/run/self-heal.js.map +1 -0
  383. package/dist/core/run/streaming.d.ts +31 -0
  384. package/dist/core/run/streaming.js +122 -0
  385. package/dist/core/run/streaming.js.map +1 -0
  386. package/dist/core/run/verify.d.ts +30 -0
  387. package/dist/core/run/verify.js +204 -0
  388. package/dist/core/run/verify.js.map +1 -0
  389. package/dist/core/sandbox/audit.d.ts +31 -0
  390. package/dist/core/sandbox/audit.js +169 -0
  391. package/dist/core/sandbox/audit.js.map +1 -0
  392. package/dist/core/sandbox/policy.d.ts +61 -0
  393. package/dist/core/sandbox/policy.js +211 -0
  394. package/dist/core/sandbox/policy.js.map +1 -0
  395. package/dist/core/sandbox/worktree.d.ts +175 -0
  396. package/dist/core/sandbox/worktree.js +673 -0
  397. package/dist/core/sandbox/worktree.js.map +1 -0
  398. package/dist/core/seams/backlog.d.ts +47 -0
  399. package/dist/core/seams/backlog.js +47 -0
  400. package/dist/core/seams/backlog.js.map +1 -0
  401. package/dist/core/seams/daemon-coordinator.d.ts +72 -0
  402. package/dist/core/seams/daemon-coordinator.js +76 -0
  403. package/dist/core/seams/daemon-coordinator.js.map +1 -0
  404. package/dist/core/seams/genome.d.ts +45 -0
  405. package/dist/core/seams/genome.js +53 -0
  406. package/dist/core/seams/genome.js.map +1 -0
  407. package/dist/core/seams/identity.d.ts +40 -0
  408. package/dist/core/seams/identity.js +44 -0
  409. package/dist/core/seams/identity.js.map +1 -0
  410. package/dist/core/seams/inbox.d.ts +60 -0
  411. package/dist/core/seams/inbox.js +66 -0
  412. package/dist/core/seams/inbox.js.map +1 -0
  413. package/dist/core/seams/index.d.ts +20 -0
  414. package/dist/core/seams/index.js +21 -0
  415. package/dist/core/seams/index.js.map +1 -0
  416. package/dist/core/seams/portfolio.d.ts +50 -0
  417. package/dist/core/seams/portfolio.js +61 -0
  418. package/dist/core/seams/portfolio.js.map +1 -0
  419. package/dist/core/seams/registry.d.ts +42 -0
  420. package/dist/core/seams/registry.js +128 -0
  421. package/dist/core/seams/registry.js.map +1 -0
  422. package/dist/core/seams/run-swarm.d.ts +66 -0
  423. package/dist/core/seams/run-swarm.js +74 -0
  424. package/dist/core/seams/run-swarm.js.map +1 -0
  425. package/dist/core/seams/types.d.ts +123 -0
  426. package/dist/core/seams/types.js +35 -0
  427. package/dist/core/seams/types.js.map +1 -0
  428. package/dist/core/spec/spec-store.d.ts +62 -0
  429. package/dist/core/spec/spec-store.js +359 -0
  430. package/dist/core/spec/spec-store.js.map +1 -0
  431. package/dist/core/swarm/gate.d.ts +45 -0
  432. package/dist/core/swarm/gate.js +114 -0
  433. package/dist/core/swarm/gate.js.map +1 -0
  434. package/dist/core/swarm/planner.d.ts +32 -0
  435. package/dist/core/swarm/planner.js +293 -0
  436. package/dist/core/swarm/planner.js.map +1 -0
  437. package/dist/core/swarm/rollback.d.ts +56 -0
  438. package/dist/core/swarm/rollback.js +266 -0
  439. package/dist/core/swarm/rollback.js.map +1 -0
  440. package/dist/core/swarm/runner.d.ts +62 -0
  441. package/dist/core/swarm/runner.js +1263 -0
  442. package/dist/core/swarm/runner.js.map +1 -0
  443. package/dist/core/swarm/sign.d.ts +71 -0
  444. package/dist/core/swarm/sign.js +362 -0
  445. package/dist/core/swarm/sign.js.map +1 -0
  446. package/dist/core/swarm/store.d.ts +52 -0
  447. package/dist/core/swarm/store.js +195 -0
  448. package/dist/core/swarm/store.js.map +1 -0
  449. package/dist/core/tidy.d.ts +32 -0
  450. package/dist/core/tidy.js +354 -0
  451. package/dist/core/tidy.js.map +1 -0
  452. package/dist/core/tools-registry.d.ts +16 -0
  453. package/dist/core/tools-registry.js +308 -0
  454. package/dist/core/tools-registry.js.map +1 -0
  455. package/dist/core/types.d.ts +2545 -0
  456. package/dist/core/types.js +9 -0
  457. package/dist/core/types.js.map +1 -0
  458. package/dist/core/web/api.d.ts +53 -0
  459. package/dist/core/web/api.js +698 -0
  460. package/dist/core/web/api.js.map +1 -0
  461. package/dist/core/web/public/app.js +1906 -0
  462. package/dist/core/web/public/index.html +721 -0
  463. package/dist/core/web/public/styles.css +2007 -0
  464. package/dist/core/web/server.d.ts +18 -0
  465. package/dist/core/web/server.js +122 -0
  466. package/dist/core/web/server.js.map +1 -0
  467. package/dist/core/web/static.d.ts +18 -0
  468. package/dist/core/web/static.js +122 -0
  469. package/dist/core/web/static.js.map +1 -0
  470. package/dist/tui/app.d.ts +33 -0
  471. package/dist/tui/app.js +350 -0
  472. package/dist/tui/app.js.map +1 -0
  473. package/dist/tui/render.d.ts +20 -0
  474. package/dist/tui/render.js +558 -0
  475. package/dist/tui/render.js.map +1 -0
  476. package/package.json +80 -0
  477. package/schema/config.schema.json +223 -0
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Swarm persistence store.
3
+ *
4
+ * Provides atomic-ish read/write for SwarmRun records to ~/.ashlr/swarms/.
5
+ * All functions are synchronous (matching the RunState/config store pattern),
6
+ * never throw, and never carry secret values in any logged/persisted output.
7
+ *
8
+ * Layout:
9
+ * ~/.ashlr/swarms/<id>.json — pretty-printed SwarmRun (one file per run)
10
+ *
11
+ * Atomic-ish write strategy: write to a .tmp sibling, then rename over the
12
+ * target. On POSIX this is an atomic rename; on Windows it is best-effort
13
+ * (rename over existing file may fail, in which case we fall back to a direct
14
+ * write). Avoids leaving a partially-written record visible to readers.
15
+ */
16
+ import { homedir } from 'node:os';
17
+ import { join } from 'node:path';
18
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
19
+ // ---------------------------------------------------------------------------
20
+ // Bounded list cap — never read more than this many swarm files at once.
21
+ // Prevents pathological I/O if the directory grows very large.
22
+ // ---------------------------------------------------------------------------
23
+ const MAX_LIST = 200;
24
+ // ---------------------------------------------------------------------------
25
+ // swarmsDir
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Absolute path to the swarms persistence directory: `~/.ashlr/swarms`.
29
+ * Re-resolved from `homedir()` on every call so tests that mutate HOME work.
30
+ */
31
+ export function swarmsDir() {
32
+ return join(homedir(), '.ashlr', 'swarms');
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Internal helpers
36
+ // ---------------------------------------------------------------------------
37
+ /** Ensure the swarms directory exists, silently creating it if needed. */
38
+ function ensureDir(dir) {
39
+ try {
40
+ if (!existsSync(dir)) {
41
+ mkdirSync(dir, { recursive: true });
42
+ }
43
+ }
44
+ catch {
45
+ // Best-effort; if we can't create the dir the subsequent write will fail
46
+ // gracefully in saveSwarm's try/catch.
47
+ }
48
+ }
49
+ /**
50
+ * Return the absolute path for a swarm record by id.
51
+ *
52
+ * Validates the id charset (mirrors orchestrator.ts runFilePath) so the store
53
+ * is self-defending against path traversal / separator injection regardless of
54
+ * how a caller derived the id (e.g. GET /api/swarm/:id). Allowed: word chars,
55
+ * dot, hyphen. Anything else throws.
56
+ */
57
+ function swarmPath(dir, id) {
58
+ if (!/^[\w.-]+$/.test(id)) {
59
+ throw new Error('Invalid swarm id');
60
+ }
61
+ return join(dir, `${id}.json`);
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // saveSwarm
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Persist a SwarmRun record to disk.
68
+ *
69
+ * Strategy:
70
+ * 1. Ensure the swarms directory exists.
71
+ * 2. Serialize to pretty-printed JSON (trailing newline for POSIX hygiene).
72
+ * 3. Write to a `.tmp` sibling file.
73
+ * 4. Rename the `.tmp` over the target path (atomic on POSIX).
74
+ * 5. If the rename fails (e.g. Windows cross-device), fall back to a direct
75
+ * overwrite.
76
+ *
77
+ * Never throws; failures are silently swallowed so a persistence error never
78
+ * crashes the swarm runner mid-execution.
79
+ */
80
+ export function saveSwarm(s) {
81
+ try {
82
+ const dir = swarmsDir();
83
+ ensureDir(dir);
84
+ const target = swarmPath(dir, s.id);
85
+ const tmp = `${target}.tmp`;
86
+ const json = JSON.stringify(s, null, 2) + '\n';
87
+ writeFileSync(tmp, json, 'utf8');
88
+ try {
89
+ renameSync(tmp, target);
90
+ }
91
+ catch {
92
+ // Rename failed (Windows cross-device, or race) — direct overwrite.
93
+ try {
94
+ writeFileSync(target, json, 'utf8');
95
+ }
96
+ catch {
97
+ // Last-resort: swallow; the .tmp may be readable for recovery.
98
+ }
99
+ }
100
+ }
101
+ catch {
102
+ // Never propagate persistence failures to the caller.
103
+ }
104
+ }
105
+ // ---------------------------------------------------------------------------
106
+ // loadSwarm
107
+ // ---------------------------------------------------------------------------
108
+ /**
109
+ * Load and deserialise a single SwarmRun by id.
110
+ *
111
+ * Returns `null` when the record does not exist, cannot be read, or fails to
112
+ * parse as a valid-looking SwarmRun. Never throws.
113
+ */
114
+ export function loadSwarm(id) {
115
+ try {
116
+ const dir = swarmsDir();
117
+ const path = swarmPath(dir, id);
118
+ if (!existsSync(path))
119
+ return null;
120
+ const raw = readFileSync(path, 'utf8');
121
+ const parsed = JSON.parse(raw);
122
+ // Basic shape guard: must be an object with a matching id field.
123
+ if (typeof parsed !== 'object' ||
124
+ parsed === null ||
125
+ Array.isArray(parsed) ||
126
+ parsed['id'] !== id) {
127
+ return null;
128
+ }
129
+ return parsed;
130
+ }
131
+ catch {
132
+ return null;
133
+ }
134
+ }
135
+ // ---------------------------------------------------------------------------
136
+ // listSwarms
137
+ // ---------------------------------------------------------------------------
138
+ /**
139
+ * List all persisted SwarmRun records, sorted by `updatedAt` descending
140
+ * (most-recent first).
141
+ *
142
+ * - Reads at most `MAX_LIST` (200) files to bound I/O on large directories.
143
+ * - Skips `.tmp` sidecars and any file that fails to parse.
144
+ * - Never throws.
145
+ */
146
+ export function listSwarms() {
147
+ try {
148
+ const dir = swarmsDir();
149
+ if (!existsSync(dir))
150
+ return [];
151
+ let entries;
152
+ try {
153
+ entries = readdirSync(dir);
154
+ }
155
+ catch {
156
+ return [];
157
+ }
158
+ // Filter to *.json (exclude .tmp sidecars and other artefacts), then cap.
159
+ const jsonFiles = entries
160
+ .filter((f) => f.endsWith('.json') && !f.endsWith('.tmp.json'))
161
+ .slice(0, MAX_LIST);
162
+ const swarms = [];
163
+ for (const file of jsonFiles) {
164
+ try {
165
+ const raw = readFileSync(join(dir, file), 'utf8');
166
+ const parsed = JSON.parse(raw);
167
+ if (typeof parsed !== 'object' ||
168
+ parsed === null ||
169
+ Array.isArray(parsed)) {
170
+ continue;
171
+ }
172
+ swarms.push(parsed);
173
+ }
174
+ catch {
175
+ // Skip unreadable / malformed records silently.
176
+ }
177
+ }
178
+ // Sort: most-recently-updated first.
179
+ swarms.sort((a, b) => {
180
+ const ta = a.updatedAt ?? '';
181
+ const tb = b.updatedAt ?? '';
182
+ // ISO timestamps sort lexicographically; descending = b before a.
183
+ if (tb > ta)
184
+ return 1;
185
+ if (tb < ta)
186
+ return -1;
187
+ return 0;
188
+ });
189
+ return swarms;
190
+ }
191
+ catch {
192
+ return [];
193
+ }
194
+ }
195
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/core/swarm/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * src/core/tidy.ts
3
+ *
4
+ * Plan and apply tidy moves for loose top-level files on the Desktop root.
5
+ *
6
+ * planTidy() — dry-run; examines only direct children of the Desktop root
7
+ * (the root in cfg.roots that is NOT under github/).
8
+ * Never plans to move: keepers, category folders, symlinks,
9
+ * the github/ dir, or git repos.
10
+ *
11
+ * applyTidy() — execute plan.moves; collision-safe (skip if dest exists or
12
+ * source is already gone); mkdir -p dest dirs as needed.
13
+ */
14
+ import type { AshlrConfig, TidyPlan } from './types.js';
15
+ /**
16
+ * Plan a tidy pass over the Desktop root.
17
+ *
18
+ * Only direct children of the root are examined (depth 1).
19
+ * Moves are first-match-wins against cfg.tidyRules.
20
+ * Items with no matching rule are recorded in skipped[].
21
+ */
22
+ export declare function planTidy(cfg: AshlrConfig): TidyPlan;
23
+ /**
24
+ * Execute a previously computed TidyPlan.
25
+ *
26
+ * For each move:
27
+ * - Create the destination directory (mkdir -p) if needed.
28
+ * - Skip (safe) if the source no longer exists.
29
+ * - Skip (safe) if the destination path already exists (collision).
30
+ * - Use fs.renameSync; falls back to copy+unlink if cross-device.
31
+ */
32
+ export declare function applyTidy(plan: TidyPlan): void;
@@ -0,0 +1,354 @@
1
+ /**
2
+ * src/core/tidy.ts
3
+ *
4
+ * Plan and apply tidy moves for loose top-level files on the Desktop root.
5
+ *
6
+ * planTidy() — dry-run; examines only direct children of the Desktop root
7
+ * (the root in cfg.roots that is NOT under github/).
8
+ * Never plans to move: keepers, category folders, symlinks,
9
+ * the github/ dir, or git repos.
10
+ *
11
+ * applyTidy() — execute plan.moves; collision-safe (skip if dest exists or
12
+ * source is already gone); mkdir -p dest dirs as needed.
13
+ */
14
+ import fs from 'node:fs';
15
+ import path from 'node:path';
16
+ // ---------------------------------------------------------------------------
17
+ // Internal helpers
18
+ // ---------------------------------------------------------------------------
19
+ /**
20
+ * Resolve the Desktop root from cfg.roots.
21
+ * We want the root that is NOT inside a github/ subtree — i.e. the Desktop
22
+ * itself, not the github scan root that may also be listed.
23
+ */
24
+ function isGithubPath(p) {
25
+ const normalized = path.normalize(p);
26
+ if (path.basename(normalized) === 'github')
27
+ return true;
28
+ return normalized.split(path.sep).includes('github');
29
+ }
30
+ function desktopRoot(cfg) {
31
+ for (const r of cfg.roots) {
32
+ // If this root is NOT the github/ dir itself (and not inside one), treat
33
+ // it as the Desktop root.
34
+ if (!isGithubPath(r)) {
35
+ return r;
36
+ }
37
+ }
38
+ // No non-github root exists — refuse to operate (do NOT fall back to
39
+ // cfg.roots[0], which would be the github container and risk moving the
40
+ // category dirs). Caller treats null as "empty plan".
41
+ return null;
42
+ }
43
+ /**
44
+ * Detect a git repo without importing git.ts (which may be an unimplemented
45
+ * stub in early build stages). A directory is a repo when it contains a
46
+ * `.git` entry (directory OR file — the latter covers worktrees/submodules).
47
+ */
48
+ function isGitRepo(dir) {
49
+ try {
50
+ const gitPath = path.join(dir, '.git');
51
+ fs.accessSync(gitPath); // throws if absent
52
+ return true;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ * Resolve whether `name` (or `fullPath`) is a keeper.
60
+ * Keepers may be stored as absolute paths OR bare basenames.
61
+ */
62
+ function isKeeper(fullPath, name, keepers) {
63
+ for (const k of keepers) {
64
+ if (k === name || k === fullPath)
65
+ return true;
66
+ // Treat entries like "Rent Application.pdf" as basename matchers.
67
+ if (path.basename(k) === name)
68
+ return true;
69
+ }
70
+ return false;
71
+ }
72
+ /**
73
+ * Test whether `name` is a known category folder (the folder itself, not
74
+ * contents — we never move the category container).
75
+ */
76
+ function isCategoryFolder(fullPath, categories) {
77
+ return Object.values(categories).some((catPath) => catPath === fullPath);
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // Glob / regex / ext matching
81
+ // ---------------------------------------------------------------------------
82
+ /**
83
+ * Convert a shell glob pattern to a RegExp.
84
+ * Supports: * (any chars except /), ** (any chars incl /), ? (single char),
85
+ * and character classes [abc].
86
+ * For tidy purposes we match against the basename only when the glob has
87
+ * no path separator, or against the full path when it does.
88
+ */
89
+ function globToRegex(glob) {
90
+ let src = '';
91
+ let i = 0;
92
+ while (i < glob.length) {
93
+ const ch = glob[i];
94
+ if (ch === '*' && glob[i + 1] === '*') {
95
+ src += '.*';
96
+ i += 2;
97
+ // Consume optional trailing /
98
+ if (glob[i] === '/')
99
+ i++;
100
+ }
101
+ else if (ch === '*') {
102
+ src += '[^/]*';
103
+ i++;
104
+ }
105
+ else if (ch === '?') {
106
+ src += '[^/]';
107
+ i++;
108
+ }
109
+ else if (ch === '[') {
110
+ // Pass character class through verbatim until ]
111
+ const end = glob.indexOf(']', i + 1);
112
+ if (end === -1) {
113
+ src += '\\[';
114
+ i++;
115
+ }
116
+ else {
117
+ src += glob.slice(i, end + 1);
118
+ i = end + 1;
119
+ }
120
+ }
121
+ else {
122
+ // Escape regex meta chars
123
+ src += ch.replace(/[.+^${}()|\\]/g, '\\$&');
124
+ i++;
125
+ }
126
+ }
127
+ return new RegExp(`^${src}$`, 'i');
128
+ }
129
+ /**
130
+ * Return true if `itemPath` matches a TidyRule.
131
+ * For 'ext' → compare lowercased extension (with leading dot).
132
+ * For 'glob' → match against basename (no separator in glob) or full path.
133
+ * For 'regex'→ match against basename.
134
+ */
135
+ function matchesRule(itemPath, rule) {
136
+ const name = path.basename(itemPath);
137
+ const ext = path.extname(name).toLowerCase();
138
+ switch (rule.matchType) {
139
+ case 'ext': {
140
+ // Normalise: accept ".pdf" or "pdf"
141
+ const ruleExt = rule.match.startsWith('.') ? rule.match.toLowerCase() : `.${rule.match.toLowerCase()}`;
142
+ return ext === ruleExt;
143
+ }
144
+ case 'glob': {
145
+ const globHasPath = rule.match.includes('/');
146
+ if (globHasPath) {
147
+ return globToRegex(rule.match).test(itemPath);
148
+ }
149
+ return globToRegex(rule.match).test(name);
150
+ }
151
+ case 'regex': {
152
+ try {
153
+ return new RegExp(rule.match, 'i').test(name);
154
+ }
155
+ catch {
156
+ // Malformed regex — never match, don't crash.
157
+ return false;
158
+ }
159
+ }
160
+ default:
161
+ return false;
162
+ }
163
+ }
164
+ /**
165
+ * Resolve a destination directory from a TidyRule.
166
+ * If `dest` is relative, resolve it relative to `root`.
167
+ * If `dest` is absolute, use it as-is.
168
+ */
169
+ function resolveDest(dest, root) {
170
+ return path.isAbsolute(dest) ? dest : path.resolve(root, dest);
171
+ }
172
+ // ---------------------------------------------------------------------------
173
+ // Public API
174
+ // ---------------------------------------------------------------------------
175
+ /**
176
+ * Plan a tidy pass over the Desktop root.
177
+ *
178
+ * Only direct children of the root are examined (depth 1).
179
+ * Moves are first-match-wins against cfg.tidyRules.
180
+ * Items with no matching rule are recorded in skipped[].
181
+ */
182
+ export function planTidy(cfg) {
183
+ const moves = [];
184
+ const skipped = [];
185
+ const root = desktopRoot(cfg);
186
+ if (!root) {
187
+ return { moves, skipped };
188
+ }
189
+ // Unconditional github protection: never operate when the resolved root is
190
+ // (or is under) a github container. desktopRoot() already excludes these,
191
+ // but assert it here so the invariant holds even if selection logic changes.
192
+ if (isGithubPath(root)) {
193
+ return { moves, skipped };
194
+ }
195
+ let entries;
196
+ try {
197
+ entries = fs.readdirSync(root, { withFileTypes: true });
198
+ }
199
+ catch {
200
+ // Root unreadable — return empty plan.
201
+ return { moves, skipped };
202
+ }
203
+ for (const entry of entries) {
204
+ const fullPath = path.join(root, entry.name);
205
+ // 1. Skip symlinks — never plan to move them.
206
+ if (entry.isSymbolicLink()) {
207
+ skipped.push({ path: fullPath, reason: 'symlink' });
208
+ continue;
209
+ }
210
+ // 2. Skip the github/ directory itself.
211
+ if (entry.name === 'github' && entry.isDirectory()) {
212
+ skipped.push({ path: fullPath, reason: 'github directory' });
213
+ continue;
214
+ }
215
+ // 3. Skip keepers.
216
+ if (isKeeper(fullPath, entry.name, cfg.keepers)) {
217
+ skipped.push({ path: fullPath, reason: 'keeper' });
218
+ continue;
219
+ }
220
+ // 4. Skip category folders themselves (don't move the container).
221
+ if (entry.isDirectory() && isCategoryFolder(fullPath, cfg.categories)) {
222
+ skipped.push({ path: fullPath, reason: 'category folder' });
223
+ continue;
224
+ }
225
+ // 5. Skip git repos — they are managed by the index, not tidy.
226
+ if (entry.isDirectory() && isGitRepo(fullPath)) {
227
+ skipped.push({ path: fullPath, reason: 'git repo' });
228
+ continue;
229
+ }
230
+ // Tidy rules only apply to regular files. A loose top-level DIRECTORY that
231
+ // passed the keeper/category/repo guards must never be moved wholesale by
232
+ // a basename glob like 'Screenshot*' or '*Contract*' (which would relocate
233
+ // an entire 'Contracts' or 'Q1 Invoices' folder). Record it as skipped.
234
+ if (!entry.isFile()) {
235
+ skipped.push({ path: fullPath, reason: 'directory — tidy rules apply to files only' });
236
+ continue;
237
+ }
238
+ // 6. Find first matching tidy rule.
239
+ let matched = false;
240
+ for (const rule of cfg.tidyRules) {
241
+ if (matchesRule(fullPath, rule)) {
242
+ const destDir = resolveDest(rule.dest, root);
243
+ const destPath = path.join(destDir, entry.name);
244
+ const ruleLabel = rule.description ?? `${rule.matchType}:${rule.match} → ${rule.dest}`;
245
+ matched = true;
246
+ // Destination safety: never let a (possibly custom) rule write into a
247
+ // github/ subtree or onto a keeper path. Skip with a clear reason.
248
+ if (isGithubPath(destDir) || isKeeper(destPath, entry.name, cfg.keepers)) {
249
+ skipped.push({ path: fullPath, reason: `unsafe destination: ${destDir}` });
250
+ break;
251
+ }
252
+ // Collision: a file already exists at the destination. Surface this in
253
+ // the dry-run plan as a skip rather than planning a move applyTidy()
254
+ // would later refuse to perform (it never overwrites).
255
+ if (fs.existsSync(destPath)) {
256
+ skipped.push({ path: fullPath, reason: `collision: ${destPath} already exists` });
257
+ break;
258
+ }
259
+ moves.push({ from: fullPath, to: destPath, rule: ruleLabel });
260
+ break; // first-match-wins
261
+ }
262
+ }
263
+ if (!matched) {
264
+ skipped.push({ path: fullPath, reason: 'no matching rule' });
265
+ }
266
+ }
267
+ return { moves, skipped };
268
+ }
269
+ /**
270
+ * Execute a previously computed TidyPlan.
271
+ *
272
+ * For each move:
273
+ * - Create the destination directory (mkdir -p) if needed.
274
+ * - Skip (safe) if the source no longer exists.
275
+ * - Skip (safe) if the destination path already exists (collision).
276
+ * - Use fs.renameSync; falls back to copy+unlink if cross-device.
277
+ */
278
+ export function applyTidy(plan) {
279
+ for (const move of plan.moves) {
280
+ // Safety: never write a move into a github/ subtree, even if a custom rule
281
+ // produced one. planTidy already guards this, but applyTidy is the last
282
+ // line of defense before an irreversible rename.
283
+ if (isGithubPath(path.dirname(move.to))) {
284
+ continue;
285
+ }
286
+ // Safety: re-check source exists.
287
+ if (!fs.existsSync(move.from)) {
288
+ continue; // Already gone — idempotent skip.
289
+ }
290
+ // Safety: skip if destination already occupied.
291
+ if (fs.existsSync(move.to)) {
292
+ continue; // Collision — do not overwrite.
293
+ }
294
+ // Ensure destination directory exists.
295
+ const destDir = path.dirname(move.to);
296
+ try {
297
+ fs.mkdirSync(destDir, { recursive: true });
298
+ }
299
+ catch {
300
+ // If we can't create the dir, skip this move rather than crashing.
301
+ continue;
302
+ }
303
+ // Attempt atomic rename.
304
+ try {
305
+ fs.renameSync(move.from, move.to);
306
+ }
307
+ catch (err) {
308
+ // EXDEV = cross-device link — copy then unlink.
309
+ if (isCrossDevice(err)) {
310
+ try {
311
+ fsCopyRecursive(move.from, move.to);
312
+ fsRemoveRecursive(move.from);
313
+ }
314
+ catch {
315
+ // Best-effort; if copy/remove fails, leave source in place.
316
+ }
317
+ }
318
+ // Other errors: silently skip rather than crashing.
319
+ }
320
+ }
321
+ }
322
+ // ---------------------------------------------------------------------------
323
+ // Cross-device fallback helpers (Node builtins only)
324
+ // ---------------------------------------------------------------------------
325
+ function isCrossDevice(err) {
326
+ return (typeof err === 'object' &&
327
+ err !== null &&
328
+ 'code' in err &&
329
+ err.code === 'EXDEV');
330
+ }
331
+ /**
332
+ * Recursively copy a file or directory tree to `dest`.
333
+ * Simple implementation using Node builtins — no third-party deps.
334
+ */
335
+ function fsCopyRecursive(src, dest) {
336
+ const stat = fs.statSync(src);
337
+ if (stat.isDirectory()) {
338
+ fs.mkdirSync(dest, { recursive: true });
339
+ for (const child of fs.readdirSync(src)) {
340
+ fsCopyRecursive(path.join(src, child), path.join(dest, child));
341
+ }
342
+ }
343
+ else {
344
+ fs.copyFileSync(src, dest);
345
+ }
346
+ }
347
+ /**
348
+ * Recursively remove a file or directory tree.
349
+ * Uses rm with recursive + force (Node 14.14+).
350
+ */
351
+ function fsRemoveRecursive(p) {
352
+ fs.rmSync(p, { recursive: true, force: true });
353
+ }
354
+ //# sourceMappingURL=tidy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tidy.js","sourceRoot":"","sources":["../../src/core/tidy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * core/tools-registry.ts — Detect installed ashlr ecosystem tools + versions.
3
+ *
4
+ * Probes each known tool via `which` (binary presence) + a `--version` invocation
5
+ * (version string). Fast, synchronous, and NEVER throws — a missing or broken
6
+ * tool yields { installed: false, version: null, path: null }.
7
+ */
8
+ import type { ToolsRegistry } from './types.js';
9
+ /**
10
+ * Detect installed ecosystem tools + versions via PATH (which + --version) or
11
+ * filesystem presence for desktop app tools (e.g. ashlr-md .app bundle).
12
+ * Fast and NEVER throws — a missing tool yields { installed:false, version:null,
13
+ * path:null }. Detects: phantom, ashlr/ashlr-plugin, stack, pulse/pulse-agent,
14
+ * ashlrcode, aw (ashlr-workbench), morphkit, binshield, ashlr-md (app), ashlr-hub.
15
+ */
16
+ export declare function getToolsRegistry(): ToolsRegistry;