spectra-cli 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (422) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/go-adapter.d.ts.map +1 -1
  3. package/dist/adapters/go-adapter.js +2 -0
  4. package/dist/adapters/go-adapter.js.map +1 -1
  5. package/dist/adapters/index.d.ts +1 -1
  6. package/dist/adapters/index.d.ts.map +1 -1
  7. package/dist/adapters/java-adapter.d.ts.map +1 -1
  8. package/dist/adapters/java-adapter.js +2 -0
  9. package/dist/adapters/java-adapter.js.map +1 -1
  10. package/dist/adapters/language-adapter.d.ts +47 -9
  11. package/dist/adapters/language-adapter.d.ts.map +1 -1
  12. package/dist/adapters/python-adapter.d.ts +34 -6
  13. package/dist/adapters/python-adapter.d.ts.map +1 -1
  14. package/dist/adapters/python-adapter.js +157 -59
  15. package/dist/adapters/python-adapter.js.map +1 -1
  16. package/dist/adapters/ts-js-adapter.d.ts +13 -5
  17. package/dist/adapters/ts-js-adapter.d.ts.map +1 -1
  18. package/dist/adapters/ts-js-adapter.js +55 -14
  19. package/dist/adapters/ts-js-adapter.js.map +1 -1
  20. package/dist/batch/batch-orchestrator.d.ts +30 -4
  21. package/dist/batch/batch-orchestrator.d.ts.map +1 -1
  22. package/dist/batch/batch-orchestrator.js +284 -7
  23. package/dist/batch/batch-orchestrator.js.map +1 -1
  24. package/dist/batch/delta-regenerator.d.ts +2 -2
  25. package/dist/batch/delta-regenerator.d.ts.map +1 -1
  26. package/dist/batch/delta-regenerator.js.map +1 -1
  27. package/dist/batch/module-grouper.d.ts +2 -2
  28. package/dist/batch/module-grouper.d.ts.map +1 -1
  29. package/dist/batch/module-grouper.js +1 -1
  30. package/dist/batch/module-grouper.js.map +1 -1
  31. package/dist/cli/commands/graph.js +1 -1
  32. package/dist/cli/commands/graph.js.map +1 -1
  33. package/dist/cli/commands/index.d.ts +8 -0
  34. package/dist/cli/commands/index.d.ts.map +1 -0
  35. package/dist/cli/commands/index.js +274 -0
  36. package/dist/cli/commands/index.js.map +1 -0
  37. package/dist/cli/commands/query.d.ts.map +1 -1
  38. package/dist/cli/commands/query.js +3 -1
  39. package/dist/cli/commands/query.js.map +1 -1
  40. package/dist/cli/index.js +9 -9
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/cli/utils/parse-args.d.ts +13 -1
  43. package/dist/cli/utils/parse-args.d.ts.map +1 -1
  44. package/dist/cli/utils/parse-args.js +79 -2
  45. package/dist/cli/utils/parse-args.js.map +1 -1
  46. package/dist/core/ast-analyzer.d.ts.map +1 -1
  47. package/dist/core/ast-analyzer.js +79 -5
  48. package/dist/core/ast-analyzer.js.map +1 -1
  49. package/dist/core/import-resolver.d.ts +90 -0
  50. package/dist/core/import-resolver.d.ts.map +1 -0
  51. package/dist/core/import-resolver.js +273 -0
  52. package/dist/core/import-resolver.js.map +1 -0
  53. package/dist/core/query-mappers/base-mapper.d.ts +13 -0
  54. package/dist/core/query-mappers/base-mapper.d.ts.map +1 -1
  55. package/dist/core/query-mappers/go-mapper.d.ts +68 -0
  56. package/dist/core/query-mappers/go-mapper.d.ts.map +1 -1
  57. package/dist/core/query-mappers/go-mapper.js +421 -0
  58. package/dist/core/query-mappers/go-mapper.js.map +1 -1
  59. package/dist/core/query-mappers/java-mapper.d.ts +196 -0
  60. package/dist/core/query-mappers/java-mapper.d.ts.map +1 -1
  61. package/dist/core/query-mappers/java-mapper.js +600 -0
  62. package/dist/core/query-mappers/java-mapper.js.map +1 -1
  63. package/dist/core/query-mappers/python-mapper.d.ts +55 -0
  64. package/dist/core/query-mappers/python-mapper.d.ts.map +1 -1
  65. package/dist/core/query-mappers/python-mapper.js +273 -0
  66. package/dist/core/query-mappers/python-mapper.js.map +1 -1
  67. package/dist/core/query-mappers/typescript-mapper.d.ts +102 -0
  68. package/dist/core/query-mappers/typescript-mapper.d.ts.map +1 -1
  69. package/dist/core/query-mappers/typescript-mapper.js +470 -0
  70. package/dist/core/query-mappers/typescript-mapper.js.map +1 -1
  71. package/dist/core/single-spec-orchestrator.d.ts.map +1 -1
  72. package/dist/core/single-spec-orchestrator.js +146 -9
  73. package/dist/core/single-spec-orchestrator.js.map +1 -1
  74. package/dist/core/tree-sitter-analyzer.d.ts +6 -0
  75. package/dist/core/tree-sitter-analyzer.d.ts.map +1 -1
  76. package/dist/core/tree-sitter-analyzer.js +33 -1
  77. package/dist/core/tree-sitter-analyzer.js.map +1 -1
  78. package/dist/core/tree-sitter-fallback.d.ts +7 -4
  79. package/dist/core/tree-sitter-fallback.d.ts.map +1 -1
  80. package/dist/core/tree-sitter-fallback.js +157 -12
  81. package/dist/core/tree-sitter-fallback.js.map +1 -1
  82. package/dist/extraction/extraction-types.d.ts +25 -25
  83. package/dist/generator/index-generator.d.ts +3 -3
  84. package/dist/generator/index-generator.d.ts.map +1 -1
  85. package/dist/generator/index-generator.js +1 -1
  86. package/dist/generator/index-generator.js.map +1 -1
  87. package/dist/graph/directory-graph.d.ts +14 -4
  88. package/dist/graph/directory-graph.d.ts.map +1 -1
  89. package/dist/graph/directory-graph.js +71 -128
  90. package/dist/graph/directory-graph.js.map +1 -1
  91. package/dist/graph/mermaid-renderer.d.ts +8 -5
  92. package/dist/graph/mermaid-renderer.d.ts.map +1 -1
  93. package/dist/graph/mermaid-renderer.js +3 -3
  94. package/dist/graph/mermaid-renderer.js.map +1 -1
  95. package/dist/graph/topological-sort.d.ts +13 -6
  96. package/dist/graph/topological-sort.d.ts.map +1 -1
  97. package/dist/graph/topological-sort.js +2 -2
  98. package/dist/graph/topological-sort.js.map +1 -1
  99. package/dist/knowledge-graph/call-resolver.d.ts +64 -0
  100. package/dist/knowledge-graph/call-resolver.d.ts.map +1 -0
  101. package/dist/knowledge-graph/call-resolver.js +323 -0
  102. package/dist/knowledge-graph/call-resolver.js.map +1 -0
  103. package/dist/knowledge-graph/import-resolver.d.ts +114 -0
  104. package/dist/knowledge-graph/import-resolver.d.ts.map +1 -0
  105. package/dist/knowledge-graph/import-resolver.js +537 -0
  106. package/dist/knowledge-graph/import-resolver.js.map +1 -0
  107. package/dist/knowledge-graph/incremental.d.ts +110 -0
  108. package/dist/knowledge-graph/incremental.d.ts.map +1 -0
  109. package/dist/knowledge-graph/incremental.js +410 -0
  110. package/dist/knowledge-graph/incremental.js.map +1 -0
  111. package/dist/knowledge-graph/index.d.ts +74 -0
  112. package/dist/knowledge-graph/index.d.ts.map +1 -0
  113. package/dist/knowledge-graph/index.js +156 -0
  114. package/dist/knowledge-graph/index.js.map +1 -0
  115. package/dist/knowledge-graph/module-derivation.d.ts +238 -0
  116. package/dist/knowledge-graph/module-derivation.d.ts.map +1 -0
  117. package/dist/knowledge-graph/module-derivation.js +418 -0
  118. package/dist/knowledge-graph/module-derivation.js.map +1 -0
  119. package/dist/knowledge-graph/persistence.d.ts +270 -0
  120. package/dist/knowledge-graph/persistence.d.ts.map +1 -0
  121. package/dist/knowledge-graph/persistence.js +226 -0
  122. package/dist/knowledge-graph/persistence.js.map +1 -0
  123. package/dist/knowledge-graph/query-helpers.d.ts +164 -0
  124. package/dist/knowledge-graph/query-helpers.d.ts.map +1 -0
  125. package/dist/knowledge-graph/query-helpers.js +394 -0
  126. package/dist/knowledge-graph/query-helpers.js.map +1 -0
  127. package/dist/knowledge-graph/unified-graph.d.ts +310 -0
  128. package/dist/knowledge-graph/unified-graph.d.ts.map +1 -0
  129. package/dist/knowledge-graph/unified-graph.js +182 -0
  130. package/dist/knowledge-graph/unified-graph.js.map +1 -0
  131. package/dist/mcp/agent-context-tools.d.ts +104 -0
  132. package/dist/mcp/agent-context-tools.d.ts.map +1 -0
  133. package/dist/mcp/agent-context-tools.js +854 -0
  134. package/dist/mcp/agent-context-tools.js.map +1 -0
  135. package/dist/mcp/graph-tools.d.ts +20 -0
  136. package/dist/mcp/graph-tools.d.ts.map +1 -1
  137. package/dist/mcp/graph-tools.js +71 -11
  138. package/dist/mcp/graph-tools.js.map +1 -1
  139. package/dist/mcp/lib/response-helpers.d.ts +67 -0
  140. package/dist/mcp/lib/response-helpers.d.ts.map +1 -0
  141. package/dist/mcp/lib/response-helpers.js +103 -0
  142. package/dist/mcp/lib/response-helpers.js.map +1 -0
  143. package/dist/mcp/server.d.ts +3 -1
  144. package/dist/mcp/server.d.ts.map +1 -1
  145. package/dist/mcp/server.js +9 -10
  146. package/dist/mcp/server.js.map +1 -1
  147. package/dist/models/call-site.d.ts +68 -0
  148. package/dist/models/call-site.d.ts.map +1 -0
  149. package/dist/models/call-site.js +60 -0
  150. package/dist/models/call-site.js.map +1 -0
  151. package/dist/models/code-skeleton.d.ts +78 -6
  152. package/dist/models/code-skeleton.d.ts.map +1 -1
  153. package/dist/models/code-skeleton.js +29 -0
  154. package/dist/models/code-skeleton.js.map +1 -1
  155. package/dist/models/drift-item.d.ts +4 -4
  156. package/dist/models/module-spec.d.ts +155 -94
  157. package/dist/models/module-spec.d.ts.map +1 -1
  158. package/dist/panoramic/adr-decision-pipeline.d.ts +53 -0
  159. package/dist/panoramic/adr-decision-pipeline.d.ts.map +1 -0
  160. package/dist/panoramic/adr-decision-pipeline.js +685 -0
  161. package/dist/panoramic/adr-decision-pipeline.js.map +1 -0
  162. package/dist/panoramic/api-surface-generator.d.ts +56 -0
  163. package/dist/panoramic/api-surface-generator.d.ts.map +1 -0
  164. package/dist/panoramic/api-surface-generator.js +1671 -0
  165. package/dist/panoramic/api-surface-generator.js.map +1 -0
  166. package/dist/panoramic/architecture-ir-builder.d.ts +19 -0
  167. package/dist/panoramic/architecture-ir-builder.d.ts.map +1 -0
  168. package/dist/panoramic/architecture-ir-builder.js +561 -0
  169. package/dist/panoramic/architecture-ir-builder.js.map +1 -0
  170. package/dist/panoramic/architecture-ir-exporters.d.ts +7 -0
  171. package/dist/panoramic/architecture-ir-exporters.d.ts.map +1 -0
  172. package/dist/panoramic/architecture-ir-exporters.js +183 -0
  173. package/dist/panoramic/architecture-ir-exporters.js.map +1 -0
  174. package/dist/panoramic/architecture-ir-generator.d.ts +36 -0
  175. package/dist/panoramic/architecture-ir-generator.d.ts.map +1 -0
  176. package/dist/panoramic/architecture-ir-generator.js +51 -0
  177. package/dist/panoramic/architecture-ir-generator.js.map +1 -0
  178. package/dist/panoramic/architecture-ir-mermaid-adapter.d.ts +6 -0
  179. package/dist/panoramic/architecture-ir-mermaid-adapter.d.ts.map +1 -0
  180. package/dist/panoramic/architecture-ir-mermaid-adapter.js +98 -0
  181. package/dist/panoramic/architecture-ir-mermaid-adapter.js.map +1 -0
  182. package/dist/panoramic/architecture-ir-model.d.ts +87 -0
  183. package/dist/panoramic/architecture-ir-model.d.ts.map +1 -0
  184. package/dist/panoramic/architecture-ir-model.js +20 -0
  185. package/dist/panoramic/architecture-ir-model.js.map +1 -0
  186. package/dist/panoramic/architecture-narrative.d.ts +68 -0
  187. package/dist/panoramic/architecture-narrative.d.ts.map +1 -0
  188. package/dist/panoramic/architecture-narrative.js +401 -0
  189. package/dist/panoramic/architecture-narrative.js.map +1 -0
  190. package/dist/panoramic/architecture-overview-generator.d.ts +31 -0
  191. package/dist/panoramic/architecture-overview-generator.d.ts.map +1 -0
  192. package/dist/panoramic/architecture-overview-generator.js +454 -0
  193. package/dist/panoramic/architecture-overview-generator.js.map +1 -0
  194. package/dist/panoramic/architecture-overview-model.d.ts +77 -0
  195. package/dist/panoramic/architecture-overview-model.d.ts.map +1 -0
  196. package/dist/panoramic/architecture-overview-model.js +31 -0
  197. package/dist/panoramic/architecture-overview-model.js.map +1 -0
  198. package/dist/panoramic/batch-project-docs.d.ts.map +1 -1
  199. package/dist/panoramic/batch-project-docs.js +4 -2
  200. package/dist/panoramic/batch-project-docs.js.map +1 -1
  201. package/dist/panoramic/builders/component-view-builder.d.ts +25 -1
  202. package/dist/panoramic/builders/component-view-builder.d.ts.map +1 -1
  203. package/dist/panoramic/builders/component-view-builder.js +83 -3
  204. package/dist/panoramic/builders/component-view-builder.js.map +1 -1
  205. package/dist/panoramic/builders/doc-graph-builder.d.ts +2 -2
  206. package/dist/panoramic/builders/doc-graph-builder.d.ts.map +1 -1
  207. package/dist/panoramic/builders/doc-graph-builder.js.map +1 -1
  208. package/dist/panoramic/component-view-builder.d.ts +17 -0
  209. package/dist/panoramic/component-view-builder.d.ts.map +1 -0
  210. package/dist/panoramic/component-view-builder.js +652 -0
  211. package/dist/panoramic/component-view-builder.js.map +1 -0
  212. package/dist/panoramic/component-view-model.d.ts +127 -0
  213. package/dist/panoramic/component-view-model.d.ts.map +1 -0
  214. package/dist/panoramic/component-view-model.js +65 -0
  215. package/dist/panoramic/component-view-model.js.map +1 -0
  216. package/dist/panoramic/config-reference-generator.d.ts +78 -0
  217. package/dist/panoramic/config-reference-generator.d.ts.map +1 -0
  218. package/dist/panoramic/config-reference-generator.js +199 -0
  219. package/dist/panoramic/config-reference-generator.js.map +1 -0
  220. package/dist/panoramic/coverage-auditor.d.ts +95 -0
  221. package/dist/panoramic/coverage-auditor.d.ts.map +1 -0
  222. package/dist/panoramic/coverage-auditor.js +290 -0
  223. package/dist/panoramic/coverage-auditor.js.map +1 -0
  224. package/dist/panoramic/cross-package-analyzer.d.ts +112 -0
  225. package/dist/panoramic/cross-package-analyzer.d.ts.map +1 -0
  226. package/dist/panoramic/cross-package-analyzer.js +258 -0
  227. package/dist/panoramic/cross-package-analyzer.js.map +1 -0
  228. package/dist/panoramic/data-model-generator.d.ts +528 -0
  229. package/dist/panoramic/data-model-generator.d.ts.map +1 -0
  230. package/dist/panoramic/data-model-generator.js +647 -0
  231. package/dist/panoramic/data-model-generator.js.map +1 -0
  232. package/dist/panoramic/doc-graph-builder.d.ts +80 -0
  233. package/dist/panoramic/doc-graph-builder.d.ts.map +1 -0
  234. package/dist/panoramic/doc-graph-builder.js +352 -0
  235. package/dist/panoramic/doc-graph-builder.js.map +1 -0
  236. package/dist/panoramic/docs-bundle-manifest-reader.d.ts +26 -0
  237. package/dist/panoramic/docs-bundle-manifest-reader.d.ts.map +1 -0
  238. package/dist/panoramic/docs-bundle-manifest-reader.js +106 -0
  239. package/dist/panoramic/docs-bundle-manifest-reader.js.map +1 -0
  240. package/dist/panoramic/docs-bundle-orchestrator.d.ts +14 -0
  241. package/dist/panoramic/docs-bundle-orchestrator.d.ts.map +1 -0
  242. package/dist/panoramic/docs-bundle-orchestrator.js +538 -0
  243. package/dist/panoramic/docs-bundle-orchestrator.js.map +1 -0
  244. package/dist/panoramic/docs-bundle-profiles.d.ts +4 -0
  245. package/dist/panoramic/docs-bundle-profiles.d.ts.map +1 -0
  246. package/dist/panoramic/docs-bundle-profiles.js +82 -0
  247. package/dist/panoramic/docs-bundle-profiles.js.map +1 -0
  248. package/dist/panoramic/docs-bundle-types.d.ts +94 -0
  249. package/dist/panoramic/docs-bundle-types.d.ts.map +1 -0
  250. package/dist/panoramic/docs-bundle-types.js +10 -0
  251. package/dist/panoramic/docs-bundle-types.js.map +1 -0
  252. package/dist/panoramic/docs-quality-evaluator.d.ts +31 -0
  253. package/dist/panoramic/docs-quality-evaluator.d.ts.map +1 -0
  254. package/dist/panoramic/docs-quality-evaluator.js +941 -0
  255. package/dist/panoramic/docs-quality-evaluator.js.map +1 -0
  256. package/dist/panoramic/docs-quality-model.d.ts +125 -0
  257. package/dist/panoramic/docs-quality-model.d.ts.map +1 -0
  258. package/dist/panoramic/docs-quality-model.js +166 -0
  259. package/dist/panoramic/docs-quality-model.js.map +1 -0
  260. package/dist/panoramic/dynamic-scenarios-builder.d.ts +18 -0
  261. package/dist/panoramic/dynamic-scenarios-builder.d.ts.map +1 -0
  262. package/dist/panoramic/dynamic-scenarios-builder.js +316 -0
  263. package/dist/panoramic/dynamic-scenarios-builder.js.map +1 -0
  264. package/dist/panoramic/event-surface-generator.d.ts +52 -0
  265. package/dist/panoramic/event-surface-generator.d.ts.map +1 -0
  266. package/dist/panoramic/event-surface-generator.js +507 -0
  267. package/dist/panoramic/event-surface-generator.js.map +1 -0
  268. package/dist/panoramic/generator-registry.d.ts +1 -1
  269. package/dist/panoramic/generator-registry.d.ts.map +1 -1
  270. package/dist/panoramic/generator-registry.js +5 -2
  271. package/dist/panoramic/generator-registry.js.map +1 -1
  272. package/dist/panoramic/generators/cross-package-analyzer.d.ts +5 -5
  273. package/dist/panoramic/generators/cross-package-analyzer.d.ts.map +1 -1
  274. package/dist/panoramic/generators/cross-package-analyzer.js +1 -1
  275. package/dist/panoramic/generators/cross-package-analyzer.js.map +1 -1
  276. package/dist/panoramic/generators/data-model-generator.d.ts +27 -27
  277. package/dist/panoramic/graph/confidence-mapper.d.ts +18 -0
  278. package/dist/panoramic/graph/confidence-mapper.d.ts.map +1 -1
  279. package/dist/panoramic/graph/confidence-mapper.js +26 -0
  280. package/dist/panoramic/graph/confidence-mapper.js.map +1 -1
  281. package/dist/panoramic/graph/graph-builder.d.ts.map +1 -1
  282. package/dist/panoramic/graph/graph-builder.js +78 -0
  283. package/dist/panoramic/graph/graph-builder.js.map +1 -1
  284. package/dist/panoramic/graph/graph-paths.d.ts +8 -0
  285. package/dist/panoramic/graph/graph-paths.d.ts.map +1 -1
  286. package/dist/panoramic/graph/graph-paths.js +10 -0
  287. package/dist/panoramic/graph/graph-paths.js.map +1 -1
  288. package/dist/panoramic/graph/graph-query.d.ts +33 -2
  289. package/dist/panoramic/graph/graph-query.d.ts.map +1 -1
  290. package/dist/panoramic/graph/graph-query.js +69 -19
  291. package/dist/panoramic/graph/graph-query.js.map +1 -1
  292. package/dist/panoramic/graph/graph-types.d.ts +32 -3
  293. package/dist/panoramic/graph/graph-types.d.ts.map +1 -1
  294. package/dist/panoramic/hyperedges/schema.d.ts +6 -6
  295. package/dist/panoramic/interface-surface-generator.d.ts +50 -0
  296. package/dist/panoramic/interface-surface-generator.d.ts.map +1 -0
  297. package/dist/panoramic/interface-surface-generator.js +388 -0
  298. package/dist/panoramic/interface-surface-generator.js.map +1 -0
  299. package/dist/panoramic/interfaces.d.ts +2 -2
  300. package/dist/panoramic/mock-readme-generator.d.ts +90 -0
  301. package/dist/panoramic/mock-readme-generator.d.ts.map +1 -0
  302. package/dist/panoramic/mock-readme-generator.js +111 -0
  303. package/dist/panoramic/mock-readme-generator.js.map +1 -0
  304. package/dist/panoramic/models/component-view-model.d.ts +1 -1
  305. package/dist/panoramic/models/component-view-model.d.ts.map +1 -1
  306. package/dist/panoramic/models/component-view-model.js.map +1 -1
  307. package/dist/panoramic/narrative-provenance-adapter.d.ts +8 -0
  308. package/dist/panoramic/narrative-provenance-adapter.d.ts.map +1 -0
  309. package/dist/panoramic/narrative-provenance-adapter.js +99 -0
  310. package/dist/panoramic/narrative-provenance-adapter.js.map +1 -0
  311. package/dist/panoramic/parser-registry.d.ts +1 -1
  312. package/dist/panoramic/parser-registry.js +1 -1
  313. package/dist/panoramic/parsers/types.d.ts +6 -6
  314. package/dist/panoramic/pattern-hints-generator.d.ts +28 -0
  315. package/dist/panoramic/pattern-hints-generator.d.ts.map +1 -0
  316. package/dist/panoramic/pattern-hints-generator.js +218 -0
  317. package/dist/panoramic/pattern-hints-generator.js.map +1 -0
  318. package/dist/panoramic/pattern-hints-model.d.ts +89 -0
  319. package/dist/panoramic/pattern-hints-model.d.ts.map +1 -0
  320. package/dist/panoramic/pattern-hints-model.js +61 -0
  321. package/dist/panoramic/pattern-hints-model.js.map +1 -0
  322. package/dist/panoramic/pattern-knowledge-base.d.ts +31 -0
  323. package/dist/panoramic/pattern-knowledge-base.d.ts.map +1 -0
  324. package/dist/panoramic/pattern-knowledge-base.js +407 -0
  325. package/dist/panoramic/pattern-knowledge-base.js.map +1 -0
  326. package/dist/panoramic/pipelines/coverage-auditor.d.ts.map +1 -1
  327. package/dist/panoramic/pipelines/coverage-auditor.js +4 -2
  328. package/dist/panoramic/pipelines/coverage-auditor.js.map +1 -1
  329. package/dist/panoramic/pipelines/docs-bundle-orchestrator.js +13 -6
  330. package/dist/panoramic/pipelines/docs-bundle-orchestrator.js.map +1 -1
  331. package/dist/panoramic/pipelines/product-ux-docs.d.ts +5 -0
  332. package/dist/panoramic/pipelines/product-ux-docs.d.ts.map +1 -1
  333. package/dist/panoramic/pipelines/product-ux-docs.js +34 -6
  334. package/dist/panoramic/pipelines/product-ux-docs.js.map +1 -1
  335. package/dist/panoramic/product-ux-docs.d.ts +104 -0
  336. package/dist/panoramic/product-ux-docs.d.ts.map +1 -0
  337. package/dist/panoramic/product-ux-docs.js +817 -0
  338. package/dist/panoramic/product-ux-docs.js.map +1 -0
  339. package/dist/panoramic/qa/__tests__/citation.test.d.ts +2 -0
  340. package/dist/panoramic/qa/__tests__/citation.test.d.ts.map +1 -0
  341. package/dist/panoramic/qa/__tests__/citation.test.js +193 -0
  342. package/dist/panoramic/qa/__tests__/citation.test.js.map +1 -0
  343. package/dist/panoramic/qa/__tests__/debt-context.test.d.ts +2 -0
  344. package/dist/panoramic/qa/__tests__/debt-context.test.d.ts.map +1 -0
  345. package/dist/panoramic/qa/__tests__/debt-context.test.js +154 -0
  346. package/dist/panoramic/qa/__tests__/debt-context.test.js.map +1 -0
  347. package/dist/panoramic/qa/__tests__/graph-retriever.test.d.ts +2 -0
  348. package/dist/panoramic/qa/__tests__/graph-retriever.test.d.ts.map +1 -0
  349. package/dist/panoramic/qa/__tests__/graph-retriever.test.js +148 -0
  350. package/dist/panoramic/qa/__tests__/graph-retriever.test.js.map +1 -0
  351. package/dist/panoramic/qa/__tests__/index.test.d.ts +2 -0
  352. package/dist/panoramic/qa/__tests__/index.test.d.ts.map +1 -0
  353. package/dist/panoramic/qa/__tests__/index.test.js +246 -0
  354. package/dist/panoramic/qa/__tests__/index.test.js.map +1 -0
  355. package/dist/panoramic/qa/__tests__/llm-caller.test.d.ts +2 -0
  356. package/dist/panoramic/qa/__tests__/llm-caller.test.d.ts.map +1 -0
  357. package/dist/panoramic/qa/__tests__/llm-caller.test.js +168 -0
  358. package/dist/panoramic/qa/__tests__/llm-caller.test.js.map +1 -0
  359. package/dist/panoramic/qa/__tests__/prompt-builder.test.d.ts +2 -0
  360. package/dist/panoramic/qa/__tests__/prompt-builder.test.d.ts.map +1 -0
  361. package/dist/panoramic/qa/__tests__/prompt-builder.test.js +150 -0
  362. package/dist/panoramic/qa/__tests__/prompt-builder.test.js.map +1 -0
  363. package/dist/panoramic/qa/__tests__/qa-integration.test.d.ts +2 -0
  364. package/dist/panoramic/qa/__tests__/qa-integration.test.d.ts.map +1 -0
  365. package/dist/panoramic/qa/__tests__/qa-integration.test.js +296 -0
  366. package/dist/panoramic/qa/__tests__/qa-integration.test.js.map +1 -0
  367. package/dist/panoramic/qa/__tests__/rag-reranker.test.d.ts +2 -0
  368. package/dist/panoramic/qa/__tests__/rag-reranker.test.d.ts.map +1 -0
  369. package/dist/panoramic/qa/__tests__/rag-reranker.test.js +136 -0
  370. package/dist/panoramic/qa/__tests__/rag-reranker.test.js.map +1 -0
  371. package/dist/panoramic/qa/index.d.ts.map +1 -1
  372. package/dist/panoramic/qa/index.js +10 -3
  373. package/dist/panoramic/qa/index.js.map +1 -1
  374. package/dist/panoramic/runtime-topology-generator.d.ts +77 -0
  375. package/dist/panoramic/runtime-topology-generator.d.ts.map +1 -0
  376. package/dist/panoramic/runtime-topology-generator.js +676 -0
  377. package/dist/panoramic/runtime-topology-generator.js.map +1 -0
  378. package/dist/panoramic/runtime-topology-model.d.ts +145 -0
  379. package/dist/panoramic/runtime-topology-model.d.ts.map +1 -0
  380. package/dist/panoramic/runtime-topology-model.js +300 -0
  381. package/dist/panoramic/runtime-topology-model.js.map +1 -0
  382. package/dist/panoramic/troubleshooting-generator.d.ts +51 -0
  383. package/dist/panoramic/troubleshooting-generator.d.ts.map +1 -0
  384. package/dist/panoramic/troubleshooting-generator.js +451 -0
  385. package/dist/panoramic/troubleshooting-generator.js.map +1 -0
  386. package/dist/panoramic/utils/text-segmenter.d.ts +15 -0
  387. package/dist/panoramic/utils/text-segmenter.d.ts.map +1 -1
  388. package/dist/panoramic/utils/text-segmenter.js +38 -0
  389. package/dist/panoramic/utils/text-segmenter.js.map +1 -1
  390. package/dist/panoramic/workspace-index-generator.d.ts +148 -0
  391. package/dist/panoramic/workspace-index-generator.d.ts.map +1 -0
  392. package/dist/panoramic/workspace-index-generator.js +497 -0
  393. package/dist/panoramic/workspace-index-generator.js.map +1 -0
  394. package/dist/runtime-bootstrap.d.ts +9 -0
  395. package/dist/runtime-bootstrap.d.ts.map +1 -0
  396. package/dist/runtime-bootstrap.js +33 -0
  397. package/dist/runtime-bootstrap.js.map +1 -0
  398. package/dist/utils/file-scanner.js +1 -1
  399. package/dist/utils/file-scanner.js.map +1 -1
  400. package/package.json +12 -2
  401. package/plugins/spec-driver/.claude-plugin/plugin.json +1 -1
  402. package/plugins/spec-driver/README.md +18 -1
  403. package/plugins/spec-driver/agents/implement.md +20 -1
  404. package/plugins/spec-driver/agents/plan.md +20 -1
  405. package/plugins/spec-driver/agents/quality-review.md +20 -1
  406. package/plugins/spec-driver/agents/spec-review.md +20 -1
  407. package/plugins/spec-driver/agents/verify.md +20 -1
  408. package/plugins/spec-driver/docs/customization.md +134 -0
  409. package/plugins/spec-driver/docs/spectra-mcp-integration.md +165 -0
  410. package/plugins/spec-driver/lib/preference-rules.mjs +96 -0
  411. package/plugins/spec-driver/scripts/postinstall.sh +1 -1
  412. package/plugins/spec-driver/scripts/sync-preference-rules.mjs +148 -0
  413. package/plugins/spec-driver/skills/spec-driver-feature/SKILL.md +10 -0
  414. package/plugins/spec-driver/skills/spec-driver-fix/SKILL.md +10 -0
  415. package/plugins/spec-driver/skills/spec-driver-implement/SKILL.md +10 -0
  416. package/plugins/spec-driver/skills/spec-driver-refactor/SKILL.md +10 -0
  417. package/plugins/spec-driver/skills/spec-driver-story/SKILL.md +10 -0
  418. package/plugins/spec-driver/templates/preference-rules.md +39 -0
  419. package/plugins/spectra/.claude-plugin/plugin.json +1 -1
  420. package/plugins/spectra/README.md +48 -1
  421. package/plugins/spectra/hooks/post-commit.sh +40 -0
  422. package/templates/product-overview.hbs +1 -1
