@invarn/cibuild 2.3.2 → 2.3.4

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.
@@ -139,6 +139,16 @@ export type StructuralFact = {
139
139
  dimension: 'w' | 'h';
140
140
  delta: number;
141
141
  }>;
142
+ } | {
143
+ /** One testTag shared by `instanceCount` nodes in the dump — an authoring
144
+ * problem with the wrapper, never a defect of the screen. Every id
145
+ * lookup (parent pairing, geometry, placement) is last-wins for a
146
+ * duplicated tag, so facts derived through it would compare arbitrary
147
+ * instances; they are WITHHELD rather than guessed while this fact is
148
+ * present, mirroring the `frame_mismatch` withhold pattern. */
149
+ kind: 'duplicate_tag';
150
+ tag: string;
151
+ instanceCount: number;
142
152
  };
143
153
  /** The declared design frame for one screen (design px, treated 1:1 with dp —
144
154
  * same convention as `ReferenceGeometry`). Composition runs declare one per
@@ -192,6 +202,14 @@ export interface DeriveStructuralFactsOptions {
192
202
  * reported as significant. */
193
203
  overlapMinRatio?: number;
194
204
  }
205
+ /**
206
+ * Node ids that appear on MORE THAN ONE node of the dump (testTag collisions),
207
+ * mapped to their instance count. Every id-keyed lookup (parent pairing,
208
+ * geometry, placement) is last-wins for such an id, so facts derived through it
209
+ * would compare arbitrary instances — consumers withhold them and report the
210
+ * collision as a `duplicate_tag` fact instead.
211
+ */
212
+ export declare function duplicatedNodeIds(nodes: readonly LayoutNode[]): Map<string, number>;
195
213
  export declare function deriveStructuralFacts(dump: LayoutDump, options?: DeriveStructuralFactsOptions): StructuralFact[];
196
214
  /** One element's geometry; x/y optional (position is advisory, see ADR-0004). */
197
215
  export interface ElementGeometry {
@@ -267,17 +285,17 @@ export interface StructuralGeometryElement {
267
285
  x: number;
268
286
  y: number;
269
287
  };
270
- design: {
288
+ design?: {
271
289
  w: number | undefined;
272
290
  h: number | undefined;
273
291
  x?: number;
274
292
  y?: number;
275
293
  };
276
- deltas: Array<{
294
+ deltas?: Array<{
277
295
  dimension: 'w' | 'h' | 'x' | 'y';
278
296
  delta: number;
279
297
  }>;
280
- sizeFlag: boolean;
298
+ sizeFlag?: boolean;
281
299
  /** Present only when the element overflows its (declared) frame. */
282
300
  overhang?: StructuralOverhang;
283
301
  }
@@ -1 +1 @@
1
- {"version":3,"file":"structural-facts.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/structural-facts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"structural-facts.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/structural-facts.ts"],"names":[],"mappings":"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"}
@@ -223,6 +223,18 @@ describe('embedded render-side stage parity', () => {
223
223
  { id: 'chip', bounds: { left: 150, top: 30, right: 195, bottom: 80 }, unclippedBounds: { left: 150, top: 30, right: 195, bottom: 80 }, parentId: 'row', clipsChildren: false },
224
224
  ],
225
225
  },
226
+ // A duplicated testTag: the collision guard must withhold the child's
227
+ // (mispairable) overflow and emit the duplicate_tag fact identically.
228
+ duplicateTag: {
229
+ canvas: CANVAS,
230
+ nodes: [
231
+ { id: 'list', bounds: { left: 0, top: 0, right: 200, bottom: 400 }, parentId: null, clipsChildren: false },
232
+ { id: 'copy_button', bounds: { left: 20, top: 20, right: 180, bottom: 60 }, parentId: 'list', clipsChildren: false },
233
+ { id: 'copy_button', bounds: { left: 20, top: 80, right: 180, bottom: 120 }, parentId: 'list', clipsChildren: false },
234
+ { id: 'copy_button', bounds: { left: 20, top: 140, right: 180, bottom: 180 }, parentId: 'list', clipsChildren: false },
235
+ { id: 'copy_label', bounds: { left: 30, top: 30, right: 120, bottom: 50 }, parentId: 'copy_button', clipsChildren: false },
236
+ ],
237
+ },
226
238
  };
227
239
  for (const [name, dump] of Object.entries(fixtures)) {
228
240
  test(`embedded port matches the module for the ${name} fixture`, () => {
@@ -256,6 +268,45 @@ describe('deriveStructuralFacts — motivating regression (voucher tag bottom-cl
256
268
  });
257
269
  });
258
270
  });
