@opensip-cli/dashboard 0.1.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 (309) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/__tests__/catalog-provenance.test.d.ts +11 -0
  5. package/dist/__tests__/catalog-provenance.test.d.ts.map +1 -0
  6. package/dist/__tests__/catalog-provenance.test.js +130 -0
  7. package/dist/__tests__/catalog-provenance.test.js.map +1 -0
  8. package/dist/__tests__/coupling-attribution.test.d.ts +9 -0
  9. package/dist/__tests__/coupling-attribution.test.d.ts.map +1 -0
  10. package/dist/__tests__/coupling-attribution.test.js +99 -0
  11. package/dist/__tests__/coupling-attribution.test.js.map +1 -0
  12. package/dist/__tests__/dashboard-bundle-weight.test.d.ts +16 -0
  13. package/dist/__tests__/dashboard-bundle-weight.test.d.ts.map +1 -0
  14. package/dist/__tests__/dashboard-bundle-weight.test.js +73 -0
  15. package/dist/__tests__/dashboard-bundle-weight.test.js.map +1 -0
  16. package/dist/__tests__/dashboard-cell-containment.test.d.ts +2 -0
  17. package/dist/__tests__/dashboard-cell-containment.test.d.ts.map +1 -0
  18. package/dist/__tests__/dashboard-cell-containment.test.js +49 -0
  19. package/dist/__tests__/dashboard-cell-containment.test.js.map +1 -0
  20. package/dist/__tests__/dashboard-cytoscape-vendor.test.d.ts +10 -0
  21. package/dist/__tests__/dashboard-cytoscape-vendor.test.d.ts.map +1 -0
  22. package/dist/__tests__/dashboard-cytoscape-vendor.test.js +40 -0
  23. package/dist/__tests__/dashboard-cytoscape-vendor.test.js.map +1 -0
  24. package/dist/__tests__/dashboard-editor-link.test.d.ts +5 -0
  25. package/dist/__tests__/dashboard-editor-link.test.d.ts.map +1 -0
  26. package/dist/__tests__/dashboard-editor-link.test.js +36 -0
  27. package/dist/__tests__/dashboard-editor-link.test.js.map +1 -0
  28. package/dist/__tests__/dashboard-filters.test.d.ts +9 -0
  29. package/dist/__tests__/dashboard-filters.test.d.ts.map +1 -0
  30. package/dist/__tests__/dashboard-filters.test.js +95 -0
  31. package/dist/__tests__/dashboard-filters.test.js.map +1 -0
  32. package/dist/__tests__/dashboard-function-card-singleton.test.d.ts +9 -0
  33. package/dist/__tests__/dashboard-function-card-singleton.test.d.ts.map +1 -0
  34. package/dist/__tests__/dashboard-function-card-singleton.test.js +87 -0
  35. package/dist/__tests__/dashboard-function-card-singleton.test.js.map +1 -0
  36. package/dist/__tests__/dashboard-function-card.test.d.ts +10 -0
  37. package/dist/__tests__/dashboard-function-card.test.d.ts.map +1 -0
  38. package/dist/__tests__/dashboard-function-card.test.js +403 -0
  39. package/dist/__tests__/dashboard-function-card.test.js.map +1 -0
  40. package/dist/__tests__/dashboard-function-row.test.d.ts +11 -0
  41. package/dist/__tests__/dashboard-function-row.test.d.ts.map +1 -0
  42. package/dist/__tests__/dashboard-function-row.test.js +101 -0
  43. package/dist/__tests__/dashboard-function-row.test.js.map +1 -0
  44. package/dist/__tests__/dashboard-generator-graph-catalog.test.d.ts +9 -0
  45. package/dist/__tests__/dashboard-generator-graph-catalog.test.d.ts.map +1 -0
  46. package/dist/__tests__/dashboard-generator-graph-catalog.test.js +75 -0
  47. package/dist/__tests__/dashboard-generator-graph-catalog.test.js.map +1 -0
  48. package/dist/__tests__/dashboard-graph-offline.integration.test.d.ts +13 -0
  49. package/dist/__tests__/dashboard-graph-offline.integration.test.d.ts.map +1 -0
  50. package/dist/__tests__/dashboard-graph-offline.integration.test.js +55 -0
  51. package/dist/__tests__/dashboard-graph-offline.integration.test.js.map +1 -0
  52. package/dist/__tests__/dashboard-graph-scc.test.d.ts +17 -0
  53. package/dist/__tests__/dashboard-graph-scc.test.d.ts.map +1 -0
  54. package/dist/__tests__/dashboard-graph-scc.test.js +89 -0
  55. package/dist/__tests__/dashboard-graph-scc.test.js.map +1 -0
  56. package/dist/__tests__/dashboard-graph-view-model.test.d.ts +12 -0
  57. package/dist/__tests__/dashboard-graph-view-model.test.d.ts.map +1 -0
  58. package/dist/__tests__/dashboard-graph-view-model.test.js +331 -0
  59. package/dist/__tests__/dashboard-graph-view-model.test.js.map +1 -0
  60. package/dist/__tests__/dashboard-help-drawer.test.d.ts +9 -0
  61. package/dist/__tests__/dashboard-help-drawer.test.d.ts.map +1 -0
  62. package/dist/__tests__/dashboard-help-drawer.test.js +101 -0
  63. package/dist/__tests__/dashboard-help-drawer.test.js.map +1 -0
  64. package/dist/__tests__/dashboard-html.test.d.ts +2 -0
  65. package/dist/__tests__/dashboard-html.test.d.ts.map +1 -0
  66. package/dist/__tests__/dashboard-html.test.js +169 -0
  67. package/dist/__tests__/dashboard-html.test.js.map +1 -0
  68. package/dist/__tests__/dashboard-indexes.test.d.ts +9 -0
  69. package/dist/__tests__/dashboard-indexes.test.d.ts.map +1 -0
  70. package/dist/__tests__/dashboard-indexes.test.js +211 -0
  71. package/dist/__tests__/dashboard-indexes.test.js.map +1 -0
  72. package/dist/__tests__/dashboard-path-utils.test.d.ts +6 -0
  73. package/dist/__tests__/dashboard-path-utils.test.d.ts.map +1 -0
  74. package/dist/__tests__/dashboard-path-utils.test.js +54 -0
  75. package/dist/__tests__/dashboard-path-utils.test.js.map +1 -0
  76. package/dist/__tests__/dashboard-search.test.d.ts +5 -0
  77. package/dist/__tests__/dashboard-search.test.d.ts.map +1 -0
  78. package/dist/__tests__/dashboard-search.test.js +46 -0
  79. package/dist/__tests__/dashboard-search.test.js.map +1 -0
  80. package/dist/__tests__/dashboard-sessions.test.d.ts +14 -0
  81. package/dist/__tests__/dashboard-sessions.test.d.ts.map +1 -0
  82. package/dist/__tests__/dashboard-sessions.test.js +330 -0
  83. package/dist/__tests__/dashboard-sessions.test.js.map +1 -0
  84. package/dist/__tests__/dashboard-trace.test.d.ts +5 -0
  85. package/dist/__tests__/dashboard-trace.test.d.ts.map +1 -0
  86. package/dist/__tests__/dashboard-trace.test.js +147 -0
  87. package/dist/__tests__/dashboard-trace.test.js.map +1 -0
  88. package/dist/__tests__/dashboard-validation.integration.test.d.ts +14 -0
  89. package/dist/__tests__/dashboard-validation.integration.test.d.ts.map +1 -0
  90. package/dist/__tests__/dashboard-validation.integration.test.js +221 -0
  91. package/dist/__tests__/dashboard-validation.integration.test.js.map +1 -0
  92. package/dist/__tests__/dashboard-view-conformance.test.d.ts +12 -0
  93. package/dist/__tests__/dashboard-view-conformance.test.d.ts.map +1 -0
  94. package/dist/__tests__/dashboard-view-conformance.test.js +58 -0
  95. package/dist/__tests__/dashboard-view-conformance.test.js.map +1 -0
  96. package/dist/__tests__/dashboard-view-coupling.test.d.ts +7 -0
  97. package/dist/__tests__/dashboard-view-coupling.test.d.ts.map +1 -0
  98. package/dist/__tests__/dashboard-view-coupling.test.js +381 -0
  99. package/dist/__tests__/dashboard-view-coupling.test.js.map +1 -0
  100. package/dist/__tests__/dashboard-view-distribution.test.d.ts +10 -0
  101. package/dist/__tests__/dashboard-view-distribution.test.d.ts.map +1 -0
  102. package/dist/__tests__/dashboard-view-distribution.test.js +272 -0
  103. package/dist/__tests__/dashboard-view-distribution.test.js.map +1 -0
  104. package/dist/__tests__/dashboard-view-graph.test.d.ts +13 -0
  105. package/dist/__tests__/dashboard-view-graph.test.d.ts.map +1 -0
  106. package/dist/__tests__/dashboard-view-graph.test.js +332 -0
  107. package/dist/__tests__/dashboard-view-graph.test.js.map +1 -0
  108. package/dist/__tests__/dashboard-view-template.test.d.ts +21 -0
  109. package/dist/__tests__/dashboard-view-template.test.d.ts.map +1 -0
  110. package/dist/__tests__/dashboard-view-template.test.js +153 -0
  111. package/dist/__tests__/dashboard-view-template.test.js.map +1 -0
  112. package/dist/__tests__/dashboard.test.d.ts +2 -0
  113. package/dist/__tests__/dashboard.test.d.ts.map +1 -0
  114. package/dist/__tests__/dashboard.test.js +129 -0
  115. package/dist/__tests__/dashboard.test.js.map +1 -0
  116. package/dist/__tests__/graph-tab.test.d.ts +10 -0
  117. package/dist/__tests__/graph-tab.test.d.ts.map +1 -0
  118. package/dist/__tests__/graph-tab.test.js +76 -0
  119. package/dist/__tests__/graph-tab.test.js.map +1 -0
  120. package/dist/checks.d.ts +7 -0
  121. package/dist/checks.d.ts.map +1 -0
  122. package/dist/checks.js +283 -0
  123. package/dist/checks.js.map +1 -0
  124. package/dist/code-paths/__tests__/views-registry.test.d.ts +13 -0
  125. package/dist/code-paths/__tests__/views-registry.test.d.ts.map +1 -0
  126. package/dist/code-paths/__tests__/views-registry.test.js +39 -0
  127. package/dist/code-paths/__tests__/views-registry.test.js.map +1 -0
  128. package/dist/code-paths/catalog-provenance.d.ts +22 -0
  129. package/dist/code-paths/catalog-provenance.d.ts.map +1 -0
  130. package/dist/code-paths/catalog-provenance.js +108 -0
  131. package/dist/code-paths/catalog-provenance.js.map +1 -0
  132. package/dist/code-paths/catalog-recipes-tables.d.ts +11 -0
  133. package/dist/code-paths/catalog-recipes-tables.d.ts.map +1 -0
  134. package/dist/code-paths/catalog-recipes-tables.js +86 -0
  135. package/dist/code-paths/catalog-recipes-tables.js.map +1 -0
  136. package/dist/code-paths/cytoscape-vendor.d.ts +27 -0
  137. package/dist/code-paths/cytoscape-vendor.d.ts.map +1 -0
  138. package/dist/code-paths/cytoscape-vendor.js +68 -0
  139. package/dist/code-paths/cytoscape-vendor.js.map +1 -0
  140. package/dist/code-paths/editor-link.d.ts +10 -0
  141. package/dist/code-paths/editor-link.d.ts.map +1 -0
  142. package/dist/code-paths/editor-link.js +20 -0
  143. package/dist/code-paths/editor-link.js.map +1 -0
  144. package/dist/code-paths/filters.d.ts +19 -0
  145. package/dist/code-paths/filters.d.ts.map +1 -0
  146. package/dist/code-paths/filters.js +47 -0
  147. package/dist/code-paths/filters.js.map +1 -0
  148. package/dist/code-paths/function-card.d.ts +15 -0
  149. package/dist/code-paths/function-card.d.ts.map +1 -0
  150. package/dist/code-paths/function-card.js +169 -0
  151. package/dist/code-paths/function-card.js.map +1 -0
  152. package/dist/code-paths/function-row.d.ts +17 -0
  153. package/dist/code-paths/function-row.d.ts.map +1 -0
  154. package/dist/code-paths/function-row.js +77 -0
  155. package/dist/code-paths/function-row.js.map +1 -0
  156. package/dist/code-paths/graph-controls.d.ts +27 -0
  157. package/dist/code-paths/graph-controls.d.ts.map +1 -0
  158. package/dist/code-paths/graph-controls.js +257 -0
  159. package/dist/code-paths/graph-controls.js.map +1 -0
  160. package/dist/code-paths/graph-scc.d.ts +32 -0
  161. package/dist/code-paths/graph-scc.d.ts.map +1 -0
  162. package/dist/code-paths/graph-scc.js +136 -0
  163. package/dist/code-paths/graph-scc.js.map +1 -0
  164. package/dist/code-paths/graph-stylesheet.d.ts +22 -0
  165. package/dist/code-paths/graph-stylesheet.d.ts.map +1 -0
  166. package/dist/code-paths/graph-stylesheet.js +121 -0
  167. package/dist/code-paths/graph-stylesheet.js.map +1 -0
  168. package/dist/code-paths/graph-view-model.d.ts +120 -0
  169. package/dist/code-paths/graph-view-model.d.ts.map +1 -0
  170. package/dist/code-paths/graph-view-model.js +199 -0
  171. package/dist/code-paths/graph-view-model.js.map +1 -0
  172. package/dist/code-paths/help-drawer.d.ts +18 -0
  173. package/dist/code-paths/help-drawer.d.ts.map +1 -0
  174. package/dist/code-paths/help-drawer.js +54 -0
  175. package/dist/code-paths/help-drawer.js.map +1 -0
  176. package/dist/code-paths/indexes.d.ts +28 -0
  177. package/dist/code-paths/indexes.d.ts.map +1 -0
  178. package/dist/code-paths/indexes.js +97 -0
  179. package/dist/code-paths/indexes.js.map +1 -0
  180. package/dist/code-paths/path-utils.d.ts +15 -0
  181. package/dist/code-paths/path-utils.d.ts.map +1 -0
  182. package/dist/code-paths/path-utils.js +47 -0
  183. package/dist/code-paths/path-utils.js.map +1 -0
  184. package/dist/code-paths/search.d.ts +14 -0
  185. package/dist/code-paths/search.d.ts.map +1 -0
  186. package/dist/code-paths/search.js +54 -0
  187. package/dist/code-paths/search.js.map +1 -0
  188. package/dist/code-paths/trace.d.ts +11 -0
  189. package/dist/code-paths/trace.d.ts.map +1 -0
  190. package/dist/code-paths/trace.js +60 -0
  191. package/dist/code-paths/trace.js.map +1 -0
  192. package/dist/code-paths/view-coupling.d.ts +22 -0
  193. package/dist/code-paths/view-coupling.d.ts.map +1 -0
  194. package/dist/code-paths/view-coupling.js +218 -0
  195. package/dist/code-paths/view-coupling.js.map +1 -0
  196. package/dist/code-paths/view-distribution.d.ts +20 -0
  197. package/dist/code-paths/view-distribution.d.ts.map +1 -0
  198. package/dist/code-paths/view-distribution.js +82 -0
  199. package/dist/code-paths/view-distribution.js.map +1 -0
  200. package/dist/code-paths/view-graph.d.ts +35 -0
  201. package/dist/code-paths/view-graph.d.ts.map +1 -0
  202. package/dist/code-paths/view-graph.js +379 -0
  203. package/dist/code-paths/view-graph.js.map +1 -0
  204. package/dist/code-paths/view-template.d.ts +154 -0
  205. package/dist/code-paths/view-template.d.ts.map +1 -0
  206. package/dist/code-paths/view-template.js +218 -0
  207. package/dist/code-paths/view-template.js.map +1 -0
  208. package/dist/code-paths/views-registry.d.ts +13 -0
  209. package/dist/code-paths/views-registry.d.ts.map +1 -0
  210. package/dist/code-paths/views-registry.js +53 -0
  211. package/dist/code-paths/views-registry.js.map +1 -0
  212. package/dist/code-paths.d.ts +69 -0
  213. package/dist/code-paths.d.ts.map +1 -0
  214. package/dist/code-paths.js +356 -0
  215. package/dist/code-paths.js.map +1 -0
  216. package/dist/css/cards.d.ts +9 -0
  217. package/dist/css/cards.d.ts.map +1 -0
  218. package/dist/css/cards.js +36 -0
  219. package/dist/css/cards.js.map +1 -0
  220. package/dist/css/code-paths.d.ts +9 -0
  221. package/dist/css/code-paths.d.ts.map +1 -0
  222. package/dist/css/code-paths.js +111 -0
  223. package/dist/css/code-paths.js.map +1 -0
  224. package/dist/css/data-table.d.ts +12 -0
  225. package/dist/css/data-table.d.ts.map +1 -0
  226. package/dist/css/data-table.js +103 -0
  227. package/dist/css/data-table.js.map +1 -0
  228. package/dist/css/function-card.d.ts +6 -0
  229. package/dist/css/function-card.d.ts.map +1 -0
  230. package/dist/css/function-card.js +26 -0
  231. package/dist/css/function-card.js.map +1 -0
  232. package/dist/css/help-drawer.d.ts +6 -0
  233. package/dist/css/help-drawer.d.ts.map +1 -0
  234. package/dist/css/help-drawer.js +22 -0
  235. package/dist/css/help-drawer.js.map +1 -0
  236. package/dist/css/tabs.d.ts +9 -0
  237. package/dist/css/tabs.d.ts.map +1 -0
  238. package/dist/css/tabs.js +28 -0
  239. package/dist/css/tabs.js.map +1 -0
  240. package/dist/css/theme.d.ts +8 -0
  241. package/dist/css/theme.d.ts.map +1 -0
  242. package/dist/css/theme.js +34 -0
  243. package/dist/css/theme.js.map +1 -0
  244. package/dist/css.d.ts +13 -0
  245. package/dist/css.d.ts.map +1 -0
  246. package/dist/css.js +30 -0
  247. package/dist/css.js.map +1 -0
  248. package/dist/generator.d.ts +33 -0
  249. package/dist/generator.d.ts.map +1 -0
  250. package/dist/generator.js +161 -0
  251. package/dist/generator.js.map +1 -0
  252. package/dist/index.d.ts +21 -0
  253. package/dist/index.d.ts.map +1 -0
  254. package/dist/index.js +20 -0
  255. package/dist/index.js.map +1 -0
  256. package/dist/overview.d.ts +13 -0
  257. package/dist/overview.d.ts.map +1 -0
  258. package/dist/overview.js +91 -0
  259. package/dist/overview.js.map +1 -0
  260. package/dist/recipes.d.ts +6 -0
  261. package/dist/recipes.d.ts.map +1 -0
  262. package/dist/recipes.js +68 -0
  263. package/dist/recipes.js.map +1 -0
  264. package/dist/sessions.d.ts +6 -0
  265. package/dist/sessions.d.ts.map +1 -0
  266. package/dist/sessions.js +288 -0
  267. package/dist/sessions.js.map +1 -0
  268. package/dist/shared/el.d.ts +13 -0
  269. package/dist/shared/el.d.ts.map +1 -0
  270. package/dist/shared/el.js +27 -0
  271. package/dist/shared/el.js.map +1 -0
  272. package/dist/shared/pagination.d.ts +15 -0
  273. package/dist/shared/pagination.d.ts.map +1 -0
  274. package/dist/shared/pagination.js +113 -0
  275. package/dist/shared/pagination.js.map +1 -0
  276. package/dist/shared/sortable.d.ts +14 -0
  277. package/dist/shared/sortable.d.ts.map +1 -0
  278. package/dist/shared/sortable.js +101 -0
  279. package/dist/shared/sortable.js.map +1 -0
  280. package/dist/shared/tab-activators.d.ts +16 -0
  281. package/dist/shared/tab-activators.d.ts.map +1 -0
  282. package/dist/shared/tab-activators.js +33 -0
  283. package/dist/shared/tab-activators.js.map +1 -0
  284. package/dist/shared/tab-bar.d.ts +8 -0
  285. package/dist/shared/tab-bar.d.ts.map +1 -0
  286. package/dist/shared/tab-bar.js +20 -0
  287. package/dist/shared/tab-bar.js.map +1 -0
  288. package/dist/shared.d.ts +26 -0
  289. package/dist/shared.d.ts.map +1 -0
  290. package/dist/shared.js +39 -0
  291. package/dist/shared.js.map +1 -0
  292. package/dist/subtab-bar.d.ts +23 -0
  293. package/dist/subtab-bar.d.ts.map +1 -0
  294. package/dist/subtab-bar.js +77 -0
  295. package/dist/subtab-bar.js.map +1 -0
  296. package/dist/tool-tab-registry.d.ts +76 -0
  297. package/dist/tool-tab-registry.d.ts.map +1 -0
  298. package/dist/tool-tab-registry.js +44 -0
  299. package/dist/tool-tab-registry.js.map +1 -0
  300. package/dist/tool-tabs-registrations.d.ts +19 -0
  301. package/dist/tool-tabs-registrations.d.ts.map +1 -0
  302. package/dist/tool-tabs-registrations.js +46 -0
  303. package/dist/tool-tabs-registrations.js.map +1 -0
  304. package/dist/tool-tabs.d.ts +12 -0
  305. package/dist/tool-tabs.d.ts.map +1 -0
  306. package/dist/tool-tabs.js +80 -0
  307. package/dist/tool-tabs.js.map +1 -0
  308. package/dist/vendor/cytoscape-bundle.js +600 -0
  309. package/package.json +52 -0
