kirograph 0.16.1 → 0.19.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 (365) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +103 -1605
  3. package/dist/architecture/layers/dart.js +112 -0
  4. package/dist/architecture/layers/dart.js.map +7 -0
  5. package/dist/architecture/layers/index.js +3 -1
  6. package/dist/architecture/layers/index.js.map +2 -2
  7. package/dist/bin/banner.js +74 -6
  8. package/dist/bin/banner.js.map +2 -2
  9. package/dist/bin/commands/affected.js +40 -5
  10. package/dist/bin/commands/affected.js.map +2 -2
  11. package/dist/bin/commands/attack-surface.js +157 -0
  12. package/dist/bin/commands/attack-surface.js.map +7 -0
  13. package/dist/bin/commands/benchmark.js +206 -0
  14. package/dist/bin/commands/benchmark.js.map +7 -0
  15. package/dist/bin/commands/budget.js +70 -0
  16. package/dist/bin/commands/budget.js.map +7 -0
  17. package/dist/bin/commands/communities.js +77 -0
  18. package/dist/bin/commands/communities.js.map +7 -0
  19. package/dist/bin/commands/data.js +665 -0
  20. package/dist/bin/commands/data.js.map +7 -0
  21. package/dist/bin/commands/dep-confusion.js +119 -0
  22. package/dist/bin/commands/dep-confusion.js.map +7 -0
  23. package/dist/bin/commands/export.js +304 -10
  24. package/dist/bin/commands/export.js.map +2 -2
  25. package/dist/bin/commands/flows.js +97 -0
  26. package/dist/bin/commands/flows.js.map +7 -0
  27. package/dist/bin/commands/help.js +386 -100
  28. package/dist/bin/commands/help.js.map +2 -2
  29. package/dist/bin/commands/install.js +90 -8
  30. package/dist/bin/commands/install.js.map +2 -2
  31. package/dist/bin/commands/licenses.js +201 -0
  32. package/dist/bin/commands/licenses.js.map +7 -0
  33. package/dist/bin/commands/reachability.js +160 -0
  34. package/dist/bin/commands/reachability.js.map +7 -0
  35. package/dist/bin/commands/read.js +100 -0
  36. package/dist/bin/commands/read.js.map +7 -0
  37. package/dist/bin/commands/refactor.js +116 -0
  38. package/dist/bin/commands/refactor.js.map +7 -0
  39. package/dist/bin/commands/remediation.js +133 -0
  40. package/dist/bin/commands/remediation.js.map +7 -0
  41. package/dist/bin/commands/sbom.js +76 -0
  42. package/dist/bin/commands/sbom.js.map +7 -0
  43. package/dist/bin/commands/security-ci-report.js +267 -0
  44. package/dist/bin/commands/security-ci-report.js.map +7 -0
  45. package/dist/bin/commands/security-export.js +1349 -0
  46. package/dist/bin/commands/security-export.js.map +7 -0
  47. package/dist/bin/commands/security-flows.js +126 -0
  48. package/dist/bin/commands/security-flows.js.map +7 -0
  49. package/dist/bin/commands/security-secrets.js +170 -0
  50. package/dist/bin/commands/security-secrets.js.map +7 -0
  51. package/dist/bin/commands/security.js +193 -0
  52. package/dist/bin/commands/security.js.map +7 -0
  53. package/dist/bin/commands/staleness.js +144 -0
  54. package/dist/bin/commands/staleness.js.map +7 -0
  55. package/dist/bin/commands/status.js +102 -2
  56. package/dist/bin/commands/status.js.map +2 -2
  57. package/dist/bin/commands/supply-chain.js +138 -0
  58. package/dist/bin/commands/supply-chain.js.map +7 -0
  59. package/dist/bin/commands/uninit.js +109 -60
  60. package/dist/bin/commands/uninit.js.map +2 -2
  61. package/dist/bin/commands/vex.js +76 -0
  62. package/dist/bin/commands/vex.js.map +7 -0
  63. package/dist/bin/commands/vuln-suppress.js +95 -0
  64. package/dist/bin/commands/vuln-suppress.js.map +7 -0
  65. package/dist/bin/commands/vulns.js +382 -0
  66. package/dist/bin/commands/vulns.js.map +7 -0
  67. package/dist/bin/installer/auto-detect.js +125 -0
  68. package/dist/bin/installer/auto-detect.js.map +7 -0
  69. package/dist/bin/installer/cli-agent.js +28 -5
  70. package/dist/bin/installer/cli-agent.js.map +2 -2
  71. package/dist/bin/installer/common.js +47 -0
  72. package/dist/bin/installer/common.js.map +2 -2
  73. package/dist/bin/installer/config-prompt.js +39 -1
  74. package/dist/bin/installer/config-prompt.js.map +2 -2
  75. package/dist/bin/installer/detect.js +309 -0
  76. package/dist/bin/installer/detect.js.map +7 -0
  77. package/dist/bin/installer/index.js +36 -1
  78. package/dist/bin/installer/index.js.map +2 -2
  79. package/dist/bin/installer/instructions.js +195 -3
  80. package/dist/bin/installer/instructions.js.map +2 -2
  81. package/dist/bin/installer/steering.js +440 -0
  82. package/dist/bin/installer/steering.js.map +2 -2
  83. package/dist/bin/installer/targets/aider.js +3 -3
  84. package/dist/bin/installer/targets/aider.js.map +2 -2
  85. package/dist/bin/installer/targets/amp.js +3 -3
  86. package/dist/bin/installer/targets/amp.js.map +2 -2
  87. package/dist/bin/installer/targets/antigravity.js +35 -6
  88. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  89. package/dist/bin/installer/targets/augment.js +3 -3
  90. package/dist/bin/installer/targets/augment.js.map +2 -2
  91. package/dist/bin/installer/targets/claude.js +49 -5
  92. package/dist/bin/installer/targets/claude.js.map +2 -2
  93. package/dist/bin/installer/targets/cline.js +32 -6
  94. package/dist/bin/installer/targets/cline.js.map +2 -2
  95. package/dist/bin/installer/targets/codex.js +64 -12
  96. package/dist/bin/installer/targets/codex.js.map +2 -2
  97. package/dist/bin/installer/targets/continue.js +2 -2
  98. package/dist/bin/installer/targets/continue.js.map +2 -2
  99. package/dist/bin/installer/targets/copilot-cli.js +101 -0
  100. package/dist/bin/installer/targets/copilot-cli.js.map +7 -0
  101. package/dist/bin/installer/targets/copilot.js +31 -5
  102. package/dist/bin/installer/targets/copilot.js.map +2 -2
  103. package/dist/bin/installer/targets/cursor.js +4 -4
  104. package/dist/bin/installer/targets/cursor.js.map +2 -2
  105. package/dist/bin/installer/targets/devin.js +2 -2
  106. package/dist/bin/installer/targets/devin.js.map +2 -2
  107. package/dist/bin/installer/targets/gemini-cli.js +2 -2
  108. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  109. package/dist/bin/installer/targets/generic.js +2 -14
  110. package/dist/bin/installer/targets/generic.js.map +2 -2
  111. package/dist/bin/installer/targets/goose.js +3 -3
  112. package/dist/bin/installer/targets/goose.js.map +2 -2
  113. package/dist/bin/installer/targets/index.js +250 -0
  114. package/dist/bin/installer/targets/index.js.map +2 -2
  115. package/dist/bin/installer/targets/junie.js +2 -2
  116. package/dist/bin/installer/targets/junie.js.map +2 -2
  117. package/dist/bin/installer/targets/kilo.js +2 -2
  118. package/dist/bin/installer/targets/kilo.js.map +2 -2
  119. package/dist/bin/installer/targets/kiro.js +3 -3
  120. package/dist/bin/installer/targets/kiro.js.map +2 -2
  121. package/dist/bin/installer/targets/opencode.js +2 -2
  122. package/dist/bin/installer/targets/opencode.js.map +2 -2
  123. package/dist/bin/installer/targets/openhands.js +3 -3
  124. package/dist/bin/installer/targets/openhands.js.map +2 -2
  125. package/dist/bin/installer/targets/qoder.js +91 -0
  126. package/dist/bin/installer/targets/qoder.js.map +7 -0
  127. package/dist/bin/installer/targets/qwen.js +96 -0
  128. package/dist/bin/installer/targets/qwen.js.map +7 -0
  129. package/dist/bin/installer/targets/replit.js +3 -3
  130. package/dist/bin/installer/targets/replit.js.map +2 -2
  131. package/dist/bin/installer/targets/roo.js +2 -2
  132. package/dist/bin/installer/targets/roo.js.map +2 -2
  133. package/dist/bin/installer/targets/tabnine.js +3 -3
  134. package/dist/bin/installer/targets/tabnine.js.map +2 -2
  135. package/dist/bin/installer/targets/trae.js +5 -5
  136. package/dist/bin/installer/targets/trae.js.map +2 -2
  137. package/dist/bin/installer/targets/warp.js +2 -2
  138. package/dist/bin/installer/targets/warp.js.map +2 -2
  139. package/dist/bin/installer/targets/windsurf.js +35 -6
  140. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  141. package/dist/bin/kirograph.js +74 -6
  142. package/dist/bin/kirograph.js.map +3 -3
  143. package/dist/bin/progress.js +30 -0
  144. package/dist/bin/progress.js.map +2 -2
  145. package/dist/compression/naive-cost.js +25 -0
  146. package/dist/compression/naive-cost.js.map +2 -2
  147. package/dist/compression/tracker.js +91 -2
  148. package/dist/compression/tracker.js.map +2 -2
  149. package/dist/compression/types.js.map +1 -1
  150. package/dist/config.js +126 -3
  151. package/dist/config.js.map +2 -2
  152. package/dist/core/pipeline.js +92 -4
  153. package/dist/core/pipeline.js.map +2 -2
  154. package/dist/data/filters.js +105 -0
  155. package/dist/data/filters.js.map +7 -0
  156. package/dist/data/indexer.js +225 -0
  157. package/dist/data/indexer.js.map +7 -0
  158. package/dist/data/linker.js +150 -0
  159. package/dist/data/linker.js.map +7 -0
  160. package/dist/data/lint.js +109 -0
  161. package/dist/data/lint.js.map +7 -0
  162. package/dist/data/parsers/csv.js +132 -0
  163. package/dist/data/parsers/csv.js.map +7 -0
  164. package/dist/data/parsers/excel.js +88 -0
  165. package/dist/data/parsers/excel.js.map +7 -0
  166. package/dist/data/parsers/index.js +79 -0
  167. package/dist/data/parsers/index.js.map +7 -0
  168. package/dist/data/parsers/json-array.js +89 -0
  169. package/dist/data/parsers/json-array.js.map +7 -0
  170. package/dist/data/parsers/jsonl.js +84 -0
  171. package/dist/data/parsers/jsonl.js.map +7 -0
  172. package/dist/data/parsers/parquet.js +95 -0
  173. package/dist/data/parsers/parquet.js.map +7 -0
  174. package/dist/data/profiler.js +182 -0
  175. package/dist/data/profiler.js.map +7 -0
  176. package/dist/data/queries.js +512 -0
  177. package/dist/data/queries.js.map +7 -0
  178. package/dist/data/types.js +17 -0
  179. package/dist/data/types.js.map +7 -0
  180. package/dist/db/data-schema.sql +61 -0
  181. package/dist/db/database.js +67 -5
  182. package/dist/db/database.js.map +2 -2
  183. package/dist/db/memory-schema.sql +5 -1
  184. package/dist/db/schema.sql +3 -1
  185. package/dist/db/security-schema.sql +72 -0
  186. package/dist/extraction/extractor.js +81 -0
  187. package/dist/extraction/extractor.js.map +2 -2
  188. package/dist/extraction/grammars.js +32 -8
  189. package/dist/extraction/grammars.js.map +2 -2
  190. package/dist/extraction/languages.js +43 -1
  191. package/dist/extraction/languages.js.map +2 -2
  192. package/dist/extraction/notebook.js +300 -0
  193. package/dist/extraction/notebook.js.map +7 -0
  194. package/dist/extraction/wasm/tree-sitter-astro.wasm +0 -0
  195. package/dist/extraction/wasm/tree-sitter-gdscript.wasm +0 -0
  196. package/dist/extraction/wasm/tree-sitter-julia.wasm +0 -0
  197. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  198. package/dist/extraction/wasm/tree-sitter-perl.wasm +0 -0
  199. package/dist/extraction/wasm/tree-sitter-powershell.wasm +0 -0
  200. package/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  201. package/dist/extraction/wasm/tree-sitter-sql.wasm +0 -0
  202. package/dist/extraction/wasm/tree-sitter-verilog.wasm +0 -0
  203. package/dist/frameworks/flutter.js +130 -0
  204. package/dist/frameworks/flutter.js.map +7 -0
  205. package/dist/frameworks/index.js +7 -1
  206. package/dist/frameworks/index.js.map +3 -3
  207. package/dist/graph/communities.js +317 -0
  208. package/dist/graph/communities.js.map +7 -0
  209. package/dist/graph/flows.js +138 -0
  210. package/dist/graph/flows.js.map +7 -0
  211. package/dist/graph/refactor.js +155 -0
  212. package/dist/graph/refactor.js.map +7 -0
  213. package/dist/index.js +1 -1
  214. package/dist/index.js.map +2 -2
  215. package/dist/mcp/cache.js +172 -0
  216. package/dist/mcp/cache.js.map +7 -0
  217. package/dist/mcp/read-modes.js +295 -0
  218. package/dist/mcp/read-modes.js.map +7 -0
  219. package/dist/mcp/server.js +2 -1
  220. package/dist/mcp/server.js.map +2 -2
  221. package/dist/mcp/tool-names.js +29 -1
  222. package/dist/mcp/tool-names.js.map +2 -2
  223. package/dist/mcp/tools.js +1588 -6
  224. package/dist/mcp/tools.js.map +3 -3
  225. package/dist/memory/database.js +32 -2
  226. package/dist/memory/database.js.map +2 -2
  227. package/dist/memory/types.js.map +1 -1
  228. package/dist/resolution/bridges/android-rn.js +298 -0
  229. package/dist/resolution/bridges/android-rn.js.map +7 -0
  230. package/dist/resolution/bridges/expo-modules.js +155 -0
  231. package/dist/resolution/bridges/expo-modules.js.map +7 -0
  232. package/dist/resolution/bridges/flutter-channel.js +385 -0
  233. package/dist/resolution/bridges/flutter-channel.js.map +7 -0
  234. package/dist/resolution/bridges/index.js +80 -0
  235. package/dist/resolution/bridges/index.js.map +7 -0
  236. package/dist/resolution/bridges/native-events.js +188 -0
  237. package/dist/resolution/bridges/native-events.js.map +7 -0
  238. package/dist/resolution/bridges/native-views.js +244 -0
  239. package/dist/resolution/bridges/native-views.js.map +7 -0
  240. package/dist/resolution/bridges/react-native.js +161 -0
  241. package/dist/resolution/bridges/react-native.js.map +7 -0
  242. package/dist/resolution/bridges/swift-objc.js +227 -0
  243. package/dist/resolution/bridges/swift-objc.js.map +7 -0
  244. package/dist/resolution/bridges/turbomodules.js +216 -0
  245. package/dist/resolution/bridges/turbomodules.js.map +7 -0
  246. package/dist/resolution/index.js +61 -2
  247. package/dist/resolution/index.js.map +2 -2
  248. package/dist/security/attack-surface.js +164 -0
  249. package/dist/security/attack-surface.js.map +7 -0
  250. package/dist/security/context-warnings.js +123 -0
  251. package/dist/security/context-warnings.js.map +7 -0
  252. package/dist/security/context-warnings.test.js +300 -0
  253. package/dist/security/context-warnings.test.js.map +7 -0
  254. package/dist/security/data-flows.js +228 -0
  255. package/dist/security/data-flows.js.map +7 -0
  256. package/dist/security/dep-confusion.js +255 -0
  257. package/dist/security/dep-confusion.js.map +7 -0
  258. package/dist/security/errors.js +51 -0
  259. package/dist/security/errors.js.map +7 -0
  260. package/dist/security/export/fix-suggestions.js +58 -0
  261. package/dist/security/export/fix-suggestions.js.map +7 -0
  262. package/dist/security/export/fix-suggestions.test.js +74 -0
  263. package/dist/security/export/fix-suggestions.test.js.map +7 -0
  264. package/dist/security/export/sbom.js +230 -0
  265. package/dist/security/export/sbom.js.map +7 -0
  266. package/dist/security/export/sbom.test.js +288 -0
  267. package/dist/security/export/sbom.test.js.map +7 -0
  268. package/dist/security/export/serialization.js +142 -0
  269. package/dist/security/export/serialization.js.map +7 -0
  270. package/dist/security/export/serialization.test.js +310 -0
  271. package/dist/security/export/serialization.test.js.map +7 -0
  272. package/dist/security/export/vex.js +220 -0
  273. package/dist/security/export/vex.js.map +7 -0
  274. package/dist/security/export/vex.test.js +278 -0
  275. package/dist/security/export/vex.test.js.map +7 -0
  276. package/dist/security/index.js +67 -0
  277. package/dist/security/index.js.map +7 -0
  278. package/dist/security/integrator-transitives.test.js +359 -0
  279. package/dist/security/integrator-transitives.test.js.map +7 -0
  280. package/dist/security/integrator.js +491 -0
  281. package/dist/security/integrator.js.map +7 -0
  282. package/dist/security/integrator.test.js +237 -0
  283. package/dist/security/integrator.test.js.map +7 -0
  284. package/dist/security/license.js +70 -0
  285. package/dist/security/license.js.map +7 -0
  286. package/dist/security/manifest/adapter.js +243 -0
  287. package/dist/security/manifest/adapter.js.map +7 -0
  288. package/dist/security/manifest/adapter.test.js +272 -0
  289. package/dist/security/manifest/adapter.test.js.map +7 -0
  290. package/dist/security/manifest/parser.js +376 -0
  291. package/dist/security/manifest/parser.js.map +7 -0
  292. package/dist/security/manifest/parser.test.js +110 -0
  293. package/dist/security/manifest/parser.test.js.map +7 -0
  294. package/dist/security/manifest/plugins/cargo.js +233 -0
  295. package/dist/security/manifest/plugins/cargo.js.map +7 -0
  296. package/dist/security/manifest/plugins/cargo.test.js +304 -0
  297. package/dist/security/manifest/plugins/cargo.test.js.map +7 -0
  298. package/dist/security/manifest/plugins/composer.js +152 -0
  299. package/dist/security/manifest/plugins/composer.js.map +7 -0
  300. package/dist/security/manifest/plugins/go.js +146 -0
  301. package/dist/security/manifest/plugins/go.js.map +7 -0
  302. package/dist/security/manifest/plugins/go.test.js +341 -0
  303. package/dist/security/manifest/plugins/go.test.js.map +7 -0
  304. package/dist/security/manifest/plugins/gradle.js +159 -0
  305. package/dist/security/manifest/plugins/gradle.js.map +7 -0
  306. package/dist/security/manifest/plugins/hex.js +159 -0
  307. package/dist/security/manifest/plugins/hex.js.map +7 -0
  308. package/dist/security/manifest/plugins/maven.js +128 -0
  309. package/dist/security/manifest/plugins/maven.js.map +7 -0
  310. package/dist/security/manifest/plugins/maven.test.js +389 -0
  311. package/dist/security/manifest/plugins/maven.test.js.map +7 -0
  312. package/dist/security/manifest/plugins/npm.js +284 -0
  313. package/dist/security/manifest/plugins/npm.js.map +7 -0
  314. package/dist/security/manifest/plugins/npm.test.js +298 -0
  315. package/dist/security/manifest/plugins/npm.test.js.map +7 -0
  316. package/dist/security/manifest/plugins/nuget.js +186 -0
  317. package/dist/security/manifest/plugins/nuget.js.map +7 -0
  318. package/dist/security/manifest/plugins/pip.js +123 -0
  319. package/dist/security/manifest/plugins/pip.js.map +7 -0
  320. package/dist/security/manifest/plugins/pip.test.js +208 -0
  321. package/dist/security/manifest/plugins/pip.test.js.map +7 -0
  322. package/dist/security/manifest/plugins/pubspec.js +212 -0
  323. package/dist/security/manifest/plugins/pubspec.js.map +7 -0
  324. package/dist/security/manifest/plugins/pyproject.js +261 -0
  325. package/dist/security/manifest/plugins/pyproject.js.map +7 -0
  326. package/dist/security/manifest/plugins/rubygems.js +185 -0
  327. package/dist/security/manifest/plugins/rubygems.js.map +7 -0
  328. package/dist/security/manifest/plugins/swift.js +200 -0
  329. package/dist/security/manifest/plugins/swift.js.map +7 -0
  330. package/dist/security/owasp.js +104 -0
  331. package/dist/security/owasp.js.map +7 -0
  332. package/dist/security/pipeline.js +125 -0
  333. package/dist/security/pipeline.js.map +7 -0
  334. package/dist/security/reachability.js +276 -0
  335. package/dist/security/reachability.js.map +7 -0
  336. package/dist/security/reachability.test.js +394 -0
  337. package/dist/security/reachability.test.js.map +7 -0
  338. package/dist/security/remediation.js +126 -0
  339. package/dist/security/remediation.js.map +7 -0
  340. package/dist/security/secrets.js +176 -0
  341. package/dist/security/secrets.js.map +7 -0
  342. package/dist/security/staleness.js +231 -0
  343. package/dist/security/staleness.js.map +7 -0
  344. package/dist/security/supply-chain.js +301 -0
  345. package/dist/security/supply-chain.js.map +7 -0
  346. package/dist/security/suppressions.js +106 -0
  347. package/dist/security/suppressions.js.map +7 -0
  348. package/dist/security/types.js +17 -0
  349. package/dist/security/types.js.map +7 -0
  350. package/dist/security/vuln/client.js +355 -0
  351. package/dist/security/vuln/client.js.map +7 -0
  352. package/dist/security/vuln/client.test.js +288 -0
  353. package/dist/security/vuln/client.test.js.map +7 -0
  354. package/dist/security/vuln/epss-client.js +95 -0
  355. package/dist/security/vuln/epss-client.js.map +7 -0
  356. package/dist/security/vuln/index.js +29 -0
  357. package/dist/security/vuln/index.js.map +7 -0
  358. package/dist/security/vuln/osv-adapter.js +321 -0
  359. package/dist/security/vuln/osv-adapter.js.map +7 -0
  360. package/dist/security/vuln/osv-adapter.test.js +391 -0
  361. package/dist/security/vuln/osv-adapter.test.js.map +7 -0
  362. package/dist/security/vuln/types.js +17 -0
  363. package/dist/security/vuln/types.js.map +7 -0
  364. package/dist/types.js.map +2 -2
  365. package/package.json +5 -2
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var dart_exports = {};
30
+ __export(dart_exports, {
31
+ dartLayerDetector: () => dartLayerDetector
32
+ });
33
+ module.exports = __toCommonJS(dart_exports);
34
+ var import_picomatch = __toESM(require("picomatch"));
35
+ const LAYER_PATTERNS = [
36
+ // UI layer
37
+ ["ui", "**/lib/screens/**", 0.9],
38
+ ["ui", "**/lib/pages/**", 0.9],
39
+ ["ui", "**/lib/views/**", 0.85],
40
+ ["ui", "**/lib/widgets/**", 0.9],
41
+ ["ui", "**/lib/components/**", 0.85],
42
+ // Service / Business logic layer
43
+ ["service", "**/lib/services/**", 0.9],
44
+ ["service", "**/lib/providers/**", 0.85],
45
+ ["service", "**/lib/blocs/**", 0.9],
46
+ ["service", "**/lib/cubits/**", 0.9],
47
+ ["service", "**/lib/notifiers/**", 0.85],
48
+ // Data layer
49
+ ["data", "**/lib/repositories/**", 0.9],
50
+ ["data", "**/lib/data/**", 0.85],
51
+ ["data", "**/lib/datasources/**", 0.9],
52
+ ["data", "**/lib/models/**", 0.85],
53
+ ["data", "**/lib/entities/**", 0.85],
54
+ ["data", "**/lib/domain/**", 0.8],
55
+ // Shared / Infrastructure layer
56
+ ["shared", "**/lib/core/**", 0.85],
57
+ ["shared", "**/lib/utils/**", 0.85],
58
+ ["shared", "**/lib/helpers/**", 0.85],
59
+ ["shared", "**/lib/extensions/**", 0.85],
60
+ ["shared", "**/lib/constants/**", 0.8],
61
+ // API / Navigation layer
62
+ ["api", "**/lib/routes/**", 0.9],
63
+ ["api", "**/lib/navigation/**", 0.85],
64
+ ["api", "**/lib/router/**", 0.85],
65
+ ["api", "**/lib/main.dart", 0.8],
66
+ ["api", "**/lib/app.dart", 0.8]
67
+ ];
68
+ const TEST_PATTERN = (0, import_picomatch.default)("**/test/**");
69
+ const dartLayerDetector = {
70
+ language: "dart",
71
+ async detect(files, _projectRoot, configLayers) {
72
+ const results = [];
73
+ const configMatchers = _buildConfigMatchers(configLayers ?? {});
74
+ for (const file of files) {
75
+ if (!file.endsWith(".dart")) continue;
76
+ if (TEST_PATTERN(file)) continue;
77
+ const configMatch = _matchConfig(file, configMatchers);
78
+ if (configMatch) {
79
+ results.push({ ...configMatch, filePath: file });
80
+ continue;
81
+ }
82
+ let best = null;
83
+ for (const [layerName, pattern, confidence] of LAYER_PATTERNS) {
84
+ if ((0, import_picomatch.default)(pattern)(file)) {
85
+ if (!best || confidence > best.confidence) {
86
+ best = { layerName, filePath: file, confidence, matchedPattern: pattern };
87
+ }
88
+ }
89
+ }
90
+ if (best) results.push(best);
91
+ }
92
+ return results;
93
+ }
94
+ };
95
+ function _buildConfigMatchers(configLayers) {
96
+ return Object.entries(configLayers).flatMap(
97
+ ([layerName, patterns]) => patterns.map(
98
+ (pattern) => [layerName, (0, import_picomatch.default)(pattern), pattern]
99
+ )
100
+ );
101
+ }
102
+ function _matchConfig(file, matchers) {
103
+ for (const [layerName, matcher, pattern] of matchers) {
104
+ if (matcher(file)) return { layerName, confidence: 1, matchedPattern: `config:${pattern}` };
105
+ }
106
+ return null;
107
+ }
108
+ // Annotate the CommonJS export names for ESM import in node:
109
+ 0 && (module.exports = {
110
+ dartLayerDetector
111
+ });
112
+ //# sourceMappingURL=dart.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/architecture/layers/dart.ts"],
4
+ "sourcesContent": ["/**\n * Layer detector for Dart / Flutter projects.\n *\n * Detects: api, service, data, ui, shared layers based on\n * directory names common in Flutter projects under lib/.\n * Files in test/ are skipped (return no match).\n */\nimport type { LayerDetector, ArchLayerMatch } from '../types';\nimport picomatch from 'picomatch';\n\n// Pattern definitions: each entry is [layerName, glob, confidence]\nconst LAYER_PATTERNS: Array<[string, string, number]> = [\n // UI layer\n ['ui', '**/lib/screens/**', 0.9],\n ['ui', '**/lib/pages/**', 0.9],\n ['ui', '**/lib/views/**', 0.85],\n ['ui', '**/lib/widgets/**', 0.9],\n ['ui', '**/lib/components/**', 0.85],\n\n // Service / Business logic layer\n ['service', '**/lib/services/**', 0.9],\n ['service', '**/lib/providers/**', 0.85],\n ['service', '**/lib/blocs/**', 0.9],\n ['service', '**/lib/cubits/**', 0.9],\n ['service', '**/lib/notifiers/**', 0.85],\n\n // Data layer\n ['data', '**/lib/repositories/**', 0.9],\n ['data', '**/lib/data/**', 0.85],\n ['data', '**/lib/datasources/**', 0.9],\n ['data', '**/lib/models/**', 0.85],\n ['data', '**/lib/entities/**', 0.85],\n ['data', '**/lib/domain/**', 0.8],\n\n // Shared / Infrastructure layer\n ['shared', '**/lib/core/**', 0.85],\n ['shared', '**/lib/utils/**', 0.85],\n ['shared', '**/lib/helpers/**', 0.85],\n ['shared', '**/lib/extensions/**', 0.85],\n ['shared', '**/lib/constants/**', 0.8],\n\n // API / Navigation layer\n ['api', '**/lib/routes/**', 0.9],\n ['api', '**/lib/navigation/**', 0.85],\n ['api', '**/lib/router/**', 0.85],\n ['api', '**/lib/main.dart', 0.8],\n ['api', '**/lib/app.dart', 0.8],\n];\n\nconst TEST_PATTERN = picomatch('**/test/**');\n\nexport const dartLayerDetector: LayerDetector = {\n language: 'dart',\n\n async detect(files: string[], _projectRoot: string, configLayers?: Record<string, string[]>): Promise<ArchLayerMatch[]> {\n const results: ArchLayerMatch[] = [];\n const configMatchers = _buildConfigMatchers(configLayers ?? {});\n\n for (const file of files) {\n if (!file.endsWith('.dart')) continue;\n\n // Skip test files\n if (TEST_PATTERN(file)) continue;\n\n const configMatch = _matchConfig(file, configMatchers);\n if (configMatch) {\n results.push({ ...configMatch, filePath: file });\n continue;\n }\n\n let best: ArchLayerMatch | null = null;\n for (const [layerName, pattern, confidence] of LAYER_PATTERNS) {\n if (picomatch(pattern)(file)) {\n if (!best || confidence > best.confidence) {\n best = { layerName, filePath: file, confidence, matchedPattern: pattern };\n }\n }\n }\n if (best) results.push(best);\n }\n\n return results;\n },\n};\n\nfunction _buildConfigMatchers(configLayers: Record<string, string[]>): Array<[string, ReturnType<typeof picomatch>, string]> {\n return Object.entries(configLayers).flatMap(([layerName, patterns]) =>\n patterns.map((pattern): [string, ReturnType<typeof picomatch>, string] =>\n [layerName, picomatch(pattern), pattern]\n )\n );\n}\n\nfunction _matchConfig(\n file: string,\n matchers: Array<[string, ReturnType<typeof picomatch>, string]>\n): Omit<ArchLayerMatch, 'filePath'> | null {\n for (const [layerName, matcher, pattern] of matchers) {\n if (matcher(file)) return { layerName, confidence: 1.0, matchedPattern: `config:${pattern}` };\n }\n return null;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,uBAAsB;AAGtB,MAAM,iBAAkD;AAAA;AAAA,EAEtD,CAAC,MAAM,qBAAqB,GAAG;AAAA,EAC/B,CAAC,MAAM,mBAAmB,GAAG;AAAA,EAC7B,CAAC,MAAM,mBAAmB,IAAI;AAAA,EAC9B,CAAC,MAAM,qBAAqB,GAAG;AAAA,EAC/B,CAAC,MAAM,wBAAwB,IAAI;AAAA;AAAA,EAGnC,CAAC,WAAW,sBAAsB,GAAG;AAAA,EACrC,CAAC,WAAW,uBAAuB,IAAI;AAAA,EACvC,CAAC,WAAW,mBAAmB,GAAG;AAAA,EAClC,CAAC,WAAW,oBAAoB,GAAG;AAAA,EACnC,CAAC,WAAW,uBAAuB,IAAI;AAAA;AAAA,EAGvC,CAAC,QAAQ,0BAA0B,GAAG;AAAA,EACtC,CAAC,QAAQ,kBAAkB,IAAI;AAAA,EAC/B,CAAC,QAAQ,yBAAyB,GAAG;AAAA,EACrC,CAAC,QAAQ,oBAAoB,IAAI;AAAA,EACjC,CAAC,QAAQ,sBAAsB,IAAI;AAAA,EACnC,CAAC,QAAQ,oBAAoB,GAAG;AAAA;AAAA,EAGhC,CAAC,UAAU,kBAAkB,IAAI;AAAA,EACjC,CAAC,UAAU,mBAAmB,IAAI;AAAA,EAClC,CAAC,UAAU,qBAAqB,IAAI;AAAA,EACpC,CAAC,UAAU,wBAAwB,IAAI;AAAA,EACvC,CAAC,UAAU,uBAAuB,GAAG;AAAA;AAAA,EAGrC,CAAC,OAAO,oBAAoB,GAAG;AAAA,EAC/B,CAAC,OAAO,wBAAwB,IAAI;AAAA,EACpC,CAAC,OAAO,oBAAoB,IAAI;AAAA,EAChC,CAAC,OAAO,oBAAoB,GAAG;AAAA,EAC/B,CAAC,OAAO,mBAAmB,GAAG;AAChC;AAEA,MAAM,mBAAe,iBAAAA,SAAU,YAAY;AAEpC,MAAM,oBAAmC;AAAA,EAC9C,UAAU;AAAA,EAEV,MAAM,OAAO,OAAiB,cAAsB,cAAoE;AACtH,UAAM,UAA4B,CAAC;AACnC,UAAM,iBAAiB,qBAAqB,gBAAgB,CAAC,CAAC;AAE9D,eAAW,QAAQ,OAAO;AACxB,UAAI,CAAC,KAAK,SAAS,OAAO,EAAG;AAG7B,UAAI,aAAa,IAAI,EAAG;AAExB,YAAM,cAAc,aAAa,MAAM,cAAc;AACrD,UAAI,aAAa;AACf,gBAAQ,KAAK,EAAE,GAAG,aAAa,UAAU,KAAK,CAAC;AAC/C;AAAA,MACF;AAEA,UAAI,OAA8B;AAClC,iBAAW,CAAC,WAAW,SAAS,UAAU,KAAK,gBAAgB;AAC7D,gBAAI,iBAAAA,SAAU,OAAO,EAAE,IAAI,GAAG;AAC5B,cAAI,CAAC,QAAQ,aAAa,KAAK,YAAY;AACzC,mBAAO,EAAE,WAAW,UAAU,MAAM,YAAY,gBAAgB,QAAQ;AAAA,UAC1E;AAAA,QACF;AAAA,MACF;AACA,UAAI,KAAM,SAAQ,KAAK,IAAI;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,cAA+F;AAC3H,SAAO,OAAO,QAAQ,YAAY,EAAE;AAAA,IAAQ,CAAC,CAAC,WAAW,QAAQ,MAC/D,SAAS;AAAA,MAAI,CAAC,YACZ,CAAC,eAAW,iBAAAA,SAAU,OAAO,GAAG,OAAO;AAAA,IACzC;AAAA,EACF;AACF;AAEA,SAAS,aACP,MACA,UACyC;AACzC,aAAW,CAAC,WAAW,SAAS,OAAO,KAAK,UAAU;AACpD,QAAI,QAAQ,IAAI,EAAG,QAAO,EAAE,WAAW,YAAY,GAAK,gBAAgB,UAAU,OAAO,GAAG;AAAA,EAC9F;AACA,SAAO;AACT;",
6
+ "names": ["picomatch"]
7
+ }
@@ -36,6 +36,7 @@ var import_scala = require("./scala");
36
36
  var import_vue = require("./vue");
