@zbigniewsobiecki/squint 1.0.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 (649) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1065 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.js +5 -0
  5. package/dist/commands/_shared/db-helper.d.ts +18 -0
  6. package/dist/commands/_shared/db-helper.d.ts.map +1 -0
  7. package/dist/commands/_shared/db-helper.js +72 -0
  8. package/dist/commands/_shared/db-helper.js.map +1 -0
  9. package/dist/commands/_shared/flags.d.ts +20 -0
  10. package/dist/commands/_shared/flags.d.ts.map +1 -0
  11. package/dist/commands/_shared/flags.js +38 -0
  12. package/dist/commands/_shared/flags.js.map +1 -0
  13. package/dist/commands/_shared/index.d.ts +6 -0
  14. package/dist/commands/_shared/index.d.ts.map +1 -0
  15. package/dist/commands/_shared/index.js +6 -0
  16. package/dist/commands/_shared/index.js.map +1 -0
  17. package/dist/commands/_shared/output.d.ts +22 -0
  18. package/dist/commands/_shared/output.d.ts.map +1 -0
  19. package/dist/commands/_shared/output.js +36 -0
  20. package/dist/commands/_shared/output.js.map +1 -0
  21. package/dist/commands/_shared/source-reader.d.ts +23 -0
  22. package/dist/commands/_shared/source-reader.d.ts.map +1 -0
  23. package/dist/commands/_shared/source-reader.js +45 -0
  24. package/dist/commands/_shared/source-reader.js.map +1 -0
  25. package/dist/commands/_shared/symbol-resolver.d.ts +35 -0
  26. package/dist/commands/_shared/symbol-resolver.d.ts.map +1 -0
  27. package/dist/commands/_shared/symbol-resolver.js +102 -0
  28. package/dist/commands/_shared/symbol-resolver.js.map +1 -0
  29. package/dist/commands/browse.d.ts +13 -0
  30. package/dist/commands/browse.d.ts.map +1 -0
  31. package/dist/commands/browse.js +106 -0
  32. package/dist/commands/browse.js.map +1 -0
  33. package/dist/commands/domains/create.d.ts +15 -0
  34. package/dist/commands/domains/create.d.ts.map +1 -0
  35. package/dist/commands/domains/create.js +34 -0
  36. package/dist/commands/domains/create.js.map +1 -0
  37. package/dist/commands/domains/delete.d.ts +14 -0
  38. package/dist/commands/domains/delete.d.ts.map +1 -0
  39. package/dist/commands/domains/delete.js +41 -0
  40. package/dist/commands/domains/delete.js.map +1 -0
  41. package/dist/commands/domains/index.d.ts +2 -0
  42. package/dist/commands/domains/index.d.ts.map +1 -0
  43. package/dist/commands/domains/index.js +2 -0
  44. package/dist/commands/domains/index.js.map +1 -0
  45. package/dist/commands/domains/list.d.ts +12 -0
  46. package/dist/commands/domains/list.d.ts.map +1 -0
  47. package/dist/commands/domains/list.js +67 -0
  48. package/dist/commands/domains/list.js.map +1 -0
  49. package/dist/commands/domains/merge.d.ts +14 -0
  50. package/dist/commands/domains/merge.d.ts.map +1 -0
  51. package/dist/commands/domains/merge.js +40 -0
  52. package/dist/commands/domains/merge.js.map +1 -0
  53. package/dist/commands/domains/rename.d.ts +14 -0
  54. package/dist/commands/domains/rename.d.ts.map +1 -0
  55. package/dist/commands/domains/rename.js +33 -0
  56. package/dist/commands/domains/rename.js.map +1 -0
  57. package/dist/commands/domains/show.d.ts +14 -0
  58. package/dist/commands/domains/show.d.ts.map +1 -0
  59. package/dist/commands/domains/show.js +47 -0
  60. package/dist/commands/domains/show.js.map +1 -0
  61. package/dist/commands/domains/sync.d.ts +11 -0
  62. package/dist/commands/domains/sync.d.ts.map +1 -0
  63. package/dist/commands/domains/sync.js +33 -0
  64. package/dist/commands/domains/sync.js.map +1 -0
  65. package/dist/commands/domains/update.d.ts +14 -0
  66. package/dist/commands/domains/update.d.ts.map +1 -0
  67. package/dist/commands/domains/update.js +28 -0
  68. package/dist/commands/domains/update.js.map +1 -0
  69. package/dist/commands/features/assign.d.ts +16 -0
  70. package/dist/commands/features/assign.d.ts.map +1 -0
  71. package/dist/commands/features/assign.js +51 -0
  72. package/dist/commands/features/assign.js.map +1 -0
  73. package/dist/commands/features/create.d.ts +15 -0
  74. package/dist/commands/features/create.d.ts.map +1 -0
  75. package/dist/commands/features/create.js +30 -0
  76. package/dist/commands/features/create.js.map +1 -0
  77. package/dist/commands/features/delete.d.ts +14 -0
  78. package/dist/commands/features/delete.d.ts.map +1 -0
  79. package/dist/commands/features/delete.js +37 -0
  80. package/dist/commands/features/delete.js.map +1 -0
  81. package/dist/commands/features/generate.d.ts +34 -0
  82. package/dist/commands/features/generate.d.ts.map +1 -0
  83. package/dist/commands/features/generate.js +178 -0
  84. package/dist/commands/features/generate.js.map +1 -0
  85. package/dist/commands/features/index.d.ts +2 -0
  86. package/dist/commands/features/index.d.ts.map +1 -0
  87. package/dist/commands/features/index.js +2 -0
  88. package/dist/commands/features/index.js.map +1 -0
  89. package/dist/commands/features/list.d.ts +11 -0
  90. package/dist/commands/features/list.d.ts.map +1 -0
  91. package/dist/commands/features/list.js +45 -0
  92. package/dist/commands/features/list.js.map +1 -0
  93. package/dist/commands/features/show.d.ts +15 -0
  94. package/dist/commands/features/show.d.ts.map +1 -0
  95. package/dist/commands/features/show.js +61 -0
  96. package/dist/commands/features/show.js.map +1 -0
  97. package/dist/commands/features/unassign.d.ts +16 -0
  98. package/dist/commands/features/unassign.d.ts.map +1 -0
  99. package/dist/commands/features/unassign.js +55 -0
  100. package/dist/commands/features/unassign.js.map +1 -0
  101. package/dist/commands/features/update.d.ts +16 -0
  102. package/dist/commands/features/update.d.ts.map +1 -0
  103. package/dist/commands/features/update.js +54 -0
  104. package/dist/commands/features/update.js.map +1 -0
  105. package/dist/commands/files/imported-by.d.ts +13 -0
  106. package/dist/commands/files/imported-by.d.ts.map +1 -0
  107. package/dist/commands/files/imported-by.js +40 -0
  108. package/dist/commands/files/imported-by.js.map +1 -0
  109. package/dist/commands/files/imports.d.ts +14 -0
  110. package/dist/commands/files/imports.d.ts.map +1 -0
  111. package/dist/commands/files/imports.js +48 -0
  112. package/dist/commands/files/imports.js.map +1 -0
  113. package/dist/commands/files/index.d.ts +2 -0
  114. package/dist/commands/files/index.d.ts.map +1 -0
  115. package/dist/commands/files/index.js +2 -0
  116. package/dist/commands/files/index.js.map +1 -0
  117. package/dist/commands/files/list.d.ts +11 -0
  118. package/dist/commands/files/list.d.ts.map +1 -0
  119. package/dist/commands/files/list.js +35 -0
  120. package/dist/commands/files/list.js.map +1 -0
  121. package/dist/commands/files/orphans.d.ts +12 -0
  122. package/dist/commands/files/orphans.d.ts.map +1 -0
  123. package/dist/commands/files/orphans.js +43 -0
  124. package/dist/commands/files/orphans.js.map +1 -0
  125. package/dist/commands/files/show.d.ts +14 -0
  126. package/dist/commands/files/show.d.ts.map +1 -0
  127. package/dist/commands/files/show.js +95 -0
  128. package/dist/commands/files/show.js.map +1 -0
  129. package/dist/commands/flows/add-step.d.ts +19 -0
  130. package/dist/commands/flows/add-step.d.ts.map +1 -0
  131. package/dist/commands/flows/add-step.js +46 -0
  132. package/dist/commands/flows/add-step.js.map +1 -0
  133. package/dist/commands/flows/create.d.ts +17 -0
  134. package/dist/commands/flows/create.d.ts.map +1 -0
  135. package/dist/commands/flows/create.js +39 -0
  136. package/dist/commands/flows/create.js.map +1 -0
  137. package/dist/commands/flows/delete.d.ts +14 -0
  138. package/dist/commands/flows/delete.d.ts.map +1 -0
  139. package/dist/commands/flows/delete.js +37 -0
  140. package/dist/commands/flows/delete.js.map +1 -0
  141. package/dist/commands/flows/generate.d.ts +50 -0
  142. package/dist/commands/flows/generate.d.ts.map +1 -0
  143. package/dist/commands/flows/generate.js +438 -0
  144. package/dist/commands/flows/generate.js.map +1 -0
  145. package/dist/commands/flows/index.d.ts +2 -0
  146. package/dist/commands/flows/index.d.ts.map +1 -0
  147. package/dist/commands/flows/index.js +2 -0
  148. package/dist/commands/flows/index.js.map +1 -0
  149. package/dist/commands/flows/list.d.ts +12 -0
  150. package/dist/commands/flows/list.d.ts.map +1 -0
  151. package/dist/commands/flows/list.js +98 -0
  152. package/dist/commands/flows/list.js.map +1 -0
  153. package/dist/commands/flows/remove-step.d.ts +18 -0
  154. package/dist/commands/flows/remove-step.d.ts.map +1 -0
  155. package/dist/commands/flows/remove-step.js +41 -0
  156. package/dist/commands/flows/remove-step.js.map +1 -0
  157. package/dist/commands/flows/show.d.ts +17 -0
  158. package/dist/commands/flows/show.d.ts.map +1 -0
  159. package/dist/commands/flows/show.js +136 -0
  160. package/dist/commands/flows/show.js.map +1 -0
  161. package/dist/commands/flows/trace.d.ts +22 -0
  162. package/dist/commands/flows/trace.d.ts.map +1 -0
  163. package/dist/commands/flows/trace.js +217 -0
  164. package/dist/commands/flows/trace.js.map +1 -0
  165. package/dist/commands/flows/update.d.ts +17 -0
  166. package/dist/commands/flows/update.d.ts.map +1 -0
  167. package/dist/commands/flows/update.js +60 -0
  168. package/dist/commands/flows/update.js.map +1 -0
  169. package/dist/commands/flows/verify.d.ts +21 -0
  170. package/dist/commands/flows/verify.d.ts.map +1 -0
  171. package/dist/commands/flows/verify.js +123 -0
  172. package/dist/commands/flows/verify.js.map +1 -0
  173. package/dist/commands/gaps.d.ts +14 -0
  174. package/dist/commands/gaps.d.ts.map +1 -0
  175. package/dist/commands/gaps.js +184 -0
  176. package/dist/commands/gaps.js.map +1 -0
  177. package/dist/commands/hierarchy/index.d.ts +20 -0
  178. package/dist/commands/hierarchy/index.d.ts.map +1 -0
  179. package/dist/commands/hierarchy/index.js +344 -0
  180. package/dist/commands/hierarchy/index.js.map +1 -0
  181. package/dist/commands/ingest.d.ts +23 -0
  182. package/dist/commands/ingest.d.ts.map +1 -0
  183. package/dist/commands/ingest.js +249 -0
  184. package/dist/commands/ingest.js.map +1 -0
  185. package/dist/commands/interactions/create.d.ts +16 -0
  186. package/dist/commands/interactions/create.d.ts.map +1 -0
  187. package/dist/commands/interactions/create.js +58 -0
  188. package/dist/commands/interactions/create.js.map +1 -0
  189. package/dist/commands/interactions/delete.d.ts +16 -0
  190. package/dist/commands/interactions/delete.d.ts.map +1 -0
  191. package/dist/commands/interactions/delete.js +28 -0
  192. package/dist/commands/interactions/delete.js.map +1 -0
  193. package/dist/commands/interactions/generate.d.ts +62 -0
  194. package/dist/commands/interactions/generate.d.ts.map +1 -0
  195. package/dist/commands/interactions/generate.js +870 -0
  196. package/dist/commands/interactions/generate.js.map +1 -0
  197. package/dist/commands/interactions/index.d.ts +2 -0
  198. package/dist/commands/interactions/index.d.ts.map +1 -0
  199. package/dist/commands/interactions/index.js +2 -0
  200. package/dist/commands/interactions/index.js.map +1 -0
  201. package/dist/commands/interactions/list.d.ts +15 -0
  202. package/dist/commands/interactions/list.d.ts.map +1 -0
  203. package/dist/commands/interactions/list.js +127 -0
  204. package/dist/commands/interactions/list.js.map +1 -0
  205. package/dist/commands/interactions/show.d.ts +17 -0
  206. package/dist/commands/interactions/show.d.ts.map +1 -0
  207. package/dist/commands/interactions/show.js +80 -0
  208. package/dist/commands/interactions/show.js.map +1 -0
  209. package/dist/commands/interactions/update.d.ts +20 -0
  210. package/dist/commands/interactions/update.d.ts.map +1 -0
  211. package/dist/commands/interactions/update.js +57 -0
  212. package/dist/commands/interactions/update.js.map +1 -0
  213. package/dist/commands/interactions/validate.d.ts +12 -0
  214. package/dist/commands/interactions/validate.d.ts.map +1 -0
  215. package/dist/commands/interactions/validate.js +94 -0
  216. package/dist/commands/interactions/validate.js.map +1 -0
  217. package/dist/commands/interactions/verify.d.ts +18 -0
  218. package/dist/commands/interactions/verify.d.ts.map +1 -0
  219. package/dist/commands/interactions/verify.js +127 -0
  220. package/dist/commands/interactions/verify.js.map +1 -0
  221. package/dist/commands/llm/_shared/base-llm-command.d.ts +44 -0
  222. package/dist/commands/llm/_shared/base-llm-command.d.ts.map +1 -0
  223. package/dist/commands/llm/_shared/base-llm-command.js +73 -0
  224. package/dist/commands/llm/_shared/base-llm-command.js.map +1 -0
  225. package/dist/commands/llm/_shared/coverage.d.ts +61 -0
  226. package/dist/commands/llm/_shared/coverage.d.ts.map +1 -0
  227. package/dist/commands/llm/_shared/coverage.js +161 -0
  228. package/dist/commands/llm/_shared/coverage.js.map +1 -0
  229. package/dist/commands/llm/_shared/csv-utils.d.ts +65 -0
  230. package/dist/commands/llm/_shared/csv-utils.d.ts.map +1 -0
  231. package/dist/commands/llm/_shared/csv-utils.js +231 -0
  232. package/dist/commands/llm/_shared/csv-utils.js.map +1 -0
  233. package/dist/commands/llm/_shared/csv.d.ts +44 -0
  234. package/dist/commands/llm/_shared/csv.d.ts.map +1 -0
  235. package/dist/commands/llm/_shared/csv.js +76 -0
  236. package/dist/commands/llm/_shared/csv.js.map +1 -0
  237. package/dist/commands/llm/_shared/entity-utils.d.ts +11 -0
  238. package/dist/commands/llm/_shared/entity-utils.d.ts.map +1 -0
  239. package/dist/commands/llm/_shared/entity-utils.js +87 -0
  240. package/dist/commands/llm/_shared/entity-utils.js.map +1 -0
  241. package/dist/commands/llm/_shared/flow-csv.d.ts +74 -0
  242. package/dist/commands/llm/_shared/flow-csv.d.ts.map +1 -0
  243. package/dist/commands/llm/_shared/flow-csv.js +198 -0
  244. package/dist/commands/llm/_shared/flow-csv.js.map +1 -0
  245. package/dist/commands/llm/_shared/flow-prompts.d.ts +61 -0
  246. package/dist/commands/llm/_shared/flow-prompts.d.ts.map +1 -0
  247. package/dist/commands/llm/_shared/flow-prompts.js +281 -0
  248. package/dist/commands/llm/_shared/flow-prompts.js.map +1 -0
  249. package/dist/commands/llm/_shared/flow-validation.d.ts +69 -0
  250. package/dist/commands/llm/_shared/flow-validation.d.ts.map +1 -0
  251. package/dist/commands/llm/_shared/flow-validation.js +176 -0
  252. package/dist/commands/llm/_shared/flow-validation.js.map +1 -0
  253. package/dist/commands/llm/_shared/llm-utils.d.ts +88 -0
  254. package/dist/commands/llm/_shared/llm-utils.d.ts.map +1 -0
  255. package/dist/commands/llm/_shared/llm-utils.js +256 -0
  256. package/dist/commands/llm/_shared/llm-utils.js.map +1 -0
  257. package/dist/commands/llm/_shared/module-csv.d.ts +76 -0
  258. package/dist/commands/llm/_shared/module-csv.d.ts.map +1 -0
  259. package/dist/commands/llm/_shared/module-csv.js +196 -0
  260. package/dist/commands/llm/_shared/module-csv.js.map +1 -0
  261. package/dist/commands/llm/_shared/module-prompts.d.ts +107 -0
  262. package/dist/commands/llm/_shared/module-prompts.d.ts.map +1 -0
  263. package/dist/commands/llm/_shared/module-prompts.js +395 -0
  264. package/dist/commands/llm/_shared/module-prompts.js.map +1 -0
  265. package/dist/commands/llm/_shared/process-utils.d.ts +52 -0
  266. package/dist/commands/llm/_shared/process-utils.d.ts.map +1 -0
  267. package/dist/commands/llm/_shared/process-utils.js +214 -0
  268. package/dist/commands/llm/_shared/process-utils.js.map +1 -0
  269. package/dist/commands/llm/_shared/prompts.d.ts +132 -0
  270. package/dist/commands/llm/_shared/prompts.d.ts.map +1 -0
  271. package/dist/commands/llm/_shared/prompts.js +391 -0
  272. package/dist/commands/llm/_shared/prompts.js.map +1 -0
  273. package/dist/commands/llm/_shared/pure-check.d.ts +10 -0
  274. package/dist/commands/llm/_shared/pure-check.d.ts.map +1 -0
  275. package/dist/commands/llm/_shared/pure-check.js +449 -0
  276. package/dist/commands/llm/_shared/pure-check.js.map +1 -0
  277. package/dist/commands/llm/_shared/verify/content-verifier.d.ts +40 -0
  278. package/dist/commands/llm/_shared/verify/content-verifier.d.ts.map +1 -0
  279. package/dist/commands/llm/_shared/verify/content-verifier.js +247 -0
  280. package/dist/commands/llm/_shared/verify/content-verifier.js.map +1 -0
  281. package/dist/commands/llm/_shared/verify/coverage-checker.d.ts +34 -0
  282. package/dist/commands/llm/_shared/verify/coverage-checker.d.ts.map +1 -0
  283. package/dist/commands/llm/_shared/verify/coverage-checker.js +1096 -0
  284. package/dist/commands/llm/_shared/verify/coverage-checker.js.map +1 -0
  285. package/dist/commands/llm/_shared/verify/verify-prompts.d.ts +30 -0
  286. package/dist/commands/llm/_shared/verify/verify-prompts.d.ts.map +1 -0
  287. package/dist/commands/llm/_shared/verify/verify-prompts.js +118 -0
  288. package/dist/commands/llm/_shared/verify/verify-prompts.js.map +1 -0
  289. package/dist/commands/llm/_shared/verify/verify-types.d.ts +47 -0
  290. package/dist/commands/llm/_shared/verify/verify-types.d.ts.map +1 -0
  291. package/dist/commands/llm/_shared/verify/verify-types.js +2 -0
  292. package/dist/commands/llm/_shared/verify/verify-types.js.map +1 -0
  293. package/dist/commands/llm/annotate.d.ts +7 -0
  294. package/dist/commands/llm/annotate.d.ts.map +1 -0
  295. package/dist/commands/llm/annotate.js +11 -0
  296. package/dist/commands/llm/annotate.js.map +1 -0
  297. package/dist/commands/llm/features/feature-grouper.d.ts +31 -0
  298. package/dist/commands/llm/features/feature-grouper.d.ts.map +1 -0
  299. package/dist/commands/llm/features/feature-grouper.js +223 -0
  300. package/dist/commands/llm/features/feature-grouper.js.map +1 -0
  301. package/dist/commands/llm/features/index.d.ts +6 -0
  302. package/dist/commands/llm/features/index.d.ts.map +1 -0
  303. package/dist/commands/llm/features/index.js +6 -0
  304. package/dist/commands/llm/features/index.js.map +1 -0
  305. package/dist/commands/llm/features/types.d.ts +10 -0
  306. package/dist/commands/llm/features/types.d.ts.map +1 -0
  307. package/dist/commands/llm/features/types.js +5 -0
  308. package/dist/commands/llm/features/types.js.map +1 -0
  309. package/dist/commands/llm/features.d.ts +7 -0
  310. package/dist/commands/llm/features.d.ts.map +1 -0
  311. package/dist/commands/llm/features.js +11 -0
  312. package/dist/commands/llm/features.js.map +1 -0
  313. package/dist/commands/llm/flows/atomic-flow-builder.d.ts +51 -0
  314. package/dist/commands/llm/flows/atomic-flow-builder.d.ts.map +1 -0
  315. package/dist/commands/llm/flows/atomic-flow-builder.js +247 -0
  316. package/dist/commands/llm/flows/atomic-flow-builder.js.map +1 -0
  317. package/dist/commands/llm/flows/dedup.d.ts +18 -0
  318. package/dist/commands/llm/flows/dedup.d.ts.map +1 -0
  319. package/dist/commands/llm/flows/dedup.js +76 -0
  320. package/dist/commands/llm/flows/dedup.js.map +1 -0
  321. package/dist/commands/llm/flows/entry-point-detector.d.ts +41 -0
  322. package/dist/commands/llm/flows/entry-point-detector.d.ts.map +1 -0
  323. package/dist/commands/llm/flows/entry-point-detector.js +388 -0
  324. package/dist/commands/llm/flows/entry-point-detector.js.map +1 -0
  325. package/dist/commands/llm/flows/flow-enhancer.d.ts +21 -0
  326. package/dist/commands/llm/flows/flow-enhancer.d.ts.map +1 -0
  327. package/dist/commands/llm/flows/flow-enhancer.js +166 -0
  328. package/dist/commands/llm/flows/flow-enhancer.js.map +1 -0
  329. package/dist/commands/llm/flows/flow-tracer.d.ts +50 -0
  330. package/dist/commands/llm/flows/flow-tracer.d.ts.map +1 -0
  331. package/dist/commands/llm/flows/flow-tracer.js +271 -0
  332. package/dist/commands/llm/flows/flow-tracer.js.map +1 -0
  333. package/dist/commands/llm/flows/flow-validator.d.ts +31 -0
  334. package/dist/commands/llm/flows/flow-validator.d.ts.map +1 -0
  335. package/dist/commands/llm/flows/flow-validator.js +262 -0
  336. package/dist/commands/llm/flows/flow-validator.js.map +1 -0
  337. package/dist/commands/llm/flows/gap-flow-generator.d.ts +13 -0
  338. package/dist/commands/llm/flows/gap-flow-generator.d.ts.map +1 -0
  339. package/dist/commands/llm/flows/gap-flow-generator.js +48 -0
  340. package/dist/commands/llm/flows/gap-flow-generator.js.map +1 -0
  341. package/dist/commands/llm/flows/index.d.ts +12 -0
  342. package/dist/commands/llm/flows/index.d.ts.map +1 -0
  343. package/dist/commands/llm/flows/index.js +12 -0
  344. package/dist/commands/llm/flows/index.js.map +1 -0
  345. package/dist/commands/llm/flows/types.d.ts +87 -0
  346. package/dist/commands/llm/flows/types.d.ts.map +1 -0
  347. package/dist/commands/llm/flows/types.js +5 -0
  348. package/dist/commands/llm/flows/types.js.map +1 -0
  349. package/dist/commands/llm/flows.d.ts +7 -0
  350. package/dist/commands/llm/flows.d.ts.map +1 -0
  351. package/dist/commands/llm/flows.js +11 -0
  352. package/dist/commands/llm/flows.js.map +1 -0
  353. package/dist/commands/llm/interactions.d.ts +7 -0
  354. package/dist/commands/llm/interactions.d.ts.map +1 -0
  355. package/dist/commands/llm/interactions.js +11 -0
  356. package/dist/commands/llm/interactions.js.map +1 -0
  357. package/dist/commands/llm/modules.d.ts +7 -0
  358. package/dist/commands/llm/modules.d.ts.map +1 -0
  359. package/dist/commands/llm/modules.js +11 -0
  360. package/dist/commands/llm/modules.js.map +1 -0
  361. package/dist/commands/llm/relationships.d.ts +7 -0
  362. package/dist/commands/llm/relationships.d.ts.map +1 -0
  363. package/dist/commands/llm/relationships.js +11 -0
  364. package/dist/commands/llm/relationships.js.map +1 -0
  365. package/dist/commands/modules/assign.d.ts +14 -0
  366. package/dist/commands/modules/assign.d.ts.map +1 -0
  367. package/dist/commands/modules/assign.js +54 -0
  368. package/dist/commands/modules/assign.js.map +1 -0
  369. package/dist/commands/modules/create.d.ts +16 -0
  370. package/dist/commands/modules/create.d.ts.map +1 -0
  371. package/dist/commands/modules/create.js +37 -0
  372. package/dist/commands/modules/create.js.map +1 -0
  373. package/dist/commands/modules/delete.d.ts +14 -0
  374. package/dist/commands/modules/delete.d.ts.map +1 -0
  375. package/dist/commands/modules/delete.js +54 -0
  376. package/dist/commands/modules/delete.js.map +1 -0
  377. package/dist/commands/modules/generate.d.ts +84 -0
  378. package/dist/commands/modules/generate.d.ts.map +1 -0
  379. package/dist/commands/modules/generate.js +1234 -0
  380. package/dist/commands/modules/generate.js.map +1 -0
  381. package/dist/commands/modules/index.d.ts +2 -0
  382. package/dist/commands/modules/index.d.ts.map +1 -0
  383. package/dist/commands/modules/index.js +2 -0
  384. package/dist/commands/modules/index.js.map +1 -0
  385. package/dist/commands/modules/list.d.ts +13 -0
  386. package/dist/commands/modules/list.d.ts.map +1 -0
  387. package/dist/commands/modules/list.js +92 -0
  388. package/dist/commands/modules/list.js.map +1 -0
  389. package/dist/commands/modules/prune.d.ts +10 -0
  390. package/dist/commands/modules/prune.d.ts.map +1 -0
  391. package/dist/commands/modules/prune.js +23 -0
  392. package/dist/commands/modules/prune.js.map +1 -0
  393. package/dist/commands/modules/show.d.ts +15 -0
  394. package/dist/commands/modules/show.d.ts.map +1 -0
  395. package/dist/commands/modules/show.js +95 -0
  396. package/dist/commands/modules/show.js.map +1 -0
  397. package/dist/commands/modules/unassign.d.ts +13 -0
  398. package/dist/commands/modules/unassign.d.ts.map +1 -0
  399. package/dist/commands/modules/unassign.js +49 -0
  400. package/dist/commands/modules/unassign.js.map +1 -0
  401. package/dist/commands/modules/update.d.ts +15 -0
  402. package/dist/commands/modules/update.d.ts.map +1 -0
  403. package/dist/commands/modules/update.js +50 -0
  404. package/dist/commands/modules/update.js.map +1 -0
  405. package/dist/commands/modules/verify.d.ts +18 -0
  406. package/dist/commands/modules/verify.d.ts.map +1 -0
  407. package/dist/commands/modules/verify.js +114 -0
  408. package/dist/commands/modules/verify.js.map +1 -0
  409. package/dist/commands/overview.d.ts +12 -0
  410. package/dist/commands/overview.d.ts.map +1 -0
  411. package/dist/commands/overview.js +219 -0
  412. package/dist/commands/overview.js.map +1 -0
  413. package/dist/commands/parse.d.ts +30 -0
  414. package/dist/commands/parse.d.ts.map +1 -0
  415. package/dist/commands/parse.js +211 -0
  416. package/dist/commands/parse.js.map +1 -0
  417. package/dist/commands/process-groups/index.d.ts +2 -0
  418. package/dist/commands/process-groups/index.d.ts.map +1 -0
  419. package/dist/commands/process-groups/index.js +2 -0
  420. package/dist/commands/process-groups/index.js.map +1 -0
  421. package/dist/commands/process-groups/list.d.ts +11 -0
  422. package/dist/commands/process-groups/list.d.ts.map +1 -0
  423. package/dist/commands/process-groups/list.js +98 -0
  424. package/dist/commands/process-groups/list.js.map +1 -0
  425. package/dist/commands/relationships/annotate.d.ts +27 -0
  426. package/dist/commands/relationships/annotate.d.ts.map +1 -0
  427. package/dist/commands/relationships/annotate.js +453 -0
  428. package/dist/commands/relationships/annotate.js.map +1 -0
  429. package/dist/commands/relationships/index.d.ts +2 -0
  430. package/dist/commands/relationships/index.d.ts.map +1 -0
  431. package/dist/commands/relationships/index.js +2 -0
  432. package/dist/commands/relationships/index.js.map +1 -0
  433. package/dist/commands/relationships/list.d.ts +18 -0
  434. package/dist/commands/relationships/list.d.ts.map +1 -0
  435. package/dist/commands/relationships/list.js +147 -0
  436. package/dist/commands/relationships/list.js.map +1 -0
  437. package/dist/commands/relationships/next.d.ts +17 -0
  438. package/dist/commands/relationships/next.d.ts.map +1 -0
  439. package/dist/commands/relationships/next.js +178 -0
  440. package/dist/commands/relationships/next.js.map +1 -0
  441. package/dist/commands/relationships/set.d.ts +19 -0
  442. package/dist/commands/relationships/set.d.ts.map +1 -0
  443. package/dist/commands/relationships/set.js +65 -0
  444. package/dist/commands/relationships/set.js.map +1 -0
  445. package/dist/commands/relationships/show.d.ts +13 -0
  446. package/dist/commands/relationships/show.d.ts.map +1 -0
  447. package/dist/commands/relationships/show.js +59 -0
  448. package/dist/commands/relationships/show.js.map +1 -0
  449. package/dist/commands/relationships/unset.d.ts +16 -0
  450. package/dist/commands/relationships/unset.d.ts.map +1 -0
  451. package/dist/commands/relationships/unset.js +62 -0
  452. package/dist/commands/relationships/unset.js.map +1 -0
  453. package/dist/commands/relationships/verify.d.ts +24 -0
  454. package/dist/commands/relationships/verify.d.ts.map +1 -0
  455. package/dist/commands/relationships/verify.js +328 -0
  456. package/dist/commands/relationships/verify.js.map +1 -0
  457. package/dist/commands/stats.d.ts +11 -0
  458. package/dist/commands/stats.d.ts.map +1 -0
  459. package/dist/commands/stats.js +207 -0
  460. package/dist/commands/stats.js.map +1 -0
  461. package/dist/commands/symbols/annotate.d.ts +32 -0
  462. package/dist/commands/symbols/annotate.d.ts.map +1 -0
  463. package/dist/commands/symbols/annotate.js +862 -0
  464. package/dist/commands/symbols/annotate.js.map +1 -0
  465. package/dist/commands/symbols/deps.d.ts +18 -0
  466. package/dist/commands/symbols/deps.d.ts.map +1 -0
  467. package/dist/commands/symbols/deps.js +104 -0
  468. package/dist/commands/symbols/deps.js.map +1 -0
  469. package/dist/commands/symbols/index.d.ts +2 -0
  470. package/dist/commands/symbols/index.d.ts.map +1 -0
  471. package/dist/commands/symbols/index.js +2 -0
  472. package/dist/commands/symbols/index.js.map +1 -0
  473. package/dist/commands/symbols/list.d.ts +17 -0
  474. package/dist/commands/symbols/list.d.ts.map +1 -0
  475. package/dist/commands/symbols/list.js +136 -0
  476. package/dist/commands/symbols/list.js.map +1 -0
  477. package/dist/commands/symbols/next.d.ts +15 -0
  478. package/dist/commands/symbols/next.d.ts.map +1 -0
  479. package/dist/commands/symbols/next.js +147 -0
  480. package/dist/commands/symbols/next.js.map +1 -0
  481. package/dist/commands/symbols/prereqs.d.ts +18 -0
  482. package/dist/commands/symbols/prereqs.d.ts.map +1 -0
  483. package/dist/commands/symbols/prereqs.js +107 -0
  484. package/dist/commands/symbols/prereqs.js.map +1 -0
  485. package/dist/commands/symbols/ready.d.ts +17 -0
  486. package/dist/commands/symbols/ready.d.ts.map +1 -0
  487. package/dist/commands/symbols/ready.js +126 -0
  488. package/dist/commands/symbols/ready.js.map +1 -0
  489. package/dist/commands/symbols/set.d.ts +27 -0
  490. package/dist/commands/symbols/set.d.ts.map +1 -0
  491. package/dist/commands/symbols/set.js +241 -0
  492. package/dist/commands/symbols/set.js.map +1 -0
  493. package/dist/commands/symbols/show.d.ts +19 -0
  494. package/dist/commands/symbols/show.d.ts.map +1 -0
  495. package/dist/commands/symbols/show.js +182 -0
  496. package/dist/commands/symbols/show.js.map +1 -0
  497. package/dist/commands/symbols/understood.d.ts +15 -0
  498. package/dist/commands/symbols/understood.d.ts.map +1 -0
  499. package/dist/commands/symbols/understood.js +101 -0
  500. package/dist/commands/symbols/understood.js.map +1 -0
  501. package/dist/commands/symbols/unset.d.ts +16 -0
  502. package/dist/commands/symbols/unset.d.ts.map +1 -0
  503. package/dist/commands/symbols/unset.js +48 -0
  504. package/dist/commands/symbols/unset.js.map +1 -0
  505. package/dist/commands/symbols/verify.d.ts +25 -0
  506. package/dist/commands/symbols/verify.d.ts.map +1 -0
  507. package/dist/commands/symbols/verify.js +360 -0
  508. package/dist/commands/symbols/verify.js.map +1 -0
  509. package/dist/db/connection.d.ts +14 -0
  510. package/dist/db/connection.d.ts.map +1 -0
  511. package/dist/db/connection.js +37 -0
  512. package/dist/db/connection.js.map +1 -0
  513. package/dist/db/database-facade.d.ts +125 -0
  514. package/dist/db/database-facade.d.ts.map +1 -0
  515. package/dist/db/database-facade.js +347 -0
  516. package/dist/db/database-facade.js.map +1 -0
  517. package/dist/db/database.d.ts +9 -0
  518. package/dist/db/database.d.ts.map +1 -0
  519. package/dist/db/database.js +11 -0
  520. package/dist/db/database.js.map +1 -0
  521. package/dist/db/index.d.ts +7 -0
  522. package/dist/db/index.d.ts.map +1 -0
  523. package/dist/db/index.js +11 -0
  524. package/dist/db/index.js.map +1 -0
  525. package/dist/db/repositories/_shared/call-graph-query.d.ts +10 -0
  526. package/dist/db/repositories/_shared/call-graph-query.d.ts.map +1 -0
  527. package/dist/db/repositories/_shared/call-graph-query.js +59 -0
  528. package/dist/db/repositories/_shared/call-graph-query.js.map +1 -0
  529. package/dist/db/repositories/call-graph-service.d.ts +28 -0
  530. package/dist/db/repositories/call-graph-service.d.ts.map +1 -0
  531. package/dist/db/repositories/call-graph-service.js +223 -0
  532. package/dist/db/repositories/call-graph-service.js.map +1 -0
  533. package/dist/db/repositories/definition-repository.d.ts +99 -0
  534. package/dist/db/repositories/definition-repository.d.ts.map +1 -0
  535. package/dist/db/repositories/definition-repository.js +317 -0
  536. package/dist/db/repositories/definition-repository.js.map +1 -0
  537. package/dist/db/repositories/dependency-repository.d.ts +78 -0
  538. package/dist/db/repositories/dependency-repository.d.ts.map +1 -0
  539. package/dist/db/repositories/dependency-repository.js +446 -0
  540. package/dist/db/repositories/dependency-repository.js.map +1 -0
  541. package/dist/db/repositories/domain-repository.d.ts +97 -0
  542. package/dist/db/repositories/domain-repository.d.ts.map +1 -0
  543. package/dist/db/repositories/domain-repository.js +261 -0
  544. package/dist/db/repositories/domain-repository.js.map +1 -0
  545. package/dist/db/repositories/feature-repository.d.ts +64 -0
  546. package/dist/db/repositories/feature-repository.d.ts.map +1 -0
  547. package/dist/db/repositories/feature-repository.js +189 -0
  548. package/dist/db/repositories/feature-repository.js.map +1 -0
  549. package/dist/db/repositories/file-repository.d.ts +67 -0
  550. package/dist/db/repositories/file-repository.d.ts.map +1 -0
  551. package/dist/db/repositories/file-repository.js +179 -0
  552. package/dist/db/repositories/file-repository.js.map +1 -0
  553. package/dist/db/repositories/flow-repository.d.ts +172 -0
  554. package/dist/db/repositories/flow-repository.d.ts.map +1 -0
  555. package/dist/db/repositories/flow-repository.js +599 -0
  556. package/dist/db/repositories/flow-repository.js.map +1 -0
  557. package/dist/db/repositories/graph-repository.d.ts +93 -0
  558. package/dist/db/repositories/graph-repository.d.ts.map +1 -0
  559. package/dist/db/repositories/graph-repository.js +413 -0
  560. package/dist/db/repositories/graph-repository.js.map +1 -0
  561. package/dist/db/repositories/index.d.ts +20 -0
  562. package/dist/db/repositories/index.d.ts.map +1 -0
  563. package/dist/db/repositories/index.js +15 -0
  564. package/dist/db/repositories/index.js.map +1 -0
  565. package/dist/db/repositories/interaction-analysis.d.ts +78 -0
  566. package/dist/db/repositories/interaction-analysis.d.ts.map +1 -0
  567. package/dist/db/repositories/interaction-analysis.js +340 -0
  568. package/dist/db/repositories/interaction-analysis.js.map +1 -0
  569. package/dist/db/repositories/interaction-repository.d.ts +145 -0
  570. package/dist/db/repositories/interaction-repository.d.ts.map +1 -0
  571. package/dist/db/repositories/interaction-repository.js +395 -0
  572. package/dist/db/repositories/interaction-repository.js.map +1 -0
  573. package/dist/db/repositories/metadata-repository.d.ts +110 -0
  574. package/dist/db/repositories/metadata-repository.d.ts.map +1 -0
  575. package/dist/db/repositories/metadata-repository.js +294 -0
  576. package/dist/db/repositories/metadata-repository.js.map +1 -0
  577. package/dist/db/repositories/module-repository.d.ts +162 -0
  578. package/dist/db/repositories/module-repository.d.ts.map +1 -0
  579. package/dist/db/repositories/module-repository.js +519 -0
  580. package/dist/db/repositories/module-repository.js.map +1 -0
  581. package/dist/db/repositories/relationship-repository.d.ts +98 -0
  582. package/dist/db/repositories/relationship-repository.d.ts.map +1 -0
  583. package/dist/db/repositories/relationship-repository.js +421 -0
  584. package/dist/db/repositories/relationship-repository.js.map +1 -0
  585. package/dist/db/schema-manager.d.ts +31 -0
  586. package/dist/db/schema-manager.d.ts.map +1 -0
  587. package/dist/db/schema-manager.js +398 -0
  588. package/dist/db/schema-manager.js.map +1 -0
  589. package/dist/db/schema.d.ts +404 -0
  590. package/dist/db/schema.d.ts.map +1 -0
  591. package/dist/db/schema.js +234 -0
  592. package/dist/db/schema.js.map +1 -0
  593. package/dist/db/utils/tree-builder.d.ts +25 -0
  594. package/dist/db/utils/tree-builder.d.ts.map +1 -0
  595. package/dist/db/utils/tree-builder.js +38 -0
  596. package/dist/db/utils/tree-builder.js.map +1 -0
  597. package/dist/index.d.ts +2 -0
  598. package/dist/index.d.ts.map +1 -0
  599. package/dist/index.js +2 -0
  600. package/dist/index.js.map +1 -0
  601. package/dist/parser/ast-parser.d.ts +23 -0
  602. package/dist/parser/ast-parser.d.ts.map +1 -0
  603. package/dist/parser/ast-parser.js +65 -0
  604. package/dist/parser/ast-parser.js.map +1 -0
  605. package/dist/parser/definition-extractor.d.ts +29 -0
  606. package/dist/parser/definition-extractor.d.ts.map +1 -0
  607. package/dist/parser/definition-extractor.js +379 -0
  608. package/dist/parser/definition-extractor.js.map +1 -0
  609. package/dist/parser/reference-extractor.d.ts +72 -0
  610. package/dist/parser/reference-extractor.d.ts.map +1 -0
  611. package/dist/parser/reference-extractor.js +759 -0
  612. package/dist/parser/reference-extractor.js.map +1 -0
  613. package/dist/utils/file-scanner.d.ts +6 -0
  614. package/dist/utils/file-scanner.d.ts.map +1 -0
  615. package/dist/utils/file-scanner.js +33 -0
  616. package/dist/utils/file-scanner.js.map +1 -0
  617. package/dist/web/api-transforms.d.ts +4 -0
  618. package/dist/web/api-transforms.d.ts.map +1 -0
  619. package/dist/web/api-transforms.js +4 -0
  620. package/dist/web/api-transforms.js.map +1 -0
  621. package/dist/web/server.d.ts +16 -0
  622. package/dist/web/server.d.ts.map +1 -0
  623. package/dist/web/server.js +229 -0
  624. package/dist/web/server.js.map +1 -0
  625. package/dist/web/server.test.d.ts +2 -0
  626. package/dist/web/server.test.d.ts.map +1 -0
  627. package/dist/web/server.test.js +505 -0
  628. package/dist/web/server.test.js.map +1 -0
  629. package/dist/web/transforms/flow-transforms.d.ts +117 -0
  630. package/dist/web/transforms/flow-transforms.d.ts.map +1 -0
  631. package/dist/web/transforms/flow-transforms.js +202 -0
  632. package/dist/web/transforms/flow-transforms.js.map +1 -0
  633. package/dist/web/transforms/index.d.ts +4 -0
  634. package/dist/web/transforms/index.d.ts.map +1 -0
  635. package/dist/web/transforms/index.js +4 -0
  636. package/dist/web/transforms/index.js.map +1 -0
  637. package/dist/web/transforms/module-transforms.d.ts +42 -0
  638. package/dist/web/transforms/module-transforms.d.ts.map +1 -0
  639. package/dist/web/transforms/module-transforms.js +64 -0
  640. package/dist/web/transforms/module-transforms.js.map +1 -0
  641. package/dist/web/transforms/symbol-transforms.d.ts +31 -0
  642. package/dist/web/transforms/symbol-transforms.d.ts.map +1 -0
  643. package/dist/web/transforms/symbol-transforms.js +95 -0
  644. package/dist/web/transforms/symbol-transforms.js.map +1 -0
  645. package/package.json +96 -0
  646. package/ui/dist/assets/index-DP3dRMlh.js +268 -0
  647. package/ui/dist/assets/index-DP3dRMlh.js.map +1 -0
  648. package/ui/dist/assets/index-Db204Xn1.css +1 -0
  649. package/ui/dist/index.html +67 -0
