my-frontend-observer 0.4.0 → 0.5.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 (53) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +39 -11
  3. package/dist/application/frontendContractEvaluationService.d.ts +49 -0
  4. package/dist/application/frontendContractEvaluationService.js +112 -0
  5. package/dist/application/frontendContractEvaluationService.js.map +1 -0
  6. package/dist/application/frontendContractPersistenceService.d.ts +56 -0
  7. package/dist/application/frontendContractPersistenceService.js +91 -0
  8. package/dist/application/frontendContractPersistenceService.js.map +1 -0
  9. package/dist/artifacts/comparisonArtifactReader.d.ts +18 -0
  10. package/dist/artifacts/comparisonArtifactReader.js +35 -0
  11. package/dist/artifacts/comparisonArtifactReader.js.map +1 -0
  12. package/dist/artifacts/frontendContractArtifactReader.d.ts +24 -0
  13. package/dist/artifacts/frontendContractArtifactReader.js +47 -0
  14. package/dist/artifacts/frontendContractArtifactReader.js.map +1 -0
  15. package/dist/artifacts/frontendContractArtifactWriter.d.ts +34 -0
  16. package/dist/artifacts/frontendContractArtifactWriter.js +70 -0
  17. package/dist/artifacts/frontendContractArtifactWriter.js.map +1 -0
  18. package/dist/artifacts/frontendContractEvaluationArtifactReader.d.ts +17 -0
  19. package/dist/artifacts/frontendContractEvaluationArtifactReader.js +34 -0
  20. package/dist/artifacts/frontendContractEvaluationArtifactReader.js.map +1 -0
  21. package/dist/artifacts/frontendContractEvaluationArtifactWriter.d.ts +32 -0
  22. package/dist/artifacts/frontendContractEvaluationArtifactWriter.js +58 -0
  23. package/dist/artifacts/frontendContractEvaluationArtifactWriter.js.map +1 -0
  24. package/dist/cli.js +496 -6
  25. package/dist/cli.js.map +1 -1
  26. package/dist/domain/frontendContractEvaluation.d.ts +57 -0
  27. package/dist/domain/frontendContractEvaluation.js +454 -0
  28. package/dist/domain/frontendContractEvaluation.js.map +1 -0
  29. package/dist/domain/frontendContractEvaluationArtifact.d.ts +65 -0
  30. package/dist/domain/frontendContractEvaluationArtifact.js +108 -0
  31. package/dist/domain/frontendContractEvaluationArtifact.js.map +1 -0
  32. package/dist/domain/frontendContractIdentity.d.ts +39 -0
  33. package/dist/domain/frontendContractIdentity.js +70 -0
  34. package/dist/domain/frontendContractIdentity.js.map +1 -0
  35. package/dist/domain/frontendContracts.d.ts +188 -0
  36. package/dist/domain/frontendContracts.js +260 -0
  37. package/dist/domain/frontendContracts.js.map +1 -0
  38. package/dist/index.d.ts +22 -0
  39. package/dist/index.js +12 -0
  40. package/dist/index.js.map +1 -1
  41. package/docs/ARCHITECTURE.md +98 -1
  42. package/docs/CI_CD.md +47 -0
  43. package/docs/COMMANDS.md +162 -0
  44. package/docs/CONTRACTS.md +175 -3
  45. package/docs/CURRENT_STATE.md +92 -10
  46. package/docs/DEVELOPMENT.md +58 -10
  47. package/docs/PROJECT_OVERVIEW.md +19 -13
  48. package/docs/QUICKSTART.md +5 -0
  49. package/docs/RELEASE.md +17 -10
  50. package/docs/ROADMAP.md +6 -0
  51. package/docs/SECURITY.md +13 -1
  52. package/docs/WORKFLOWS.md +65 -8
  53. package/package.json +1 -1
