@contentful/experience-design-system-cli 2.26.1-dev-build-a852362.0 → 2.26.1-dev-build-f03f014.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 (204) hide show
  1. package/dist/package.json +14 -10
  2. package/dist/src/index.js +34937 -9
  3. package/dist/src/lib/cli-path.d.ts +4 -0
  4. package/dist/src/runs/export-helpers.d.ts +1 -12
  5. package/dist/src/runs/push-helpers.d.ts +1 -6
  6. package/package.json +12 -7
  7. package/skills/generate-components.md +427 -0
  8. package/skills/generate-tokens.md +194 -0
  9. package/skills/select-components.md +224 -0
  10. package/dist/src/analytics/apply.js +0 -30
  11. package/dist/src/analytics/client.js +0 -81
  12. package/dist/src/analytics/constants.js +0 -4
  13. package/dist/src/analytics/env.js +0 -14
  14. package/dist/src/analytics/exit.js +0 -24
  15. package/dist/src/analytics/index.js +0 -9
  16. package/dist/src/analytics/normalize.js +0 -18
  17. package/dist/src/analytics/os.js +0 -13
  18. package/dist/src/analytics/session.js +0 -15
  19. package/dist/src/analytics/tracker.js +0 -126
  20. package/dist/src/analytics/types.js +0 -1
  21. package/dist/src/analyze/build-analyze-view-rows.js +0 -63
  22. package/dist/src/analyze/command.js +0 -599
  23. package/dist/src/analyze/composite-closure.js +0 -0
  24. package/dist/src/analyze/composition/agent-parser/author-prompt.js +0 -22
  25. package/dist/src/analyze/composition/agent-parser/extract-parser.js +0 -44
  26. package/dist/src/analyze/composition/agent-parser/load-prompt.js +0 -31
  27. package/dist/src/analyze/composition/agent-parser/resolve-via-parser.js +0 -88
  28. package/dist/src/analyze/composition/agent-parser/sandbox.js +0 -187
  29. package/dist/src/analyze/composition/apply-mapping.js +0 -67
  30. package/dist/src/analyze/composition/candidate-critic-agent.js +0 -39
  31. package/dist/src/analyze/composition/candidate-critic.js +0 -63
  32. package/dist/src/analyze/composition/candidate-files.js +0 -131
  33. package/dist/src/analyze/composition/composition-cache-key.js +0 -19
  34. package/dist/src/analyze/composition/interchange-schema.js +0 -61
  35. package/dist/src/analyze/composition/manifest-doc-evidence.js +0 -136
  36. package/dist/src/analyze/composition/merge-edges.js +0 -70
  37. package/dist/src/analyze/composition/parse-map-edges.js +0 -55
  38. package/dist/src/analyze/composition/resolve-mapping-cli.js +0 -29
  39. package/dist/src/analyze/composition/resolve-mapping.js +0 -111
  40. package/dist/src/analyze/cycle-detection.js +0 -234
  41. package/dist/src/analyze/cycle-view.js +0 -28
  42. package/dist/src/analyze/fuzzy-search.js +0 -55
  43. package/dist/src/analyze/issue-inheritance.js +0 -108
  44. package/dist/src/analyze/lineage.js +0 -0
  45. package/dist/src/analyze/scope-gate-cascade.js +0 -170
  46. package/dist/src/analyze/search-neighborhood.js +0 -56
  47. package/dist/src/analyze/select/command.js +0 -484
  48. package/dist/src/analyze/select/index.js +0 -5
  49. package/dist/src/analyze/select/parser.js +0 -53
  50. package/dist/src/analyze/select/persistence.js +0 -80
  51. package/dist/src/analyze/select/preview-annotations.js +0 -62
  52. package/dist/src/analyze/select/stdout.js +0 -3
  53. package/dist/src/analyze/select/tui/App.js +0 -483
  54. package/dist/src/analyze/select/tui/components/ComponentDetail.js +0 -48
  55. package/dist/src/analyze/select/tui/components/ComponentRationalePanel.js +0 -125
  56. package/dist/src/analyze/select/tui/components/FieldEditor.js +0 -1131
  57. package/dist/src/analyze/select/tui/components/FinalizeDialog.js +0 -36
  58. package/dist/src/analyze/select/tui/components/GotoBanner.js +0 -30
  59. package/dist/src/analyze/select/tui/components/GroupedSidebar.js +0 -517
  60. package/dist/src/analyze/select/tui/components/HelpOverlay.js +0 -17
  61. package/dist/src/analyze/select/tui/components/JsonEditor.js +0 -131
  62. package/dist/src/analyze/select/tui/components/JsonPanel.js +0 -66
  63. package/dist/src/analyze/select/tui/components/LineagePanel.js +0 -22
  64. package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +0 -29
  65. package/dist/src/analyze/select/tui/components/QuitDialog.js +0 -14
  66. package/dist/src/analyze/select/tui/components/RationalePanel.js +0 -80
  67. package/dist/src/analyze/select/tui/components/Sidebar.js +0 -92
  68. package/dist/src/analyze/select/tui/components/SourcePanel.js +0 -52
  69. package/dist/src/analyze/select/tui/components/StatusBar.js +0 -7
  70. package/dist/src/analyze/select/tui/components/TopBar.js +0 -10
  71. package/dist/src/analyze/select/tui/components/removed-components-text.js +0 -11
  72. package/dist/src/analyze/select/tui/hooks/scroll-offset.js +0 -26
  73. package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +0 -66
  74. package/dist/src/analyze/select/tui/hooks/useKeymap.js +0 -67
  75. package/dist/src/analyze/select/tui/hooks/useSession.js +0 -52
  76. package/dist/src/analyze/select/tui/hooks/useUndo.js +0 -26
  77. package/dist/src/analyze/select/tui/theme.js +0 -28
  78. package/dist/src/analyze/select/types.js +0 -39
  79. package/dist/src/analyze/select-agent/command.js +0 -558
  80. package/dist/src/analyze/select-agent/context-builder.js +0 -197
  81. package/dist/src/analyze/select-agent/show-rationale.js +0 -92
  82. package/dist/src/analyze/selection-cascade.js +0 -19
  83. package/dist/src/analyze/slot-graph.js +0 -17
  84. package/dist/src/analyze/tui/AnalyzeView.js +0 -64
  85. package/dist/src/apply/api-client.js +0 -440
  86. package/dist/src/apply/command.js +0 -845
  87. package/dist/src/apply/manifest.js +0 -1
  88. package/dist/src/apply/preview-utils.js +0 -26
  89. package/dist/src/apply/tui/SelectView.js +0 -34
  90. package/dist/src/apply/tui/ServerApplyView.js +0 -49
  91. package/dist/src/apply/tui/ServerPreviewView.js +0 -23
  92. package/dist/src/credentials-store.js +0 -74
  93. package/dist/src/generate/command.js +0 -597
  94. package/dist/src/generate/edit/command.js +0 -127
  95. package/dist/src/generate/tui/GenerateView.js +0 -10
  96. package/dist/src/host-utils.js +0 -26
  97. package/dist/src/import/agent-model-resolve.js +0 -35
  98. package/dist/src/import/auto-filter-resolve.js +0 -16
  99. package/dist/src/import/command.js +0 -380
  100. package/dist/src/import/cycle-auto-reject.js +0 -14
  101. package/dist/src/import/orchestrator.js +0 -603
  102. package/dist/src/import/path-utils.js +0 -30
  103. package/dist/src/import/picker-dispatch.js +0 -44
  104. package/dist/src/import/print-prompt.js +0 -31
  105. package/dist/src/import/strip-allowed-components.js +0 -22
  106. package/dist/src/import/tui/CustomPromptBanner.js +0 -8
  107. package/dist/src/import/tui/WizardApp.js +0 -1670
  108. package/dist/src/import/tui/ai-flag.js +0 -6
  109. package/dist/src/import/tui/auto-filter-error.js +0 -29
  110. package/dist/src/import/tui/autocomplete.js +0 -32
  111. package/dist/src/import/tui/components/AutoFilterBanner.js +0 -19
  112. package/dist/src/import/tui/components/CounterStrip.js +0 -12
  113. package/dist/src/import/tui/components/LegendEntry.js +0 -6
  114. package/dist/src/import/tui/cycle-panel-scroll.js +0 -33
  115. package/dist/src/import/tui/final-review-host.js +0 -25
  116. package/dist/src/import/tui/group-collapse.js +0 -11
  117. package/dist/src/import/tui/history.js +0 -53
  118. package/dist/src/import/tui/hooks/useLineage.js +0 -50
  119. package/dist/src/import/tui/hooks/useOverlayPanel.js +0 -27
  120. package/dist/src/import/tui/lineage-layout.js +0 -82
  121. package/dist/src/import/tui/merge-ai-decisions.js +0 -22
  122. package/dist/src/import/tui/push-decision-gate-helpers.js +0 -8
  123. package/dist/src/import/tui/push-progress.js +0 -1
  124. package/dist/src/import/tui/run-print-files-helpers.js +0 -8
  125. package/dist/src/import/tui/run-teaser.js +0 -9
  126. package/dist/src/import/tui/runLivePreview.js +0 -82
  127. package/dist/src/import/tui/runScopeGate.js +0 -28
  128. package/dist/src/import/tui/scope-gate-columns.js +0 -94
  129. package/dist/src/import/tui/scope-gate-host.js +0 -28
  130. package/dist/src/import/tui/sidebar-width.js +0 -3
  131. package/dist/src/import/tui/spawn-generate.js +0 -53
  132. package/dist/src/import/tui/step-filters.js +0 -42
  133. package/dist/src/import/tui/steps/AtomicGenerateReviewStep.js +0 -726
  134. package/dist/src/import/tui/steps/AtomicScopeGateStep.js +0 -210
  135. package/dist/src/import/tui/steps/CredentialsStep.js +0 -108
  136. package/dist/src/import/tui/steps/DoneStep.js +0 -24
  137. package/dist/src/import/tui/steps/ErrorStep.js +0 -16
  138. package/dist/src/import/tui/steps/GateStep.js +0 -22
  139. package/dist/src/import/tui/steps/GenerateReviewStep.js +0 -1618
  140. package/dist/src/import/tui/steps/PathValidationStep.js +0 -152
  141. package/dist/src/import/tui/steps/PreviewStep.js +0 -37
  142. package/dist/src/import/tui/steps/PreviewValidationErrorStep.js +0 -23
  143. package/dist/src/import/tui/steps/PushDecisionGateStep.js +0 -73
  144. package/dist/src/import/tui/steps/PushingStep.js +0 -24
  145. package/dist/src/import/tui/steps/RunningStep.js +0 -21
  146. package/dist/src/import/tui/steps/ScopeGateStep.js +0 -907
  147. package/dist/src/import/tui/steps/TokenInputStep.js +0 -88
  148. package/dist/src/import/tui/steps/WelcomeStep.js +0 -34
  149. package/dist/src/import/tui/steps/WizardPreviewStep.js +0 -169
  150. package/dist/src/import/tui/steps/auto-reject-decision.js +0 -9
  151. package/dist/src/import/tui/steps/breaking-change-format.js +0 -24
  152. package/dist/src/import/tui/steps/enumerate-cycle-breaks.js +0 -0
  153. package/dist/src/import/tui/steps/preview-diff.js +0 -175
  154. package/dist/src/import/tui/useFinalizePreview.js +0 -0
  155. package/dist/src/import/tui/useLivePreview.js +0 -122
  156. package/dist/src/import/tui/wizard-422-helpers.js +0 -60
  157. package/dist/src/import/tui/wizard-generate-progress.js +0 -25
  158. package/dist/src/import/tui/wizard-save-flow.js +0 -20
  159. package/dist/src/import/tui/wizard-state-transitions.js +0 -32
  160. package/dist/src/lib/agent-model-options.js +0 -15
  161. package/dist/src/lib/command-options.js +0 -30
  162. package/dist/src/lib/composition-mode.js +0 -39
  163. package/dist/src/lib/contentful-urls.js +0 -27
  164. package/dist/src/lib/debug-logger.js +0 -229
  165. package/dist/src/lib/debug-preamble.js +0 -33
  166. package/dist/src/lib/error-parser.js +0 -269
  167. package/dist/src/lib/prompt-overrides.js +0 -69
  168. package/dist/src/lib/terminal-capabilities.js +0 -51
  169. package/dist/src/lib/user-agent.js +0 -29
  170. package/dist/src/output/format.js +0 -110
  171. package/dist/src/print/command.js +0 -221
  172. package/dist/src/print/validate/tui/ValidateView.js +0 -37
  173. package/dist/src/print/validate/validators/cdf-validator.js +0 -104
  174. package/dist/src/print/validate/validators/dtcg-validator.js +0 -110
  175. package/dist/src/print/validate/validators/format-errors.js +0 -18
  176. package/dist/src/program.js +0 -105
  177. package/dist/src/runs/export-helpers.js +0 -59
  178. package/dist/src/runs/fingerprint.js +0 -75
  179. package/dist/src/runs/ls-command.js +0 -137
  180. package/dist/src/runs/modify-launcher.js +0 -42
  181. package/dist/src/runs/path-prompt.js +0 -72
  182. package/dist/src/runs/push-creds-prompt.js +0 -39
  183. package/dist/src/runs/push-helpers.js +0 -72
  184. package/dist/src/runs/push-launcher.js +0 -77
  185. package/dist/src/runs/replay-helpers.js +0 -164
  186. package/dist/src/runs/resolve-run-target.js +0 -45
  187. package/dist/src/runs/run-picker-mount.js +0 -72
  188. package/dist/src/runs/run-picker.js +0 -129
  189. package/dist/src/runs/save-conflict.js +0 -56
  190. package/dist/src/runs/save-path-resolver.js +0 -75
  191. package/dist/src/runs/staleness.js +0 -140
  192. package/dist/src/runs/store.js +0 -136
  193. package/dist/src/session/cache-keys.js +0 -44
  194. package/dist/src/session/command.js +0 -261
  195. package/dist/src/session/db.js +0 -1538
  196. package/dist/src/session/migration.js +0 -117
  197. package/dist/src/session/session-id.js +0 -212
  198. package/dist/src/session/stats.js +0 -89
  199. package/dist/src/setup/analytics-prompt.js +0 -24
  200. package/dist/src/setup/auto-filter-prompt.js +0 -24
  201. package/dist/src/setup/command.js +0 -966
  202. package/dist/src/setup/composition-mode-prompt.js +0 -37
  203. package/dist/src/setup/debug-mode-prompt.js +0 -22
  204. package/dist/src/types.js +0 -1
@@ -1,234 +0,0 @@
1
- function buildGraph(components) {
2
- const nodes = [];
3
- const seen = new Set();
4
- for (const c of components) {
5
- if (seen.has(c.name))
6
- continue;
7
- seen.add(c.name);
8
- nodes.push(c.name);
9
- }
10
- const adjacency = new Map();
11
- for (const node of nodes)
12
- adjacency.set(node, []);
13
- for (const comp of components) {
14
- const outgoing = adjacency.get(comp.name);
15
- if (!outgoing)
16
- continue;
17
- for (const slot of comp.slots) {
18
- const allowed = slot.allowedComponents ?? [];
19
- for (const target of allowed) {
20
- if (!seen.has(target))
21
- continue;
22
- outgoing.push({ target, slotName: slot.name });
23
- }
24
- }
25
- }
26
- return { nodes, adjacency };
27
- }
28
- function stronglyConnectedComponents(nodes, adjacency) {
29
- const index = new Map();
30
- const lowlink = new Map();
31
- const onStack = new Set();
32
- const stack = [];
33
- const sccs = [];
34
- let counter = 0;
35
- const nodeSet = new Set(nodes);
36
- function strongconnect(v) {
37
- index.set(v, counter);
38
- lowlink.set(v, counter);
39
- counter += 1;
40
- stack.push(v);
41
- onStack.add(v);
42
- const neighbours = adjacency.get(v) ?? [];
43
- for (const { target } of neighbours) {
44
- if (!nodeSet.has(target))
45
- continue;
46
- if (!index.has(target)) {
47
- strongconnect(target);
48
- lowlink.set(v, Math.min(lowlink.get(v), lowlink.get(target)));
49
- }
50
- else if (onStack.has(target)) {
51
- lowlink.set(v, Math.min(lowlink.get(v), index.get(target)));
52
- }
53
- }
54
- if (lowlink.get(v) === index.get(v)) {
55
- const scc = [];
56
- let w;
57
- do {
58
- w = stack.pop();
59
- onStack.delete(w);
60
- scc.push(w);
61
- } while (w !== v);
62
- sccs.push(scc);
63
- }
64
- }
65
- for (const node of nodes) {
66
- if (!index.has(node))
67
- strongconnect(node);
68
- }
69
- return sccs;
70
- }
71
- function makeCycle(path, edges) {
72
- return { path: [...path, path[0]], edges: [...edges] };
73
- }
74
- export function findSlotCycles(components) {
75
- if (components.length === 0)
76
- return [];
77
- const { nodes, adjacency } = buildGraph(components);
78
- if (nodes.length === 0)
79
- return [];
80
- const cycles = [];
81
- for (const node of nodes) {
82
- const outgoing = adjacency.get(node) ?? [];
83
- for (const edge of outgoing) {
84
- if (edge.target === node) {
85
- cycles.push({
86
- path: [node, node],
87
- edges: [{ fromComponent: node, slotName: edge.slotName, toComponent: node }],
88
- });
89
- }
90
- }
91
- }
92
- const nodeOrder = [...nodes].sort();
93
- let remaining = [...nodeOrder];
94
- while (remaining.length > 0) {
95
- const subgraphNodes = remaining;
96
- const sccs = stronglyConnectedComponents(subgraphNodes, adjacency).filter((scc) => {
97
- if (scc.length > 1)
98
- return true;
99
- return false;
100
- });
101
- if (sccs.length === 0)
102
- break;
103
- let startNode = null;
104
- let startScc = null;
105
- for (const scc of sccs) {
106
- const min = [...scc].sort()[0];
107
- if (startNode === null || min < startNode) {
108
- startNode = min;
109
- startScc = scc;
110
- }
111
- }
112
- if (startNode === null || startScc === null)
113
- break;
114
- const sccSet = new Set(startScc);
115
- const blocked = new Set();
116
- const blockedMap = new Map();
117
- const pathStack = [];
118
- const edgeStack = [];
119
- function unblock(u) {
120
- blocked.delete(u);
121
- const dependents = blockedMap.get(u);
122
- if (!dependents)
123
- return;
124
- for (const w of dependents) {
125
- if (blocked.has(w))
126
- unblock(w);
127
- }
128
- dependents.clear();
129
- }
130
- function circuit(v, root) {
131
- let foundCycle = false;
132
- pathStack.push(v);
133
- blocked.add(v);
134
- const outgoing = adjacency.get(v) ?? [];
135
- for (const { target: w, slotName } of outgoing) {
136
- if (!sccSet.has(w))
137
- continue;
138
- edgeStack.push({ fromComponent: v, slotName, toComponent: w });
139
- if (w === root) {
140
- cycles.push(makeCycle(pathStack, edgeStack));
141
- foundCycle = true;
142
- }
143
- else if (!blocked.has(w)) {
144
- if (circuit(w, root))
145
- foundCycle = true;
146
- }
147
- edgeStack.pop();
148
- }
149
- if (foundCycle) {
150
- unblock(v);
151
- }
152
- else {
153
- for (const { target: w } of outgoing) {
154
- if (!sccSet.has(w))
155
- continue;
156
- let deps = blockedMap.get(w);
157
- if (!deps) {
158
- deps = new Set();
159
- blockedMap.set(w, deps);
160
- }
161
- deps.add(v);
162
- }
163
- }
164
- pathStack.pop();
165
- return foundCycle;
166
- }
167
- circuit(startNode, startNode);
168
- remaining = remaining.filter((n) => n !== startNode);
169
- }
170
- return cycles;
171
- }
172
- export function suggestCycleBreakEdge(cycle, allCycles) {
173
- if (cycle.edges.length === 0) {
174
- throw new Error('suggestCycleBreakEdge: cycle has no edges');
175
- }
176
- const indegree = new Map();
177
- for (const c of allCycles) {
178
- for (const edge of c.edges) {
179
- indegree.set(edge.toComponent, (indegree.get(edge.toComponent) ?? 0) + 1);
180
- }
181
- }
182
- let best = cycle.edges[0];
183
- let bestScore = indegree.get(best.toComponent) ?? 0;
184
- for (const edge of cycle.edges) {
185
- const score = indegree.get(edge.toComponent) ?? 0;
186
- if (score > bestScore) {
187
- best = edge;
188
- bestScore = score;
189
- }
190
- }
191
- return best;
192
- }
193
- export function formatCyclePath(cycle, maxHops = 8) {
194
- const arrow = ' → ';
195
- const parts = [];
196
- for (let i = 0; i < cycle.edges.length; i += 1) {
197
- parts.push(cycle.path[i]);
198
- parts.push(cycle.edges[i].slotName);
199
- }
200
- parts.push(cycle.path[cycle.path.length - 1]);
201
- if (cycle.edges.length <= maxHops) {
202
- return parts.join(arrow);
203
- }
204
- const keepHops = Math.max(1, maxHops - 1);
205
- const keepTokens = keepHops * 2;
206
- const head = parts.slice(0, keepTokens).join(arrow);
207
- const tail = parts[parts.length - 1];
208
- return `${head}${arrow}…${arrow}${tail}`;
209
- }
210
- export function formatCyclePathSegments(cycle, maxHops = 8) {
211
- const raw = [];
212
- for (let i = 0; i < cycle.edges.length; i += 1) {
213
- raw.push({ kind: 'component', text: cycle.path[i] });
214
- raw.push({ kind: 'slot', text: `[${cycle.edges[i].slotName}]` });
215
- }
216
- raw.push({ kind: 'component', text: cycle.path[cycle.path.length - 1] });
217
- const withArrows = (segs) => {
218
- const out = [];
219
- for (let i = 0; i < segs.length; i += 1) {
220
- if (i > 0)
221
- out.push({ kind: 'arrow', text: ' → ' });
222
- out.push(segs[i]);
223
- }
224
- return out;
225
- };
226
- if (cycle.edges.length <= maxHops) {
227
- return withArrows(raw);
228
- }
229
- const keepHops = Math.max(1, maxHops - 1);
230
- const keepTokens = keepHops * 2;
231
- const head = raw.slice(0, keepTokens);
232
- const tail = raw[raw.length - 1];
233
- return withArrows([...head, { kind: 'component', text: '…' }, tail]);
234
- }
@@ -1,28 +0,0 @@
1
- import { findSlotCycles } from './cycle-detection.js';
2
- import { buildComponentGraph } from './slot-graph.js';
3
- export function computeCycleView(components) {
4
- const filtered = components.filter((c) => c.status !== 'rejected');
5
- const filteredGraph = buildComponentGraph(filtered);
6
- const unfilteredGraph = buildComponentGraph(components);
7
- let pushBlocking = [];
8
- const structural = new Set();
9
- try {
10
- pushBlocking = findSlotCycles(filteredGraph);
11
- for (const cyc of pushBlocking)
12
- for (const p of cyc.path)
13
- structural.add(p);
14
- }
15
- catch {
16
- // Malformed slot data — intentional swallow.
17
- }
18
- try {
19
- const unfilteredCycles = findSlotCycles(unfilteredGraph);
20
- for (const cyc of unfilteredCycles)
21
- for (const p of cyc.path)
22
- structural.add(p);
23
- }
24
- catch {
25
- // Malformed slot data — intentional swallow.
26
- }
27
- return { pushBlocking, structural };
28
- }
@@ -1,55 +0,0 @@
1
- function match(query, text) {
2
- if (query.length === 0)
3
- return { score: 0 };
4
- if (text.length === 0)
5
- return null;
6
- const queryLower = query.toLowerCase();
7
- const textLower = text.toLowerCase();
8
- let score = 0;
9
- let qi = 0;
10
- let lastMatchIndex = -2;
11
- for (let ti = 0; ti < text.length && qi < query.length; ti++) {
12
- if (textLower[ti] === queryLower[qi]) {
13
- score += 10;
14
- if (text[ti] === query[qi]) {
15
- score += 5;
16
- }
17
- if (ti === 0 && qi === 0) {
18
- score += 15;
19
- }
20
- if (ti === lastMatchIndex + 1) {
21
- score += 5;
22
- }
23
- lastMatchIndex = ti;
24
- qi++;
25
- }
26
- }
27
- if (qi < query.length)
28
- return null;
29
- score -= text.length * 0.1;
30
- return { score };
31
- }
32
- export function fuzzyMatches(query, text) {
33
- return match(query, text) !== null;
34
- }
35
- export function fuzzyScore(query, text) {
36
- const result = match(query, text);
37
- return result === null ? null : result.score;
38
- }
39
- export function fuzzyFilter(query, candidates) {
40
- if (query.length === 0)
41
- return [...candidates];
42
- const scored = candidates
43
- .map((candidate, index) => ({
44
- candidate,
45
- index,
46
- score: fuzzyScore(query, candidate),
47
- }))
48
- .filter((entry) => entry.score !== null);
49
- scored.sort((a, b) => {
50
- if (b.score !== a.score)
51
- return b.score - a.score;
52
- return a.index - b.index;
53
- });
54
- return scored.map((entry) => entry.candidate);
55
- }
@@ -1,108 +0,0 @@
1
- const STATUS_RANK = { ok: 0, warning: 1, error: 2 };
2
- const RANK_STATUS = ['ok', 'warning', 'error'];
3
- function worstOf(statuses) {
4
- let worst = 0;
5
- for (const s of statuses) {
6
- const r = STATUS_RANK[s];
7
- if (r > worst)
8
- worst = r;
9
- }
10
- return RANK_STATUS[worst];
11
- }
12
- export function computeRenderStatuses(closure, directIssues) {
13
- const out = new Map();
14
- if (closure.nodes.length === 0)
15
- return out;
16
- const nodesByName = new Map();
17
- for (const node of closure.nodes) {
18
- nodesByName.set(node.name, { name: node.name, path: node.path });
19
- }
20
- // Descendant relationship: A is an ancestor of B iff A appears in B.path
21
- // (which is the shortest path from root to B) at a position before B. Note
22
- // this uses the ONE canonical shortest path. For pure-inheritance semantics
23
- // — a node has an inherited issue iff any node reachable from it in the
24
- // closure has an issue — we need transitive descendants. In this closure
25
- // model, every node's `path` field gives its shortest-path ancestor chain,
26
- // and every ancestor along that chain is transitively a "container" of that
27
- // node. That is sufficient here because the closure is rooted and a node is
28
- // reachable from the root iff it appears in the closure.
29
- const own = new Map();
30
- for (const node of closure.nodes) {
31
- const s = directIssues.get(node.name);
32
- if (s && s !== 'ok')
33
- own.set(node.name, s);
34
- }
35
- const inheritedSources = new Map();
36
- for (const node of closure.nodes) {
37
- const ownStatus = own.get(node.name);
38
- if (!ownStatus)
39
- continue;
40
- for (let i = 0; i < node.path.length - 1; i++) {
41
- const ancestor = node.path[i];
42
- if (!inheritedSources.has(ancestor))
43
- inheritedSources.set(ancestor, new Map());
44
- inheritedSources.get(ancestor).set(node.name, ownStatus);
45
- }
46
- }
47
- for (const [name, status] of own.entries()) {
48
- out.set(name, {
49
- status,
50
- isOwn: true,
51
- sourceComponents: [name],
52
- });
53
- }
54
- for (const [ancestor, sources] of inheritedSources.entries()) {
55
- if (out.has(ancestor))
56
- continue;
57
- const sourceNames = [...sources.keys()].sort();
58
- const status = worstOf([...sources.values()]);
59
- out.set(ancestor, {
60
- status,
61
- isOwn: false,
62
- sourceComponents: sourceNames,
63
- });
64
- }
65
- return out;
66
- }
67
- export function pickDrillTarget(ancestor, closure, directIssues) {
68
- const ancestorDirect = directIssues.get(ancestor);
69
- if (ancestorDirect && ancestorDirect !== 'ok')
70
- return null;
71
- const nodesByName = new Map();
72
- for (const node of closure.nodes)
73
- nodesByName.set(node.name, node);
74
- const ancestorNode = nodesByName.get(ancestor);
75
- if (!ancestorNode)
76
- return null;
77
- const candidates = [];
78
- const ancestorDepth = ancestorNode.path.length - 1;
79
- for (const node of closure.nodes) {
80
- if (node.name === ancestor)
81
- continue;
82
- const idx = node.path.indexOf(ancestor);
83
- if (idx === -1)
84
- continue;
85
- const status = directIssues.get(node.name);
86
- if (!status || status === 'ok')
87
- continue;
88
- // depthFromAncestor is number of edges between ancestor and node along
89
- // the shortest path from root. Since `path` is the shortest path from
90
- // root, path.length-1 == node.depth and idx == ancestor.depth along that
91
- // path, so distance = (node.path.length - 1) - idx.
92
- const depthFromAncestor = node.path.length - 1 - idx;
93
- void ancestorDepth;
94
- candidates.push({ name: node.name, status, depthFromAncestor });
95
- }
96
- if (candidates.length === 0)
97
- return null;
98
- candidates.sort((a, b) => {
99
- const rDiff = STATUS_RANK[b.status] - STATUS_RANK[a.status];
100
- if (rDiff !== 0)
101
- return rDiff;
102
- if (a.depthFromAncestor !== b.depthFromAncestor) {
103
- return a.depthFromAncestor - b.depthFromAncestor;
104
- }
105
- return a.name.localeCompare(b.name);
106
- });
107
- return candidates[0].name;
108
- }
Binary file
@@ -1,170 +0,0 @@
1
- import { findDirectParents } from './lineage.js';
2
- export function buildCycleUnits(slotCycles) {
3
- const parent = new Map();
4
- const find = (x) => {
5
- let cur = x;
6
- while (parent.get(cur) !== cur) {
7
- cur = parent.get(cur);
8
- }
9
- let walk = x;
10
- while (parent.get(walk) !== cur) {
11
- const next = parent.get(walk);
12
- parent.set(walk, cur);
13
- walk = next;
14
- }
15
- return cur;
16
- };
17
- const union = (a, b) => {
18
- const ra = find(a);
19
- const rb = find(b);
20
- if (ra !== rb)
21
- parent.set(ra, rb);
22
- };
23
- for (const cycle of slotCycles) {
24
- for (const node of cycle.path) {
25
- if (!parent.has(node))
26
- parent.set(node, node);
27
- }
28
- // `path` has the first node duplicated at the end; union with path[0] is
29
- // enough to link every node in the cycle.
30
- for (let i = 1; i < cycle.path.length; i++) {
31
- union(cycle.path[0], cycle.path[i]);
32
- }
33
- }
34
- const groups = new Map();
35
- for (const node of parent.keys()) {
36
- const root = find(node);
37
- let group = groups.get(root);
38
- if (!group) {
39
- group = new Set();
40
- groups.set(root, group);
41
- }
42
- group.add(node);
43
- }
44
- const out = new Map();
45
- for (const group of groups.values()) {
46
- for (const node of group) {
47
- out.set(node, group);
48
- }
49
- }
50
- return out;
51
- }
52
- function slotTargets(node, byName) {
53
- const c = byName.get(node);
54
- if (!c)
55
- return [];
56
- const seen = new Set();
57
- const out = [];
58
- for (const slot of c.slots) {
59
- for (const target of slot.allowedComponents ?? []) {
60
- if (!byName.has(target))
61
- continue;
62
- if (seen.has(target))
63
- continue;
64
- seen.add(target);
65
- out.push(target);
66
- }
67
- }
68
- return out;
69
- }
70
- export function computeCycleAwareAcceptCascade(target, components, cycleUnits) {
71
- const byName = new Map(components.map((c) => [c.name, c]));
72
- const visited = new Set();
73
- const queue = [];
74
- const enqueue = (name) => {
75
- if (visited.has(name))
76
- return;
77
- visited.add(name);
78
- queue.push(name);
79
- // Cohesion: touching any cycle member pulls its whole unit along.
80
- const unit = cycleUnits.get(name);
81
- if (unit) {
82
- for (const member of unit) {
83
- if (!visited.has(member)) {
84
- visited.add(member);
85
- queue.push(member);
86
- }
87
- }
88
- }
89
- };
90
- enqueue(target);
91
- while (queue.length > 0) {
92
- const cur = queue.shift();
93
- for (const next of slotTargets(cur, byName)) {
94
- enqueue(next);
95
- }
96
- }
97
- return visited;
98
- }
99
- export function computeCycleAwareRejectCascade(target, components, cycleUnits) {
100
- const toReject = new Set();
101
- const targetUnit = cycleUnits.get(target);
102
- const initialSeeds = targetUnit ? [...targetUnit] : [target];
103
- for (const seed of initialSeeds)
104
- toReject.add(seed);
105
- // Walk ancestors. Whenever a newly-added node happens to be a cycle
106
- // member, splice in its whole cycle unit and keep walking from each unit
107
- // member. Terminates because every add is idempotent against `toReject`.
108
- const stack = [...toReject];
109
- while (stack.length > 0) {
110
- const cur = stack.pop();
111
- for (const { parent } of findDirectParents(cur, components)) {
112
- if (toReject.has(parent))
113
- continue;
114
- toReject.add(parent);
115
- stack.push(parent);
116
- const unit = cycleUnits.get(parent);
117
- if (unit) {
118
- for (const member of unit) {
119
- if (!toReject.has(member)) {
120
- toReject.add(member);
121
- stack.push(member);
122
- }
123
- }
124
- }
125
- }
126
- }
127
- const acceptCascade = computeCycleAwareAcceptCascade(target, components, cycleUnits);
128
- const toDeselect = new Set();
129
- for (const n of acceptCascade) {
130
- if (toReject.has(n))
131
- continue;
132
- toDeselect.add(n);
133
- }
134
- const cyclePartners = [];
135
- if (targetUnit) {
136
- for (const m of targetUnit) {
137
- if (m !== target)
138
- cyclePartners.push(m);
139
- }
140
- cyclePartners.sort();
141
- }
142
- return { toReject, toDeselect, cyclePartners };
143
- }
144
- export function collectReachableCycleUnits(seeds, components, cycleUnits) {
145
- const out = new Set();
146
- if (cycleUnits.size === 0)
147
- return out;
148
- const byName = new Map(components.map((c) => [c.name, c]));
149
- const visited = new Set();
150
- const queue = [...seeds];
151
- while (queue.length > 0) {
152
- const cur = queue.shift();
153
- if (visited.has(cur))
154
- continue;
155
- visited.add(cur);
156
- const unit = cycleUnits.get(cur);
157
- if (unit) {
158
- for (const member of unit) {
159
- out.add(member);
160
- if (!visited.has(member))
161
- queue.push(member);
162
- }
163
- }
164
- for (const next of slotTargets(cur, byName)) {
165
- if (!visited.has(next))
166
- queue.push(next);
167
- }
168
- }
169
- return out;
170
- }
@@ -1,56 +0,0 @@
1
- export function computeDirectNeighborhood(matches, graph) {
2
- const matchSet = new Set(matches);
3
- const out = new Set(matchSet);
4
- if (matchSet.size === 0)
5
- return out;
6
- for (const node of graph) {
7
- const targets = [];
8
- for (const slot of node.slots) {
9
- for (const t of slot.allowedComponents ?? [])
10
- targets.push(t);
11
- }
12
- if (matchSet.has(node.name)) {
13
- for (const t of targets)
14
- out.add(t);
15
- }
16
- for (const t of targets) {
17
- if (matchSet.has(t)) {
18
- out.add(node.name);
19
- break;
20
- }
21
- }
22
- }
23
- return out;
24
- }
25
- export function findAllAncestors(target, graph) {
26
- const out = new Set([target]);
27
- const parentsOf = new Map();
28
- for (const node of graph) {
29
- for (const slot of node.slots) {
30
- for (const child of slot.allowedComponents ?? []) {
31
- const list = parentsOf.get(child);
32
- if (list) {
33
- if (!list.includes(node.name))
34
- list.push(node.name);
35
- }
36
- else {
37
- parentsOf.set(child, [node.name]);
38
- }
39
- }
40
- }
41
- }
42
- const queue = [target];
43
- while (queue.length > 0) {
44
- const cur = queue.shift();
45
- const parents = parentsOf.get(cur);
46
- if (!parents)
47
- continue;
48
- for (const p of parents) {
49
- if (out.has(p))
50
- continue;
51
- out.add(p);
52
- queue.push(p);
53
- }
54
- }
55
- return out;
56
- }