@untangle-code/cli 0.0.0-stage → 0.1.1

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 (571) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +451 -2
  4. package/THIRD_PARTY_LICENSES.md +152 -0
  5. package/dist/cli/args.d.ts +48 -0
  6. package/dist/cli/args.d.ts.map +1 -0
  7. package/dist/cli/args.js +167 -0
  8. package/dist/cli/args.js.map +1 -0
  9. package/dist/cli/command.d.ts +69 -0
  10. package/dist/cli/command.d.ts.map +1 -0
  11. package/dist/cli/command.js +82 -0
  12. package/dist/cli/command.js.map +1 -0
  13. package/dist/cli/deadline.d.ts +33 -0
  14. package/dist/cli/deadline.d.ts.map +1 -0
  15. package/dist/cli/deadline.js +49 -0
  16. package/dist/cli/deadline.js.map +1 -0
  17. package/dist/cli/embedder-deadline.d.ts +72 -0
  18. package/dist/cli/embedder-deadline.d.ts.map +1 -0
  19. package/dist/cli/embedder-deadline.js +117 -0
  20. package/dist/cli/embedder-deadline.js.map +1 -0
  21. package/dist/cli/exit.d.ts +71 -0
  22. package/dist/cli/exit.d.ts.map +1 -0
  23. package/dist/cli/exit.js +81 -0
  24. package/dist/cli/exit.js.map +1 -0
  25. package/dist/cli/graphs.d.ts +65 -0
  26. package/dist/cli/graphs.d.ts.map +1 -0
  27. package/dist/cli/graphs.js +108 -0
  28. package/dist/cli/graphs.js.map +1 -0
  29. package/dist/cli/index-freshness.d.ts +13 -0
  30. package/dist/cli/index-freshness.d.ts.map +1 -0
  31. package/dist/cli/index-freshness.js +226 -0
  32. package/dist/cli/index-freshness.js.map +1 -0
  33. package/dist/cli/index-refresh.d.ts +10 -0
  34. package/dist/cli/index-refresh.d.ts.map +1 -0
  35. package/dist/cli/index-refresh.js +76 -0
  36. package/dist/cli/index-refresh.js.map +1 -0
  37. package/dist/cli/index-state.d.ts +184 -0
  38. package/dist/cli/index-state.d.ts.map +1 -0
  39. package/dist/cli/index-state.js +852 -0
  40. package/dist/cli/index-state.js.map +1 -0
  41. package/dist/cli/io.d.ts +29 -0
  42. package/dist/cli/io.d.ts.map +1 -0
  43. package/dist/cli/io.js +42 -0
  44. package/dist/cli/io.js.map +1 -0
  45. package/dist/cli/language-support.d.ts +77 -0
  46. package/dist/cli/language-support.d.ts.map +1 -0
  47. package/dist/cli/language-support.js +152 -0
  48. package/dist/cli/language-support.js.map +1 -0
  49. package/dist/cli/renewing-lease.d.ts +26 -0
  50. package/dist/cli/renewing-lease.d.ts.map +1 -0
  51. package/dist/cli/renewing-lease.js +102 -0
  52. package/dist/cli/renewing-lease.js.map +1 -0
  53. package/dist/cli/search-graph-enrichment.d.ts +16 -0
  54. package/dist/cli/search-graph-enrichment.d.ts.map +1 -0
  55. package/dist/cli/search-graph-enrichment.js +428 -0
  56. package/dist/cli/search-graph-enrichment.js.map +1 -0
  57. package/dist/cli/system.d.ts +34 -0
  58. package/dist/cli/system.d.ts.map +1 -0
  59. package/dist/cli/system.js +89 -0
  60. package/dist/cli/system.js.map +1 -0
  61. package/dist/cli/vector-store-policy.d.ts +116 -0
  62. package/dist/cli/vector-store-policy.d.ts.map +1 -0
  63. package/dist/cli/vector-store-policy.js +160 -0
  64. package/dist/cli/vector-store-policy.js.map +1 -0
  65. package/dist/cli/version.d.ts +3 -0
  66. package/dist/cli/version.d.ts.map +1 -0
  67. package/dist/cli/version.js +3 -0
  68. package/dist/cli/version.js.map +1 -0
  69. package/dist/cli/workspace.d.ts +105 -0
  70. package/dist/cli/workspace.d.ts.map +1 -0
  71. package/dist/cli/workspace.js +215 -0
  72. package/dist/cli/workspace.js.map +1 -0
  73. package/dist/commands/complexity.d.ts +72 -0
  74. package/dist/commands/complexity.d.ts.map +1 -0
  75. package/dist/commands/complexity.js +580 -0
  76. package/dist/commands/complexity.js.map +1 -0
  77. package/dist/commands/doctor.d.ts +66 -0
  78. package/dist/commands/doctor.d.ts.map +1 -0
  79. package/dist/commands/doctor.js +764 -0
  80. package/dist/commands/doctor.js.map +1 -0
  81. package/dist/commands/doctor.languages.d.ts +37 -0
  82. package/dist/commands/doctor.languages.d.ts.map +1 -0
  83. package/dist/commands/doctor.languages.js +143 -0
  84. package/dist/commands/doctor.languages.js.map +1 -0
  85. package/dist/commands/doctor.storage.d.ts +17 -0
  86. package/dist/commands/doctor.storage.d.ts.map +1 -0
  87. package/dist/commands/doctor.storage.js +91 -0
  88. package/dist/commands/doctor.storage.js.map +1 -0
  89. package/dist/commands/extensions/add.d.ts +10 -0
  90. package/dist/commands/extensions/add.d.ts.map +1 -0
  91. package/dist/commands/extensions/add.js +213 -0
  92. package/dist/commands/extensions/add.js.map +1 -0
  93. package/dist/commands/extensions/configure.d.ts +5 -0
  94. package/dist/commands/extensions/configure.d.ts.map +1 -0
  95. package/dist/commands/extensions/configure.js +58 -0
  96. package/dist/commands/extensions/configure.js.map +1 -0
  97. package/dist/commands/extensions/container.d.ts +15 -0
  98. package/dist/commands/extensions/container.d.ts.map +1 -0
  99. package/dist/commands/extensions/container.js +135 -0
  100. package/dist/commands/extensions/container.js.map +1 -0
  101. package/dist/commands/extensions/context.d.ts +37 -0
  102. package/dist/commands/extensions/context.d.ts.map +1 -0
  103. package/dist/commands/extensions/context.js +72 -0
  104. package/dist/commands/extensions/context.js.map +1 -0
  105. package/dist/commands/extensions/enable.d.ts +6 -0
  106. package/dist/commands/extensions/enable.d.ts.map +1 -0
  107. package/dist/commands/extensions/enable.js +180 -0
  108. package/dist/commands/extensions/enable.js.map +1 -0
  109. package/dist/commands/extensions/environment.d.ts +74 -0
  110. package/dist/commands/extensions/environment.d.ts.map +1 -0
  111. package/dist/commands/extensions/environment.js +168 -0
  112. package/dist/commands/extensions/environment.js.map +1 -0
  113. package/dist/commands/extensions/feature-scan.d.ts +48 -0
  114. package/dist/commands/extensions/feature-scan.d.ts.map +1 -0
  115. package/dist/commands/extensions/feature-scan.js +156 -0
  116. package/dist/commands/extensions/feature-scan.js.map +1 -0
  117. package/dist/commands/extensions/invoke.d.ts +60 -0
  118. package/dist/commands/extensions/invoke.d.ts.map +1 -0
  119. package/dist/commands/extensions/invoke.js +275 -0
  120. package/dist/commands/extensions/invoke.js.map +1 -0
  121. package/dist/commands/extensions/list.d.ts +5 -0
  122. package/dist/commands/extensions/list.d.ts.map +1 -0
  123. package/dist/commands/extensions/list.js +125 -0
  124. package/dist/commands/extensions/list.js.map +1 -0
  125. package/dist/commands/extensions/logs.d.ts +5 -0
  126. package/dist/commands/extensions/logs.d.ts.map +1 -0
  127. package/dist/commands/extensions/logs.js +74 -0
  128. package/dist/commands/extensions/logs.js.map +1 -0
  129. package/dist/commands/extensions/provision.d.ts +36 -0
  130. package/dist/commands/extensions/provision.d.ts.map +1 -0
  131. package/dist/commands/extensions/provision.js +137 -0
  132. package/dist/commands/extensions/provision.js.map +1 -0
  133. package/dist/commands/extensions/remove.d.ts +5 -0
  134. package/dist/commands/extensions/remove.d.ts.map +1 -0
  135. package/dist/commands/extensions/remove.js +77 -0
  136. package/dist/commands/extensions/remove.js.map +1 -0
  137. package/dist/commands/extensions/render.d.ts +16 -0
  138. package/dist/commands/extensions/render.d.ts.map +1 -0
  139. package/dist/commands/extensions/render.js +25 -0
  140. package/dist/commands/extensions/render.js.map +1 -0
  141. package/dist/commands/extensions/run.d.ts +30 -0
  142. package/dist/commands/extensions/run.d.ts.map +1 -0
  143. package/dist/commands/extensions/run.js +292 -0
  144. package/dist/commands/extensions/run.js.map +1 -0
  145. package/dist/commands/extensions/secret-store.d.ts +15 -0
  146. package/dist/commands/extensions/secret-store.d.ts.map +1 -0
  147. package/dist/commands/extensions/secret-store.js +164 -0
  148. package/dist/commands/extensions/secret-store.js.map +1 -0
  149. package/dist/commands/extensions/setup.d.ts +17 -0
  150. package/dist/commands/extensions/setup.d.ts.map +1 -0
  151. package/dist/commands/extensions/setup.js +94 -0
  152. package/dist/commands/extensions/setup.js.map +1 -0
  153. package/dist/commands/extensions/source.d.ts +47 -0
  154. package/dist/commands/extensions/source.d.ts.map +1 -0
  155. package/dist/commands/extensions/source.js +142 -0
  156. package/dist/commands/extensions/source.js.map +1 -0
  157. package/dist/commands/extensions/state.d.ts +62 -0
  158. package/dist/commands/extensions/state.d.ts.map +1 -0
  159. package/dist/commands/extensions/state.js +177 -0
  160. package/dist/commands/extensions/state.js.map +1 -0
  161. package/dist/commands/extensions/status.d.ts +9 -0
  162. package/dist/commands/extensions/status.d.ts.map +1 -0
  163. package/dist/commands/extensions/status.js +239 -0
  164. package/dist/commands/extensions/status.js.map +1 -0
  165. package/dist/commands/extensions.d.ts +3 -0
  166. package/dist/commands/extensions.d.ts.map +1 -0
  167. package/dist/commands/extensions.js +223 -0
  168. package/dist/commands/extensions.js.map +1 -0
  169. package/dist/commands/flow/index.d.ts +3 -0
  170. package/dist/commands/flow/index.d.ts.map +1 -0
  171. package/dist/commands/flow/index.js +295 -0
  172. package/dist/commands/flow/index.js.map +1 -0
  173. package/dist/commands/flow/limits.d.ts +12 -0
  174. package/dist/commands/flow/limits.d.ts.map +1 -0
  175. package/dist/commands/flow/limits.js +13 -0
  176. package/dist/commands/flow/limits.js.map +1 -0
  177. package/dist/commands/flow/output.d.ts +8 -0
  178. package/dist/commands/flow/output.d.ts.map +1 -0
  179. package/dist/commands/flow/output.js +11 -0
  180. package/dist/commands/flow/output.js.map +1 -0
  181. package/dist/commands/flow/render.d.ts +51 -0
  182. package/dist/commands/flow/render.d.ts.map +1 -0
  183. package/dist/commands/flow/render.js +220 -0
  184. package/dist/commands/flow/render.js.map +1 -0
  185. package/dist/commands/flow/select.d.ts +31 -0
  186. package/dist/commands/flow/select.d.ts.map +1 -0
  187. package/dist/commands/flow/select.js +62 -0
  188. package/dist/commands/flow/select.js.map +1 -0
  189. package/dist/commands/graph/boundaries-input.d.ts +26 -0
  190. package/dist/commands/graph/boundaries-input.d.ts.map +1 -0
  191. package/dist/commands/graph/boundaries-input.js +54 -0
  192. package/dist/commands/graph/boundaries-input.js.map +1 -0
  193. package/dist/commands/graph/boundaries.d.ts +4 -0
  194. package/dist/commands/graph/boundaries.d.ts.map +1 -0
  195. package/dist/commands/graph/boundaries.js +141 -0
  196. package/dist/commands/graph/boundaries.js.map +1 -0
  197. package/dist/commands/graph/bounds.d.ts +16 -0
  198. package/dist/commands/graph/bounds.d.ts.map +1 -0
  199. package/dist/commands/graph/bounds.js +22 -0
  200. package/dist/commands/graph/bounds.js.map +1 -0
  201. package/dist/commands/graph/category-clusters.d.ts +20 -0
  202. package/dist/commands/graph/category-clusters.d.ts.map +1 -0
  203. package/dist/commands/graph/category-clusters.js +158 -0
  204. package/dist/commands/graph/category-clusters.js.map +1 -0
  205. package/dist/commands/graph/feature-3d.d.ts +22 -0
  206. package/dist/commands/graph/feature-3d.d.ts.map +1 -0
  207. package/dist/commands/graph/feature-3d.js +114 -0
  208. package/dist/commands/graph/feature-3d.js.map +1 -0
  209. package/dist/commands/graph/feature-clusters.d.ts +17 -0
  210. package/dist/commands/graph/feature-clusters.d.ts.map +1 -0
  211. package/dist/commands/graph/feature-clusters.js +94 -0
  212. package/dist/commands/graph/feature-clusters.js.map +1 -0
  213. package/dist/commands/graph/feature-html.d.ts +26 -0
  214. package/dist/commands/graph/feature-html.d.ts.map +1 -0
  215. package/dist/commands/graph/feature-html.js +314 -0
  216. package/dist/commands/graph/feature-html.js.map +1 -0
  217. package/dist/commands/graph/feature-map.d.ts +31 -0
  218. package/dist/commands/graph/feature-map.d.ts.map +1 -0
  219. package/dist/commands/graph/feature-map.js +217 -0
  220. package/dist/commands/graph/feature-map.js.map +1 -0
  221. package/dist/commands/graph/feature-model.d.ts +55 -0
  222. package/dist/commands/graph/feature-model.d.ts.map +1 -0
  223. package/dist/commands/graph/feature-model.js +167 -0
  224. package/dist/commands/graph/feature-model.js.map +1 -0
  225. package/dist/commands/graph/feature-untangle-motion.d.ts +33 -0
  226. package/dist/commands/graph/feature-untangle-motion.d.ts.map +1 -0
  227. package/dist/commands/graph/feature-untangle-motion.js +155 -0
  228. package/dist/commands/graph/feature-untangle-motion.js.map +1 -0
  229. package/dist/commands/graph/index.d.ts +3 -0
  230. package/dist/commands/graph/index.d.ts.map +1 -0
  231. package/dist/commands/graph/index.js +414 -0
  232. package/dist/commands/graph/index.js.map +1 -0
  233. package/dist/commands/graph/render.d.ts +63 -0
  234. package/dist/commands/graph/render.d.ts.map +1 -0
  235. package/dist/commands/graph/render.js +352 -0
  236. package/dist/commands/graph/render.js.map +1 -0
  237. package/dist/commands/graph/select.d.ts +34 -0
  238. package/dist/commands/graph/select.d.ts.map +1 -0
  239. package/dist/commands/graph/select.js +55 -0
  240. package/dist/commands/graph/select.js.map +1 -0
  241. package/dist/commands/index/index.d.ts +6 -0
  242. package/dist/commands/index/index.d.ts.map +1 -0
  243. package/dist/commands/index/index.js +461 -0
  244. package/dist/commands/index/index.js.map +1 -0
  245. package/dist/commands/index/render.d.ts +53 -0
  246. package/dist/commands/index/render.d.ts.map +1 -0
  247. package/dist/commands/index/render.js +205 -0
  248. package/dist/commands/index/render.js.map +1 -0
  249. package/dist/commands/index/target.d.ts +34 -0
  250. package/dist/commands/index/target.d.ts.map +1 -0
  251. package/dist/commands/index/target.js +97 -0
  252. package/dist/commands/index/target.js.map +1 -0
  253. package/dist/commands/index-watch.d.ts +30 -0
  254. package/dist/commands/index-watch.d.ts.map +1 -0
  255. package/dist/commands/index-watch.js +138 -0
  256. package/dist/commands/index-watch.js.map +1 -0
  257. package/dist/commands/init/command.d.ts +25 -0
  258. package/dist/commands/init/command.d.ts.map +1 -0
  259. package/dist/commands/init/command.js +198 -0
  260. package/dist/commands/init/command.js.map +1 -0
  261. package/dist/commands/init/config-draft.d.ts +48 -0
  262. package/dist/commands/init/config-draft.d.ts.map +1 -0
  263. package/dist/commands/init/config-draft.js +201 -0
  264. package/dist/commands/init/config-draft.js.map +1 -0
  265. package/dist/commands/init/diff.d.ts +33 -0
  266. package/dist/commands/init/diff.d.ts.map +1 -0
  267. package/dist/commands/init/diff.js +109 -0
  268. package/dist/commands/init/diff.js.map +1 -0
  269. package/dist/commands/init/http-probe.d.ts +26 -0
  270. package/dist/commands/init/http-probe.d.ts.map +1 -0
  271. package/dist/commands/init/http-probe.js +144 -0
  272. package/dist/commands/init/http-probe.js.map +1 -0
  273. package/dist/commands/init/ignore-rules.d.ts +70 -0
  274. package/dist/commands/init/ignore-rules.d.ts.map +1 -0
  275. package/dist/commands/init/ignore-rules.js +146 -0
  276. package/dist/commands/init/ignore-rules.js.map +1 -0
  277. package/dist/commands/init/index.d.ts +33 -0
  278. package/dist/commands/init/index.d.ts.map +1 -0
  279. package/dist/commands/init/index.js +32 -0
  280. package/dist/commands/init/index.js.map +1 -0
  281. package/dist/commands/init/integrations-apply.d.ts +50 -0
  282. package/dist/commands/init/integrations-apply.d.ts.map +1 -0
  283. package/dist/commands/init/integrations-apply.js +452 -0
  284. package/dist/commands/init/integrations-apply.js.map +1 -0
  285. package/dist/commands/init/integrations-plan.d.ts +68 -0
  286. package/dist/commands/init/integrations-plan.d.ts.map +1 -0
  287. package/dist/commands/init/integrations-plan.js +515 -0
  288. package/dist/commands/init/integrations-plan.js.map +1 -0
  289. package/dist/commands/init/integrations.d.ts +5 -0
  290. package/dist/commands/init/integrations.d.ts.map +1 -0
  291. package/dist/commands/init/integrations.js +4 -0
  292. package/dist/commands/init/integrations.js.map +1 -0
  293. package/dist/commands/init/languages.d.ts +55 -0
  294. package/dist/commands/init/languages.d.ts.map +1 -0
  295. package/dist/commands/init/languages.js +245 -0
  296. package/dist/commands/init/languages.js.map +1 -0
  297. package/dist/commands/init/product-context.d.ts +63 -0
  298. package/dist/commands/init/product-context.d.ts.map +1 -0
  299. package/dist/commands/init/product-context.js +390 -0
  300. package/dist/commands/init/product-context.js.map +1 -0
  301. package/dist/commands/init/render.d.ts +38 -0
  302. package/dist/commands/init/render.d.ts.map +1 -0
  303. package/dist/commands/init/render.js +501 -0
  304. package/dist/commands/init/render.js.map +1 -0
  305. package/dist/commands/init/report.d.ts +24 -0
  306. package/dist/commands/init/report.d.ts.map +1 -0
  307. package/dist/commands/init/report.js +163 -0
  308. package/dist/commands/init/report.js.map +1 -0
  309. package/dist/commands/init/run.d.ts +71 -0
  310. package/dist/commands/init/run.d.ts.map +1 -0
  311. package/dist/commands/init/run.js +253 -0
  312. package/dist/commands/init/run.js.map +1 -0
  313. package/dist/commands/init/services.d.ts +82 -0
  314. package/dist/commands/init/services.d.ts.map +1 -0
  315. package/dist/commands/init/services.js +209 -0
  316. package/dist/commands/init/services.js.map +1 -0
  317. package/dist/commands/init/storage.d.ts +8 -0
  318. package/dist/commands/init/storage.d.ts.map +1 -0
  319. package/dist/commands/init/storage.js +102 -0
  320. package/dist/commands/init/storage.js.map +1 -0
  321. package/dist/commands/init/toml.d.ts +65 -0
  322. package/dist/commands/init/toml.d.ts.map +1 -0
  323. package/dist/commands/init/toml.js +159 -0
  324. package/dist/commands/init/toml.js.map +1 -0
  325. package/dist/commands/init/topology.d.ts +54 -0
  326. package/dist/commands/init/topology.d.ts.map +1 -0
  327. package/dist/commands/init/topology.js +146 -0
  328. package/dist/commands/init/topology.js.map +1 -0
  329. package/dist/commands/init/types.d.ts +334 -0
  330. package/dist/commands/init/types.d.ts.map +1 -0
  331. package/dist/commands/init/types.js +31 -0
  332. package/dist/commands/init/types.js.map +1 -0
  333. package/dist/commands/init/wizard-terminal.d.ts +36 -0
  334. package/dist/commands/init/wizard-terminal.d.ts.map +1 -0
  335. package/dist/commands/init/wizard-terminal.js +163 -0
  336. package/dist/commands/init/wizard-terminal.js.map +1 -0
  337. package/dist/commands/init/wizard.d.ts +25 -0
  338. package/dist/commands/init/wizard.d.ts.map +1 -0
  339. package/dist/commands/init/wizard.js +358 -0
  340. package/dist/commands/init/wizard.js.map +1 -0
  341. package/dist/commands/mcp.d.ts +4 -0
  342. package/dist/commands/mcp.d.ts.map +1 -0
  343. package/dist/commands/mcp.js +111 -0
  344. package/dist/commands/mcp.js.map +1 -0
  345. package/dist/commands/product-test-runner.d.ts +4 -0
  346. package/dist/commands/product-test-runner.d.ts.map +1 -0
  347. package/dist/commands/product-test-runner.js +85 -0
  348. package/dist/commands/product-test-runner.js.map +1 -0
  349. package/dist/commands/product.d.ts +16 -0
  350. package/dist/commands/product.d.ts.map +1 -0
  351. package/dist/commands/product.js +262 -0
  352. package/dist/commands/product.js.map +1 -0
  353. package/dist/commands/query.d.ts +114 -0
  354. package/dist/commands/query.d.ts.map +1 -0
  355. package/dist/commands/query.js +783 -0
  356. package/dist/commands/query.js.map +1 -0
  357. package/dist/commands/scan.d.ts +10 -0
  358. package/dist/commands/scan.d.ts.map +1 -0
  359. package/dist/commands/scan.js +302 -0
  360. package/dist/commands/scan.js.map +1 -0
  361. package/dist/commands/sdd.d.ts +24 -0
  362. package/dist/commands/sdd.d.ts.map +1 -0
  363. package/dist/commands/sdd.js +195 -0
  364. package/dist/commands/sdd.js.map +1 -0
  365. package/dist/commands/unavailable.d.ts +40 -0
  366. package/dist/commands/unavailable.d.ts.map +1 -0
  367. package/dist/commands/unavailable.js +73 -0
  368. package/dist/commands/unavailable.js.map +1 -0
  369. package/dist/commands/watch/analyze.d.ts +69 -0
  370. package/dist/commands/watch/analyze.d.ts.map +1 -0
  371. package/dist/commands/watch/analyze.js +402 -0
  372. package/dist/commands/watch/analyze.js.map +1 -0
  373. package/dist/commands/watch/cli.d.ts +8 -0
  374. package/dist/commands/watch/cli.d.ts.map +1 -0
  375. package/dist/commands/watch/cli.js +97 -0
  376. package/dist/commands/watch/cli.js.map +1 -0
  377. package/dist/commands/watch/delta.d.ts +46 -0
  378. package/dist/commands/watch/delta.d.ts.map +1 -0
  379. package/dist/commands/watch/delta.js +170 -0
  380. package/dist/commands/watch/delta.js.map +1 -0
  381. package/dist/commands/watch/events.d.ts +214 -0
  382. package/dist/commands/watch/events.d.ts.map +1 -0
  383. package/dist/commands/watch/events.js +13 -0
  384. package/dist/commands/watch/events.js.map +1 -0
  385. package/dist/commands/watch/index.d.ts +19 -0
  386. package/dist/commands/watch/index.d.ts.map +1 -0
  387. package/dist/commands/watch/index.js +15 -0
  388. package/dist/commands/watch/index.js.map +1 -0
  389. package/dist/commands/watch/options.d.ts +43 -0
  390. package/dist/commands/watch/options.d.ts.map +1 -0
  391. package/dist/commands/watch/options.js +193 -0
  392. package/dist/commands/watch/options.js.map +1 -0
  393. package/dist/commands/watch/render.d.ts +26 -0
  394. package/dist/commands/watch/render.d.ts.map +1 -0
  395. package/dist/commands/watch/render.js +175 -0
  396. package/dist/commands/watch/render.js.map +1 -0
  397. package/dist/commands/watch/run.d.ts +14 -0
  398. package/dist/commands/watch/run.d.ts.map +1 -0
  399. package/dist/commands/watch/run.js +460 -0
  400. package/dist/commands/watch/run.js.map +1 -0
  401. package/dist/commands/watch/runtime.d.ts +67 -0
  402. package/dist/commands/watch/runtime.d.ts.map +1 -0
  403. package/dist/commands/watch/runtime.js +149 -0
  404. package/dist/commands/watch/runtime.js.map +1 -0
  405. package/dist/commands/watch-command.d.ts +3 -0
  406. package/dist/commands/watch-command.d.ts.map +1 -0
  407. package/dist/commands/watch-command.js +273 -0
  408. package/dist/commands/watch-command.js.map +1 -0
  409. package/dist/entry-point.d.ts +11 -0
  410. package/dist/entry-point.d.ts.map +1 -0
  411. package/dist/entry-point.js +65 -0
  412. package/dist/entry-point.js.map +1 -0
  413. package/dist/index.d.ts +38 -0
  414. package/dist/index.d.ts.map +1 -0
  415. package/dist/index.js +245 -0
  416. package/dist/index.js.map +1 -0
  417. package/dist/mcp/boundaries-schema.d.ts +262 -0
  418. package/dist/mcp/boundaries-schema.d.ts.map +1 -0
  419. package/dist/mcp/boundaries-schema.js +183 -0
  420. package/dist/mcp/boundaries-schema.js.map +1 -0
  421. package/dist/mcp/default-runtime.d.ts +16 -0
  422. package/dist/mcp/default-runtime.d.ts.map +1 -0
  423. package/dist/mcp/default-runtime.js +718 -0
  424. package/dist/mcp/default-runtime.js.map +1 -0
  425. package/dist/mcp/envelope.d.ts +13 -0
  426. package/dist/mcp/envelope.d.ts.map +1 -0
  427. package/dist/mcp/envelope.js +29 -0
  428. package/dist/mcp/envelope.js.map +1 -0
  429. package/dist/mcp/index.d.ts +8 -0
  430. package/dist/mcp/index.d.ts.map +1 -0
  431. package/dist/mcp/index.js +8 -0
  432. package/dist/mcp/index.js.map +1 -0
  433. package/dist/mcp/output-schemas.d.ts +5928 -0
  434. package/dist/mcp/output-schemas.d.ts.map +1 -0
  435. package/dist/mcp/output-schemas.js +2814 -0
  436. package/dist/mcp/output-schemas.js.map +1 -0
  437. package/dist/mcp/path-sandbox.d.ts +35 -0
  438. package/dist/mcp/path-sandbox.d.ts.map +1 -0
  439. package/dist/mcp/path-sandbox.js +128 -0
  440. package/dist/mcp/path-sandbox.js.map +1 -0
  441. package/dist/mcp/server.d.ts +155 -0
  442. package/dist/mcp/server.d.ts.map +1 -0
  443. package/dist/mcp/server.js +257 -0
  444. package/dist/mcp/server.js.map +1 -0
  445. package/dist/mcp/stdio.d.ts +20 -0
  446. package/dist/mcp/stdio.d.ts.map +1 -0
  447. package/dist/mcp/stdio.js +71 -0
  448. package/dist/mcp/stdio.js.map +1 -0
  449. package/dist/mcp/tools.d.ts +355 -0
  450. package/dist/mcp/tools.d.ts.map +1 -0
  451. package/dist/mcp/tools.js +319 -0
  452. package/dist/mcp/tools.js.map +1 -0
  453. package/dist/mcp/types.d.ts +15 -0
  454. package/dist/mcp/types.d.ts.map +1 -0
  455. package/dist/mcp/types.js +45 -0
  456. package/dist/mcp/types.js.map +1 -0
  457. package/package.json +99 -3
  458. package/src/cli/args.ts +231 -0
  459. package/src/cli/command.ts +146 -0
  460. package/src/cli/deadline.ts +56 -0
  461. package/src/cli/embedder-deadline.ts +187 -0
  462. package/src/cli/exit.ts +94 -0
  463. package/src/cli/graphs.ts +191 -0
  464. package/src/cli/index-freshness.ts +303 -0
  465. package/src/cli/index-refresh.ts +125 -0
  466. package/src/cli/index-state.ts +1217 -0
  467. package/src/cli/io.ts +56 -0
  468. package/src/cli/language-support.ts +203 -0
  469. package/src/cli/renewing-lease.ts +121 -0
  470. package/src/cli/search-graph-enrichment.ts +639 -0
  471. package/src/cli/system.ts +94 -0
  472. package/src/cli/vector-store-policy.ts +213 -0
  473. package/src/cli/version.ts +2 -0
  474. package/src/cli/workspace.ts +324 -0
  475. package/src/commands/complexity.ts +776 -0
  476. package/src/commands/doctor.languages.ts +187 -0
  477. package/src/commands/doctor.storage.ts +124 -0
  478. package/src/commands/doctor.ts +946 -0
  479. package/src/commands/extensions/add.ts +312 -0
  480. package/src/commands/extensions/configure.ts +82 -0
  481. package/src/commands/extensions/container.ts +209 -0
  482. package/src/commands/extensions/context.ts +109 -0
  483. package/src/commands/extensions/enable.ts +237 -0
  484. package/src/commands/extensions/environment.ts +218 -0
  485. package/src/commands/extensions/feature-scan.ts +232 -0
  486. package/src/commands/extensions/invoke.ts +368 -0
  487. package/src/commands/extensions/list.ts +158 -0
  488. package/src/commands/extensions/logs.ts +104 -0
  489. package/src/commands/extensions/provision.ts +206 -0
  490. package/src/commands/extensions/remove.ts +110 -0
  491. package/src/commands/extensions/render.ts +32 -0
  492. package/src/commands/extensions/run.ts +386 -0
  493. package/src/commands/extensions/secret-store.ts +223 -0
  494. package/src/commands/extensions/setup.ts +140 -0
  495. package/src/commands/extensions/source.ts +189 -0
  496. package/src/commands/extensions/state.ts +252 -0
  497. package/src/commands/extensions/status.ts +320 -0
  498. package/src/commands/extensions.ts +280 -0
  499. package/src/commands/flow/index.ts +402 -0
  500. package/src/commands/flow/limits.ts +14 -0
  501. package/src/commands/flow/output.ts +16 -0
  502. package/src/commands/flow/render.ts +318 -0
  503. package/src/commands/flow/select.ts +101 -0
  504. package/src/commands/graph/boundaries-input.ts +63 -0
  505. package/src/commands/graph/boundaries.ts +182 -0
  506. package/src/commands/graph/bounds.ts +25 -0
  507. package/src/commands/graph/category-clusters.ts +194 -0
  508. package/src/commands/graph/feature-3d.ts +141 -0
  509. package/src/commands/graph/feature-clusters.ts +125 -0
  510. package/src/commands/graph/feature-html.ts +336 -0
  511. package/src/commands/graph/feature-map.ts +270 -0
  512. package/src/commands/graph/feature-model.ts +234 -0
  513. package/src/commands/graph/feature-untangle-motion.ts +192 -0
  514. package/src/commands/graph/index.ts +562 -0
  515. package/src/commands/graph/render.ts +503 -0
  516. package/src/commands/graph/select.ts +77 -0
  517. package/src/commands/index/index.ts +595 -0
  518. package/src/commands/index/render.ts +325 -0
  519. package/src/commands/index/target.ts +136 -0
  520. package/src/commands/index-watch.ts +206 -0
  521. package/src/commands/init/command.ts +238 -0
  522. package/src/commands/init/config-draft.ts +235 -0
  523. package/src/commands/init/diff.ts +117 -0
  524. package/src/commands/init/http-probe.ts +150 -0
  525. package/src/commands/init/ignore-rules.ts +170 -0
  526. package/src/commands/init/index.ts +63 -0
  527. package/src/commands/init/integrations-apply.ts +618 -0
  528. package/src/commands/init/integrations-plan.ts +634 -0
  529. package/src/commands/init/integrations.ts +8 -0
  530. package/src/commands/init/languages.ts +320 -0
  531. package/src/commands/init/product-context.ts +576 -0
  532. package/src/commands/init/render.ts +598 -0
  533. package/src/commands/init/report.ts +204 -0
  534. package/src/commands/init/run.ts +349 -0
  535. package/src/commands/init/services.ts +271 -0
  536. package/src/commands/init/storage.ts +136 -0
  537. package/src/commands/init/toml.ts +174 -0
  538. package/src/commands/init/topology.ts +192 -0
  539. package/src/commands/init/types.ts +366 -0
  540. package/src/commands/init/wizard-terminal.ts +206 -0
  541. package/src/commands/init/wizard.ts +450 -0
  542. package/src/commands/mcp.ts +123 -0
  543. package/src/commands/product-test-runner.ts +80 -0
  544. package/src/commands/product.ts +331 -0
  545. package/src/commands/query.ts +1032 -0
  546. package/src/commands/scan.ts +360 -0
  547. package/src/commands/sdd.ts +243 -0
  548. package/src/commands/unavailable.ts +92 -0
  549. package/src/commands/watch/README.md +160 -0
  550. package/src/commands/watch/analyze.ts +600 -0
  551. package/src/commands/watch/cli.ts +108 -0
  552. package/src/commands/watch/delta.ts +186 -0
  553. package/src/commands/watch/events.ts +235 -0
  554. package/src/commands/watch/index.ts +53 -0
  555. package/src/commands/watch/options.ts +234 -0
  556. package/src/commands/watch/render.ts +240 -0
  557. package/src/commands/watch/run.ts +553 -0
  558. package/src/commands/watch/runtime.ts +167 -0
  559. package/src/commands/watch-command.ts +294 -0
  560. package/src/entry-point.ts +67 -0
  561. package/src/index.ts +291 -0
  562. package/src/mcp/boundaries-schema.ts +193 -0
  563. package/src/mcp/default-runtime.ts +1034 -0
  564. package/src/mcp/envelope.ts +57 -0
  565. package/src/mcp/index.ts +28 -0
  566. package/src/mcp/output-schemas.ts +3071 -0
  567. package/src/mcp/path-sandbox.ts +156 -0
  568. package/src/mcp/server.ts +358 -0
  569. package/src/mcp/stdio.ts +92 -0
  570. package/src/mcp/tools.ts +563 -0
  571. package/src/mcp/types.ts +66 -0