@@ -0,0 +1,260 @@
1
+ import { isValidEvidenceReference, PAIRWISE_RELATIONSHIP_KINDS, PAGE_LEVEL_RELATIONSHIP_KINDS } from './relationships.js';
2
+ import { DEPENDENCY_PROPERTIES } from './comparison.js';
3
+ import { PRODUCER_NAME, SCHEMA_VERSION as OBSERVATION_SCHEMA_VERSION } from './schema.js';
4
+ function isPlainObject(value) {
5
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
6
+ }
7
+ function isNonEmptyString(value) {
8
+ return typeof value === 'string' && value.length > 0;
9
+ }
10
+ function isEvidenceReferenceArray(value) {
11
+ return Array.isArray(value) && value.every((entry) => isValidEvidenceReference(entry));
12
+ }
13
+ export const CONTRACT_ARTIFACT_KIND = 'my-frontend-observer/frontend-contract';
14
+ export const CONTRACT_SCHEMA_VERSION = '1.0.0';
15
+ // --- Change-scope vocabulary --------------------------------------------------
16
+ /** The authored per-change contract has exactly these 4 intent categories - `'unexpected'` is never a member. */
17
+ export const AUTHORED_CHANGE_SCOPE_CATEGORIES = ['requested', 'expected-dependent', 'protected', 'preserved'];
18
+ export function isAuthoredChangeScopeCategory(value) {
19
+ return typeof value === 'string' && AUTHORED_CHANGE_SCOPE_CATEGORIES.includes(value);
20
+ }
21
+ /**
22
+ * Full derived classification vocabulary, kept structurally separate from
23
+ * AUTHORED_CHANGE_SCOPE_CATEGORIES - `'unexpected'` is a classification a
24
+ * future evaluator produces, never an authored permission. No function in
25
+ * this module converts between the two vocabularies.
26
+ */
27
+ export const CHANGE_SCOPE_CLASSIFICATIONS = [...AUTHORED_CHANGE_SCOPE_CATEGORIES, 'unexpected'];
28
+ export const EXPECTED_DEPENDENT_MODES = ['required', 'permitted'];
29
+ export function isValidExpectedDependentMode(value) {
30
+ return typeof value === 'string' && EXPECTED_DEPENDENT_MODES.includes(value);
31
+ }
32
+ // --- Contract tolerance (bounded, closed - never a generic expression) -------
33
+ /** Independently declared from GEOMETRY_TOLERANCE_*_PX (src/domain/relationships.ts): comparison tolerance suppresses insignificant geometry noise and is never contract authorization. */
34
+ export const CONTRACT_TOLERANCE_ABSOLUTE_PX_MIN = 0;
35
+ export const CONTRACT_TOLERANCE_ABSOLUTE_PX_MAX = 100;
36
+ export const CONTRACT_TOLERANCE_PERCENT_MIN = 0;
37
+ export const CONTRACT_TOLERANCE_PERCENT_MAX = 100;
38
+ export function isValidContractTolerance(value) {
39
+ if (!isPlainObject(value))
40
+ return false;
41
+ if (value.kind === 'exact')
42
+ return Object.keys(value).length === 1;
43
+ if (value.kind === 'absolute-px') {
44
+ return (typeof value.amount === 'number' &&
45
+ Number.isFinite(value.amount) &&
46
+ value.amount >= CONTRACT_TOLERANCE_ABSOLUTE_PX_MIN &&
47
+ value.amount <= CONTRACT_TOLERANCE_ABSOLUTE_PX_MAX);
48
+ }
49
+ if (value.kind === 'percent') {
50
+ return (typeof value.amount === 'number' &&
51
+ Number.isFinite(value.amount) &&
52
+ value.amount >= CONTRACT_TOLERANCE_PERCENT_MIN &&
53
+ value.amount <= CONTRACT_TOLERANCE_PERCENT_MAX);
54
+ }
55
+ return false;
56
+ }
57
+ // --- Contract primitive vocabulary (bounded, closed) --------------------------
58
+ /** Every contract primitive kind this batch freezes - deliberately bounded, never a generic rule/expression language. */
59
+ export const CONTRACT_PRIMITIVE_KINDS = [
60
+ 'target-visible',
61
+ 'target-not-clipped',
62
+ 'target-width-within-bound',
63
+ 'targets-do-not-overlap',
64
+ 'target-wider-than',
65
+ 'target-follows-vertically',
66
+ 'target-fits-inside',
67
+ 'document-width-fits-viewport',
68
+ 'scroll-owner-is-document',
69
+ 'target-does-not-own-scroll',
70
+ 'target-begins-below-initial-viewport',
71
+ 'relationship-unchanged',
72
+ 'property-unchanged-within-tolerance',
73
+ 'property-increases',
74
+ 'property-decreases',
75
+ ];
76
+ const ALL_RELATIONSHIP_KINDS = [...PAIRWISE_RELATIONSHIP_KINDS, ...PAGE_LEVEL_RELATIONSHIP_KINDS];
77
+ function isOptionalFiniteNumber(value) {
78
+ return value === undefined || (typeof value === 'number' && Number.isFinite(value));
79
+ }
80
+ function isOptionalNonNegativeFiniteNumber(value) {
81
+ return value === undefined || (typeof value === 'number' && Number.isFinite(value) && value >= 0);
82
+ }
83
+ /** Rejects extra keys beyond the given allowlist, keeping every ContractPrimitive variant a closed shape rather than an open bag of fields. */
84
+ function hasOnlyKeys(value, allowedKeys) {
85
+ return Object.keys(value).every((key) => allowedKeys.includes(key));
86
+ }
87
+ export function isValidContractPrimitive(value) {
88
+ if (!isPlainObject(value) || typeof value.kind !== 'string')
89
+ return false;
90
+ switch (value.kind) {
91
+ case 'target-visible':
92
+ return hasOnlyKeys(value, ['kind', 'target']) && isNonEmptyString(value.target);
93
+ case 'target-not-clipped':
94
+ return (hasOnlyKeys(value, ['kind', 'target', 'axis']) &&
95
+ isNonEmptyString(value.target) &&
96
+ (value.axis === undefined || value.axis === 'horizontal' || value.axis === 'vertical' || value.axis === 'both'));
97
+ case 'target-width-within-bound': {
98
+ if (!hasOnlyKeys(value, ['kind', 'target', 'minPx', 'maxPx']))
99
+ return false;
100
+ if (!isNonEmptyString(value.target))
101
+ return false;
102
+ if (!isOptionalFiniteNumber(value.minPx) || !isOptionalFiniteNumber(value.maxPx))
103
+ return false;
104
+ if (value.minPx === undefined && value.maxPx === undefined)
105
+ return false;
106
+ if (typeof value.minPx === 'number' && typeof value.maxPx === 'number' && value.minPx > value.maxPx)
107
+ return false;
108
+ return true;
109
+ }
110
+ case 'targets-do-not-overlap':
111
+ case 'target-wider-than':
112
+ case 'target-follows-vertically':
113
+ return (hasOnlyKeys(value, ['kind', 'targetA', 'targetB']) &&
114
+ isNonEmptyString(value.targetA) &&
115
+ isNonEmptyString(value.targetB) &&
116
+ value.targetA !== value.targetB);
117
+ case 'target-fits-inside':
118
+ return (hasOnlyKeys(value, ['kind', 'target', 'container']) &&
119
+ isNonEmptyString(value.target) &&
120
+ isNonEmptyString(value.container) &&
121
+ value.target !== value.container);
122
+ case 'document-width-fits-viewport':
123
+ case 'scroll-owner-is-document':
124
+ return hasOnlyKeys(value, ['kind']) && Object.keys(value).length === 1;
125
+ case 'target-does-not-own-scroll':
126
+ case 'target-begins-below-initial-viewport':
127
+ return hasOnlyKeys(value, ['kind', 'target']) && isNonEmptyString(value.target);
128
+ case 'relationship-unchanged':
129
+ return (hasOnlyKeys(value, ['kind', 'relationshipKind', 'subjectTarget', 'relatedTarget']) &&
130
+ typeof value.relationshipKind === 'string' &&
131
+ ALL_RELATIONSHIP_KINDS.includes(value.relationshipKind) &&
132
+ (value.subjectTarget === undefined || typeof value.subjectTarget === 'string') &&
133
+ (value.relatedTarget === undefined || typeof value.relatedTarget === 'string'));
134
+ case 'property-unchanged-within-tolerance':
135
+ return (hasOnlyKeys(value, ['kind', 'target', 'property', 'tolerance']) &&
136
+ isNonEmptyString(value.target) &&
137
+ typeof value.property === 'string' &&
138
+ DEPENDENCY_PROPERTIES.includes(value.property) &&
139
+ isValidContractTolerance(value.tolerance));
140
+ case 'property-increases':
141
+ case 'property-decreases':
142
+ return (hasOnlyKeys(value, ['kind', 'target', 'property', 'minimumDeltaPx']) &&
143
+ isNonEmptyString(value.target) &&
144
+ typeof value.property === 'string' &&
145
+ DEPENDENCY_PROPERTIES.includes(value.property) &&
146
+ isOptionalNonNegativeFiniteNumber(value.minimumDeltaPx));
147
+ default:
148
+ return false;
149
+ }
150
+ }
151
+ export function isValidBaselineClause(value) {
152
+ if (!isPlainObject(value))
153
+ return false;
154
+ return isNonEmptyString(value.clauseId) && isValidContractPrimitive(value.primitive) && isEvidenceReferenceArray(value.supportingEvidence);
155
+ }
156
+ export function isValidPerChangeClause(value) {
157
+ if (!isPlainObject(value))
158
+ return false;
159
+ if (!isValidBaselineClause(value))
160
+ return false;
161
+ const record = value;
162
+ if (!isAuthoredChangeScopeCategory(record.category))
163
+ return false;
164
+ const hasMode = 'expectedDependentMode' in record && record.expectedDependentMode !== undefined;
165
+ if (record.category === 'expected-dependent') {
166
+ if (!hasMode || !isValidExpectedDependentMode(record.expectedDependentMode))
167
+ return false;
168
+ }
169
+ else if (hasMode) {
170
+ return false;
171
+ }
172
+ if ('supersedesBaselineClauseIds' in record && record.supersedesBaselineClauseIds !== undefined) {
173
+ const ids = record.supersedesBaselineClauseIds;
174
+ if (!Array.isArray(ids) || ids.length === 0)
175
+ return false;
176
+ if (!ids.every((id) => isNonEmptyString(id)))
177
+ return false;
178
+ }
179
+ return true;
180
+ }
181
+ export function isValidFrontendContractObservationReference(value) {
182
+ if (!isPlainObject(value))
183
+ return false;
184
+ if (!isNonEmptyString(value.observationId) || !isNonEmptyString(value.requestId))
185
+ return false;
186
+ if (!isPlainObject(value.producer) || value.producer.name !== PRODUCER_NAME || !isNonEmptyString(value.producer.version))
187
+ return false;
188
+ return value.observationSchemaVersion === OBSERVATION_SCHEMA_VERSION;
189
+ }
190
+ export function isValidPersistentBaselineContract(value) {
191
+ if (!isPlainObject(value))
192
+ return { valid: false, reason: 'contract must be an object' };
193
+ if (value.artifactKind !== CONTRACT_ARTIFACT_KIND)
194
+ return { valid: false, reason: 'artifactKind mismatch' };
195
+ if (value.schemaVersion !== CONTRACT_SCHEMA_VERSION)
196
+ return { valid: false, reason: 'schemaVersion mismatch' };
197
+ if (value.contractClass !== 'baseline')
198
+ return { valid: false, reason: 'contractClass must be "baseline"' };
199
+ if (!isNonEmptyString(value.baselineId))
200
+ return { valid: false, reason: 'baselineId must be a non-empty string' };
201
+ if ('supersedesBaselineId' in value && value.supersedesBaselineId !== undefined && !isNonEmptyString(value.supersedesBaselineId)) {
202
+ return { valid: false, reason: 'supersedesBaselineId must be a non-empty string when present' };
203
+ }
204
+ if (!isValidFrontendContractObservationReference(value.sourceObservation))
205
+ return { valid: false, reason: 'sourceObservation is invalid' };
206
+ if (!Array.isArray(value.clauses) || !value.clauses.every((c) => isValidBaselineClause(c))) {
207
+ return { valid: false, reason: 'clauses must be an array of valid BaselineClause values' };
208
+ }
209
+ if (!isPlainObject(value.provenance) || !isNonEmptyString(value.provenance.approvedAt)) {
210
+ return { valid: false, reason: 'provenance.approvedAt must be a non-empty string' };
211
+ }
212
+ return { valid: true };
213
+ }
214
+ export function isValidPerChangeContract(value) {
215
+ if (!isPlainObject(value))
216
+ return { valid: false, reason: 'contract must be an object' };
217
+ if (value.artifactKind !== CONTRACT_ARTIFACT_KIND)
218
+ return { valid: false, reason: 'artifactKind mismatch' };
219
+ if (value.schemaVersion !== CONTRACT_SCHEMA_VERSION)
220
+ return { valid: false, reason: 'schemaVersion mismatch' };
221
+ if (value.contractClass !== 'change')
222
+ return { valid: false, reason: 'contractClass must be "change"' };
223
+ if (!isNonEmptyString(value.contractId))
224
+ return { valid: false, reason: 'contractId must be a non-empty string' };
225
+ if (!isNonEmptyString(value.contractRequestId))
226
+ return { valid: false, reason: 'contractRequestId must be a non-empty string' };
227
+ if (!Array.isArray(value.activeBaselineIds) || !value.activeBaselineIds.every((id) => isNonEmptyString(id))) {
228
+ return { valid: false, reason: 'activeBaselineIds must be an array of non-empty strings' };
229
+ }
230
+ if (!Array.isArray(value.clauses) || !value.clauses.every((c) => isValidPerChangeClause(c))) {
231
+ return { valid: false, reason: 'clauses must be an array of valid PerChangeClause values' };
232
+ }
233
+ return { valid: true };
234
+ }
235
+ // --- Per-clause evaluation result vocabulary (frozen vocabulary only; no producer in this batch) --
236
+ export const CLAUSE_RESULT_STATUSES = ['pass', 'fail', 'unavailable', 'conflict'];
237
+ /** Honest per-clause result vocabulary: `'unavailable'` requires a non-empty reason (never fabricated pass/fail); `'conflict'` requires at least 2 conflicting clause ids. */
238
+ export function isValidClauseEvaluationResult(value) {
239
+ if (!isPlainObject(value) || !isNonEmptyString(value.clauseId))
240
+ return false;
241
+ if (!isEvidenceReferenceArray(value.supportingEvidence))
242
+ return false;
243
+ switch (value.status) {
244
+ case 'pass':
245
+ case 'fail':
246
+ return !('reason' in value) && !('conflictingClauseIds' in value);
247
+ case 'unavailable':
248
+ return isNonEmptyString(value.reason) && !('conflictingClauseIds' in value);
249
+ case 'conflict':
250
+ return (isNonEmptyString(value.reason) &&
251
+ Array.isArray(value.conflictingClauseIds) &&
252
+ value.conflictingClauseIds.length >= 2 &&
253
+ value.conflictingClauseIds.every((id) => isNonEmptyString(id)));
254
+ default:
255
+ return false;
256
+ }
257
+ }
258
+ // --- Overall verdict vocabulary (type only; no producer in this batch) -----------
259
+ export const OVERALL_VERDICTS = ['PASS', 'FAIL'];
260
+ //# sourceMappingURL=frontendContracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontendContracts.js","sourceRoot":"","sources":["../../src/domain/frontendContracts.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -24,6 +24,28 @@ export { HORIZONTAL_ORDER_RELATIONSHIPS, VERTICAL_ORDER_RELATIONSHIPS, AREA_OVER
24
24
  export type { DependencyProperty, DependencyDirection, ExpectedDependencySource, DependencyTermDeclaration, ExpectedDependencyDeclaration, DependencyEvidenceOutcome, ExpectedDependencyEvidence, ComparisonConfig, ComparabilityState, ComparabilityReasonCode, ComparabilityReasonSeverity, ComparabilityReason, ComparabilityResult, TargetConfigurationChangeKind, TargetConfigurationChange, DifferenceKind, ComparisonDifferenceSubject, ComparisonDifference, RelationshipChangeRecord, ComparisonSourceObservationReference, ComparisonArtifact, ComparisonSchemaValidationResult, } from './domain/comparison.js';