package/dist/checks.js ADDED
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Checks catalog rendering — browsable catalog of checks with run stats.
3
+ * Reusable: renderChecksCatalog(container, catalogData) can be called from any panel.
4
+ * Returns JS code as a string.
5
+ */
6
+ export function dashboardChecksJs() {
7
+ return `
8
+ // =======================================================
9
+ // CHECKS CATALOG
10
+ // =======================================================
11
+
12
+ function computeCheckStats() {
13
+ const stats = {};
14
+ for (const s of sessions) {
15
+ // Per-session detail lives in the tool-owned opaque payload; fitness
16
+ // sessions carry { summary, checks }. Sessions without checks (graph,
17
+ // sim) contribute nothing here.
18
+ const checks = (s.payload && s.payload.checks) || [];
19
+ for (const ch of checks) {
20
+ if (!stats[ch.checkSlug]) stats[ch.checkSlug] = { runs: 0, passed: 0, failed: 0, lastRun: null };
21
+ const st = stats[ch.checkSlug];
22
+ st.runs++;
23
+ if (ch.passed) st.passed++; else st.failed++;
24
+ if (!st.lastRun || s.startedAt > st.lastRun) st.lastRun = s.startedAt;
25
+ }
26
+ }
27
+ return stats;
28
+ }
29
+ const checkStats = computeCheckStats();
30
+
31
+ /** Render longDescription as DOM nodes with bold and code formatting. Safe — no innerHTML. */
32
+ function renderLongDesc(text) {
33
+ const container = document.createElement('div');
34
+ container.className = 'check-long-desc';
35
+ if (!text) return container;
36
+ const parts = text.split(/(\\*\\*[^*]+\\*\\*|\\\`[^\\\`]+\\\`|\\n)/g);
37
+ parts.forEach(part => {
38
+ if (part === '\\n') {
39
+ container.appendChild(document.createElement('br'));
40
+ } else if (part.startsWith('**') && part.endsWith('**')) {
41
+ const strong = document.createElement('strong');
42
+ strong.textContent = part.slice(2, -2);
43
+ container.appendChild(strong);
44
+ } else if (part.startsWith('\\\`') && part.endsWith('\\\`')) {
45
+ const code = document.createElement('code');
46
+ code.textContent = part.slice(1, -1);
47
+ container.appendChild(code);
48
+ } else {
49
+ container.appendChild(document.createTextNode(part));
50
+ }
51
+ });
52
+ return container;
53
+ }
54
+
55
+ /**
56
+ * Render a check catalog table into any container element.
57
+ * @param panel - DOM element to render into
58
+ * @param catalogData - array of check catalog entries
59
+ */
60
+ function renderChecksCatalog(panel, catalogData) {
61
+ if (!catalogData.length) {
62
+ panel.appendChild(el('div', {class:'empty', text:'No checks registered.'}));
63
+ return;
64
+ }
65
+
66
+ const allTags = new Set();
67
+ catalogData.forEach(c => (c.tags || []).forEach(t => allTags.add(t)));
68
+ const sortedTags = Array.from(allTags).sort();
69
+
70
+ // Filter bar
71
+ const filterBar = el('div', {class:'filter-bar'});
72
+ const searchInput = el('input', {class:'search-input', type:'text', placeholder:'Search checks...'});
73
+ const tagSelect = el('select', {class:'filter-select'});
74
+ tagSelect.appendChild(el('option', {value:'', text:'All tags'}));
75
+ sortedTags.forEach(t => tagSelect.appendChild(el('option', {value:t, text:t})));
76
+ const sourceSelect = el('select', {class:'filter-select'});
77
+ ['', 'built-in', 'community'].forEach(v => {
78
+ sourceSelect.appendChild(el('option', {value:v, text: v || 'All sources'}));
79
+ });
80
+ filterBar.appendChild(searchInput);
81
+ filterBar.appendChild(tagSelect);
82
+ filterBar.appendChild(sourceSelect);
83
+ panel.appendChild(filterBar);
84
+
85
+ // Stats summary
86
+ const totalChecks = catalogData.length;
87
+ const builtinCount = catalogData.filter(c => c.source === 'built-in').length;
88
+ const communityCount = catalogData.filter(c => c.source === 'community').length;
89
+ const statsRow = el('div', {style:'display:flex;gap:16px;margin-bottom:16px;font-size:13px;color:var(--text-muted)'});
90
+ statsRow.appendChild(el('span', {text: totalChecks + ' total checks'}));
91
+ statsRow.appendChild(el('span', {text: builtinCount + ' built-in', style:'color:var(--accent)'}));
92
+ if (communityCount > 0) statsRow.appendChild(el('span', {text: communityCount + ' community', style:'color:var(--accent-sim)'}));
93
+ panel.appendChild(statsRow);
94
+
95
+ // Table
96
+ const table = el('table', {class:'data-table sortable'});
97
+ const thead = el('thead');
98
+ const headerRow = el('tr');
99
+ ['', 'Check', 'Tags', 'Confidence', 'Source', 'Runs', 'Pass Rate', 'Last Run'].forEach(h => {
100
+ headerRow.appendChild(el('th', {text: h}));
101
+ });
102
+ thead.appendChild(headerRow);
103
+ table.appendChild(thead);
104
+
105
+ const tbody = el('tbody');
106
+ const sorted = [...catalogData].sort((a, b) => a.slug.localeCompare(b.slug));
107
+ const uid = 'cc-' + Math.random().toString(36).slice(2, 8);
108
+
109
+ sorted.forEach((check, i) => {
110
+ const st = checkStats[check.slug] || { runs: 0, passed: 0, failed: 0, lastRun: null };
111
+ const rate = st.runs > 0 ? Math.round((st.passed / st.runs) * 100) : -1;
112
+ const hasDesc = !!check.longDescription;
113
+ const expanderId = uid + '-exp-' + i;
114
+
115
+ const arrowCell = el('td', {style:'width:24px;text-align:center;color:var(--text-dim);font-size:12px'});
116
+ if (hasDesc) arrowCell.textContent = '\\u25B6';
117
+
118
+ const row = el('tr', {
119
+ class: hasDesc ? 'clickable' : '',
120
+ 'data-slug': check.slug,
121
+ 'data-tags': (check.tags || []).join(','),
122
+ 'data-source': check.source,
123
+ 'data-name': check.name.toLowerCase(),
124
+ onclick: hasDesc ? () => {
125
+ const exp = document.getElementById(expanderId);
126
+ if (exp) {
127
+ const isOpen = exp.classList.toggle('open');
128
+ exp.style.display = isOpen ? 'table-row' : 'none';
129
+ arrowCell.textContent = isOpen ? '\\u25BC' : '\\u25B6';
130
+ }
131
+ row.classList.toggle('expanded');
132
+ } : undefined
133
+ });
134
+ row.appendChild(arrowCell);
135
+
136
+ const nameCell = el('td', {style:'font-weight:500'});
137
+ nameCell.appendChild(document.createTextNode(check.slug));
138
+ row.appendChild(nameCell);
139
+
140
+ const tagsCell = el('td');
141
+ (check.tags || []).slice(0, 4).forEach(t => {
142
+ tagsCell.appendChild(el('span', {class:'tag-badge', text:t}));
143
+ });
144
+ if ((check.tags || []).length > 4) {
145
+ tagsCell.appendChild(el('span', {class:'tag-badge', text:'+' + ((check.tags || []).length - 4)}));
146
+ }
147
+ row.appendChild(tagsCell);
148
+
149
+ const confCell = el('td');
150
+ confCell.appendChild(el('span', {class:'badge badge-' + check.confidence, text: check.confidence}));
151
+ row.appendChild(confCell);
152
+
153
+ const sourceCell = el('td');
154
+ const sourceStyle = check.source === 'built-in' ? 'color:var(--accent)' : 'color:var(--accent-sim)';
155
+ sourceCell.appendChild(el('span', {text: check.source, style: sourceStyle + ';font-size:12px'}));
156
+ row.appendChild(sourceCell);
157
+
158
+ row.appendChild(el('td', {text: st.runs > 0 ? '' + st.runs : '\\u2014', style:'color:var(--text-dim)'}));
159
+
160
+ const rateCell = el('td');
161
+ if (rate >= 0) {
162
+ const rateColor = rate >= 90 ? 'var(--success)' : rate >= 70 ? 'var(--warning)' : 'var(--error)';
163
+ const bar = el('span', {class:'pass-rate-bar'});
164
+ const track = el('span', {class:'pass-rate-track'});
165
+ track.appendChild(el('span', {class:'pass-rate-fill', style:'width:' + rate + '%;background:' + rateColor}));
166
+ bar.appendChild(track);
167
+ bar.appendChild(el('span', {text: rate + '%', style:'font-size:12px;color:' + rateColor}));
168
+ rateCell.appendChild(bar);
169
+ } else {
170
+ rateCell.textContent = '\\u2014';
171
+ rateCell.style.color = 'var(--text-dim)';
172
+ }
173
+ row.appendChild(rateCell);
174
+
175
+ row.appendChild(el('td', {
176
+ text: st.lastRun ? new Date(st.lastRun).toLocaleDateString() : '\\u2014',
177
+ style:'color:var(--text-dim);font-size:12px'
178
+ }));
179
+
180
+ tbody.appendChild(row);
181
+
182
+ if (hasDesc) {
183
+ const expRow = el('tr', {id: expanderId, class:'expander-row', 'data-slug': check.slug, 'data-tags': (check.tags || []).join(','), 'data-source': check.source, 'data-name': check.name.toLowerCase()});
184
+ const expCell = el('td', {colspan:'8', style:'padding:0'});
185
+ const expContent = el('div', {class:'expander-content'});
186
+ expContent.appendChild(renderLongDesc(check.longDescription));
187
+ expCell.appendChild(expContent);
188
+ expRow.appendChild(expCell);
189
+ tbody.appendChild(expRow);
190
+ }
191
+ });
192
+
193
+ table.appendChild(tbody);
194
+ const pag = el('div', {class:'pagination'});
195
+ const card = el('div', {class:'card'}, [table, pag]);
196
+ panel.appendChild(card);
197
+
198
+ const emptyMsg = el('div', {class:'empty', style:'display:none', text:'No checks match your filters.'});
199
+ card.insertBefore(emptyMsg, pag);
200
+ paginateGroupedRows(tbody, pag, 10);
201
+
202
+ function applyFilters() {
203
+ const search = searchInput.value.toLowerCase();
204
+ const tag = tagSelect.value;
205
+ const source = sourceSelect.value;
206
+ const allRows = Array.from(tbody.children);
207
+ let visibleCount = 0;
208
+
209
+ // First pass: mark rows visible/hidden and collapse expanders
210
+ for (let i = 0; i < allRows.length; i++) {
211
+ const row = allRows[i];
212
+ if (row.classList.contains('expander-row')) continue;
213
+ const slug = row.getAttribute('data-slug') || '';
214
+ const name = row.getAttribute('data-name') || '';
215
+ const rowTags = row.getAttribute('data-tags') || '';
216
+ const rowSource = row.getAttribute('data-source') || '';
217
+ const matchSearch = !search || slug.includes(search) || name.includes(search);
218
+ const matchTag = !tag || rowTags.split(',').includes(tag);
219
+ const matchSource = !source || rowSource === source;
220
+ const visible = matchSearch && matchTag && matchSource;
221
+ row.style.display = visible ? '' : 'none';
222
+ row._filterVisible = visible;
223
+ if (visible) visibleCount++;
224
+ if (i + 1 < allRows.length && allRows[i + 1].classList.contains('expander-row')) {
225
+ allRows[i + 1].style.display = 'none';
226
+ allRows[i + 1].classList.remove('open');
227
+ if (row.classList.contains('expanded')) {
228
+ row.classList.remove('expanded');
229
+ const arrowTd = row.children[0];
230
+ if (arrowTd) arrowTd.textContent = '\\u25B6';
231
+ }
232
+ }
233
+ }
234
+ emptyMsg.style.display = visibleCount === 0 ? '' : 'none';
235
+
236
+ // Re-paginate only visible rows
237
+ const hasFilters = search || tag || source;
238
+ if (hasFilters) {
239
+ // Hide all first, then paginate only matching groups
240
+ const groups = [];
241
+ for (let i = 0; i < allRows.length; i++) {
242
+ const row = allRows[i];
243
+ if (row.classList.contains('expander-row')) continue;
244
+ if (!row._filterVisible) continue;
245
+ const group = [row];
246
+ if (i + 1 < allRows.length && allRows[i+1].classList.contains('expander-row')) {
247
+ group.push(allRows[i+1]);
248
+ }
249
+ groups.push(group);
250
+ }
251
+
252
+ // Custom pagination for filtered results
253
+ let currentPage = 0;
254
+ const pageSize = 10;
255
+ const totalPages = Math.max(1, Math.ceil(groups.length / pageSize));
256
+
257
+ function renderFilteredPage() {
258
+ // Hide all filtered rows first
259
+ groups.forEach(g => g.forEach(r => { r.style.display = 'none'; }));
260
+ const start = currentPage * pageSize;
261
+ const end = start + pageSize;
262
+ groups.slice(start, end).forEach(g => { g[0].style.display = ''; });
263
+
264
+ while (pag.firstChild) pag.removeChild(pag.firstChild);
265
+ if (groups.length <= pageSize) return;
266
+ pag.appendChild(el('div', {class:'pagination-info', text: 'Showing ' + (start+1) + '-' + Math.min(end, groups.length) + ' of ' + groups.length + ' checks'}));
267
+ const btns = el('div', {class:'pagination-btns'});
268
+ renderPageButtons(btns, currentPage, totalPages, (p) => { currentPage = p; renderFilteredPage(); });
269
+ pag.appendChild(btns);
270
+ }
271
+ renderFilteredPage();
272
+ } else {
273
+ paginateGroupedRows(tbody, pag, 10);
274
+ }
275
+ }
276
+
277
+ searchInput.addEventListener('input', applyFilters);
278
+ tagSelect.addEventListener('change', applyFilters);
279
+ sourceSelect.addEventListener('change', applyFilters);
280
+ }
281
+ `;
282
+ }
283
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,iBAAiB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRR,CAAC;AACF,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Restructured Code Paths explore-tab set (Plan D — shipped).
3
+ *
4
+ * The explore-tab restructure has shipped: `dashboardCodePathsJs` emits exactly
5
+ * the kept views (graph / coupling) plus the ranked-distribution "Functions"
6
+ * affordance, and the single-metric / standalone-SCC view sources were deleted.
7
+ * The former standalone Search subtab was folded into the Functions view as an
8
+ * in-table name filter, so it no longer registers a `search` view.
9
+ * The emitter no longer has a legacy branch — the `restructured` parameter is a
10
+ * vestigial test-seam arg that always yields the restructured set.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=views-registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views-registry.test.d.ts","sourceRoot":"","sources":["../../../src/code-paths/__tests__/views-registry.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @fileoverview Restructured Code Paths explore-tab set (Plan D — shipped).
3
+ *
4
+ * The explore-tab restructure has shipped: `dashboardCodePathsJs` emits exactly
5
+ * the kept views (graph / coupling) plus the ranked-distribution "Functions"
6
+ * affordance, and the single-metric / standalone-SCC view sources were deleted.
7
+ * The former standalone Search subtab was folded into the Functions view as an
8
+ * in-table name filter, so it no longer registers a `search` view.
9
+ * The emitter no longer has a legacy branch — the `restructured` parameter is a
10
+ * vestigial test-seam arg that always yields the restructured set.
11
+ */
12
+ import { describe, expect, it } from 'vitest';
13
+ import { dashboardCodePathsJs } from '../../code-paths.js';
14
+ /** Pull every `id: '<x>'` from a `views.push({ id: '<x>' ... })` literal. */
15
+ function registeredViewIds(js) {
16
+ const ids = [];
17
+ // Split on the literal `views.push({` boundary, then match the first `id:`
18
+ // in each chunk. Avoids a backtracking-prone whitespace pattern.
19
+ const chunks = js.split('views.push({');
20
+ for (let i = 1; i < chunks.length; i++) {
21
+ const m = /id:\s*'([a-z-]+)'/.exec(chunks[i] ?? '');
22
+ if (m)
23
+ ids.push(m[1]);
24
+ }
25
+ return ids;
26
+ }
27
+ describe('Code Paths explore-tab set', () => {
28
+ it('emitter registers exactly {graph, coupling, distribution}', () => {
29
+ const ids = registeredViewIds(dashboardCodePathsJs());
30
+ expect(new Set(ids)).toEqual(new Set(['graph', 'coupling', 'distribution']));
31
+ });
32
+ it('drops the single-metric + standalone-SCC + standalone-search views', () => {
33
+ const ids = registeredViewIds(dashboardCodePathsJs());
34
+ for (const removed of ['big', 'hot', 'wide', 'untested', 'sccs', 'search']) {
35
+ expect(ids).not.toContain(removed);
36
+ }
37
+ });
38
+ });
39
+ //# sourceMappingURL=views-registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views-registry.test.js","sourceRoot":"","sources":["../../../src/code-paths/__tests__/views-registry.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,6EAA6E;AAC7E,SAAS,iBAAiB,CAAC,EAAU;IACnC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,2EAA2E;IAC3E,iEAAiE;IACjE,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,iBAAiB,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,GAAG,GAAG,iBAAiB,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACtD,KAAK,MAAM,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC3E,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Catalog provenance bar for the Explore tab.
3
+ *
4
+ * The Explore views (Coupling / Functions / Visualization) all render from the
5
+ * single cached graph catalog — the LATEST `graph` build, whatever its scope.
6
+ * A scoped run (`graph packages/contracts`) or a stale build therefore narrows
7
+ * every view, with no on-page indication. Without a provenance line a
8
+ * single-package catalog reads as "the tool is broken" instead of "this catalog
9
+ * only covers one package."
10
+ *
11
+ * This bar surfaces what the views are built from — package scope, function
12
+ * count, build time, and engine — so a scoped/stale catalog is self-explanatory.
13
+ * Every value is DERIVED from the embedded catalog itself, so it is ground truth
14
+ * and can never drift from what the views render (no separately-persisted
15
+ * "scope" field to fall out of sync).
16
+ *
17
+ * Declares the top-level `renderCatalogProvenance(host, catalog)` consumed by
18
+ * the Explore body. Depends on `packagesInCatalog` (filters.ts) and the shared
19
+ * `el` helper, so it must be concatenated AFTER filters.ts in the prelude.
20
+ */
21
+ export declare function dashboardCatalogProvenanceJs(): string;
22
+ //# sourceMappingURL=catalog-provenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-provenance.d.ts","sourceRoot":"","sources":["../../src/code-paths/catalog-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,wBAAgB,4BAA4B,IAAI,MAAM,CAsFrD"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Catalog provenance bar for the Explore tab.
3
+ *
4
+ * The Explore views (Coupling / Functions / Visualization) all render from the
5
+ * single cached graph catalog — the LATEST `graph` build, whatever its scope.
6
+ * A scoped run (`graph packages/contracts`) or a stale build therefore narrows
7
+ * every view, with no on-page indication. Without a provenance line a
8
+ * single-package catalog reads as "the tool is broken" instead of "this catalog
9
+ * only covers one package."
10
+ *
11
+ * This bar surfaces what the views are built from — package scope, function
12
+ * count, build time, and engine — so a scoped/stale catalog is self-explanatory.
13
+ * Every value is DERIVED from the embedded catalog itself, so it is ground truth
14
+ * and can never drift from what the views render (no separately-persisted
15
+ * "scope" field to fall out of sync).
16
+ *
17
+ * Declares the top-level `renderCatalogProvenance(host, catalog)` consumed by
18
+ * the Explore body. Depends on `packagesInCatalog` (filters.ts) and the shared
19
+ * `el` helper, so it must be concatenated AFTER filters.ts in the prelude.
20
+ */
21
+ export function dashboardCatalogProvenanceJs() {
22
+ return String.raw `
23
+ // Build engine ('sharded' | 'exact') parsed from the catalog cache key
24
+ // (e.g. "eng=0.1.0|mode=sharded|..."). Null when the marker is absent.
25
+ function catalogEngineMode(catalog) {
26
+ const m = /(?:^|\|)mode=([a-z]+)/.exec((catalog && catalog.cacheKey) || '');
27
+ return m ? m[1] : null;
28
+ }
29
+
30
+ // Total function OCCURRENCES across the catalog (each occurrence is one graph
31
+ // node) — the catalog's size, not just distinct names.
32
+ function catalogFunctionCount(catalog) {
33
+ if (!catalog || !catalog.functions) return 0;
34
+ let n = 0;
35
+ for (const name of Object.keys(catalog.functions)) n += (catalog.functions[name] || []).length;
36
+ return n;
37
+ }
38
+
39
+ // Coarse "N <unit> ago" for the build time. Browser Date.now() is fine here
40
+ // (this is page JS, not the engine's Date.now()-free pure layer).
41
+ function provenanceRelTime(iso) {
42
+ const t = Date.parse(iso);
43
+ if (isNaN(t)) return '';
44
+ const secs = Math.max(0, Math.round((Date.now() - t) / 1000));
45
+ if (secs < 45) return 'just now';
46
+ const mins = Math.round(secs / 60);
47
+ if (mins < 60) return mins + ' min' + (mins !== 1 ? 's' : '') + ' ago';
48
+ const hrs = Math.round(mins / 60);
49
+ if (hrs < 24) return hrs + ' hour' + (hrs !== 1 ? 's' : '') + ' ago';
50
+ const days = Math.round(hrs / 24);
51
+ return days + ' day' + (days !== 1 ? 's' : '') + ' ago';
52
+ }
53
+
54
+ function provenanceChip(label, value, opts) {
55
+ opts = opts || {};
56
+ const chip = el('span', { style: 'display:inline-flex;align-items:baseline;gap:6px' });
57
+ chip.appendChild(el('span', { text: label, style: 'color:var(--text-dim);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em' }));
58
+ chip.appendChild(el('span', { text: value, title: opts.title || '', style: 'color:' + (opts.color || 'var(--text)') + ';font-weight:600;font-size:13px' }));
59
+ return chip;
60
+ }
61
+
62
+ // Render the provenance bar into host. No-op when no catalog is loaded (the
63
+ // caller already shows a "No catalog yet." empty state in that case).
64
+ function renderCatalogProvenance(host, catalog) {
65
+ if (!catalog) return;
66
+ const pkgs = packagesInCatalog(catalog);
67
+ const fnCount = catalogFunctionCount(catalog);
68
+ const engine = catalogEngineMode(catalog);
69
+ const builtAt = catalog.builtAt ? new Date(catalog.builtAt) : null;
70
+
71
+ const bar = el('div', {
72
+ class: 'catalog-provenance',
73
+ style: 'display:flex;flex-wrap:wrap;align-items:center;gap:10px 20px;margin:0 0 16px;padding:10px 14px;border:1px solid var(--border);border-radius:8px;background:var(--bg-card)',
74
+ });
75
+
76
+ // Scope is the headline signal: 1 package vs the whole repo. List the names
77
+ // inline when the set is small (so a scoped build reads "1 package: contracts"
78
+ // directly); always carry the full sorted list in the title for hover.
79
+ const pkgLabel = pkgs.length === 1 ? '1 package' : String(pkgs.length) + ' packages';
80
+ const pkgNames = pkgs.length > 0 && pkgs.length <= 4 ? ': ' + pkgs.join(', ') : '';
81
+ bar.appendChild(
82
+ provenanceChip('Scope', pkgLabel + pkgNames, {
83
+ color: 'var(--accent)',
84
+ title: pkgs.join(', '),
85
+ }),
86
+ );
87
+
88
+ bar.appendChild(provenanceChip('Functions', fnCount.toLocaleString()));
89
+
90
+ if (builtAt && !isNaN(builtAt.getTime())) {
91
+ bar.appendChild(
92
+ provenanceChip('Built', provenanceRelTime(catalog.builtAt), { title: builtAt.toLocaleString() }),
93
+ );
94
+ }
95
+
96
+ if (engine) bar.appendChild(provenanceChip('Engine', engine));
97
+
98
+ // 'fast' resolution = syntactic (approximate) edges, so the coupling matrix /
99
+ // visualization are approximate too. 'exact' is the default and needs no flag.
100
+ if (catalog.resolutionMode === 'fast') {
101
+ bar.appendChild(provenanceChip('Resolution', 'fast (approximate)', { color: 'var(--warning)' }));
102
+ }
103
+
104
+ host.appendChild(bar);
105
+ }
106
+ `;
107
+ }
108
+ //# sourceMappingURL=catalog-provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-provenance.js","sourceRoot":"","sources":["../../src/code-paths/catalog-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,UAAU,4BAA4B;IAC1C,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoFlB,CAAC;AACF,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Code Paths — Catalog & Recipes subtab tables.
3
+ *
4
+ * Declares the two top-level renderers the Code Paths panel mounts for its
5
+ * "Catalog" (graph rule catalog) and "Recipes" (graph recipe catalog) subtabs.
6
+ * Extracted from the panel orchestrator (code-paths.ts) to keep that aggregator
7
+ * focused on wiring; both functions are pure DOM table builders that close over
8
+ * the shared `el` helper, so they only need to be concatenated after it.
9
+ */
10
+ export declare function dashboardCatalogRecipesTablesJs(): string;
11
+ //# sourceMappingURL=catalog-recipes-tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-recipes-tables.d.ts","sourceRoot":"","sources":["../../src/code-paths/catalog-recipes-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wBAAgB,+BAA+B,IAAI,MAAM,CA2ExD"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Code Paths — Catalog & Recipes subtab tables.
3
+ *
4
+ * Declares the two top-level renderers the Code Paths panel mounts for its
5
+ * "Catalog" (graph rule catalog) and "Recipes" (graph recipe catalog) subtabs.
6
+ * Extracted from the panel orchestrator (code-paths.ts) to keep that aggregator
7
+ * focused on wiring; both functions are pure DOM table builders that close over
8
+ * the shared `el` helper, so they only need to be concatenated after it.
9
+ */
10
+ export function dashboardCatalogRecipesTablesJs() {
11
+ return String.raw `
12
+ // =======================================================
13
+ // CODE PATHS — CATALOG SUBTAB (graph rule catalog)
14
+ // =======================================================
15
+ function renderGraphRuleCatalog(container, rulesData) {
16
+ if (!rulesData || !rulesData.length) {
17
+ container.appendChild(el('div', { class: 'empty', text: 'No rules available.' }));
18
+ return;
19
+ }
20
+ const table = el('table', { class: 'data-table' });
21
+ const thead = el('thead');
22
+ const headerRow = el('tr');
23
+ ['Rule', 'Default Severity', 'Source'].forEach(h => {
24
+ headerRow.appendChild(el('th', { text: h }));
25
+ });
26
+ thead.appendChild(headerRow);
27
+ table.appendChild(thead);
28
+
29
+ const tbody = el('tbody');
30
+ rulesData.forEach(rule => {
31
+ const row = el('tr');
32
+ row.appendChild(el('td', { text: rule.slug, style: 'font-weight:500' }));
33
+ const sevCell = el('td');
34
+ const sevColor = rule.defaultSeverity === 'error' ? 'color:var(--danger)' : 'color:var(--warning)';
35
+ sevCell.appendChild(el('span', { text: rule.defaultSeverity, style: sevColor + ';font-size:12px' }));
36
+ row.appendChild(sevCell);
37
+ const srcCell = el('td');
38
+ srcCell.appendChild(el('span', { class: 'badge', style: 'background:var(--bg-hover);color:var(--text-muted)', text: rule.source }));
39
+ row.appendChild(srcCell);
40
+ tbody.appendChild(row);
41
+ });
42
+ table.appendChild(tbody);
43
+ container.appendChild(el('div', { class: 'card' }, [table]));
44
+ }
45
+
46
+ // =======================================================
47
+ // CODE PATHS — RECIPES SUBTAB (graph recipe catalog)
48
+ // =======================================================
49
+ function renderGraphRecipeCatalog(container, recipesData) {
50
+ if (!recipesData || !recipesData.length) {
51
+ container.appendChild(el('div', { class: 'empty', text: 'No recipes available.' }));
52
+ return;
53
+ }
54
+ const table = el('table', { class: 'data-table' });
55
+ const thead = el('thead');
56
+ const headerRow = el('tr');
57
+ ['Recipe', 'Description', 'Selector', 'Tags'].forEach(h => {
58
+ headerRow.appendChild(el('th', { text: h }));
59
+ });
60
+ thead.appendChild(headerRow);
61
+ table.appendChild(thead);
62
+
63
+ const tbody = el('tbody');
64
+ recipesData.forEach(recipe => {
65
+ const row = el('tr');
66
+ const nameCell = el('td', { style: 'font-weight:500' });
67
+ nameCell.appendChild(el('div', { text: recipe.displayName }));
68
+ nameCell.appendChild(el('div', { text: recipe.name, style: 'font-size:11px;color:var(--text-dim);font-weight:400' }));
69
+ row.appendChild(nameCell);
70
+ row.appendChild(el('td', { text: recipe.description, style: 'color:var(--text-muted)' }));
71
+ const selCell = el('td');
72
+ selCell.appendChild(el('span', { class: 'badge', style: 'background:var(--bg-hover);color:var(--text-muted)', text: recipe.selectorType }));
73
+ row.appendChild(selCell);
74
+ const tagsCell = el('td');
75
+ (recipe.tags || []).forEach(t => {
76
+ tagsCell.appendChild(el('span', { class: 'tag-badge', text: t }));
77
+ });
78
+ row.appendChild(tagsCell);
79
+ tbody.appendChild(row);
80
+ });
81
+ table.appendChild(tbody);
82
+ container.appendChild(el('div', { class: 'card' }, [table]));
83
+ }
84
+ `;
85
+ }
86
+ //# sourceMappingURL=catalog-recipes-tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-recipes-tables.js","sourceRoot":"","sources":["../../src/code-paths/catalog-recipes-tables.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,UAAU,+BAA+B;IAC7C,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyElB,CAAC;AACF,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Vendored Cytoscape emitter.
3
+ *
4
+ * Reads the committed `src/vendor/cytoscape-bundle.js` UMD blob at
5
+ * generation time and returns it as a JS string for inlining into the
6
+ * report's single `<script>` block. The bundle registers the `cytoscape`
7
+ * and `cytoscapeDagre` browser globals the Graph view (`view-graph.ts`)
8
+ * consumes — fully offline, no CDN, no network at view time.
9
+ *
10
+ * Architectural note: this module reads the bundle via `node:fs`, it does
11
+ * NOT `import 'cytoscape'`. That is deliberate — the `dashboard-no-ui-
12
+ * framework` dependency-cruiser rule forbids importing a visualization
13
+ * library into `packages/dashboard/src/`. The renderer reaches the report
14
+ * as committed source text, never as a module dependency. The `cytoscape`
15
+ * / `cytoscape-dagre` packages are devDependencies used only by the vendor
16
+ * build script (`scripts/vendor-cytoscape.mjs`), which lives outside
17
+ * `src/` and so is out of the rule's scope.
18
+ */
19
+ /**
20
+ * Emit the vendored Cytoscape UMD bundle as a JS string for inlining.
21
+ *
22
+ * MUST be concatenated into the Code Paths script BEFORE any view emitter
23
+ * that references the `cytoscape` global (i.e. before
24
+ * `dashboardViewGraphJs()`).
25
+ */
26
+ export declare function dashboardCytoscapeVendorJs(): string;
27
+ //# sourceMappingURL=cytoscape-vendor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cytoscape-vendor.d.ts","sourceRoot":"","sources":["../../src/code-paths/cytoscape-vendor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA8CH;;;;;;GAMG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAEnD"}