@@ -0,0 +1,776 @@
1
+ /**
2
+ * `untangle complexity` — die einzige Analyse, die HEUTE vollstaendig laeuft.
3
+ *
4
+ * Sie braucht keinen Index und keinen Dienst: der Scanner findet die Dateien,
5
+ * die parser-registry parst sie, @untangle-code/complexity rechnet. Alles im
6
+ * Prozess, alles deterministisch.
7
+ *
8
+ * ZWEI ENTSCHEIDUNGEN, DIE MAN KENNEN MUSS:
9
+ *
10
+ * 1. Eine Datei mit beschaedigtem Syntaxbaum (`parseQuality !== "complete"`)
11
+ * geht in KEINE Zahl ein. Ein kaputter Baum liefert falsche Scope-Grenzen,
12
+ * und eine falsche Hotspot-Liste ist schlimmer als eine kurze: nach ihr
13
+ * wird priorisiert. Die Datei steht dafuer im Skip-Ledger.
14
+ * 2. Die Summen sind die FUNKTIONS-LESART: aeusserste Ausfuehrungseinheiten
15
+ * gehen mit ihrem INKLUSIVEN Wert ein.
16
+ * Innere Funktionen sind darin enthalten; Scopes ausserhalb einer
17
+ * Ausfuehrungseinheit tragen nur ihren Eigenanteil bei (execution_unit).
18
+ *
19
+ * 3. PROSA WIRD NICHT MIT CODE VERRECHNET (WP-217, vision.md §1c). Ein
20
+ * Markdown-Dokument hat keine Entscheidungspunkte und keine
21
+ * Ausfuehrungseinheiten; zyklomatische Komplexitaet darueber ist keine
22
+ * schlechte Zahl, sondern gar keine. Prosa bekommt deshalb eine EIGENE
23
+ * Auswertung mit eigenen Massen (Struktur- und Verweislast) und eine
24
+ * eigene Liste. Die beiden Summen beruehren einander nie — die
25
+ * Prosa-Messwerte sind `ProseNumberV1`-Objekte und passen gar nicht in
26
+ * eine Code-Summe.
27
+ * 4. WAS UEBERSPRUNGEN WIRD, BEKOMMT DEN RICHTIGEN GRUND. Eine
28
+ * `untangle.toml` ist nicht "unsupported_language" — sie ist verstanden
29
+ * (Stufe `text`), es ist nur keine Komplexitaetsmetrik dafuer definiert:
30
+ * `no_metric_defined`. Eine `pnpm-lock.yaml` ist `generated_content`.
31
+ * Ein falscher Grund ist ein stiller Datenverlust mit Etikett.
32
+ *
33
+ * Fuer „continuous complexity monitoring": `--max-cognitive` und
34
+ * `--max-cyclomatic` machen daraus ein Gate mit Exit-Code 5.
35
+ */
36
+
37
+ import { existsSync, readFileSync } from "node:fs";
38
+ import path from "node:path";
39
+
40
+ import {
41
+ aggregateScopeTree,
42
+ buildSymbolIR,
43
+ compareProseByStructureLoad,
44
+ computeCognitive,
45
+ computeCyclomatic,
46
+ computeProseMetrics,
47
+ containsRange,
48
+ selectSymbolFacts,
49
+ withUniqueScopeIds,
50
+ type ScopeMetricNodeV1,
51
+ } from "@untangle-code/complexity";
52
+ import {
53
+ COGNITIVE_ALGORITHM_ID,
54
+ METRICS_VERSION,
55
+ buildSkipLedgerEntry,
56
+ classifyAdapterFailure,
57
+ classifyTextFormat,
58
+ compareCodepoints,
59
+ formatProseNumber,
60
+ type LanguageAdapter,
61
+ type ParsedAst,
62
+ type ProseMetricsV1,
63
+ type SkipLedgerEntryV1,
64
+ type SkipReason,
65
+ } from "@untangle-code/domain";
66
+ import { createParserRegistry } from "@untangle-code/parser-registry";
67
+ import { discoverFiles } from "@untangle-code/scanner";
68
+ import { NodeFileSystem } from "@untangle-code/scanner/node-fs";
69
+
70
+ import {
71
+ enumFlag,
72
+ integerFlag,
73
+ numberFlag,
74
+ stringFlag,
75
+ type FlagSpecs,
76
+ type ParsedArgs,
77
+ } from "../cli/args.js";
78
+ import type { Command, CommandContext } from "../cli/command.js";
79
+ import { EXIT, OperationalError } from "../cli/exit.js";
80
+ import { line, note } from "../cli/io.js";
81
+ import { errorMessage } from "../cli/workspace.js";
82
+
83
+ /**
84
+ * Scope-Arten, die eine eigene Ausfuehrungseinheit sind. `kind` ist ein
85
+ * adapterspezifischer String; @untangle-code/complexity dokumentiert bewusst
86
+ * keine Sprach-Taxonomie, also steht die Zuordnung hier.
87
+ */
88
+ const EXECUTION_UNIT_KINDS = new Set(["function", "method", "constructor", "lambda"]);
89
+
90
+ interface SymbolEntry {
91
+ readonly filePath: string;
92
+ readonly name: string;
93
+ readonly kind: string;
94
+ readonly line: number;
95
+ readonly executionUnit: boolean;
96
+ readonly cognitive: number;
97
+ readonly cyclomatic: number;
98
+ readonly sloc: number;
99
+ }
100
+
101
+ export interface AnalysisResult {
102
+ readonly root: string;
103
+ readonly filesDiscovered: number;
104
+ readonly filesAnalyzed: number;
105
+ /** Dokumente mit Prosa-Metriken; getrennt gezaehlt, weil getrennt gemessen. */
106
+ readonly proseAnalyzed: number;
107
+ readonly symbols: readonly SymbolEntry[];
108
+ /** Prosa-Dokumente mit ihrer eigenen Metrikfamilie; NIE Teil von `totals`. */
109
+ readonly prose: readonly ProseMetricsV1[];
110
+ readonly skipped: readonly SkipLedgerEntryV1[];
111
+ readonly totalsReading: "execution_unit";
112
+ readonly totals: {
113
+ /** All function-like scopes, including nested functions shown as hotspots. */
114
+ readonly executionUnits: number;
115
+ /** Outermost execution units that contribute inclusive values to totals. */
116
+ readonly executionUnitRoots: number;
117
+ readonly cognitive: number;
118
+ readonly cyclomatic: number;
119
+ };
120
+ }
121
+
122
+ const FLAGS: FlagSpecs = {
123
+ root: {
124
+ kind: "string",
125
+ placeholder: "PATH",
126
+ describe: "Directory to analyze.",
127
+ defaultLabel: "current directory",
128
+ },
129
+ top: {
130
+ kind: "number",
131
+ placeholder: "N",
132
+ describe: "Maximum hotspot entries.",
133
+ defaultLabel: "20",
134
+ },
135
+ format: {
136
+ kind: "string",
137
+ placeholder: "text|json|jsonl",
138
+ describe: "Output format.",
139
+ defaultLabel: "text",
140
+ },
141
+ "max-cognitive": {
142
+ kind: "number",
143
+ placeholder: "N",
144
+ describe: "Gate: no symbol may exceed this cognitive value.",
145
+ },
146
+ "max-cyclomatic": {
147
+ kind: "number",
148
+ placeholder: "N",
149
+ describe: "Gate: no symbol may exceed this cyclomatic value.",
150
+ },
151
+ "include-nested": {
152
+ kind: "boolean",
153
+ describe: "Also show scopes that are not separate execution units.",
154
+ },
155
+ prose: {
156
+ kind: "boolean",
157
+ describe: "Show only prose analysis (documents instead of symbols).",
158
+ },
159
+ };
160
+
161
+ export const complexityCommand: Command = {
162
+ spec: {
163
+ name: "complexity",
164
+ implementedBy: "commands/complexity.js",
165
+ summary: "Measure complexity without an index or services",
166
+ usage: "untangle complexity [--root=<PATH>] [--top=<N>] [--max-cognitive=<N>]",
167
+ details: [
168
+ "Reads files directly, parses them with real language adapters and computes cognitive and cyclomatic complexity per symbol. No index, Qdrant or Ollama is required.",
169
+ "Totals use execution_unit: outermost functions contribute inclusive values; outside them, only self contributions count. Nested functions are not added twice. executionUnits counts all functions; executionUnitRoots counts only outermost functions. Individual hotspots remain visible.",
170
+ "Files with damaged syntax trees contribute to no measurement and appear in the skip ledger. This prevents an incorrect hotspot ranking from appearing valid.",
171
+ "--max-cognitive and --max-cyclomatic turn the run into a gate, producing exit code 5 on a violation for monitoring loops or CI.",
172
+ ],
173
+ flags: FLAGS,
174
+ examples: [
175
+ "untangle complexity",
176
+ "untangle complexity --top=5 --format=json",
177
+ "untangle complexity --max-cognitive=25",
178
+ ],
179
+ exitCodes: [
180
+ [EXIT.ok, "Analysis completed without a gate violation."],
181
+ [EXIT.operational, "Unreadable directory or no built language adapter."],
182
+ [EXIT.usage, "Invalid arguments."],
183
+ [EXIT.gate, "A threshold was exceeded; analysis itself completed."],
184
+ [EXIT.cancelled, "Cancelled."],
185
+ ],
186
+ },
187
+
188
+ async run(ctx: CommandContext, args: ParsedArgs): Promise<number> {
189
+ const format = enumFlag(args, "format", ["text", "json", "jsonl"] as const, "text");
190
+ const top = integerFlag(args, "top", 20);
191
+ const includeNested = args.flags["include-nested"] === true;
192
+ const root = path.resolve(ctx.cwd, stringFlag(args, "root") ?? ".");
193
+ const maxCognitive = numberFlag(args, "max-cognitive");
194
+ const maxCyclomatic = numberFlag(args, "max-cyclomatic");
195
+
196
+ const result = await analyze(root, ctx.signal);
197
+ ctx.signal.throwIfAborted();
198
+
199
+ const shown = includeNested ? result.symbols : result.symbols.filter((s) => s.executionUnit);
200
+ const hotspots = [...shown]
201
+ .sort(
202
+ (a, b) =>
203
+ b.cognitive - a.cognitive ||
204
+ b.cyclomatic - a.cyclomatic ||
205
+ compareCodepoints(a.filePath, b.filePath) ||
206
+ a.line - b.line,
207
+ )
208
+ .slice(0, top);
209
+
210
+ const violations = collectViolations(shown, maxCognitive, maxCyclomatic);
211
+ // Eigene Ordnung, eigene Liste: Prosa steht nie in derselben Rangfolge
212
+ // wie Code, weil die Zahlen nicht dieselbe Bedeutung haben.
213
+ const proseRanked = [...result.prose].sort(compareProseByStructureLoad).slice(0, top);
214
+ const proseOnly = args.flags["prose"] === true;
215
+
216
+ if (format === "json") {
217
+ line(
218
+ ctx.io,
219
+ JSON.stringify(
220
+ {
221
+ schemaVersion: 1,
222
+ root: result.root,
223
+ filesDiscovered: result.filesDiscovered,
224
+ filesAnalyzed: result.filesAnalyzed,
225
+ filesProse: result.proseAnalyzed,
226
+ totalsReading: result.totalsReading,
227
+ totals: result.totals,
228
+ hotspots,
229
+ violations,
230
+ // Getrenntes Feld, getrennte Familie: die Werte sind Objekte mit
231
+ // Einheit (`ProseNumberV1`), keine blanken Zahlen — sie lassen
232
+ // sich gar nicht versehentlich zu `totals` addieren.
233
+ prose: proseRanked.map(proseSummary),
234
+ skipped: result.skipped,
235
+ },
236
+ null,
237
+ 2,
238
+ ),
239
+ );
240
+ } else if (format === "jsonl") {
241
+ line(
242
+ ctx.io,
243
+ JSON.stringify({
244
+ schemaVersion: 1,
245
+ kind: "header",
246
+ root: result.root,
247
+ filesDiscovered: result.filesDiscovered,
248
+ filesAnalyzed: result.filesAnalyzed,
249
+ totalsReading: result.totalsReading,
250
+ totals: result.totals,
251
+ filesProse: result.proseAnalyzed,
252
+ skippedCount: result.skipped.length,
253
+ }),
254
+ );
255
+ // `record` steht vorn, `kind` des Symbols bleibt erhalten — zwei
256
+ // verschiedene Begriffe, also zwei verschiedene Feldnamen.
257
+ for (const entry of hotspots) line(ctx.io, JSON.stringify({ record: "symbol", ...entry }));
258
+ for (const entry of violations)
259
+ line(ctx.io, JSON.stringify({ record: "violation", ...entry }));
260
+ for (const entry of proseRanked)
261
+ line(ctx.io, JSON.stringify({ record: "document", ...proseSummary(entry) }));
262
+ } else {
263
+ renderText(ctx, result, hotspots, includeNested, proseRanked, proseOnly);
264
+ }
265
+
266
+ if (violations.length > 0) {
267
+ note(ctx.io, "");
268
+ note(ctx.io, `${String(violations.length)} threshold violation(s):`);
269
+ for (const violation of violations) {
270
+ note(
271
+ ctx.io,
272
+ ` ${violation.filePath}:${String(violation.line)} ${violation.name} ` +
273
+ `${violation.metric}=${String(violation.value)} > ${String(violation.threshold)}`,
274
+ );
275
+ }
276
+ note(ctx.io, "");
277
+ note(ctx.io, "Next step: `untangle complexity --top=5` shows the largest hotspots first.");
278
+ return EXIT.gate;
279
+ }
280
+
281
+ return EXIT.ok;
282
+ },
283
+ };
284
+
285
+ /* --------------------------------------------------------------------- */
286
+
287
+ interface Violation {
288
+ readonly filePath: string;
289
+ readonly line: number;
290
+ readonly name: string;
291
+ readonly metric: "cognitive" | "cyclomatic";
292
+ readonly value: number;
293
+ readonly threshold: number;
294
+ }
295
+
296
+ function collectViolations(
297
+ symbols: readonly SymbolEntry[],
298
+ maxCognitive: number | undefined,
299
+ maxCyclomatic: number | undefined,
300
+ ): Violation[] {
301
+ const out: Violation[] = [];
302
+ for (const symbol of symbols) {
303
+ if (maxCognitive !== undefined && symbol.cognitive > maxCognitive) {
304
+ out.push({
305
+ filePath: symbol.filePath,
306
+ line: symbol.line,
307
+ name: symbol.name,
308
+ metric: "cognitive",
309
+ value: symbol.cognitive,
310
+ threshold: maxCognitive,
311
+ });
312
+ }
313
+ if (maxCyclomatic !== undefined && symbol.cyclomatic > maxCyclomatic) {
314
+ out.push({
315
+ filePath: symbol.filePath,
316
+ line: symbol.line,
317
+ name: symbol.name,
318
+ metric: "cyclomatic",
319
+ value: symbol.cyclomatic,
320
+ threshold: maxCyclomatic,
321
+ });
322
+ }
323
+ }
324
+ return out.sort(
325
+ (a, b) =>
326
+ b.value - a.value ||
327
+ compareCodepoints(a.filePath, b.filePath) ||
328
+ a.line - b.line ||
329
+ compareCodepoints(a.metric, b.metric),
330
+ );
331
+ }
332
+
333
+ /**
334
+ * Die serialisierbare Kurzform eines Prosa-Ergebnisses.
335
+ *
336
+ * Die Belegfelder (`sections`, `links`) bleiben absichtlich draussen: sie
337
+ * sind bei `spec.md` vierstellig lang und wuerden die Ausgabe unbrauchbar
338
+ * machen. Was hier steht, sind die Messwerte selbst — als Objekte mit
339
+ * Einheit, damit auch im JSON sichtbar bleibt, dass es eine ANDERE Familie
340
+ * ist als `totals`.
341
+ */
342
+ function proseSummary(metrics: ProseMetricsV1): Record<string, unknown> {
343
+ return {
344
+ path: metrics.path,
345
+ metricsVersion: metrics.metricsVersion,
346
+ structureLoad: metrics.structureLoad,
347
+ sectionCount: metrics.sectionCount,
348
+ sectionDepth: metrics.sectionDepth,
349
+ maxSectionLines: metrics.maxSectionLines,
350
+ linkDensity: metrics.linkDensity,
351
+ unresolvedLinkRatio: metrics.unresolvedLinkRatio,
352
+ repetitionRatio: metrics.repetitionRatio,
353
+ contentLines: metrics.contentLines,
354
+ };
355
+ }
356
+
357
+ function renderText(
358
+ ctx: CommandContext,
359
+ result: AnalysisResult,
360
+ hotspots: readonly SymbolEntry[],
361
+ includeNested: boolean,
362
+ prose: readonly ProseMetricsV1[],
363
+ proseOnly: boolean,
364
+ ): void {
365
+ line(ctx.io, `Root: ${result.root}`);
366
+ line(ctx.io, `Files discovered: ${String(result.filesDiscovered)}`);
367
+ line(ctx.io, `Files measured: ${String(result.filesAnalyzed)} (Code)`);
368
+ line(ctx.io, `Documents: ${String(result.proseAnalyzed)} (prose)`);
369
+ line(
370
+ ctx.io,
371
+ `Skipped: ${String(result.skipped.length)} (with reasons; see --format=json)`,
372
+ );
373
+
374
+ if (!proseOnly) {
375
+ line(ctx.io, "");
376
+ line(
377
+ ctx.io,
378
+ `Execution units: ${String(result.totals.executionUnits)}` +
379
+ ` Cognitive total: ${String(result.totals.cognitive)}` +
380
+ ` Cyclomatic total: ${String(result.totals.cyclomatic)}`,
381
+ );
382
+ line(ctx.io, "");
383
+ line(
384
+ ctx.io,
385
+ `Totals: execution_unit; ${String(result.totals.executionUnitRoots)} outermost units; nested functions are not added twice.`,
386
+ );
387
+ line(ctx.io, `HOTSPOTS (${includeNested ? "all scopes" : "execution units only"})`);
388
+ if (hotspots.length === 0) {
389
+ line(ctx.io, " (none)");
390
+ } else {
391
+ line(ctx.io, " cognitive cyclomatic sloc location");
392
+ for (const entry of hotspots) {
393
+ line(
394
+ ctx.io,
395
+ ` ${String(entry.cognitive).padStart(9)} ${String(entry.cyclomatic).padStart(10)} ` +
396
+ `${String(entry.sloc).padStart(4)} ${entry.filePath}:${String(entry.line)} ${entry.name}`,
397
+ );
398
+ }
399
+ }
400
+ }
401
+
402
+ renderProse(ctx, prose);
403
+ }
404
+
405
+ /**
406
+ * Die Prosa-Tafel. Sie steht bewusst UNTER einer eigenen Ueberschrift und
407
+ * mit eigenen Spaltennamen: kein Wert aus dieser Tabelle darf mit einem Wert
408
+ * aus der Hotspot-Tabelle verglichen oder addiert werden, und die Ausgabe
409
+ * soll das auch optisch klarmachen.
410
+ */
411
+ function renderProse(ctx: CommandContext, prose: readonly ProseMetricsV1[]): void {
412
+ line(ctx.io, "");
413
+ line(ctx.io, "PROSE (separate metric family; never combined with code metrics)");
414
+ if (prose.length === 0) {
415
+ line(ctx.io, " (no documents)");
416
+ return;
417
+ }
418
+ line(ctx.io, " Structural load = sum of all section heading levels.");
419
+ line(ctx.io, "");
420
+ line(ctx.io, " load sectns depth max-lines links/100 unresolved repeats document");
421
+ for (const entry of prose) {
422
+ line(
423
+ ctx.io,
424
+ ` ${String(entry.structureLoad.value).padStart(5)}` +
425
+ ` ${String(entry.sectionCount.value).padStart(6)}` +
426
+ ` ${String(entry.sectionDepth.value).padStart(5)}` +
427
+ ` ${String(entry.maxSectionLines.value).padStart(9)}` +
428
+ ` ${entry.linkDensity.value.toFixed(1).padStart(12)}` +
429
+ ` ${(entry.unresolvedLinkRatio === null
430
+ ? "n/a"
431
+ : formatProseNumber(entry.unresolvedLinkRatio)
432
+ ).padStart(7)}` +
433
+ ` ${formatProseNumber(entry.repetitionRatio).padStart(7)}` +
434
+ ` ${entry.path}`,
435
+ );
436
+ }
437
+ }
438
+
439
+ /* --------------------------------------------------------------------- */
440
+
441
+ /** Shared local analysis for complexity and scan; every excluded file has a ledger entry. */
442
+ export async function analyze(root: string, signal: AbortSignal): Promise<AnalysisResult> {
443
+ const registry = createParserRegistry();
444
+ const fs = new NodeFileSystem();
445
+ if ((await fs.stat(root))?.kind !== "directory") {
446
+ throw new OperationalError(
447
+ `Directory "${root}" does not exist or is not a directory.`,
448
+ "Check --root and read permissions.",
449
+ );
450
+ }
451
+ const totals = { executionUnits: 0, executionUnitRoots: 0, cognitive: 0, cyclomatic: 0 };
452
+ const skipped: SkipLedgerEntryV1[] = [];
453
+ const symbols: SymbolEntry[] = [];
454
+ const prose: ProseMetricsV1[] = [];
455
+ let filesDiscovered = 0;
456
+ let filesAnalyzed = 0;
457
+ let proseAnalyzed = 0;
458
+
459
+ /**
460
+ * Aufloeser fuer relative Dateiverweise in Prosa. Er sieht auf die Platte —
461
+ * deshalb steht er HIER und nicht in @untangle-code/complexity, das
462
+ * I/O-frei bleibt. Ohne ihn bliebe `unresolvedLinkRatio` `null`, und das
463
+ * waere ein Zustandsvermerk statt eines Messwerts (vision.md §1d).
464
+ */
465
+ const resolveLink = (documentPath: string, targetFilePath: string): boolean => {
466
+ const base = path.dirname(path.resolve(root, documentPath));
467
+ return existsSync(path.resolve(base, targetFilePath));
468
+ };
469
+
470
+ const stream = discoverFiles({
471
+ fs,
472
+ roots: [root],
473
+ repoRoot: root,
474
+ onSkip: (skip) => {
475
+ skipped.push(
476
+ buildSkipLedgerEntry({
477
+ stage: "scan",
478
+ subjectKind: "file",
479
+ path: skip.relativePath,
480
+ reason: scannerSkipReason(skip.reason),
481
+ detail:
482
+ `Excluded by the scanner (${skip.reason})` +
483
+ (skip.detail === undefined ? "." : `: ${skip.detail}`),
484
+ recoverable: skip.reason === "unreadable",
485
+ }),
486
+ );
487
+ },
488
+ });
489
+
490
+ try {
491
+ for await (const file of stream) {
492
+ // Ein Abbruch ist kein erfolgreiches Teilergebnis. Insbesondere MCP
493
+ // muss CANCELLED statt `ok: true` mit einer zufaelligen Praefixmenge
494
+ // erhalten.
495
+ signal.throwIfAborted();
496
+ filesDiscovered++;
497
+
498
+ // Maschinell erzeugte Dateien werden VOR der Adapterfrage aussortiert:
499
+ // eine `pnpm-lock.yaml` ist gueltiges YAML, aber niemandes Text. Der
500
+ // Grund gehoert deshalb an den Inhalt, nicht an die Sprache.
501
+ if (classifyTextFormat(file.relativePath) === "generated") {
502
+ skipped.push(
503
+ buildSkipLedgerEntry({
504
+ stage: "parse",
505
+ subjectKind: "file",
506
+ path: file.relativePath,
507
+ reason: "generated_content",
508
+ detail:
509
+ "Generated file (such as a lockfile). It contains no authored " +
510
+ "statement to measure and contributes to no measurement.",
511
+ recoverable: false,
512
+ }),
513
+ );
514
+ continue;
515
+ }
516
+
517
+ const adapter = registry.getAdapterForPath(file.relativePath);
518
+ if (adapter === null) {
519
+ skipped.push(
520
+ buildSkipLedgerEntry({
521
+ stage: "parse",
522
+ subjectKind: "file",
523
+ path: file.relativePath,
524
+ reason: "unsupported_language",
525
+ detail: `No language adapter for "${file.languageId}"; this file contributes to no measurement.`,
526
+ recoverable: false,
527
+ }),
528
+ );
529
+ continue;
530
+ }
531
+
532
+ let content: string;
533
+ try {
534
+ content = readFileSync(file.absolutePath, "utf8");
535
+ } catch (error) {
536
+ skipped.push(
537
+ buildSkipLedgerEntry({
538
+ stage: "scan",
539
+ subjectKind: "file",
540
+ path: file.relativePath,
541
+ reason: "provider_unavailable",
542
+ detail: `Cannot read file: ${errorMessage(error)}`,
543
+ recoverable: true,
544
+ }),
545
+ );
546
+ continue;
547
+ }
548
+
549
+ // WP-217: Stufe `text` heisst NICHT "weniger Code", sondern "kein
550
+ // Code". Der Weg trennt sich hier, damit nie eine Prosa-Zahl in eine
551
+ // Code-Summe und nie eine Code-Metrik auf ein Dokument geraet.
552
+ if (adapter.supportLevel === "text") {
553
+ if (classifyTextFormat(file.relativePath) === "prose") {
554
+ prose.push(computeProseMetrics(file.relativePath, content, { resolveLink }));
555
+ proseAnalyzed++;
556
+ } else {
557
+ skipped.push(
558
+ buildSkipLedgerEntry({
559
+ stage: "parse",
560
+ subjectKind: "file",
561
+ path: file.relativePath,
562
+ reason: "no_metric_defined",
563
+ detail:
564
+ `Format "${file.languageId}" is supported (tier "text": chunks and search ` +
565
+ "work), but structured configuration has no control flow or " +
566
+ "section structure; neither a code metric nor a prose metric is " +
567
+ "defined for it.",
568
+ recoverable: false,
569
+ }),
570
+ );
571
+ }
572
+ continue;
573
+ }
574
+
575
+ let parsed;
576
+ try {
577
+ parsed = adapter.parse({
578
+ fileId: file.relativePath,
579
+ repoId: "cli",
580
+ refId: "cli:working-tree",
581
+ path: file.relativePath,
582
+ languageId: file.languageId,
583
+ content,
584
+ contentHash: file.contentHash,
585
+ sizeBytes: file.sizeBytes,
586
+ });
587
+ } catch (error) {
588
+ // WP-216: NIE `errorMessage(error)` als Grund durchreichen. "Invalid
589
+ // argument" ist keine Diagnose — `classifyAdapterFailure` bildet jede
590
+ // Adapterausnahme auf einen BENANNTEN Grund samt Messwerten ab, der
591
+ // Rohtext ueberlebt nur als Anhang im Detail (E4).
592
+ const failure = classifyAdapterFailure(error, { sizeBytes: file.sizeBytes });
593
+ skipped.push(
594
+ buildSkipLedgerEntry({
595
+ stage: "parse",
596
+ subjectKind: "file",
597
+ path: file.relativePath,
598
+ reason: failure.reason,
599
+ detail: failure.detail,
600
+ recoverable: failure.recoverable,
601
+ }),
602
+ );
603
+ continue;
604
+ }
605
+
606
+ if (parsed.ast === null || parsed.parseQuality !== "complete") {
607
+ skipped.push(
608
+ buildSkipLedgerEntry({
609
+ stage: "parse",
610
+ subjectKind: "file",
611
+ path: file.relativePath,
612
+ reason: "parse_failed",
613
+ detail:
614
+ `parseQuality="${parsed.parseQuality}"; scope boundaries and decision points ` +
615
+ "are therefore unreliable, so this file contributes to no measurement.",
616
+ recoverable: true,
617
+ }),
618
+ );
619
+ continue;
620
+ }
621
+
622
+ for (const diagnostic of parsed.diagnostics) {
623
+ if (diagnostic.code !== "analysis_scope_limited" || diagnostic.range === undefined)
624
+ continue;
625
+ skipped.push(
626
+ buildSkipLedgerEntry({
627
+ stage: "parse",
628
+ subjectKind: "range",
629
+ path: file.relativePath,
630
+ range: diagnostic.range,
631
+ reason: "no_metric_defined",
632
+ detail: diagnostic.message,
633
+ recoverable: false,
634
+ }),
635
+ );
636
+ }
637
+ filesAnalyzed++;
638
+ const measured = symbolsOfFile(adapter, parsed.ast, file.relativePath);
639
+ symbols.push(...measured.symbols);
640
+ totals.executionUnits += measured.symbols.filter((entry) => entry.executionUnit).length;
641
+ totals.executionUnitRoots += measured.executionUnitRoots;
642
+ totals.cognitive += measured.cognitive;
643
+ totals.cyclomatic += measured.cyclomatic;
644
+ }
645
+ } catch (error) {
646
+ signal.throwIfAborted();
647
+ throw new OperationalError(
648
+ `Directory "${root}" could not be read completely: ${errorMessage(error)}`,
649
+ "Check the path and read permissions, or select another directory with --root.",
650
+ { cause: error },
651
+ );
652
+ }
653
+
654
+ signal.throwIfAborted();
655
+
656
+ symbols.sort(
657
+ (a, b) =>
658
+ compareCodepoints(a.filePath, b.filePath) ||
659
+ a.line - b.line ||
660
+ compareCodepoints(a.name, b.name),
661
+ );
662
+ skipped.sort(
663
+ (a, b) =>
664
+ compareCodepoints(a.path ?? "", b.path ?? "") || compareCodepoints(a.reason, b.reason),
665
+ );
666
+
667
+ prose.sort((a, b) => compareCodepoints(a.path, b.path));
668
+
669
+ return {
670
+ root,
671
+ filesDiscovered,
672
+ filesAnalyzed,
673
+ proseAnalyzed,
674
+ symbols,
675
+ prose,
676
+ skipped,
677
+ totalsReading: "execution_unit",
678
+ totals,
679
+ };
680
+ }
681
+
682
+ /**
683
+ * Metriken je Scope einer Datei.
684
+ *
685
+ * Der INKLUSIVE Wert wird berichtet: der Wert eines Symbols einschliesslich
686
+ * seiner verschachtelten Scopes. Das ist die Zahl, die zur Frage „wie schwer
687
+ * ist diese Funktion zu lesen?" passt — der Leser liest die inneren Scopes ja
688
+ * mit. Fuer cyclomatic wird die erweiterte Variante genommen (spec.md §16.3).
689
+ */
690
+ function symbolsOfFile(
691
+ adapter: LanguageAdapter,
692
+ ast: ParsedAst,
693
+ relativePath: string,
694
+ ): { symbols: SymbolEntry[]; executionUnitRoots: number; cognitive: number; cyclomatic: number } {
695
+ const repaired = withUniqueScopeIds(
696
+ adapter.computeComplexity(ast),
697
+ adapter.extractCalls(ast),
698
+ relativePath,
699
+ );
700
+ const facts = repaired.facts;
701
+ const calls = repaired.calls;
702
+
703
+ const out: SymbolEntry[] = [];
704
+ const cognitive: ScopeMetricNodeV1[] = [];
705
+ const cyclomatic: ScopeMetricNodeV1[] = [];
706
+ for (const scope of facts.symbolScopes) {
707
+ const id = scope.symbolScopeId;
708
+ const inclusiveIr = buildSymbolIR(facts, id, { calls });
709
+ const subtreeFacts = {
710
+ ...facts,
711
+ decisions: facts.decisions.filter((decision) => containsRange(scope.range, decision.range)),
712
+ };
713
+ const ownFacts = selectSymbolFacts(facts, id);
714
+ const ownIr = buildSymbolIR(ownFacts, id, { calls });
715
+ const shared = {
716
+ metricsScopeId: id,
717
+ executionUnit: EXECUTION_UNIT_KINDS.has(scope.kind),
718
+ ...(scope.parentScopeId === undefined ? {} : { parentScopeId: scope.parentScopeId }),
719
+ };
720
+ const inclusiveCognitive =
721
+ inclusiveIr === undefined ? 0 : computeCognitive(inclusiveIr, COGNITIVE_ALGORITHM_ID).value;
722
+ const inclusiveCyclomatic = computeCyclomatic(
723
+ subtreeFacts,
724
+ scope.range.startLine,
725
+ METRICS_VERSION,
726
+ ).extended;
727
+ cognitive.push({
728
+ ...shared,
729
+ inclusiveValue: inclusiveCognitive,
730
+ selfValue: ownIr === undefined ? 0 : computeCognitive(ownIr, COGNITIVE_ALGORITHM_ID).value,
731
+ });
732
+ cyclomatic.push({
733
+ ...shared,
734
+ inclusiveValue: inclusiveCyclomatic,
735
+ selfValue: computeCyclomatic(ownFacts, scope.range.startLine, METRICS_VERSION).extended,
736
+ });
737
+ out.push({
738
+ filePath: relativePath,
739
+ name: scope.qualifiedName || scope.name || `(${scope.kind})`,
740
+ kind: scope.kind,
741
+ line: scope.range.startLine,
742
+ executionUnit: EXECUTION_UNIT_KINDS.has(scope.kind),
743
+ cognitive: inclusiveCognitive,
744
+ cyclomatic: inclusiveCyclomatic,
745
+ sloc: Math.max(1, scope.range.endLine - scope.range.startLine + 1),
746
+ });
747
+ }
748
+ const cognitiveTotals = aggregateScopeTree(cognitive);
749
+ const cyclomaticTotals = aggregateScopeTree(cyclomatic, { perScopeBase: 1 });
750
+ return {
751
+ symbols: out,
752
+ executionUnitRoots: cognitiveTotals.executionUnitRootCount,
753
+ cognitive: cognitiveTotals.executionUnitSum,
754
+ cyclomatic: cyclomaticTotals.executionUnitSum,
755
+ };
756
+ }
757
+
758
+ /**
759
+ * Der Scanner kennt eigene Ausschlussgruende; der Ledger kennt seine eigenen.
760
+ * Diese Abbildung ist die Uebersetzung — sie wirft nichts weg, sie benennt es
761
+ * nur in der Sprache des Ledgers.
762
+ */
763
+ function scannerSkipReason(reason: string): SkipReason {
764
+ switch (reason) {
765
+ case "binary":
766
+ return "binary_content";
767
+ case "size-limit":
768
+ return "file_too_large";
769
+ case "unreadable":
770
+ return "provider_unavailable";
771
+ default:
772
+ // config-exclude, untangleignore, gitignore, default-exclude, security,
773
+ // symlink-cycle, symlink-escape
774
+ return "excluded_by_configuration";
775
+ }
776
+ }