25
25
  export { COMPARISON_ARTIFACT_KIND, COMPARISON_SCHEMA_VERSION, GEOMETRY_TOLERANCE_DEFAULT_PX, GEOMETRY_TOLERANCE_MIN_PX, GEOMETRY_TOLERANCE_MAX_PX, isValidGeometryTolerancePx, DEPENDENCY_PROPERTIES, DEPENDENCY_DIRECTIONS, EXPECTED_DEPENDENCY_SOURCES, isValidExpectedDependencyDeclaration, DEPENDENCY_EVIDENCE_OUTCOMES, isValidExpectedDependencyEvidence, isValidComparisonConfig, COMPARABILITY_STATES, COMPARABILITY_REASON_CODES, COMPARABILITY_REASON_SEVERITY, isValidComparabilityResult, TARGET_CONFIGURATION_CHANGE_KINDS, isValidTargetConfigurationChange, DIFFERENCE_KINDS, isValidComparisonDifference, isValidComparisonSourceObservationReference, isValidComparisonArtifact, } from './domain/comparison.js';
26
26
  export { buildComparisonRequestIdentity, buildComparisonIdentity } from './domain/comparisonIdentity.js';
27
+ export type { AuthoredChangeScopeCategory, ChangeScopeClassification, ExpectedDependentMode, ContractTolerance, ContractPrimitiveKind, ContractPrimitive, FrontendContractClauseBase, BaselineClause, PerChangeClause, FrontendContractObservationReference, PersistentBaselineContract, FrontendContractValidationResult, PerChangeContract, ClauseResultStatus, ClauseEvaluationResult, OverallVerdict, } from './domain/frontendContracts.js';
28
+ export { CONTRACT_ARTIFACT_KIND, CONTRACT_SCHEMA_VERSION, AUTHORED_CHANGE_SCOPE_CATEGORIES, isAuthoredChangeScopeCategory, CHANGE_SCOPE_CLASSIFICATIONS, EXPECTED_DEPENDENT_MODES, isValidExpectedDependentMode, CONTRACT_TOLERANCE_ABSOLUTE_PX_MIN, CONTRACT_TOLERANCE_ABSOLUTE_PX_MAX, CONTRACT_TOLERANCE_PERCENT_MIN, CONTRACT_TOLERANCE_PERCENT_MAX, isValidContractTolerance, CONTRACT_PRIMITIVE_KINDS, isValidContractPrimitive, isValidBaselineClause, isValidPerChangeClause, isValidFrontendContractObservationReference, isValidPersistentBaselineContract, isValidPerChangeContract, CLAUSE_RESULT_STATUSES, isValidClauseEvaluationResult, OVERALL_VERDICTS, } from './domain/frontendContracts.js';
29
+ export { buildFrontendContractRequestIdentity, buildFrontendContractInstanceIdentity, buildClauseIdentity } from './domain/frontendContractIdentity.js';
30
+ export type { FrontendContractEvaluationInput, UnexpectedChangeResult, FrontendContractEvaluationResult, EvaluateFrontendContractResult } from './domain/frontendContractEvaluation.js';
31
+ export { evaluateFrontendContract } from './domain/frontendContractEvaluation.js';
32
+ export { buildFrontendContractEvaluationRequestIdentity } from './domain/frontendContractIdentity.js';
33
+ export type { FrontendContractEvaluationSourceReference, FrontendContractEvaluationArtifact, FrontendContractEvaluationArtifactValidationResult, BuildFrontendContractEvaluationArtifactInput, } from './domain/frontendContractEvaluationArtifact.js';
34
+ export { EVALUATION_ARTIFACT_KIND, EVALUATION_SCHEMA_VERSION, isValidFrontendContractEvaluationArtifact, buildFrontendContractEvaluationArtifact, } from './domain/frontendContractEvaluationArtifact.js';
35
+ export type { PersistedFrontendContractResult, WriteFrontendContractArtifactOptions } from './artifacts/frontendContractArtifactWriter.js';
36
+ export { FRONTEND_CONTRACT_MANIFEST_FILENAME, writePersistentBaselineContract, writePerChangeContract } from './artifacts/frontendContractArtifactWriter.js';
37
+ export type { ReadPersistentBaselineContractResult, ReadPerChangeContractResult } from './artifacts/frontendContractArtifactReader.js';
38
+ export { readPersistentBaselineContract, readPerChangeContract } from './artifacts/frontendContractArtifactReader.js';
39
+ export type { ReadComparisonArtifactResult } from './artifacts/comparisonArtifactReader.js';
40
+ export { readComparisonArtifact } from './artifacts/comparisonArtifactReader.js';
41
+ export type { PersistedFrontendContractEvaluationResult, WriteFrontendContractEvaluationArtifactOptions } from './artifacts/frontendContractEvaluationArtifactWriter.js';
42
+ export { EVALUATION_MANIFEST_FILENAME, writeFrontendContractEvaluationArtifact } from './artifacts/frontendContractEvaluationArtifactWriter.js';
43
+ export type { ReadFrontendContractEvaluationArtifactResult } from './artifacts/frontendContractEvaluationArtifactReader.js';
44
+ export { readFrontendContractEvaluationArtifact } from './artifacts/frontendContractEvaluationArtifactReader.js';
45
+ export type { EvaluateAndPersistOptions, ApplicationFrontendContractEvaluationResult } from './application/frontendContractEvaluationService.js';
46
+ export { DEFAULT_EVALUATION_OUTPUT_LOCATION, evaluateAndPersist, evaluateAndPersistFromArtifactRoots } from './application/frontendContractEvaluationService.js';
47
+ export type { PersistFrontendContractOptions, ApplicationApproveBaselineResult, ApplicationPersistChangeContractResult } from './application/frontendContractPersistenceService.js';
48
+ export { approveAndPersistBaseline, persistPerChangeContract } from './application/frontendContractPersistenceService.js';
27
49
  export type { CompareObservationsResult } from './domain/comparisonEngine.js';
