@grafema/util 0.3.0-beta

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 (324) hide show
  1. package/LICENSE +190 -0
  2. package/dist/api/GraphAPI.d.ts +87 -0
  3. package/dist/api/GraphAPI.d.ts.map +1 -0
  4. package/dist/api/GraphAPI.js +212 -0
  5. package/dist/api/GraphAPI.js.map +1 -0
  6. package/dist/api/GuaranteeAPI.d.ts +147 -0
  7. package/dist/api/GuaranteeAPI.d.ts.map +1 -0
  8. package/dist/api/GuaranteeAPI.js +290 -0
  9. package/dist/api/GuaranteeAPI.js.map +1 -0
  10. package/dist/config/ConfigLoader.d.ts +214 -0
  11. package/dist/config/ConfigLoader.d.ts.map +1 -0
  12. package/dist/config/ConfigLoader.js +441 -0
  13. package/dist/config/ConfigLoader.js.map +1 -0
  14. package/dist/config/index.d.ts +6 -0
  15. package/dist/config/index.d.ts.map +1 -0
  16. package/dist/config/index.js +5 -0
  17. package/dist/config/index.js.map +1 -0
  18. package/dist/core/CoverageAnalyzer.d.ts +65 -0
  19. package/dist/core/CoverageAnalyzer.d.ts.map +1 -0
  20. package/dist/core/CoverageAnalyzer.js +199 -0
  21. package/dist/core/CoverageAnalyzer.js.map +1 -0
  22. package/dist/core/FileExplainer.d.ts +101 -0
  23. package/dist/core/FileExplainer.d.ts.map +1 -0
  24. package/dist/core/FileExplainer.js +140 -0
  25. package/dist/core/FileExplainer.js.map +1 -0
  26. package/dist/core/FileOverview.d.ts +124 -0
  27. package/dist/core/FileOverview.d.ts.map +1 -0
  28. package/dist/core/FileOverview.js +279 -0
  29. package/dist/core/FileOverview.js.map +1 -0
  30. package/dist/core/GrafemaUri.d.ts +66 -0
  31. package/dist/core/GrafemaUri.d.ts.map +1 -0
  32. package/dist/core/GrafemaUri.js +191 -0
  33. package/dist/core/GrafemaUri.js.map +1 -0
  34. package/dist/core/GraphBackend.d.ts +158 -0
  35. package/dist/core/GraphBackend.d.ts.map +1 -0
  36. package/dist/core/GraphBackend.js +85 -0
  37. package/dist/core/GraphBackend.js.map +1 -0
  38. package/dist/core/GraphFreshnessChecker.d.ts +33 -0
  39. package/dist/core/GraphFreshnessChecker.d.ts.map +1 -0
  40. package/dist/core/GraphFreshnessChecker.js +104 -0
  41. package/dist/core/GraphFreshnessChecker.js.map +1 -0
  42. package/dist/core/GuaranteeManager.d.ts +254 -0
  43. package/dist/core/GuaranteeManager.d.ts.map +1 -0
  44. package/dist/core/GuaranteeManager.js +447 -0
  45. package/dist/core/GuaranteeManager.js.map +1 -0
  46. package/dist/core/HashUtils.d.ts +24 -0
  47. package/dist/core/HashUtils.d.ts.map +1 -0
  48. package/dist/core/HashUtils.js +46 -0
  49. package/dist/core/HashUtils.js.map +1 -0
  50. package/dist/core/IncrementalReanalyzer.d.ts +33 -0
  51. package/dist/core/IncrementalReanalyzer.d.ts.map +1 -0
  52. package/dist/core/IncrementalReanalyzer.js +67 -0
  53. package/dist/core/IncrementalReanalyzer.js.map +1 -0
  54. package/dist/core/ResourceRegistry.d.ts +17 -0
  55. package/dist/core/ResourceRegistry.d.ts.map +1 -0
  56. package/dist/core/ResourceRegistry.js +32 -0
  57. package/dist/core/ResourceRegistry.js.map +1 -0
  58. package/dist/core/SemanticId.d.ts +159 -0
  59. package/dist/core/SemanticId.d.ts.map +1 -0
  60. package/dist/core/SemanticId.js +291 -0
  61. package/dist/core/SemanticId.js.map +1 -0
  62. package/dist/core/VersionManager.d.ts +166 -0
  63. package/dist/core/VersionManager.d.ts.map +1 -0
  64. package/dist/core/VersionManager.js +239 -0
  65. package/dist/core/VersionManager.js.map +1 -0
  66. package/dist/core/brandNodeInternal.d.ts +14 -0
  67. package/dist/core/brandNodeInternal.d.ts.map +1 -0
  68. package/dist/core/brandNodeInternal.js +4 -0
  69. package/dist/core/brandNodeInternal.js.map +1 -0
  70. package/dist/core/nodes/GuaranteeNode.d.ts +76 -0
  71. package/dist/core/nodes/GuaranteeNode.d.ts.map +1 -0
  72. package/dist/core/nodes/GuaranteeNode.js +118 -0
  73. package/dist/core/nodes/GuaranteeNode.js.map +1 -0
  74. package/dist/core/nodes/IssueNode.d.ts +73 -0
  75. package/dist/core/nodes/IssueNode.d.ts.map +1 -0
  76. package/dist/core/nodes/IssueNode.js +130 -0
  77. package/dist/core/nodes/IssueNode.js.map +1 -0
  78. package/dist/core/nodes/NodeKind.d.ts +104 -0
  79. package/dist/core/nodes/NodeKind.d.ts.map +1 -0
  80. package/dist/core/nodes/NodeKind.js +166 -0
  81. package/dist/core/nodes/NodeKind.js.map +1 -0
  82. package/dist/diagnostics/DiagnosticCollector.d.ts +103 -0
  83. package/dist/diagnostics/DiagnosticCollector.d.ts.map +1 -0
  84. package/dist/diagnostics/DiagnosticCollector.js +133 -0
  85. package/dist/diagnostics/DiagnosticCollector.js.map +1 -0
  86. package/dist/diagnostics/DiagnosticReporter.d.ts +122 -0
  87. package/dist/diagnostics/DiagnosticReporter.d.ts.map +1 -0
  88. package/dist/diagnostics/DiagnosticReporter.js +300 -0
  89. package/dist/diagnostics/DiagnosticReporter.js.map +1 -0
  90. package/dist/diagnostics/DiagnosticWriter.d.ts +31 -0
  91. package/dist/diagnostics/DiagnosticWriter.d.ts.map +1 -0
  92. package/dist/diagnostics/DiagnosticWriter.js +44 -0
  93. package/dist/diagnostics/DiagnosticWriter.js.map +1 -0
  94. package/dist/diagnostics/categories.d.ts +57 -0
  95. package/dist/diagnostics/categories.d.ts.map +1 -0
  96. package/dist/diagnostics/categories.js +71 -0
  97. package/dist/diagnostics/categories.js.map +1 -0
  98. package/dist/diagnostics/index.d.ts +17 -0
  99. package/dist/diagnostics/index.d.ts.map +1 -0
  100. package/dist/diagnostics/index.js +15 -0
  101. package/dist/diagnostics/index.js.map +1 -0
  102. package/dist/errors/GrafemaError.d.ts +200 -0
  103. package/dist/errors/GrafemaError.d.ts.map +1 -0
  104. package/dist/errors/GrafemaError.js +209 -0
  105. package/dist/errors/GrafemaError.js.map +1 -0
  106. package/dist/index.d.ts +75 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +76 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/instructions/index.d.ts +8 -0
  111. package/dist/instructions/index.d.ts.map +1 -0
  112. package/dist/instructions/index.js +20 -0
  113. package/dist/instructions/index.js.map +1 -0
  114. package/dist/instructions/onboarding.md +133 -0
  115. package/dist/knowledge/KnowledgeBase.d.ts +113 -0
  116. package/dist/knowledge/KnowledgeBase.d.ts.map +1 -0
  117. package/dist/knowledge/KnowledgeBase.js +420 -0
  118. package/dist/knowledge/KnowledgeBase.js.map +1 -0
  119. package/dist/knowledge/SemanticAddressResolver.d.ts +59 -0
  120. package/dist/knowledge/SemanticAddressResolver.d.ts.map +1 -0
  121. package/dist/knowledge/SemanticAddressResolver.js +160 -0
  122. package/dist/knowledge/SemanticAddressResolver.js.map +1 -0
  123. package/dist/knowledge/git-ingest.d.ts +58 -0
  124. package/dist/knowledge/git-ingest.d.ts.map +1 -0
  125. package/dist/knowledge/git-ingest.js +301 -0
  126. package/dist/knowledge/git-ingest.js.map +1 -0
  127. package/dist/knowledge/git-queries.d.ts +86 -0
  128. package/dist/knowledge/git-queries.d.ts.map +1 -0
  129. package/dist/knowledge/git-queries.js +177 -0
  130. package/dist/knowledge/git-queries.js.map +1 -0
  131. package/dist/knowledge/index.d.ts +14 -0
  132. package/dist/knowledge/index.d.ts.map +1 -0
  133. package/dist/knowledge/index.js +10 -0
  134. package/dist/knowledge/index.js.map +1 -0
  135. package/dist/knowledge/parser.d.ts +39 -0
  136. package/dist/knowledge/parser.d.ts.map +1 -0
  137. package/dist/knowledge/parser.js +292 -0
  138. package/dist/knowledge/parser.js.map +1 -0
  139. package/dist/knowledge/types.d.ts +133 -0
  140. package/dist/knowledge/types.d.ts.map +1 -0
  141. package/dist/knowledge/types.js +8 -0
  142. package/dist/knowledge/types.js.map +1 -0
  143. package/dist/logging/Logger.d.ts +98 -0
  144. package/dist/logging/Logger.d.ts.map +1 -0
  145. package/dist/logging/Logger.js +274 -0
  146. package/dist/logging/Logger.js.map +1 -0
  147. package/dist/notation/archetypes.d.ts +36 -0
  148. package/dist/notation/archetypes.d.ts.map +1 -0
  149. package/dist/notation/archetypes.js +173 -0
  150. package/dist/notation/archetypes.js.map +1 -0
  151. package/dist/notation/fold.d.ts +25 -0
  152. package/dist/notation/fold.d.ts.map +1 -0
  153. package/dist/notation/fold.js +598 -0
  154. package/dist/notation/fold.js.map +1 -0
  155. package/dist/notation/index.d.ts +18 -0
  156. package/dist/notation/index.d.ts.map +1 -0
  157. package/dist/notation/index.js +16 -0
  158. package/dist/notation/index.js.map +1 -0
  159. package/dist/notation/lodExtractor.d.ts +32 -0
  160. package/dist/notation/lodExtractor.d.ts.map +1 -0
  161. package/dist/notation/lodExtractor.js +149 -0
  162. package/dist/notation/lodExtractor.js.map +1 -0
  163. package/dist/notation/nameShortener.d.ts +22 -0
  164. package/dist/notation/nameShortener.d.ts.map +1 -0
  165. package/dist/notation/nameShortener.js +24 -0
  166. package/dist/notation/nameShortener.js.map +1 -0
  167. package/dist/notation/perspectives.d.ts +11 -0
  168. package/dist/notation/perspectives.d.ts.map +1 -0
  169. package/dist/notation/perspectives.js +16 -0
  170. package/dist/notation/perspectives.js.map +1 -0
  171. package/dist/notation/renderer.d.ts +31 -0
  172. package/dist/notation/renderer.d.ts.map +1 -0
  173. package/dist/notation/renderer.js +315 -0
  174. package/dist/notation/renderer.js.map +1 -0
  175. package/dist/notation/traceRenderer.d.ts +39 -0
  176. package/dist/notation/traceRenderer.d.ts.map +1 -0
  177. package/dist/notation/traceRenderer.js +358 -0
  178. package/dist/notation/traceRenderer.js.map +1 -0
  179. package/dist/notation/types.d.ts +66 -0
  180. package/dist/notation/types.d.ts.map +1 -0
  181. package/dist/notation/types.js +10 -0
  182. package/dist/notation/types.js.map +1 -0
  183. package/dist/queries/NodeContext.d.ts +81 -0
  184. package/dist/queries/NodeContext.d.ts.map +1 -0
  185. package/dist/queries/NodeContext.js +196 -0
  186. package/dist/queries/NodeContext.js.map +1 -0
  187. package/dist/queries/findCallsInFunction.d.ts +62 -0
  188. package/dist/queries/findCallsInFunction.d.ts.map +1 -0
  189. package/dist/queries/findCallsInFunction.js +169 -0
  190. package/dist/queries/findCallsInFunction.js.map +1 -0
  191. package/dist/queries/findContainingFunction.d.ts +57 -0
  192. package/dist/queries/findContainingFunction.d.ts.map +1 -0
  193. package/dist/queries/findContainingFunction.js +91 -0
  194. package/dist/queries/findContainingFunction.js.map +1 -0
  195. package/dist/queries/index.d.ts +18 -0
  196. package/dist/queries/index.d.ts.map +1 -0
  197. package/dist/queries/index.js +14 -0
  198. package/dist/queries/index.js.map +1 -0
  199. package/dist/queries/traceDataflow.d.ts +65 -0
  200. package/dist/queries/traceDataflow.d.ts.map +1 -0
  201. package/dist/queries/traceDataflow.js +754 -0
  202. package/dist/queries/traceDataflow.js.map +1 -0
  203. package/dist/queries/traceValues.d.ts +70 -0
  204. package/dist/queries/traceValues.d.ts.map +1 -0
  205. package/dist/queries/traceValues.js +373 -0
  206. package/dist/queries/traceValues.js.map +1 -0
  207. package/dist/queries/types.d.ts +166 -0
  208. package/dist/queries/types.d.ts.map +1 -0
  209. package/dist/queries/types.js +10 -0
  210. package/dist/queries/types.js.map +1 -0
  211. package/dist/schema/GraphSchemaExtractor.d.ts +53 -0
  212. package/dist/schema/GraphSchemaExtractor.d.ts.map +1 -0
  213. package/dist/schema/GraphSchemaExtractor.js +125 -0
  214. package/dist/schema/GraphSchemaExtractor.js.map +1 -0
  215. package/dist/schema/InterfaceSchemaExtractor.d.ts +73 -0
  216. package/dist/schema/InterfaceSchemaExtractor.d.ts.map +1 -0
  217. package/dist/schema/InterfaceSchemaExtractor.js +113 -0
  218. package/dist/schema/InterfaceSchemaExtractor.js.map +1 -0
  219. package/dist/schema/index.d.ts +5 -0
  220. package/dist/schema/index.d.ts.map +1 -0
  221. package/dist/schema/index.js +3 -0
  222. package/dist/schema/index.js.map +1 -0
  223. package/dist/storage/backends/RFDBServerBackend.d.ts +356 -0
  224. package/dist/storage/backends/RFDBServerBackend.d.ts.map +1 -0
  225. package/dist/storage/backends/RFDBServerBackend.js +748 -0
  226. package/dist/storage/backends/RFDBServerBackend.js.map +1 -0
  227. package/dist/storage/backends/typeValidation.d.ts +47 -0
  228. package/dist/storage/backends/typeValidation.d.ts.map +1 -0
  229. package/dist/storage/backends/typeValidation.js +141 -0
  230. package/dist/storage/backends/typeValidation.js.map +1 -0
  231. package/dist/utils/findRfdbBinary.d.ts +67 -0
  232. package/dist/utils/findRfdbBinary.d.ts.map +1 -0
  233. package/dist/utils/findRfdbBinary.js +261 -0
  234. package/dist/utils/findRfdbBinary.js.map +1 -0
  235. package/dist/utils/lazyDownload.d.ts +43 -0
  236. package/dist/utils/lazyDownload.d.ts.map +1 -0
  237. package/dist/utils/lazyDownload.js +175 -0
  238. package/dist/utils/lazyDownload.js.map +1 -0
  239. package/dist/utils/moduleResolution.d.ts +134 -0
  240. package/dist/utils/moduleResolution.d.ts.map +1 -0
  241. package/dist/utils/moduleResolution.js +189 -0
  242. package/dist/utils/moduleResolution.js.map +1 -0
  243. package/dist/utils/resolveNodeFile.d.ts +13 -0
  244. package/dist/utils/resolveNodeFile.d.ts.map +1 -0
  245. package/dist/utils/resolveNodeFile.js +18 -0
  246. package/dist/utils/resolveNodeFile.js.map +1 -0
  247. package/dist/utils/startRfdbServer.d.ts +63 -0
  248. package/dist/utils/startRfdbServer.d.ts.map +1 -0
  249. package/dist/utils/startRfdbServer.js +142 -0
  250. package/dist/utils/startRfdbServer.js.map +1 -0
  251. package/dist/validation/PathValidator.d.ts +80 -0
  252. package/dist/validation/PathValidator.d.ts.map +1 -0
  253. package/dist/validation/PathValidator.js +252 -0
  254. package/dist/validation/PathValidator.js.map +1 -0
  255. package/dist/version.d.ts +11 -0
  256. package/dist/version.d.ts.map +1 -0
  257. package/dist/version.js +26 -0
  258. package/dist/version.js.map +1 -0
  259. package/package.json +50 -0
  260. package/src/api/GraphAPI.ts +307 -0
  261. package/src/api/GuaranteeAPI.ts +402 -0
  262. package/src/config/ConfigLoader.ts +653 -0
  263. package/src/config/index.ts +13 -0
  264. package/src/core/CoverageAnalyzer.ts +243 -0
  265. package/src/core/FileExplainer.ts +179 -0
  266. package/src/core/FileOverview.ts +397 -0
  267. package/src/core/GrafemaUri.ts +216 -0
  268. package/src/core/GraphBackend.ts +266 -0
  269. package/src/core/GraphFreshnessChecker.ts +145 -0
  270. package/src/core/GuaranteeManager.ts +684 -0
  271. package/src/core/HashUtils.ts +48 -0
  272. package/src/core/IncrementalReanalyzer.ts +106 -0
  273. package/src/core/ResourceRegistry.ts +39 -0
  274. package/src/core/SemanticId.ts +423 -0
  275. package/src/core/VersionManager.ts +405 -0
  276. package/src/core/brandNodeInternal.ts +16 -0
  277. package/src/core/nodes/GuaranteeNode.ts +162 -0
  278. package/src/core/nodes/IssueNode.ts +177 -0
  279. package/src/core/nodes/NodeKind.ts +192 -0
  280. package/src/diagnostics/DiagnosticCollector.ts +170 -0
  281. package/src/diagnostics/DiagnosticReporter.ts +395 -0
  282. package/src/diagnostics/DiagnosticWriter.ts +50 -0
  283. package/src/diagnostics/categories.ts +104 -0
  284. package/src/diagnostics/index.ts +30 -0
  285. package/src/errors/GrafemaError.ts +297 -0
  286. package/src/index.ts +261 -0
  287. package/src/instructions/index.ts +21 -0
  288. package/src/instructions/onboarding.md +133 -0
  289. package/src/knowledge/KnowledgeBase.ts +486 -0
  290. package/src/knowledge/SemanticAddressResolver.ts +191 -0
  291. package/src/knowledge/git-ingest.ts +402 -0
  292. package/src/knowledge/git-queries.ts +269 -0
  293. package/src/knowledge/index.ts +29 -0
  294. package/src/knowledge/parser.ts +294 -0
  295. package/src/knowledge/types.ts +146 -0
  296. package/src/logging/Logger.ts +303 -0
  297. package/src/notation/archetypes.ts +189 -0
  298. package/src/notation/fold.ts +696 -0
  299. package/src/notation/index.ts +27 -0
  300. package/src/notation/lodExtractor.ts +177 -0
  301. package/src/notation/nameShortener.ts +24 -0
  302. package/src/notation/perspectives.ts +18 -0
  303. package/src/notation/renderer.ts +394 -0
  304. package/src/notation/traceRenderer.ts +458 -0
  305. package/src/notation/types.ts +79 -0
  306. package/src/queries/NodeContext.ts +280 -0
  307. package/src/queries/findCallsInFunction.ts +249 -0
  308. package/src/queries/findContainingFunction.ts +124 -0
  309. package/src/queries/index.ts +44 -0
  310. package/src/queries/traceDataflow.ts +838 -0
  311. package/src/queries/traceValues.ts +531 -0
  312. package/src/queries/types.ts +191 -0
  313. package/src/schema/GraphSchemaExtractor.ts +177 -0
  314. package/src/schema/InterfaceSchemaExtractor.ts +173 -0
  315. package/src/schema/index.ts +5 -0
  316. package/src/storage/backends/RFDBServerBackend.ts +895 -0
  317. package/src/storage/backends/typeValidation.ts +154 -0
  318. package/src/utils/findRfdbBinary.ts +288 -0
  319. package/src/utils/lazyDownload.ts +206 -0
  320. package/src/utils/moduleResolution.ts +271 -0
  321. package/src/utils/resolveNodeFile.ts +18 -0
  322. package/src/utils/startRfdbServer.ts +197 -0
  323. package/src/validation/PathValidator.ts +334 -0
  324. package/src/version.ts +28 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * LOD (Level of Detail) Subgraph Extractor