@@ -0,0 +1,676 @@
1
+ /**
2
+ * RuntimeTopologyGenerator
3
+ *
4
+ * 统一抽取 Compose / Dockerfile / .env / 配置提示,产出共享 RuntimeTopology。
5
+ * Feature 043 负责生产它;Feature 045 将直接消费 topology 字段。
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import { DockerfileParser } from './parsers/dockerfile-parser.js';
10
+ import { EnvConfigParser } from './parsers/env-config-parser.js';
11
+ import { TomlConfigParser } from './parsers/toml-config-parser.js';
12
+ import { YamlConfigParser, parseYamlDocument } from './parsers/yaml-config-parser.js';
13
+ import { loadTemplate } from './utils/template-loader.js';
14
+ import { buildSyntheticImageName, collectRuntimeConfigHints, extractRuntimeBuildStages, mergeEnvironmentVariables, normalizeCommandValue, summarizeRuntimeTopology, } from './runtime-topology-model.js';
15
+ const COMPOSE_FILE_RE = /^(?:docker-compose|compose)(?:\.[^/]+)*\.ya?ml$/i;
16
+ const ROOT_DOCKERFILE_RE = /^Dockerfile(?:\.[^/]+)*$/;
17
+ const ENV_FILE_RE = /^\.env(?:\.[^/]+)*$/;
18
+ const YAML_CONFIG_RE = /\.ya?ml$/i;
19
+ const TOML_CONFIG_RE = /\.toml$/i;
20
+ /**
21
+ * 运行时拓扑生成器。
22
+ */
23
+ export class RuntimeTopologyGenerator {
24
+ id = 'runtime-topology';
25
+ name = '运行时拓扑生成器';
26
+ description = '联合解析 Compose、Dockerfile、.env 和配置提示,生成统一运行时拓扑模型';
27
+ isApplicable(context) {
28
+ return (discoverComposeFiles(context.projectRoot, context.configFiles).length > 0 ||
29
+ discoverRootDockerfiles(context.projectRoot, context.configFiles).length > 0);
30
+ }
31
+ async extract(context) {
32
+ const projectName = detectProjectName(context.projectRoot);
33
+ const warnings = new Set();
34
+ const composeFiles = this.extractComposeFiles(context.projectRoot, context.configFiles, warnings);
35
+ const dockerfiles = await this.extractDockerfiles(context.projectRoot, context.configFiles, composeFiles, warnings);
36
+ const envFiles = await this.extractEnvFiles(context.projectRoot, composeFiles, warnings);
37
+ const configHints = await this.extractRuntimeConfigHints(context.projectRoot, composeFiles, dockerfiles, envFiles);
38
+ return {
39
+ projectName,
40
+ composeFiles,
41
+ dockerfiles,
42
+ envFiles,
43
+ configHints,
44
+ warnings: [...warnings].sort(),
45
+ };
46
+ }
47
+ async generate(input, _options) {
48
+ const envMap = new Map(input.envFiles.map((envFile) => [envFile.filePath, envFile.entries]));
49
+ const stagesByDockerfile = new Map();
50
+ for (const dockerfile of input.dockerfiles) {
51
+ stagesByDockerfile.set(dockerfile.relativePath, extractRuntimeBuildStages(dockerfile.parsed, dockerfile.relativePath, dockerfile.runtimeTargets));
52
+ }
53
+ const services = [];
54
+ const containers = [];
55
+ const imagesByKey = new Map();
56
+ for (const composeFile of input.composeFiles) {
57
+ for (const service of composeFile.services) {
58
+ const envFileEntries = service.envFiles.flatMap((envFile) => envMap.get(envFile) ?? []);
59
+ const environment = mergeEnvironmentVariables(envFileEntries, service.environment);
60
+ const stageNames = service.build?.dockerfilePath
61
+ ? (stagesByDockerfile.get(service.build.dockerfilePath) ?? []).map((stage) => stage.name)
62
+ : [];
63
+ const imageName = service.image ?? buildSyntheticImageName(service.name);
64
+ services.push({
65
+ name: service.name,
66
+ sourceFile: service.sourceFile,
67
+ containerName: service.containerName,
68
+ image: imageName,
69
+ buildContext: service.build?.context,
70
+ dockerfilePath: service.build?.dockerfilePath,
71
+ targetStage: service.build?.targetStage,
72
+ stageNames,
73
+ command: service.command,
74
+ entrypoint: service.entrypoint,
75
+ environment,
76
+ envFiles: service.envFiles,
77
+ ports: service.ports,
78
+ volumes: service.volumes,
79
+ dependsOn: service.dependsOn,
80
+ });
81
+ containers.push({
82
+ name: service.containerName,
83
+ service: service.name,
84
+ sourceFile: service.sourceFile,
85
+ image: imageName,
86
+ command: service.command,
87
+ entrypoint: service.entrypoint,
88
+ environment,
89
+ ports: service.ports,
90
+ volumes: service.volumes,
91
+ dependsOn: service.dependsOn.map((dependency) => dependency.service),
92
+ });
93
+ const imageKey = [
94
+ imageName,
95
+ service.build?.dockerfilePath ?? '',
96
+ service.build?.targetStage ?? '',
97
+ ].join('|');
98
+ if (!imagesByKey.has(imageKey)) {
99
+ imagesByKey.set(imageKey, {
100
+ name: imageName,
101
+ explicitImage: service.image,
102
+ sourceFile: service.sourceFile,
103
+ buildContext: service.build?.context,
104
+ dockerfilePath: service.build?.dockerfilePath,
105
+ targetStage: service.build?.targetStage,
106
+ stageNames,
107
+ });
108
+ }
109
+ }
110
+ }
111
+ // Dockerfile-only 场景仍保留镜像和 stages
112
+ for (const dockerfile of input.dockerfiles) {
113
+ const existing = dockerfile.serviceNames.length > 0
114
+ ? undefined
115
+ : imagesByKey.get(`${dockerfile.relativePath}||`);
116
+ if (!existing && dockerfile.serviceNames.length === 0) {
117
+ const standaloneName = dockerfile.relativePath;
118
+ imagesByKey.set(`${standaloneName}||`, {
119
+ name: standaloneName,
120
+ sourceFile: dockerfile.relativePath,
121
+ dockerfilePath: dockerfile.relativePath,
122
+ stageNames: (stagesByDockerfile.get(dockerfile.relativePath) ?? []).map((stage) => stage.name),
123
+ });
124
+ }
125
+ }
126
+ const stages = [...stagesByDockerfile.values()]
127
+ .flat()
128
+ .sort((a, b) => a.sourceFile.localeCompare(b.sourceFile) || a.index - b.index);
129
+ const topology = {
130
+ projectName: input.projectName,
131
+ services: services.sort((a, b) => a.name.localeCompare(b.name)),
132
+ images: [...imagesByKey.values()].sort((a, b) => a.name.localeCompare(b.name)),
133
+ containers: containers.sort((a, b) => a.name.localeCompare(b.name)),
134
+ stages,
135
+ configHints: dedupeConfigHints(input.configHints),
136
+ sourceFiles: collectSourceFiles(input, stagesByDockerfile),
137
+ };
138
+ return {
139
+ title: `运行时拓扑: ${input.projectName}`,
140
+ generatedAt: new Date().toISOString().split('T')[0],
141
+ topology,
142
+ stats: summarizeRuntimeTopology(topology),
143
+ warnings: input.warnings,
144
+ };
145
+ }
146
+ render(output) {
147
+ const template = loadTemplate('runtime-topology.hbs', import.meta.url);
148
+ return template(output);
149
+ }
150
+ extractComposeFiles(projectRoot, configFiles, warnings) {
151
+ const composeFiles = [];
152
+ for (const composePath of discoverComposeFiles(projectRoot, configFiles)) {
153
+ try {
154
+ const content = fs.readFileSync(composePath, 'utf-8');
155
+ composeFiles.push(parseComposeFile(projectRoot, composePath, content));
156
+ }
157
+ catch (error) {
158
+ warnings.add(`无法读取 Compose 文件: ${toProjectRelativePath(projectRoot, composePath)} (${String(error)})`);
159
+ }
160
+ }
161
+ return composeFiles.sort((a, b) => a.filePath.localeCompare(b.filePath));
162
+ }
163
+ async extractDockerfiles(projectRoot, configFiles, composeFiles, warnings) {
164
+ const dockerfileRefs = new Map();
165
+ for (const dockerfilePath of discoverRootDockerfiles(projectRoot, configFiles)) {
166
+ dockerfileRefs.set(dockerfilePath, {
167
+ relativePath: toProjectRelativePath(projectRoot, dockerfilePath),
168
+ serviceNames: new Set(),
169
+ runtimeTargets: new Set(),
170
+ });
171
+ }
172
+ for (const composeFile of composeFiles) {
173
+ for (const service of composeFile.services) {
174
+ if (!service.build?.dockerfilePath)
175
+ continue;
176
+ const absolutePath = path.resolve(projectRoot, service.build.dockerfilePath);
177
+ const existing = dockerfileRefs.get(absolutePath) ?? {
178
+ relativePath: toProjectRelativePath(projectRoot, absolutePath),
179
+ serviceNames: new Set(),
180
+ runtimeTargets: new Set(),
181
+ };
182
+ existing.serviceNames.add(service.name);
183
+ if (service.build.targetStage) {
184
+ existing.runtimeTargets.add(service.build.targetStage);
185
+ }
186
+ dockerfileRefs.set(absolutePath, existing);
187
+ }
188
+ }
189
+ const parser = new DockerfileParser();
190
+ const results = [];
191
+ for (const [absolutePath, metadata] of dockerfileRefs) {
192
+ if (!fs.existsSync(absolutePath)) {
193
+ warnings.add(`引用的 Dockerfile 不存在: ${metadata.relativePath}`);
194
+ continue;
195
+ }
196
+ const parsed = await parser.parse(absolutePath);
197
+ results.push({
198
+ filePath: absolutePath,
199
+ relativePath: metadata.relativePath,
200
+ parsed,
201
+ serviceNames: [...metadata.serviceNames].sort(),
202
+ runtimeTargets: [...metadata.runtimeTargets].sort(),
203
+ });
204
+ }
205
+ return results.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
206
+ }
207
+ async extractEnvFiles(projectRoot, composeFiles, warnings) {
208
+ const envPaths = new Set(discoverRootEnvFiles(projectRoot));
209
+ for (const composeFile of composeFiles) {
210
+ for (const service of composeFile.services) {
211
+ for (const envFile of service.envFiles) {
212
+ const absolutePath = path.resolve(projectRoot, envFile);
213
+ if (!fs.existsSync(absolutePath)) {
214
+ warnings.add(`引用的 env_file 不存在: ${envFile}`);
215
+ continue;
216
+ }
217
+ envPaths.add(absolutePath);
218
+ }
219
+ }
220
+ }
221
+ const parser = new EnvConfigParser();
222
+ const results = [];
223
+ for (const envPath of envPaths) {
224
+ const relativePath = toProjectRelativePath(projectRoot, envPath);
225
+ const parsed = await parser.parse(envPath);
226
+ results.push({
227
+ filePath: relativePath,
228
+ entries: parsed.entries.map((entry) => ({
229
+ name: entry.keyPath,
230
+ value: entry.defaultValue,
231
+ sourceKind: 'env-file',
232
+ sourceFile: relativePath,
233
+ scope: 'global',
234
+ })),
235
+ });
236
+ }
237
+ return results.sort((a, b) => a.filePath.localeCompare(b.filePath));
238
+ }
239
+ async extractRuntimeConfigHints(projectRoot, composeFiles, dockerfiles, envFiles) {
240
+ const composePaths = new Set(composeFiles.map((file) => path.resolve(projectRoot, file.filePath)));
241
+ const dockerfilePaths = new Set(dockerfiles.map((dockerfile) => dockerfile.filePath));
242
+ const envPaths = new Set(envFiles.map((envFile) => path.resolve(projectRoot, envFile.filePath)));
243
+ const hints = [];
244
+ for (const envFile of envFiles) {
245
+ hints.push(...envFile.entries.map((entry) => ({
246
+ keyPath: entry.name,
247
+ value: entry.value ?? '',
248
+ sourceFile: envFile.filePath,
249
+ format: 'env',
250
+ category: 'environment',
251
+ })));
252
+ }
253
+ const rootEntries = safeReadDir(projectRoot);
254
+ const yamlParser = new YamlConfigParser();
255
+ const tomlParser = new TomlConfigParser();
256
+ for (const entry of rootEntries) {
257
+ if (!entry.isFile())
258
+ continue;
259
+ const absolutePath = path.join(projectRoot, entry.name);
260
+ if (composePaths.has(absolutePath) || dockerfilePaths.has(absolutePath) || envPaths.has(absolutePath)) {
261
+ continue;
262
+ }
263
+ const relativePath = toProjectRelativePath(projectRoot, absolutePath);
264
+ if (YAML_CONFIG_RE.test(entry.name)) {
265
+ const parsed = await yamlParser.parse(absolutePath);
266
+ hints.push(...collectRuntimeConfigHints(parsed.entries, relativePath, 'yaml'));
267
+ }
268
+ else if (TOML_CONFIG_RE.test(entry.name)) {
269
+ const parsed = await tomlParser.parse(absolutePath);
270
+ hints.push(...collectRuntimeConfigHints(parsed.entries, relativePath, 'toml'));
271
+ }
272
+ }
273
+ return hints.sort((a, b) => a.sourceFile.localeCompare(b.sourceFile) ||
274
+ a.keyPath.localeCompare(b.keyPath));
275
+ }
276
+ }
277
+ function parseComposeFile(projectRoot, composePath, content) {
278
+ const composeDoc = parseYamlDocument(content);
279
+ const servicesNode = composeDoc.services;
280
+ const services = isYamlObject(servicesNode)
281
+ ? Object.entries(servicesNode).flatMap(([serviceName, serviceValue]) => {
282
+ if (!isYamlObject(serviceValue)) {
283
+ return [];
284
+ }
285
+ return [parseComposeService(projectRoot, composePath, serviceName, serviceValue)];
286
+ })
287
+ : [];
288
+ return {
289
+ filePath: toProjectRelativePath(projectRoot, composePath),
290
+ services: services.sort((a, b) => a.name.localeCompare(b.name)),
291
+ };
292
+ }
293
+ function parseComposeService(projectRoot, composePath, serviceName, serviceNode) {
294
+ const relativeComposePath = toProjectRelativePath(projectRoot, composePath);
295
+ const composeDir = path.dirname(composePath);
296
+ return {
297
+ name: serviceName,
298
+ sourceFile: relativeComposePath,
299
+ image: yamlToString(serviceNode.image),
300
+ build: parseComposeBuild(projectRoot, composeDir, serviceNode.build),
301
+ containerName: yamlToString(serviceNode.container_name) ?? serviceName,
302
+ command: normalizeCommandValue(serviceNode.command),
303
+ entrypoint: normalizeCommandValue(serviceNode.entrypoint),
304
+ environment: parseComposeEnvironment(serviceNode.environment, relativeComposePath),
305
+ envFiles: parseComposeEnvFiles(projectRoot, composeDir, serviceNode.env_file),
306
+ ports: parseComposePorts(serviceNode.ports, relativeComposePath),
307
+ volumes: parseComposeVolumes(serviceNode.volumes, relativeComposePath),
308
+ dependsOn: parseComposeDependsOn(serviceNode.depends_on, relativeComposePath),
309
+ };
310
+ }
311
+ function parseComposeBuild(projectRoot, composeDir, buildNode) {
312
+ if (buildNode === undefined) {
313
+ return undefined;
314
+ }
315
+ if (typeof buildNode === 'string') {
316
+ const buildContext = resolveComposePath(projectRoot, composeDir, buildNode);
317
+ return {
318
+ context: toProjectRelativePath(projectRoot, buildContext),
319
+ dockerfilePath: toProjectRelativePath(projectRoot, resolveComposePath(projectRoot, buildContext, 'Dockerfile')),
320
+ };
321
+ }
322
+ if (!isYamlObject(buildNode)) {
323
+ return undefined;
324
+ }
325
+ const rawContext = yamlToString(buildNode.context) ?? '.';
326
+ const buildContext = resolveComposePath(projectRoot, composeDir, rawContext);
327
+ const rawDockerfile = yamlToString(buildNode.dockerfile) ?? 'Dockerfile';
328
+ return {
329
+ context: toProjectRelativePath(projectRoot, buildContext),
330
+ dockerfilePath: toProjectRelativePath(projectRoot, resolveComposePath(projectRoot, buildContext, rawDockerfile)),
331
+ targetStage: yamlToString(buildNode.target),
332
+ };
333
+ }
334
+ function parseComposeEnvironment(environmentNode, sourceFile) {
335
+ if (!environmentNode) {
336
+ return [];
337
+ }
338
+ const environment = [];
339
+ if (isYamlObject(environmentNode)) {
340
+ for (const [name, rawValue] of Object.entries(environmentNode)) {
341
+ environment.push({
342
+ name,
343
+ value: yamlToString(rawValue),
344
+ sourceKind: 'compose',
345
+ sourceFile,
346
+ scope: 'service',
347
+ });
348
+ }
349
+ }
350
+ else if (Array.isArray(environmentNode)) {
351
+ for (const item of environmentNode) {
352
+ const rawValue = yamlToString(item);
353
+ if (!rawValue)
354
+ continue;
355
+ const separatorIndex = rawValue.indexOf('=');
356
+ if (separatorIndex < 0) {
357
+ environment.push({
358
+ name: rawValue,
359
+ sourceKind: 'compose',
360
+ sourceFile,
361
+ scope: 'service',
362
+ });
363
+ continue;
364
+ }
365
+ environment.push({
366
+ name: rawValue.slice(0, separatorIndex),
367
+ value: rawValue.slice(separatorIndex + 1),
368
+ sourceKind: 'compose',
369
+ sourceFile,
370
+ scope: 'service',
371
+ });
372
+ }
373
+ }
374
+ return environment.sort((a, b) => a.name.localeCompare(b.name));
375
+ }
376
+ function parseComposeEnvFiles(projectRoot, composeDir, envNode) {
377
+ if (!envNode) {
378
+ return [];
379
+ }
380
+ if (typeof envNode === 'string') {
381
+ return [toProjectRelativePath(projectRoot, resolveComposePath(projectRoot, composeDir, envNode))];
382
+ }
383
+ if (Array.isArray(envNode)) {
384
+ return envNode
385
+ .map((item) => yamlToString(item))
386
+ .filter((item) => Boolean(item))
387
+ .map((item) => toProjectRelativePath(projectRoot, resolveComposePath(projectRoot, composeDir, item)))
388
+ .sort();
389
+ }
390
+ return [];
391
+ }
392
+ function parseComposeDependsOn(dependsOnNode, sourceFile) {
393
+ if (!dependsOnNode) {
394
+ return [];
395
+ }
396
+ const dependsOn = [];
397
+ if (Array.isArray(dependsOnNode)) {
398
+ for (const item of dependsOnNode) {
399
+ const service = yamlToString(item);
400
+ if (!service)
401
+ continue;
402
+ dependsOn.push({ service, sourceFile });
403
+ }
404
+ }
405
+ else if (isYamlObject(dependsOnNode)) {
406
+ for (const [service, rawValue] of Object.entries(dependsOnNode)) {
407
+ if (isYamlObject(rawValue)) {
408
+ dependsOn.push({
409
+ service,
410
+ sourceFile,
411
+ condition: yamlToString(rawValue.condition),
412
+ required: yamlToBoolean(rawValue.required),
413
+ });
414
+ }
415
+ else {
416
+ dependsOn.push({
417
+ service,
418
+ sourceFile,
419
+ condition: yamlToString(rawValue),
420
+ });
421
+ }
422
+ }
423
+ }
424
+ return dependsOn.sort((a, b) => a.service.localeCompare(b.service));
425
+ }
426
+ function parseComposePorts(portsNode, sourceFile) {
427
+ if (!portsNode || !Array.isArray(portsNode)) {
428
+ return [];
429
+ }
430
+ return portsNode
431
+ .flatMap((portNode) => {
432
+ if (typeof portNode === 'string') {
433
+ return [parseComposeShortPort(portNode, sourceFile)];
434
+ }
435
+ if (isYamlObject(portNode)) {
436
+ const target = yamlToString(portNode.target);
437
+ if (!target)
438
+ return [];
439
+ return [{
440
+ target,
441
+ published: yamlToString(portNode.published),
442
+ hostIp: yamlToString(portNode.host_ip),
443
+ protocol: yamlToString(portNode.protocol) ?? 'tcp',
444
+ mode: yamlToString(portNode.mode),
445
+ raw: buildComposeLongSyntax(portNode),
446
+ sourceFile,
447
+ }];
448
+ }
449
+ return [];
450
+ })
451
+ .sort((a, b) => a.target.localeCompare(b.target));
452
+ }
453
+ function parseComposeShortPort(rawPort, sourceFile) {
454
+ const [basePort, protocol = 'tcp'] = rawPort.split('/');
455
+ const parts = basePort.split(':');
456
+ if (parts.length === 1) {
457
+ return {
458
+ target: parts[0],
459
+ protocol,
460
+ raw: rawPort,
461
+ sourceFile,
462
+ };
463
+ }
464
+ if (parts.length === 2) {
465
+ return {
466
+ published: parts[0],
467
+ target: parts[1],
468
+ protocol,
469
+ raw: rawPort,
470
+ sourceFile,
471
+ };
472
+ }
473
+ return {
474
+ hostIp: parts[0],
475
+ published: parts[1],
476
+ target: parts[2] ?? '',
477
+ protocol,
478
+ raw: rawPort,
479
+ sourceFile,
480
+ };
481
+ }
482
+ function parseComposeVolumes(volumesNode, sourceFile) {
483
+ if (!volumesNode || !Array.isArray(volumesNode)) {
484
+ return [];
485
+ }
486
+ return volumesNode
487
+ .flatMap((volumeNode) => {
488
+ if (typeof volumeNode === 'string') {
489
+ return [parseComposeShortVolume(volumeNode, sourceFile)];
490
+ }
491
+ if (isYamlObject(volumeNode)) {
492
+ const target = yamlToString(volumeNode.target);
493
+ if (!target)
494
+ return [];
495
+ const source = yamlToString(volumeNode.source);
496
+ return [{
497
+ target,
498
+ source,
499
+ type: parseVolumeType(yamlToString(volumeNode.type), source),
500
+ readOnly: yamlToBoolean(volumeNode.read_only) ?? yamlToBoolean(volumeNode.readonly) ?? false,
501
+ raw: buildComposeLongSyntax(volumeNode),
502
+ sourceFile,
503
+ }];
504
+ }
505
+ return [];
506
+ })
507
+ .sort((a, b) => a.target.localeCompare(b.target));
508
+ }
509
+ function parseComposeShortVolume(rawVolume, sourceFile) {
510
+ const parts = rawVolume.split(':');
511
+ if (parts.length === 1) {
512
+ return {
513
+ target: parts[0],
514
+ type: 'volume',
515
+ readOnly: false,
516
+ raw: rawVolume,
517
+ sourceFile,
518
+ };
519
+ }
520
+ const source = parts[0];
521
+ const target = parts[1] ?? '';
522
+ const flags = parts.slice(2);
523
+ return {
524
+ source,
525
+ target,
526
+ type: parseVolumeType(undefined, source),
527
+ readOnly: flags.includes('ro') || flags.includes('readonly'),
528
+ raw: rawVolume,
529
+ sourceFile,
530
+ };
531
+ }
532
+ function parseVolumeType(rawType, source) {
533
+ if (rawType === 'bind' || rawType === 'volume' || rawType === 'tmpfs') {
534
+ return rawType;
535
+ }
536
+ if (!source) {
537
+ return 'volume';
538
+ }
539
+ if (source.startsWith('.') || source.startsWith('/') || source.startsWith('~')) {
540
+ return 'bind';
541
+ }
542
+ return 'volume';
543
+ }
544
+ function resolveComposePath(projectRoot, baseDir, rawPath) {
545
+ if (path.isAbsolute(rawPath)) {
546
+ return rawPath;
547
+ }
548
+ return path.resolve(baseDir, rawPath);
549
+ }
550
+ function detectProjectName(projectRoot) {
551
+ const packageJsonPath = path.join(projectRoot, 'package.json');
552
+ try {
553
+ if (fs.existsSync(packageJsonPath)) {
554
+ const parsed = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
555
+ if (typeof parsed.name === 'string' && parsed.name.length > 0) {
556
+ return parsed.name;
557
+ }
558
+ }
559
+ }
560
+ catch {
561
+ // ignore and fallback to dirname
562
+ }
563
+ return path.basename(projectRoot);
564
+ }
565
+ function discoverComposeFiles(projectRoot, configFiles) {
566
+ const composePaths = new Set();
567
+ for (const [name, filePath] of configFiles) {
568
+ if (COMPOSE_FILE_RE.test(name)) {
569
+ composePaths.add(filePath);
570
+ }
571
+ }
572
+ for (const entry of safeReadDir(projectRoot)) {
573
+ if (entry.isFile() && COMPOSE_FILE_RE.test(entry.name)) {
574
+ composePaths.add(path.join(projectRoot, entry.name));
575
+ }
576
+ }
577
+ return [...composePaths].sort();
578
+ }
579
+ function discoverRootDockerfiles(projectRoot, configFiles) {
580
+ const dockerfiles = new Set();
581
+ for (const [name, filePath] of configFiles) {
582
+ if (ROOT_DOCKERFILE_RE.test(name)) {
583
+ dockerfiles.add(filePath);
584
+ }
585
+ }
586
+ for (const entry of safeReadDir(projectRoot)) {
587
+ if (entry.isFile() && ROOT_DOCKERFILE_RE.test(entry.name)) {
588
+ dockerfiles.add(path.join(projectRoot, entry.name));
589
+ }
590
+ }
591
+ return [...dockerfiles].sort();
592
+ }
593
+ function discoverRootEnvFiles(projectRoot) {
594
+ return safeReadDir(projectRoot)
595
+ .filter((entry) => entry.isFile() && ENV_FILE_RE.test(entry.name))
596
+ .map((entry) => path.join(projectRoot, entry.name))
597
+ .sort();
598
+ }
599
+ function dedupeConfigHints(configHints) {
600
+ const seen = new Map();
601
+ for (const hint of configHints) {
602
+ seen.set(`${hint.sourceFile}:${hint.keyPath}:${hint.category}`, hint);
603
+ }
604
+ return [...seen.values()].sort((a, b) => a.sourceFile.localeCompare(b.sourceFile) || a.keyPath.localeCompare(b.keyPath));
605
+ }
606
+ function collectSourceFiles(input, stagesByDockerfile) {
607
+ const sourceFiles = new Set();
608
+ for (const composeFile of input.composeFiles) {
609
+ sourceFiles.add(composeFile.filePath);
610
+ }
611
+ for (const envFile of input.envFiles) {
612
+ sourceFiles.add(envFile.filePath);
613
+ }
614
+ for (const hint of input.configHints) {
615
+ sourceFiles.add(hint.sourceFile);
616
+ }
617
+ for (const dockerfile of input.dockerfiles) {
618
+ sourceFiles.add(dockerfile.relativePath);
619
+ }
620
+ for (const [dockerfilePath, stages] of stagesByDockerfile) {
621
+ if (stages.length > 0) {
622
+ sourceFiles.add(dockerfilePath);
623
+ }
624
+ }
625
+ return [...sourceFiles].sort();
626
+ }
627
+ function safeReadDir(dir) {
628
+ try {
629
+ return fs.readdirSync(dir, { withFileTypes: true });
630
+ }
631
+ catch {
632
+ return [];
633
+ }
634
+ }
635
+ function toProjectRelativePath(projectRoot, targetPath) {
636
+ const relativePath = path.relative(projectRoot, targetPath);
637
+ return relativePath.split(path.sep).join('/');
638
+ }
639
+ function yamlToString(value) {
640
+ if (value === null || value === undefined) {
641
+ return undefined;
642
+ }
643
+ if (typeof value === 'string') {
644
+ return value;
645
+ }
646
+ if (typeof value === 'number' || typeof value === 'boolean') {
647
+ return String(value);
648
+ }
649
+ return undefined;
650
+ }
651
+ function yamlToBoolean(value) {
652
+ if (typeof value === 'boolean') {
653
+ return value;
654
+ }
655
+ if (typeof value === 'string') {
656
+ if (value === 'true')
657
+ return true;
658
+ if (value === 'false')
659
+ return false;
660
+ }
661
+ return undefined;
662
+ }
663
+ function buildComposeLongSyntax(value) {
664
+ return Object.entries(value)
665
+ .map(([key, item]) => `${key}=${yamlToString(item) ?? ''}`)
666
+ .join(', ');
667
+ }
668
+ function isYamlObject(value) {
669
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
670
+ }
671
+ function _isYamlArray(value) {
672
+ return Array.isArray(value);
673
+ }
674
+ // 导出测试辅助函数
675
+ export { discoverComposeFiles as _discoverComposeFiles, parseComposeFile as _parseComposeFile, parseComposeShortPort as _parseComposeShortPort, parseComposeShortVolume as _parseComposeShortVolume, dedupeConfigHints as _dedupeConfigHints, _isYamlArray, };
676
+ //# sourceMappingURL=runtime-topology-generator.js.map