28
50
  export { compareObservations, evaluateComparability, evaluateExpectedDependencies, compareTargetConfiguration } from './domain/comparisonEngine.js';
29
51
  export type { PersistedComparisonResult, WriteComparisonArtifactOptions } from './artifacts/comparisonArtifactWriter.js';
package/dist/index.js CHANGED
@@ -12,6 +12,18 @@ export { buildObservationArtifact, persistBrowserCapture, observe } from './appl
12
12
  export { HORIZONTAL_ORDER_RELATIONSHIPS, VERTICAL_ORDER_RELATIONSHIPS, AREA_OVERLAP_RELATIONSHIPS, RELATIVE_WIDTH_RELATIONSHIPS, GEOMETRIC_FIT_RELATIONSHIPS, VERTICAL_SEQUENCE_RELATIONSHIPS, PAGE_WIDTH_RELATIONSHIPS, PAIRWISE_RELATIONSHIP_KINDS, PAGE_LEVEL_RELATIONSHIP_KINDS, MAX_CONFIGURED_TARGETS_FOR_RELATIONSHIPS, MAX_PAIRWISE_RELATIONSHIP_PAIRS, PAIRWISE_RELATIONSHIP_FAMILY_COUNT, MAX_PAIRWISE_RELATIONSHIP_RECORDS, CLIPPING_STATES, CLIPPING_OVERFLOW_STYLES, isValidEvidenceReference, isValidPairwiseLayoutRelationship, isValidPageLevelLayoutRelationship, isValidUnresolvedRelationshipTarget, isValidLayoutRelationshipGraph, isValidTargetClippingEvidence, deriveTargetClipping, deriveLayoutRelationships, } from './domain/relationships.js';
