@invarn/cibuild 2.3.6 → 2.3.8
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.
- package/dist/cli.cjs +221 -44
- package/dist/src/yaml/steps/fidelity-reference-provenance.d.ts +54 -12
- package/dist/src/yaml/steps/fidelity-reference-provenance.d.ts.map +1 -1
- package/dist/src/yaml/steps/fidelity-reference-provenance.js +74 -32
- package/dist/src/yaml/steps/fidelity-reference-provenance.test.d.ts +14 -6
- package/dist/src/yaml/steps/fidelity-reference-provenance.test.d.ts.map +1 -1
- package/dist/src/yaml/steps/fidelity-reference-provenance.test.js +92 -28
- package/dist/src/yaml/steps/ui-fidelity-render-android.d.ts +11 -6
- package/dist/src/yaml/steps/ui-fidelity-render-android.d.ts.map +1 -1
- package/dist/src/yaml/steps/ui-fidelity-render-android.js +105 -39
- package/dist/src/yaml/steps/ui-fidelity-render-android.test.js +93 -18
- package/dist/src/yaml/steps/ui-fidelity-render.d.ts +10 -0
- package/dist/src/yaml/steps/ui-fidelity-render.d.ts.map +1 -1
- package/dist/src/yaml/steps/ui-fidelity-render.js +127 -1
- package/dist/src/yaml/steps/ui-fidelity-render.test.js +122 -0
- package/package.json +1 -1
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reference-provenance
|
|
2
|
+
* Reference-provenance assessment.
|
|
3
3
|
*
|
|
4
4
|
* A UI-fidelity reference is a PNG the gate cannot read, so reference validity
|
|
5
5
|
* is asserted at export time as provenance metadata (`figmaNode`, `locale`,
|
|
6
6
|
* `resolved`, `exportedAt`) and the gate checks that METADATA — never the
|
|
7
|
-
* pixels, never via OCR.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* pixels, never via OCR.
|
|
8
|
+
*
|
|
9
|
+
* The assessment splits into two severities:
|
|
10
|
+
*
|
|
11
|
+
* - FATAL faults → status `unverifiable` for the screen. A reference that is
|
|
12
|
+
* absent has nothing to judge against (`REFERENCE_ABSENT`); a screen with no
|
|
13
|
+
* provenance while the run declares a render locale keeps the legacy
|
|
14
|
+
* `NO_PROVENANCE` verdict (verifiable is earned only through the full
|
|
15
|
+
* export path, and it kills the ad-hoc-Figma-fetch root cause).
|
|
16
|
+
* - COPY-CHANNEL downgrades → the screen still renders and is judged on
|
|
17
|
+
* geometry, colors, typeface, spans, and lines; only copy comparisons are
|
|
18
|
+
* skipped, reported as a structured `copy_unverifiable` advisory naming the
|
|
19
|
+
* reason. Placeholder copy (`resolved == false`) and locale mismatches are
|
|
20
|
+
* normal customer reality — dynamic content is designed as placeholders —
|
|
21
|
+
* so the product adapts instead of refusing the screen or telling the
|
|
22
|
+
* customer to re-export.
|
|
23
|
+
*
|
|
24
|
+
* The check arms whenever per-screen provenance rides in params; a declared
|
|
25
|
+
* render locale is only required for the locale comparison itself. Screens
|
|
26
|
+
* with neither provenance nor a declared locale are unarmed and keep the
|
|
27
|
+
* caller's legacy behaviour.
|
|
12
28
|
*
|
|
13
29
|
* Content differences (copy wording, geometry) are deliberately NOT evaluated
|
|
14
30
|
* here — those are soft, judged findings that legitimately drift between
|
|
@@ -27,19 +43,45 @@ export interface ReferenceProvenanceMeta {
|
|
|
27
43
|
resolved?: boolean;
|
|
28
44
|
exportedAt?: string;
|
|
29
45
|
}
|
|
30
|
-
/** A reason a reference cannot be honestly judged. */
|
|
46
|
+
/** A reason a reference cannot be honestly judged at all. */
|
|
31
47
|
export interface ProvenanceFault {
|
|
32
|
-
/** Stable machine code (NO_PROVENANCE /
|
|
48
|
+
/** Stable machine code (NO_PROVENANCE / REFERENCE_ABSENT). */
|
|
33
49
|
code: string;
|
|
34
50
|
/** Human/agent-readable reason, naming the screen. */
|
|
35
51
|
message: string;
|
|
36
52
|
}
|
|
53
|
+
/** Advisory code for a downgraded copy channel. */
|
|
54
|
+
export declare const COPY_UNVERIFIABLE_CODE = "copy_unverifiable";
|
|
55
|
+
/**
|
|
56
|
+
* A copy-channel downgrade: the screen is judged normally except that copy
|
|
57
|
+
* comparisons are unverifiable for the named reason.
|
|
58
|
+
*/
|
|
59
|
+
export interface CopyChannelAdvisory {
|
|
60
|
+
code: typeof COPY_UNVERIFIABLE_CODE;
|
|
61
|
+
reason: 'unresolved_placeholders' | 'locale_mismatch';
|
|
62
|
+
/** Human/agent-readable reason, naming the screen. */
|
|
63
|
+
message: string;
|
|
64
|
+
}
|
|
65
|
+
/** The outcome of assessing one screen's reference provenance. */
|
|
66
|
+
export interface ProvenanceAssessment {
|
|
67
|
+
/** Fatal: the screen cannot be judged (status `unverifiable`), or null. */
|
|
68
|
+
fault: ProvenanceFault | null;
|
|
69
|
+
/** Copy-channel downgrade riding in the per-screen result, or null. */
|
|
70
|
+
copyAdvisory: CopyChannelAdvisory | null;
|
|
71
|
+
}
|
|
37
72
|
/** The per-state status string written to protocol-result.json. */
|
|
38
73
|
export declare const UNVERIFIABLE_STATUS = "unverifiable";
|
|
39
74
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
75
|
+
* Whether provenance is "present" for arming purposes. A partial object (e.g.
|
|
76
|
+
* a hand-dropped `{ figmaNode }`) is treated as no provenance — verifiable is
|
|
77
|
+
* earned only through the full export path.
|
|
78
|
+
*/
|
|
79
|
+
export declare function hasReferenceProvenance(p: ReferenceProvenanceMeta | null | undefined): p is ReferenceProvenanceMeta;
|
|
80
|
+
/**
|
|
81
|
+
* Assesses one screen's reference. Returns a fatal fault (screen
|
|
82
|
+
* `unverifiable`), a copy-channel advisory (screen judged, copy skipped), or
|
|
83
|
+
* neither. Never both: an absent reference wins over a downgrade because there
|
|
84
|
+
* is nothing to judge against.
|
|
43
85
|
*/
|
|
44
|
-
export declare function
|
|
86
|
+
export declare function assessReferenceProvenance(screen: string, provenance: ReferenceProvenanceMeta | null | undefined, renderLocale: string | null, referenceExists: boolean): ProvenanceAssessment;
|
|
45
87
|
//# sourceMappingURL=fidelity-reference-provenance.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fidelity-reference-provenance.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/fidelity-reference-provenance.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fidelity-reference-provenance.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/fidelity-reference-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,qEAAqE;AACrE,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mDAAmD;AACnD,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,sBAAsB,CAAC;IACpC,MAAM,EAAE,yBAAyB,GAAG,iBAAiB,CAAC;IACtD,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,uEAAuE;IACvE,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAC1C;AAED,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,GAC5C,CAAC,IAAI,uBAAuB,CAO9B;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EACtD,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,eAAe,EAAE,OAAO,GACvB,oBAAoB,CAqDtB"}
|
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reference-provenance
|
|
2
|
+
* Reference-provenance assessment.
|
|
3
3
|
*
|
|
4
4
|
* A UI-fidelity reference is a PNG the gate cannot read, so reference validity
|
|
5
5
|
* is asserted at export time as provenance metadata (`figmaNode`, `locale`,
|
|
6
6
|
* `resolved`, `exportedAt`) and the gate checks that METADATA — never the
|
|
7
|
-
* pixels, never via OCR.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* pixels, never via OCR.
|
|
8
|
+
*
|
|
9
|
+
* The assessment splits into two severities:
|
|
10
|
+
*
|
|
11
|
+
* - FATAL faults → status `unverifiable` for the screen. A reference that is
|
|
12
|
+
* absent has nothing to judge against (`REFERENCE_ABSENT`); a screen with no
|
|
13
|
+
* provenance while the run declares a render locale keeps the legacy
|
|
14
|
+
* `NO_PROVENANCE` verdict (verifiable is earned only through the full
|
|
15
|
+
* export path, and it kills the ad-hoc-Figma-fetch root cause).
|
|
16
|
+
* - COPY-CHANNEL downgrades → the screen still renders and is judged on
|
|
17
|
+
* geometry, colors, typeface, spans, and lines; only copy comparisons are
|
|
18
|
+
* skipped, reported as a structured `copy_unverifiable` advisory naming the
|
|
19
|
+
* reason. Placeholder copy (`resolved == false`) and locale mismatches are
|
|
20
|
+
* normal customer reality — dynamic content is designed as placeholders —
|
|
21
|
+
* so the product adapts instead of refusing the screen or telling the
|
|
22
|
+
* customer to re-export.
|
|
23
|
+
*
|
|
24
|
+
* The check arms whenever per-screen provenance rides in params; a declared
|
|
25
|
+
* render locale is only required for the locale comparison itself. Screens
|
|
26
|
+
* with neither provenance nor a declared locale are unarmed and keep the
|
|
27
|
+
* caller's legacy behaviour.
|
|
12
28
|
*
|
|
13
29
|
* Content differences (copy wording, geometry) are deliberately NOT evaluated
|
|
14
30
|
* here — those are soft, judged findings that legitimately drift between
|
|
@@ -20,50 +36,76 @@
|
|
|
20
36
|
* tests exercise that inlined copy end-to-end against the same fixtures, so the
|
|
21
37
|
* two cannot silently drift.
|
|
22
38
|
*/
|
|
39
|
+
/** Advisory code for a downgraded copy channel. */
|
|
40
|
+
export const COPY_UNVERIFIABLE_CODE = 'copy_unverifiable';
|
|
23
41
|
/** The per-state status string written to protocol-result.json. */
|
|
24
42
|
export const UNVERIFIABLE_STATUS = 'unverifiable';
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Whether provenance is "present" for arming purposes. A partial object (e.g.
|
|
45
|
+
* a hand-dropped `{ figmaNode }`) is treated as no provenance — verifiable is
|
|
46
|
+
* earned only through the full export path.
|
|
47
|
+
*/
|
|
48
|
+
export function hasReferenceProvenance(p) {
|
|
29
49
|
return (p != null &&
|
|
30
50
|
typeof p === 'object' &&
|
|
31
51
|
typeof p.locale === 'string' &&
|
|
32
52
|
typeof p.resolved === 'boolean');
|
|
33
53
|
}
|
|
34
54
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
55
|
+
* Assesses one screen's reference. Returns a fatal fault (screen
|
|
56
|
+
* `unverifiable`), a copy-channel advisory (screen judged, copy skipped), or
|
|
57
|
+
* neither. Never both: an absent reference wins over a downgrade because there
|
|
58
|
+
* is nothing to judge against.
|
|
38
59
|
*/
|
|
39
|
-
export function
|
|
40
|
-
if (!
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
export function assessReferenceProvenance(screen, provenance, renderLocale, referenceExists) {
|
|
61
|
+
if (!hasReferenceProvenance(provenance)) {
|
|
62
|
+
if (renderLocale !== null) {
|
|
63
|
+
return {
|
|
64
|
+
fault: {
|
|
65
|
+
code: 'NO_PROVENANCE',
|
|
66
|
+
message: `reference for ${screen} has no export provenance; a reference is ` +
|
|
67
|
+
`verifiable only when exported through the deterministic path`,
|
|
68
|
+
},
|
|
69
|
+
copyAdvisory: null,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Unarmed: no provenance rode in and no locale was declared — the caller
|
|
73
|
+
// keeps its legacy behaviour (including its own reference-existence check).
|
|
74
|
+
return { fault: null, copyAdvisory: null };
|
|
46
75
|
}
|
|
47
|
-
if (
|
|
76
|
+
if (!referenceExists) {
|
|
48
77
|
return {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
`
|
|
78
|
+
fault: {
|
|
79
|
+
code: 'REFERENCE_ABSENT',
|
|
80
|
+
message: `reference image for ${screen} is absent`,
|
|
81
|
+
},
|
|
82
|
+
copyAdvisory: null,
|
|
52
83
|
};
|
|
53
84
|
}
|
|
54
|
-
if (provenance.
|
|
85
|
+
if (provenance.resolved === false) {
|
|
55
86
|
return {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
87
|
+
fault: null,
|
|
88
|
+
copyAdvisory: {
|
|
89
|
+
code: COPY_UNVERIFIABLE_CODE,
|
|
90
|
+
reason: 'unresolved_placeholders',
|
|
91
|
+
message: `reference for ${screen} carries unresolved copy placeholders ` +
|
|
92
|
+
`(resolved=false); copy comparisons are skipped — geometry, color, ` +
|
|
93
|
+
`typeface, span, and line judging still hold`,
|
|
94
|
+
},
|
|
59
95
|
};
|
|
60
96
|
}
|
|
61
|
-
if (
|
|
97
|
+
if (renderLocale !== null && provenance.locale !== renderLocale) {
|
|
62
98
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
99
|
+
fault: null,
|
|
100
|
+
copyAdvisory: {
|
|
101
|
+
code: COPY_UNVERIFIABLE_CODE,
|
|
102
|
+
reason: 'locale_mismatch',
|
|
103
|
+
message: `reference for ${screen} is locale "${provenance.locale}" but the ` +
|
|
104
|
+
`render locale is "${renderLocale}"; copy comparisons are skipped — ` +
|
|
105
|
+
`geometry, color, typeface, span, and line judging still hold`,
|
|
106
|
+
},
|
|
65
107
|
};
|
|
66
108
|
}
|
|
67
|
-
return null;
|
|
109
|
+
return { fault: null, copyAdvisory: null };
|
|
68
110
|
}
|
|
69
111
|
//# sourceMappingURL=fidelity-reference-provenance.js.map
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unit tests for the reference-provenance
|
|
2
|
+
* Unit tests for the reference-provenance assessment.
|
|
3
3
|
*
|
|
4
4
|
* A UI-fidelity reference is a PNG; the gate cannot read its text. So validity
|
|
5
5
|
* is asserted at export time as provenance metadata, and the gate checks the
|
|
6
|
-
* METADATA, never the pixels (no OCR).
|
|
7
|
-
* placeholder-bearing (`resolved == false`), or in the wrong locale is
|
|
8
|
-
* UNVERIFIABLE — a loud, mechanical verdict, not a confident-but-false PASS.
|
|
6
|
+
* METADATA, never the pixels (no OCR).
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* The assessment splits into two severities:
|
|
9
|
+
* - FATAL faults (reference absent; no provenance while a render locale is
|
|
10
|
+
* declared): the screen cannot be judged at all → status `unverifiable`.
|
|
11
|
+
* - COPY-CHANNEL downgrades (unresolved placeholders, locale mismatch): the
|
|
12
|
+
* screen renders and is judged on every non-copy channel; copy comparisons
|
|
13
|
+
* are skipped and reported as a `copy_unverifiable` advisory. Placeholder
|
|
14
|
+
* copy in a design is normal customer reality — the product adapts, the
|
|
15
|
+
* customer is never told to re-export.
|
|
16
|
+
*
|
|
17
|
+
* The check arms whenever provenance is present; a declared render locale is
|
|
18
|
+
* only required for the locale comparison itself (and preserves the legacy
|
|
19
|
+
* NO_PROVENANCE behaviour for unprovenanced screens).
|
|
12
20
|
*/
|
|
13
21
|
export {};
|
|
14
22
|
//# sourceMappingURL=fidelity-reference-provenance.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fidelity-reference-provenance.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/fidelity-reference-provenance.test.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fidelity-reference-provenance.test.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/fidelity-reference-provenance.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -1,52 +1,116 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unit tests for the reference-provenance
|
|
2
|
+
* Unit tests for the reference-provenance assessment.
|
|
3
3
|
*
|
|
4
4
|
* A UI-fidelity reference is a PNG; the gate cannot read its text. So validity
|
|
5
5
|
* is asserted at export time as provenance metadata, and the gate checks the
|
|
6
|
-
* METADATA, never the pixels (no OCR).
|
|
7
|
-
* placeholder-bearing (`resolved == false`), or in the wrong locale is
|
|
8
|
-
* UNVERIFIABLE — a loud, mechanical verdict, not a confident-but-false PASS.
|
|
6
|
+
* METADATA, never the pixels (no OCR).
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* The assessment splits into two severities:
|
|
9
|
+
* - FATAL faults (reference absent; no provenance while a render locale is
|
|
10
|
+
* declared): the screen cannot be judged at all → status `unverifiable`.
|
|
11
|
+
* - COPY-CHANNEL downgrades (unresolved placeholders, locale mismatch): the
|
|
12
|
+
* screen renders and is judged on every non-copy channel; copy comparisons
|
|
13
|
+
* are skipped and reported as a `copy_unverifiable` advisory. Placeholder
|
|
14
|
+
* copy in a design is normal customer reality — the product adapts, the
|
|
15
|
+
* customer is never told to re-export.
|
|
16
|
+
*
|
|
17
|
+
* The check arms whenever provenance is present; a declared render locale is
|
|
18
|
+
* only required for the locale comparison itself (and preserves the legacy
|
|
19
|
+
* NO_PROVENANCE behaviour for unprovenanced screens).
|
|
12
20
|
*/
|
|
13
21
|
import { describe, test, expect } from '@jest/globals';
|
|
14
|
-
import {
|
|
22
|
+
import { assessReferenceProvenance, hasReferenceProvenance, UNVERIFIABLE_STATUS, COPY_UNVERIFIABLE_CODE, } from './fidelity-reference-provenance.js';
|
|
15
23
|
const GOOD = {
|
|
16
24
|
figmaNode: '12:345',
|
|
17
25
|
locale: 'en',
|
|
18
26
|
resolved: true,
|
|
19
27
|
exportedAt: '2026-06-18T10:00:00Z',
|
|
20
28
|
};
|
|
21
|
-
describe('
|
|
22
|
-
test('a present, provenanced, resolved, locale-matching reference is
|
|
23
|
-
expect(
|
|
29
|
+
describe('assessReferenceProvenance', () => {
|
|
30
|
+
test('a present, provenanced, resolved, locale-matching reference is clean', () => {
|
|
31
|
+
expect(assessReferenceProvenance('Guest', GOOD, 'en', true)).toEqual({
|
|
32
|
+
fault: null,
|
|
33
|
+
copyAdvisory: null,
|
|
34
|
+
});
|
|
24
35
|
});
|
|
25
|
-
test('
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
test('provenance present without a declared render locale is clean too', () => {
|
|
37
|
+
expect(assessReferenceProvenance('Guest', GOOD, null, true)).toEqual({
|
|
38
|
+
fault: null,
|
|
39
|
+
copyAdvisory: null,
|
|
40
|
+
});
|
|
28
41
|
});
|
|
29
|
-
test('
|
|
30
|
-
expect(
|
|
31
|
-
expect(
|
|
42
|
+
test('an absent reference with provenance is FATAL (REFERENCE_ABSENT), locale or not', () => {
|
|
43
|
+
expect(assessReferenceProvenance('Guest', GOOD, 'en', false).fault?.code).toBe('REFERENCE_ABSENT');
|
|
44
|
+
expect(assessReferenceProvenance('Guest', GOOD, null, false).fault?.code).toBe('REFERENCE_ABSENT');
|
|
32
45
|
});
|
|
33
|
-
test('
|
|
34
|
-
|
|
46
|
+
test('unresolved placeholders downgrade the copy channel — never the screen', () => {
|
|
47
|
+
const assessment = assessReferenceProvenance('Guest', { ...GOOD, resolved: false }, 'en', true);
|
|
48
|
+
expect(assessment.fault).toBeNull();
|
|
49
|
+
expect(assessment.copyAdvisory?.code).toBe(COPY_UNVERIFIABLE_CODE);
|
|
50
|
+
expect(assessment.copyAdvisory?.reason).toBe('unresolved_placeholders');
|
|
35
51
|
});
|
|
36
|
-
test('
|
|
37
|
-
|
|
38
|
-
|
|
52
|
+
test('unresolved placeholders downgrade identically without a render locale', () => {
|
|
53
|
+
// Live evidence: the same resolved:false reference must earn the same
|
|
54
|
+
// verdict whether or not the run declared render_locale.
|
|
55
|
+
const assessment = assessReferenceProvenance('Guest', { ...GOOD, resolved: false }, null, true);
|
|
56
|
+
expect(assessment.fault).toBeNull();
|
|
57
|
+
expect(assessment.copyAdvisory?.reason).toBe('unresolved_placeholders');
|
|
39
58
|
});
|
|
40
|
-
test('a wrong-locale reference
|
|
59
|
+
test('a wrong-locale reference downgrades the copy channel (LOCALE reason)', () => {
|
|
41
60
|
// Italian reference vs an English render.
|
|
42
|
-
const
|
|
43
|
-
expect(fault
|
|
61
|
+
const assessment = assessReferenceProvenance('Guest', { ...GOOD, locale: 'it' }, 'en', true);
|
|
62
|
+
expect(assessment.fault).toBeNull();
|
|
63
|
+
expect(assessment.copyAdvisory?.code).toBe(COPY_UNVERIFIABLE_CODE);
|
|
64
|
+
expect(assessment.copyAdvisory?.reason).toBe('locale_mismatch');
|
|
65
|
+
});
|
|
66
|
+
test('locale comparison requires a declared render locale — its absence skips only that', () => {
|
|
67
|
+
const assessment = assessReferenceProvenance('Guest', { ...GOOD, locale: 'it' }, null, true);
|
|
68
|
+
expect(assessment).toEqual({ fault: null, copyAdvisory: null });
|
|
69
|
+
});
|
|
70
|
+
test('an absent reference wins over a copy downgrade (nothing to judge against)', () => {
|
|
71
|
+
const assessment = assessReferenceProvenance('Guest', { ...GOOD, resolved: false }, 'en', false);
|
|
72
|
+
expect(assessment.fault?.code).toBe('REFERENCE_ABSENT');
|
|
73
|
+
expect(assessment.copyAdvisory).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
test('no provenance with a declared render locale stays FATAL (NO_PROVENANCE, legacy arming)', () => {
|
|
76
|
+
expect(assessReferenceProvenance('Guest', null, 'en', true).fault?.code).toBe('NO_PROVENANCE');
|
|
77
|
+
expect(assessReferenceProvenance('Guest', undefined, 'en', true).fault?.code).toBe('NO_PROVENANCE');
|
|
78
|
+
});
|
|
79
|
+
test('incomplete provenance (missing locale/resolved) is treated as no provenance', () => {
|
|
80
|
+
expect(assessReferenceProvenance('Guest', { figmaNode: 'x', exportedAt: 'y' }, 'en', true).fault
|
|
81
|
+
?.code).toBe('NO_PROVENANCE');
|
|
44
82
|
});
|
|
45
|
-
test('
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
83
|
+
test('no provenance and no render locale is unarmed — the caller keeps legacy behaviour', () => {
|
|
84
|
+
expect(assessReferenceProvenance('Guest', null, null, false)).toEqual({
|
|
85
|
+
fault: null,
|
|
86
|
+
copyAdvisory: null,
|
|
87
|
+
});
|
|
88
|
+
expect(assessReferenceProvenance('Guest', null, null, true)).toEqual({
|
|
89
|
+
fault: null,
|
|
90
|
+
copyAdvisory: null,
|
|
91
|
+
});
|
|
49
92
|
});
|
|
93
|
+
test('faults and advisories carry the screen name and a human reason', () => {
|
|
94
|
+
const fatal = assessReferenceProvenance('LoggedIn', GOOD, 'en', false);
|
|
95
|
+
expect(fatal.fault?.message).toContain('LoggedIn');
|
|
96
|
+
const downgraded = assessReferenceProvenance('LoggedIn', { ...GOOD, resolved: false }, 'en', true);
|
|
97
|
+
expect(downgraded.copyAdvisory?.message).toContain('LoggedIn');
|
|
98
|
+
expect(downgraded.copyAdvisory.message.length).toBeGreaterThan(10);
|
|
99
|
+
});
|
|
100
|
+
test('the downgrade message never tells the customer to fix their design', () => {
|
|
101
|
+
const assessment = assessReferenceProvenance('Guest', { ...GOOD, resolved: false }, 'en', true);
|
|
102
|
+
expect(assessment.copyAdvisory?.message.toLowerCase()).not.toContain('export it');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('hasReferenceProvenance', () => {
|
|
106
|
+
test('full export-path provenance is present; partial or missing is not', () => {
|
|
107
|
+
expect(hasReferenceProvenance(GOOD)).toBe(true);
|
|
108
|
+
expect(hasReferenceProvenance(null)).toBe(false);
|
|
109
|
+
expect(hasReferenceProvenance(undefined)).toBe(false);
|
|
110
|
+
expect(hasReferenceProvenance({ figmaNode: 'x' })).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe('status strings', () => {
|
|
50
114
|
test('exposes the unverifiable status string the result document uses', () => {
|
|
51
115
|
expect(UNVERIFIABLE_STATUS).toBe('unverifiable');
|
|
52
116
|
});
|
|
@@ -12,12 +12,17 @@
|
|
|
12
12
|
* Optional reference-provenance sidecar (manifest-driven multi-state path):
|
|
13
13
|
* `"render_locale": "<locale>"` plus
|
|
14
14
|
* `"provenance": { "<ScreenName>": { figmaNode, locale, resolved, exportedAt } }`.
|
|
15
|
-
*
|
|
16
|
-
* provenance METADATA (never
|
|
17
|
-
*
|
|
18
|
-
* `
|
|
19
|
-
* of yielding a confident-but-false PASS.
|
|
20
|
-
*
|
|
15
|
+
* The gate arms whenever a screen's provenance is present (or, legacy, when
|
|
16
|
+
* `render_locale` is declared) and checks provenance METADATA only (never
|
|
17
|
+
* pixels/OCR). An absent reference — or an unprovenanced screen while
|
|
18
|
+
* `render_locale` is declared — is FATAL: status `unverifiable`, failing
|
|
19
|
+
* loud instead of yielding a confident-but-false PASS. `resolved == false`
|
|
20
|
+
* (placeholder copy) or `locale != render_locale` downgrade ONLY the copy
|
|
21
|
+
* channel: the screen renders and is judged on geometry, colors, typeface,
|
|
22
|
+
* spans, and lines, while copy comparisons are skipped and reported as a
|
|
23
|
+
* per-screen `copy_advisory` (`copy_unverifiable` + reason) in
|
|
24
|
+
* protocol-result.json. Content differences (copy, geometry) are NOT gated
|
|
25
|
+
* here — they stay soft, judged findings.
|
|
21
26
|
* 2. Extracts and validates the shipped Gradle project shipped as
|
|
22
27
|
* `.ci/inputs/package.tar.gz` (single project root carrying a settings
|
|
23
28
|
* script, bounded extracted size, safe member paths).
|
|
@@ -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
|
|
1
|
+
{"version":3,"file":"ui-fidelity-render-android.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/ui-fidelity-render-android.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;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;AAMpE,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,iDAAiD;AACjD,eAAO,MAAM,eAAe,6BAA8B,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAAwB,CAAC;AAE9D,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAA0B,CAAC;AAElE,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;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAkiCD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAqBrF;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;CA0EpB"}
|