3
+ *
4
+ * Extracts a SubgraphData from the graph backend using BFS from a root node.
5
+ * Different depth levels control how much of the graph neighborhood is fetched.
6
+ *
7
+ * - LOD 0: Root + direct containment children (names only in renderer)
8
+ * - LOD 1: Same + outgoing non-containment edges for each child, resolved targets
9
+ * - LOD 2: Same + expand children that have their own CONTAINS children
10
+ *
11
+ * @module notation/lodExtractor
12
+ */
13
+ import type { BaseNodeRecord, EdgeRecord } from '@grafema/types';
14
+ import type { SubgraphData } from './types.js';
15
+ /**
16
+ * Minimal backend interface — matches the project pattern of loose coupling.
17
+ */
18
+ interface GraphBackend {
19
+ getNode(id: string): Promise<BaseNodeRecord | null>;
20
+ getOutgoingEdges(nodeId: string, edgeTypes?: string[] | null): Promise<EdgeRecord[]>;
21
+ getIncomingEdges(nodeId: string, edgeTypes?: string[] | null): Promise<EdgeRecord[]>;
22
+ }
23
+ /**
24
+ * Extract a subgraph from the backend, rooted at the given node.
25
+ *
26
+ * @param backend Graph backend
27
+ * @param rootNodeId Semantic ID of the root node
28
+ * @param depth LOD level (0, 1, or 2)
29
+ */
30
+ export declare function extractSubgraph(backend: GraphBackend, rootNodeId: string, depth?: number): Promise<SubgraphData>;
31
+ export {};
32
+ //# sourceMappingURL=lodExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lodExtractor.d.ts","sourceRoot":"","sources":["../../src/notation/lodExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;GAEG;AACH,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACrF,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CACtF;AAYD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,YAAY,CAAC,CAqFvB"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * LOD (Level of Detail) Subgraph Extractor
3
+ *
4
+ * Extracts a SubgraphData from the graph backend using BFS from a root node.
5
+ * Different depth levels control how much of the graph neighborhood is fetched.
6
+ *
7
+ * - LOD 0: Root + direct containment children (names only in renderer)
8
+ * - LOD 1: Same + outgoing non-containment edges for each child, resolved targets
9
+ * - LOD 2: Same + expand children that have their own CONTAINS children
10
+ *
11
+ * @module notation/lodExtractor
12
+ */
13
+ import { lookupEdge } from './archetypes.js';
14
+ /**
15
+ * Containment edge types that define the nesting tree.
16
+ */
17
+ const CONTAINMENT_TYPES = [
18
+ 'CONTAINS', 'HAS_SCOPE', 'HAS_MEMBER', 'HAS_BODY',
19
+ 'HAS_PROPERTY', 'HAS_ELEMENT', 'HAS_INIT', 'HAS_UPDATE',
20
+ 'HAS_CALLBACK', 'HAS_CATCH', 'HAS_FINALLY',
21
+ 'DECLARES', 'DEFINES', 'MOUNTS', 'PROPERTY_KEY', 'PROPERTY_VALUE',
22
+ ];
23
+ /**
24
+ * Extract a subgraph from the backend, rooted at the given node.
25
+ *
26
+ * @param backend Graph backend
27
+ * @param rootNodeId Semantic ID of the root node
28
+ * @param depth LOD level (0, 1, or 2)
29
+ */
30
+ export async function extractSubgraph(backend, rootNodeId, depth = 1) {
31
+ const nodeMap = new Map();
32
+ const allEdges = [];
33
+ const root = await backend.getNode(rootNodeId);
34
+ if (!root) {
35
+ return { rootNodes: [], edges: [], nodeMap };
36
+ }
37
+ nodeMap.set(root.id, root);
38
+ // Step 1: Get direct containment children
39
+ const containmentEdges = await backend.getOutgoingEdges(rootNodeId, CONTAINMENT_TYPES);
40
+ const childIds = [];
41
+ for (const edge of containmentEdges) {
42
+ allEdges.push(edge);
43
+ childIds.push(edge.dst);
44
+ if (!nodeMap.has(edge.dst)) {
45
+ const child = await backend.getNode(edge.dst);
46
+ if (child)
47
+ nodeMap.set(child.id, child);
48
+ }
49
+ }
50
+ // LOD 0: stop here (renderer shows names only)
51
+ if (depth <= 0) {
52
+ return { rootNodes: [root], edges: allEdges, nodeMap };
53
+ }
54
+ // Step 2: For each child (and root), get outgoing non-containment edges
55
+ const nodesToExpand = [rootNodeId, ...childIds];
56
+ for (const nodeId of nodesToExpand) {
57
+ const outgoing = await backend.getOutgoingEdges(nodeId);
58
+ for (const edge of outgoing) {
59
+ const mapping = lookupEdge(edge.type);
60
+ if (mapping.archetype === 'contains')
61
+ continue; // already handled
62
+ allEdges.push(edge);
63
+ // Resolve target nodes
64
+ if (!nodeMap.has(edge.dst)) {
65
+ const target = await backend.getNode(edge.dst);
66
+ if (target)
67
+ nodeMap.set(target.id, target);
68
+ }
69
+ }
70
+ }
71
+ // LOD 1: stop here
72
+ if (depth <= 1) {
73
+ return { rootNodes: [root], edges: allEdges, nodeMap };
74
+ }
75
+ // Step 3 (LOD 2): Expand children that have their own containment children
76
+ for (const childId of childIds) {
77
+ const childContainment = await backend.getOutgoingEdges(childId, CONTAINMENT_TYPES);
78
+ for (const edge of childContainment) {
79
+ allEdges.push(edge);
80
+ if (!nodeMap.has(edge.dst)) {
81
+ const grandchild = await backend.getNode(edge.dst);
82
+ if (grandchild)
83
+ nodeMap.set(grandchild.id, grandchild);
84
+ }
85
+ }
86
+ // Also get operator edges for grandchildren
87
+ const grandchildIds = childContainment.map(e => e.dst);
88
+ for (const gcId of grandchildIds) {
89
+ const gcOutgoing = await backend.getOutgoingEdges(gcId);
90
+ for (const edge of gcOutgoing) {
91
+ const mapping = lookupEdge(edge.type);
92
+ if (mapping.archetype === 'contains')
93
+ continue;
94
+ allEdges.push(edge);
95
+ if (!nodeMap.has(edge.dst)) {
96
+ const target = await backend.getNode(edge.dst);
97
+ if (target)
98
+ nodeMap.set(target.id, target);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ // Step 4: Fetch incoming PASSES_ARGUMENT edges for anonymous functions
104
+ // so the renderer can resolve λ names via callback context.
105
+ // CALL nodes are often not in the containment tree, so their outgoing
106
+ // PASSES_ARGUMENT edges don't get picked up by the BFS above.
107
+ await fetchCallbackContext(backend, allEdges, nodeMap);
108
+ return { rootNodes: [root], edges: allEdges, nodeMap };
109
+ }
110
+ /**
111
+ * For each anonymous arrow/expression in nodeMap, fetch incoming
112
+ * PASSES_ARGUMENT edges and resolve the CALL source node + sibling args.
113
+ */
114
+ async function fetchCallbackContext(backend, allEdges, nodeMap) {
115
+ const edgeSet = new Set(allEdges.map(e => `${e.src}|${e.dst}|${e.type}`));
116
+ for (const node of nodeMap.values()) {
117
+ if (node.name !== '<arrow>' && node.name !== '<expression>')
118
+ continue;
119
+ const incoming = await backend.getIncomingEdges(node.id, ['PASSES_ARGUMENT']);
120
+ for (const edge of incoming) {
121
+ const key = `${edge.src}|${edge.dst}|${edge.type}`;
122
+ if (edgeSet.has(key))
123
+ continue;
124
+ edgeSet.add(key);
125
+ allEdges.push(edge);
126
+ // Resolve the CALL node (edge source)
127
+ if (!nodeMap.has(edge.src)) {
128
+ const callNode = await backend.getNode(edge.src);
129
+ if (callNode)
130
+ nodeMap.set(callNode.id, callNode);
131
+ }
132
+ // Fetch all PASSES_ARGUMENT from same CALL to find sibling args
133
+ const callOutgoing = await backend.getOutgoingEdges(edge.src, ['PASSES_ARGUMENT']);
134
+ for (const sibEdge of callOutgoing) {
135
+ const sibKey = `${sibEdge.src}|${sibEdge.dst}|${sibEdge.type}`;
136
+ if (edgeSet.has(sibKey))
137
+ continue;
138
+ edgeSet.add(sibKey);
139
+ allEdges.push(sibEdge);
140
+ if (!nodeMap.has(sibEdge.dst)) {
141
+ const sibNode = await backend.getNode(sibEdge.dst);
142
+ if (sibNode)
143
+ nodeMap.set(sibNode.id, sibNode);
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }
149
+ //# sourceMappingURL=lodExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lodExtractor.js","sourceRoot":"","sources":["../../src/notation/lodExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Name Shortener — shortest-unambiguous-name within scope
3
+ *
4
+ * Given a set of display names in a subgraph, shorten them to the
5
+ * minimum unique suffix. For example:
6
+ *
7
+ * auth/login.ts -> UserDB.findByEmail → UserDB.findByEmail
8
+ * auth/login.ts -> createToken → createToken
9
+ * auth/utils.ts -> createToken → utils:createToken
10
+ *
11
+ * Phase 4 feature — placeholder for future implementation.
12
+ *
13
+ * @module notation/nameShortener
14
+ */
15
+ /**
16
+ * Shorten a display name to its shortest unambiguous form
17
+ * within the given set of all names.
18
+ *
19
+ * Current implementation: return name as-is (no shortening).
20
+ */
21
+ export declare function shortenName(name: string, _allNames: string[]): string;
22
+ //# sourceMappingURL=nameShortener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nameShortener.d.ts","sourceRoot":"","sources":["../../src/notation/nameShortener.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAErE"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Name Shortener — shortest-unambiguous-name within scope
3
+ *
4
+ * Given a set of display names in a subgraph, shorten them to the
5
+ * minimum unique suffix. For example:
6
+ *
7
+ * auth/login.ts -> UserDB.findByEmail → UserDB.findByEmail
8
+ * auth/login.ts -> createToken → createToken
9
+ * auth/utils.ts -> createToken → utils:createToken
10
+ *
11
+ * Phase 4 feature — placeholder for future implementation.
12
+ *
13
+ * @module notation/nameShortener
14
+ */
15
+ /**
16
+ * Shorten a display name to its shortest unambiguous form
17
+ * within the given set of all names.
18
+ *
19
+ * Current implementation: return name as-is (no shortening).
20
+ */
21
+ export function shortenName(name, _allNames) {
22
+ return name;
23
+ }
24
+ //# sourceMappingURL=nameShortener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nameShortener.js","sourceRoot":"","sources":["../../src/notation/nameShortener.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,SAAmB;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Perspective Presets — archetype filters for describe tool
3
+ *
4
+ * Shared between MCP and CLI to keep perspectives in sync.
5
+ *
6
+ * @module notation/perspectives
7
+ */
8
+ import type { Archetype } from './types.js';
9
+ /** Perspective presets map to archetype filters */
10
+ export declare const PERSPECTIVES: Record<string, Archetype[]>;
11
+ //# sourceMappingURL=perspectives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perspectives.d.ts","sourceRoot":"","sources":["../../src/notation/perspectives.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,mDAAmD;AACnD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAMpD,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Perspective Presets — archetype filters for describe tool
3
+ *
4
+ * Shared between MCP and CLI to keep perspectives in sync.
5
+ *
6
+ * @module notation/perspectives
7
+ */
8
+ /** Perspective presets map to archetype filters */
9
+ export const PERSPECTIVES = {
10
+ security: ['write', 'exception'],
11
+ data: ['flow_out', 'flow_in', 'write'],
12
+ errors: ['exception'],
13
+ api: ['flow_out', 'publishes', 'depends'],
14
+ events: ['publishes'],
15
+ };
16
+ //# sourceMappingURL=perspectives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perspectives.js","sourceRoot":"","sources":["../../src/notation/perspectives.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,mDAAmD;AACnD,MAAM,CAAC,MAAM,YAAY,GAAgC;IACvD,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAChC,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC;IACtC,MAAM,EAAE,CAAC,WAAW,CAAC;IACrB,GAAG,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,SAAS,CAAC;IACzC,MAAM,EAAE,CAAC,WAAW,CAAC;CACtB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Notation Renderer — pure function: SubgraphData → DSL string
3
+ *
4
+ * Pipeline:
5
+ * 1. Classify edges via EDGE_ARCHETYPE_MAP
6
+ * 2. Separate containment from operator edges
7
+ * 3. Group operator edges by source node
8
+ * 4. Sort lines by sortOrder
9
+ * 5. Merge same-operator same-verb targets
10
+ * 6. Serialize to indented DSL text
11
+ *
12
+ * @module notation/renderer
13
+ */
14
+ import type { DescribeOptions, SubgraphData } from './types.js';
15
+ /**
16
+ * Render a subgraph as compact DSL notation.
17
+ *
18
+ * Example output:
19
+ * ```
20
+ * login {
21
+ * o- imports bcrypt
22
+ * > calls UserDB.findByEmail, createToken
23
+ * < reads config.auth
24
+ * => writes session
25
+ * >x throws AuthError
26
+ * ~>> emits 'auth:login'
27
+ * }
28
+ * ```
29
+ */
30
+ export declare function renderNotation(input: SubgraphData, options?: DescribeOptions): string;
31
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/notation/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,eAAe,EAA+B,YAAY,EAAE,MAAM,YAAY,CAAC;AAK7F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAMR"}
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Notation Renderer — pure function: SubgraphData → DSL string
3
+ *
4
+ * Pipeline:
5
+ * 1. Classify edges via EDGE_ARCHETYPE_MAP
6
+ * 2. Separate containment from operator edges
7
+ * 3. Group operator edges by source node
8
+ * 4. Sort lines by sortOrder
9
+ * 5. Merge same-operator same-verb targets
10
+ * 6. Serialize to indented DSL text
11
+ *
12
+ * @module notation/renderer
13
+ */
14
+ import { lookupEdge } from './archetypes.js';
15
+ import { getNodeDisplayName } from '../queries/NodeContext.js';
16
+ import { foldBlocks } from './fold.js';
17
+ /**
18
+ * Render a subgraph as compact DSL notation.
19
+ *
20
+ * Example output:
21
+ * ```
22
+ * login {
23
+ * o- imports bcrypt
24
+ * > calls UserDB.findByEmail, createToken
25
+ * < reads config.auth
26
+ * => writes session
27
+ * >x throws AuthError
28
+ * ~>> emits 'auth:login'
29
+ * }
30
+ * ```
31
+ */
32
+ export function renderNotation(input, options = {}) {
33
+ const { depth = 1, archetypeFilter, budget = 7, includeLocations = false } = options;
34
+ const blocks = buildBlocks(input, depth, archetypeFilter, budget, includeLocations);
35
+ const finalBlocks = depth === 2 ? foldBlocks(blocks) : blocks;
36
+ return serializeBlocks(finalBlocks, 0);
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Block building
40
+ // ---------------------------------------------------------------------------
41
+ function buildBlocks(input, depth, archetypeFilter, budget, includeLocations) {
42
+ const { rootNodes, edges, nodeMap } = input;
43
+ // Index: src → edges, containment edges (src → child node IDs)
44
+ const outgoingBySource = new Map();
45
+ const childrenOf = new Map();
46
+ for (const edge of edges) {
47
+ const mapping = lookupEdge(edge.type);
48
+ if (mapping.archetype === 'contains') {
49
+ // Containment defines tree structure
50
+ if (!childrenOf.has(edge.src))
51
+ childrenOf.set(edge.src, []);
52
+ childrenOf.get(edge.src).push(edge.dst);
53
+ }
54
+ else {
55
+ if (!outgoingBySource.has(edge.src))
56
+ outgoingBySource.set(edge.src, []);
57
+ outgoingBySource.get(edge.src).push(edge);
58
+ }
59
+ }
60
+ // Build set of node IDs that are descendants of LOOP nodes in containment tree
61
+ const insideLoopNodes = buildLoopDescendants(childrenOf, nodeMap);
62
+ const resolvedNames = resolveAnonymousNames(edges, nodeMap);
63
+ return rootNodes.map(node => buildBlock(node, outgoingBySource, childrenOf, nodeMap, depth, archetypeFilter, budget, includeLocations, insideLoopNodes, resolvedNames));
64
+ }
65
+ /**
66
+ * Collect all node IDs that are descendants of LOOP-type nodes in the containment tree.
67
+ * Uses BFS from each LOOP node, traversing containment children recursively.
68
+ */
69
+ function buildLoopDescendants(childrenOf, nodeMap) {
70
+ const result = new Set();
71
+ // Find all LOOP nodes and collect their descendants
72
+ for (const [parentId, children] of childrenOf) {
73
+ const parentNode = nodeMap.get(parentId);
74
+ if (parentNode?.type === 'LOOP') {
75
+ // BFS to collect all descendants of this LOOP node
76
+ const queue = [...children];
77
+ while (queue.length > 0) {
78
+ const id = queue.shift();
79
+ if (result.has(id))
80
+ continue;
81
+ result.add(id);
82
+ const grandchildren = childrenOf.get(id);
83
+ if (grandchildren) {
84
+ queue.push(...grandchildren);
85
+ }
86
+ }
87
+ }
88
+ }
89
+ return result;
90
+ }
91
+ /**
92
+ * Resolve meaningful names for anonymous arrow functions and expressions.
93
+ *
94
+ * Priority:
95
+ * 1. Assignment: `const handler = () => {}` → "handler"
96
+ * 2. Callback: `setRequestHandler(Schema, λ)` → "λ → setRequestHandler(Schema)"
97
+ * 3. Fallback: "λ"
98
+ */
99
+ function resolveAnonymousNames(edges, nodeMap) {
100
+ const resolved = new Map();
101
+ // Reverse index: dstId → edges (for ASSIGNED_FROM and PASSES_ARGUMENT)
102
+ const incomingByDst = new Map();
103
+ // Forward index: srcId → PASSES_ARGUMENT edges (for finding siblings)
104
+ const passArgBySrc = new Map();
105
+ for (const edge of edges) {
106
+ if (edge.type === 'ASSIGNED_FROM' || edge.type === 'PASSES_ARGUMENT') {
107
+ if (!incomingByDst.has(edge.dst))
108
+ incomingByDst.set(edge.dst, []);
109
+ incomingByDst.get(edge.dst).push(edge);
110
+ }
111
+ if (edge.type === 'PASSES_ARGUMENT') {
112
+ if (!passArgBySrc.has(edge.src))
113
+ passArgBySrc.set(edge.src, []);
114
+ passArgBySrc.get(edge.src).push(edge);
115
+ }
116
+ }
117
+ for (const [nodeId, node] of nodeMap) {
118
+ if (node.name !== '<arrow>' && node.name !== '<expression>')
119
+ continue;
120
+ const incoming = incomingByDst.get(nodeId) ?? [];
121
+ // Priority 1: Assignment — const handler = () => {}
122
+ const assignEdge = incoming.find(e => e.type === 'ASSIGNED_FROM');
123
+ if (assignEdge) {
124
+ const srcNode = nodeMap.get(assignEdge.src);
125
+ if (srcNode?.name && srcNode.name !== '<arrow>' && srcNode.name !== '<expression>') {
126
+ resolved.set(nodeId, srcNode.name);
127
+ continue;
128
+ }
129
+ }
130
+ // Priority 2: Callback — setRequestHandler(Schema, λ)
131
+ const passEdge = incoming.find(e => e.type === 'PASSES_ARGUMENT');
132
+ if (passEdge) {
133
+ const callNode = nodeMap.get(passEdge.src);
134
+ const callName = callNode ? getNodeDisplayName(callNode) : null;
135
+ if (callName && callName !== '<arrow>' && callName !== '<expression>' && callName !== 'λ') {
136
+ // Named sibling args (skip other anonymous ones)
137
+ const allSiblings = passArgBySrc.get(passEdge.src) ?? [];
138
+ const namedSiblings = allSiblings
139
+ .filter(e => e.dst !== nodeId)
140
+ .map(e => {
141
+ const argNode = nodeMap.get(e.dst);
142
+ if (!argNode?.name)
143
+ return null;
144
+ if (argNode.name === '<arrow>' || argNode.name === '<expression>')
145
+ return null;
146
+ return argNode.name;
147
+ })
148
+ .filter((n) => n !== null);
149
+ // Multiple lambdas in same call → add index to distinguish
150
+ const lambdaCount = allSiblings.filter(e => {
151
+ const n = nodeMap.get(e.dst);
152
+ return n && (n.name === '<arrow>' || n.name === '<expression>');
153
+ }).length;
154
+ const indexSuffix = lambdaCount > 1
155
+ ? String(passEdge.metadata?.index ?? passEdge.metadata?.argIndex ?? '')
156
+ : '';
157
+ const argStr = namedSiblings.length > 0 ? `(${namedSiblings.join(', ')})` : '';
158
+ resolved.set(nodeId, `λ${indexSuffix} → ${callName}${argStr}`);
159
+ continue;
160
+ }
161
+ }
162
+ // Priority 3: Fallback
163
+ resolved.set(nodeId, 'λ');
164
+ }
165
+ return resolved;
166
+ }
167
+ function buildBlock(node, outgoingBySource, childrenOf, nodeMap, depth, archetypeFilter, budget, includeLocations, insideLoopNodes, resolvedNames) {
168
+ const displayName = resolvedNames.get(node.id) ?? getNodeDisplayName(node);
169
+ const location = includeLocations && node.file
170
+ ? `${node.file}${node.line ? ':' + node.line : ''}`
171
+ : undefined;
172
+ // LOD 0: names only — no edges, no children
173
+ if (depth <= 0) {
174
+ return { nodeId: node.id, displayName, nodeType: node.type, lines: [], children: [], location };
175
+ }
176
+ // LOD 1+: build edge lines
177
+ const nodeEdges = outgoingBySource.get(node.id) ?? [];
178
+ const lines = buildLines(nodeEdges, nodeMap, archetypeFilter, budget, resolvedNames);
179
+ // Apply [] loop modifier if this node is inside a LOOP
180
+ // Combines with existing modifiers: [] ?? > calls foo
181
+ if (insideLoopNodes.has(node.id)) {
182
+ for (const line of lines) {
183
+ line.modifier = line.modifier ? `[] ${line.modifier}` : '[]';
184
+ }
185
+ }
186
+ // LOD 2+: recurse into contained children
187
+ let children = [];
188
+ if (depth >= 2) {
189
+ const childIds = childrenOf.get(node.id) ?? [];
190
+ children = childIds
191
+ .map(id => nodeMap.get(id))
192
+ .filter((n) => n != null)
193
+ .map(child => buildBlock(child, outgoingBySource, childrenOf, nodeMap, depth - 1, archetypeFilter, budget, includeLocations, insideLoopNodes, resolvedNames));
194
+ }
195
+ return { nodeId: node.id, displayName, nodeType: node.type, lines, children, location };
196
+ }
197
+ // ---------------------------------------------------------------------------
198
+ // Line building — group, sort, merge
199
+ // ---------------------------------------------------------------------------
200
+ function buildLines(edges, nodeMap, archetypeFilter, budget, resolvedNames) {
201
+ // Group by modifier+operator+verb key (modifier separates certain from uncertain)
202
+ const groups = new Map();
203
+ for (const edge of edges) {
204
+ const mapping = lookupEdge(edge.type);
205
+ // Apply archetype filter
206
+ if (archetypeFilter && !archetypeFilter.includes(mapping.archetype))
207
+ continue;
208
+ const targetNode = nodeMap.get(edge.dst);
209
+ const targetName = resolvedNames.get(edge.dst) ?? (targetNode ? getNodeDisplayName(targetNode) : edge.dst);
210
+ // Detect dynamic/uncertain edges
211
+ const modifier = isDynamicEdge(edge) ? '??' : undefined;
212
+ const key = `${modifier ?? ''}|${mapping.operator}|${mapping.verb}`;
213
+ if (!groups.has(key)) {
214
+ groups.set(key, {
215
+ operator: mapping.operator,
216
+ verb: mapping.verb,
217
+ targets: [],
218
+ sortOrder: mapping.sortOrder,
219
+ modifier,
220
+ });
221
+ }
222
+ groups.get(key).targets.push(targetName);
223
+ }
224
+ // Sort by sortOrder
225
+ const sorted = Array.from(groups.values()).sort((a, b) => a.sortOrder - b.sortOrder);
226
+ // Apply budget: show top-N, summarize rest
227
+ if (sorted.length > budget) {
228
+ const shown = sorted.slice(0, budget);
229
+ const hidden = sorted.slice(budget);
230
+ const hiddenCount = hidden.reduce((sum, g) => sum + g.targets.length, 0);
231
+ shown.push({
232
+ operator: '',
233
+ verb: `...+${hiddenCount} more`,
234
+ targets: [],
235
+ sortOrder: 999,
236
+ });
237
+ return shown.map(g => ({
238
+ operator: g.operator,
239
+ verb: g.verb,
240
+ targets: g.targets,
241
+ sortOrder: g.sortOrder,
242
+ modifier: g.modifier,
243
+ }));
244
+ }
245
+ return sorted.map(g => ({
246
+ operator: g.operator,
247
+ verb: g.verb,
248
+ targets: g.targets,
249
+ sortOrder: g.sortOrder,
250
+ modifier: g.modifier,
251
+ }));
252
+ }
253
+ // ---------------------------------------------------------------------------
254
+ // Edge metadata helpers
255
+ // ---------------------------------------------------------------------------
256
+ /**
257
+ * Check if an edge is dynamic/uncertain based on its metadata.
258
+ *
259
+ * An edge is dynamic/uncertain if any of these hold:
260
+ * - metadata.resolved === false (unresolved reference)
261
+ * - metadata.confidence exists and is < 1.0 (low-confidence inference)
262
+ * - metadata.dynamic === true (dynamic dispatch)
263
+ */
264
+ function isDynamicEdge(edge) {
265
+ const meta = edge.metadata;
266
+ if (!meta)
267
+ return false;
268
+ if (meta.resolved === false)
269
+ return true;
270
+ if (typeof meta.confidence === 'number' && meta.confidence < 1.0)
271
+ return true;
272
+ if (meta.dynamic === true)
273
+ return true;
274
+ return false;
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // Serialization
278
+ // ---------------------------------------------------------------------------
279
+ function serializeBlocks(blocks, indentLevel) {
280
+ return blocks.map(block => serializeBlock(block, indentLevel)).join('\n');
281
+ }
282
+ function serializeBlock(block, indentLevel) {
283
+ const indent = ' '.repeat(indentLevel);
284
+ const hasContent = block.lines.length > 0 || block.children.length > 0;
285
+ // Header
286
+ const loc = block.location ? ` (${block.location})` : '';
287
+ let result;
288
+ if (!hasContent) {
289
+ // Leaf node — just name
290
+ result = `${indent}${block.displayName}${loc}`;
291
+ }
292
+ else {
293
+ result = `${indent}${block.displayName}${loc} {\n`;
294
+ // Lines
295
+ for (const line of block.lines) {
296
+ result += serializeLine(line, indentLevel + 1);
297
+ }
298
+ // Children
299
+ if (block.children.length > 0) {
300
+ result += serializeBlocks(block.children, indentLevel + 1) + '\n';
301
+ }
302
+ result += `${indent}}`;
303
+ }
304
+ return result;
305
+ }
306
+ function serializeLine(line, indentLevel) {
307
+ const indent = ' '.repeat(indentLevel);
308
+ const mod = line.modifier ? `${line.modifier} ` : '';
309
+ const prefix = line.operator ? `${line.operator} ` : '';
310
+ if (line.targets.length === 0) {
311
+ return `${indent}${mod}${prefix}${line.verb}\n`;
312
+ }
313
+ return `${indent}${mod}${prefix}${line.verb} ${line.targets.join(', ')}\n`;
314
+ }
315
+ //# sourceMappingURL=renderer.js.map