13
13
  export { COMPARISON_ARTIFACT_KIND, COMPARISON_SCHEMA_VERSION, GEOMETRY_TOLERANCE_DEFAULT_PX, GEOMETRY_TOLERANCE_MIN_PX, GEOMETRY_TOLERANCE_MAX_PX, isValidGeometryTolerancePx, DEPENDENCY_PROPERTIES, DEPENDENCY_DIRECTIONS, EXPECTED_DEPENDENCY_SOURCES, isValidExpectedDependencyDeclaration, DEPENDENCY_EVIDENCE_OUTCOMES, isValidExpectedDependencyEvidence, isValidComparisonConfig, COMPARABILITY_STATES, COMPARABILITY_REASON_CODES, COMPARABILITY_REASON_SEVERITY, isValidComparabilityResult, TARGET_CONFIGURATION_CHANGE_KINDS, isValidTargetConfigurationChange, DIFFERENCE_KINDS, isValidComparisonDifference, isValidComparisonSourceObservationReference, isValidComparisonArtifact, } from './domain/comparison.js';
14
14
  export { buildComparisonRequestIdentity, buildComparisonIdentity } from './domain/comparisonIdentity.js';
15
+ export { CONTRACT_ARTIFACT_KIND, CONTRACT_SCHEMA_VERSION, AUTHORED_CHANGE_SCOPE_CATEGORIES, isAuthoredChangeScopeCategory, CHANGE_SCOPE_CLASSIFICATIONS, EXPECTED_DEPENDENT_MODES, isValidExpectedDependentMode, CONTRACT_TOLERANCE_ABSOLUTE_PX_MIN, CONTRACT_TOLERANCE_ABSOLUTE_PX_MAX, CONTRACT_TOLERANCE_PERCENT_MIN, CONTRACT_TOLERANCE_PERCENT_MAX, isValidContractTolerance, CONTRACT_PRIMITIVE_KINDS, isValidContractPrimitive, isValidBaselineClause, isValidPerChangeClause, isValidFrontendContractObservationReference, isValidPersistentBaselineContract, isValidPerChangeContract, CLAUSE_RESULT_STATUSES, isValidClauseEvaluationResult, OVERALL_VERDICTS, } from './domain/frontendContracts.js';
16
+ export { buildFrontendContractRequestIdentity, buildFrontendContractInstanceIdentity, buildClauseIdentity } from './domain/frontendContractIdentity.js';
17
+ export { evaluateFrontendContract } from './domain/frontendContractEvaluation.js';
18
+ export { buildFrontendContractEvaluationRequestIdentity } from './domain/frontendContractIdentity.js';
19
+ export { EVALUATION_ARTIFACT_KIND, EVALUATION_SCHEMA_VERSION, isValidFrontendContractEvaluationArtifact, buildFrontendContractEvaluationArtifact, } from './domain/frontendContractEvaluationArtifact.js';
20
+ export { FRONTEND_CONTRACT_MANIFEST_FILENAME, writePersistentBaselineContract, writePerChangeContract } from './artifacts/frontendContractArtifactWriter.js';
21
+ export { readPersistentBaselineContract, readPerChangeContract } from './artifacts/frontendContractArtifactReader.js';
22
+ export { readComparisonArtifact } from './artifacts/comparisonArtifactReader.js';
23
+ export { EVALUATION_MANIFEST_FILENAME, writeFrontendContractEvaluationArtifact } from './artifacts/frontendContractEvaluationArtifactWriter.js';
24
+ export { readFrontendContractEvaluationArtifact } from './artifacts/frontendContractEvaluationArtifactReader.js';
25
+ export { DEFAULT_EVALUATION_OUTPUT_LOCATION, evaluateAndPersist, evaluateAndPersistFromArtifactRoots } from './application/frontendContractEvaluationService.js';
26
+ export { approveAndPersistBaseline, persistPerChangeContract } from './application/frontendContractPersistenceService.js';
15
27
  export { compareObservations, evaluateComparability, evaluateExpectedDependencies, compareTargetConfiguration } from './domain/comparisonEngine.js';
