@invarn/cibuild 2.1.9 → 2.2.1

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.
@@ -39,6 +39,12 @@ export interface LayoutNode {
39
39
  /** Legacy clip hint (parent clips its children). The current emitter writes a
40
40
  * constant false; used only for the legacy (no-`unclippedBounds`) fallback. */
41
41
  clipsChildren: boolean;
42
+ /** Accessible text content. */
43
+ text?: string;
44
+ /** Fill (background) color, hex. */
45
+ fillColor?: string;
46
+ /** Text (foreground) color, hex. */
47
+ textColor?: string;
42
48
  }
43
49
  export interface LayoutDump {
44
50
  /** The captured canvas / root bounds in px. */
@@ -185,7 +191,90 @@ export interface StructuralBlock {
185
191
  summary: StructuralSummary;
186
192
  facts: StructuralFact[];
187
193
  geometry?: StructuralGeometry;
194
+ appearance?: StructuralAppearance;
188
195
  }
196
+ /** Which reference the appearance facts were diffed against. `previous_render`
197
+ * facts are regressions/drift, NOT design divergences (the no-Figma path). */
198
+ export type AppearanceBaseline = 'figma' | 'previous_render';
199
+ export type AppearanceFact = {
200
+ kind: 'color';
201
+ elementId: string;
202
+ channel: 'fill' | 'text';
203
+ rendered: string;
204
+ reference: string;
205
+ /** CIEDE2000 perceptual distance — measurement only, no significance. */
206
+ deltaE: number;
207
+ } | {
208
+ kind: 'text_mismatch';
209
+ elementId: string;
210
+ rendered: string;
211
+ reference: string;
212
+ } | {
213
+ kind: 'text_missing';
214
+ elementId: string;
215
+ reference: string;
216
+ }
217
+ /** In the reference, not rendered. */
218
+ | {
219
+ kind: 'element_missing';
220
+ elementId: string;
221
+ }
222
+ /** Rendered, not in the reference. */
223
+ | {
224
+ kind: 'element_extra';
225
+ elementId: string;
226
+ };
227
+ export interface StructuralAppearance {
228
+ baseline: AppearanceBaseline;
229
+ facts: AppearanceFact[];
230
+ }
231
+ /**
232
+ * The reference side of the appearance diff, passed into `buildStructuralBlock`.
233
+ * `elementIds` is the reference element-id set (Figma node ids on the `figma`
234
+ * baseline; the previous render's element ids on `previous_render`). This slice
235
+ * derives presence only; the copy/color slices extend this with reference text /
236
+ * colors keyed by element id.
237
+ */
238
+ export interface AppearanceReference {
239
+ baseline: AppearanceBaseline;
240
+ elementIds: string[];
241
+ /** Reference text per element id (Figma `characters` on the figma baseline; the
242
+ * previous render's text on `previous_render`). When supplied, copy facts are
243
+ * derived against the render's per-node text. Absent → presence facts only. */
244
+ text?: TextSource;
245
+ }
246
+ /**
247
+ * Element-presence facts from the set difference of the rendered element-id set
248
+ * and the reference element-id set, keyed on the stable element id shared with
249
+ * Signal B. An id present in the reference but not rendered is `element_missing`;
250
+ * an id rendered but not in the reference is `element_extra`.
251
+ *
252
+ * Pure and platform-agnostic: it takes two id collections and is order-
253
+ * independent — the result depends only on the two SETS, not on input order or
254
+ * duplicates. Output is sorted (missing before extra, each by id) so callers get
255
+ * a deterministic list. The deriver reports facts only; significance is a later,
256
+ * separately-wired concern.
257
+ */
258
+ export declare function derivePresenceFacts(renderedIds: Iterable<string>, referenceIds: Iterable<string>): AppearanceFact[];
259
+ /** Per-element text content, keyed on the stable element id (rendered text from
260
+ * the layout dump's per-node `text`; reference text from the Figma node tree's
261
+ * `characters`). A missing or empty string means "no text signal for that
262
+ * element," which the deriver treats as absence, never a divergence. */
263
+ export type TextSource = Record<string, string | undefined>;
264
+ /**
265
+ * Copy/text facts from the per-element comparison of rendered text vs reference
266
+ * text, keyed on the stable element id shared with Signal B. For each element the
267
+ * REFERENCE declares text for: identical text → no fact; a different rendered
268
+ * string → `text_mismatch` (both strings attached); empty/absent rendered text →
269
+ * `text_missing`. An element with no reference text signal produces no fact —
270
+ * absence of a signal is never reported as a divergence, so a rendered string the
271
+ * reference never declared is silent.
272
+ *
273
+ * Pure and platform-agnostic; order-independent and deterministic (output sorted
274
+ * by element id). The deriver reports facts only; significance is a later,
275
+ * separately-wired concern.
276
+ */
277
+ export declare function deriveCopyFacts(rendered: TextSource, reference: TextSource): AppearanceFact[];
189
278
  /**
190
279
  * Assemble the inline `structural` block (ADR-0004): Signal-A facts always, plus
191
280
  * the Signal-B geometry block when `referenceGeometry` is supplied. Size (w/h)
@@ -195,7 +284,7 @@ export interface StructuralBlock {
195
284
  export declare function buildStructuralBlock(dump: LayoutDump, referenceGeometry?: ReferenceGeometry | null, density?: number, options?: {
196
285
  sizeTolerancePx?: number;
197
286
  overhangTolerancePx?: number;
198
- }): StructuralBlock;
287
+ }, appearanceReference?: AppearanceReference | null): StructuralBlock;
199
288
  export interface ReviewRow {
200
289
  element: string;
201
290
  rendered: string | null;
@@ -265,10 +354,12 @@ export declare function getGeometryStageInternals(): {
265
354
  buildStructuralBlock: (dump: LayoutDump, referenceGeometry?: ReferenceGeometry | null, density?: number, options?: {
266
355
  sizeTolerancePx?: number;
267
356
  overhangTolerancePx?: number;
268
- }) => StructuralBlock;
357
+ }, appearanceReference?: AppearanceReference | null) => StructuralBlock;
269
358
  buildReviewScaffold: (structural: {
270
359
  facts?: StructuralFact[];
271
360
  geometry?: StructuralGeometry | null;
272
361
  }) => ReviewScaffold;
362
+ derivePresenceFacts: (renderedIds: Iterable<string>, referenceIds: Iterable<string>) => AppearanceFact[];
363
+ deriveCopyFacts: (rendered: TextSource, reference: TextSource) => AppearanceFact[];
273
364
  };
274
365
  //# sourceMappingURL=structural-facts.d.ts.map
@@ -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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"}
@@ -8,7 +8,7 @@
8
8
  * overflowing voucher tag; the deriver must surface the bottom clip as a
9
9
  * fact so it is never again skipped by eye.
10
10
  */
11
- import { deriveStructuralFacts, diffKeyGeometry, buildStructuralBlock, buildReviewScaffold, getStructuralFactsStageInternals, getGeometryStageInternals, } from './structural-facts.js';
11
+ import { deriveStructuralFacts, derivePresenceFacts, deriveCopyFacts, diffKeyGeometry, buildStructuralBlock, buildReviewScaffold, getStructuralFactsStageInternals, getGeometryStageInternals, } from './structural-facts.js';
12
12
  // 200x400 canvas in px for all fixtures unless noted.
13
13
  const CANVAS = { left: 0, top: 0, right: 200, bottom: 400 };
14
14
  describe('deriveStructuralFacts — containment', () => {
@@ -484,6 +484,142 @@ describe('buildReviewScaffold — run-only verdict obligation', () => {
484
484
  });
485
485
  });
486
486
  });