271
+ describe('deriveStructuralFacts — duplicate testTag collision guard', () => {
272
+ // Repeated rows tagging their pill with one shared testTag: parent lookups
273
+ // resolve through a last-wins id map, so overflow/clip derived through the
274
+ // duplicated tag compares arbitrary instances (a child of the first row
275
+ // measured against the last row's box reads as a huge spurious overflow).
276
+ // The deriver must refuse to guess — name the collision as a fact and
277
+ // withhold the pairing-derived facts for that tag.
278
+ test('three nodes sharing one testTag yield a duplicate_tag fact and no overflow/clip facts through that tag', () => {
279
+ const dump = {
280
+ canvas: CANVAS,
281
+ nodes: [
282
+ { id: 'list', bounds: { left: 0, top: 0, right: 200, bottom: 400 }, parentId: null, clipsChildren: false },
283
+ { id: 'copy_button', bounds: { left: 20, top: 20, right: 180, bottom: 60 }, parentId: 'list', clipsChildren: false },
284
+ { id: 'copy_button', bounds: { left: 20, top: 80, right: 180, bottom: 120 }, parentId: 'list', clipsChildren: false },
285
+ { id: 'copy_button', bounds: { left: 20, top: 140, right: 180, bottom: 180 }, parentId: 'list', clipsChildren: false },
286
+ // Sits inside the FIRST pill; paired against the last-wins instance
287
+ // (top 140) it would read as a spurious 110px top overflow.
288
+ { id: 'copy_label', bounds: { left: 30, top: 30, right: 120, bottom: 50 }, parentId: 'copy_button', clipsChildren: false },
289
+ ],
290
+ };
291
+ expect(deriveStructuralFacts(dump)).toEqual([
292
+ { kind: 'duplicate_tag', tag: 'copy_button', instanceCount: 3 },
293
+ ]);
294
+ });
295
+ test('a duplicated node overflowing its unique parent is withheld too — attribution is ambiguous', () => {
296
+ const dump = {
297
+ canvas: CANVAS,
298
+ nodes: [
299
+ { id: 'row', bounds: { left: 20, top: 20, right: 180, bottom: 100 }, parentId: null, clipsChildren: false },
300
+ // The first instance sticks out 15px past the row; the second is contained.
301
+ { id: 'chip', bounds: { left: 150, top: 30, right: 195, bottom: 80 }, parentId: 'row', clipsChildren: false },
302
+ { id: 'chip', bounds: { left: 30, top: 30, right: 60, bottom: 60 }, parentId: 'row', clipsChildren: false },
303
+ ],
304
+ };
305
+ expect(deriveStructuralFacts(dump)).toEqual([
306
+ { kind: 'duplicate_tag', tag: 'chip', instanceCount: 2 },
307
+ ]);
308
+ });
309
+ });
259
310
  // ---- Signal B: key-geometry diff + inline structural-block assembly ----
