@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,192 @@
1
+ /**
2
+ * core/integrations/vercel.ts — Read-only Vercel project status via the
3
+ * `vercel` CLI.
4
+ *
5
+ * RULES:
6
+ * - READ-ONLY. Deploying stays in `ashlr ship` (already --confirm gated).
7
+ * - NEVER throws. Every exported function degrades gracefully on any
8
+ * failure (CLI absent, not authed, not linked, malformed output).
9
+ * - Uses the installed `vercel` CLI — no raw tokens are read, stored,
10
+ * logged, or printed.
11
+ * - spawnSync only (no shell prevents shell injection).
12
+ * - Bounded timeouts so a slow/hung CLI never blocks the caller.
13
+ */
14
+ import { spawnSync } from 'node:child_process';
15
+ import { existsSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ // ---------------------------------------------------------------------------
18
+ // Internal constants
19
+ // ---------------------------------------------------------------------------
20
+ const VERCEL_BIN = 'vercel';
21
+ const TIMEOUT_MS = 8_000; // ms — vercel ls can be slow on first run
22
+ const MAX_DEPLOYS = 10;
23
+ // ---------------------------------------------------------------------------
24
+ // Internal helpers
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Run a vercel sub-command synchronously inside `cwd`.
28
+ * Returns trimmed stdout or null on any failure. Never throws.
29
+ */
30
+ function runVercel(args, cwd) {
31
+ try {
32
+ const res = spawnSync(VERCEL_BIN, args, {
33
+ cwd,
34
+ timeout: TIMEOUT_MS,
35
+ stdio: 'pipe',
36
+ encoding: 'utf8',
37
+ env: {
38
+ ...process.env,
39
+ // Suppress interactive prompts and update checks so the CLI
40
+ // is usable in a non-TTY context.
41
+ CI: '1',
42
+ FORCE_COLOR: '0',
43
+ },
44
+ });
45
+ // spawn error (e.g. ENOENT — vercel not on PATH) or non-zero exit → null.
46
+ if (res.error)
47
+ return null;
48
+ if (res.status !== 0)
49
+ return null;
50
+ return typeof res.stdout === 'string' ? res.stdout.trim() : null;
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ /**
57
+ * Returns true when a `.vercel/project.json` file exists in `cwd`, which
58
+ * indicates the directory has been linked to a Vercel project.
59
+ */
60
+ function hasProjectJson(cwd) {
61
+ return existsSync(join(cwd, '.vercel', 'project.json'));
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // JSON parsing helpers
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Parse the JSON emitted by `vercel ls --format json`.
68
+ *
69
+ * The modern CLI emits `{ deployments: [...] }`; older shapes emit a bare
70
+ * array of deployment objects. Each relevant
71
+ * field is extracted defensively; unknown shapes produce an empty array.
72
+ */
73
+ function parseDeployList(raw) {
74
+ const trimmed = raw.trim();
75
+ // vercel ls --format json wraps the array under a top-level key (or, on
76
+ // older CLI versions, emits a bare array).
77
+ let parsed;
78
+ try {
79
+ parsed = JSON.parse(trimmed);
80
+ }
81
+ catch {
82
+ return [];
83
+ }
84
+ // Accept a bare array OR { deployments: [...] } / { data: [...] } wrappers.
85
+ let items = null;
86
+ if (Array.isArray(parsed)) {
87
+ items = parsed;
88
+ }
89
+ else if (parsed !== null && typeof parsed === 'object') {
90
+ const obj = parsed;
91
+ for (const key of ['deployments', 'data', 'items']) {
92
+ if (Array.isArray(obj[key])) {
93
+ items = obj[key];
94
+ break;
95
+ }
96
+ }
97
+ }
98
+ if (items === null)
99
+ return [];
100
+ const results = [];
101
+ for (const item of items) {
102
+ if (item === null || typeof item !== 'object')
103
+ continue;
104
+ const d = item;
105
+ // URL — vercel uses "url" or "alias" (first element).
106
+ let url = '';
107
+ if (typeof d['url'] === 'string' && d['url'].length > 0) {
108
+ url = d['url'];
109
+ }
110
+ else if (Array.isArray(d['alias']) && typeof d['alias'][0] === 'string') {
111
+ url = d['alias'][0];
112
+ }
113
+ if (!url)
114
+ continue; // skip entries without a URL
115
+ // State — various field names depending on vercel CLI version.
116
+ let state = 'UNKNOWN';
117
+ for (const key of ['state', 'readyState', 'status']) {
118
+ if (typeof d[key] === 'string' && d[key].length > 0) {
119
+ state = d[key].toUpperCase();
120
+ break;
121
+ }
122
+ }
123
+ // Created timestamp.
124
+ let createdAt = null;
125
+ for (const key of ['createdAt', 'created', 'createdTime']) {
126
+ const val = d[key];
127
+ if (typeof val === 'string' && val.length > 0) {
128
+ createdAt = val;
129
+ break;
130
+ }
131
+ if (typeof val === 'number') {
132
+ createdAt = new Date(val).toISOString();
133
+ break;
134
+ }
135
+ }
136
+ // Target — "production" | "preview" | null.
137
+ let target = null;
138
+ for (const key of ['target', 'meta.githubCommitRef']) {
139
+ if (typeof d[key] === 'string' && d[key].length > 0) {
140
+ target = d[key];
141
+ break;
142
+ }
143
+ }
144
+ results.push({ url, state, createdAt, target });
145
+ if (results.length >= MAX_DEPLOYS)
146
+ break;
147
+ }
148
+ return results;
149
+ }
150
+ // ---------------------------------------------------------------------------
151
+ // Public API
152
+ // ---------------------------------------------------------------------------
153
+ /**
154
+ * Read-only linked-project snapshot via the `vercel` CLI.
155
+ * NEVER throws — degrades to `{ linked: false, latestState: null, url: null }`
156
+ * on any failure (CLI absent, not authed, not linked, scope prompt, timeout).
157
+ */
158
+ export function vercelStatus(cwd) {
159
+ const unlinked = { linked: false, latestState: null, url: null };
160
+ // Fast-path: check for .vercel/project.json before spawning the CLI.
161
+ if (!hasProjectJson(cwd))
162
+ return unlinked;
163
+ // Attempt `vercel ls --format json` for a live deployment list — take the
164
+ // first (most recent) entry as the latest status. The modern Vercel CLI uses
165
+ // `-F, --format json`; the legacy `--json` flag errors with "unknown option".
166
+ const raw = runVercel(['ls', '--format', 'json'], cwd);
167
+ if (raw === null)
168
+ return unlinked;
169
+ const deploys = parseDeployList(raw);
170
+ if (deploys.length > 0) {
171
+ const latest = deploys[0];
172
+ return {
173
+ linked: true,
174
+ latestState: latest.state,
175
+ url: latest.url,
176
+ };
177
+ }
178
+ // `vercel ls` returned parseable JSON but no deployments — still linked.
179
+ return { linked: true, latestState: null, url: null };
180
+ }
181
+ /**
182
+ * List recent deployments for the Vercel project linked to `cwd`.
183
+ * NEVER throws — returns [] on any failure (CLI absent, not authed, not
184
+ * linked, malformed output, timeout).
185
+ */
186
+ export function listDeploys(cwd) {
187
+ const raw = runVercel(['ls', '--format', 'json'], cwd);
188
+ if (raw === null)
189
+ return [];
190
+ return parseDeployList(raw);
191
+ }
192
+ //# sourceMappingURL=vercel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../src/core/integrations/vercel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ask.ts — Portfolio RAG: retrieve + synthesize answers from the knowledge index.
3
+ *
4
+ * INVARIANTS (non-negotiable):
5
+ * 1. LOCAL-ONLY BY DEFAULT — code/chunks are NEVER sent to a cloud model unless
6
+ * opts.allowCloud === true AND a cloud key exists. Any code-to-cloud on the
7
+ * default path is a contract violation.
8
+ * 2. READ-ONLY — this module never modifies any enrolled repo or any file
9
+ * outside knowledgeDir().
10
+ * 3. ENROLLMENT-SCOPED — retrieval is limited to loadChunks() output, which
11
+ * itself is scoped to the persisted index (enrolled repos only).
12
+ * 4. BOUNDED — top-K retrieval is capped; chunk text in the prompt is capped.
13
+ * 5. NO SECRETS — chunks stored in the index are already scrubbed; we do not
14
+ * re-expose them beyond the local synthesis prompt.
15
+ * 6. NEVER THROWS — degrades gracefully; returns a useful message on any failure.
16
+ */
17
+ import type { AskResult } from '../types.js';
18
+ /**
19
+ * Answer `question` using a local RAG pipeline over the persisted knowledge index.
20
+ *
21
+ * Retrieval: embedding cosine similarity (local Ollama) when vectors are present,
22
+ * else keyword/TF-IDF. Synthesis: LOCAL model via getActiveClient (Ollama/LM Studio).
23
+ *
24
+ * PRIVACY GUARDRAIL: code chunks are only sent to the local synthesis model by
25
+ * default. They are sent to a cloud model ONLY when opts.allowCloud === true AND
26
+ * a cloud key exists (enforced by getActiveClient — it throws otherwise).
27
+ *
28
+ * Never throws. Degrades to an informational message when nothing is indexed
29
+ * or the local model is unreachable.
30
+ */
31
+ export declare function ask(question: string, opts: {
32
+ repo?: string;
33
+ allowCloud: boolean;
34
+ }): Promise<AskResult>;
@@ -0,0 +1,325 @@
1
+ /**
2
+ * ask.ts — Portfolio RAG: retrieve + synthesize answers from the knowledge index.
3
+ *
4
+ * INVARIANTS (non-negotiable):
5
+ * 1. LOCAL-ONLY BY DEFAULT — code/chunks are NEVER sent to a cloud model unless
6
+ * opts.allowCloud === true AND a cloud key exists. Any code-to-cloud on the
7
+ * default path is a contract violation.
8
+ * 2. READ-ONLY — this module never modifies any enrolled repo or any file
9
+ * outside knowledgeDir().
10
+ * 3. ENROLLMENT-SCOPED — retrieval is limited to loadChunks() output, which
11
+ * itself is scoped to the persisted index (enrolled repos only).
12
+ * 4. BOUNDED — top-K retrieval is capped; chunk text in the prompt is capped.
13
+ * 5. NO SECRETS — chunks stored in the index are already scrubbed; we do not
14
+ * re-expose them beyond the local synthesis prompt.
15
+ * 6. NEVER THROWS — degrades gracefully; returns a useful message on any failure.
16
+ */
17
+ import { loadChunks } from './index.js';
18
+ import { getActiveClient } from '../run/provider-client.js';
19
+ import { loadConfig } from '../config.js';
20
+ // ---------------------------------------------------------------------------
21
+ // Constants
22
+ // ---------------------------------------------------------------------------
23
+ /** Number of top chunks to retrieve for synthesis. */
24
+ const TOP_K = 8;
25
+ /** Max characters of a single chunk to include in the synthesis prompt. */
26
+ const CHUNK_TEXT_CAP = 600;
27
+ /** Max total characters of all chunk context in the synthesis prompt. */
28
+ const CONTEXT_TOTAL_CAP = 6000;
29
+ /** Timeout (ms) for the local Ollama /api/embeddings request. */
30
+ const EMBED_TIMEOUT_MS = 8000;
31
+ // ---------------------------------------------------------------------------
32
+ // Tokenisation (shared pattern with recall.ts — no import to avoid coupling)
33
+ // ---------------------------------------------------------------------------
34
+ function tokenize(text) {
35
+ return text
36
+ .toLowerCase()
37
+ .split(/[^a-z0-9]+/)
38
+ .filter((t) => t.length > 1); // drop single-char tokens
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Cosine similarity
42
+ // ---------------------------------------------------------------------------
43
+ function cosine(a, b) {
44
+ if (a.length === 0 || a.length !== b.length)
45
+ return 0;
46
+ let dot = 0, normA = 0, normB = 0;
47
+ for (let i = 0; i < a.length; i++) {
48
+ dot += a[i] * b[i];
49
+ normA += a[i] * a[i];
50
+ normB += b[i] * b[i];
51
+ }
52
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
53
+ return denom === 0 ? 0 : dot / denom;
54
+ }
55
+ // ---------------------------------------------------------------------------
56
+ // Keyword / TF-IDF scoring for a chunk
57
+ // ---------------------------------------------------------------------------
58
+ function keywordScoreChunk(query, chunk) {
59
+ const queryTerms = new Set(tokenize(query));
60
+ if (queryTerms.size === 0)
61
+ return 0;
62
+ // Weight file path tokens slightly (they indicate structural relevance)
63
+ const fileTokens = tokenize(chunk.file);
64
+ const textTokens = tokenize(chunk.text);
65
+ const weightedFreq = new Map();
66
+ for (const t of fileTokens) {
67
+ weightedFreq.set(t, (weightedFreq.get(t) ?? 0) + 2);
68
+ }
69
+ for (const t of textTokens) {
70
+ weightedFreq.set(t, (weightedFreq.get(t) ?? 0) + 1);
71
+ }
72
+ if (weightedFreq.size === 0)
73
+ return 0;
74
+ let hits = 0;
75
+ for (const term of queryTerms) {
76
+ hits += weightedFreq.get(term) ?? 0;
77
+ }
78
+ return hits === 0 ? 0 : hits / queryTerms.size;
79
+ }
80
+ // ---------------------------------------------------------------------------
81
+ // Local Ollama embedding helpers (best-effort; never throw)
82
+ // ---------------------------------------------------------------------------
83
+ async function detectEmbeddingModel(ollamaBase) {
84
+ const controller = new AbortController();
85
+ const timer = setTimeout(() => controller.abort(), 3000);
86
+ try {
87
+ const res = await fetch(`${ollamaBase.replace(/\/+$/, '')}/api/tags`, {
88
+ signal: controller.signal,
89
+ headers: { Accept: 'application/json' },
90
+ });
91
+ if (!res.ok)
92
+ return { available: false };
93
+ const body = (await res.json());
94
+ if (typeof body !== 'object' ||
95
+ body === null ||
96
+ !Array.isArray(body['models'])) {
97
+ return { available: false };
98
+ }
99
+ const models = body.models;
100
+ const EMBED_HINTS = ['bge', 'nomic-embed', 'mxbai-embed', 'all-minilm', 'embed'];
101
+ for (const hint of EMBED_HINTS) {
102
+ const found = models.find((m) => m.name.toLowerCase().includes(hint));
103
+ if (found)
104
+ return { available: true, model: found.name };
105
+ }
106
+ return { available: false };
107
+ }
108
+ catch {
109
+ return { available: false };
110
+ }
111
+ finally {
112
+ clearTimeout(timer);
113
+ }
114
+ }
115
+ async function fetchEmbedding(ollamaBase, model, text) {
116
+ const controller = new AbortController();
117
+ const timer = setTimeout(() => controller.abort(), EMBED_TIMEOUT_MS);
118
+ try {
119
+ const res = await fetch(`${ollamaBase.replace(/\/+$/, '')}/api/embeddings`, {
120
+ method: 'POST',
121
+ signal: controller.signal,
122
+ headers: { 'Content-Type': 'application/json' },
123
+ body: JSON.stringify({ model, prompt: text.slice(0, 2000) }),
124
+ });
125
+ if (!res.ok)
126
+ return null;
127
+ const body = (await res.json());
128
+ if (typeof body !== 'object' ||
129
+ body === null ||
130
+ !Array.isArray(body['embedding'])) {
131
+ return null;
132
+ }
133
+ const embedding = body.embedding;
134
+ if (!embedding.every((v) => typeof v === 'number'))
135
+ return null;
136
+ return embedding;
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ finally {
142
+ clearTimeout(timer);
143
+ }
144
+ }
145
+ /**
146
+ * Retrieve the top-K most relevant chunks from the index for `question`.
147
+ * Tries embedding cosine similarity first (local Ollama); falls back to
148
+ * keyword/TF-IDF. Never throws; returns [] on any failure.
149
+ */
150
+ async function retrieve(question, chunks, ollamaBase) {
151
+ if (chunks.length === 0)
152
+ return { hits: [], method: 'keyword' };
153
+ // --- Attempt embedding retrieval if any chunks have vectors ---
154
+ const chunksWithVectors = chunks.filter((c) => c.vector && c.vector.length > 0);
155
+ if (chunksWithVectors.length > 0) {
156
+ // Try to get a query embedding from local Ollama
157
+ try {
158
+ const modelProbe = await detectEmbeddingModel(ollamaBase);
159
+ if (modelProbe.available) {
160
+ const queryVec = await fetchEmbedding(ollamaBase, modelProbe.model, question);
161
+ if (queryVec !== null) {
162
+ // Score all chunks that have vectors by cosine; keyword score for the rest
163
+ const hits = chunks.map((chunk) => {
164
+ if (chunk.vector && chunk.vector.length > 0) {
165
+ return {
166
+ chunk,
167
+ score: cosine(queryVec, chunk.vector),
168
+ method: 'embedding',
169
+ };
170
+ }
171
+ return {
172
+ chunk,
173
+ score: keywordScoreChunk(question, chunk),
174
+ method: 'keyword',
175
+ };
176
+ });
177
+ hits.sort((a, b) => b.score - a.score);
178
+ return { hits: hits.slice(0, TOP_K), method: 'embedding' };
179
+ }
180
+ }
181
+ }
182
+ catch {
183
+ // Fall through to keyword
184
+ }
185
+ }
186
+ // --- Keyword / TF-IDF fallback ---
187
+ const hits = chunks.map((chunk) => ({
188
+ chunk,
189
+ score: keywordScoreChunk(question, chunk),
190
+ method: 'keyword',
191
+ }));
192
+ hits.sort((a, b) => b.score - a.score);
193
+ return { hits: hits.slice(0, TOP_K), method: 'keyword' };
194
+ }
195
+ // ---------------------------------------------------------------------------
196
+ // Prompt construction
197
+ // ---------------------------------------------------------------------------
198
+ function buildPrompt(question, hits) {
199
+ if (hits.length === 0) {
200
+ return `Answer the following question as best you can. No source context is available.\n\nQuestion: ${question}`;
201
+ }
202
+ const contextParts = [];
203
+ let totalChars = 0;
204
+ for (const hit of hits) {
205
+ const { chunk } = hit;
206
+ const header = `[${chunk.repo}] ${chunk.file}:${chunk.startLine}-${chunk.endLine}`;
207
+ const body = chunk.text.slice(0, CHUNK_TEXT_CAP);
208
+ const entry = `${header}\n${body}`;
209
+ if (totalChars + entry.length > CONTEXT_TOTAL_CAP)
210
+ break;
211
+ contextParts.push(entry);
212
+ totalChars += entry.length;
213
+ }
214
+ return [
215
+ 'You are a software assistant with access to source code excerpts from an enrolled code portfolio.',
216
+ 'Answer the question using only the provided context. Cite the source (repo, file, line) for each claim.',
217
+ 'If the context does not contain enough information, say so clearly.',
218
+ '',
219
+ '--- SOURCE CONTEXT ---',
220
+ contextParts.join('\n\n---\n'),
221
+ '--- END CONTEXT ---',
222
+ '',
223
+ `Question: ${question}`,
224
+ ].join('\n');
225
+ }
226
+ // ---------------------------------------------------------------------------
227
+ // Public API
228
+ // ---------------------------------------------------------------------------
229
+ /**
230
+ * Answer `question` using a local RAG pipeline over the persisted knowledge index.
231
+ *
232
+ * Retrieval: embedding cosine similarity (local Ollama) when vectors are present,
233
+ * else keyword/TF-IDF. Synthesis: LOCAL model via getActiveClient (Ollama/LM Studio).
234
+ *
235
+ * PRIVACY GUARDRAIL: code chunks are only sent to the local synthesis model by
236
+ * default. They are sent to a cloud model ONLY when opts.allowCloud === true AND
237
+ * a cloud key exists (enforced by getActiveClient — it throws otherwise).
238
+ *
239
+ * Never throws. Degrades to an informational message when nothing is indexed
240
+ * or the local model is unreachable.
241
+ */
242
+ export async function ask(question, opts) {
243
+ const noKnowledge = (reason) => ({
244
+ question,
245
+ answer: reason,
246
+ sources: [],
247
+ method: 'keyword',
248
+ local: true,
249
+ });
250
+ // --- Load chunks from the persisted index ---
251
+ let chunks;
252
+ try {
253
+ chunks = loadChunks(opts.repo);
254
+ }
255
+ catch {
256
+ return noKnowledge('No knowledge indexed — run `ashlr knowledge build` to index enrolled repos.');
257
+ }
258
+ if (chunks.length === 0) {
259
+ const scope = opts.repo ? ` for repo ${opts.repo}` : '';
260
+ return noKnowledge(`No knowledge indexed${scope} — run \`ashlr knowledge build\` to index enrolled repos.`);
261
+ }
262
+ // --- Load config (synchronous) for Ollama base URL and provider client ---
263
+ let cfg;
264
+ try {
265
+ cfg = loadConfig();
266
+ }
267
+ catch {
268
+ return noKnowledge('Could not load ashlr config — run `ashlr` once to initialize.');
269
+ }
270
+ const ollamaBase = (cfg.models?.ollama ?? 'http://localhost:11434').replace(/\/+$/, '');
271
+ // --- Retrieve top-K relevant chunks ---
272
+ let hits;
273
+ let method;
274
+ try {
275
+ ({ hits, method } = await retrieve(question, chunks, ollamaBase));
276
+ }
277
+ catch {
278
+ hits = [];
279
+ method = 'keyword';
280
+ }
281
+ // --- Build cited sources from retrieved hits ---
282
+ const sources = hits.map((h) => ({
283
+ repo: h.chunk.repo,
284
+ file: h.chunk.file,
285
+ line: h.chunk.startLine,
286
+ }));
287
+ // --- Synthesize answer via local model ---
288
+ // PRIVACY: getActiveClient enforces LOCAL-ONLY by default.
289
+ // allowCloud is forwarded verbatim — the client will throw if cloud is
290
+ // selected without --allow-cloud, providing a clear error message.
291
+ const prompt = buildPrompt(question, hits);
292
+ let answer;
293
+ let isLocal = true;
294
+ try {
295
+ const client = await getActiveClient(cfg, { allowCloud: opts.allowCloud });
296
+ // ALLOWLIST (not denylist): treat ONLY the known local providers as local.
297
+ // Any unknown/new provider id (e.g. a future 'bedrock'/'vertex') defaults to
298
+ // local:false (cloud) so it correctly triggers the cloud warning rather than
299
+ // being silently mislabeled as local.
300
+ isLocal = client.id === 'ollama' || client.id === 'lmstudio';
301
+ const result = await client.chat([
302
+ { role: 'user', content: prompt },
303
+ ]);
304
+ answer = result.content.trim();
305
+ if (!answer) {
306
+ answer = 'The local model returned an empty response. Ensure Ollama is running with a chat model loaded.';
307
+ }
308
+ }
309
+ catch (err) {
310
+ const msg = err instanceof Error ? err.message : String(err);
311
+ // Surface the local-first refusal clearly so the user knows what to do
312
+ answer = `Could not synthesize an answer: ${msg}`;
313
+ // If the error is a local-first refusal (no cloud without --allow-cloud),
314
+ // treat it as a local attempt (the synthesis just failed)
315
+ isLocal = true;
316
+ }
317
+ return {
318
+ question,
319
+ answer,
320
+ sources,
321
+ method,
322
+ local: isLocal,
323
+ };
324
+ }
325
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../src/core/knowledge/ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * graph.ts — Knowledge Graph + Impact analysis for enrolled repos.
3
+ *
4
+ * INVARIANTS (docs/contracts/CONTRACT-M25.md):
5
+ * 1. READ-ONLY: never modifies any enrolled repo; analysis only.
6
+ * 2. ENROLLMENT-SCOPED: default repos = listEnrolled() (DEFAULT EMPTY => empty graph).
7
+ * 3. BOUNDED: caps file walk depth, file count, and skips node_modules/.git/dist/binaries.
8
+ * 4. NEVER THROWS: all functions catch internally; callers get empty structures on error.
9
+ * 5. LOCAL-ONLY: no network calls; pure filesystem analysis.
10
+ * 6. NO SECRETS: skips .env/key files; does not emit secret-shaped content.
11
+ *
12
+ * buildGraph(repos?): construct KnowledgeGraph from persisted index + package.json manifests
13
+ * + import/require statements. Nodes: repos, key modules, shared deps.
14
+ * Edges: imports/depends/shared-dep. CrossRepo: same dep across repos, duplicated modules.
15
+ *
16
+ * impact(target, repos?): find all references to a file path or symbol across enrolled repos
17
+ * via the persisted index + grep-style scan. Returns ImpactResult with references + dependents.
18
+ */
19
+ import type { KnowledgeGraph, ImpactResult } from '../types.js';
20
+ /**
21
+ * Build a KnowledgeGraph from enrolled repos (or the provided list).
22
+ *
23
+ * Nodes:
24
+ * - kind:'repo' — each enrolled repo
25
+ * - kind:'module' — key source files within a repo (those that import packages)
26
+ * - kind:'dep' — external dependencies (package names)
27
+ *
28
+ * Edges:
29
+ * - kind:'depends' — repo -> dep (from package.json)
30
+ * - kind:'imports' — module -> dep (from import statements)
31
+ * - kind:'shared-dep' — dep -> dep node (already in graph; used for cross-repo detection)
32
+ *
33
+ * CrossRepo:
34
+ * - kind:'shared-dep' when a dep appears in 2+ repos
35
+ * - kind:'duplicate-module' when the same relative module path exists in 2+ repos
36
+ *
37
+ * BOUNDED, READ-ONLY, NEVER THROWS.
38
+ */
39
+ export declare function buildGraph(repos?: string[]): KnowledgeGraph;
40
+ /**
41
+ * Find all references to a file path or symbol across enrolled repos.
42
+ *
43
+ * For a file target: searches for import/require of that file (by basename and
44
+ * relative paths) and any text occurrence of the path.
45
+ * For a symbol target (no path separators, no extension): searches for usage
46
+ * occurrences in source files via text scan.
47
+ *
48
+ * Returns references (repo/file:line) and a list of dependent module names.
49
+ * BOUNDED (MAX_REFERENCES cap). READ-ONLY. NEVER THROWS.
50
+ */
51
+ export declare function impact(target: string, repos?: string[]): ImpactResult;