@@ -0,0 +1,1234 @@
1
+ import { Flags } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import path from 'node:path';
4
+ import { LlmFlags, SharedFlags } from '../_shared/index.js';
5
+ import { BaseLlmCommand } from '../llm/_shared/base-llm-command.js';
6
+ import { completeWithLogging, getErrorMessage, logLlmRequest, logLlmResponse, } from '../llm/_shared/llm-utils.js';
7
+ import { isValidModulePath, parseAssignmentCsv, parseDeepenCsv, parseTreeCsv } from '../llm/_shared/module-csv.js';
8
+ import { buildAssignmentSystemPrompt, buildAssignmentUserPrompt, buildBranchPushdownSystemPrompt, buildDeepenSystemPrompt, buildDeepenUserPrompt, buildRebalanceSystemPrompt, buildRebalanceUserPrompt, buildTreeSystemPrompt, buildTreeUserPrompt, isTestFile, toSymbolForAssignment, } from '../llm/_shared/module-prompts.js';
9
+ export default class ModulesGenerate extends BaseLlmCommand {
10
+ static description = 'Create module tree structure and assign symbols using LLM';
11
+ static examples = [
12
+ '<%= config.bin %> modules generate',
13
+ '<%= config.bin %> modules generate --phase tree --dry-run',
14
+ '<%= config.bin %> modules generate --phase assign --batch-size 30',
15
+ '<%= config.bin %> modules generate --force',
16
+ ];
17
+ static flags = {
18
+ database: SharedFlags.database,
19
+ json: SharedFlags.json,
20
+ ...LlmFlags,
21
+ 'max-gate-retries': Flags.integer({
22
+ default: 3,
23
+ description: 'Maximum retry attempts when assignment gate fails',
24
+ }),
25
+ phase: Flags.string({
26
+ options: ['all', 'tree', 'assign'],
27
+ default: 'all',
28
+ description: 'Which phase to run: tree (structure), assign (symbols), or all',
29
+ }),
30
+ 'batch-size': Flags.integer({
31
+ default: 20,
32
+ description: 'Symbols per LLM call during assignment phase',
33
+ }),
34
+ 'max-iterations': Flags.integer({
35
+ default: 100,
36
+ description: 'Maximum LLM iterations for assignment phase',
37
+ }),
38
+ incremental: Flags.boolean({
39
+ default: false,
40
+ description: 'Only assign unassigned symbols (skip tree generation)',
41
+ }),
42
+ 'deepen-threshold': Flags.integer({
43
+ default: 10,
44
+ description: 'Min members before splitting a module (0 to disable deepening)',
45
+ }),
46
+ 'max-unassigned-pct': Flags.integer({
47
+ default: 5,
48
+ description: 'Maximum % of symbols allowed to remain unassigned',
49
+ }),
50
+ 'max-depth': Flags.integer({
51
+ default: 7,
52
+ description: 'Maximum module tree depth (prevents over-nesting during deepening)',
53
+ }),
54
+ 'max-modules': Flags.integer({
55
+ default: 0,
56
+ description: 'Maximum total modules allowed (0 = unlimited)',
57
+ }),
58
+ };
59
+ async execute(ctx, flags) {
60
+ const { db, isJson, dryRun, verbose } = ctx;
61
+ const phase = flags.phase;
62
+ const incremental = flags.incremental;
63
+ const llmLogOptions = {
64
+ showRequests: ctx.llmOptions.showLlmRequests,
65
+ showResponses: ctx.llmOptions.showLlmResponses,
66
+ isJson,
67
+ };
68
+ // Check existing modules
69
+ const existingModuleCount = db.modules.getCount();
70
+ if (!incremental) {
71
+ if (!this.checkExistingAndClear(ctx, {
72
+ entityName: 'Modules',
73
+ existingCount: existingModuleCount,
74
+ force: flags.force,
75
+ clearFn: () => db.modules.clear(),
76
+ forceHint: 'Use --force to recreate or --incremental to assign unassigned symbols',
77
+ })) {
78
+ return;
79
+ }
80
+ }
81
+ const maxModules = flags['max-modules'];
82
+ // Phase 1: Tree Structure Generation
83
+ if ((phase === 'all' || phase === 'tree') && !incremental) {
84
+ await this.runTreePhase(db, flags, dryRun, isJson, verbose, llmLogOptions, maxModules);
85
+ }
86
+ // Phase 2: Symbol Assignment
87
+ if (phase === 'all' || phase === 'assign') {
88
+ await this.runAssignmentPhase(db, flags, dryRun, isJson, verbose, llmLogOptions);
89
+ // Coverage gate: check unassigned % and run catch-up passes if needed
90
+ if (!dryRun) {
91
+ const maxUnassignedPct = flags['max-unassigned-pct'];
92
+ const maxGateRetries = flags['max-gate-retries'];
93
+ await this.runAssignmentCoverageGate(db, flags, maxUnassignedPct, maxGateRetries, isJson, verbose);
94
+ }
95
+ // Deterministic fallback for symbols LLM couldn't assign
96
+ if (!dryRun) {
97
+ const remaining = db.modules.getUnassigned();
98
+ if (remaining.length > 0) {
99
+ const fallbackCount = this.assignByFileCohortFallback(db, isJson, verbose);
100
+ if (fallbackCount > 0 && !isJson) {
101
+ this.log(chalk.green(` Deterministic fallback: assigned ${fallbackCount} remaining symbols`));
102
+ }
103
+ }
104
+ }
105
+ // Prune empty leaf modules after assignment
106
+ if (!dryRun) {
107
+ const pruned = db.modules.pruneEmptyLeaves();
108
+ if (pruned > 0 && !isJson) {
109
+ this.log(chalk.green(` Pruned ${pruned} empty leaf modules`));
110
+ }
111
+ }
112
+ // Phase 3: Deepening (automatic after assignment, unless disabled)
113
+ const deepenThreshold = flags['deepen-threshold'];
114
+ if (deepenThreshold > 0) {
115
+ await this.runDeepenPhase(db, flags, deepenThreshold, dryRun, isJson, verbose, llmLogOptions, maxModules);
116
+ // Prune any modules emptied by reassignment during deepening
117
+ if (!dryRun) {
118
+ const pruned = db.modules.pruneEmptyLeaves();
119
+ if (pruned > 0 && !isJson) {
120
+ this.log(chalk.green(` Pruned ${pruned} empty leaf modules after deepening`));
121
+ }
122
+ }
123
+ }
124
+ }
125
+ // Assign color indices for consistent cross-view coloring
126
+ if (!dryRun) {
127
+ db.modules.assignColorIndices();
128
+ }
129
+ // Final stats
130
+ if (!dryRun) {
131
+ const stats = db.modules.getStats();
132
+ if (isJson) {
133
+ this.log(JSON.stringify(stats));
134
+ }
135
+ else {
136
+ this.log('');
137
+ this.log(chalk.green('Module tree complete.'));
138
+ this.log(chalk.gray(` Modules: ${stats.moduleCount}`));
139
+ this.log(chalk.gray(` Assigned symbols: ${stats.assigned}`));
140
+ this.log(chalk.gray(` Unassigned symbols: ${stats.unassigned}`));
141
+ }
142
+ }
143
+ }
144
+ /**
145
+ * Phase 1: Generate the module tree structure.
146
+ */
147
+ async runTreePhase(db, flags, dryRun, isJson, verbose, llmLogOptions, maxModules) {
148
+ if (!isJson) {
149
+ this.log(chalk.bold('Phase 1: Tree Structure Generation'));
150
+ }
151
+ // Ensure root module exists
152
+ if (!dryRun) {
153
+ db.modules.ensureRoot();
154
+ }
155
+ // Gather context for the LLM
156
+ const context = this.buildTreeContext(db, maxModules);
157
+ if (context.totalSymbolCount === 0) {
158
+ if (isJson) {
159
+ this.log(JSON.stringify({ error: 'No symbols found in database' }));
160
+ }
161
+ else {
162
+ this.log(chalk.yellow('No symbols found in database.'));
163
+ }
164
+ return;
165
+ }
166
+ if (!isJson && verbose) {
167
+ this.log(chalk.gray(` Total symbols: ${context.totalSymbolCount}`));
168
+ this.log(chalk.gray(` Domains found: ${context.domains.length}`));
169
+ }
170
+ // Build prompts
171
+ const systemPrompt = buildTreeSystemPrompt();
172
+ const userPrompt = buildTreeUserPrompt(context);
173
+ if (verbose && !isJson) {
174
+ this.log(chalk.gray(' Calling LLM for tree structure...'));
175
+ }
176
+ logLlmRequest(this, 'runTreePhase', systemPrompt, userPrompt, llmLogOptions);
177
+ // Call LLM
178
+ const response = await completeWithLogging({
179
+ model: flags.model,
180
+ systemPrompt,
181
+ userPrompt,
182
+ temperature: 0,
183
+ command: this,
184
+ isJson,
185
+ });
186
+ logLlmResponse(this, 'runTreePhase', response, llmLogOptions);
187
+ // Parse response
188
+ const { modules: parsedModules, errors } = parseTreeCsv(response);
189
+ if (errors.length > 0 && !isJson) {
190
+ this.log(chalk.yellow(` Parse warnings: ${errors.length}`));
191
+ if (verbose) {
192
+ for (const err of errors.slice(0, 5)) {
193
+ this.log(chalk.gray(` ${err}`));
194
+ }
195
+ }
196
+ }
197
+ if (parsedModules.length === 0) {
198
+ if (isJson) {
199
+ this.log(JSON.stringify({ error: 'No modules parsed from LLM response', parseErrors: errors }));
200
+ }
201
+ else {
202
+ this.log(chalk.red('No modules parsed from LLM response.'));
203
+ }
204
+ return;
205
+ }
206
+ if (dryRun) {
207
+ if (isJson) {
208
+ this.log(JSON.stringify({
209
+ phase: 'tree',
210
+ dryRun: true,
211
+ proposedModules: parsedModules,
212
+ parseErrors: errors,
213
+ }, null, 2));
214
+ }
215
+ else {
216
+ this.log(chalk.gray(` Proposed modules: ${parsedModules.length}`));
217
+ this.log('');
218
+ for (const mod of parsedModules) {
219
+ const fullPath = `${mod.parentPath}.${mod.slug}`;
220
+ this.log(chalk.cyan(` ${fullPath}: ${mod.name}`));
221
+ if (mod.description) {
222
+ this.log(chalk.gray(` ${mod.description}`));
223
+ }
224
+ }
225
+ }
226
+ return;
227
+ }
228
+ // Insert modules in order (parent before child)
229
+ // Sort by parentPath length to ensure parents are created first
230
+ const sortedModules = [...parsedModules].sort((a, b) => {
231
+ const aDepth = a.parentPath.split('.').length;
232
+ const bDepth = b.parentPath.split('.').length;
233
+ return aDepth - bDepth;
234
+ });
235
+ let insertedCount = 0;
236
+ for (const mod of sortedModules) {
237
+ if (maxModules > 0 && db.modules.getCount() >= maxModules) {
238
+ if (!isJson) {
239
+ this.log(chalk.yellow(` Reached max-modules limit (${maxModules}), stopping module creation`));
240
+ }
241
+ break;
242
+ }
243
+ const parent = db.modules.getByPath(mod.parentPath);
244
+ if (!parent) {
245
+ if (verbose && !isJson) {
246
+ this.log(chalk.yellow(` Skipping ${mod.slug}: parent ${mod.parentPath} not found`));
247
+ }
248
+ continue;
249
+ }
250
+ try {
251
+ db.modules.insert(parent.id, mod.slug, mod.name, mod.description, mod.isTest);
252
+ insertedCount++;
253
+ }
254
+ catch (error) {
255
+ if (verbose && !isJson) {
256
+ const message = getErrorMessage(error);
257
+ this.log(chalk.yellow(` Failed to insert ${mod.slug}: ${message}`));
258
+ }
259
+ }
260
+ }
261
+ if (!isJson) {
262
+ this.log(chalk.green(` Created ${insertedCount} modules`));
263
+ }
264
+ }
265
+ /**
266
+ * Phase 2: Assign symbols to modules.
267
+ */
268
+ async runAssignmentPhase(db, flags, dryRun, isJson, verbose, llmLogOptions) {
269
+ if (!isJson) {
270
+ this.log('');
271
+ this.log(chalk.bold('Phase 2: Symbol Assignment'));
272
+ }
273
+ // Get all modules
274
+ const modules = db.modules.getAll();
275
+ if (modules.length === 0) {
276
+ if (isJson) {
277
+ this.log(JSON.stringify({ error: 'No modules found. Run tree phase first.' }));
278
+ }
279
+ else {
280
+ this.log(chalk.yellow('No modules found. Run tree phase first.'));
281
+ }
282
+ return;
283
+ }
284
+ // Build module path lookup
285
+ const moduleByPath = new Map(modules.map((m) => [m.fullPath, m]));
286
+ // Get unassigned symbols
287
+ const unassignedSymbols = db.modules.getUnassigned();
288
+ if (unassignedSymbols.length === 0) {
289
+ if (isJson) {
290
+ this.log(JSON.stringify({ message: 'All symbols already assigned' }));
291
+ }
292
+ else {
293
+ this.log(chalk.green(' All symbols already assigned.'));
294
+ }
295
+ return;
296
+ }
297
+ if (!isJson) {
298
+ this.log(chalk.gray(` Unassigned symbols: ${unassignedSymbols.length}`));
299
+ this.log(chalk.gray(` Available modules: ${modules.length}`));
300
+ }
301
+ const batchSize = flags['batch-size'];
302
+ const maxIterations = flags['max-iterations'];
303
+ const systemPrompt = buildAssignmentSystemPrompt();
304
+ // Auto-adjust max iterations to ensure every symbol gets at least one LLM attempt
305
+ const neededIterations = Math.ceil(unassignedSymbols.length / batchSize);
306
+ const effectiveMaxIterations = Math.max(maxIterations, neededIterations);
307
+ if (effectiveMaxIterations > maxIterations && !isJson) {
308
+ this.log(chalk.gray(` Auto-adjusted max iterations: ${maxIterations} → ${effectiveMaxIterations} (to cover all ${unassignedSymbols.length} symbols)`));
309
+ }
310
+ let totalAssigned = 0;
311
+ let iteration = 0;
312
+ const allAssignments = [];
313
+ let directoryHints;
314
+ // Process in batches
315
+ for (let i = 0; i < unassignedSymbols.length && iteration < effectiveMaxIterations; i += batchSize) {
316
+ iteration++;
317
+ const batch = unassignedSymbols.slice(i, i + batchSize);
318
+ const symbolsForAssignment = batch.map(toSymbolForAssignment);
319
+ // Recompute directory hints every 5 batches (first batch has no hints — no symbols assigned yet)
320
+ if (!dryRun && iteration > 1 && (iteration - 1) % 5 === 0) {
321
+ directoryHints = this.computeModuleDirectoryHints(db);
322
+ }
323
+ if (verbose && !isJson) {
324
+ this.log(chalk.gray(` Batch ${iteration}: ${batch.length} symbols...`));
325
+ }
326
+ const userPrompt = buildAssignmentUserPrompt(modules, symbolsForAssignment, directoryHints);
327
+ try {
328
+ logLlmRequest(this, `runAssignmentPhase-batch${iteration}`, systemPrompt, userPrompt, llmLogOptions);
329
+ const response = await completeWithLogging({
330
+ model: flags.model,
331
+ systemPrompt,
332
+ userPrompt,
333
+ temperature: 0,
334
+ command: this,
335
+ isJson,
336
+ iteration: { current: iteration, max: effectiveMaxIterations },
337
+ });
338
+ logLlmResponse(this, `runAssignmentPhase-batch${iteration}`, response, llmLogOptions);
339
+ const { assignments, errors } = parseAssignmentCsv(response);
340
+ if (errors.length > 0 && verbose && !isJson) {
341
+ this.log(chalk.yellow(` Parse warnings: ${errors.length}`));
342
+ }
343
+ // Validate and apply assignments
344
+ const result = this.applyParsedAssignments(assignments, moduleByPath, db, dryRun, allAssignments);
345
+ totalAssigned += result.assigned;
346
+ if (!isJson && (result.invalidPath > 0 || result.notFound > 0 || result.fuzzy > 0)) {
347
+ const parts = [];
348
+ if (result.fuzzy > 0)
349
+ parts.push(`${result.fuzzy} fuzzy-resolved`);
350
+ if (result.invalidPath > 0)
351
+ parts.push(`${result.invalidPath} invalid-path`);
352
+ if (result.notFound > 0)
353
+ parts.push(`${result.notFound} not-found`);
354
+ this.log(chalk.yellow(` Batch ${iteration}: ${parts.join(', ')}`));
355
+ }
356
+ // Detect omitted symbols and retry once
357
+ const returnedIds = new Set(assignments.map((a) => a.symbolId));
358
+ const omittedSymbols = batch.filter((s) => !returnedIds.has(s.id));
359
+ if (omittedSymbols.length > 0 && omittedSymbols.length <= batchSize / 2) {
360
+ const retrySymbols = omittedSymbols.map(toSymbolForAssignment);
361
+ const retryUserPrompt = buildAssignmentUserPrompt(modules, retrySymbols, directoryHints);
362
+ try {
363
+ const retryResponse = await completeWithLogging({
364
+ model: flags.model,
365
+ systemPrompt,
366
+ userPrompt: retryUserPrompt,
367
+ temperature: 0,
368
+ command: this,
369
+ isJson,
370
+ iteration: { current: iteration, max: effectiveMaxIterations },
371
+ });
372
+ const { assignments: retryAssignments } = parseAssignmentCsv(retryResponse);
373
+ const retryResult = this.applyParsedAssignments(retryAssignments, moduleByPath, db, dryRun, allAssignments);
374
+ totalAssigned += retryResult.assigned;
375
+ if (verbose && !isJson) {
376
+ this.log(chalk.gray(` Retry: ${omittedSymbols.length} omitted → ${retryResult.assigned} assigned`));
377
+ }
378
+ }
379
+ catch {
380
+ // Retry failed — will be caught by coverage gate or fallback
381
+ }
382
+ }
383
+ if (!isJson && !verbose) {
384
+ process.stdout.write(chalk.gray('.'));
385
+ }
386
+ }
387
+ catch (error) {
388
+ const message = getErrorMessage(error);
389
+ if (!isJson) {
390
+ this.log(chalk.red(` Batch ${iteration} failed: ${message}`));
391
+ }
392
+ }
393
+ }
394
+ if (!isJson && !verbose) {
395
+ this.log(''); // New line after dots
396
+ }
397
+ if (dryRun) {
398
+ if (isJson) {
399
+ this.log(JSON.stringify({
400
+ phase: 'assign',
401
+ dryRun: true,
402
+ proposedAssignments: allAssignments,
403
+ totalAssigned,
404
+ }, null, 2));
405
+ }
406
+ else {
407
+ this.log(chalk.gray(` Would assign ${totalAssigned} symbols`));
408
+ }
409
+ return;
410
+ }
411
+ if (!isJson) {
412
+ this.log(chalk.green(` Assigned ${totalAssigned} symbols`));
413
+ }
414
+ }
415
+ /**
416
+ * Coverage gate: check unassigned symbol % and run catch-up passes if needed.
417
+ */
418
+ async runAssignmentCoverageGate(db, flags, maxUnassignedPct, maxGateRetries, isJson, _verbose) {
419
+ const stats = db.modules.getStats();
420
+ const total = stats.assigned + stats.unassigned;
421
+ if (total === 0)
422
+ return;
423
+ let unassignedPct = (stats.unassigned / total) * 100;
424
+ if (unassignedPct <= maxUnassignedPct)
425
+ return;
426
+ if (!isJson) {
427
+ this.log('');
428
+ this.log(chalk.yellow(` ${unassignedPct.toFixed(1)}% symbols still unassigned (threshold: ${maxUnassignedPct}%), running catch-up passes`));
429
+ }
430
+ const modules = db.modules.getAll();
431
+ const moduleByPath = new Map(modules.map((m) => [m.fullPath, m]));
432
+ const batchSize = flags['batch-size'];
433
+ const relaxedSystemPrompt = `You are a software architect assigning symbols to modules.
434
+ Each symbol must be assigned to exactly ONE module path.
435
+
436
+ ## Your Task
437
+ These symbols were difficult to assign in prior passes. Use your best judgment.
438
+ If none of the existing modules fit perfectly, assign to the closest parent module.
439
+
440
+ ## Output Format
441
+ Respond with **only** a CSV table:
442
+
443
+ \`\`\`csv
444
+ type,symbol_id,module_path
445
+ assignment,42,project.frontend.screens.login
446
+ \`\`\`
447
+
448
+ ## Guidelines
449
+ - Every symbol must be assigned to exactly one module
450
+ - Module paths must match existing modules in the tree
451
+ - Prefer more specific modules, but if unsure use the closest parent
452
+ - Consider the file path as a strong hint
453
+ - CRITICAL: Output exactly one assignment row for every symbol listed. Do not skip any.`;
454
+ for (let retry = 0; retry < maxGateRetries; retry++) {
455
+ const unassigned = db.modules.getUnassigned();
456
+ if (unassigned.length === 0)
457
+ break;
458
+ const currentPct = (unassigned.length / total) * 100;
459
+ if (currentPct <= maxUnassignedPct)
460
+ break;
461
+ if (!isJson) {
462
+ this.log(chalk.gray(` Catch-up pass ${retry + 1}/${maxGateRetries}: ${unassigned.length} symbols remaining`));
463
+ }
464
+ let passAssigned = 0;
465
+ let passFuzzy = 0;
466
+ let passInvalidPath = 0;
467
+ let passNotFound = 0;
468
+ let passErrors = 0;
469
+ for (let i = 0; i < unassigned.length; i += batchSize) {
470
+ const batch = unassigned.slice(i, i + batchSize);
471
+ const symbolsForAssignment = batch.map(toSymbolForAssignment);
472
+ const userPrompt = buildAssignmentUserPrompt(modules, symbolsForAssignment);
473
+ try {
474
+ const response = await completeWithLogging({
475
+ model: flags.model,
476
+ systemPrompt: relaxedSystemPrompt,
477
+ userPrompt,
478
+ temperature: 0,
479
+ command: this,
480
+ isJson,
481
+ iteration: { current: retry + 1, max: maxGateRetries },
482
+ });
483
+ const { assignments } = parseAssignmentCsv(response);
484
+ for (const assignment of assignments) {
485
+ if (!isValidModulePath(assignment.modulePath)) {
486
+ passInvalidPath++;
487
+ continue;
488
+ }
489
+ let targetModule = moduleByPath.get(assignment.modulePath);
490
+ if (!targetModule) {
491
+ targetModule = this.resolveModulePath(assignment.modulePath, moduleByPath);
492
+ if (targetModule) {
493
+ passFuzzy++;
494
+ }
495
+ else {
496
+ passNotFound++;
497
+ continue;
498
+ }
499
+ }
500
+ db.modules.assignSymbol(assignment.symbolId, targetModule.id);
501
+ passAssigned++;
502
+ }
503
+ }
504
+ catch (error) {
505
+ passErrors++;
506
+ const message = getErrorMessage(error);
507
+ if (!isJson) {
508
+ this.log(chalk.red(` Catch-up batch error: ${message}`));
509
+ }
510
+ }
511
+ }
512
+ if (!isJson) {
513
+ const parts = [`${passAssigned} assigned`];
514
+ if (passFuzzy > 0)
515
+ parts.push(`${passFuzzy} fuzzy-resolved`);
516
+ if (passInvalidPath > 0)
517
+ parts.push(`${passInvalidPath} invalid-path`);
518
+ if (passNotFound > 0)
519
+ parts.push(`${passNotFound} not-found`);
520
+ if (passErrors > 0)
521
+ parts.push(`${passErrors} errors`);
522
+ this.log(chalk.gray(` Pass ${retry + 1} summary: ${parts.join(', ')}`));
523
+ }
524
+ // Early exit: no progress this pass
525
+ if (passAssigned === 0) {
526
+ if (!isJson) {
527
+ this.log(chalk.yellow(' No progress this pass \u2014 stopping early'));
528
+ }
529
+ break;
530
+ }
531
+ // Re-check
532
+ const updatedStats = db.modules.getStats();
533
+ unassignedPct = (updatedStats.unassigned / total) * 100;
534
+ if (unassignedPct <= maxUnassignedPct) {
535
+ if (!isJson) {
536
+ this.log(chalk.green(` Coverage gate passed: ${unassignedPct.toFixed(1)}% unassigned`));
537
+ }
538
+ return;
539
+ }
540
+ }
541
+ if (!isJson) {
542
+ const finalStats = db.modules.getStats();
543
+ const finalPct = (finalStats.unassigned / total) * 100;
544
+ this.log(chalk.yellow(` Coverage gate: ${finalPct.toFixed(1)}% still unassigned after ${maxGateRetries} retries`));
545
+ }
546
+ }
547
+ /**
548
+ * Phase 3: Deepen large modules by splitting them into sub-modules.
549
+ * Step 1: Rebalance branch modules (has children + direct members) — no new modules created.
550
+ * Step 2: Split leaf modules (largest first) — consumes module budget.
551
+ */
552
+ async runDeepenPhase(db, flags, threshold, dryRun, isJson, verbose, llmLogOptions, maxModules) {
553
+ if (!isJson) {
554
+ this.log('');
555
+ this.log(chalk.bold('Phase 3: Module Deepening'));
556
+ }
557
+ let totalNewModules = 0;
558
+ let totalReassignments = 0;
559
+ let totalRebalanced = 0;
560
+ // Step 1: Rebalance branch modules (no new modules, no budget spent)
561
+ if (!dryRun) {
562
+ const branchModules = db.modules.getBranchModulesWithDirectMembers(threshold);
563
+ if (branchModules.length > 0 && !isJson) {
564
+ this.log(chalk.gray(` Rebalancing ${branchModules.length} branch modules with direct members`));
565
+ }
566
+ for (const mod of branchModules) {
567
+ if (verbose && !isJson) {
568
+ this.log(chalk.gray(` Rebalancing ${mod.fullPath} (${mod.members.length} direct members)...`));
569
+ }
570
+ // Get existing children paths
571
+ const children = db.modules.getChildren(mod.id);
572
+ const childPaths = children.map((c) => c.fullPath);
573
+ if (childPaths.length === 0)
574
+ continue;
575
+ try {
576
+ const rebalanced = await this.rebalanceAncestorSymbols(db, mod.fullPath, childPaths, flags, isJson, verbose, llmLogOptions, true // includeSelf: push branch's own members to children
577
+ );
578
+ totalRebalanced += rebalanced;
579
+ }
580
+ catch (error) {
581
+ const message = getErrorMessage(error);
582
+ if (!isJson) {
583
+ this.log(chalk.red(` Failed to rebalance ${mod.fullPath}: ${message}`));
584
+ }
585
+ }
586
+ }
587
+ }
588
+ // Step 2: Split leaf modules (budget consumed)
589
+ const maxIterations = 5; // Safety limit to prevent infinite loops
590
+ const maxDepth = flags['max-depth'];
591
+ let iteration = 0;
592
+ let hitModuleLimit = false;
593
+ while (iteration < maxIterations && !hitModuleLimit) {
594
+ iteration++;
595
+ // Query leaf modules exceeding threshold (largest first)
596
+ const allLargeLeaves = dryRun
597
+ ? db.modules.getModulesExceedingThreshold(threshold)
598
+ : db.modules.getLeafModulesExceedingThreshold(threshold);
599
+ // Filter out modules already at max depth
600
+ const largeLeaves = allLargeLeaves.filter((m) => m.depth < maxDepth);
601
+ if (largeLeaves.length < allLargeLeaves.length && verbose && !isJson) {
602
+ this.log(chalk.gray(` Skipped ${allLargeLeaves.length - largeLeaves.length} modules at max depth ${maxDepth}`));
603
+ }
604
+ if (largeLeaves.length === 0) {
605
+ if (verbose && !isJson) {
606
+ this.log(chalk.gray(` Iteration ${iteration}: All leaf modules under threshold or at max depth`));
607
+ }
608
+ break;
609
+ }
610
+ if (!isJson) {
611
+ this.log(chalk.gray(` Iteration ${iteration}: ${largeLeaves.length} leaf modules exceed threshold`));
612
+ }
613
+ // Process each large leaf module
614
+ for (const mod of largeLeaves) {
615
+ if (hitModuleLimit)
616
+ break;
617
+ if (verbose && !isJson) {
618
+ this.log(chalk.gray(` Splitting ${mod.fullPath} (${mod.members.length} members)...`));
619
+ }
620
+ // Build prompt data
621
+ const moduleForDeepening = {
622
+ id: mod.id,
623
+ fullPath: mod.fullPath,
624
+ name: mod.name,
625
+ members: mod.members.map((m) => ({
626
+ definitionId: m.definitionId,
627
+ name: m.name,
628
+ kind: m.kind,
629
+ filePath: m.filePath,
630
+ isExported: m.isExported,
631
+ })),
632
+ };
633
+ try {
634
+ const deepenSystemPrompt = buildDeepenSystemPrompt();
635
+ const deepenUserPrompt = buildDeepenUserPrompt(moduleForDeepening);
636
+ logLlmRequest(this, `runDeepenPhase-${mod.fullPath}`, deepenSystemPrompt, deepenUserPrompt, llmLogOptions);
637
+ const response = await completeWithLogging({
638
+ model: flags.model,
639
+ systemPrompt: deepenSystemPrompt,
640
+ userPrompt: deepenUserPrompt,
641
+ temperature: 0,
642
+ command: this,
643
+ isJson,
644
+ });
645
+ logLlmResponse(this, `runDeepenPhase-${mod.fullPath}`, response, llmLogOptions);
646
+ // Parse response
647
+ const { newModules, reassignments, errors } = parseDeepenCsv(response);
648
+ if (errors.length > 0 && verbose && !isJson) {
649
+ this.log(chalk.yellow(` Parse warnings: ${errors.length}`));
650
+ for (const err of errors.slice(0, 3)) {
651
+ this.log(chalk.gray(` ${err}`));
652
+ }
653
+ }
654
+ if (newModules.length === 0) {
655
+ if (verbose && !isJson) {
656
+ this.log(chalk.yellow(` No sub-modules proposed for ${mod.fullPath}`));
657
+ }
658
+ continue;
659
+ }
660
+ if (dryRun) {
661
+ if (verbose && !isJson) {
662
+ this.log(chalk.gray(` Would create ${newModules.length} sub-modules`));
663
+ for (const sub of newModules) {
664
+ this.log(chalk.cyan(` ${mod.fullPath}.${sub.slug}: ${sub.name}`));
665
+ }
666
+ }
667
+ totalNewModules += newModules.length;
668
+ totalReassignments += reassignments.length;
669
+ continue;
670
+ }
671
+ // Create sub-modules
672
+ const createdSubModulePaths = [];
673
+ for (const subMod of newModules) {
674
+ if (maxModules > 0 && db.modules.getCount() >= maxModules) {
675
+ if (!isJson) {
676
+ this.log(chalk.yellow(` Reached max-modules limit (${maxModules}), stopping module creation`));
677
+ }
678
+ hitModuleLimit = true;
679
+ break;
680
+ }
681
+ const parent = db.modules.getByPath(subMod.parentPath);
682
+ if (!parent) {
683
+ if (verbose && !isJson) {
684
+ this.log(chalk.yellow(` Parent not found: ${subMod.parentPath}`));
685
+ }
686
+ continue;
687
+ }
688
+ try {
689
+ // isTest is inherited from parent in ModuleRepository.insert()
690
+ db.modules.insert(parent.id, subMod.slug, subMod.name, subMod.description);
691
+ totalNewModules++;
692
+ createdSubModulePaths.push(`${subMod.parentPath}.${subMod.slug}`);
693
+ }
694
+ catch (error) {
695
+ if (verbose && !isJson) {
696
+ const message = getErrorMessage(error);
697
+ this.log(chalk.yellow(` Failed to create ${subMod.slug}: ${message}`));
698
+ }
699
+ }
700
+ }
701
+ // Reassign symbols to new sub-modules
702
+ for (const reassignment of reassignments) {
703
+ const targetModule = db.modules.getByPath(reassignment.targetModulePath);
704
+ if (!targetModule) {
705
+ if (verbose && !isJson) {
706
+ this.log(chalk.yellow(` Target module not found: ${reassignment.targetModulePath}`));
707
+ }
708
+ continue;
709
+ }
710
+ db.modules.assignSymbol(reassignment.definitionId, targetModule.id);
711
+ totalReassignments++;
712
+ }
713
+ // Rebalance ancestor symbols into new sub-modules
714
+ if (createdSubModulePaths.length > 0 && !hitModuleLimit) {
715
+ const rebalanced = await this.rebalanceAncestorSymbols(db, mod.fullPath, createdSubModulePaths, flags, isJson, verbose, llmLogOptions);
716
+ totalRebalanced += rebalanced;
717
+ }
718
+ }
719
+ catch (error) {
720
+ const message = getErrorMessage(error);
721
+ if (!isJson) {
722
+ this.log(chalk.red(` Failed to process ${mod.fullPath}: ${message}`));
723
+ }
724
+ }
725
+ }
726
+ }
727
+ if (iteration >= maxIterations && !isJson) {
728
+ this.log(chalk.yellow(` Warning: Reached max iterations (${maxIterations})`));
729
+ }
730
+ // Deterministic fallback: push remaining branch members to children by file/directory cohort
731
+ if (!dryRun) {
732
+ const fallbackPushed = this.pushdownBranchMembersFallback(db, isJson, verbose);
733
+ if (fallbackPushed > 0) {
734
+ totalRebalanced += fallbackPushed;
735
+ }
736
+ }
737
+ if (dryRun) {
738
+ if (isJson) {
739
+ this.log(JSON.stringify({
740
+ phase: 'deepen',
741
+ dryRun: true,
742
+ proposedNewModules: totalNewModules,
743
+ proposedReassignments: totalReassignments,
744
+ }));
745
+ }
746
+ else {
747
+ this.log(chalk.gray(` Would create ${totalNewModules} sub-modules`));
748
+ this.log(chalk.gray(` Would reassign ${totalReassignments} symbols`));
749
+ }
750
+ }
751
+ else if (!isJson) {
752
+ this.log(chalk.green(` Created ${totalNewModules} sub-modules`));
753
+ this.log(chalk.green(` Reassigned ${totalReassignments} symbols`));
754
+ if (totalRebalanced > 0) {
755
+ this.log(chalk.green(` Rebalanced ${totalRebalanced} symbols from ancestors`));
756
+ }
757
+ }
758
+ }
759
+ /**
760
+ * Rebalance symbols from ancestor modules into newly created sub-modules.
761
+ * Walks up from the deepened module collecting symbols from ancestors,
762
+ * then asks the LLM if any should be moved into the new sub-structure.
763
+ * Returns the number of symbols rebalanced.
764
+ */
765
+ async rebalanceAncestorSymbols(db, deepenedModulePath, newSubModulePaths, flags, isJson, verbose, llmLogOptions, includeSelf = false) {
766
+ // Walk up from the deepened module to collect ancestor paths (excluding root "project")
767
+ const segments = deepenedModulePath.split('.');
768
+ const ancestorPaths = [];
769
+ // Include the module's own path for branch pushdown
770
+ if (includeSelf) {
771
+ ancestorPaths.push(deepenedModulePath);
772
+ }
773
+ for (let i = segments.length - 1; i >= 1; i--) {
774
+ const ancestorPath = segments.slice(0, i).join('.');
775
+ if (ancestorPath === 'project')
776
+ break; // don't rebalance from root
777
+ ancestorPaths.push(ancestorPath);
778
+ }
779
+ if (ancestorPaths.length === 0)
780
+ return 0;
781
+ // Collect symbols from each ancestor
782
+ const ancestorSymbols = [];
783
+ for (const p of ancestorPaths) {
784
+ const mod = db.modules.getByPath(p);
785
+ if (!mod)
786
+ continue;
787
+ const symbols = db.modules.getSymbols(mod.id);
788
+ if (symbols.length === 0)
789
+ continue;
790
+ ancestorSymbols.push({ moduleId: mod.id, modulePath: p, symbols });
791
+ }
792
+ if (ancestorSymbols.length === 0)
793
+ return 0;
794
+ const totalSymbols = ancestorSymbols.reduce((sum, g) => sum + g.symbols.length, 0);
795
+ if (verbose && !isJson) {
796
+ this.log(chalk.gray(` Rebalancing: ${totalSymbols} ancestor symbols across ${ancestorSymbols.length} modules`));
797
+ }
798
+ // Build info about new sub-modules
799
+ const newSubModules = [];
800
+ for (const subPath of newSubModulePaths) {
801
+ const mod = db.modules.getByPath(subPath);
802
+ if (!mod)
803
+ continue;
804
+ newSubModules.push({ path: mod.fullPath, name: mod.name, description: mod.description });
805
+ }
806
+ if (newSubModules.length === 0)
807
+ return 0;
808
+ // Call LLM for rebalancing — use aggressive prompt for branch pushdown
809
+ const systemPrompt = includeSelf ? buildBranchPushdownSystemPrompt() : buildRebalanceSystemPrompt();
810
+ const userPrompt = buildRebalanceUserPrompt(ancestorSymbols, newSubModules);
811
+ logLlmRequest(this, `rebalance-${deepenedModulePath}`, systemPrompt, userPrompt, llmLogOptions);
812
+ try {
813
+ const response = await completeWithLogging({
814
+ model: flags.model,
815
+ systemPrompt,
816
+ userPrompt,
817
+ temperature: 0,
818
+ command: this,
819
+ isJson,
820
+ });
821
+ logLlmResponse(this, `rebalance-${deepenedModulePath}`, response, llmLogOptions);
822
+ const { assignments, errors } = parseAssignmentCsv(response);
823
+ if (errors.length > 0 && verbose && !isJson) {
824
+ this.log(chalk.yellow(` Rebalance parse warnings: ${errors.length}`));
825
+ }
826
+ // Apply reassignments — only allow moves into the new sub-structure
827
+ const validSubPaths = new Set(newSubModulePaths);
828
+ const subModuleByPath = new Map();
829
+ for (const p of newSubModulePaths) {
830
+ const mod = db.modules.getByPath(p);
831
+ if (mod)
832
+ subModuleByPath.set(p, { id: mod.id, fullPath: mod.fullPath });
833
+ }
834
+ let rebalanced = 0;
835
+ for (const assignment of assignments) {
836
+ let targetModule;
837
+ if (validSubPaths.has(assignment.modulePath)) {
838
+ targetModule = subModuleByPath.get(assignment.modulePath);
839
+ }
840
+ else {
841
+ // Fuzzy resolve constrained to the deepened module prefix
842
+ targetModule = this.resolveModulePath(assignment.modulePath, subModuleByPath, deepenedModulePath);
843
+ }
844
+ if (!targetModule) {
845
+ if (verbose && !isJson) {
846
+ this.log(chalk.yellow(` Rebalance: skipping move to ${assignment.modulePath} (not a new sub-module)`));
847
+ }
848
+ continue;
849
+ }
850
+ db.modules.assignSymbol(assignment.symbolId, targetModule.id);
851
+ rebalanced++;
852
+ }
853
+ if (rebalanced > 0 && verbose && !isJson) {
854
+ this.log(chalk.gray(` Rebalanced ${rebalanced} symbols from ancestors`));
855
+ }
856
+ return rebalanced;
857
+ }
858
+ catch (error) {
859
+ const message = getErrorMessage(error);
860
+ if (verbose && !isJson) {
861
+ this.log(chalk.yellow(` Rebalance failed: ${message}`));
862
+ }
863
+ return 0;
864
+ }
865
+ }
866
+ /**
867
+ * Validate and apply parsed assignment rows.
868
+ * Returns counts of assigned, fuzzy-resolved, invalid-path, and not-found assignments.
869
+ */
870
+ applyParsedAssignments(assignments, moduleByPath, db, dryRun, allAssignments) {
871
+ let assigned = 0;
872
+ let fuzzy = 0;
873
+ let invalidPath = 0;
874
+ let notFound = 0;
875
+ for (const assignment of assignments) {
876
+ if (!isValidModulePath(assignment.modulePath)) {
877
+ invalidPath++;
878
+ continue;
879
+ }
880
+ let targetModule = moduleByPath.get(assignment.modulePath);
881
+ if (!targetModule) {
882
+ targetModule = this.resolveModulePath(assignment.modulePath, moduleByPath);
883
+ if (targetModule) {
884
+ fuzzy++;
885
+ }
886
+ else {
887
+ notFound++;
888
+ continue;
889
+ }
890
+ }
891
+ if (!dryRun) {
892
+ db.modules.assignSymbol(assignment.symbolId, targetModule.id);
893
+ }
894
+ allAssignments.push({ symbolId: assignment.symbolId, modulePath: targetModule.fullPath });
895
+ assigned++;
896
+ }
897
+ return { assigned, fuzzy, invalidPath, notFound };
898
+ }
899
+ /**
900
+ * Resolve a module path against the lookup map.
901
+ * Tries exact match first, then falls back to matching by final segment(s).
902
+ * Returns undefined if no match or ambiguous (multiple candidates).
903
+ */
904
+ resolveModulePath(modulePath, moduleByPath, constrainPrefix) {
905
+ // Exact match
906
+ const exact = moduleByPath.get(modulePath);
907
+ if (exact)
908
+ return exact;
909
+ // Fuzzy: match by final segment(s)
910
+ const segments = modulePath.split('.');
911
+ const candidates = [];
912
+ for (const [fullPath, mod] of moduleByPath) {
913
+ if (constrainPrefix && !fullPath.startsWith(constrainPrefix))
914
+ continue;
915
+ const fullSegments = fullPath.split('.');
916
+ // Check if the path's segments match the tail of the full path
917
+ if (fullSegments.length >= segments.length) {
918
+ const tail = fullSegments.slice(fullSegments.length - segments.length);
919
+ if (tail.every((s, i) => s === segments[i])) {
920
+ candidates.push(mod);
921
+ }
922
+ }
923
+ }
924
+ // Only return if exactly one candidate (avoid ambiguity)
925
+ return candidates.length === 1 ? candidates[0] : undefined;
926
+ }
927
+ /**
928
+ * Compute directory hints for each module based on current member file paths.
929
+ * Returns the top 3 directories per module by member count.
930
+ */
931
+ computeModuleDirectoryHints(db) {
932
+ const hints = new Map();
933
+ for (const mod of db.modules.getAllWithMembers()) {
934
+ if (mod.members.length === 0)
935
+ continue;
936
+ const dirCounts = new Map();
937
+ for (const m of mod.members) {
938
+ const dir = m.filePath.split('/').slice(0, -1).join('/');
939
+ if (dir)
940
+ dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);
941
+ }
942
+ hints.set(mod.id, Array.from(dirCounts.entries())
943
+ .sort((a, b) => b[1] - a[1])
944
+ .slice(0, 3)
945
+ .map(([dir]) => dir));
946
+ }
947
+ return hints;
948
+ }
949
+ /**
950
+ * Deterministic fallback: assign remaining unassigned symbols using file/directory cohort majority.
951
+ * Tier 1: If other symbols in the same file are assigned to a module, assign there.
952
+ * Tier 2: If other symbols in the same directory are assigned to a module, assign there.
953
+ * Walks up parent directories if no match at the immediate level.
954
+ * Test-file guard: test file symbols only assigned to test modules.
955
+ */
956
+ assignByFileCohortFallback(db, isJson, verbose) {
957
+ const allModulesWithMembers = db.modules.getAllWithMembers();
958
+ const allModules = db.modules.getAll();
959
+ const moduleById = new Map(allModules.map((m) => [m.id, m]));
960
+ // Build per-file and per-directory module counts from assigned symbols
961
+ const fileModuleCounts = new Map();
962
+ const dirModuleCounts = new Map();
963
+ for (const mod of allModulesWithMembers) {
964
+ for (const member of mod.members) {
965
+ // Per-file counts
966
+ let fileCounts = fileModuleCounts.get(member.filePath);
967
+ if (!fileCounts) {
968
+ fileCounts = new Map();
969
+ fileModuleCounts.set(member.filePath, fileCounts);
970
+ }
971
+ fileCounts.set(mod.id, (fileCounts.get(mod.id) ?? 0) + 1);
972
+ // Per-directory counts
973
+ const dir = path.dirname(member.filePath);
974
+ if (dir) {
975
+ let dirCounts = dirModuleCounts.get(dir);
976
+ if (!dirCounts) {
977
+ dirCounts = new Map();
978
+ dirModuleCounts.set(dir, dirCounts);
979
+ }
980
+ dirCounts.set(mod.id, (dirCounts.get(mod.id) ?? 0) + 1);
981
+ }
982
+ }
983
+ }
984
+ // Resolve majority module per file
985
+ const fileMajority = new Map();
986
+ for (const [filePath, moduleCounts] of fileModuleCounts) {
987
+ let bestModuleId = -1;
988
+ let bestCount = 0;
989
+ for (const [moduleId, count] of moduleCounts) {
990
+ if (count > bestCount) {
991
+ bestModuleId = moduleId;
992
+ bestCount = count;
993
+ }
994
+ }
995
+ if (bestModuleId >= 0) {
996
+ fileMajority.set(filePath, { moduleId: bestModuleId, count: bestCount });
997
+ }
998
+ }
999
+ // Resolve majority module per directory
1000
+ const dirMajority = new Map();
1001
+ for (const [dir, moduleCounts] of dirModuleCounts) {
1002
+ let bestModuleId = -1;
1003
+ let bestCount = 0;
1004
+ for (const [moduleId, count] of moduleCounts) {
1005
+ if (count > bestCount) {
1006
+ bestModuleId = moduleId;
1007
+ bestCount = count;
1008
+ }
1009
+ }
1010
+ if (bestModuleId >= 0) {
1011
+ dirMajority.set(dir, { moduleId: bestModuleId, count: bestCount });
1012
+ }
1013
+ }
1014
+ const unassigned = db.modules.getUnassigned();
1015
+ let tier1Count = 0;
1016
+ let tier2Count = 0;
1017
+ const stillUnassigned = [];
1018
+ for (const sym of unassigned) {
1019
+ const symIsTest = isTestFile(sym.filePath);
1020
+ // Tier 1: Same-file majority
1021
+ const fileMaj = fileMajority.get(sym.filePath);
1022
+ if (fileMaj) {
1023
+ const mod = moduleById.get(fileMaj.moduleId);
1024
+ if (mod && (!symIsTest || mod.isTest)) {
1025
+ db.modules.assignSymbol(sym.id, fileMaj.moduleId);
1026
+ tier1Count++;
1027
+ continue;
1028
+ }
1029
+ }
1030
+ // Tier 2: Same-directory majority, walking up parent dirs
1031
+ let dir = path.dirname(sym.filePath);
1032
+ let assigned = false;
1033
+ while (dir && dir !== '.' && dir !== '/') {
1034
+ const dirMaj = dirMajority.get(dir);
1035
+ if (dirMaj) {
1036
+ const mod = moduleById.get(dirMaj.moduleId);
1037
+ if (mod && (!symIsTest || mod.isTest)) {
1038
+ db.modules.assignSymbol(sym.id, dirMaj.moduleId);
1039
+ tier2Count++;
1040
+ assigned = true;
1041
+ break;
1042
+ }
1043
+ }
1044
+ dir = path.dirname(dir);
1045
+ }
1046
+ if (!assigned) {
1047
+ stillUnassigned.push(sym);
1048
+ }
1049
+ }
1050
+ if (verbose && !isJson) {
1051
+ this.log(chalk.gray(' Deterministic fallback:'));
1052
+ this.log(chalk.gray(` Tier 1 (file cohort): ${tier1Count} assigned`));
1053
+ this.log(chalk.gray(` Tier 2 (directory cohort): ${tier2Count} assigned`));
1054
+ if (stillUnassigned.length > 0) {
1055
+ this.log(chalk.gray(` Still unassigned: ${stillUnassigned.length}`));
1056
+ }
1057
+ }
1058
+ return tier1Count + tier2Count;
1059
+ }
1060
+ /**
1061
+ * Deterministic fallback: push direct members of branch modules to their children
1062
+ * using file/directory cohort voting. Loops until no more progress.
1063
+ */
1064
+ pushdownBranchMembersFallback(db, isJson, verbose) {
1065
+ let totalPushed = 0;
1066
+ let progress = true;
1067
+ while (progress) {
1068
+ progress = false;
1069
+ const branchModules = db.modules.getBranchModulesWithDirectMembers(0);
1070
+ if (branchModules.length === 0)
1071
+ break;
1072
+ for (const branch of branchModules) {
1073
+ const children = db.modules.getChildren(branch.id);
1074
+ if (children.length === 0)
1075
+ continue;
1076
+ // Build file/directory vote maps from children's members
1077
+ const fileVotes = new Map();
1078
+ const dirVotes = new Map();
1079
+ for (const child of children) {
1080
+ const childMembers = db.modules.getMemberInfo(child.id);
1081
+ for (const member of childMembers) {
1082
+ // File votes
1083
+ let fv = fileVotes.get(member.filePath);
1084
+ if (!fv) {
1085
+ fv = new Map();
1086
+ fileVotes.set(member.filePath, fv);
1087
+ }
1088
+ fv.set(child.id, (fv.get(child.id) ?? 0) + 1);
1089
+ // Directory votes
1090
+ const dir = path.dirname(member.filePath);
1091
+ if (dir) {
1092
+ let dv = dirVotes.get(dir);
1093
+ if (!dv) {
1094
+ dv = new Map();
1095
+ dirVotes.set(dir, dv);
1096
+ }
1097
+ dv.set(child.id, (dv.get(child.id) ?? 0) + 1);
1098
+ }
1099
+ }
1100
+ }
1101
+ // Resolve majority child per file
1102
+ const fileMajority = new Map();
1103
+ for (const [filePath, votes] of fileVotes) {
1104
+ let bestId = -1;
1105
+ let bestCount = 0;
1106
+ for (const [childId, count] of votes) {
1107
+ if (count > bestCount) {
1108
+ bestId = childId;
1109
+ bestCount = count;
1110
+ }
1111
+ }
1112
+ if (bestId >= 0)
1113
+ fileMajority.set(filePath, bestId);
1114
+ }
1115
+ // Resolve majority child per directory
1116
+ const dirMajority = new Map();
1117
+ for (const [dir, votes] of dirVotes) {
1118
+ let bestId = -1;
1119
+ let bestCount = 0;
1120
+ for (const [childId, count] of votes) {
1121
+ if (count > bestCount) {
1122
+ bestId = childId;
1123
+ bestCount = count;
1124
+ }
1125
+ }
1126
+ if (bestId >= 0)
1127
+ dirMajority.set(dir, bestId);
1128
+ }
1129
+ const childById = new Map(children.map((c) => [c.id, c]));
1130
+ for (const member of branch.members) {
1131
+ const symIsTest = isTestFile(member.filePath);
1132
+ let targetChildId;
1133
+ // Tier 1: Same-file majority
1134
+ const fileTarget = fileMajority.get(member.filePath);
1135
+ if (fileTarget !== undefined) {
1136
+ const child = childById.get(fileTarget);
1137
+ if (child && (!symIsTest || child.isTest)) {
1138
+ targetChildId = fileTarget;
1139
+ }
1140
+ }
1141
+ // Tier 2: Same-directory majority (walk up)
1142
+ if (targetChildId === undefined) {
1143
+ let dir = path.dirname(member.filePath);
1144
+ while (dir && dir !== '.' && dir !== '/') {
1145
+ const dirTarget = dirMajority.get(dir);
1146
+ if (dirTarget !== undefined) {
1147
+ const child = childById.get(dirTarget);
1148
+ if (child && (!symIsTest || child.isTest)) {
1149
+ targetChildId = dirTarget;
1150
+ break;
1151
+ }
1152
+ }
1153
+ dir = path.dirname(dir);
1154
+ }
1155
+ }
1156
+ // Tier 3: Single child — move unconditionally
1157
+ if (targetChildId === undefined && children.length === 1) {
1158
+ const child = children[0];
1159
+ if (!symIsTest || child.isTest) {
1160
+ targetChildId = child.id;
1161
+ }
1162
+ }
1163
+ if (targetChildId !== undefined) {
1164
+ db.modules.assignSymbol(member.definitionId, targetChildId);
1165
+ totalPushed++;
1166
+ progress = true;
1167
+ }
1168
+ }
1169
+ }
1170
+ }
1171
+ if (totalPushed > 0 && verbose && !isJson) {
1172
+ this.log(chalk.gray(` Branch pushdown fallback: ${totalPushed} symbols pushed to children`));
1173
+ }
1174
+ return totalPushed;
1175
+ }
1176
+ /**
1177
+ * Build context for tree generation from database.
1178
+ */
1179
+ buildTreeContext(db, maxModules) {
1180
+ // Get all annotated symbols
1181
+ const allSymbols = db.modules.getUnassigned();
1182
+ // Aggregate by domain
1183
+ const domainMap = new Map();
1184
+ for (const sym of allSymbols) {
1185
+ const domains = sym.domain ?? ['untagged'];
1186
+ for (const domain of domains) {
1187
+ const existing = domainMap.get(domain) ?? { count: 0, symbols: [] };
1188
+ existing.count++;
1189
+ if (existing.symbols.length < 10) {
1190
+ existing.symbols.push({ name: sym.name, kind: sym.kind, role: sym.role });
1191
+ }
1192
+ domainMap.set(domain, existing);
1193
+ }
1194
+ }
1195
+ // Convert to DomainSummary array, sorted by count
1196
+ const domains = Array.from(domainMap.entries())
1197
+ .map(([domain, data]) => ({
1198
+ domain,
1199
+ count: data.count,
1200
+ sampleSymbols: data.symbols,
1201
+ }))
1202
+ .sort((a, b) => b.count - a.count);
1203
+ // Count symbols per leaf directory
1204
+ const dirCounts = new Map();
1205
+ for (const sym of allSymbols) {
1206
+ const dir = sym.filePath.split('/').slice(0, -1).join('/');
1207
+ if (dir)
1208
+ dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);
1209
+ }
1210
+ // Build DirectoryInfo[] — include all ancestor directories too, with cumulative counts
1211
+ const allDirs = new Set();
1212
+ for (const sym of allSymbols) {
1213
+ const parts = sym.filePath.split('/');
1214
+ let dirPath = '';
1215
+ for (let i = 0; i < parts.length - 1; i++) {
1216
+ dirPath = dirPath ? `${dirPath}/${parts[i]}` : parts[i];
1217
+ allDirs.add(dirPath);
1218
+ }
1219
+ }
1220
+ const directoryStructure = Array.from(allDirs)
1221
+ .sort()
1222
+ .map((dir) => ({
1223
+ path: dir,
1224
+ symbolCount: dirCounts.get(dir) ?? 0,
1225
+ }));
1226
+ return {
1227
+ totalSymbolCount: allSymbols.length,
1228
+ domains,
1229
+ directoryStructure,
1230
+ maxModules: maxModules && maxModules > 0 ? maxModules : undefined,
1231
+ };
1232
+ }
1233
+ }
1234
+ //# sourceMappingURL=generate.js.map