@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,250 @@
1
+ /**
2
+ * Provider registry — probes local-model endpoints (LM Studio, Ollama) and
3
+ * resolves the active provider from the configured chain.
4
+ *
5
+ * Rules:
6
+ * - NEVER throws; all probes return typed results with up:false on failure.
7
+ * - Uses global fetch (Node 22+) with a 2-second AbortController timeout.
8
+ * - Cloud providers (e.g. 'anthropic') are treated as up when the relevant
9
+ * env var is present (ANTHROPIC_API_KEY), else skipped.
10
+ */
11
+ // ---------------------------------------------------------------------------
12
+ // Internal helpers
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * Ensure a base URL has the expected path suffix.
16
+ * e.g. ensurePath('http://localhost:1234', '/v1/models') -> 'http://localhost:1234/v1/models'
17
+ * If the URL already ends with the path, it is returned unchanged.
18
+ */
19
+ function ensurePath(base, suffix) {
20
+ const stripped = base.replace(/\/+$/, '');
21
+ if (stripped.endsWith(suffix))
22
+ return stripped;
23
+ return stripped + suffix;
24
+ }
25
+ /**
26
+ * Parse model names from an LM Studio /v1/models response (OpenAI shape).
27
+ * Returns empty array on any shape mismatch.
28
+ */
29
+ function parseLmStudioModels(body) {
30
+ if (typeof body !== 'object' ||
31
+ body === null ||
32
+ !Array.isArray(body['data'])) {
33
+ return [];
34
+ }
35
+ const data = body.data;
36
+ return data
37
+ .filter((m) => typeof m['id'] === 'string')
38
+ .map((m) => m.id);
39
+ }
40
+ /**
41
+ * Parse model names from an Ollama /api/tags response.
42
+ * Returns empty array on any shape mismatch.
43
+ */
44
+ function parseOllamaModels(body) {
45
+ if (typeof body !== 'object' ||
46
+ body === null ||
47
+ !Array.isArray(body['models'])) {
48
+ return [];
49
+ }
50
+ const models = body.models;
51
+ return models
52
+ .filter((m) => typeof m['name'] === 'string')
53
+ .map((m) => m.name);
54
+ }
55
+ /**
56
+ * Determine which response shape to use for a given probe URL.
57
+ * - URL ends with /v1/models → LM Studio (OpenAI) shape
58
+ * - URL ends with /api/tags → Ollama shape
59
+ * - Fallback: try LM Studio shape first, then Ollama
60
+ */
61
+ function parseModels(url, body) {
62
+ if (url.endsWith('/v1/models'))
63
+ return parseLmStudioModels(body);
64
+ if (url.endsWith('/api/tags'))
65
+ return parseOllamaModels(body);
66
+ // Unknown path — try both shapes, take whichever yields results
67
+ const lm = parseLmStudioModels(body);
68
+ return lm.length > 0 ? lm : parseOllamaModels(body);
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Cloud provider env-var map
72
+ // Extend as new cloud providers are added to providerChain.
73
+ // ---------------------------------------------------------------------------
74
+ const CLOUD_PROVIDER_ENV = {
75
+ anthropic: 'ANTHROPIC_API_KEY',
76
+ openai: 'OPENAI_API_KEY',
77
+ gemini: 'GEMINI_API_KEY',
78
+ cohere: 'COHERE_API_KEY',
79
+ groq: 'GROQ_API_KEY',
80
+ };
81
+ /**
82
+ * Returns true if a cloud provider's API key is present in process.env.
83
+ * Unknown cloud providers default to false (not considered up).
84
+ */
85
+ function cloudProviderUp(id) {
86
+ const envVar = CLOUD_PROVIDER_ENV[id.toLowerCase()];
87
+ if (!envVar)
88
+ return false;
89
+ const val = process.env[envVar];
90
+ return typeof val === 'string' && val.trim().length > 0;
91
+ }
92
+ // ---------------------------------------------------------------------------
93
+ // Public API
94
+ // ---------------------------------------------------------------------------
95
+ /**
96
+ * Probe a single provider endpoint with a 2-second timeout.
97
+ *
98
+ * - For LM Studio: GET <url>/v1/models (appended if not already present)
99
+ * - For Ollama: GET <url>/api/tags (appended if not already present)
100
+ * - For other ids: url is used as-is (caller must supply full probe URL)
101
+ *
102
+ * Never throws — returns up:false with an error string on any failure.
103
+ */
104
+ export async function probeEndpoint(id, url) {
105
+ // Determine the canonical probe URL
106
+ let probeUrl;
107
+ if (id === 'lmstudio') {
108
+ probeUrl = ensurePath(url, '/v1/models');
109
+ }
110
+ else if (id === 'ollama') {
111
+ probeUrl = ensurePath(url, '/api/tags');
112
+ }
113
+ else {
114
+ probeUrl = url;
115
+ }
116
+ const controller = new AbortController();
117
+ const timer = setTimeout(() => controller.abort(), 2000);
118
+ try {
119
+ const response = await fetch(probeUrl, {
120
+ method: 'GET',
121
+ signal: controller.signal,
122
+ headers: { Accept: 'application/json' },
123
+ });
124
+ // NOTE: do NOT clearTimeout here — the abort signal must stay armed across
125
+ // the response-body read below so a server that streams/hangs the body is
126
+ // still bounded by the 2s timeout. Cleared in the finally block.
127
+ if (!response.ok) {
128
+ return {
129
+ id,
130
+ url: probeUrl,
131
+ up: false,
132
+ models: [],
133
+ error: `HTTP ${response.status} ${response.statusText}`,
134
+ };
135
+ }
136
+ let body;
137
+ try {
138
+ body = await response.json();
139
+ }
140
+ catch {
141
+ return {
142
+ id,
143
+ url: probeUrl,
144
+ up: false,
145
+ models: [],
146
+ error: 'Response body is not valid JSON',
147
+ };
148
+ }
149
+ const models = parseModels(probeUrl, body);
150
+ return { id, url: probeUrl, up: true, models };
151
+ }
152
+ catch (err) {
153
+ let message;
154
+ if (err instanceof Error) {
155
+ message = err.name === 'AbortError' ? 'Probe timed out after 2s' : err.message;
156
+ }
157
+ else {
158
+ message = String(err);
159
+ }
160
+ return { id, url: probeUrl, up: false, models: [], error: message };
161
+ }
162
+ finally {
163
+ // Disarm the timeout only after the body read has completed or failed,
164
+ // so the abort signal bounds both the fetch() and the response.json().
165
+ clearTimeout(timer);
166
+ }
167
+ }
168
+ /**
169
+ * Build the full ProviderRegistry from the current config.
170
+ *
171
+ * - Probes cfg.models.lmstudio and cfg.models.ollama in parallel.
172
+ * - Walks cfg.models.providerChain in order to find the first up provider.
173
+ * - Cloud providers (e.g. 'anthropic') count as up if their env key exists.
174
+ * - Local providers not in the config (unknown ids) are skipped gracefully.
175
+ */
176
+ export async function getProviderRegistry(cfg) {
177
+ const chain = cfg.models.providerChain;
178
+ // Probe the two known local endpoints in parallel
179
+ const [lmResult, ollamaResult] = await Promise.all([
180
+ probeEndpoint('lmstudio', cfg.models.lmstudio),
181
+ probeEndpoint('ollama', cfg.models.ollama),
182
+ ]);
183
+ // Build a lookup map for the probed local endpoints
184
+ const localEndpoints = {
185
+ lmstudio: lmResult,
186
+ ollama: ollamaResult,
187
+ };
188
+ // Assemble the providers list in chain order where possible,
189
+ // appending any probed endpoints not present in the chain.
190
+ const seenIds = new Set();
191
+ const providers = [];
192
+ for (const providerId of chain) {
193
+ if (seenIds.has(providerId))
194
+ continue;
195
+ seenIds.add(providerId);
196
+ if (localEndpoints[providerId] !== undefined) {
197
+ providers.push(localEndpoints[providerId]);
198
+ }
199
+ // Cloud providers are not added as ProviderEndpoint entries
200
+ // (they have no local URL to probe) — they participate only in
201
+ // activeProvider resolution below.
202
+ }
203
+ // Add any probed local endpoints that were not in the chain
204
+ for (const [id, endpoint] of Object.entries(localEndpoints)) {
205
+ if (!seenIds.has(id)) {
206
+ seenIds.add(id);
207
+ providers.push(endpoint);
208
+ }
209
+ }
210
+ // Resolve activeProvider: first entry in chain that is considered "up"
211
+ let activeProvider = null;
212
+ for (const providerId of chain) {
213
+ const local = localEndpoints[providerId];
214
+ if (local !== undefined) {
215
+ if (local.up) {
216
+ activeProvider = providerId;
217
+ break;
218
+ }
219
+ }
220
+ else {
221
+ // Treat as a cloud provider — up if env key is present
222
+ if (cloudProviderUp(providerId)) {
223
+ activeProvider = providerId;
224
+ break;
225
+ }
226
+ }
227
+ }
228
+ // Failover fallback: if the configured chain yielded no active provider but a
229
+ // probed local endpoint is actually up (e.g. a custom chain that omits an up
230
+ // local id), select the first up local endpoint. Keeps default behavior
231
+ // identical (the default chain already lists both local ids) while making
232
+ // failover correct for non-default chains.
233
+ if (activeProvider === null) {
234
+ for (const endpoint of providers) {
235
+ if (endpoint.up) {
236
+ activeProvider = endpoint.id;
237
+ break;
238
+ }
239
+ }
240
+ }
241
+ return { providers, activeProvider, chain };
242
+ }
243
+ /**
244
+ * Convenience wrapper — returns the id of the active provider, or null.
245
+ */
246
+ export async function resolveActiveProvider(cfg) {
247
+ const registry = await getProviderRegistry(cfg);
248
+ return registry.activeProvider;
249
+ }
250
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/core/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * conventions.ts — Read-only PROJECT-STANDARDS probes for a single repo (M27).
3
+ *
4
+ * GUARDRAILS (enforced throughout this file):
5
+ * - READ-ONLY: pure FS reads (existsSync / statSync / readFileSync). NO writes,
6
+ * NO git mutations, NO installs, NO shell. NEVER mutates a user repo working tree.
7
+ * - Bounded: a fixed, small set of top-level presence checks + a shallow read of
8
+ * the root package.json; no deep tree traversal, no unbounded loops.
9
+ * - Never throws: returns [] on any error so callers (health.ts) stay unblocked.
10
+ * - No secrets: emitted ConventionFinding values are presence/label metadata only.
11
+ * - Enrollment-scoping is the CALLER's responsibility (health.ts) — this module
12
+ * is a pure probe over whatever absolute path it is handed.
13
+ */
14
+ import type { ConventionFinding } from '../types.js';
15
+ /**
16
+ * Probe `repo` (an absolute path) for project-standard conventions.
17
+ *
18
+ * Returns a deterministic, ordered ConventionFinding[] covering:
19
+ * - README presence + thinness (< THIN_README_BYTES bytes)
20
+ * - LICENSE presence
21
+ * - lockfile presence (package-lock.json / yarn.lock / pnpm-lock.yaml / bun.lockb / Cargo.lock / …)
22
+ * - .gitignore presence
23
+ * - a test signal (test|tests|__tests__|spec dir, or a package.json "test" script)
24
+ * - a CI config presence (.github/workflows / .gitlab-ci.yml / .circleci / …)
25
+ * - (Node projects only) a package.json `license` field
26
+ * - (Node projects only) a package.json `repository` field
27
+ *
28
+ * Pure FS reads, bounded (fixed check list + one shallow package.json read; no
29
+ * deep traversal), NEVER mutates, NEVER throws (returns [] on failure).
30
+ *
31
+ * Mirrors the read-only presence/size heuristics in
32
+ * portfolio/scanners.ts#scanDocs / #scanTests. Enrollment-scoping is the
33
+ * caller's responsibility (health.ts).
34
+ */
35
+ export declare function probeConventions(repo: string): ConventionFinding[];
@@ -0,0 +1,267 @@
1
+ /**
2
+ * conventions.ts — Read-only PROJECT-STANDARDS probes for a single repo (M27).
3
+ *
4
+ * GUARDRAILS (enforced throughout this file):
5
+ * - READ-ONLY: pure FS reads (existsSync / statSync / readFileSync). NO writes,
6
+ * NO git mutations, NO installs, NO shell. NEVER mutates a user repo working tree.
7
+ * - Bounded: a fixed, small set of top-level presence checks + a shallow read of
8
+ * the root package.json; no deep tree traversal, no unbounded loops.
9
+ * - Never throws: returns [] on any error so callers (health.ts) stay unblocked.
10
+ * - No secrets: emitted ConventionFinding values are presence/label metadata only.
11
+ * - Enrollment-scoping is the CALLER's responsibility (health.ts) — this module
12
+ * is a pure probe over whatever absolute path it is handed.
13
+ */
14
+ import { existsSync, statSync, readFileSync } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ // ---------------------------------------------------------------------------
17
+ // Bounds / weights
18
+ // ---------------------------------------------------------------------------
19
+ /** Minimum README size (bytes) below which it is considered "thin". */
20
+ const THIN_README_BYTES = 300;
21
+ /** Fixed candidate name sets (no deep traversal — top-level presence only). */
22
+ const README_NAMES = ['README.md', 'README.txt', 'README', 'readme.md', 'Readme.md'];
23
+ const LICENSE_NAMES = ['LICENSE', 'LICENSE.md', 'LICENSE.txt', 'LICENCE', 'LICENCE.md', 'COPYING'];
24
+ const LOCKFILE_NAMES = [
25
+ 'package-lock.json',
26
+ 'yarn.lock',
27
+ 'pnpm-lock.yaml',
28
+ 'bun.lockb',
29
+ 'Cargo.lock',
30
+ 'poetry.lock',
31
+ 'Pipfile.lock',
32
+ 'go.sum',
33
+ 'composer.lock',
34
+ 'Gemfile.lock',
35
+ ];
36
+ const TEST_DIR_NAMES = ['test', 'tests', '__tests__', 'spec'];
37
+ const CI_PATHS = ['.github/workflows', '.gitlab-ci.yml', '.circleci', 'azure-pipelines.yml', '.travis.yml'];
38
+ // ---------------------------------------------------------------------------
39
+ // Helpers
40
+ // ---------------------------------------------------------------------------
41
+ /** True when ANY of `names` exists directly under `dir`. Never throws. */
42
+ function anyExists(dir, names) {
43
+ for (const name of names) {
44
+ try {
45
+ if (existsSync(join(dir, name)))
46
+ return true;
47
+ }
48
+ catch {
49
+ // ignore — treat as absent
50
+ }
51
+ }
52
+ return false;
53
+ }
54
+ /** Byte size of the first existing file in `names` under `dir`, else 0. */
55
+ function firstSize(dir, names) {
56
+ for (const name of names) {
57
+ const p = join(dir, name);
58
+ try {
59
+ if (existsSync(p))
60
+ return statSync(p).size;
61
+ }
62
+ catch {
63
+ return 0;
64
+ }
65
+ }
66
+ return 0;
67
+ }
68
+ /** True when `name` exists directly under `dir` AND is a directory. Never throws. */
69
+ function dirExists(dir, name) {
70
+ try {
71
+ const p = join(dir, name);
72
+ return existsSync(p) && statSync(p).isDirectory();
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ /**
79
+ * Shallow read of a repo's top-level package.json. Returns null when absent or
80
+ * malformed. Read-only; never throws.
81
+ */
82
+ function readPackageJson(repo) {
83
+ const p = join(repo, 'package.json');
84
+ try {
85
+ if (!existsSync(p))
86
+ return null;
87
+ const raw = readFileSync(p, 'utf8');
88
+ const parsed = JSON.parse(raw);
89
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
90
+ return parsed;
91
+ }
92
+ }
93
+ catch {
94
+ // malformed — treat as absent
95
+ }
96
+ return null;
97
+ }
98
+ /** True when `pkg` has a non-empty "test" script. */
99
+ function hasTestScript(pkg) {
100
+ if (pkg === null)
101
+ return false;
102
+ const scripts = pkg['scripts'];
103
+ if (scripts === null || typeof scripts !== 'object' || Array.isArray(scripts))
104
+ return false;
105
+ const test = scripts['test'];
106
+ return typeof test === 'string' && test.trim() !== '';
107
+ }
108
+ /** True when `pkg` carries a non-empty string field at `key`. */
109
+ function hasStringField(pkg, key) {
110
+ const v = pkg[key];
111
+ return typeof v === 'string' && v.trim() !== '';
112
+ }
113
+ /** True when `pkg` carries a `repository` field (string or object form). */
114
+ function hasRepositoryField(pkg) {
115
+ const v = pkg['repository'];
116
+ if (typeof v === 'string')
117
+ return v.trim() !== '';
118
+ if (typeof v === 'object' && v !== null && !Array.isArray(v)) {
119
+ const url = v['url'];
120
+ return typeof url === 'string' && url.trim() !== '';
121
+ }
122
+ return false;
123
+ }
124
+ // ---------------------------------------------------------------------------
125
+ // probeConventions — the single public entry point
126
+ // ---------------------------------------------------------------------------
127
+ /**
128
+ * Probe `repo` (an absolute path) for project-standard conventions.
129
+ *
130
+ * Returns a deterministic, ordered ConventionFinding[] covering:
131
+ * - README presence + thinness (< THIN_README_BYTES bytes)
132
+ * - LICENSE presence
133
+ * - lockfile presence (package-lock.json / yarn.lock / pnpm-lock.yaml / bun.lockb / Cargo.lock / …)
134
+ * - .gitignore presence
135
+ * - a test signal (test|tests|__tests__|spec dir, or a package.json "test" script)
136
+ * - a CI config presence (.github/workflows / .gitlab-ci.yml / .circleci / …)
137
+ * - (Node projects only) a package.json `license` field
138
+ * - (Node projects only) a package.json `repository` field
139
+ *
140
+ * Pure FS reads, bounded (fixed check list + one shallow package.json read; no
141
+ * deep traversal), NEVER mutates, NEVER throws (returns [] on failure).
142
+ *
143
+ * Mirrors the read-only presence/size heuristics in
144
+ * portfolio/scanners.ts#scanDocs / #scanTests. Enrollment-scoping is the
145
+ * caller's responsibility (health.ts).
146
+ */
147
+ export function probeConventions(repo) {
148
+ try {
149
+ const findings = [];
150
+ const pkg = readPackageJson(repo);
151
+ // 1. README presence + thinness ----------------------------------------
152
+ const hasReadme = anyExists(repo, README_NAMES);
153
+ if (!hasReadme) {
154
+ findings.push({
155
+ key: 'readme',
156
+ label: 'README',
157
+ ok: false,
158
+ weight: 3,
159
+ detail: 'No README file found at the repo root.',
160
+ });
161
+ }
162
+ else {
163
+ const size = firstSize(repo, README_NAMES);
164
+ const thin = size < THIN_README_BYTES;
165
+ findings.push({
166
+ key: 'readme',
167
+ label: 'README',
168
+ ok: !thin,
169
+ weight: 2,
170
+ detail: thin
171
+ ? `README is only ${size} bytes (< ${THIN_README_BYTES}); consider expanding usage/setup.`
172
+ : `README present (${size} bytes).`,
173
+ });
174
+ }
175
+ // 2. LICENSE file presence ---------------------------------------------
176
+ const hasLicenseFile = anyExists(repo, LICENSE_NAMES);
177
+ findings.push({
178
+ key: 'license',
179
+ label: 'LICENSE file',
180
+ ok: hasLicenseFile,
181
+ weight: 3,
182
+ detail: hasLicenseFile
183
+ ? 'LICENSE file present at the repo root.'
184
+ : 'No LICENSE file found at the repo root.',
185
+ });
186
+ // 3. lockfile presence --------------------------------------------------
187
+ const hasLockfile = anyExists(repo, LOCKFILE_NAMES);
188
+ findings.push({
189
+ key: 'lockfile',
190
+ label: 'Dependency lockfile',
191
+ ok: hasLockfile,
192
+ weight: 3,
193
+ detail: hasLockfile
194
+ ? 'A dependency lockfile is present (reproducible installs).'
195
+ : 'No lockfile found (package-lock.json / yarn.lock / pnpm-lock.yaml / Cargo.lock / …).',
196
+ });
197
+ // 4. .gitignore presence ------------------------------------------------
198
+ const hasGitignore = anyExists(repo, ['.gitignore']);
199
+ findings.push({
200
+ key: 'gitignore',
201
+ label: '.gitignore',
202
+ ok: hasGitignore,
203
+ weight: 2,
204
+ detail: hasGitignore
205
+ ? '.gitignore present at the repo root.'
206
+ : 'No .gitignore found at the repo root.',
207
+ });
208
+ // 5. test signal: a test dir OR a package.json "test" script -----------
209
+ const hasTestDir = TEST_DIR_NAMES.some(name => dirExists(repo, name));
210
+ const testScript = hasTestScript(pkg);
211
+ const hasTests = hasTestDir || testScript;
212
+ findings.push({
213
+ key: 'testdir',
214
+ label: 'Test suite signal',
215
+ ok: hasTests,
216
+ weight: 4,
217
+ detail: hasTests
218
+ ? testScript
219
+ ? 'package.json defines a "test" script.'
220
+ : 'A test directory (test/tests/__tests__/spec) is present.'
221
+ : 'No test directory or package.json "test" script found.',
222
+ });
223
+ // 6. CI config presence -------------------------------------------------
224
+ // .github/workflows is a directory; the rest are files — anyExists covers both.
225
+ const hasCi = anyExists(repo, CI_PATHS);
226
+ findings.push({
227
+ key: 'ci',
228
+ label: 'CI configuration',
229
+ ok: hasCi,
230
+ weight: 3,
231
+ detail: hasCi
232
+ ? 'A CI config is present (.github/workflows / .gitlab-ci.yml / …).'
233
+ : 'No CI config found (.github/workflows / .gitlab-ci.yml / .circleci / …).',
234
+ });
235
+ // 7 & 8. package.json metadata fields (Node projects only) -------------
236
+ // Only probed when a parseable package.json exists, so non-Node repos are
237
+ // not penalized for missing npm-specific metadata.
238
+ if (pkg !== null) {
239
+ const hasLicenseField = hasStringField(pkg, 'license');
240
+ findings.push({
241
+ key: 'pkg-license',
242
+ label: 'package.json license field',
243
+ ok: hasLicenseField,
244
+ weight: 2,
245
+ detail: hasLicenseField
246
+ ? 'package.json declares a "license" field.'
247
+ : 'package.json has no "license" field.',
248
+ });
249
+ const hasRepo = hasRepositoryField(pkg);
250
+ findings.push({
251
+ key: 'pkg-repository',
252
+ label: 'package.json repository field',
253
+ ok: hasRepo,
254
+ weight: 1,
255
+ detail: hasRepo
256
+ ? 'package.json declares a "repository" field.'
257
+ : 'package.json has no "repository" field.',
258
+ });
259
+ }
260
+ return findings;
261
+ }
262
+ catch {
263
+ // Any unexpected failure — stay unblocked, report nothing.
264
+ return [];
265
+ }
266
+ }
267
+ //# sourceMappingURL=conventions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../../src/core/quality/conventions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,uEAAuE;AACvE,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,+EAA+E;AAC/E,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AACrF,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AACnG,MAAM,cAAc,GAAG;IACrB,mBAAmB;IACnB,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,cAAc;IACd,QAAQ;IACR,eAAe;IACf,cAAc;CACf,CAAC;AACF,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAC9D,MAAM,QAAQ,GAAG,CAAC,mBAAmB,EAAE,gBAAgB,EAAE,WAAW,EAAE,qBAAqB,EAAE,aAAa,CAAC,CAAC;AAE5G,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,0EAA0E;AAC1E,SAAS,SAAS,CAAC,GAAW,EAAE,KAAe;IAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2EAA2E;AAC3E,SAAS,SAAS,CAAC,GAAW,EAAE,KAAe;IAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC;YACH,IAAI,UAAU,CAAC,CAAC,CAAC;gBAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,qFAAqF;AACrF,SAAS,SAAS,CAAC,GAAW,EAAE,IAAY;IAC1C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACrC,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,OAAO,MAAiC,CAAC;QAC3C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qDAAqD;AACrD,SAAS,aAAa,CAAC,GAAmC;IACxD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5F,MAAM,IAAI,GAAI,OAAmC,CAAC,MAAM,CAAC,CAAC;IAC1D,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AACxD,CAAC;AAED,iEAAiE;AACjE,SAAS,cAAc,CAAC,GAA4B,EAAE,GAAW;IAC/D,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAClD,CAAC;AAED,4EAA4E;AAC5E,SAAS,kBAAkB,CAAC,GAA4B;IACtD,MAAM,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAClD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAI,CAA6B,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,mDAAmD;AACnD,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAElC,yEAAyE;QACzE,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,EAAE,QAAQ;gBACb,KAAK,EAAE,QAAQ;gBACf,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,wCAAwC;aACjD,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,GAAG,iBAAiB,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,EAAE,QAAQ;gBACb,KAAK,EAAE,QAAQ;gBACf,EAAE,EAAE,CAAC,IAAI;gBACT,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,IAAI;oBACV,CAAC,CAAC,kBAAkB,IAAI,aAAa,iBAAiB,oCAAoC;oBAC1F,CAAC,CAAC,mBAAmB,IAAI,UAAU;aACtC,CAAC,CAAC;QACL,CAAC;QAED,yEAAyE;QACzE,MAAM,cAAc,GAAG,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,cAAc;YACrB,EAAE,EAAE,cAAc;YAClB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,cAAc;gBACpB,CAAC,CAAC,wCAAwC;gBAC1C,CAAC,CAAC,yCAAyC;SAC9C,CAAC,CAAC;QAEH,0EAA0E;QAC1E,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,qBAAqB;YAC5B,EAAE,EAAE,WAAW;YACf,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,WAAW;gBACjB,CAAC,CAAC,2DAA2D;gBAC7D,CAAC,CAAC,sFAAsF;SAC3F,CAAC,CAAC;QAEH,0EAA0E;QAC1E,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,YAAY;YACnB,EAAE,EAAE,YAAY;YAChB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,YAAY;gBAClB,CAAC,CAAC,sCAAsC;gBACxC,CAAC,CAAC,uCAAuC;SAC5C,CAAC,CAAC;QAEH,yEAAyE;QACzE,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,UAAU,IAAI,UAAU,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,mBAAmB;YAC1B,EAAE,EAAE,QAAQ;YACZ,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,QAAQ;gBACd,CAAC,CAAC,UAAU;oBACV,CAAC,CAAC,uCAAuC;oBACzC,CAAC,CAAC,0DAA0D;gBAC9D,CAAC,CAAC,wDAAwD;SAC7D,CAAC,CAAC;QAEH,0EAA0E;QAC1E,gFAAgF;QAChF,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxC,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,IAAI;YACT,KAAK,EAAE,kBAAkB;YACzB,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,KAAK;gBACX,CAAC,CAAC,kEAAkE;gBACpE,CAAC,CAAC,0EAA0E;SAC/E,CAAC,CAAC;QAEH,yEAAyE;QACzE,0EAA0E;QAC1E,mDAAmD;QACnD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,MAAM,eAAe,GAAG,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,EAAE,aAAa;gBAClB,KAAK,EAAE,4BAA4B;gBACnC,EAAE,EAAE,eAAe;gBACnB,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,eAAe;oBACrB,CAAC,CAAC,0CAA0C;oBAC5C,CAAC,CAAC,sCAAsC;aAC3C,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC;gBACZ,GAAG,EAAE,gBAAgB;gBACrB,KAAK,EAAE,+BAA+B;gBACtC,EAAE,EAAE,OAAO;gBACX,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,OAAO;oBACb,CAAC,CAAC,6CAA6C;oBAC/C,CAAC,CAAC,yCAAyC;aAC9C,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;QAC3D,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * fixes.ts — Deterministic advisory SAFE FIXES + PROPOSAL emission (M27).
3
+ *
4
+ * HARD SAFETY INVARIANTS (enforced throughout this file):
5
+ * - PROPOSAL-ONLY: emitFixProposals routes each SafeFix to the M23 Approval
6
+ * Inbox via createProposal() as a PENDING proposal (status 'pending', NEVER
7
+ * auto-advanced/applied). The default proposal kind is 'note' (advisory, no
8
+ * diff), origin 'manual'.
9
+ * - READ-ONLY / NO MUTATION: deriveSafeFixes is a pure function of a
10
+ * HealthScore. NEITHER function writes to a user repo, writes CONFIG, pushes,
11
+ * opens a PR, or deploys. There is NO apply path here.
12
+ * - OPTIONAL SANDBOX-PATCH (STRETCH, documented only): if a deterministic fix
13
+ * diff is ever generated, it MUST be produced in an M21 sandbox worktree
14
+ * (src/core/sandbox/*) and attached to a PENDING 'patch' proposal — NEVER
15
+ * written to the real tree, NEVER pushed. The DEFAULT is advisory 'note's.
16
+ * - Bounded: caps fixes emitted per run. Never throws (createProposal best-effort).
17
+ * - No secrets: SafeFix / proposal fields are advisory metadata only.
18
+ */
19
+ import type { HealthScore, Proposal, SafeFix } from '../types.js';
20
+ /**
21
+ * Derive deterministic, advisory SafeFix[] from a per-repo HealthScore.
22
+ *
23
+ * Walks the score's failed convention probes (ok === false) and worst offenders,
24
+ * mapping each actionable, concretely-phraseable gap into an advisory SafeFix:
25
+ * - missing LICENSE -> { dimension:'docs', key:'docs.add-license' }
26
+ * - missing README -> { dimension:'docs', key:'docs.add-readme' }
27
+ * - missing .gitignore -> { dimension:'conventions', key:'conventions.add-gitignore' }
28
+ * - missing lockfile/CI -> { dimension:'conventions', key:'conventions.add-{lockfile,ci}' }
29
+ * - vulnerable/stale dep -> { dimension:'deps', key:'deps.upgrade:<pkg>' }
30
+ * - missing test -> { dimension:'tests', key:'tests.add-test[:…]' }
31
+ * - high TODO debt -> { dimension:'codeDebt', key:'codeDebt.resolve:…' }
32
+ *
33
+ * Pure function (no I/O), deterministic ordering, deduped by `key`, bounded to
34
+ * MAX_FIXES_PER_REPO. Every SafeFix defaults to proposalKind 'note' (advisory).
35
+ * NEVER mutates anything.
36
+ */
37
+ export declare function deriveSafeFixes(score: HealthScore): SafeFix[];
38
+ /**
39
+ * Emit each SafeFix as a PENDING M23 Approval Inbox proposal.
40
+ *
41
+ * For each fix: createProposal({ repo, origin: 'manual', kind: 'note', title,
42
+ * summary }) — status is assigned 'pending' BY THE STORE and NEVER auto-advanced.
43
+ * Default kind is 'note' (advisory, no diff). M27 does NOT apply patches and does
44
+ * NOT mutate working trees here; this module advances no proposal status, pushes
45
+ * nothing, opens no PR, and deploys nothing — createProposal() is its ONLY effect.
46
+ *
47
+ * (STRETCH, NOT wired by default) A fix with proposalKind 'patch' would require
48
+ * generating its diff in an M21 sandbox worktree and attaching it as a PENDING
49
+ * 'patch' proposal with the sandboxId — never written to the real tree. This
50
+ * build emits NOTES ONLY; any 'patch'-kind SafeFix is downgraded to a 'note'
51
+ * proposal here (no diff is produced), keeping the inbox advisory.
52
+ *
53
+ * Returns the created Proposal[] (pending). Never throws (createProposal is
54
+ * best-effort and returns the in-memory proposal even on persistence failure).
55
+ */
56
+ export declare function emitFixProposals(fixes: SafeFix[]): Proposal[];