37
37
  var import_solidity = require("./solidity");
38
38
  var import_ocaml = require("./ocaml");
39
+ var import_dart = require("./dart");
39
40
  const LAYER_DETECTORS = [
40
41
  import_typescript.typescriptLayerDetector,
41
42
  import_python.pythonLayerDetector,
@@ -48,7 +49,8 @@ const LAYER_DETECTORS = [
48
49
  import_scala.scalaLayerDetector,
49
50
  import_vue.vueLayerDetector,
50
51
  import_solidity.solidityLayerDetector,
51
- import_ocaml.ocamlLayerDetector
52
+ import_ocaml.ocamlLayerDetector,
53
+ import_dart.dartLayerDetector
52
54
  ];
53
55
  function getAllLayerDetectors() {
54
56
  return LAYER_DETECTORS;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/architecture/layers/index.ts"],
4
- "sourcesContent": ["/**\n * Layer Detector Registry\n *\n * Dispatches layer detection to language-specific detectors.\n * Config-defined layers always win over auto-detection.\n */\nimport type { LayerDetector, ArchLayerMatch, ArchLayer } from '../types';\nimport { typescriptLayerDetector } from './typescript';\nimport { pythonLayerDetector } from './python';\nimport { goLayerDetector } from './go';\nimport { javaLayerDetector } from './java';\nimport { rubyLayerDetector } from './ruby';\nimport { rustLayerDetector } from './rust';\nimport { csharpLayerDetector } from './csharp';\nimport { elixirLayerDetector } from './elixir';\nimport { scalaLayerDetector } from './scala';\nimport { vueLayerDetector } from './vue';\nimport { solidityLayerDetector } from './solidity';\nimport { ocamlLayerDetector } from './ocaml';\n\nconst LAYER_DETECTORS: LayerDetector[] = [\n typescriptLayerDetector,\n pythonLayerDetector,\n goLayerDetector,\n javaLayerDetector,\n rubyLayerDetector,\n rustLayerDetector,\n csharpLayerDetector,\n elixirLayerDetector,\n scalaLayerDetector,\n vueLayerDetector,\n solidityLayerDetector,\n ocamlLayerDetector,\n];\n\nexport function getAllLayerDetectors(): LayerDetector[] {\n return LAYER_DETECTORS;\n}\n\nexport function registerLayerDetector(detector: LayerDetector): void {\n const idx = LAYER_DETECTORS.findIndex(d => d.language === detector.language && d.framework === detector.framework);\n if (idx >= 0) LAYER_DETECTORS[idx] = detector;\n else LAYER_DETECTORS.push(detector);\n}\n\nexport interface FileLayerAssignment {\n filePath: string;\n layerName: string;\n confidence: number;\n matchedPattern: string;\n}\n\n/**\n * Run all language-specific layer detectors against the file list.\n * Each file gets at most one layer assignment (highest confidence wins).\n * Config-defined layers (confidence=1.0) always beat auto-detected ones.\n *\n * @param files - relative file paths (from project root)\n * @param projectRoot - absolute project root path\n * @param configLayers - user-defined layer\u2192glob overrides from config\n */\nexport async function detectAllLayers(\n files: string[],\n projectRoot: string,\n configLayers?: Record<string, string[]>\n): Promise<FileLayerAssignment[]> {\n // Collect all matches from all detectors\n const allMatches: ArchLayerMatch[] = [];\n for (const detector of LAYER_DETECTORS) {\n const matches = await detector.detect(files, projectRoot, configLayers);\n allMatches.push(...matches);\n }\n\n // Per file, keep the highest-confidence match\n const best = new Map<string, ArchLayerMatch>();\n for (const match of allMatches) {\n const existing = best.get(match.filePath);\n if (!existing || match.confidence > existing.confidence) {\n best.set(match.filePath, match);\n }\n }\n\n return [...best.values()].map(m => ({\n filePath: m.filePath,\n layerName: m.layerName,\n confidence: m.confidence,\n matchedPattern: m.matchedPattern,\n }));\n}\n\n/**\n * From a list of FileLayerAssignment, derive the unique ArchLayer records.\n */\nexport function buildArchLayers(\n assignments: FileLayerAssignment[],\n configLayers?: Record<string, string[]>\n): ArchLayer[] {\n const layerMap = new Map<string, ArchLayer>();\n\n for (const a of assignments) {\n if (!layerMap.has(a.layerName)) {\n const isConfig = configLayers && a.layerName in configLayers;\n layerMap.set(a.layerName, {\n id: `layer:${a.layerName}`,\n name: a.layerName,\n source: isConfig ? 'config' : 'auto',\n patterns: [],\n updatedAt: Date.now(),\n });\n }\n const layer = layerMap.get(a.layerName)!;\n if (!layer.patterns.includes(a.matchedPattern)) {\n layer.patterns.push(a.matchedPattern);\n }\n }\n\n return [...layerMap.values()];\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,wBAAwC;AACxC,oBAAoC;AACpC,gBAAgC;AAChC,kBAAkC;AAClC,kBAAkC;AAClC,kBAAkC;AAClC,oBAAoC;AACpC,oBAAoC;AACpC,mBAAmC;AACnC,iBAAiC;AACjC,sBAAsC;AACtC,mBAAmC;AAEnC,MAAM,kBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,uBAAwC;AACtD,SAAO;AACT;AAEO,SAAS,sBAAsB,UAA+B;AACnE,QAAM,MAAM,gBAAgB,UAAU,OAAK,EAAE,aAAa,SAAS,YAAY,EAAE,cAAc,SAAS,SAAS;AACjH,MAAI,OAAO,EAAG,iBAAgB,GAAG,IAAI;AAAA,MAChC,iBAAgB,KAAK,QAAQ;AACpC;AAkBA,eAAsB,gBACpB,OACA,aACA,cACgC;AAEhC,QAAM,aAA+B,CAAC;AACtC,aAAW,YAAY,iBAAiB;AACtC,UAAM,UAAU,MAAM,SAAS,OAAO,OAAO,aAAa,YAAY;AACtE,eAAW,KAAK,GAAG,OAAO;AAAA,EAC5B;AAGA,QAAM,OAAO,oBAAI,IAA4B;AAC7C,aAAW,SAAS,YAAY;AAC9B,UAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AACxC,QAAI,CAAC,YAAY,MAAM,aAAa,SAAS,YAAY;AACvD,WAAK,IAAI,MAAM,UAAU,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC,EAAE,IAAI,QAAM;AAAA,IAClC,UAAU,EAAE;AAAA,IACZ,WAAW,EAAE;AAAA,IACb,YAAY,EAAE;AAAA,IACd,gBAAgB,EAAE;AAAA,EACpB,EAAE;AACJ;AAKO,SAAS,gBACd,aACA,cACa;AACb,QAAM,WAAW,oBAAI,IAAuB;AAE5C,aAAW,KAAK,aAAa;AAC3B,QAAI,CAAC,SAAS,IAAI,EAAE,SAAS,GAAG;AAC9B,YAAM,WAAW,gBAAgB,EAAE,aAAa;AAChD,eAAS,IAAI,EAAE,WAAW;AAAA,QACxB,IAAI,SAAS,EAAE,SAAS;AAAA,QACxB,MAAM,EAAE;AAAA,QACR,QAAQ,WAAW,WAAW;AAAA,QAC9B,UAAU,CAAC;AAAA,QACX,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AACA,UAAM,QAAQ,SAAS,IAAI,EAAE,SAAS;AACtC,QAAI,CAAC,MAAM,SAAS,SAAS,EAAE,cAAc,GAAG;AAC9C,YAAM,SAAS,KAAK,EAAE,cAAc;AAAA,IACtC;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,SAAS,OAAO,CAAC;AAC9B;",
4
+ "sourcesContent": ["/**\n * Layer Detector Registry\n *\n * Dispatches layer detection to language-specific detectors.\n * Config-defined layers always win over auto-detection.\n */\nimport type { LayerDetector, ArchLayerMatch, ArchLayer } from '../types';\nimport { typescriptLayerDetector } from './typescript';\nimport { pythonLayerDetector } from './python';\nimport { goLayerDetector } from './go';\nimport { javaLayerDetector } from './java';\nimport { rubyLayerDetector } from './ruby';\nimport { rustLayerDetector } from './rust';\nimport { csharpLayerDetector } from './csharp';\nimport { elixirLayerDetector } from './elixir';\nimport { scalaLayerDetector } from './scala';\nimport { vueLayerDetector } from './vue';\nimport { solidityLayerDetector } from './solidity';\nimport { ocamlLayerDetector } from './ocaml';\nimport { dartLayerDetector } from './dart';\n\nconst LAYER_DETECTORS: LayerDetector[] = [\n typescriptLayerDetector,\n pythonLayerDetector,\n goLayerDetector,\n javaLayerDetector,\n rubyLayerDetector,\n rustLayerDetector,\n csharpLayerDetector,\n elixirLayerDetector,\n scalaLayerDetector,\n vueLayerDetector,\n solidityLayerDetector,\n ocamlLayerDetector,\n dartLayerDetector,\n];\n\nexport function getAllLayerDetectors(): LayerDetector[] {\n return LAYER_DETECTORS;\n}\n\nexport function registerLayerDetector(detector: LayerDetector): void {\n const idx = LAYER_DETECTORS.findIndex(d => d.language === detector.language && d.framework === detector.framework);\n if (idx >= 0) LAYER_DETECTORS[idx] = detector;\n else LAYER_DETECTORS.push(detector);\n}\n\nexport interface FileLayerAssignment {\n filePath: string;\n layerName: string;\n confidence: number;\n matchedPattern: string;\n}\n\n/**\n * Run all language-specific layer detectors against the file list.\n * Each file gets at most one layer assignment (highest confidence wins).\n * Config-defined layers (confidence=1.0) always beat auto-detected ones.\n *\n * @param files - relative file paths (from project root)\n * @param projectRoot - absolute project root path\n * @param configLayers - user-defined layer\u2192glob overrides from config\n */\nexport async function detectAllLayers(\n files: string[],\n projectRoot: string,\n configLayers?: Record<string, string[]>\n): Promise<FileLayerAssignment[]> {\n // Collect all matches from all detectors\n const allMatches: ArchLayerMatch[] = [];\n for (const detector of LAYER_DETECTORS) {\n const matches = await detector.detect(files, projectRoot, configLayers);\n allMatches.push(...matches);\n }\n\n // Per file, keep the highest-confidence match\n const best = new Map<string, ArchLayerMatch>();\n for (const match of allMatches) {\n const existing = best.get(match.filePath);\n if (!existing || match.confidence > existing.confidence) {\n best.set(match.filePath, match);\n }\n }\n\n return [...best.values()].map(m => ({\n filePath: m.filePath,\n layerName: m.layerName,\n confidence: m.confidence,\n matchedPattern: m.matchedPattern,\n }));\n}\n\n/**\n * From a list of FileLayerAssignment, derive the unique ArchLayer records.\n */\nexport function buildArchLayers(\n assignments: FileLayerAssignment[],\n configLayers?: Record<string, string[]>\n): ArchLayer[] {\n const layerMap = new Map<string, ArchLayer>();\n\n for (const a of assignments) {\n if (!layerMap.has(a.layerName)) {\n const isConfig = configLayers && a.layerName in configLayers;\n layerMap.set(a.layerName, {\n id: `layer:${a.layerName}`,\n name: a.layerName,\n source: isConfig ? 'config' : 'auto',\n patterns: [],\n updatedAt: Date.now(),\n });\n }\n const layer = layerMap.get(a.layerName)!;\n if (!layer.patterns.includes(a.matchedPattern)) {\n layer.patterns.push(a.matchedPattern);\n }\n }\n\n return [...layerMap.values()];\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,wBAAwC;AACxC,oBAAoC;AACpC,gBAAgC;AAChC,kBAAkC;AAClC,kBAAkC;AAClC,kBAAkC;AAClC,oBAAoC;AACpC,oBAAoC;AACpC,mBAAmC;AACnC,iBAAiC;AACjC,sBAAsC;AACtC,mBAAmC;AACnC,kBAAkC;AAElC,MAAM,kBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,uBAAwC;AACtD,SAAO;AACT;AAEO,SAAS,sBAAsB,UAA+B;AACnE,QAAM,MAAM,gBAAgB,UAAU,OAAK,EAAE,aAAa,SAAS,YAAY,EAAE,cAAc,SAAS,SAAS;AACjH,MAAI,OAAO,EAAG,iBAAgB,GAAG,IAAI;AAAA,MAChC,iBAAgB,KAAK,QAAQ;AACpC;AAkBA,eAAsB,gBACpB,OACA,aACA,cACgC;AAEhC,QAAM,aAA+B,CAAC;AACtC,aAAW,YAAY,iBAAiB;AACtC,UAAM,UAAU,MAAM,SAAS,OAAO,OAAO,aAAa,YAAY;AACtE,eAAW,KAAK,GAAG,OAAO;AAAA,EAC5B;AAGA,QAAM,OAAO,oBAAI,IAA4B;AAC7C,aAAW,SAAS,YAAY;AAC9B,UAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AACxC,QAAI,CAAC,YAAY,MAAM,aAAa,SAAS,YAAY;AACvD,WAAK,IAAI,MAAM,UAAU,KAAK;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC,EAAE,IAAI,QAAM;AAAA,IAClC,UAAU,EAAE;AAAA,IACZ,WAAW,EAAE;AAAA,IACb,YAAY,EAAE;AAAA,IACd,gBAAgB,EAAE;AAAA,EACpB,EAAE;AACJ;AAKO,SAAS,gBACd,aACA,cACa;AACb,QAAM,WAAW,oBAAI,IAAuB;AAE5C,aAAW,KAAK,aAAa;AAC3B,QAAI,CAAC,SAAS,IAAI,EAAE,SAAS,GAAG;AAC9B,YAAM,WAAW,gBAAgB,EAAE,aAAa;AAChD,eAAS,IAAI,EAAE,WAAW;AAAA,QACxB,IAAI,SAAS,EAAE,SAAS;AAAA,QACxB,MAAM,EAAE;AAAA,QACR,QAAQ,WAAW,WAAW;AAAA,QAC9B,UAAU,CAAC;AAAA,QACX,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AACA,UAAM,QAAQ,SAAS,IAAI,EAAE,SAAS;AACtC,QAAI,CAAC,MAAM,SAAS,SAAS,EAAE,cAAc,GAAG;AAC9C,YAAM,SAAS,KAAK,EAAE,cAAc;AAAA,IACtC;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,SAAS,OAAO,CAAC;AAC9B;",
6
6
  "names": []
7
7
  }
@@ -33,6 +33,7 @@ const c = {
33
33
  white: "\x1B[97m"
34
34
  };
35
35
  const TIPS = [
36
+ // Core graph
36
37
  `Run ${c.cyan}kirograph context "your task"${c.reset} to get relevant code
37
38
  in one shot \u2014 no file scanning needed.`,
38
39
  `Use ${c.cyan}kirograph query <name>${c.reset} instead of grep.
@@ -41,14 +42,81 @@ const TIPS = [
41
42
  that depends on a changed file \u2014 great for CI.`,
42
43
  `${c.cyan}kirograph files --format grouped${c.reset} shows your project
43
44
  structure grouped by language from the index.`,
44
- `${c.cyan}kirograph impact <symbol>${c.reset} shows the blast radius
45
- before you change anything.`,
46
- `Run ${c.cyan}kirograph install${c.reset} once per Kiro workspace to wire up
47
- MCP, auto-sync hooks, and steering automatically.`,
45
+ `${c.cyan}kirograph path LoginController DatabasePool${c.reset}
46
+ finds the shortest connection between any two symbols.`,
47
+ `${c.cyan}kirograph hotspots${c.reset} ranks symbols by edge degree \u2014
48
+ the top results are the riskiest to change.`,
49
+ `${c.cyan}kirograph surprising${c.reset} surfaces hidden cross-module coupling
50
+ you didn't know existed.`,
51
+ `${c.cyan}kirograph dead-code${c.reset} lists unexported symbols with zero
52
+ incoming references \u2014 safe candidates for deletion.`,
53
+ `${c.cyan}kirograph snapshot save pre-refactor${c.reset} then
54
+ ${c.cyan}kirograph snapshot diff pre-refactor${c.reset} after \u2014 structural changelog.`,
55
+ `Pipe git diff into kirograph:
56
+ ${c.cyan}git diff --name-only | kirograph affected --stdin${c.reset}`,
57
+ // Indexing
48
58
  `${c.cyan}kirograph sync${c.reset} is incremental \u2014 it only re-parses
49
59
  files whose content has changed since last index.`,
50
- `Pipe git diff into kirograph:
51
- ${c.cyan}git diff --name-only | kirograph affected --stdin${c.reset}`
60
+ `${c.cyan}kirograph sync-if-dirty${c.reset} is safe to call on every agent stop \u2014
61
+ it's a no-op when nothing changed.`,
62
+ `Run ${c.cyan}kirograph install${c.reset} once per workspace to wire up
63
+ MCP, auto-sync hooks, and steering automatically.`,
64
+ // Architecture
65
+ `${c.cyan}kirograph coupling --sort instability${c.reset} shows which packages
66
+ are most volatile and risky to depend on.`,
67
+ `${c.cyan}kirograph architecture${c.reset} detects packages and layers (api/service/
68
+ data/ui/shared) without any config \u2014 just enable it.`,
69
+ `${c.cyan}kirograph package src/auth${c.reset} shows incoming dependents,
70
+ outgoing deps, and files in one call.`,
71
+ // Security
72
+ `${c.cyan}kirograph security${c.reset} gives an instant vulnerability overview \u2014
73
+ dep count, CVEs, verdict breakdown, stale warnings.`,
74
+ `${c.cyan}kirograph vulns --verdict affected${c.reset} filters to only CVEs
75
+ with a confirmed reachable call path from your entry points.`,
76
+ `${c.cyan}kirograph vulns --epss 0.5${c.reset} shows only vulnerabilities
77
+ with >= 50% exploitation probability \u2014 EPSS beats CVSS for triage.`,
78
+ `${c.cyan}kirograph reachability CVE-2024-1234${c.reset} shows the exact
79
+ call path from your entry points to the vulnerable dependency.`,
80
+ `${c.cyan}kirograph licenses --policy${c.reset} flags dependencies that violate
81
+ your configured SPDX license policy (deny/warn lists).`,
82
+ `${c.cyan}kirograph staleness --threshold 0.7${c.reset} identifies dependencies
83
+ that are significantly behind their latest published version.`,
84
+ `${c.cyan}kirograph sbom --output sbom.json${c.reset} exports a CycloneDX 1.5
85
+ SBOM \u2014 parent directory is created automatically if missing.`,
86
+ `${c.cyan}kirograph vex --output vex.json${c.reset} exports a VEX document
87
+ with reachability-derived analysis states for each CVE.`,
88
+ // Memory
89
+ `${c.cyan}kirograph mem search "auth decision"${c.reset} recalls past observations
90
+ using hybrid FTS + vector search across all sessions.`,
91
+ `${c.cyan}kirograph mem store "..." --kind decision${c.reset} saves an observation
92
+ linked to relevant code symbols automatically.`,
93
+ `${c.cyan}kirograph mem timeline${c.reset} shows recent sessions and what
94
+ the agent observed \u2014 great for onboarding after a break.`,
95
+ // Docs & Data
96
+ `${c.cyan}kirograph docs search "authentication"${c.reset} searches indexed
97
+ documentation sections \u2014 faster than reading full files.`,
98
+ `${c.cyan}kirograph data describe orders${c.reset} gives full schema profile
99
+ without loading a single data row into context.`,
100
+ `${c.cyan}kirograph data aggregate orders --group-by region --metric sum:amount${c.reset}
101
+ runs GROUP BY server-side \u2014 only results enter context.`,
102
+ // Export & token tools
103
+ `${c.cyan}kirograph export start${c.reset} opens an interactive graph dashboard
104
+ in your browser \u2014 search, path-find, cluster, heat map.`,
105
+ `${c.cyan}kirograph exec "npm test"${c.reset} compresses test output by 80-90% \u2014
106
+ you get pass/fail and errors, not thousands of lines of noise.`,
107
+ `${c.cyan}kirograph gain --graph${c.reset} shows your cumulative token savings
108
+ from graph tools and shell compression over time.`,
109
+ // Workflow files
110
+ `Type ${c.cyan}/kirograph-security${c.reset} in Kiro to activate a step-by-step
111
+ security audit workflow with CVE triage and EPSS guidance.`,
112
+ `Type ${c.cyan}/kirograph-review${c.reset} in Kiro for a structured code review:
113
+ blast radius, test coverage, surprising coupling.`,
114
+ `Type ${c.cyan}/kirograph-refactor${c.reset} in Kiro before any major refactor \u2014
115
+ it guides you through blast radius, rename preview, and diff verify.`,
116
+ `Type ${c.cyan}/kirograph-debug${c.reset} in Kiro to trace a bug systematically:
117
+ callers, callees, recent diff, root cause analysis.`,
118
+ `Type ${c.cyan}/kirograph-architecture${c.reset} in Kiro for a full architecture
119
+ exploration: packages, layers, coupling, hidden cycles.`
52
120
  ];
53
121
  function pickTip() {
54
122
  const idx = Math.floor(Date.now() / 864e5) % TIPS.length;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/bin/banner.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph CLI Banner\n * Displays the KIROGRAPH ASCII art header and a rotating \"Did you know?\" tip.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst figlet = require('figlet');\n\n// ANSI color helpers (no external deps)\nconst c = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n purple: '\\x1b[38;5;135m',\n violet: '\\x1b[38;5;99m',\n cyan: '\\x1b[38;5;117m',\n gray: '\\x1b[90m',\n white: '\\x1b[97m',\n};\n\nconst TIPS = [\n `Run ${c.cyan}kirograph context \"your task\"${c.reset} to get relevant code\\n in one shot \u2014 no file scanning needed.`,\n `Use ${c.cyan}kirograph query <name>${c.reset} instead of grep.\\n It searches the symbol index instantly.`,\n `${c.cyan}kirograph affected src/foo.ts${c.reset} finds every test file\\n that depends on a changed file \u2014 great for CI.`,\n `${c.cyan}kirograph files --format grouped${c.reset} shows your project\\n structure grouped by language from the index.`,\n `${c.cyan}kirograph impact <symbol>${c.reset} shows the blast radius\\n before you change anything.`,\n `Run ${c.cyan}kirograph install${c.reset} once per Kiro workspace to wire up\\n MCP, auto-sync hooks, and steering automatically.`,\n `${c.cyan}kirograph sync${c.reset} is incremental \u2014 it only re-parses\\n files whose content has changed since last index.`,\n `Pipe git diff into kirograph:\\n ${c.cyan}git diff --name-only | kirograph affected --stdin${c.reset}`,\n];\n\nfunction pickTip(): string {\n // Rotate daily so it feels fresh but is deterministic\n const idx = Math.floor(Date.now() / 86_400_000) % TIPS.length;\n return TIPS[idx];\n}\n\nfunction boxed(text: string, width = 70): string {\n const lines = text.split('\\n');\n const top = `${c.gray}\u250C${'\u2500'.repeat(width - 2)}\u2510${c.reset}`;\n const bottom = `${c.gray}\u2514${'\u2500'.repeat(width - 2)}\u2518${c.reset}`;\n const padded = lines.map(l => {\n // Strip ANSI for length calculation\n const plain = l.replace(/\\x1b\\[[0-9;]*m/g, '');\n const pad = Math.max(0, width - 4 - plain.length);\n return `${c.gray}\u2502${c.reset} ${l}${' '.repeat(pad)} ${c.gray}\u2502${c.reset}`;\n });\n return [top, ...padded, bottom].join('\\n');\n}\n\nexport function printBanner(): void {\n // ASCII art title\n const art: string = figlet.textSync('KIROGRAPH', { font: 'ANSI Shadow' });\n\n // Colorize each line of the art in purple/violet gradient\n const artLines = art.split('\\n');\n const colored = artLines.map((line, i) => {\n const color = i < artLines.length / 2 ? c.purple : c.violet;\n return `${color}${line}${c.reset}`;\n }).join('\\n');\n\n console.log('\\n' + colored);\n\n // Subtitle\n console.log(`${c.dim} Semantic code knowledge graph for Kiro \u2014 100% local${c.reset}`);\n console.log(`${c.dim} Inspired by CodeGraph \u2014 original idea by ${c.reset}${c.violet}github.com/colbymchenry${c.reset}\\n`);\n\n // Did you know box\n const label = `${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 ${c.reset}${c.bold}${c.white}Did you know?${c.reset}${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}`;\n console.log(label);\n console.log(boxed(pickTip()));\n console.log();\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,SAAS,QAAQ,QAAQ;AAG/B,MAAM,IAAI;AAAA,EACR,OAAQ;AAAA,EACR,MAAQ;AAAA,EACR,KAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,OAAQ;AACV;AAEA,MAAM,OAAO;AAAA,EACX,OAAO,EAAE,IAAI,gCAAgC,EAAE,KAAK;AAAA;AAAA,EACpD,OAAO,EAAE,IAAI,yBAAyB,EAAE,KAAK;AAAA;AAAA,EAC7C,GAAG,EAAE,IAAI,gCAAgC,EAAE,KAAK;AAAA;AAAA,EAChD,GAAG,EAAE,IAAI,mCAAmC,EAAE,KAAK;AAAA;AAAA,EACnD,GAAG,EAAE,IAAI,4BAA4B,EAAE,KAAK;AAAA;AAAA,EAC5C,OAAO,EAAE,IAAI,oBAAoB,EAAE,KAAK;AAAA;AAAA,EACxC,GAAG,EAAE,IAAI,iBAAiB,EAAE,KAAK;AAAA;AAAA,EACjC;AAAA,IAAoC,EAAE,IAAI,oDAAoD,EAAE,KAAK;AACvG;AAEA,SAAS,UAAkB;AAEzB,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,KAAU,IAAI,KAAK;AACvD,SAAO,KAAK,GAAG;AACjB;AAEA,SAAS,MAAM,MAAc,QAAQ,IAAY;AAC/C,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,MAAS,GAAG,EAAE,IAAI,SAAI,SAAI,OAAO,QAAQ,CAAC,CAAC,SAAI,EAAE,KAAK;AAC5D,QAAM,SAAS,GAAG,EAAE,IAAI,SAAI,SAAI,OAAO,QAAQ,CAAC,CAAC,SAAI,EAAE,KAAK;AAC5D,QAAM,SAAS,MAAM,IAAI,OAAK;AAE5B,UAAM,QAAQ,EAAE,QAAQ,mBAAmB,EAAE;AAC7C,UAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,IAAI,MAAM,MAAM;AAChD,WAAO,GAAG,EAAE,IAAI,SAAI,EAAE,KAAK,KAAK,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,KAAK,EAAE,IAAI,SAAI,EAAE,KAAK;AAAA,EAC3E,CAAC;AACD,SAAO,CAAC,KAAK,GAAG,QAAQ,MAAM,EAAE,KAAK,IAAI;AAC3C;AAEO,SAAS,cAAoB;AAElC,QAAM,MAAc,OAAO,SAAS,aAAa,EAAE,MAAM,cAAc,CAAC;AAGxE,QAAM,WAAW,IAAI,MAAM,IAAI;AAC/B,QAAM,UAAU,SAAS,IAAI,CAAC,MAAM,MAAM;AACxC,UAAM,QAAQ,IAAI,SAAS,SAAS,IAAI,EAAE,SAAS,EAAE;AACrD,WAAO,GAAG,KAAK,GAAG,IAAI,GAAG,EAAE,KAAK;AAAA,EAClC,CAAC,EAAE,KAAK,IAAI;AAEZ,UAAQ,IAAI,OAAO,OAAO;AAG1B,UAAQ,IAAI,GAAG,EAAE,GAAG,6DAAwD,EAAE,KAAK,EAAE;AACrF,UAAQ,IAAI,GAAG,EAAE,GAAG,mDAA8C,EAAE,KAAK,GAAG,EAAE,MAAM,0BAA0B,EAAE,KAAK;AAAA,CAAI;AAGzH,QAAM,QAAQ,GAAG,EAAE,IAAI,8IAA2B,EAAE,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,KAAK,gBAAgB,EAAE,KAAK,GAAG,EAAE,IAAI,8IAA2B,EAAE,KAAK;AAC9I,UAAQ,IAAI,KAAK;AACjB,UAAQ,IAAI,MAAM,QAAQ,CAAC,CAAC;AAC5B,UAAQ,IAAI;AACd;",
4
+ "sourcesContent": ["/**\n * KiroGraph CLI Banner\n * Displays the KIROGRAPH ASCII art header and a rotating \"Did you know?\" tip.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nconst figlet = require('figlet');\n\n// ANSI color helpers (no external deps)\nconst c = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n purple: '\\x1b[38;5;135m',\n violet: '\\x1b[38;5;99m',\n cyan: '\\x1b[38;5;117m',\n gray: '\\x1b[90m',\n white: '\\x1b[97m',\n};\n\nconst TIPS = [\n // Core graph\n `Run ${c.cyan}kirograph context \"your task\"${c.reset} to get relevant code\\n in one shot \u2014 no file scanning needed.`,\n `Use ${c.cyan}kirograph query <name>${c.reset} instead of grep.\\n It searches the symbol index instantly.`,\n `${c.cyan}kirograph affected src/foo.ts${c.reset} finds every test file\\n that depends on a changed file \u2014 great for CI.`,\n `${c.cyan}kirograph files --format grouped${c.reset} shows your project\\n structure grouped by language from the index.`,\n `${c.cyan}kirograph path LoginController DatabasePool${c.reset}\\n finds the shortest connection between any two symbols.`,\n `${c.cyan}kirograph hotspots${c.reset} ranks symbols by edge degree \u2014\\n the top results are the riskiest to change.`,\n `${c.cyan}kirograph surprising${c.reset} surfaces hidden cross-module coupling\\n you didn't know existed.`,\n `${c.cyan}kirograph dead-code${c.reset} lists unexported symbols with zero\\n incoming references \u2014 safe candidates for deletion.`,\n `${c.cyan}kirograph snapshot save pre-refactor${c.reset} then\\n ${c.cyan}kirograph snapshot diff pre-refactor${c.reset} after \u2014 structural changelog.`,\n `Pipe git diff into kirograph:\\n ${c.cyan}git diff --name-only | kirograph affected --stdin${c.reset}`,\n // Indexing\n `${c.cyan}kirograph sync${c.reset} is incremental \u2014 it only re-parses\\n files whose content has changed since last index.`,\n `${c.cyan}kirograph sync-if-dirty${c.reset} is safe to call on every agent stop \u2014\\n it's a no-op when nothing changed.`,\n `Run ${c.cyan}kirograph install${c.reset} once per workspace to wire up\\n MCP, auto-sync hooks, and steering automatically.`,\n // Architecture\n `${c.cyan}kirograph coupling --sort instability${c.reset} shows which packages\\n are most volatile and risky to depend on.`,\n `${c.cyan}kirograph architecture${c.reset} detects packages and layers (api/service/\\n data/ui/shared) without any config \u2014 just enable it.`,\n `${c.cyan}kirograph package src/auth${c.reset} shows incoming dependents,\\n outgoing deps, and files in one call.`,\n // Security\n `${c.cyan}kirograph security${c.reset} gives an instant vulnerability overview \u2014\\n dep count, CVEs, verdict breakdown, stale warnings.`,\n `${c.cyan}kirograph vulns --verdict affected${c.reset} filters to only CVEs\\n with a confirmed reachable call path from your entry points.`,\n `${c.cyan}kirograph vulns --epss 0.5${c.reset} shows only vulnerabilities\\n with >= 50% exploitation probability \u2014 EPSS beats CVSS for triage.`,\n `${c.cyan}kirograph reachability CVE-2024-1234${c.reset} shows the exact\\n call path from your entry points to the vulnerable dependency.`,\n `${c.cyan}kirograph licenses --policy${c.reset} flags dependencies that violate\\n your configured SPDX license policy (deny/warn lists).`,\n `${c.cyan}kirograph staleness --threshold 0.7${c.reset} identifies dependencies\\n that are significantly behind their latest published version.`,\n `${c.cyan}kirograph sbom --output sbom.json${c.reset} exports a CycloneDX 1.5\\n SBOM \u2014 parent directory is created automatically if missing.`,\n `${c.cyan}kirograph vex --output vex.json${c.reset} exports a VEX document\\n with reachability-derived analysis states for each CVE.`,\n // Memory\n `${c.cyan}kirograph mem search \"auth decision\"${c.reset} recalls past observations\\n using hybrid FTS + vector search across all sessions.`,\n `${c.cyan}kirograph mem store \"...\" --kind decision${c.reset} saves an observation\\n linked to relevant code symbols automatically.`,\n `${c.cyan}kirograph mem timeline${c.reset} shows recent sessions and what\\n the agent observed \u2014 great for onboarding after a break.`,\n // Docs & Data\n `${c.cyan}kirograph docs search \"authentication\"${c.reset} searches indexed\\n documentation sections \u2014 faster than reading full files.`,\n `${c.cyan}kirograph data describe orders${c.reset} gives full schema profile\\n without loading a single data row into context.`,\n `${c.cyan}kirograph data aggregate orders --group-by region --metric sum:amount${c.reset}\\n runs GROUP BY server-side \u2014 only results enter context.`,\n // Export & token tools\n `${c.cyan}kirograph export start${c.reset} opens an interactive graph dashboard\\n in your browser \u2014 search, path-find, cluster, heat map.`,\n `${c.cyan}kirograph exec \"npm test\"${c.reset} compresses test output by 80-90% \u2014\\n you get pass/fail and errors, not thousands of lines of noise.`,\n `${c.cyan}kirograph gain --graph${c.reset} shows your cumulative token savings\\n from graph tools and shell compression over time.`,\n // Workflow files\n `Type ${c.cyan}/kirograph-security${c.reset} in Kiro to activate a step-by-step\\n security audit workflow with CVE triage and EPSS guidance.`,\n `Type ${c.cyan}/kirograph-review${c.reset} in Kiro for a structured code review:\\n blast radius, test coverage, surprising coupling.`,\n `Type ${c.cyan}/kirograph-refactor${c.reset} in Kiro before any major refactor \u2014\\n it guides you through blast radius, rename preview, and diff verify.`,\n `Type ${c.cyan}/kirograph-debug${c.reset} in Kiro to trace a bug systematically:\\n callers, callees, recent diff, root cause analysis.`,\n `Type ${c.cyan}/kirograph-architecture${c.reset} in Kiro for a full architecture\\n exploration: packages, layers, coupling, hidden cycles.`,\n];\n\nfunction pickTip(): string {\n // Rotate daily so it feels fresh but is deterministic\n const idx = Math.floor(Date.now() / 86_400_000) % TIPS.length;\n return TIPS[idx];\n}\n\nfunction boxed(text: string, width = 70): string {\n const lines = text.split('\\n');\n const top = `${c.gray}\u250C${'\u2500'.repeat(width - 2)}\u2510${c.reset}`;\n const bottom = `${c.gray}\u2514${'\u2500'.repeat(width - 2)}\u2518${c.reset}`;\n const padded = lines.map(l => {\n // Strip ANSI for length calculation\n const plain = l.replace(/\\x1b\\[[0-9;]*m/g, '');\n const pad = Math.max(0, width - 4 - plain.length);\n return `${c.gray}\u2502${c.reset} ${l}${' '.repeat(pad)} ${c.gray}\u2502${c.reset}`;\n });\n return [top, ...padded, bottom].join('\\n');\n}\n\nexport function printBanner(): void {\n // ASCII art title\n const art: string = figlet.textSync('KIROGRAPH', { font: 'ANSI Shadow' });\n\n // Colorize each line of the art in purple/violet gradient\n const artLines = art.split('\\n');\n const colored = artLines.map((line, i) => {\n const color = i < artLines.length / 2 ? c.purple : c.violet;\n return `${color}${line}${c.reset}`;\n }).join('\\n');\n\n console.log('\\n' + colored);\n\n // Subtitle\n console.log(`${c.dim} Semantic code knowledge graph for Kiro \u2014 100% local${c.reset}`);\n console.log(`${c.dim} Inspired by CodeGraph \u2014 original idea by ${c.reset}${c.violet}github.com/colbymchenry${c.reset}\\n`);\n\n // Did you know box\n const label = `${c.gray}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 ${c.reset}${c.bold}${c.white}Did you know?${c.reset}${c.gray} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c.reset}`;\n console.log(label);\n console.log(boxed(pickTip()));\n console.log();\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -53,18 +53,53 @@ function register(program) {
53
53
  depth: parseInt(opts.depth),
54
54
  testPattern: opts.filter
55
55
  });
56
+ const affectedSet = new Set(affected);
57
+ try {
58
+ const { loadConfig } = await Promise.resolve().then(() => require("../../config.js"));
59
+ const config = await loadConfig(target);
60
+ if (config.enableData) {
61
+ const db = cg.getDatabase();
62
+ db.applyDataSchema();
63
+ const rawDb = db.getRawDb();
64
+ const tableExists = rawDb.get("SELECT name FROM sqlite_master WHERE type='table' AND name='data_code_refs'");
65
+ if (tableExists) {
66
+ for (const file of changedFiles) {
67
+ const rel = file.replace(/\\/g, "/").replace(/^\.\//, "");
68
+ const dataset = rawDb.get("SELECT id FROM data_datasets WHERE file_path = ?", [rel]);
69
+ if (dataset) {
70
+ const refs = rawDb.all(
71
+ "SELECT qualified_name FROM data_code_refs WHERE dataset_id = ?",
72
+ [dataset.id]
73
+ );
74
+ for (const ref of refs) {
75
+ const picomatch = require("picomatch");
76
+ const isTest = picomatch(
77
+ opts.filter ?? "{**/*.spec.*,**/*.test.*,**/*_test.*,**/*Test.*,**/*Spec.*,**/*.t.sol,**/*.bats,**/e2e/**,**/test/**,**/tests/**,**/spec/**,**/__tests__/**,**/src/test/**}"
78
+ );
79
+ const node = rawDb.get("SELECT file_path FROM nodes WHERE qualified_name = ?", [ref.qualified_name]);
80
+ if (node && isTest(node.file_path)) {
81
+ affectedSet.add(node.file_path);
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ } catch {
89
+ }
90
+ const finalAffected = [...affectedSet].sort();
56
91
  if (opts.json) {
57
- console.log(JSON.stringify({ changedFiles, affectedTests: affected }, null, 2));
92
+ console.log(JSON.stringify({ changedFiles, affectedTests: finalAffected }, null, 2));
58
93
  } else if (opts.quiet) {
59
- for (const f of affected) console.log(f);
94
+ for (const f of finalAffected) console.log(f);
60
95
  } else {
61
- if (affected.length === 0) {
96
+ if (finalAffected.length === 0) {
62
97
  console.log(` ${import_ui.dim}No affected test files found.${import_ui.reset}`);
63
98
  } else {
64
99
  console.log(`
65
- ${(0, import_ui.section)("Affected test files")} ${import_ui.dim}(${affected.length})${import_ui.reset}
100
+ ${(0, import_ui.section)("Affected test files")} ${import_ui.dim}(${finalAffected.length})${import_ui.reset}
66
101
  `);
67
- for (const f of affected) console.log(` ${import_ui.violet}${import_ui.bold}${f}${import_ui.reset}`);
102
+ for (const f of finalAffected) console.log(` ${import_ui.violet}${import_ui.bold}${f}${import_ui.reset}`);
68
103
  console.log();
69
104
  }
70
105
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/commands/affected.ts"],
4
- "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { dim, reset, violet, bold, section } from '../ui';\n\nexport function register(program: Command): void {\n program\n .command('affected [files...]')\n .description('Find test files affected by changed source files')\n .option('--stdin', 'Read file list from stdin (one per line)')\n .option('-d, --depth <n>', 'Max dependency traversal depth', '5')\n .option('-f, --filter <glob>', 'Custom glob to identify test files')\n .option('-j, --json', 'Output as JSON')\n .option('-q, --quiet', 'Output file paths only')\n .option('-p, --path <path>', 'Project path')\n .action(async (files: string[], opts: {\n stdin?: boolean; depth: string; filter?: string;\n json?: boolean; quiet?: boolean; path?: string;\n }) => {\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n const target = path.resolve(opts.path ?? process.cwd());\n const cg = await KiroGraph.open(target);\n\n let changedFiles = [...files];\n\n if (opts.stdin) {\n const lines = fs.readFileSync('/dev/stdin', 'utf8').split('\\n').map((l: string) => l.trim()).filter(Boolean);\n changedFiles.push(...lines);\n }\n\n if (changedFiles.length === 0) {\n console.error('No files provided. Pass files as arguments or use --stdin.');\n cg.close(); process.exit(1);\n }\n\n const affected = cg.getAffectedTests(changedFiles, {\n depth: parseInt(opts.depth),\n testPattern: opts.filter,\n });\n\n if (opts.json) {\n console.log(JSON.stringify({ changedFiles, affectedTests: affected }, null, 2));\n } else if (opts.quiet) {\n for (const f of affected) console.log(f);\n } else {\n if (affected.length === 0) {\n console.log(` ${dim}No affected test files found.${reset}`);\n } else {\n console.log(`\\n ${section('Affected test files')} ${dim}(${affected.length})${reset}\\n`);\n for (const f of affected) console.log(` ${violet}${bold}${f}${reset}`);\n console.log();\n }\n }\n cg.close();\n });\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,WAAsB;AACtB,SAAoB;AACpB,gBAAkD;AAE3C,SAAS,SAAS,SAAwB;AAC/C,UACG,QAAQ,qBAAqB,EAC7B,YAAY,kDAAkD,EAC9D,OAAO,WAAW,0CAA0C,EAC5D,OAAO,mBAAmB,kCAAkC,GAAG,EAC/D,OAAO,uBAAuB,oCAAoC,EAClE,OAAO,cAAc,gBAAgB,EACrC,OAAO,eAAe,wBAAwB,EAC9C,OAAO,qBAAqB,cAAc,EAC1C,OAAO,OAAO,OAAiB,SAG1B;AACJ,UAAM,aAAa,MAAM,QAAQ,QAAQ,EAAE,KAAK,MAAM,QAAQ,gBAAgB,CAAC,GAAG;AAClF,UAAM,SAAS,KAAK,QAAQ,KAAK,QAAQ,QAAQ,IAAI,CAAC;AACtD,UAAM,KAAK,MAAM,UAAU,KAAK,MAAM;AAEtC,QAAI,eAAe,CAAC,GAAG,KAAK;AAE5B,QAAI,KAAK,OAAO;AACd,YAAM,QAAQ,GAAG,aAAa,cAAc,MAAM,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAC3G,mBAAa,KAAK,GAAG,KAAK;AAAA,IAC5B;AAEA,QAAI,aAAa,WAAW,GAAG;AAC7B,cAAQ,MAAM,4DAA4D;AAC1E,SAAG,MAAM;AAAG,cAAQ,KAAK,CAAC;AAAA,IAC5B;AAEA,UAAM,WAAW,GAAG,iBAAiB,cAAc;AAAA,MACjD,OAAO,SAAS,KAAK,KAAK;AAAA,MAC1B,aAAa,KAAK;AAAA,IACpB,CAAC;AAED,QAAI,KAAK,MAAM;AACb,cAAQ,IAAI,KAAK,UAAU,EAAE,cAAc,eAAe,SAAS,GAAG,MAAM,CAAC,CAAC;AAAA,IAChF,WAAW,KAAK,OAAO;AACrB,iBAAW,KAAK,SAAU,SAAQ,IAAI,CAAC;AAAA,IACzC,OAAO;AACL,UAAI,SAAS,WAAW,GAAG;AACzB,gBAAQ,IAAI,KAAK,aAAG,gCAAgC,eAAK,EAAE;AAAA,MAC7D,OAAO;AACL,gBAAQ,IAAI;AAAA,QAAO,mBAAQ,qBAAqB,CAAC,KAAK,aAAG,IAAI,SAAS,MAAM,IAAI,eAAK;AAAA,CAAI;AACzF,mBAAW,KAAK,SAAU,SAAQ,IAAI,KAAK,gBAAM,GAAG,cAAI,GAAG,CAAC,GAAG,eAAK,EAAE;AACtE,gBAAQ,IAAI;AAAA,MACd;AAAA,IACF;AACA,OAAG,MAAM;AAAA,EACX,CAAC;AACL;",
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { dim, reset, violet, bold, section } from '../ui';\n\nexport function register(program: Command): void {\n program\n .command('affected [files...]')\n .description('Find test files affected by changed source files')\n .option('--stdin', 'Read file list from stdin (one per line)')\n .option('-d, --depth <n>', 'Max dependency traversal depth', '5')\n .option('-f, --filter <glob>', 'Custom glob to identify test files')\n .option('-j, --json', 'Output as JSON')\n .option('-q, --quiet', 'Output file paths only')\n .option('-p, --path <path>', 'Project path')\n .action(async (files: string[], opts: {\n stdin?: boolean; depth: string; filter?: string;\n json?: boolean; quiet?: boolean; path?: string;\n }) => {\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n const target = path.resolve(opts.path ?? process.cwd());\n const cg = await KiroGraph.open(target);\n\n let changedFiles = [...files];\n\n if (opts.stdin) {\n const lines = fs.readFileSync('/dev/stdin', 'utf8').split('\\n').map((l: string) => l.trim()).filter(Boolean);\n changedFiles.push(...lines);\n }\n\n if (changedFiles.length === 0) {\n console.error('No files provided. Pass files as arguments or use --stdin.');\n cg.close(); process.exit(1);\n }\n\n const affected = cg.getAffectedTests(changedFiles, {\n depth: parseInt(opts.depth),\n testPattern: opts.filter,\n });\n\n // Data file awareness: if a changed file is a data file referenced by test files,\n // include those test files in the affected list.\n const affectedSet = new Set(affected);\n try {\n const { loadConfig } = await Promise.resolve().then(() => require('../../config.js'));\n const config = await loadConfig(target);\n if (config.enableData) {\n const db = cg.getDatabase();\n db.applyDataSchema();\n const rawDb = db.getRawDb();\n\n // Check if data_code_refs table exists\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='data_code_refs'\");\n if (tableExists) {\n for (const file of changedFiles) {\n const rel = file.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n // Check if this file is a data file\n const dataset = rawDb.get('SELECT id FROM data_datasets WHERE file_path = ?', [rel]);\n if (dataset) {\n // Find code files that reference this dataset\n const refs = rawDb.all(\n 'SELECT qualified_name FROM data_code_refs WHERE dataset_id = ?',\n [dataset.id],\n ) as Array<{ qualified_name: string }>;\n\n for (const ref of refs) {\n // qualified_name might be a file path or a symbol \u2014 check if it's a test file\n const picomatch = require('picomatch');\n const isTest = picomatch(\n opts.filter ?? '{**/*.spec.*,**/*.test.*,**/*_test.*,**/*Test.*,**/*Spec.*,**/*.t.sol,**/*.bats,**/e2e/**,**/test/**,**/tests/**,**/spec/**,**/__tests__/**,**/src/test/**}'\n );\n // Look up the file path for this qualified name from the nodes table\n const node = rawDb.get('SELECT file_path FROM nodes WHERE qualified_name = ?', [ref.qualified_name]);\n if (node && isTest(node.file_path)) {\n affectedSet.add(node.file_path);\n }\n }\n }\n }\n }\n }\n } catch { /* data awareness is non-critical */ }\n\n const finalAffected = [...affectedSet].sort();\n\n if (opts.json) {\n console.log(JSON.stringify({ changedFiles, affectedTests: finalAffected }, null, 2));\n } else if (opts.quiet) {\n for (const f of finalAffected) console.log(f);\n } else {\n if (finalAffected.length === 0) {\n console.log(` ${dim}No affected test files found.${reset}`);\n } else {\n console.log(`\\n ${section('Affected test files')} ${dim}(${finalAffected.length})${reset}\\n`);\n for (const f of finalAffected) console.log(` ${violet}${bold}${f}${reset}`);\n console.log();\n }\n }\n cg.close();\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var attack_surface_exports = {};
30
+ __export(attack_surface_exports, {
31
+ register: () => register
32
+ });
33
+ module.exports = __toCommonJS(attack_surface_exports);
34
+ var path = __toESM(require("path"));
35
+ var import_config = require("../../config");
36
+ var import_ui = require("../ui");
37
+ const red = "\x1B[31m";
38
+ const yellow = "\x1B[33m";
39
+ function register(program) {
40
+ program.command("attack-surface [projectPath]").description("Map HTTP routes to reachable vulnerable dependencies").option("--limit <n>", "Max routes to show (default: 20)", "20").option("--public-only", "Show only public/unauthenticated routes").option("--format <fmt>", "Output format: text, json (default: text)", "text").action(async (projectPath, opts) => {
41
+ const target = path.resolve(projectPath ?? process.cwd());
42
+ const config = await (0, import_config.loadConfig)(target);
43
+ if (!config.enableSecurity) {
44
+ console.error(`
45
+ ${yellow}\u26A0 Security analysis is disabled.${import_ui.reset}`);
46
+ console.error(` ${import_ui.dim}Enable it in .kirograph/config.json:${import_ui.reset} ${import_ui.violet}${import_ui.bold}"enableSecurity": true${import_ui.reset}`);
47
+ console.error(` ${import_ui.dim}Then re-run:${import_ui.reset} ${import_ui.violet}${import_ui.bold}kirograph index${import_ui.reset}
48
+ `);
49
+ process.exit(1);
50
+ }
51
+ const limit = parseInt(opts.limit, 10);
52
+ if (isNaN(limit) || limit < 1) {
53
+ console.error(` \u2716 Invalid --limit value: ${opts.limit}. Must be a positive integer.`);
54
+ process.exit(1);
55
+ }
56
+ const validFormats = ["text", "json"];
57
+ if (!validFormats.includes(opts.format)) {
58
+ console.error(` \u2716 Invalid --format value: ${opts.format}. Use: text, json`);
59
+ process.exit(1);
60
+ }
61
+ const KiroGraph = (await Promise.resolve().then(() => require("../../index.js"))).default;
62
+ if (!KiroGraph.isInitialized(target)) {
63
+ console.error(" \u2716 KiroGraph not initialized. Run: kirograph init");
64
+ process.exit(1);
65
+ }
66
+ const cg = await KiroGraph.open(target);
67
+ const db = cg.getDatabase();
68
+ db.applySecuritySchema();
69
+ const { AttackSurfaceAnalyzer } = await Promise.resolve().then(() => require("../../security/attack-surface.js"));
70
+ const analyzer = new AttackSurfaceAnalyzer(db);
71
+ const result = await analyzer.analyze();
72
+ cg.close();
73
+ let routes = opts.publicOnly ? result.allRoutes.filter((r) => r.exposureLevel === "public") : result.allRoutes;
74
+ const limited = routes.slice(0, limit);
75
+ if (opts.format === "json") {
76
+ console.log(JSON.stringify(
77
+ {
78
+ totalRoutes: result.totalRoutes,
79
+ publicRoutes: result.publicRoutes,
80
+ authenticatedRoutes: result.authenticatedRoutes,
81
+ routesWithVulns: result.routesWithVulns,
82
+ criticalPaths: result.criticalPaths,
83
+ routes: limited
84
+ },
85
+ null,
86
+ 2
87
+ ));
88
+ return;
89
+ }
90
+ const totalLabel = result.totalRoutes === 1 ? "route" : "routes";
91
+ console.log(
92
+ `
93
+ ${(0, import_ui.section)("Attack Surface")} ${import_ui.dim}(${result.totalRoutes} ${totalLabel} total: ${result.publicRoutes} public, ${result.authenticatedRoutes} authenticated)${import_ui.reset}
94
+ `
95
+ );
96
+ if (result.criticalPaths.length === 0) {
97
+ console.log(` ${import_ui.dim}No routes reaching vulnerable dependencies found.${import_ui.reset}
98
+ `);
99
+ return;
100
+ }
101
+ console.log(` ${import_ui.violet}${import_ui.bold}\u25CF Critical paths${import_ui.reset} ${import_ui.dim}(routes reaching affected vulnerabilities)${import_ui.reset}
102
+ `);
103
+ const criticalToShow = result.criticalPaths.slice(0, limit);
104
+ for (const entry of criticalToShow) {
105
+ printRouteEntry(entry);
106
+ }
107
+ if (!opts.publicOnly) {
108
+ const cleanCount = result.totalRoutes - result.routesWithVulns;
109
+ if (cleanCount > 0) {
110
+ console.log(` ${import_ui.dim}+ ${cleanCount} clean route${cleanCount === 1 ? "" : "s"} (no reachable vulnerabilities)${import_ui.reset}
111
+ `);
112
+ }
113
+ }
114
+ });
115
+ }
116
+ function printRouteEntry(entry) {
117
+ const isPublicVuln = entry.exposureLevel === "public" && entry.vulnerableDeps.length > 0;
118
+ const isAuthVuln = (entry.exposureLevel === "authenticated" || entry.exposureLevel === "internal") && entry.vulnerableDeps.length > 0;
119
+ const routeColor = isPublicVuln ? red : isAuthVuln ? yellow : import_ui.dim;
120
+ const riskLabel = entry.riskScore > 0 ? `${entry.riskScore.toFixed(1)}` : "?";
121
+ const exposureBadge = (() => {
122
+ switch (entry.exposureLevel) {
123
+ case "public":
124
+ return `${red}public${import_ui.reset} `;
125
+ case "authenticated":
126
+ return `${yellow}authenticated${import_ui.reset}`;
127
+ case "internal":
128
+ return `${import_ui.dim}internal${import_ui.reset} `;
129
+ default:
130
+ return `${import_ui.dim}unknown${import_ui.reset} `;
131
+ }
132
+ })();
133
+ const topVuln = entry.vulnerableDeps.reduce(
134
+ (best, v) => {
135
+ if (!best) return v;
136
+ if ((v.riskScore ?? 0) > (best.riskScore ?? 0)) return v;
137
+ return best;
138
+ },
139
+ null
140
+ );
141
+ let vulnSuffix = "";
142
+ if (topVuln) {
143
+ const hopWord = topVuln.hopCount === 1 ? "1 hop" : `${topVuln.hopCount} hops`;
144
+ vulnSuffix = ` ${import_ui.dim}\u2192${import_ui.reset} ${import_ui.violet}${topVuln.packageName}${import_ui.reset} ${import_ui.dim}${topVuln.cveId}${import_ui.reset} ${import_ui.dim}(${hopWord})${import_ui.reset}`;
145
+ if (entry.vulnerableDeps.length > 1) {
146
+ vulnSuffix += ` ${import_ui.dim}+${entry.vulnerableDeps.length - 1} more${import_ui.reset}`;
147
+ }
148
+ }
149
+ console.log(
150
+ ` ${routeColor}[${riskLabel}]${import_ui.reset} ${import_ui.bold}${entry.route.padEnd(30)}${import_ui.reset} ${exposureBadge}${vulnSuffix}`
151
+ );
152
+ }
153
+ // Annotate the CommonJS export names for ESM import in node:
154
+ 0 && (module.exports = {
155
+ register
156
+ });
157
+ //# sourceMappingURL=attack-surface.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/bin/commands/attack-surface.ts"],
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport { loadConfig } from '../../config';\nimport { dim, reset, violet, bold, section } from '../ui';\nimport type { AttackSurfaceEntry } from '../../security/attack-surface';\n\nconst red = '\\x1b[31m';\nconst yellow = '\\x1b[33m';\n\nexport function register(program: Command): void {\n program\n .command('attack-surface [projectPath]')\n .description('Map HTTP routes to reachable vulnerable dependencies')\n .option('--limit <n>', 'Max routes to show (default: 20)', '20')\n .option('--public-only', 'Show only public/unauthenticated routes')\n .option('--format <fmt>', 'Output format: text, json (default: text)', 'text')\n .action(async (\n projectPath: string | undefined,\n opts: { limit: string; publicOnly?: boolean; format: string },\n ) => {\n const target = path.resolve(projectPath ?? process.cwd());\n const config = await loadConfig(target);\n\n if (!config.enableSecurity) {\n console.error(`\\n ${yellow}\u26A0 Security analysis is disabled.${reset}`);\n console.error(` ${dim}Enable it in .kirograph/config.json:${reset} ${violet}${bold}\"enableSecurity\": true${reset}`);\n console.error(` ${dim}Then re-run:${reset} ${violet}${bold}kirograph index${reset}\\n`);\n process.exit(1);\n }\n\n const limit = parseInt(opts.limit, 10);\n if (isNaN(limit) || limit < 1) {\n console.error(` \u2716 Invalid --limit value: ${opts.limit}. Must be a positive integer.`);\n process.exit(1);\n }\n\n const validFormats = ['text', 'json'];\n if (!validFormats.includes(opts.format)) {\n console.error(` \u2716 Invalid --format value: ${opts.format}. Use: text, json`);\n process.exit(1);\n }\n\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n if (!KiroGraph.isInitialized(target)) {\n console.error(' \u2716 KiroGraph not initialized. Run: kirograph init');\n process.exit(1);\n }\n\n const cg = await KiroGraph.open(target);\n const db = cg.getDatabase();\n db.applySecuritySchema();\n\n const { AttackSurfaceAnalyzer } = await Promise.resolve().then(() => require('../../security/attack-surface.js'));\n const analyzer = new AttackSurfaceAnalyzer(db);\n const result = await analyzer.analyze();\n\n cg.close();\n\n // Apply --public-only filter\n let routes = opts.publicOnly\n ? result.allRoutes.filter(r => r.exposureLevel === 'public')\n : result.allRoutes;\n\n // Apply limit\n const limited = routes.slice(0, limit);\n\n // \u2500\u2500 JSON output \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (opts.format === 'json') {\n console.log(JSON.stringify(\n {\n totalRoutes: result.totalRoutes,\n publicRoutes: result.publicRoutes,\n authenticatedRoutes: result.authenticatedRoutes,\n routesWithVulns: result.routesWithVulns,\n criticalPaths: result.criticalPaths,\n routes: limited,\n },\n null,\n 2,\n ));\n return;\n }\n\n // \u2500\u2500 Text output \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const totalLabel = result.totalRoutes === 1 ? 'route' : 'routes';\n console.log(\n `\\n ${section('Attack Surface')} ` +\n `${dim}(${result.totalRoutes} ${totalLabel} total: ${result.publicRoutes} public, ${result.authenticatedRoutes} authenticated)${reset}\\n`,\n );\n\n if (result.criticalPaths.length === 0) {\n console.log(` ${dim}No routes reaching vulnerable dependencies found.${reset}\\n`);\n return;\n }\n\n // Critical paths section\n console.log(` ${violet}${bold}\u25CF Critical paths${reset} ${dim}(routes reaching affected vulnerabilities)${reset}\\n`);\n\n const criticalToShow = result.criticalPaths.slice(0, limit);\n\n for (const entry of criticalToShow) {\n printRouteEntry(entry);\n }\n\n // If public-only was not set, also show clean routes summary\n if (!opts.publicOnly) {\n const cleanCount = result.totalRoutes - result.routesWithVulns;\n if (cleanCount > 0) {\n console.log(` ${dim}+ ${cleanCount} clean route${cleanCount === 1 ? '' : 's'} (no reachable vulnerabilities)${reset}\\n`);\n }\n }\n });\n}\n\nfunction printRouteEntry(entry: AttackSurfaceEntry): void {\n const isPublicVuln = entry.exposureLevel === 'public' && entry.vulnerableDeps.length > 0;\n const isAuthVuln = (entry.exposureLevel === 'authenticated' || entry.exposureLevel === 'internal') && entry.vulnerableDeps.length > 0;\n\n const routeColor = isPublicVuln ? red : isAuthVuln ? yellow : dim;\n const riskLabel = entry.riskScore > 0 ? `${entry.riskScore.toFixed(1)}` : '?';\n\n // Exposure badge\n const exposureBadge = (() => {\n switch (entry.exposureLevel) {\n case 'public': return `${red}public${reset} `;\n case 'authenticated': return `${yellow}authenticated${reset}`;\n case 'internal': return `${dim}internal${reset} `;\n default: return `${dim}unknown${reset} `;\n }\n })();\n\n // Pick the top vuln by riskScore to show inline\n const topVuln = entry.vulnerableDeps.reduce<AttackSurfaceEntry['vulnerableDeps'][0] | null>(\n (best, v) => {\n if (!best) return v;\n if ((v.riskScore ?? 0) > (best.riskScore ?? 0)) return v;\n return best;\n },\n null,\n );\n\n let vulnSuffix = '';\n if (topVuln) {\n const hopWord = topVuln.hopCount === 1 ? '1 hop' : `${topVuln.hopCount} hops`;\n vulnSuffix = ` ${dim}\u2192${reset} ${violet}${topVuln.packageName}${reset} ${dim}${topVuln.cveId}${reset} ${dim}(${hopWord})${reset}`;\n if (entry.vulnerableDeps.length > 1) {\n vulnSuffix += ` ${dim}+${entry.vulnerableDeps.length - 1} more${reset}`;\n }\n }\n\n console.log(\n ` ${routeColor}[${riskLabel}]${reset} ${bold}${entry.route.padEnd(30)}${reset} ${exposureBadge}${vulnSuffix}`,\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }