@knapsack/source-conflicts-adapter 4.89.11 → 4.89.12--canary.7237.e7e94a1.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 (60) hide show
  1. package/README.md +110 -66
  2. package/dist/analyzer.d.ts +12 -20
  3. package/dist/analyzer.d.ts.map +1 -1
  4. package/dist/analyzer.js +41 -25
  5. package/dist/analyzer.js.map +1 -1
  6. package/dist/analyzer.vitest.js +31 -2
  7. package/dist/analyzer.vitest.js.map +1 -1
  8. package/dist/detect.d.ts +3 -3
  9. package/dist/detect.js +14 -14
  10. package/dist/detect.js.map +1 -1
  11. package/dist/detect.vitest.js +16 -16
  12. package/dist/detect.vitest.js.map +1 -1
  13. package/dist/index.d.ts +5 -5
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/json/jsonConflicts.d.ts +5 -7
  18. package/dist/json/jsonConflicts.d.ts.map +1 -1
  19. package/dist/json/jsonConflicts.js +22 -61
  20. package/dist/json/jsonConflicts.js.map +1 -1
  21. package/dist/json/jsonConflicts.vitest.js +13 -44
  22. package/dist/json/jsonConflicts.vitest.js.map +1 -1
  23. package/dist/mdx/mdxConflicts.d.ts +19 -20
  24. package/dist/mdx/mdxConflicts.d.ts.map +1 -1
  25. package/dist/mdx/mdxConflicts.js +106 -120
  26. package/dist/mdx/mdxConflicts.js.map +1 -1
  27. package/dist/mdx/mdxConflicts.vitest.js +295 -10
  28. package/dist/mdx/mdxConflicts.vitest.js.map +1 -1
  29. package/dist/mdx/tableMdx.d.ts +5 -0
  30. package/dist/mdx/tableMdx.d.ts.map +1 -1
  31. package/dist/mdx/tableMdx.js +10 -0
  32. package/dist/mdx/tableMdx.js.map +1 -1
  33. package/dist/multiSourceCompare.d.ts +2 -3
  34. package/dist/multiSourceCompare.d.ts.map +1 -1
  35. package/dist/multiSourceCompare.js +2 -3
  36. package/dist/multiSourceCompare.js.map +1 -1
  37. package/dist/multiSourceCompare.vitest.js +4 -4
  38. package/dist/multiSourceCompare.vitest.js.map +1 -1
  39. package/dist/parser.js +1 -1
  40. package/dist/transformer.d.ts.map +1 -1
  41. package/dist/transformer.js +0 -7
  42. package/dist/transformer.js.map +1 -1
  43. package/dist/types.d.ts +83 -12
  44. package/dist/types.d.ts.map +1 -1
  45. package/dist/types.js.map +1 -1
  46. package/dist/utils/entityKey.d.ts +11 -0
  47. package/dist/utils/entityKey.d.ts.map +1 -0
  48. package/dist/utils/entityKey.js +31 -0
  49. package/dist/utils/entityKey.js.map +1 -0
  50. package/dist/utils/entityKey.vitest.d.ts +2 -0
  51. package/dist/utils/entityKey.vitest.d.ts.map +1 -0
  52. package/dist/utils/entityKey.vitest.js +41 -0
  53. package/dist/utils/entityKey.vitest.js.map +1 -0
  54. package/dist/utils/fingerprint.d.ts +12 -0
  55. package/dist/utils/fingerprint.d.ts.map +1 -0
  56. package/dist/utils/fingerprint.js +17 -0
  57. package/dist/utils/fingerprint.js.map +1 -0
  58. package/example/demo-output.json +953 -0
  59. package/example/run-demo.mjs +21 -0
  60. package/package.json +7 -6
package/README.md CHANGED
@@ -13,7 +13,7 @@ When the same entity (e.g. `button.react.mdx` or `global.tokens.json`) is contri
13
13
  3. **Detects** conflicts by comparing content across sources:
14
14
  - **MDX/MD**: parses into anchored sections, applies a chain of canonicalization rules
15
15
  - **JSON (W3C Design Token)**: flattens token leaves (`$value`) to anchors, compares by exact hash
16
- 4. **Reports** per-anchor verdicts: `ALL_SAME`, `DIFFERENT`, or `MISSING`
16
+ 4. **Reports** per-anchor verdicts: `DIFFERENT` or `MISSING` (only conflicting anchors are included — `ALL_SAME` anchors are filtered out)
17
17
 
18
18
  ### Entity file layout
19
19
 
@@ -39,27 +39,25 @@ This package lives in the monorepo at `libs/ingest-pipeline/adapters/source-conf
39
39
 
40
40
  ---
41
41
 
42
- ## Quick start — standalone analyzer
42
+ ## Quick start — `run()`
43
43
 
44
- The fastest way to detect conflicts without running the full pipeline is via the `analyzer` interface:
44
+ The fastest way to detect conflicts without running the full pipeline is via `run()`:
45
45
 
46
46
  ```typescript
47
- import * as fs from 'node:fs/promises';
48
- import * as path from 'node:path';
49
- import { analyze } from '@knapsack/source-conflicts-adapter';
47
+ import { run } from '@knapsack/source-conflicts-adapter';
50
48
  import { createLogger } from '@knapsack/utils';
51
49
 
52
- const entitiesRootAbs = '/absolute/path/to/entities';
53
- const outputFile = path.join(entitiesRootAbs, 'source-conflicts-result.json');
54
- const logger = createLogger('source-conflicts');
55
-
56
- const result = await analyze({ entitiesRootAbs }, { logger });
50
+ const report = await run({
51
+ entitiesRootAbs: '/absolute/path/to/entities',
52
+ outputPath: '/absolute/path/to/output.json', // optional
53
+ logger: createLogger('source-conflicts'),
54
+ });
57
55
 
58
- await fs.writeFile(outputFile, JSON.stringify(result, null, 2), 'utf8');
59
- console.log(`Wrote results to ${outputFile}`);
56
+ console.log(`Entities: ${report.summary.entityCount}`);
57
+ console.log(`Conflicts: ${report.summary.totalConflicts}`);
60
58
  ```
61
59
 
62
- The output file contains the full `SourceConflictsAnalysisResult` as JSON `groupResults` with per-anchor verdicts and previews, plus `skippedGroupKeys` for any groups that were excluded.
60
+ `run()` scans the entities directory, detects all conflicts, and returns a `ConflictReport`. When `outputPath` is provided, the report is also written as JSON.
63
61
 
64
62
  ---
65
63
 
@@ -108,9 +106,35 @@ const result = await sourceConflictsAdapter.analyzer!.analyze(config, {
108
106
 
109
107
  ---
110
108
 
111
- ## Result shape
109
+ ## Result shapes
112
110
 
113
- ### `SourceConflictsAnalysisResult`
111
+ ### `ConflictReport` (from `run()`)
112
+
113
+ ```typescript
114
+ type ConflictReport = {
115
+ generatedAt: string;
116
+ entitiesRootAbs: string;
117
+ entities: ConflictReportEntity[];
118
+ summary: {
119
+ entityCount: number;
120
+ totalConflicts: number;
121
+ differentCount: number;
122
+ missingCount: number;
123
+ };
124
+ };
125
+
126
+ type ConflictReportEntity = {
127
+ entityKey: string;
128
+ entityType: EntityKind;
129
+ entityRelPath: string;
130
+ /** Source key URIs of all sources involved in this entity. */
131
+ sources: string[];
132
+ /** DIFFERENT and MISSING anchors only. */
133
+ conflicts: AnchorDiffView[];
134
+ };
135
+ ```
136
+
137
+ ### `SourceConflictsAnalysisResult` (from `analyze()`)
114
138
 
115
139
  ```typescript
116
140
  type SourceConflictsAnalysisResult = {
@@ -125,24 +149,63 @@ type SourceConflictsAnalysisResult = {
125
149
 
126
150
  ```typescript
127
151
  type ConflictGroupResult = {
128
- group: ConflictGroup; // entityKind, relPath, artifacts[]
129
- bundle: ConflictBundle; // source-agnostic per-anchor snapshot (serializable — store in DB)
130
- baselineSourceKey: string; // frontmatter URI of the baseline source, e.g. "knapsack://patterns/button"
131
- compareSourceKeys: string[]; // frontmatter URIs of compare sources (up to MAX_COMPARE_SOURCES)
132
- verdicts: AnchorVerdictView[]; // per-anchor verdict derived from bundle for this baseline/compare
152
+ group: ConflictGroup; // entityType, relPath, artifacts[]
153
+ bundle: ConflictBundle; // source-agnostic per-anchor snapshot (serializable — store in DB)
154
+ anchors: AnchorDiffView[]; // DIFFERENT and MISSING anchors only
133
155
  };
134
156
  ```
135
157
 
136
- `bundle` is a fully-serializable JSON snapshot — no functions, no circular refs. Storing it once and calling `computeVerdictsForBaselineCompare` with different baseline/compare args is the recommended pattern (see [Option A](#option-a--bundle-first-pattern)).
158
+ `bundle` is a fully-serializable JSON snapshot — no functions, no circular refs.
159
+
160
+ ### `AnchorDiffView`
161
+
162
+ ```typescript
163
+ type AnchorDiffView = {
164
+ readonly anchor: string;
165
+ readonly verdict: 'DIFFERENT' | 'MISSING';
166
+ /**
167
+ * One entry per distinct canonical form — sources that share the same hash are grouped.
168
+ * Present when verdict is DIFFERENT or MISSING (and at least one source has a value).
169
+ */
170
+ readonly variants?: AnchorVariant[];
171
+ /**
172
+ * All pairwise unified diffs (n*(n-1)/2 pairs).
173
+ * Present when verdict is DIFFERENT and text values are available.
174
+ */
175
+ readonly diffs?: AnchorPairDiff[];
176
+ /**
177
+ * Source key URIs of sources that have no definition for this anchor.
178
+ * Present when verdict is MISSING.
179
+ */
180
+ readonly missingSourceKeys?: string[];
181
+ };
182
+
183
+ type AnchorVariant = {
184
+ /** Source key URIs that share this canonical form. */
185
+ readonly sourceKeys: string[];
186
+ /** Canonical text (may be truncated by PreviewBounds). */
187
+ readonly text: string;
188
+ /** Language hint for syntax highlighting. Present for code fence anchors. */
189
+ readonly lang?: string;
190
+ };
191
+
192
+ type AnchorPairDiff = {
193
+ readonly fromSourceKeys: string[];
194
+ readonly toSourceKeys: string[];
195
+ /** Unified diff string (GNU patch format). */
196
+ readonly unifiedDiff: string;
197
+ };
198
+ ```
137
199
 
138
200
  ### `ConflictItemRecord` (inside `ConflictBundle.items`)
139
201
 
140
202
  ```typescript
141
203
  type ConflictItemRecord = {
142
204
  fingerprint: string;
143
- sourceType: SourceType; // filename-parsed, e.g. "KNAPSACK" used internally for matching
144
- sourceKey: string; // URI, e.g. "knapsack://patterns/button" — use this for display and storage
145
- // MDX: read from YAML frontmatter; JSON: read from $extensions.pcif.sourceKey
205
+ /** Filename-parsed source type (e.g. "KNAPSACK"). Used internally for matching. */
206
+ sourceType: SourceType;
207
+ /** URI, e.g. "knapsack://patterns/button". The authoritative source identifier. */
208
+ sourceKey: string;
146
209
  frontmatterSchemaVersion: number;
147
210
  frontmatter: Record<string, unknown>; // MDX: YAML frontmatter; JSON: $extensions.pcif contents
148
211
  };
@@ -150,61 +213,38 @@ type ConflictItemRecord = {
150
213
 
151
214
  ### Verdicts
152
215
 
153
- | Value | Meaning |
154
- | ----------- | --------------------------------------------------------------------- |
155
- | `ALL_SAME` | All sources agree (or content was unified by a canonicalization rule) |
156
- | `DIFFERENT` | At least one source has different content for this anchor |
157
- | `MISSING` | At least one source does not contain this anchor |
158
-
159
- ---
216
+ | Value | Meaning |
217
+ | ----------- | ----------------------------------------------------------------- |
218
+ | `DIFFERENT` | At least one source has different content for this anchor |
219
+ | `MISSING` | At least one source does not contain this anchor |
160
220
 
161
- ## Option A bundle-first pattern
221
+ `ALL_SAME` anchors (where all sources agree) are excluded from `anchors` / `conflicts` output.
162
222
 
163
- `ConflictBundle` is the stable stored artifact. `computeVerdictsForBaselineCompare` is a pure function that derives verdicts from any stored bundle with no I/O or re-parsing.
223
+ ---
164
224
 
165
- ### Recommended DB/GraphQL pattern
225
+ ## Bundle-first pattern
166
226
 
167
- 1. **Store** the bundle when running the detection pipeline.
168
- 2. **Load** the bundle from storage when serving a request.
169
- 3. **Call** `computeVerdictsForBaselineCompare` with the caller-specified baseline/compare source URIs.
227
+ `ConflictBundle` is the stable stored artifact. `computeDiffsForAllSources` is a pure function that derives diffs from any stored bundle with no I/O or re-parsing.
170
228
 
171
229
  ```typescript
172
230
  import {
173
- computeVerdictsForBaselineCompare,
231
+ computeDiffsForAllSources,
174
232
  getAvailableSourceKeysFromBundle,
175
233
  } from '@knapsack/source-conflicts-adapter';
176
234
  import type { ConflictBundle } from '@knapsack/source-conflicts-adapter';
177
235
 
178
- // Load stored bundle from DB (JSON column → parse → use directly, no re-detection)
236
+ // Load stored bundle from DB (JSON column → parse → use directly)
179
237
  const bundle: ConflictBundle = JSON.parse(row.bundleJson);
180
238
 
181
- // Discover which source URIs are available without re-detecting
239
+ // Discover which source URIs are available
182
240
  const available = getAvailableSourceKeysFromBundle(bundle);
183
241
  // e.g. ["knapsack://patterns/button", "storybook://components/button"]
184
242
 
185
- // Derive verdicts for any baseline/compare combination — instant, no I/O
186
- const verdicts = computeVerdictsForBaselineCompare(
187
- bundle,
188
- 'knapsack://patterns/button', // baseline URI
189
- ['storybook://components/button'], // compare URIs
190
- );
191
-
192
- // Swap baseline without re-detecting — just call again
193
- const swappedVerdicts = computeVerdictsForBaselineCompare(
194
- bundle,
195
- 'storybook://components/button',
196
- ['knapsack://patterns/button'],
197
- );
198
- ```
199
-
200
- ### `getAvailableSourceKeysFromBundle`
201
-
202
- ```typescript
203
- function getAvailableSourceKeysFromBundle(bundle: ConflictBundle): string[];
243
+ // Derive diffs across all sources — instant, no I/O
244
+ const anchors = computeDiffsForAllSources(bundle);
245
+ // Returns only DIFFERENT and MISSING anchors
204
246
  ```
205
247
 
206
- Returns the frontmatter source URI (`sourceKey`) for every item in the bundle. Any of these can be passed as `baselineSourceKey` to `computeVerdictsForBaselineCompare` without re-running detection. Sources in `bundle.excludedSourceKeys` (if any, when `MAX_COMPARE_SOURCES` is exceeded) are **not** in the bundle and cannot be used as baseline without a full re-detect.
207
-
208
248
  ---
209
249
 
210
250
  ## Comparison rules
@@ -256,19 +296,21 @@ src/
256
296
  ├── index.ts # Adapter export + public API re-exports
257
297
  ├── types.ts # Shared types: SourceConflictsConfig, ArtifactRef, ConflictGroup,
258
298
  │ # ConflictBundle, ConflictRecord, ConflictItemRecord,
259
- │ # AgnosticDefinition, AnchorDefinitionsRecord, AnchorVerdictView,
260
- │ # VERDICT, Rule, CanonicalizeContext, PreviewBounds
299
+ │ # AgnosticDefinition, AnchorDefinitionsRecord,
300
+ │ # AnchorDiffView, AnchorVariant, AnchorPairDiff,
301
+ │ # ConflictReport, ConflictReportEntity, VERDICT, Rule,
302
+ │ # CanonicalizeContext, PreviewBounds
261
303
  ├── validator.ts # validateConfig / validateFull
262
304
  ├── parser.ts # parse() — indexes entities, writes manifest
263
305
  ├── transformer.ts # transform() — runs detection, writes verdict bundles
264
- ├── analyzer.ts # analyze() — in-process detection, returns typed result
306
+ ├── analyzer.ts # analyze() / run() — in-process detection, returns typed result
265
307
  ├── detect.ts # indexEntitiesDir / findConflictGroups (filesystem)
266
308
  ├── parse.ts # parseEntityKind / parseSourceType (filename parsing)
267
309
  ├── multiSourceCompare.ts # compareAnchorMultiSource (rule engine)
268
310
  ├── compare/
269
311
  │ └── preview.ts # Preview/truncation helpers
270
312
  ├── mdx/
271
- │ ├── mdxConflicts.ts # detectMdxConflictBundle / computeVerdictsForBaselineCompare
313
+ │ ├── mdxConflicts.ts # detectMdxConflictBundle / computeDiffsForAllSources
272
314
  │ ├── mdxRules.ts # Built-in canonicalization rules
273
315
  │ ├── tableMdx.ts # Table parsing / canonicalization
274
316
  │ └── sharedProcessor.ts # Shared remark processor
@@ -276,6 +318,8 @@ src/
276
318
  │ └── jsonConflicts.ts # detectJsonConflictBundle / flattenTokenAnchors / extractJsonSourceKey
277
319
  └── utils/
278
320
  ├── canonicalCache.ts # In-memory canonical result cache (sha256)
321
+ ├── entityKey.ts # parseGroupKey — shared entity key parsing for MDX and JSON
322
+ ├── fingerprint.ts # computeFingerprintV1 — entity-level fingerprint
279
323
  └── frontmatter.ts # Frontmatter parsing helpers
280
324
  ```
281
325
 
@@ -1,29 +1,21 @@
1
1
  import type { Logger } from '@knapsack/adapter-core';
2
- import type { SourceConflictsConfig } from './types.js';
3
- import type { AnchorVerdictView, ConflictBundle } from './types.js';
4
- import type { ConflictGroup } from './types.js';
5
- export type ConflictGroupResult = {
6
- group: ConflictGroup;
7
- bundle: ConflictBundle;
8
- /** Frontmatter sourceKey URI of the baseline source (e.g. "knapsack://patterns/button"). */
9
- baselineSourceKey: string;
10
- /** Frontmatter sourceKey URIs of the compare sources. */
11
- compareSourceKeys: string[];
12
- verdicts: AnchorVerdictView[];
13
- };
14
- export type SourceConflictsAnalysisResult = {
15
- groupResults: ConflictGroupResult[];
16
- /** Groups that were skipped (non-MDX or not enough sources). */
17
- skippedGroupKeys: string[];
2
+ import type { SourceConflictsConfig, ConflictBundle, SourceConflictsAnalysisResult, ConflictReport } from './types.js';
3
+ export type RunOptions = SourceConflictsConfig & {
4
+ readonly logger: Logger;
5
+ /** When provided, the report JSON is written to this path. */
6
+ readonly outputPath?: string;
18
7
  };
19
8
  export declare function analyze(config: SourceConflictsConfig, deps: Pick<{
20
9
  logger: Logger;
21
10
  }, 'logger'>): Promise<SourceConflictsAnalysisResult>;
22
11
  /**
23
- * Returns the source keys present in a stored bundle.
24
- * Any of these can be passed as `baselineSourceKey` to
25
- * `computeVerdictsForBaselineCompare` without re-running detection.
26
- * Sources in `bundle.excludedSourceKeys` are NOT available.
12
+ * Returns the source keys of all sources present in a stored bundle.
13
+ * Useful for inspecting which sources contributed to a previously detected conflict.
27
14
  */
28
15
  export declare function getAvailableSourceKeysFromBundle(bundle: ConflictBundle): string[];
16
+ /**
17
+ * Scan an entities directory, detect all conflicts, and return a structured report.
18
+ * Optionally writes the report as JSON to outputPath.
19
+ */
20
+ export declare function run(options: RunOptions): Promise<ConflictReport>;
29
21
  //# sourceMappingURL=analyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAQxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,4FAA4F;IAC5F,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,gEAAgE;IAChE,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAsB,OAAO,CAC3B,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,IAAI,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,CAAC,GACvC,OAAO,CAAC,6BAA6B,CAAC,CA4ExC;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,cAAc,GACrB,MAAM,EAAE,CAEV"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,qBAAqB,EACrB,cAAc,EAEd,6BAA6B,EAC7B,cAAc,EAEf,MAAM,YAAY,CAAC;AAQpB,MAAM,MAAM,UAAU,GAAG,qBAAqB,GAAG;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,wBAAsB,OAAO,CAC3B,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE,IAAI,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,CAAC,GACvC,OAAO,CAAC,6BAA6B,CAAC,CAiDxC;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,cAAc,GACrB,MAAM,EAAE,CAEV;AAED;;;GAGG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAkCtE"}
package/dist/analyzer.js CHANGED
@@ -1,5 +1,6 @@
1
+ import * as fs from 'node:fs/promises';
1
2
  import { indexEntitiesDir, findConflictGroups } from './detect.js';
2
- import { detectMdxConflictBundle, computeVerdictsForBaselineCompare, MAX_COMPARE_SOURCES, MIN_COMPARE_SOURCES, } from './mdx/mdxConflicts.js';
3
+ import { detectMdxConflictBundle, computeDiffsForAllSources, } from './mdx/mdxConflicts.js';
3
4
  import { detectJsonConflictBundle } from './json/jsonConflicts.js';
4
5
  export async function analyze(config, deps) {
5
6
  const { logger } = deps;
@@ -14,20 +15,15 @@ export async function analyze(config, deps) {
14
15
  skippedGroupKeys.push(group.key);
15
16
  continue;
16
17
  }
17
- const sources = [
18
- ...new Set(group.artifacts.map((a) => a.sourceKey)),
19
- ].sort();
20
- if (sources.length < 1 + MIN_COMPARE_SOURCES) {
18
+ // Require at least 2 distinct source types. No upper limit — all sources are compared equally.
19
+ const uniqueSources = new Set(group.artifacts.map((a) => a.sourceType));
20
+ if (uniqueSources.size < 2) {
21
21
  skippedGroupKeys.push(group.key);
22
22
  continue;
23
23
  }
24
- const baselineSourceKey = sources[0];
25
- const compareSourceKeys = sources.slice(1, 1 + MAX_COMPARE_SOURCES);
26
24
  const detectArgs = {
27
25
  groupKey: group.key,
28
26
  artifacts: group.artifacts,
29
- baselineSourceKey,
30
- compareSourceKeys,
31
27
  siteId: config.siteId,
32
28
  userId: config.userId,
33
29
  configId: config.configId,
@@ -40,28 +36,48 @@ export async function analyze(config, deps) {
40
36
  skippedGroupKeys.push(group.key);
41
37
  continue;
42
38
  }
43
- // Map filename-parsed SourceType → frontmatter URI using bundle.items.
44
- const getUri = (st) => bundle.items.find((i) => i.sourceType === st)?.sourceKey ?? st;
45
- const baselineUri = getUri(baselineSourceKey);
46
- const compareUris = compareSourceKeys.map(getUri);
47
- const verdicts = computeVerdictsForBaselineCompare(bundle, baselineUri, compareUris);
48
- groupResults.push({
49
- group,
50
- bundle,
51
- baselineSourceKey: baselineUri,
52
- compareSourceKeys: compareUris,
53
- verdicts,
54
- });
39
+ const anchors = computeDiffsForAllSources(bundle);
40
+ groupResults.push({ group, bundle, anchors });
55
41
  }
56
42
  return { groupResults, skippedGroupKeys };
57
43
  }
58
44
  /**
59
- * Returns the source keys present in a stored bundle.
60
- * Any of these can be passed as `baselineSourceKey` to
61
- * `computeVerdictsForBaselineCompare` without re-running detection.
62
- * Sources in `bundle.excludedSourceKeys` are NOT available.
45
+ * Returns the source keys of all sources present in a stored bundle.
46
+ * Useful for inspecting which sources contributed to a previously detected conflict.
63
47
  */
64
48
  export function getAvailableSourceKeysFromBundle(bundle) {
65
49
  return bundle.items.map((item) => item.sourceKey);
66
50
  }
51
+ /**
52
+ * Scan an entities directory, detect all conflicts, and return a structured report.
53
+ * Optionally writes the report as JSON to outputPath.
54
+ */
55
+ export async function run(options) {
56
+ const { logger, outputPath, ...config } = options;
57
+ const { groupResults } = await analyze(config, { logger });
58
+ const entities = groupResults.map(({ group, bundle, anchors }) => ({
59
+ entityKey: group.key,
60
+ entityType: group.entityType,
61
+ entityRelPath: group.relPath,
62
+ sources: bundle.items.map((i) => i.sourceKey).sort(),
63
+ conflicts: anchors,
64
+ }));
65
+ const allConflicts = entities.flatMap((e) => e.conflicts);
66
+ const report = {
67
+ generatedAt: new Date().toISOString(),
68
+ entitiesRootAbs: config.entitiesRootAbs,
69
+ entities,
70
+ summary: {
71
+ conflictingEntityCount: entities.length,
72
+ totalConflicts: allConflicts.length,
73
+ differentCount: allConflicts.filter((c) => c.verdict === 'DIFFERENT')
74
+ .length,
75
+ missingCount: allConflicts.filter((c) => c.verdict === 'MISSING').length,
76
+ },
77
+ };
78
+ if (outputPath) {
79
+ await fs.writeFile(outputPath, JSON.stringify(report, null, 2), 'utf8');
80
+ }
81
+ return report;
82
+ }
67
83
  //# sourceMappingURL=analyzer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,9 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { getAvailableSourceKeysFromBundle } from './analyzer.js';
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { getAvailableSourceKeysFromBundle, run } from './analyzer.js';
3
+ vi.mock('./detect.js', () => ({
4
+ indexEntitiesDir: vi.fn().mockResolvedValue([]),
5
+ findConflictGroups: vi.fn().mockReturnValue([]),
6
+ }));
3
7
  function makeBundle(items) {
4
8
  return {
5
9
  conflict: {
@@ -14,6 +18,31 @@ function makeBundle(items) {
14
18
  anchorDefinitions: [],
15
19
  };
16
20
  }
21
+ const silentLogger = {
22
+ debug: () => { },
23
+ info: () => { },
24
+ warn: () => { },
25
+ error: () => { },
26
+ };
27
+ describe('run() summary', () => {
28
+ it('returns zero counts when there are no conflicting groups', async () => {
29
+ const report = await run({
30
+ entitiesRootAbs: '/fake/entities',
31
+ logger: silentLogger,
32
+ });
33
+ expect(report.summary.conflictingEntityCount).toBe(0);
34
+ expect(report.summary.totalConflicts).toBe(0);
35
+ expect(report.summary.differentCount).toBe(0);
36
+ expect(report.summary.missingCount).toBe(0);
37
+ });
38
+ it('totalConflicts equals differentCount + missingCount', async () => {
39
+ const report = await run({
40
+ entitiesRootAbs: '/fake/entities',
41
+ logger: silentLogger,
42
+ });
43
+ expect(report.summary.totalConflicts).toBe(report.summary.differentCount + report.summary.missingCount);
44
+ });
45
+ });
17
46
  describe('getAvailableSourceKeysFromBundle', () => {
18
47
  it('returns URI sourceKeys for all items in the bundle', () => {
19
48
  const bundle = makeBundle([
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.vitest.js","sourceRoot":"","sources":["../src/analyzer.vitest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,gCAAgC,EAAE,MAAM,eAAe,CAAC;AAEjE,SAAS,UAAU,CAAC,KAA8B;IAChD,OAAO;QACL,QAAQ,EAAE;YACR,SAAS,EAAE,wBAAwB;YACnC,UAAU,EAAE,WAAW;YACvB,aAAa,EAAE,cAAc;YAC7B,WAAW,EAAE,WAAW;YACxB,SAAS,EAAE,sBAAsB;YACjC,SAAS,EAAE,sBAAsB;SAClC;QACD,KAAK;QACL,iBAAiB,EAAE,EAAE;KACtB,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,UAAU,CAAC;YACxB;gBACE,WAAW,EAAE,KAAK;gBAClB,UAAU,EAAE,UAAU;gBACtB,SAAS,EAAE,4BAA4B;gBACvC,wBAAwB,EAAE,CAAC;gBAC3B,WAAW,EAAE,EAAE;aAChB;YACD;gBACE,WAAW,EAAE,KAAK;gBAClB,UAAU,EAAE,WAAW;gBACvB,SAAS,EAAE,+BAA+B;gBAC1C,wBAAwB,EAAE,CAAC;gBAC3B,WAAW,EAAE,EAAE;aAChB;SACF,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;YACnB,4BAA4B;YAC5B,+BAA+B;SAChC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,gCAAgC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,UAAU,CAAC;YACxB;gBACE,WAAW,EAAE,KAAK;gBAClB,UAAU,EAAE,UAAU;gBACtB,SAAS,EAAE,4BAA4B;gBACvC,wBAAwB,EAAE,CAAC;gBAC3B,WAAW,EAAE,EAAE;aAChB;SACF,CAAC,CAAC;QACH,MAAM,CAAC,gCAAgC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YACvD,4BAA4B;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"analyzer.vitest.js","sourceRoot":"","sources":["../src/analyzer.vitest.ts"],"names":[],"mappings":"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"}
package/dist/detect.d.ts CHANGED
@@ -2,10 +2,10 @@ import type { Logger } from '@knapsack/adapter-core';
2
2
  import type { ArtifactRef, ConflictGroup } from './types.js';
3
3
  export type { ArtifactRef, ConflictGroup } from './types.js';
4
4
  /**
5
- * Index filesystem artifacts by (entityKind + canonical relPath).
5
+ * Index filesystem artifacts by (entityType + canonical relPath).
6
6
  *
7
- * Expected layout: entities/<entityKind>/<base>.<sourceType>-<hash>.<ext>
8
- * Same entity = same entityKind + same base name (e.g. button.react.mdx or button.react.md);
7
+ * Expected layout: entities/<entityType>/<base>.<sourceType>-<hash>.<ext>
8
+ * Same entity = same entityType + same base name (e.g. button.react.mdx or button.react.md);
9
9
  * sourceType and hash are read from the filename.
10
10
  */
11
11
  export declare function indexEntitiesDir(entitiesRootAbs: string, logger: Logger): Promise<Map<string, ArtifactRef[]>>;
package/dist/detect.js CHANGED
@@ -32,18 +32,18 @@ function parseArtifactFilename(filename) {
32
32
  const hash = sourceTypeHash.slice(dashIdx + 1);
33
33
  if (!rawSourceType || !hash)
34
34
  return null;
35
- const sourceKey = parseSourceType(rawSourceType);
36
- if (!sourceKey)
35
+ const sourceType = parseSourceType(rawSourceType);
36
+ if (!sourceType)
37
37
  return null;
38
38
  const base = parts.join('.');
39
39
  const relPath = `${base}.${ext}`;
40
- return { relPath, sourceKey, hash };
40
+ return { relPath, sourceType, hash };
41
41
  }
42
42
  /**
43
- * Index filesystem artifacts by (entityKind + canonical relPath).
43
+ * Index filesystem artifacts by (entityType + canonical relPath).
44
44
  *
45
- * Expected layout: entities/<entityKind>/<base>.<sourceType>-<hash>.<ext>
46
- * Same entity = same entityKind + same base name (e.g. button.react.mdx or button.react.md);
45
+ * Expected layout: entities/<entityType>/<base>.<sourceType>-<hash>.<ext>
46
+ * Same entity = same entityType + same base name (e.g. button.react.mdx or button.react.md);
47
47
  * sourceType and hash are read from the filename.
48
48
  */
49
49
  export async function indexEntitiesDir(entitiesRootAbs, logger) {
@@ -54,8 +54,8 @@ export async function indexEntitiesDir(entitiesRootAbs, logger) {
54
54
  for (const etEnt of entityTypeDirs) {
55
55
  if (!etEnt.isDirectory())
56
56
  continue;
57
- const entityKind = parseEntityKind(etEnt.name);
58
- if (!entityKind)
57
+ const entityType = parseEntityKind(etEnt.name);
58
+ if (!entityType)
59
59
  continue;
60
60
  const etDir = path.join(entitiesRootAbs, etEnt.name);
61
61
  const files = await walkFiles(etDir);
@@ -64,10 +64,10 @@ export async function indexEntitiesDir(entitiesRootAbs, logger) {
64
64
  const parsed = parseArtifactFilename(filename);
65
65
  if (!parsed)
66
66
  continue;
67
- const key = `${entityKind}::${parsed.relPath}`;
67
+ const key = `${entityType}::${parsed.relPath}`;
68
68
  const ref = {
69
- sourceKey: parsed.sourceKey,
70
- entityKind,
69
+ sourceType: parsed.sourceType,
70
+ entityType,
71
71
  relPath: parsed.relPath,
72
72
  absPath,
73
73
  };
@@ -88,9 +88,9 @@ export function findConflictGroups(index, logger) {
88
88
  for (const [key, artifacts] of index.entries()) {
89
89
  if (artifacts.length < 2)
90
90
  continue;
91
- // all same entityKind/relPath by construction
92
- const { entityKind, relPath } = artifacts[0];
93
- conflicts.push({ key, entityKind, relPath, artifacts });
91
+ // all same entityType/relPath by construction
92
+ const { entityType, relPath } = artifacts[0];
93
+ conflicts.push({ key, entityType, relPath, artifacts });
94
94
  }
95
95
  conflicts.sort((a, b) => a.key.localeCompare(b.key)); // stable order for deterministic output
96
96
  logger.info('Conflict groups', {
@@ -1 +1 @@
1
- {"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}