260
311
  describe('diffKeyGeometry — dimensional gaps', () => {
261
312
  test('reports a size delta on the right element beyond tolerance', () => {
@@ -286,13 +337,65 @@ const HUB_PROMO_DUMP = {
286
337
  };
287
338
  const HUB_PROMO_REFERENCE = { voucher: { w: 81, h: 81 }, banner: { w: 343, h: 72 } };
288
339
  describe('buildStructuralBlock — facts only (no reference geometry)', () => {
289
- test('surfaces facts + summary, no geometry block', () => {
340
+ test('surfaces facts + summary; geometry describes what rasterized (rendered-only boxes)', () => {
290
341
  const block = buildStructuralBlock(HUB_PROMO_DUMP, null, 2);
291
342
  expect(block.facts).toEqual([
292
343
  { kind: 'overlap', nodeIds: ['copy', 'voucher'], overlapPx: { width: 160, height: 93 }, ratio: 0.4036458333333333 },
293
344
  ]);
345
+ // Summary is byte-identical to the pre-description era: max deltas stay
346
+ // null (no comparison ran), clean is fact-driven only.
294
347
  expect(block.summary).toEqual({ clean: false, factCount: 1, maxSizeDeltaDp: null, maxClipDeltaDp: null });
295
- expect(block.geometry).toBeUndefined();
348
+ // Description vs comparison: rendered boxes persist for every authored-tag
349
+ // node even without a reference. No design/deltas/sizeFlag — those exist
350
+ // only where a reference declares the element. The synthetic root
351
+ // (node-1) is not fact-named, so it does not persist.
352
+ expect(block.geometry).toEqual({
353
+ unit: 'dp',
354
+ density: 2,
355
+ elements: [
356
+ { id: 'banner', rendered: { w: 360, h: 96, x: 0, y: 0 } },
357
+ { id: 'voucher', rendered: { w: 96, h: 96, x: 248, y: 0 } },
358
+ { id: 'copy', rendered: { w: 296, h: 47, x: 32, y: 12 } },
359
+ ],
360
+ });
361
+ });
362
+ test('a fact-named synthetic node persists its box; unnamed synthetics never do', () => {
363
+ // An untagged sibling (node-7) overlaps the tagged chip: the deriver names
364
+ // it in the overlap fact, so the collision scene needs its box. The
365
+ // untagged root (node-1) participates in no fact and stays out.
366
+ const dump = {
367
+ canvas: { left: 0, top: 0, right: 200, bottom: 400 },
368
+ nodes: [
369
+ { id: 'node-1', bounds: { left: 0, top: 0, right: 200, bottom: 400 }, parentId: null, clipsChildren: false },
370
+ { id: 'chip', bounds: { left: 0, top: 0, right: 100, bottom: 40 }, parentId: 'node-1', clipsChildren: false },
371
+ { id: 'node-7', bounds: { left: 40, top: 0, right: 140, bottom: 40 }, parentId: 'node-1', clipsChildren: false },
372
+ ],
373
+ };
374
+ const block = buildStructuralBlock(dump, null, 2);
375
+ expect(block.facts).toEqual([
376
+ expect.objectContaining({ kind: 'overlap', nodeIds: ['chip', 'node-7'] }),
377
+ ]);
378
+ expect(block.geometry?.elements).toEqual([
379
+ { id: 'chip', rendered: { w: 50, h: 20, x: 0, y: 0 } },
380
+ { id: 'node-7', rendered: { w: 50, h: 20, x: 20, y: 0 } },
381
+ ]);
382
+ });
383
+ test('a duplicated testTag persists no box (last-wins geometry is ambiguous)', () => {
384
+ const dump = {
385
+ canvas: { left: 0, top: 0, right: 200, bottom: 400 },
386
+ nodes: [
387
+ { id: 'node-1', bounds: { left: 0, top: 0, right: 200, bottom: 400 }, parentId: null, clipsChildren: false },
388
+ { id: 'chip', bounds: { left: 0, top: 0, right: 40, bottom: 20 }, parentId: 'node-1', clipsChildren: false },
389
+ { id: 'chip', bounds: { left: 60, top: 0, right: 100, bottom: 20 }, parentId: 'node-1', clipsChildren: false },
390
+ { id: 'label', bounds: { left: 0, top: 40, right: 40, bottom: 60 }, parentId: 'node-1', clipsChildren: false },
391
+ ],
392
+ };
393
+ const block = buildStructuralBlock(dump, null, 2);
394
+ // The duplicate_tag fact carries the collision; a box for an arbitrary
395
+ // instance would be misleading, so only the unambiguous tag persists.
396
+ expect(block.geometry?.elements).toEqual([
397
+ { id: 'label', rendered: { w: 20, h: 10, x: 0, y: 20 } },
398
+ ]);
296
399
  });
297
400
  });
298
401
  describe('buildStructuralBlock — with reference geometry (Signal B)', () => {
@@ -315,6 +418,17 @@ describe('buildStructuralBlock — with reference geometry (Signal B)', () => {
315
418
  expect(banner?.sizeFlag).toBe(true);
316
419
  expect(banner?.deltas).toContainEqual({ dimension: 'h', delta: 24 });
317
420
  });
421
+ test('authored elements outside the reference ride along as rendered-only boxes', () => {
422
+ const block = buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2);
423
+ // The reference declares voucher+banner; `copy` is authored but undeclared,
424
+ // so it persists as a description (rendered only, no comparison fields),
425
+ // appended after the compared elements.
426
+ expect(block.geometry?.elements.map((e) => e.id)).toEqual(['voucher', 'banner', 'copy']);
427
+ const copy = block.geometry?.elements.find((e) => e.id === 'copy');
428
+ expect(copy).toEqual({ id: 'copy', rendered: { w: 296, h: 47, x: 32, y: 12 } });
429
+ // The summary still reflects the comparison only.
430
+ expect(block.summary).toEqual({ clean: false, factCount: 1, maxSizeDeltaDp: 24, maxClipDeltaDp: 0 });
431
+ });
318
432
  });
319
433
  // ---- Signal B v2: per-edge overhang (clip) diff ----
320
434
  //
@@ -1772,6 +1886,235 @@ describe('buildStructuralBlock — placement facts (composition runs)', () => {
1772
1886
  }
1773
1887
  });
1774
1888
  });
1889
+ describe('buildStructuralBlock — duplicate testTag withhold (geometry / overhang / placement)', () => {
1890
+ // A duplicated tag's entry in the generated-geometry map is last-wins, so its
1891
+ // size diff, any overhang computed against it as a frame, and its placement
1892
+ // drift would all compare an arbitrary instance. Each is withheld; the
1893
+ // deriver's duplicate_tag fact carries the collision.
1894
+ test('a duplicated tag gets no geometry element — no size/clip facts for it', () => {
1895
+ const dump = {
1896
+ canvas: { left: 0, top: 0, right: 360, bottom: 200 },
1897
+ nodes: [
1898
+ { id: 'card', bounds: { left: 0, top: 0, right: 360, bottom: 200 }, parentId: null, clipsChildren: false },
1899
+ // 64×33 rendered vs 60×36 declared — would sizeFlag if compared.
1900
+ { id: 'pill', bounds: { left: 10, top: 10, right: 74, bottom: 43 }, parentId: 'card', clipsChildren: false },
1901
+ { id: 'pill', bounds: { left: 10, top: 60, right: 74, bottom: 93 }, parentId: 'card', clipsChildren: false },
1902
+ ],
1903
+ };
1904
+ const block = buildStructuralBlock(dump, { card: { w: 360, h: 200 }, pill: { w: 60, h: 36 } }, 1);
1905
+ expect(block.facts).toContainEqual({ kind: 'duplicate_tag', tag: 'pill', instanceCount: 2 });
1906
+ expect(block.geometry.elements.map((e) => e.id)).toEqual(['card']);
1907
+ expect(block.summary.clean).toBe(false);
1908
+ });
1909
+ test('no overhang is computed against a duplicated frame — the pairing would be arbitrary', () => {
1910
+ const dump = {
1911
+ canvas: { left: 0, top: 0, right: 360, bottom: 400 },
1912
+ nodes: [
1913
+ { id: 'banner', bounds: { left: 0, top: 0, right: 343, bottom: 72 }, parentId: null, clipsChildren: false },
1914
+ { id: 'banner', bounds: { left: 0, top: 100, right: 343, bottom: 172 }, parentId: null, clipsChildren: false },
1915
+ // Child of the duplicated banner: vs the last-wins instance it would
1916
+ // read a spurious 100dp top clip.
1917
+ { id: 'coin', bounds: { left: 300, top: 40, right: 340, bottom: 90 }, parentId: 'banner', clipsChildren: false },
1918
+ ],
1919
+ };
1920
+ const block = buildStructuralBlock(dump, { banner: { x: 0, y: 0, w: 343, h: 72 }, coin: { x: 300, y: 40, w: 40, h: 50 } }, 1);
1921
+ const coin = block.geometry.elements.find((e) => e.id === 'coin');
1922
+ expect(coin).toBeDefined();
1923
+ expect(coin.overhang).toBeUndefined();
1924
+ });
1925
+ test('placement facts skip a duplicated member tag (composition runs)', () => {
1926
+ const dump = {
1927
+ canvas: { left: 0, top: 0, right: 360, bottom: 640 },
1928
+ nodes: [
1929
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
1930
+ { id: 'member', bounds: { left: 0, top: 0, right: 360, bottom: 100 }, parentId: 'root', clipsChildren: false },
1931
+ { id: 'member', bounds: { left: 0, top: 200, right: 360, bottom: 300 }, parentId: 'root', clipsChildren: false },
1932
+ // Genuinely misplaced: rendered y 500 vs design y 540.
1933
+ { id: 'footer', bounds: { left: 0, top: 500, right: 360, bottom: 640 }, parentId: 'root', clipsChildren: false },
1934
+ ],
1935
+ };
1936
+ const block = buildStructuralBlock(dump, { member: { x: 0, y: 0, w: 360, h: 100 }, footer: { x: 0, y: 540, w: 360, h: 140 } }, 1, undefined, undefined, { w: 360, h: 640 });
1937
+ expect(block.placement.withheld).toBe(false);
1938
+ expect(block.placement.facts.map((f) => f.elementId)).toEqual(['footer']);
1939
+ });
1940
+ test('the review scaffold rows the collision under the tag with the re-tag remediation', () => {
1941
+ const scaffold = buildReviewScaffold({
1942
+ facts: [{ kind: 'duplicate_tag', tag: 'copy_button', instanceCount: 3 }],
1943
+ });
1944
+ expect(scaffold.mustExplain).toEqual(['copy_button']);
1945
+ expect(scaffold.rows).toHaveLength(1);
1946
+ expect(scaffold.rows[0].element).toBe('copy_button');
1947
+ expect(scaffold.rows[0].fact).toContain('3 nodes');
1948
+ expect(scaffold.rows[0].fact).toContain('unique testTag');
1949
+ });
1950
+ });
1951
+ describe('buildStructuralBlock — text-aware size tolerance (line-box residue)', () => {
1952
+ // JVM (Robolectric) text metrics differ a few dp from Figma's nominal line
1953
+ // boxes, so a text-driven element legitimately renders ±~2dp per laid-out
1954
+ // line. The significance flag (sizeFlag) gets that band — min(8, 2 + 2·L)dp
1955
+ // over the element's subtree line count — while the MEASUREMENT (deltas)
1956
+ // stays exact and non-text elements keep the strict 1dp band (ADR-0004:
1957
+ // strict, not loosen). Fixtures pin the July log cases.
1958
+ const CANVAS_640 = { left: 0, top: 0, right: 360, bottom: 640 };
1959
+ test('the 1-line pill (64×33 rendered vs 60×36 design) records the deltas but does not size-flag', () => {
1960
+ const dump = {
1961
+ canvas: CANVAS_640,
1962
+ nodes: [
1963
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
1964
+ { id: 'pill', bounds: { left: 16, top: 16, right: 80, bottom: 49 }, parentId: 'root', clipsChildren: false },
1965
+ {
1966
+ id: 'pill_label',
1967
+ bounds: { left: 24, top: 24, right: 72, bottom: 41 },
1968
+ parentId: 'pill',
1969
+ clipsChildren: false,
1970
+ text: 'Copy code',
1971
+ textLines: [{ start: 0, end: 9, text: 'Copy code' }],
1972
+ },
1973
+ ],
1974
+ };
1975
+ const block = buildStructuralBlock(dump, { pill: { w: 60, h: 36 } }, 1);
1976
+ const pill = block.geometry.elements.find((e) => e.id === 'pill');
1977
+ // Measurement integrity: the deltas are still recorded, exactly.
1978
+ expect(pill.deltas).toEqual([
1979
+ { dimension: 'w', delta: 4 },
1980
+ { dimension: 'h', delta: -3 },
1981
+ ]);
1982
+ // Significance: within the 1-line text band (±4dp) — not a size divergence.
1983
+ expect(pill.sizeFlag).toBe(false);
1984
+ expect(block.summary.clean).toBe(true);
1985
+ });
1986
+ test('the 3-line card (65dp rendered vs 72 design) is within the line-scaled band', () => {
1987
+ const dump = {
1988
+ canvas: CANVAS_640,
1989
+ nodes: [
1990
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
1991
+ { id: 'card', bounds: { left: 16, top: 16, right: 359, bottom: 81 }, parentId: 'root', clipsChildren: false },
1992
+ {
1993
+ id: 'title',
1994
+ bounds: { left: 24, top: 24, right: 351, bottom: 45 },
1995
+ parentId: 'card',
1996
+ clipsChildren: false,
1997
+ text: 'Fresh picks',
1998
+ textLines: [{ start: 0, end: 11, text: 'Fresh picks' }],
1999
+ },
2000
+ {
2001
+ id: 'subtitle',
2002
+ bounds: { left: 24, top: 49, right: 351, bottom: 73 },
2003
+ parentId: 'card',
2004
+ clipsChildren: false,
2005
+ text: 'Two lines of helper copy wrap here',
2006
+ textLines: [
2007
+ { start: 0, end: 17, text: 'Two lines of help' },
2008
+ { start: 18, end: 34, text: 'er copy wrap here' },
2009
+ ],
2010
+ },
2011
+ ],
2012
+ };
2013
+ const block = buildStructuralBlock(dump, { card: { w: 343, h: 72 } }, 1);
2014
+ const card = block.geometry.elements.find((e) => e.id === 'card');
2015
+ expect(card.deltas).toEqual([{ dimension: 'h', delta: -7 }]);
2016
+ // 3 laid-out lines in the subtree → band min(8, 2 + 2·3) = 8dp ≥ 7.
2017
+ expect(card.sizeFlag).toBe(false);
2018
+ });
2019
+ test('a −2dp helper text node stays unflagged (its own line makes it text-driven)', () => {
2020
+ const dump = {
2021
+ canvas: CANVAS_640,
2022
+ nodes: [
2023
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
2024
+ {
2025
+ id: 'helper',
2026
+ bounds: { left: 16, top: 100, right: 136, bottom: 118 },
2027
+ parentId: 'root',
2028
+ clipsChildren: false,
2029
+ text: 'Terms apply',
2030
+ textLines: [{ start: 0, end: 11, text: 'Terms apply' }],
2031
+ },
2032
+ ],
2033
+ };
2034
+ const block = buildStructuralBlock(dump, { helper: { w: 120, h: 20 } }, 1);
2035
+ const helper = block.geometry.elements.find((e) => e.id === 'helper');
2036
+ expect(helper.deltas).toEqual([{ dimension: 'h', delta: -2 }]);
2037
+ expect(helper.sizeFlag).toBe(false);
2038
+ });
2039
+ test('the 328 vs 343dp button class still fails — 15dp is no line-box residue', () => {
2040
+ const dump = {
2041
+ canvas: CANVAS_640,
2042
+ nodes: [
2043
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
2044
+ { id: 'button', bounds: { left: 16, top: 500, right: 344, bottom: 548 }, parentId: 'root', clipsChildren: false },
2045
+ {
2046
+ id: 'button_label',
2047
+ bounds: { left: 100, top: 514, right: 260, bottom: 534 },
2048
+ parentId: 'button',
2049
+ clipsChildren: false,
2050
+ text: 'Continue',
2051
+ textLines: [{ start: 0, end: 8, text: 'Continue' }],
2052
+ },
2053
+ ],
2054
+ };
2055
+ const block = buildStructuralBlock(dump, { button: { w: 343, h: 48 } }, 1);
2056
+ const button = block.geometry.elements.find((e) => e.id === 'button');
2057
+ expect(button.sizeFlag).toBe(true);
2058
+ expect(block.summary.clean).toBe(false);
2059
+ });
2060
+ test('the text band is capped at 8dp — a 10dp delta on a 5-line block still fails', () => {
2061
+ const dump = {
2062
+ canvas: CANVAS_640,
2063
+ nodes: [
2064
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
2065
+ {
2066
+ id: 'paragraph',
2067
+ bounds: { left: 16, top: 16, right: 344, bottom: 126 },
2068
+ parentId: 'root',
2069
+ clipsChildren: false,
2070
+ text: 'five lines of copy wrap',
2071
+ textLines: [
2072
+ { start: 0, end: 4, text: 'five' },
2073
+ { start: 5, end: 10, text: 'lines' },
2074
+ { start: 11, end: 13, text: 'of' },
2075
+ { start: 14, end: 18, text: 'copy' },
2076
+ { start: 19, end: 23, text: 'wrap' },
2077
+ ],
2078
+ },
2079
+ ],
2080
+ };
2081
+ const block = buildStructuralBlock(dump, { paragraph: { w: 328, h: 120 } }, 1);
2082
+ const paragraph = block.geometry.elements.find((e) => e.id === 'paragraph');
2083
+ // min(8, 2 + 2·5) = 8dp < 10dp — the cap keeps large stacks honest.
2084
+ expect(paragraph.sizeFlag).toBe(true);
2085
+ });
2086
+ test('a non-text element keeps the strict band — a 3dp delta still flags', () => {
2087
+ const dump = {
2088
+ canvas: CANVAS_640,
2089
+ nodes: [
2090
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
2091
+ { id: 'thumbnail', bounds: { left: 16, top: 16, right: 119, bottom: 116 }, parentId: 'root', clipsChildren: false },
2092
+ ],
2093
+ };
2094
+ const block = buildStructuralBlock(dump, { thumbnail: { w: 100, h: 100 } }, 1);
2095
+ const thumbnail = block.geometry.elements.find((e) => e.id === 'thumbnail');
2096
+ expect(thumbnail.deltas).toEqual([{ dimension: 'w', delta: 3 }]);
2097
+ expect(thumbnail.sizeFlag).toBe(true);
2098
+ });
2099
+ test('an old package (text but no textLines) still counts one line per text node', () => {
2100
+ const dump = {
2101
+ canvas: CANVAS_640,
2102
+ nodes: [
2103
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
2104
+ { id: 'pill', bounds: { left: 16, top: 16, right: 80, bottom: 49 }, parentId: 'root', clipsChildren: false },
2105
+ {
2106
+ id: 'pill_label',
2107
+ bounds: { left: 24, top: 24, right: 72, bottom: 41 },
2108
+ parentId: 'pill',
2109
+ clipsChildren: false,
2110
+ text: 'Copy code',
2111
+ },
2112
+ ],
2113
+ };
2114
+ const block = buildStructuralBlock(dump, { pill: { w: 60, h: 36 } }, 1);
2115
+ expect(block.geometry.elements.find((e) => e.id === 'pill').sizeFlag).toBe(false);
2116
+ });
2117
+ });
1775
2118
  describe('embedded geometry stage parity', () => {
1776
2119
  // The render ships a JS-source port of the differ + assembler. It must produce
1777
2120
  // byte-identical blocks to the canonical typed module, or run-side structural
@@ -1799,6 +2142,21 @@ describe('embedded geometry stage parity', () => {
1799
2142
  const appearanceReference = { baseline: 'figma', elementIds: ['banner', 'voucher'] };
1800
2143
  expect(embedded.buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2, undefined, appearanceReference)).toEqual(buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2, undefined, appearanceReference));
1801
2144
  });
2145
+ test('embedded buildStructuralBlock matches the module for rendered-only geometry (no reference)', () => {
2146
+ // The description path: authored tags + a fact-named synthetic node, no
2147
+ // reference geometry at all. Both copies must select the same ids and emit
2148
+ // identical rendered-only boxes.
2149
+ const dump = {
2150
+ canvas: { left: 0, top: 0, right: 200, bottom: 400 },
2151
+ nodes: [
2152
+ { id: 'node-1', bounds: { left: 0, top: 0, right: 200, bottom: 400 }, parentId: null, clipsChildren: false },
2153
+ { id: 'chip', bounds: { left: 0, top: 0, right: 100, bottom: 40 }, parentId: 'node-1', clipsChildren: false },
2154
+ { id: 'node-7', bounds: { left: 40, top: 0, right: 140, bottom: 40 }, parentId: 'node-1', clipsChildren: false },
2155
+ ],
2156
+ };
2157
+ expect(embedded.buildStructuralBlock(dump, null, 2)).toEqual(buildStructuralBlock(dump, null, 2));
2158
+ expect(embedded.buildStructuralBlock(HUB_PROMO_DUMP, null, 2)).toEqual(buildStructuralBlock(HUB_PROMO_DUMP, null, 2));
2159
+ });
1802
2160
  test('embedded deriveSpanFacts matches the module (Signal C, issue 16)', () => {
1803
2161
  const cases = [
1804
2162
  [{ discountText: [{ start: 4, end: 13, text: '5 EUR off' }] }, { discountText: { text: '5 EUR off' } }],
@@ -2044,6 +2402,40 @@ describe('embedded geometry stage parity', () => {
2044
2402
  };
2045
2403
  expect(embedded.buildStructuralBlock(dumpWithText, null, 2, undefined, appearanceReference)).toEqual(buildStructuralBlock(dumpWithText, null, 2, undefined, appearanceReference));
2046
2404
  });
2405
+ // Duplicated banner tag + a child declared in the reference: exercises the
2406
+ // collision guard end-to-end (duplicate_tag fact, geometry skip, overhang
2407
+ // withheld against the duplicated frame, scaffold row).
2408
+ const DUPLICATE_TAG_DUMP = {
2409
+ canvas: { left: 0, top: 0, right: 720, bottom: 800 },
2410
+ nodes: [
2411
+ { id: 'banner', bounds: { left: 0, top: 0, right: 686, bottom: 144 }, parentId: null, clipsChildren: false },
2412
+ { id: 'banner', bounds: { left: 0, top: 200, right: 686, bottom: 344 }, parentId: null, clipsChildren: false },
2413
+ { id: 'coin', bounds: { left: 600, top: 80, right: 680, bottom: 180 }, parentId: 'banner', clipsChildren: false },
2414
+ ],
2415
+ };
2416
+ const DUPLICATE_TAG_REF = {
2417
+ banner: { x: 0, y: 0, w: 343, h: 72 },
2418
+ coin: { x: 300, y: 40, w: 40, h: 50 },
2419
+ };
2420
+ // A text-driven pill inside the band (density 2: px are 2× the dp numbers)
2421
+ // plus a non-text sibling outside it — exercises the text-aware size band.
2422
+ const TEXT_BAND_DUMP = {
2423
+ canvas: { left: 0, top: 0, right: 720, bottom: 400 },
2424
+ nodes: [
2425
+ { id: 'root', bounds: { left: 0, top: 0, right: 720, bottom: 400 }, parentId: null, clipsChildren: false },
2426
+ { id: 'pill', bounds: { left: 32, top: 32, right: 160, bottom: 98 }, parentId: 'root', clipsChildren: false },
2427
+ {
2428
+ id: 'pill_label',
2429
+ bounds: { left: 48, top: 48, right: 144, bottom: 82 },
2430
+ parentId: 'pill',
2431
+ clipsChildren: false,
2432
+ text: 'Copy code',
2433
+ textLines: [{ start: 0, end: 9, text: 'Copy code' }],
2434
+ },
2435
+ { id: 'thumbnail', bounds: { left: 200, top: 32, right: 406, bottom: 232 }, parentId: 'root', clipsChildren: false },
2436
+ ],
2437
+ };
2438
+ const TEXT_BAND_REF = { pill: { w: 60, h: 36 }, thumbnail: { w: 100, h: 100 } };
2047
2439
  const parityCases = [
2048
2440
  { name: 'factsOnly', dump: HUB_PROMO_DUMP, ref: null },
2049
2441
  { name: 'withGeometry', dump: HUB_PROMO_DUMP, ref: HUB_PROMO_REFERENCE },
@@ -2051,6 +2443,8 @@ describe('embedded geometry stage parity', () => {
2051
2443
  { name: 'overhangGuest', dump: OVERHANG_GUEST_DUMP, ref: OVERHANG_GUEST_REF },
2052
2444
  { name: 'overhangPosition', dump: OVERHANG_POSITION_DUMP, ref: OVERHANG_POSITION_REF },
2053
2445
  { name: 'overhangMissing', dump: OVERHANG_MISSING_DUMP, ref: OVERHANG_MISSING_REF },
2446
+ { name: 'duplicateTag', dump: DUPLICATE_TAG_DUMP, ref: DUPLICATE_TAG_REF },
2447
+ { name: 'textSizeBand', dump: TEXT_BAND_DUMP, ref: TEXT_BAND_REF },
2054
2448
  ];
2055
2449
  for (const { name, dump, ref } of parityCases) {
2056
2450
  test(`embedded buildStructuralBlock matches the module (${name})`, () => {
@@ -2061,5 +2455,19 @@ describe('embedded geometry stage parity', () => {
2061
2455
  expect(embedded.buildReviewScaffold(block)).toEqual(buildReviewScaffold(block));
2062
2456
  });
2063
2457
  }
2458
+ test('embedded buildStructuralBlock matches the module for a duplicated member tag under a declared frame', () => {
2459
+ const dump = {
2460
+ canvas: { left: 0, top: 0, right: 360, bottom: 640 },
2461
+ nodes: [
2462
+ { id: 'root', bounds: { left: 0, top: 0, right: 360, bottom: 640 }, parentId: null, clipsChildren: false },
2463
+ { id: 'member', bounds: { left: 0, top: 0, right: 360, bottom: 100 }, parentId: 'root', clipsChildren: false },
2464
+ { id: 'member', bounds: { left: 0, top: 200, right: 360, bottom: 300 }, parentId: 'root', clipsChildren: false },
2465
+ { id: 'footer', bounds: { left: 0, top: 500, right: 360, bottom: 640 }, parentId: 'root', clipsChildren: false },
2466
+ ],
2467
+ };
2468
+ const ref = { member: { x: 0, y: 0, w: 360, h: 100 }, footer: { x: 0, y: 540, w: 360, h: 140 } };
2469
+ const frame = { w: 360, h: 640 };
2470
+ expect(embedded.buildStructuralBlock(dump, ref, 1, undefined, undefined, frame)).toEqual(buildStructuralBlock(dump, ref, 1, undefined, undefined, frame));
2471
+ });
2064
2472
  });
2065
2473
  //# sourceMappingURL=structural-facts.test.js.map
@@ -400,10 +400,20 @@ describe('android render runtime — render + trim (happy path)', () => {
400
400
  });
401
401
  expect(run.status).toBe(0);
402
402
  const screen = readResult(project).screens.find((s) => s.screen === 'XProof');
403
- // Signal A surfaces inline (no reference_geometry no geometry block).
403
+ // Signal A surfaces inline; max deltas stay null (no comparison ran).
404
404
  expect(screen?.structural?.summary).toEqual({ clean: false, factCount: 1, maxSizeDeltaDp: null, maxClipDeltaDp: null });
405
405
  expect(screen?.structural?.facts).toHaveLength(1);
406
- expect(screen?.structural?.geometry).toBeUndefined();
406
+ // Description vs comparison: with no reference_geometry the geometry block
407
+ // still persists the authored-tag nodes' rendered boxes — and nothing else
408
+ // (no design/deltas/sizeFlag).
409
+ expect(screen?.structural?.geometry).toEqual({
410
+ unit: 'dp',
411
+ density: 2,
412
+ elements: [
413
+ { id: 'card', rendered: { w: 80, h: 90, x: 10, y: 10 } },
414
+ { id: 'tag', rendered: { w: 40, h: 37, x: 30, y: 75 } },
415
+ ],
416
+ });
407
417
  // The verdict obligation is baked onto the run result by the runner: the
408
418
  // clip fact (node 'tag') becomes a must-explain row with a null verdict.
409
419
  expect(screen?.structural?.review?.verdict).toBeNull();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",