16
28
  export { COMPARISON_MANIFEST_FILENAME, writeComparisonArtifact } from './artifacts/comparisonArtifactWriter.js';
17
29
  export { readObservationArtifact } from './artifacts/artifactReader.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG3E,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGlG,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAmC1D,OAAO,EACL,aAAa,EACb,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,eAAe,EACf,0BAA0B,GAC3B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAetF,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGzH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAG3E,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEvF,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,yCAAyC,CAAC;AAwBnH,OAAO,EACL,8BAA8B,EAC9B,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,EAC3B,+BAA+B,EAC/B,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,wCAAwC,EACxC,+BAA+B,EAC/B,kCAAkC,EAClC,iCAAiC,EACjC,eAAe,EACf,wBAAwB,EACxB,wBAAwB,EACxB,iCAAiC,EACjC,kCAAkC,EAClC,mCAAmC,EACnC,8BAA8B,EAC9B,6BAA6B,EAC7B,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AA0BnC,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,oCAAoC,EACpC,4BAA4B,EAC5B,iCAAiC,EACjC,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,6BAA6B,EAC7B,0BAA0B,EAC1B,iCAAiC,EACjC,gCAAgC,EAChC,gBAAgB,EAChB,2BAA2B,EAC3B,2CAA2C,EAC3C,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,8BAA8B,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAGzG,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAGpJ,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAGhH,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,kCAAkC,EAAE,iBAAiB,EAAE,kCAAkC,EAAE,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  ## Current scaffold architecture
4
4
 
5
5
  The current repository is one published TypeScript ESM package
6
- (`my-frontend-observer@0.4.0`):
6
+ (`my-frontend-observer@0.5.0`):
7
7
 
8
8
  - `src/cli.ts` is the real, thin `observe` command entry point (argument
9
9
  parsing/output only).
@@ -181,6 +181,103 @@ path never launches Chromium** - `src/cli.ts` imports nothing from
181
181
  reading indirectly, through the application-layer seam above), matching the
182
182
  same import-boundary discipline already enforced for `observe`.
183
183
 
184
+ ## Current v0.5 architecture (released/current architecture)
185
+
186
+ v0.5 adds one new downstream layer that consumes `ComparisonArtifact` values
187
+ (plus the source `ObservationArtifact` pair) rather than producing them - no
188
+ new browser lifecycle, target resolver, or comparison engine is added:
189
+
190
+ ```text
191
+ ObservationArtifact before + after
192
+ ↓
193
+ existing v0.4 comparison/relationship pipeline (unchanged)
194
+ ↓
195
+ ComparisonArtifact
196
+ ↓ PersistentBaselineContract
197
+ | +
198
+ `------------------------→ PerChangeContract
199
+ ↓
200
+ canonical contract evaluation
201
+ (src/domain/frontendContractEvaluation.ts#evaluateFrontendContract)
202
+ ↓
203
+ clause results + unexpected changes + overall PASS/FAIL
204
+ ```
205
+
206
+ `src/domain/frontendContracts.ts` froze the contract/change-scope type,
207
+ constant, and structural-validator vocabulary (Batch 1); `src/domain/
208
+ frontendContractIdentity.ts` froze deterministic contract/baseline/clause
209
+ identity in the same canonicalize+sha256(+opaque-nonce) style as `src/domain/
210
+ comparisonIdentity.ts`. `src/domain/frontendContractEvaluation.ts#evaluateFrontendContract`
211
+ (Batch 2) is the one canonical pure evaluation entry point: it validates its
212
+ five inputs (before/after `ObservationArtifact`, `ComparisonArtifact`,
213
+ `PersistentBaselineContract`, `PerChangeContract`) are structurally coherent
214
+ and mutually consistent, calculates the active baseline clause set after
215
+ explicit supersession, detects bounded structural conflicts, evaluates every
216
+ active clause via the frozen 15-primitive vocabulary against the existing
217
+ `ComparisonArtifact`/`ObservationArtifact` evidence (never re-deriving
218
+ clipping/relationship/scroll-owner facts), classifies unaccounted-for
219
+ `ComparisonArtifact.differences` entries as `unexpected`, and derives one
220
+ overall `PASS`/`FAIL` verdict. It performs no I/O, launches no browser, and
221
+ persists nothing - `src/domain/frontendContractEvaluation.ts` itself remains
222
+ untouched by the persistence layer below (Batch 3).
223
+
224
+ Batch 3 adds the persistence/application boundary around this frozen domain,
225
+ without redefining it:
226
+
227
+ ```text
228
+ ComparisonArtifact (read via new src/artifacts/comparisonArtifactReader.ts)
229
+ +
230
+ PersistentBaselineContract / PerChangeContract
231
+ (read/written via src/artifacts/frontendContractArtifactReader.ts / ...Writer.ts)
232
+ ↓
233
+ src/application/frontendContractEvaluationService.ts#evaluateAndPersist
234
+ ↓
235
+ evaluateFrontendContract() [called exactly once, unmodified]
236
+ ↓
237
+ src/domain/frontendContractEvaluationArtifact.ts
238
+ (minimal additive persisted envelope around the frozen result)
239
+ ↓
240
+ src/artifacts/frontendContractEvaluationArtifactWriter.ts
241
+ (atomic write, exactly once on a structurally constructible result)
242
+ ```
243
+
244
+ `evaluateAndPersistFromArtifactRoots` is the CLI-facing wrapper, reading
245
+ before/after observations through the existing `readObservationArtifact` (no
246
+ second observation reader), the comparison and both contract classes
247
+ through the new readers, then delegating to `evaluateAndPersist` exactly
248
+ once - mirroring `application/comparisonService.ts#compareAndPersistFromArtifactRoots`'s
249
+ own thin-wrapper shape.
250
+
251
+ Batch 4 exposes this through the same thin-CLI boundary already established
252
+ by `observe`/`compare`:
253
+
254
+ ```text
255
+ src/cli.ts (argument parsing, JSON-file-shape checks, help/output formatting,
256
+ exit-code selection only)
257
+ ↓
258
+ src/application/frontendContractPersistenceService.ts#approveAndPersistBaseline
259
+ src/application/frontendContractPersistenceService.ts#persistPerChangeContract
260
+ src/application/frontendContractEvaluationService.ts#evaluateAndPersistFromArtifactRoots
261
+ ↓
262
+ domain validators (isValidPersistentBaselineContract / isValidPerChangeContract)
263
+ + artifact readers/writers (Batch 3)
264
+ + evaluateFrontendContract() (Batch 2, unmodified)
265
+ ```
266
+
267
+ Three new top-level commands - `approve-baseline`, `save-change-contract`,
268
+ `evaluate-contract` - each parse only CLI-syntax concerns (duplicate/missing
269
+ flags, JSON-file readability/parseability/object-root shape) and delegate to
270
+ exactly one application-layer call; `src/cli.ts` imports no artifact writer/
271
+ reader module and no browser code, matching the existing `observe`/`compare`
272
+ import-boundary discipline exactly. `approveAndPersistBaseline` adds the one
273
+ new coherence check Batch 3 did not need: verifying a baseline contract's
274
+ frozen `sourceObservation` reference actually matches the supplied
275
+ observation artifact before persisting - explicit approval only, never
276
+ inferred from a `compare` or `evaluate-contract` result. `--enforce` on
277
+ `evaluate-contract` is applied only after evaluation and persistence have
278
+ already completed; it selects the process exit status for an already-final
279
+ `FAIL` result and is never part of any identity or persisted field.
280
+
184
281
  ## Planned v0.1 architecture constraints
185
282
 
186
283
  v0.1 planning must preserve these approved boundaries without treating module
package/docs/CI_CD.md CHANGED
@@ -96,3 +96,50 @@ observations. This preserves every pre-existing v0.1-v0.3 packed
96
96
  observation proof unchanged and adds the v0.4 proof additively, in the same
97
97
  script and the same candidate, per the established same-candidate
98
98
  architecture (no second `npm pack`, no per-platform rebuild).
99
+
100
+ ## v0.5 readiness coverage
101
+
102
+ The packed-readiness coverage gap identified during the v0.5 implementation-
103
+ completeness audit as `V0_5_READINESS_VALIDATION_GAP_EXISTS` - the packed
104
+ candidate smoke exercised `observe`/`compare` but not `approve-baseline`/
105
+ `save-change-contract`/`evaluate-contract` - has been **corrected locally**:
106
+ `scripts/ci/runPackedObservationSmoke.mjs` now also installs the same
107
+ candidate tarball, observes a deterministic navigation/workspace/rail
108
+ fixture through the installed `observe`, and drives the complete installed
109
+ `approve-baseline` → `save-change-contract` → `observe` (candidate) →
110
+ `compare` → `evaluate-contract` sequence, proving both a fully successful
111
+ contract change (overall `PASS`, `--enforce` still exits `0`) and the
112
+ milestone-signature failure (a locally successful requested/expected-
113
+ dependent change alongside a real protected right-rail regression and a
114
+ real preserved navigation-clipping regression, overall `FAIL`) - including
115
+ `--enforce` producing a nonzero exit for the identical `FAIL` evidence
116
+ (`evaluationRequestId` and `clauseResults` unchanged), full source
117
+ observation/comparison/contract-artifact immutability, no copied
118
+ screenshots, and no repository-root artifact leakage. All product behavior
119
+ under test is invoked through the installed tarball's own executable, never
120
+ imported from the source checkout. This addition is exercised in every
121
+ existing matrix lane (`windows-latest`, `ubuntu-latest`, `macos-latest`)
122
+ because all three already invoke this same script against the same
123
+ candidate tarball - no workflow YAML change was required.
124
+
125
+ This correction has since been proven cross-platform on the validation
126
+ branch `validation/v0.5-pre-release`, first tested at commit
127
+ `90255a9175503664f3e65d4114ee205176b7040a`: GitHub Actions run
128
+ [`31727856546`](https://github.com/dailephd/my-frontend-observer/actions/runs/31727856546)
129
+ passed completely - the candidate job (Linux, Node 24) and all three
130
+ `matrix-smoke` lanes (`windows-latest` Node v24.18.1, `ubuntu-latest` Node
131
+ v24.19.0, `macos-latest` Node v24.18.0) - using one shared candidate
132
+ tarball, `my-frontend-observer-0.4.0.tgz`, SHA-256
133
+ `9533a53e475614cd80a29dfa8b0f85e533e3ad736596579f559479e90e78941a`,
134
+ independently hash-verified by each of the three matrix lanes before any of
135
+ them ran the smoke (no lane built its own tarball). Every lane's
136
+ `smoke-summary.json` reported byte-identical v0.5 evidence: the installed
137
+ candidate's `approve-baseline`/`save-change-contract`/`evaluate-contract`
138
+ `--help` all present, a real successful contract change (overall `PASS`,
139
+ `--enforce` exits `0`), and the real milestone-signature failure (requested/
140
+ expected-dependent `pass`, protected/preserved `fail`, overall `FAIL`,
141
+ identical `evaluationRequestId`/`clauseResults` with `--enforce` exiting `1`
142
+ and without it exiting `0`), plus source-artifact immutability, no copied
143
+ screenshot, no path leakage, and no repository-root leakage - alongside
144
+ every pre-existing v0.1-v0.4 packed observe/compare/scroll assertion, still
145
+ passing unchanged on all three platforms.