487
+ // ---- Signal C: element-presence facts (appearance container) ----
488
+ describe('derivePresenceFacts — set difference over element ids', () => {
489
+ test('equal element sets produce no facts', () => {
490
+ expect(derivePresenceFacts(['a', 'b', 'c'], ['a', 'b', 'c'])).toEqual([]);
491
+ });
492
+ test('an id only in the reference yields element_missing', () => {
493
+ // rendered lacks `voucher`, which the reference declares.
494
+ expect(derivePresenceFacts(['banner'], ['banner', 'voucher'])).toEqual([
495
+ { kind: 'element_missing', elementId: 'voucher' },
496
+ ]);
497
+ });
498
+ test('an id only in the render yields element_extra', () => {
499
+ // rendered has an extra `debugOverlay` the reference does not declare.
500
+ expect(derivePresenceFacts(['banner', 'debugOverlay'], ['banner'])).toEqual([
501
+ { kind: 'element_extra', elementId: 'debugOverlay' },
502
+ ]);
503
+ });
504
+ test('reports both a missing and an extra id, missing before extra', () => {
505
+ expect(derivePresenceFacts(['banner', 'extra'], ['banner', 'gone'])).toEqual([
506
+ { kind: 'element_missing', elementId: 'gone' },
507
+ { kind: 'element_extra', elementId: 'extra' },
508
+ ]);
509
+ });
510
+ test('result is order-independent — same sets in any input order give the same facts', () => {
511
+ const a = derivePresenceFacts(['a', 'b', 'c'], ['b', 'd', 'a']);
512
+ const b = derivePresenceFacts(['c', 'b', 'a'], ['d', 'a', 'b']);
513
+ expect(a).toEqual(b);
514
+ // d missing, c extra — independent of how the ids were ordered or duplicated.
515
+ expect(derivePresenceFacts(['c', 'c', 'b', 'a'], ['a', 'b', 'd', 'd'])).toEqual([
516
+ { kind: 'element_missing', elementId: 'd' },
517
+ { kind: 'element_extra', elementId: 'c' },
518
+ ]);
519
+ });
520
+ });
521
+ describe('deriveCopyFacts — rendered vs reference text per element', () => {
522
+ test('identical text produces no fact', () => {
523
+ expect(deriveCopyFacts({ title: '5 EUR off' }, { title: '5 EUR off' })).toEqual([]);
524
+ });
525
+ test('differing text yields text_mismatch with both strings', () => {
526
+ expect(deriveCopyFacts({ title: '5 EUR' }, { title: '5 EUR off' })).toEqual([{ kind: 'text_mismatch', elementId: 'title', rendered: '5 EUR', reference: '5 EUR off' }]);
527
+ });
528
+ test('reference text with empty/absent render yields text_missing', () => {
529
+ // absent render entry
530
+ expect(deriveCopyFacts({}, { cta: 'Shop now' })).toEqual([
531
+ { kind: 'text_missing', elementId: 'cta', reference: 'Shop now' },
532
+ ]);
533
+ // empty-string render entry counts as no rendered text
534
+ expect(deriveCopyFacts({ cta: '' }, { cta: 'Shop now' })).toEqual([
535
+ { kind: 'text_missing', elementId: 'cta', reference: 'Shop now' },
536
+ ]);
537
+ });
538
+ test('an element with no reference text produces no fact (absence of signal is not a divergence)', () => {
539
+ // render has text the reference never declared → no fact (no reference signal)
540
+ expect(deriveCopyFacts({ debugLabel: 'x' }, {})).toEqual([]);
541
+ // reference declares an empty string → no signal → no fact regardless of render
542
+ expect(deriveCopyFacts({ note: 'hi' }, { note: '' })).toEqual([]);
543
+ });
544
+ test('result is order-independent and deterministic (sorted by element id)', () => {
545
+ const a = deriveCopyFacts({ b: 'r', a: 'wrong' }, { a: 'right', b: 'r', c: 'gone' });
546
+ const b = deriveCopyFacts({ a: 'wrong', b: 'r' }, { c: 'gone', b: 'r', a: 'right' });
547
+ expect(a).toEqual(b);
548
+ expect(a).toEqual([
549
+ { kind: 'text_mismatch', elementId: 'a', rendered: 'wrong', reference: 'right' },
550
+ { kind: 'text_missing', elementId: 'c', reference: 'gone' },
551
+ ]);
552
+ });
553
+ });
554
+ describe('buildStructuralBlock — appearance container (Signal C, additive)', () => {
555
+ test('no appearanceReference → no appearance container; facts + geometry unchanged', () => {
556
+ const withC = buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2);
557
+ const without = buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2, undefined, null);
558
+ expect(withC.appearance).toBeUndefined();
559
+ // Signal A facts and Signal B geometry are byte-identical whether or not the
560
+ // appearance arg is threaded.
561
+ expect(without).toEqual(withC);
562
+ });
563
+ test('with a figma appearanceReference → presence facts from rendered vs reference ids', () => {
564
+ // dump node ids: node-1, banner, voucher, copy; reference declares banner+voucher.
565
+ const block = buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2, undefined, {
566
+ baseline: 'figma',
567
+ elementIds: ['banner', 'voucher'],
568
+ });
569
+ expect(block.appearance).toEqual({
570
+ baseline: 'figma',
571
+ facts: [
572
+ { kind: 'element_extra', elementId: 'copy' },
573
+ { kind: 'element_extra', elementId: 'node-1' },
574
+ ],
575
+ });
576
+ // Additive: the existing Signal A facts and Signal B geometry are untouched.
577
+ expect(block.facts).toEqual(buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2).facts);
578
+ expect(block.geometry).toEqual(buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2).geometry);
579
+ });
580
+ test('an appearanceReference matching the render → ran-and-clean (baseline, zero facts)', () => {
581
+ const block = buildStructuralBlock(HUB_PROMO_DUMP, null, 2, undefined, {
582
+ baseline: 'figma',
583
+ elementIds: ['node-1', 'banner', 'voucher', 'copy'],
584
+ });
585
+ expect(block.appearance).toEqual({ baseline: 'figma', facts: [] });
586
+ });
587
+ // A dump whose per-node `text` (Signal C render-side enrichment) drives the
588
+ // copy-fact comparison: `title` renders the wrong string, `cta` renders no
589
+ // text, and `debugOverlay` is an extra element absent from the reference.
590
+ const COPY_DUMP = {
591
+ canvas: { left: 0, top: 0, right: 200, bottom: 400 },
592
+ nodes: [
593
+ { id: 'title', bounds: { left: 0, top: 0, right: 100, bottom: 20 }, parentId: null, clipsChildren: false, text: '5 EUR' },
594
+ { id: 'cta', bounds: { left: 0, top: 30, right: 100, bottom: 50 }, parentId: null, clipsChildren: false },
595
+ { id: 'debugOverlay', bounds: { left: 0, top: 60, right: 100, bottom: 80 }, parentId: null, clipsChildren: false },
596
+ ],
597
+ };
598
+ test('with reference text → copy facts are appended after presence facts', () => {
599
+ const block = buildStructuralBlock(COPY_DUMP, null, 2, undefined, {
600
+ baseline: 'figma',
601
+ elementIds: ['title', 'cta'],
602
+ text: { title: '5 EUR off', cta: 'Shop now' },
603
+ });
604
+ expect(block.appearance).toEqual({
605
+ baseline: 'figma',
606
+ facts: [
607
+ // presence first (debugOverlay is rendered but not in the reference)
608
+ { kind: 'element_extra', elementId: 'debugOverlay' },
609
+ // then copy (sorted by id: cta missing, title mismatched)
610
+ { kind: 'text_missing', elementId: 'cta', reference: 'Shop now' },
611
+ { kind: 'text_mismatch', elementId: 'title', rendered: '5 EUR', reference: '5 EUR off' },
612
+ ],
613
+ });
614
+ });
615
+ test('an appearanceReference without text → presence only (issue-01 behavior unchanged)', () => {
616
+ const block = buildStructuralBlock(COPY_DUMP, null, 2, undefined, {
617
+ baseline: 'figma',
618
+ elementIds: ['title', 'cta', 'debugOverlay'],
619
+ });
620
+ expect(block.appearance).toEqual({ baseline: 'figma', facts: [] });
621
+ });
622
+ });
487
623
  describe('embedded geometry stage parity', () => {
488
624
  // The render ships a JS-source port of the differ + assembler. It must produce
489
625
  // byte-identical blocks to the canonical typed module, or run-side structural
@@ -494,6 +630,52 @@ describe('embedded geometry stage parity', () => {
494
630
  const reference = { card: { width: 328, height: 72 } };
495
631
  expect(embedded.diffKeyGeometry(generated, reference)).toEqual(diffKeyGeometry(generated, reference));
496
632
  });
633
+ test('embedded derivePresenceFacts matches the module (Signal C)', () => {
634
+ const cases = [
635
+ [['a', 'b', 'c'], ['a', 'b', 'c']],
636
+ [['banner'], ['banner', 'voucher']],
637
+ [['banner', 'debugOverlay'], ['banner']],
638
+ [['c', 'b', 'a'], ['d', 'a', 'b']],
639
+ [[], ['x', 'y']],
640
+ [['x', 'y'], []],
641
+ ];
642
+ for (const [rendered, reference] of cases) {
643
+ expect(embedded.derivePresenceFacts(rendered, reference)).toEqual(derivePresenceFacts(rendered, reference));
644
+ }
645
+ });
646
+ test('embedded buildStructuralBlock matches the module with an appearanceReference', () => {
647
+ const appearanceReference = { baseline: 'figma', elementIds: ['banner', 'voucher'] };
648
+ expect(embedded.buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2, undefined, appearanceReference)).toEqual(buildStructuralBlock(HUB_PROMO_DUMP, HUB_PROMO_REFERENCE, 2, undefined, appearanceReference));
649
+ });
650
+ test('embedded deriveCopyFacts matches the module (Signal C)', () => {
651
+ const cases = [
652
+ [{ title: 'a' }, { title: 'a' }],
653
+ [{ title: 'a' }, { title: 'b' }],
654
+ [{}, { cta: 'Shop now' }],
655
+ [{ cta: '' }, { cta: 'Shop now' }],
656
+ [{ debugLabel: 'x' }, {}],
657
+ [{ note: 'hi' }, { note: '' }],
658
+ [{ b: 'r', a: 'wrong' }, { a: 'right', b: 'r', c: 'gone' }],
659
+ ];
660
+ for (const [rendered, reference] of cases) {
661
+ expect(embedded.deriveCopyFacts(rendered, reference)).toEqual(deriveCopyFacts(rendered, reference));
662
+ }
663
+ });
664
+ test('embedded buildStructuralBlock matches the module with an appearanceReference carrying text', () => {
665
+ const dumpWithText = {
666
+ canvas: { left: 0, top: 0, right: 200, bottom: 400 },
667
+ nodes: [
668
+ { id: 'title', bounds: { left: 0, top: 0, right: 100, bottom: 20 }, parentId: null, clipsChildren: false, text: '5 EUR' },
669
+ { id: 'cta', bounds: { left: 0, top: 30, right: 100, bottom: 50 }, parentId: null, clipsChildren: false },
670
+ ],
671
+ };
672
+ const appearanceReference = {
673
+ baseline: 'figma',
674
+ elementIds: ['title', 'cta'],
675
+ text: { title: '5 EUR off', cta: 'Shop now' },
676
+ };
677
+ expect(embedded.buildStructuralBlock(dumpWithText, null, 2, undefined, appearanceReference)).toEqual(buildStructuralBlock(dumpWithText, null, 2, undefined, appearanceReference));
678
+ });
497
679
  const parityCases = [
498
680
  { name: 'factsOnly', dump: HUB_PROMO_DUMP, ref: null },
499
681
  { name: 'withGeometry', dump: HUB_PROMO_DUMP, ref: HUB_PROMO_REFERENCE },
@@ -1 +1 @@
1
- {"version":3,"file":"ui-fidelity-render-android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render-android.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAKpE,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AA8vBD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAYrF;AAED;;;GAGG;AACH,qBAAa,mCAAoC,SAAQ,gBAAgB;IACvE,yBAAyB,CACvB,OAAO,EAAE,6BAA6B,EACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAepB,OAAO,CACX,MAAM,EAAE,6BAA6B,EACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CAgBpB"}
1
+ {"version":3,"file":"ui-fidelity-render-android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render-android.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAKpE,sDAAsD;AACtD,MAAM,WAAW,6BAA6B;IAC5C;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAEzD,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AA0wBD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAYrF;AAED;;;GAGG;AACH,qBAAa,mCAAoC,SAAQ,gBAAgB;IACvE,yBAAyB,CACvB,OAAO,EAAE,6BAA6B,EACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,qBAAqB,EAAE;IAepB,OAAO,CACX,MAAM,EAAE,6BAA6B,EACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,OAAO,CAAC;CAgBpB"}
@@ -95,6 +95,10 @@ var buildError = null;
95
95
  // read by the structural assembler. Null when the run declared none → Signal B
96
96
  // is skipped and the structural block carries facts only.
97
97
  var referenceGeometry = null;
98
+ // params.reference_text (Signal C: Figma characters per element id per screen),
99
+ // set in main() and read by the structural assembler. Null when none declared →
100
+ // the appearance container carries presence facts only (no copy facts).
101
+ var referenceText = null;
98
102
 
99
103
  function log(message) {
100
104
  console.log('[ui-fidelity-render-android] ' + message);
@@ -607,7 +611,7 @@ function renderScreens(renderable, projectRoot) {
607
611
  // geometry deltas vs reference_geometry) onto the screen entry, so the
608
612
  // judge reads the signals from protocol-result.json without fetching
609
613
  // artifacts. CONFIG.scale is the render density (dp = px / scale).
610
- assembleStructural(entry, layoutSource, referenceGeometry, CONFIG.scale);
614
+ assembleStructural(entry, layoutSource, referenceGeometry, CONFIG.scale, referenceText);
611
615
  }
612
616
  });
613
617
  } finally {
@@ -673,6 +677,14 @@ function main() {
673
677
  !Array.isArray(params.reference_geometry)
674
678
  ? params.reference_geometry
675
679
  : null;
680
+ // Signal-C copy reference: { "<Screen>": { "<elementId>": "<text>" } } — the
681
+ // Figma characters mapped to element ids. Absent → presence facts only.
682
+ referenceText =
683
+ params.reference_text &&
684
+ typeof params.reference_text === 'object' &&
685
+ !Array.isArray(params.reference_text)
686
+ ? params.reference_text
687
+ : null;
676
688
 
677
689
  var screens = Object.keys(params.screens);
678
690
  currentEntries = screens.map(function (screen) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@invarn/cibuild",
3
- "version": "2.1.9",
3
+ "version": "2.2.1",
4
4
  "description": "CI Build CLI — local pipeline orchestration and validation",
5
5
  "type": "module",
6
6
  "main": "dist/cli.cjs",