@dailephd/my-frontend-observer 0.9.1 → 0.10.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 (104) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +17 -9
  3. package/dist/application/visualChangeAgentHandoffService.d.ts +28 -0
  4. package/dist/application/visualChangeAgentHandoffService.js +111 -0
  5. package/dist/application/visualChangeAgentHandoffService.js.map +1 -0
  6. package/dist/application/visualChangeProjectWorkflowService.d.ts +95 -0
  7. package/dist/application/visualChangeProjectWorkflowService.js +376 -0
  8. package/dist/application/visualChangeProjectWorkflowService.js.map +1 -0
  9. package/dist/application/visualChangeReviewService.d.ts +50 -0
  10. package/dist/application/visualChangeReviewService.js +69 -0
  11. package/dist/application/visualChangeReviewService.js.map +1 -0
  12. package/dist/application/visualChangeWorkflowPersistenceService.d.ts +26 -0
  13. package/dist/application/visualChangeWorkflowPersistenceService.js +15 -0
  14. package/dist/application/visualChangeWorkflowPersistenceService.js.map +1 -0
  15. package/dist/artifacts/visualChangeWorkflowArtifactReader.d.ts +9 -0
  16. package/dist/artifacts/visualChangeWorkflowArtifactReader.js +47 -0
  17. package/dist/artifacts/visualChangeWorkflowArtifactReader.js.map +1 -0
  18. package/dist/artifacts/visualChangeWorkflowArtifactWriter.d.ts +20 -0
  19. package/dist/artifacts/visualChangeWorkflowArtifactWriter.js +41 -0
  20. package/dist/artifacts/visualChangeWorkflowArtifactWriter.js.map +1 -0
  21. package/dist/cli.js +510 -508
  22. package/dist/cli.js.map +1 -1
  23. package/dist/domain/visualChangeAgentHandoff.d.ts +82 -0
  24. package/dist/domain/visualChangeAgentHandoff.js +80 -0
  25. package/dist/domain/visualChangeAgentHandoff.js.map +1 -0
  26. package/dist/domain/visualChangeAgentHandoffSerialization.d.ts +2 -0
  27. package/dist/domain/visualChangeAgentHandoffSerialization.js +11 -0
  28. package/dist/domain/visualChangeAgentHandoffSerialization.js.map +1 -0
  29. package/dist/domain/visualChangeCycle.d.ts +8 -0
  30. package/dist/domain/visualChangeCycle.js +7 -0
  31. package/dist/domain/visualChangeCycle.js.map +1 -0
  32. package/dist/domain/visualChangeWorkflow.d.ts +125 -0
  33. package/dist/domain/visualChangeWorkflow.js +109 -0
  34. package/dist/domain/visualChangeWorkflow.js.map +1 -0
  35. package/dist/domain/visualChangeWorkflowIdentity.d.ts +5 -0
  36. package/dist/domain/visualChangeWorkflowIdentity.js +24 -0
  37. package/dist/domain/visualChangeWorkflowIdentity.js.map +1 -0
  38. package/dist/index.d.ts +21 -1
  39. package/dist/index.js +12 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/projectWorkflow/projectPaths.d.ts +3 -0
  42. package/dist/projectWorkflow/projectPaths.js +7 -0
  43. package/dist/projectWorkflow/projectPaths.js.map +1 -1
  44. package/dist/viewer/assets/index-DglJ6f28.css +1 -0
  45. package/dist/viewer/assets/index-DsODREY5.js +9 -0
  46. package/dist/viewer/index.html +2 -2
  47. package/dist/viewer/sw.js +1 -1
  48. package/dist/viewerServer/evidence/classify.d.ts +3 -1
  49. package/dist/viewerServer/evidence/classify.js +10 -0
  50. package/dist/viewerServer/evidence/classify.js.map +1 -1
  51. package/dist/viewerServer/evidence/handles.js +1 -0
  52. package/dist/viewerServer/evidence/handles.js.map +1 -1
  53. package/dist/viewerServer/evidence/projection.d.ts +5 -0
  54. package/dist/viewerServer/evidence/projection.js +19 -0
  55. package/dist/viewerServer/evidence/projection.js.map +1 -1
  56. package/dist/viewerServer/evidence/visualChangeWorkflowView.d.ts +31 -0
  57. package/dist/viewerServer/evidence/visualChangeWorkflowView.js +36 -0
  58. package/dist/viewerServer/evidence/visualChangeWorkflowView.js.map +1 -0
  59. package/dist/viewerServer/httpServer.js +323 -1
  60. package/dist/viewerServer/httpServer.js.map +1 -1
  61. package/dist/viewerServer/referenceApproval.d.ts +22 -0
  62. package/dist/viewerServer/referenceApproval.js +42 -0
  63. package/dist/viewerServer/referenceApproval.js.map +1 -0
  64. package/dist/viewerServer/referenceVisualChangeAuthoring.d.ts +28 -0
  65. package/dist/viewerServer/referenceVisualChangeAuthoring.js +134 -0
  66. package/dist/viewerServer/referenceVisualChangeAuthoring.js.map +1 -0
  67. package/dist/viewerServer/runtimeVisualChangeAuthoring.d.ts +33 -0
  68. package/dist/viewerServer/runtimeVisualChangeAuthoring.js +81 -0
  69. package/dist/viewerServer/runtimeVisualChangeAuthoring.js.map +1 -0
  70. package/dist/viewerServer/visualChangeAuthoring.d.ts +46 -0
  71. package/dist/viewerServer/visualChangeAuthoring.js +63 -0
  72. package/dist/viewerServer/visualChangeAuthoring.js.map +1 -0
  73. package/dist/viewerServer/visualChangeHandoff.d.ts +23 -0
  74. package/dist/viewerServer/visualChangeHandoff.js +31 -0
  75. package/dist/viewerServer/visualChangeHandoff.js.map +1 -0
  76. package/dist/viewerServer/visualChangeReview.d.ts +30 -0
  77. package/dist/viewerServer/visualChangeReview.js +46 -0
  78. package/dist/viewerServer/visualChangeReview.js.map +1 -0
  79. package/docs/ARCHITECTURE.md +17 -5
  80. package/docs/CI_CD.md +12 -1
  81. package/docs/COMMANDS.md +18 -4
  82. package/docs/CONTRACTS.md +38 -4
  83. package/docs/CURRENT_STATE.md +23 -9
  84. package/docs/PROJECT_OVERVIEW.md +21 -16
  85. package/docs/QUICKSTART.md +7 -3
  86. package/docs/RELEASE.md +15 -12
  87. package/docs/ROADMAP.md +6 -5
  88. package/docs/SECURITY.md +25 -3
  89. package/docs/WORKFLOWS.md +28 -2
  90. package/docs/plans/v0.10-implementation-plan.md +1509 -0
  91. package/docs/reports/v0.10-batch1-visual-change-workflow-foundation.md +102 -0
  92. package/docs/reports/v0.10-batch2-project-composition-check-recording.md +103 -0
  93. package/docs/reports/v0.10-batch3-viewer-visual-change-workspace.md +93 -0
  94. package/docs/reports/v0.10-batch4-actual-frontend-entry.md +59 -0
  95. package/docs/reports/v0.10-batch5-reference-driven-entry.md +238 -0
  96. package/docs/reports/v0.10-batch6-coding-agent-handoff.md +85 -0
  97. package/docs/reports/v0.10-batch7-correction-review-acceptance.md +145 -0
  98. package/docs/reports/v0.10-batch8-integrated-acceptance.md +109 -0
  99. package/docs/reports/v0.10-implementation-completeness-documentation-reconciliation.md +344 -0
  100. package/docs/reports/v0.10-pre-release-readiness.md +120 -0
  101. package/docs/reports/v0.10-release-preparation.md +70 -0
  102. package/package.json +1 -1
  103. package/dist/viewer/assets/index-BN41MI7m.css +0 -1
  104. package/dist/viewer/assets/index-CkKXnlrI.js +0 -9
package/dist/cli.js CHANGED
@@ -25,526 +25,528 @@ const defaultIO = {
25
25
  process.stderr.write(text);
26
26
  },
27
27
  };
28
- const TOP_LEVEL_HELP = `my-frontend-observer - local-first browser runtime evidence producer
29
-
30
- Usage:
31
- my-frontend-observer <command> [options]
32
-
33
- Common workflow:
34
- init Initialize project-local Observer configuration and state.
35
- capture <alias> Capture one project-configured observation under a human alias.
36
- check [baseline] Capture current state and evaluate configured acceptance.
37
- view Start the viewer; discovers project evidence when --root is omitted.
38
-
39
- Advanced:
40
- observe Capture one bounded browser observation and persist
41
- it as a portable artifact.
42
- compare Compare two persisted observations and write a
43
- structured comparison artifact.
44
- approve-baseline Explicitly approve and persist one already-authored
45
- persistent baseline contract against the observation
46
- it claims to approve.
47
- save-change-contract Validate and persist one already-authored per-change
48
- contract so it can later be evaluated.
49
- evaluate-contract Evaluate a candidate change against an approved
50
- baseline, a per-change contract, and existing
51
- before/after/comparison evidence, and persist the
52
- result.
53
- import-reference Validate and persist one local external design-
54
- reference image as a new, unapproved
55
- external-reference artifact.
56
- approve-reference Explicitly approve one already-imported
57
- external-reference artifact, persisting a new
58
- approved artifact instance.
59
- evaluate-reference-fidelity Evaluate whether a candidate observation
60
- satisfies an external reference's selected design
61
- requirements, gated by reference adequacy,
62
- reference/candidate compatibility, and explicit
63
- region-to-target bindings. Prints a structured
64
- result; persists nothing.
65
-
66
- Options:
67
- --help Show this help.
68
- --version Print the package version.
69
-
70
- Run "my-frontend-observer <command> --help" for command-specific options.
28
+ const TOP_LEVEL_HELP = `my-frontend-observer - local-first browser runtime evidence producer
29
+
30
+ Usage:
31
+ my-frontend-observer <command> [options]
32
+
33
+ Common workflow:
34
+ init Initialize project-local Observer configuration and state.
35
+ capture <alias> Capture one project-configured observation under a human alias.
36
+ check [baseline] Capture current state and evaluate configured acceptance.
37
+ view Start the viewer; discovers project evidence when --root is omitted.
38
+
39
+ Advanced:
40
+ observe Capture one bounded browser observation and persist
41
+ it as a portable artifact.
42
+ compare Compare two persisted observations and write a
43
+ structured comparison artifact.
44
+ approve-baseline Explicitly approve and persist one already-authored
45
+ persistent baseline contract against the observation
46
+ it claims to approve.
47
+ save-change-contract Validate and persist one already-authored per-change
48
+ contract so it can later be evaluated.
49
+ evaluate-contract Evaluate a candidate change against an approved
50
+ baseline, a per-change contract, and existing
51
+ before/after/comparison evidence, and persist the
52
+ result.
53
+ import-reference Validate and persist one local external design-
54
+ reference image as a new, unapproved
55
+ external-reference artifact.
56
+ approve-reference Explicitly approve one already-imported
57
+ external-reference artifact, persisting a new
58
+ approved artifact instance.
59
+ evaluate-reference-fidelity Evaluate whether a candidate observation
60
+ satisfies an external reference's selected design
61
+ requirements, gated by reference adequacy,
62
+ reference/candidate compatibility, and explicit
63
+ region-to-target bindings. Prints a structured
64
+ result; persists nothing.
65
+
66
+ Options:
67
+ --help Show this help.
68
+ --version Print the package version.
69
+
70
+ Run "my-frontend-observer <command> --help" for command-specific options.
71
71
  `;
72
- const VIEW_HELP = `Usage:
73
- my-frontend-observer view [--root <evidence-root>] [--bindings-file <json-file>] [--context-file <json-file>] [options]
74
-
75
- Project or standalone input:
76
- --root <path> Local evidence-root directory the viewer session
77
- represents. When supplied, existing standalone behavior is
78
- used and no initialized project or alias catalog is required.
79
- Without --root, view requires an initialized project and
80
- discovers its managed evidence root and alias metadata.
81
-
82
- Options:
83
- --port <n> TCP port to bind, in [0, 65535]. Defaults to ${DEFAULT_VIEWER_PORT}.
84
- An explicit alternate port is a different web origin than
85
- the default - an installed PWA is not portable across
86
- origins. If the requested port is already in use, this
87
- command fails with an actionable error; it never silently
88
- falls back to a different port.
89
- --bindings-file <json-file> Local JSON file of the form
90
- { "bindings": [ { "referenceRegion": "...", "runtimeTarget": "..." } ] }
91
- (the exact same operational wrapper format as
92
- \`evaluate-reference-fidelity --bindings-file\`, sharing its
93
- parser). Explicit, session-only viewer input: read once at
94
- startup, never persisted, never written into any Observer
95
- artifact, and never exposed as a path to the browser. Its
96
- declarations become available for on-demand binding/
97
- fidelity evaluation once a reference and candidate are
98
- explicitly selected in the viewer. Reference-specific
99
- validity (region existence, etc.) is checked when a
100
- reference is actually selected, not at startup - only the
101
- file's own readability/JSON/wrapper shape is validated at
102
- startup. Omit to run with no binding declarations (the
103
- viewer remains fully usable; cross-selection stays
104
- disabled).
105
- --context-file <json-file> Local JSON file containing exactly one
106
- BoundedAgentContextArtifact value directly (no wrapper
107
- object) - e.g. { "artifactKind":
108
- "my-frontend-observer/bounded-agent-context",
109
- "schemaVersion": "1.0.0", ... }. Explicit, session-only
110
- viewer input: read once at startup, validated through the
111
- existing canonical isValidBoundedAgentContextArtifact,
112
- held only in server memory, never persisted, never written
113
- into any Observer artifact, and never exposed as a path to
114
- the browser. Bounded agent context remains programmatic-
115
- only as an Observer-produced contract - this command does
116
- not add a way to generate, save, or write one; the viewer
117
- never rebuilds it (no projectBoundedAgentContext call) and
118
- never derives runtime/static correlation (no
119
- deriveRuntimeStaticCorrelations/attachRuntimeStaticCorrelations
120
- call) - it only displays the exact context it was given.
121
- A recognized artifactKind with a schemaVersion other than
122
- the currently supported one starts the viewer showing an
123
- honest "unsupported version" context state rather than
124
- failing. An unreadable file, invalid JSON, wrong
125
- artifactKind, or a structurally invalid current-schema
126
- artifact fails startup clearly. Omit to run with no
127
- bounded context supplied (the viewer remains fully usable;
128
- the context panel says none was supplied). May be combined
129
- with --bindings-file.
130
- --no-open Do not attempt to open the system default browser after
131
- the server starts. Browser auto-open is a best-effort
132
- convenience only: its failure is never fatal and never
133
- affects server startup success.
134
- --help Show this help.
135
-
136
- Starts one Node HTTP server bound only to 127.0.0.1, serving the built
137
- React + TypeScript + Vite viewer application (and its PWA manifest/service
138
- worker) plus its local evidence API. With --root the session is read-only
139
- and never writes to the supplied evidence root. Without --root the
140
- project-aware session also enables local visual-annotation authoring: the
141
- viewer page may save immutable annotations, promote selected confirmed
142
- runtime intent into a change contract, and materialize selected confirmed
143
- reference intent into a new imported reference revision, all inside the
144
- project's managed evidence root. The server never edits target source,
145
- never approves baselines or references, never exposes the evidence root as
146
- a generic static directory, and never launches a browser observation. The
147
- process keeps running (serving the viewer) until interrupted. On success,
148
- prints the viewer URL and exits only when the server stops. On invalid
149
- syntax, a missing/non-directory --root, an invalid --port, or a port
150
- already in use, prints structured diagnostics to stderr and exits nonzero
151
- without starting a server.
72
+ const VIEW_HELP = `Usage:
73
+ my-frontend-observer view [--root <evidence-root>] [--bindings-file <json-file>] [--context-file <json-file>] [options]
74
+
75
+ Project or standalone input:
76
+ --root <path> Local evidence-root directory the viewer session
77
+ represents. When supplied, existing standalone behavior is
78
+ used and no initialized project or alias catalog is required.
79
+ Without --root, view requires an initialized project and
80
+ discovers its managed evidence root and alias metadata.
81
+
82
+ Options:
83
+ --port <n> TCP port to bind, in [0, 65535]. Defaults to ${DEFAULT_VIEWER_PORT}.
84
+ An explicit alternate port is a different web origin than
85
+ the default - an installed PWA is not portable across
86
+ origins. If the requested port is already in use, this
87
+ command fails with an actionable error; it never silently
88
+ falls back to a different port.
89
+ --bindings-file <json-file> Local JSON file of the form
90
+ { "bindings": [ { "referenceRegion": "...", "runtimeTarget": "..." } ] }
91
+ (the exact same operational wrapper format as
92
+ \`evaluate-reference-fidelity --bindings-file\`, sharing its
93
+ parser). Explicit, session-only viewer input: read once at
94
+ startup, never persisted, never written into any Observer
95
+ artifact, and never exposed as a path to the browser. Its
96
+ declarations become available for on-demand binding/
97
+ fidelity evaluation once a reference and candidate are
98
+ explicitly selected in the viewer. Reference-specific
99
+ validity (region existence, etc.) is checked when a
100
+ reference is actually selected, not at startup - only the
101
+ file's own readability/JSON/wrapper shape is validated at
102
+ startup. Omit to run with no binding declarations (the
103
+ viewer remains fully usable; cross-selection stays
104
+ disabled).
105
+ --context-file <json-file> Local JSON file containing exactly one
106
+ BoundedAgentContextArtifact value directly (no wrapper
107
+ object) - e.g. { "artifactKind":
108
+ "my-frontend-observer/bounded-agent-context",
109
+ "schemaVersion": "1.0.0", ... }. Explicit, session-only
110
+ viewer input: read once at startup, validated through the
111
+ existing canonical isValidBoundedAgentContextArtifact,
112
+ held only in server memory, never persisted, never written
113
+ into any Observer artifact, and never exposed as a path to
114
+ the browser. Bounded agent context remains programmatic-
115
+ only as an Observer-produced contract - this command does
116
+ not add a way to generate, save, or write one; the viewer
117
+ never rebuilds it (no projectBoundedAgentContext call) and
118
+ never derives runtime/static correlation (no
119
+ deriveRuntimeStaticCorrelations/attachRuntimeStaticCorrelations
120
+ call) - it only displays the exact context it was given.
121
+ A recognized artifactKind with a schemaVersion other than
122
+ the currently supported one starts the viewer showing an
123
+ honest "unsupported version" context state rather than
124
+ failing. An unreadable file, invalid JSON, wrong
125
+ artifactKind, or a structurally invalid current-schema
126
+ artifact fails startup clearly. Omit to run with no
127
+ bounded context supplied (the viewer remains fully usable;
128
+ the context panel says none was supplied). May be combined
129
+ with --bindings-file.
130
+ --no-open Do not attempt to open the system default browser after
131
+ the server starts. Browser auto-open is a best-effort
132
+ convenience only: its failure is never fatal and never
133
+ affects server startup success.
134
+ --help Show this help.
135
+
136
+ Starts one Node HTTP server bound only to 127.0.0.1, serving the built
137
+ React + TypeScript + Vite viewer application (and its PWA manifest/service
138
+ worker) plus its local evidence API. With --root the session is read-only
139
+ and never writes to the supplied evidence root. Without --root the
140
+ project-aware session also enables local visual-annotation and Visual Change
141
+ authoring: the viewer may create immutable annotations/contracts/references,
142
+ explicitly approve an imported reference, create/activate/check a frozen
143
+ workflow, prepare a non-persisted handoff, review attempts, and record already
144
+ completed governance results. All writes stay inside managed project evidence
145
+ and use canonical application owners. The server never edits target source,
146
+ never automatically approves a baseline/reference or restores acceptance,
147
+ never exposes the evidence root as a generic static directory, never launches a browser observation,
148
+ and never launches a coding agent or orchestrator. The
149
+ process keeps running (serving the viewer) until interrupted. On success,
150
+ prints the viewer URL and exits only when the server stops. On invalid
151
+ syntax, a missing/non-directory --root, an invalid --port, or a port
152
+ already in use, prints structured diagnostics to stderr and exits nonzero
153
+ without starting a server.
152
154
  `;
153
- const INIT_HELP = `Usage:
154
- my-frontend-observer init --url <loopback-url> [options]
155
-
156
- Options:
157
- --url <loopback-url> Required loopback frontend URL.
158
- --viewport <WIDTHxHEIGHT> Viewport size, e.g. 1280x720.
159
- --target <id=selector> Repeatable CSS-shorthand target.
160
- --targets-file <json-file> Structured target file; mutually exclusive with --target.
161
- --default-baseline <alias> Default baseline alias. Defaults to baseline.
162
- --replace Replace configuration only; preserve managed evidence/catalog.
163
- --help Show this help.
155
+ const INIT_HELP = `Usage:
156
+ my-frontend-observer init --url <loopback-url> [options]
157
+
158
+ Options:
159
+ --url <loopback-url> Required loopback frontend URL.
160
+ --viewport <WIDTHxHEIGHT> Viewport size, e.g. 1280x720.
161
+ --target <id=selector> Repeatable CSS-shorthand target.
162
+ --targets-file <json-file> Structured target file; mutually exclusive with --target.
163
+ --default-baseline <alias> Default baseline alias. Defaults to baseline.
164
+ --replace Replace configuration only; preserve managed evidence/catalog.
165
+ --help Show this help.
164
166
  `;
165
- const CAPTURE_HELP = `Usage:
166
- my-frontend-observer capture <alias> [--replace]
167
-
168
- Options:
169
- --replace Capture new canonical evidence, then update an existing alias.
170
- --help Show this help.
171
-
172
- URL, viewport, targets, and output are read from the discovered project configuration.
167
+ const CAPTURE_HELP = `Usage:
168
+ my-frontend-observer capture <alias> [--replace]
169
+
170
+ Options:
171
+ --replace Capture new canonical evidence, then update an existing alias.
172
+ --help Show this help.
173
+
174
+ URL, viewport, targets, and output are read from the discovered project configuration.
173
175
  `;
174
- const CHECK_HELP = `Usage:
175
- my-frontend-observer check [<baseline>] [--json]
176
-
177
- Uses defaultBaseline when the alias is omitted. Captures the reserved current
178
- candidate, persists a canonical comparison, and evaluates configured contract
179
- and approved-reference acceptance. Comparison alone returns REVIEW_REQUIRED.
180
-
181
- Options:
182
- --json Print exactly one bounded CheckWorkflowResult JSON document.
183
- --help Show this help.
184
-
185
- Exit codes: PASS 0; FAIL 1; REVIEW_REQUIRED 2; BLOCKED 3.
176
+ const CHECK_HELP = `Usage:
177
+ my-frontend-observer check [<baseline>] [--json]
178
+
179
+ Uses defaultBaseline when the alias is omitted. Captures the reserved current
180
+ candidate, persists a canonical comparison, and evaluates configured contract
181
+ and approved-reference acceptance. Comparison alone returns REVIEW_REQUIRED.
182
+
183
+ Options:
184
+ --json Print exactly one bounded CheckWorkflowResult JSON document.
185
+ --help Show this help.
186
+
187
+ Exit codes: PASS 0; FAIL 1; REVIEW_REQUIRED 2; BLOCKED 3.
186
188
  `;
187
- const OBSERVE_HELP = `Usage:
188
- my-frontend-observer observe --url <loopback-url> [options]
189
-
190
- Required:
191
- --url <url> Loopback target URL (http/https, localhost/127.x.x.x/::1 only).
192
-
193
- Options:
194
- --viewport <WIDTHxHEIGHT> Viewport size, e.g. 1280x720.
195
- --target <id=selector> An explicit CSS-shorthand observation target.
196
- Repeatable. Parsed on the first "=" only, so
197
- selectors containing "=" (e.g.
198
- button[data-state="active"]) are preserved
199
- intact. Cannot be combined with --targets-file.
200
- --targets-file <json-file> Loads structured semantic observation targets
201
- from a local JSON file: { "targets": [ { "name":
202
- "...", "locators": [ { "kind": "role"|"id"|
203
- "data-attribute"|"semantic-element"|"css"|"text",
204
- ... } ] } ] }. Locator order within a target is
205
- the fallback order. Relative paths resolve from
206
- the current working directory; the file path
207
- itself is never persisted into the artifact or
208
- included in the observation's request identity.
209
- Cannot be combined with --target.
210
- --scroll-scenario-file <json-file>
211
- Loads one bounded runtime scroll scenario from a
212
- local JSON file: { "action": { "kind":
213
- "window-scroll-by"|"target-scroll-by", ...,
214
- "deltaX": <int>, "deltaY": <int> } }.
215
- "target-scroll-by" additionally requires a
216
- "target" naming a configured stable target.
217
- Exactly zero or one scenario per observation.
218
- Relative paths resolve from the current working
219
- directory; the file path itself is never
220
- persisted into the artifact or included in the
221
- observation's request identity. May be combined
222
- with either --target or --targets-file.
223
- --state-file <json-file> Loads explicit, caller-declared frontend state
224
- identity from a local JSON file: { "theme":
225
- "...", "applicationState": "...",
226
- "authenticatedState": "authenticated"|
227
- "unauthenticated" } (each field independently
228
- optional; at least one required). Never inferred
229
- by the observer from screenshot pixels, CSS, DOM,
230
- or URLs - this is caller-declared metadata only,
231
- used solely for later comparability/compatibility
232
- evaluation. Relative paths resolve from the
233
- current working directory; the file path itself
234
- is never persisted into the artifact or included
235
- in the observation's request identity.
236
- --output <directory> Portable, relative output location for the
237
- observation artifact.
238
- --timeout <ms> Overall request timeout in milliseconds.
239
- --help Show this help.
240
-
241
- On success, prints a concise result and exits 0. On invalid syntax, invalid
242
- request, unsafe/failed navigation, or a failed artifact write, prints
243
- structured diagnostics to stderr and exits nonzero. No progress output is
244
- printed during a normal capture.
189
+ const OBSERVE_HELP = `Usage:
190
+ my-frontend-observer observe --url <loopback-url> [options]
191
+
192
+ Required:
193
+ --url <url> Loopback target URL (http/https, localhost/127.x.x.x/::1 only).
194
+
195
+ Options:
196
+ --viewport <WIDTHxHEIGHT> Viewport size, e.g. 1280x720.
197
+ --target <id=selector> An explicit CSS-shorthand observation target.
198
+ Repeatable. Parsed on the first "=" only, so
199
+ selectors containing "=" (e.g.
200
+ button[data-state="active"]) are preserved
201
+ intact. Cannot be combined with --targets-file.
202
+ --targets-file <json-file> Loads structured semantic observation targets
203
+ from a local JSON file: { "targets": [ { "name":
204
+ "...", "locators": [ { "kind": "role"|"id"|
205
+ "data-attribute"|"semantic-element"|"css"|"text",
206
+ ... } ] } ] }. Locator order within a target is
207
+ the fallback order. Relative paths resolve from
208
+ the current working directory; the file path
209
+ itself is never persisted into the artifact or
210
+ included in the observation's request identity.
211
+ Cannot be combined with --target.
212
+ --scroll-scenario-file <json-file>
213
+ Loads one bounded runtime scroll scenario from a
214
+ local JSON file: { "action": { "kind":
215
+ "window-scroll-by"|"target-scroll-by", ...,
216
+ "deltaX": <int>, "deltaY": <int> } }.
217
+ "target-scroll-by" additionally requires a
218
+ "target" naming a configured stable target.
219
+ Exactly zero or one scenario per observation.
220
+ Relative paths resolve from the current working
221
+ directory; the file path itself is never
222
+ persisted into the artifact or included in the
223
+ observation's request identity. May be combined
224
+ with either --target or --targets-file.
225
+ --state-file <json-file> Loads explicit, caller-declared frontend state
226
+ identity from a local JSON file: { "theme":
227
+ "...", "applicationState": "...",
228
+ "authenticatedState": "authenticated"|
229
+ "unauthenticated" } (each field independently
230
+ optional; at least one required). Never inferred
231
+ by the observer from screenshot pixels, CSS, DOM,
232
+ or URLs - this is caller-declared metadata only,
233
+ used solely for later comparability/compatibility
234
+ evaluation. Relative paths resolve from the
235
+ current working directory; the file path itself
236
+ is never persisted into the artifact or included
237
+ in the observation's request identity.
238
+ --output <directory> Portable, relative output location for the
239
+ observation artifact.
240
+ --timeout <ms> Overall request timeout in milliseconds.
241
+ --help Show this help.
242
+
243
+ On success, prints a concise result and exits 0. On invalid syntax, invalid
244
+ request, unsafe/failed navigation, or a failed artifact write, prints
245
+ structured diagnostics to stderr and exits nonzero. No progress output is
246
+ printed during a normal capture.
245
247
  `;
246
- const COMPARE_HELP = `Usage:
247
- my-frontend-observer compare --before <observation-artifact-root> --after <observation-artifact-root> --output <directory> [options]
248
-
249
- Required:
250
- --before <path> Root directory of the "before" persisted
251
- observation artifact (the directory containing
252
- its manifest.json).
253
- --after <path> Root directory of the "after" persisted
254
- observation artifact.
255
- --output <directory> Portable, relative output location for the
256
- comparison artifact.
257
-
258
- Options:
259
- --config-file <json-file> Loads a comparison configuration from a local
260
- JSON file: { "geometryTolerancePx": <0-10>,
261
- "expectedDependencies": [ { "cause": { "target":
262
- "...", "property": "x"|"y"|"width"|"height",
263
- "direction": "increase"|"decrease"|"change"|
264
- "unchanged" }, "effect": { ... same shape ... },
265
- "source": "explicit-config" } ] }. Relative
266
- paths resolve from the current working
267
- directory; the file path itself is never
268
- persisted into the artifact or included in the
269
- comparison request identity. Without
270
- --config-file, geometryTolerancePx defaults to
271
- 0.5 with no declared dependencies.
272
- --help Show this help.
273
-
274
- Comparison reads two already-persisted observation artifacts and derives
275
- evidence purely from their existing content - it never launches a browser
276
- and never re-observes either target. On success, prints a concise result
277
- and exits 0, including when the two observations are found to be
278
- "incomparable" (that is itself a successful comparison outcome, not a
279
- failure). On invalid syntax, an unreadable or structurally invalid source
280
- artifact, invalid configuration, or a failed artifact write, prints
281
- structured diagnostics to stderr and exits nonzero. No progress output is
282
- printed during a normal comparison.
248
+ const COMPARE_HELP = `Usage:
249
+ my-frontend-observer compare --before <observation-artifact-root> --after <observation-artifact-root> --output <directory> [options]
250
+
251
+ Required:
252
+ --before <path> Root directory of the "before" persisted
253
+ observation artifact (the directory containing
254
+ its manifest.json).
255
+ --after <path> Root directory of the "after" persisted
256
+ observation artifact.
257
+ --output <directory> Portable, relative output location for the
258
+ comparison artifact.
259
+
260
+ Options:
261
+ --config-file <json-file> Loads a comparison configuration from a local
262
+ JSON file: { "geometryTolerancePx": <0-10>,
263
+ "expectedDependencies": [ { "cause": { "target":
264
+ "...", "property": "x"|"y"|"width"|"height",
265
+ "direction": "increase"|"decrease"|"change"|
266
+ "unchanged" }, "effect": { ... same shape ... },
267
+ "source": "explicit-config" } ] }. Relative
268
+ paths resolve from the current working
269
+ directory; the file path itself is never
270
+ persisted into the artifact or included in the
271
+ comparison request identity. Without
272
+ --config-file, geometryTolerancePx defaults to
273
+ 0.5 with no declared dependencies.
274
+ --help Show this help.
275
+
276
+ Comparison reads two already-persisted observation artifacts and derives
277
+ evidence purely from their existing content - it never launches a browser
278
+ and never re-observes either target. On success, prints a concise result
279
+ and exits 0, including when the two observations are found to be
280
+ "incomparable" (that is itself a successful comparison outcome, not a
281
+ failure). On invalid syntax, an unreadable or structurally invalid source
282
+ artifact, invalid configuration, or a failed artifact write, prints
283
+ structured diagnostics to stderr and exits nonzero. No progress output is
284
+ printed during a normal comparison.
283
285
  `;
284
- const APPROVE_BASELINE_HELP = `Usage:
285
- my-frontend-observer approve-baseline --observation <observation-artifact-root> --contract-file <json-file> --output <directory>
286
-
287
- Required:
288
- --observation <path> Root directory of the persisted observation
289
- artifact (the directory containing its
290
- manifest.json) that this baseline claims to
291
- approve.
292
- --contract-file <json-file> Local JSON file containing one already-authored
293
- persistent baseline contract (the raw contract
294
- value, no wrapper field). Relative paths resolve
295
- from the current working directory; the file
296
- path itself is never persisted or included in
297
- any identity.
298
- --output <directory> Portable, relative output location for the
299
- baseline artifact.
300
-
301
- Options:
302
- --help Show this help.
303
-
304
- This command is the only explicit baseline-approval act in the observer -
305
- approval is never inferred from a successful comparison or evaluation. The
306
- supplied contract's source-observation reference must match the supplied
307
- observation artifact's stable identity; a mismatched or unrelated observation
308
- is rejected. Any \`supersedesBaselineId\` already authored in the contract is
309
- preserved exactly - this command never discovers, infers, or deletes a prior
310
- baseline. Remains local and non-mutating: it never launches a browser and
311
- never modifies the source observation or any existing baseline artifact. On
312
- success, prints a concise result and exits 0. On invalid syntax, an
313
- unreadable/malformed contract file, a non-baseline contract, a
314
- structurally invalid contract, a source-observation mismatch, an existing
315
- artifact collision, or a persistence failure, prints structured diagnostics
316
- to stderr and exits nonzero.
286
+ const APPROVE_BASELINE_HELP = `Usage:
287
+ my-frontend-observer approve-baseline --observation <observation-artifact-root> --contract-file <json-file> --output <directory>
288
+
289
+ Required:
290
+ --observation <path> Root directory of the persisted observation
291
+ artifact (the directory containing its
292
+ manifest.json) that this baseline claims to
293
+ approve.
294
+ --contract-file <json-file> Local JSON file containing one already-authored
295
+ persistent baseline contract (the raw contract
296
+ value, no wrapper field). Relative paths resolve
297
+ from the current working directory; the file
298
+ path itself is never persisted or included in
299
+ any identity.
300
+ --output <directory> Portable, relative output location for the
301
+ baseline artifact.
302
+
303
+ Options:
304
+ --help Show this help.
305
+
306
+ This command is the only explicit baseline-approval act in the observer -
307
+ approval is never inferred from a successful comparison or evaluation. The
308
+ supplied contract's source-observation reference must match the supplied
309
+ observation artifact's stable identity; a mismatched or unrelated observation
310
+ is rejected. Any \`supersedesBaselineId\` already authored in the contract is
311
+ preserved exactly - this command never discovers, infers, or deletes a prior
312
+ baseline. Remains local and non-mutating: it never launches a browser and
313
+ never modifies the source observation or any existing baseline artifact. On
314
+ success, prints a concise result and exits 0. On invalid syntax, an
315
+ unreadable/malformed contract file, a non-baseline contract, a
316
+ structurally invalid contract, a source-observation mismatch, an existing
317
+ artifact collision, or a persistence failure, prints structured diagnostics
318
+ to stderr and exits nonzero.
317
319
  `;
318
- const SAVE_CHANGE_CONTRACT_HELP = `Usage:
319
- my-frontend-observer save-change-contract --contract-file <json-file> --output <directory>
320
-
321
- Required:
322
- --contract-file <json-file> Local JSON file containing one already-authored
323
- per-change contract (the raw contract value, no
324
- wrapper field). Relative paths resolve from the
325
- current working directory; the file path itself
326
- is never persisted or included in any identity.
327
- --output <directory> Portable, relative output location for the
328
- change-contract artifact.
329
-
330
- Options:
331
- --help Show this help.
332
-
333
- This command validates and persists a per-change contract only - it does not
334
- approve anything. Any \`supersedesBaselineClauseIds\` already authored on a
335
- clause is preserved exactly; resolving those references against a particular
336
- baseline remains \`evaluate-contract\`'s responsibility, not this command's.
337
- Remains local and non-mutating. On success, prints a concise result and
338
- exits 0. On invalid syntax, an unreadable/malformed contract file, a
339
- non-change contract (e.g. a persistent baseline contract), a structurally
340
- invalid contract (including an authored \`unexpected\` category, which is
341
- never a valid authored scope), an existing artifact collision, or a
342
- persistence failure, prints structured diagnostics to stderr and exits
343
- nonzero.
320
+ const SAVE_CHANGE_CONTRACT_HELP = `Usage:
321
+ my-frontend-observer save-change-contract --contract-file <json-file> --output <directory>
322
+
323
+ Required:
324
+ --contract-file <json-file> Local JSON file containing one already-authored
325
+ per-change contract (the raw contract value, no
326
+ wrapper field). Relative paths resolve from the
327
+ current working directory; the file path itself
328
+ is never persisted or included in any identity.
329
+ --output <directory> Portable, relative output location for the
330
+ change-contract artifact.
331
+
332
+ Options:
333
+ --help Show this help.
334
+
335
+ This command validates and persists a per-change contract only - it does not
336
+ approve anything. Any \`supersedesBaselineClauseIds\` already authored on a
337
+ clause is preserved exactly; resolving those references against a particular
338
+ baseline remains \`evaluate-contract\`'s responsibility, not this command's.
339
+ Remains local and non-mutating. On success, prints a concise result and
340
+ exits 0. On invalid syntax, an unreadable/malformed contract file, a
341
+ non-change contract (e.g. a persistent baseline contract), a structurally
342
+ invalid contract (including an authored \`unexpected\` category, which is
343
+ never a valid authored scope), an existing artifact collision, or a
344
+ persistence failure, prints structured diagnostics to stderr and exits
345
+ nonzero.
344
346
  `;
345
- const EVALUATE_CONTRACT_HELP = `Usage:
346
- my-frontend-observer evaluate-contract --before <observation-artifact-root> --after <observation-artifact-root> --comparison <comparison-artifact-root> --baseline <baseline-contract-artifact-root> --change <per-change-contract-artifact-root> --output <directory> [--enforce]
347
-
348
- Required:
349
- --before <path> Root directory of the "before" persisted observation
350
- artifact.
351
- --after <path> Root directory of the "after" persisted observation
352
- artifact.
353
- --comparison <path> Root directory of the already-persisted comparison
354
- artifact for that before/after pair.
355
- --baseline <path> Root directory of the already-approved persistent
356
- baseline contract artifact.
357
- --change <path> Root directory of the already-persisted per-change
358
- contract artifact.
359
- --output <directory> Portable, relative output location for the
360
- evaluation artifact.
361
-
362
- Options:
363
- --enforce Make a FAIL verdict produce a nonzero process exit status. A
364
- FAIL evaluation is always persisted and printed identically
365
- with or without this flag - it changes only the process exit
366
- code, never evaluation identity, contents, or persistence.
367
- --help Show this help.
368
-
369
- This command never launches a browser, never re-resolves targets, and never
370
- recomputes comparison or relationship evidence - it reads the already-
371
- persisted before/after observations and comparison exactly as given and
372
- evaluates the supplied baseline/change contracts against them exactly once.
373
- A FAIL verdict (a found regression or unsatisfied contract clause) is a
374
- successful, persisted evaluation outcome, not an execution error; without
375
- --enforce it exits 0 like PASS. On success (evaluation constructed and
376
- persisted, verdict PASS, or verdict FAIL without --enforce), prints a
377
- concise result and exits 0. With --enforce and verdict FAIL, prints the same
378
- result and exits nonzero. On invalid syntax, an unreadable/malformed/
379
- incoherent source artifact, or a persistence failure (evaluation could not
380
- even be constructed), prints structured diagnostics to stderr, persists
381
- nothing, and exits nonzero.
347
+ const EVALUATE_CONTRACT_HELP = `Usage:
348
+ my-frontend-observer evaluate-contract --before <observation-artifact-root> --after <observation-artifact-root> --comparison <comparison-artifact-root> --baseline <baseline-contract-artifact-root> --change <per-change-contract-artifact-root> --output <directory> [--enforce]
349
+
350
+ Required:
351
+ --before <path> Root directory of the "before" persisted observation
352
+ artifact.
353
+ --after <path> Root directory of the "after" persisted observation
354
+ artifact.
355
+ --comparison <path> Root directory of the already-persisted comparison
356
+ artifact for that before/after pair.
357
+ --baseline <path> Root directory of the already-approved persistent
358
+ baseline contract artifact.
359
+ --change <path> Root directory of the already-persisted per-change
360
+ contract artifact.
361
+ --output <directory> Portable, relative output location for the
362
+ evaluation artifact.
363
+
364
+ Options:
365
+ --enforce Make a FAIL verdict produce a nonzero process exit status. A
366
+ FAIL evaluation is always persisted and printed identically
367
+ with or without this flag - it changes only the process exit
368
+ code, never evaluation identity, contents, or persistence.
369
+ --help Show this help.
370
+
371
+ This command never launches a browser, never re-resolves targets, and never
372
+ recomputes comparison or relationship evidence - it reads the already-
373
+ persisted before/after observations and comparison exactly as given and
374
+ evaluates the supplied baseline/change contracts against them exactly once.
375
+ A FAIL verdict (a found regression or unsatisfied contract clause) is a
376
+ successful, persisted evaluation outcome, not an execution error; without
377
+ --enforce it exits 0 like PASS. On success (evaluation constructed and
378
+ persisted, verdict PASS, or verdict FAIL without --enforce), prints a
379
+ concise result and exits 0. With --enforce and verdict FAIL, prints the same
380
+ result and exits nonzero. On invalid syntax, an unreadable/malformed/
381
+ incoherent source artifact, or a persistence failure (evaluation could not
382
+ even be constructed), prints structured diagnostics to stderr, persists
383
+ nothing, and exits nonzero.
382
384
  `;
383
- const IMPORT_REFERENCE_HELP = `Usage:
384
- my-frontend-observer import-reference <image-file> --output <directory> [options]
385
-
386
- Required:
387
- <image-file> Local path to a PNG, JPEG, or WebP external design-
388
- reference image.
389
- --output <directory> Portable, relative output location for the
390
- external-reference artifact.
391
-
392
- Options:
393
- --label <text> Optional human-readable label, stored as pure
394
- provenance - never part of the reference's logical
395
- identity.
396
- --supersedes <path> Root directory of a prior external-reference
397
- artifact (imported or approved) that this import
398
- explicitly supersedes. The prior artifact is never
399
- modified.
400
- --regions-file <json-file> Local JSON file of the form { "regions": [...] }
401
- declaring explicit, meaningful reference-image
402
- regions (id + a {x, y, width, height} rectangle in
403
- reference-image pixels, origin at the image's
404
- top-left corner). Optional - a reference imported
405
- without this flag behaves exactly as in v0.7 Prompt
406
- 1. Region content participates in the reference's
407
- logical identity; the file path itself never does.
408
- --requirements-file <json-file> Local JSON file of the form
409
- { "requirements": [...] } declaring explicit,
410
- user-selected design requirements over the regions
411
- above - what actually matters for later candidate
412
- evaluation, never inferred merely because a region
413
- property/relationship exists. Each requirement has
414
- a "category" (requested | expected-dependent |
415
- protected | preserved - "unexpected" is never
416
- authorable), a "subject" (a region property, a
417
- region-to-region relationship, or a derived
418
- two-region measurement), and - for property/
419
- measurement subjects - a "tolerance" (exact |
420
- absolute-reference-px | percent; relationship
421
- subjects must omit tolerance). Requires --regions-
422
- file (or an already-present region set) supplying
423
- every region a requirement refers to. Optional -
424
- a reference imported without this flag behaves
425
- exactly as in v0.7 Prompt 1/2. Requirement content
426
- participates in the reference's logical identity.
427
- --applicability-file <json-file> Local JSON file declaring the runtime
428
- frontend state this reference is intended to
429
- represent: { "viewport": { "width", "height" },
430
- "theme": "...", "applicationState": "...",
431
- "authenticatedState": "authenticated"|
432
- "unauthenticated" } (each field independently
433
- optional; at least one required). "viewport" here
434
- is the CSS-pixel runtime viewport the design
435
- represents - distinct from the reference image's
436
- own pixel dimensions, which are never assumed
437
- equal. Never inferred from the image - caller-
438
- declared metadata only, used for later reference/
439
- candidate compatibility evaluation (see
440
- docs/CONTRACTS.md "v0.7 Prompt 4"). Optional - a
441
- reference imported without this flag behaves
442
- exactly as in v0.7 Prompt 1/2/3. Applicability
443
- content participates in the reference's logical
444
- identity.
445
- --help Show this help.
446
-
447
- Detects the image format from its header bytes only (never from the file
448
- extension), reads its pixel dimensions from the same bounded header bytes
449
- (never decoding pixel data), and persists a new external-reference artifact
450
- in the "imported" lifecycle state - importing never approves it. On success,
451
- prints a concise result (including the accepted region/requirement counts,
452
- the resulting reference-side requirement adequacy: adequate, partial, or
453
- inadequate, and whether applicability was declared) and exits 0. On an
454
- unreadable file, an unsupported or undetectable format, invalid/out-of-bound
455
- dimensions, an over-limit file size, an unresolvable --supersedes target, an
456
- invalid region (missing/duplicate/malformed id, non-finite/negative/zero
457
- geometry, a region extending outside the image, or more than the bounded
458
- maximum region count), an invalid requirement (unsupported category/
459
- property/measurement/relationship, a tolerance that is missing/inapplicable/
460
- out of bounds, a reference to an unknown region id, a duplicate requirement
461
- subject, or more than the bounded maximum requirement count), or invalid
462
- applicability (an out-of-bound viewport, an invalid state label, an
463
- unsupported authenticatedState value, or an empty applicability object),
464
- prints structured diagnostics to stderr and exits nonzero.
385
+ const IMPORT_REFERENCE_HELP = `Usage:
386
+ my-frontend-observer import-reference <image-file> --output <directory> [options]
387
+
388
+ Required:
389
+ <image-file> Local path to a PNG, JPEG, or WebP external design-
390
+ reference image.
391
+ --output <directory> Portable, relative output location for the
392
+ external-reference artifact.
393
+
394
+ Options:
395
+ --label <text> Optional human-readable label, stored as pure
396
+ provenance - never part of the reference's logical
397
+ identity.
398
+ --supersedes <path> Root directory of a prior external-reference
399
+ artifact (imported or approved) that this import
400
+ explicitly supersedes. The prior artifact is never
401
+ modified.
402
+ --regions-file <json-file> Local JSON file of the form { "regions": [...] }
403
+ declaring explicit, meaningful reference-image
404
+ regions (id + a {x, y, width, height} rectangle in
405
+ reference-image pixels, origin at the image's
406
+ top-left corner). Optional - a reference imported
407
+ without this flag behaves exactly as in v0.7 Prompt
408
+ 1. Region content participates in the reference's
409
+ logical identity; the file path itself never does.
410
+ --requirements-file <json-file> Local JSON file of the form
411
+ { "requirements": [...] } declaring explicit,
412
+ user-selected design requirements over the regions
413
+ above - what actually matters for later candidate
414
+ evaluation, never inferred merely because a region
415
+ property/relationship exists. Each requirement has
416
+ a "category" (requested | expected-dependent |
417
+ protected | preserved - "unexpected" is never
418
+ authorable), a "subject" (a region property, a
419
+ region-to-region relationship, or a derived
420
+ two-region measurement), and - for property/
421
+ measurement subjects - a "tolerance" (exact |
422
+ absolute-reference-px | percent; relationship
423
+ subjects must omit tolerance). Requires --regions-
424
+ file (or an already-present region set) supplying
425
+ every region a requirement refers to. Optional -
426
+ a reference imported without this flag behaves
427
+ exactly as in v0.7 Prompt 1/2. Requirement content
428
+ participates in the reference's logical identity.
429
+ --applicability-file <json-file> Local JSON file declaring the runtime
430
+ frontend state this reference is intended to
431
+ represent: { "viewport": { "width", "height" },
432
+ "theme": "...", "applicationState": "...",
433
+ "authenticatedState": "authenticated"|
434
+ "unauthenticated" } (each field independently
435
+ optional; at least one required). "viewport" here
436
+ is the CSS-pixel runtime viewport the design
437
+ represents - distinct from the reference image's
438
+ own pixel dimensions, which are never assumed
439
+ equal. Never inferred from the image - caller-
440
+ declared metadata only, used for later reference/
441
+ candidate compatibility evaluation (see
442
+ docs/CONTRACTS.md "v0.7 Prompt 4"). Optional - a
443
+ reference imported without this flag behaves
444
+ exactly as in v0.7 Prompt 1/2/3. Applicability
445
+ content participates in the reference's logical
446
+ identity.
447
+ --help Show this help.
448
+
449
+ Detects the image format from its header bytes only (never from the file
450
+ extension), reads its pixel dimensions from the same bounded header bytes
451
+ (never decoding pixel data), and persists a new external-reference artifact
452
+ in the "imported" lifecycle state - importing never approves it. On success,
453
+ prints a concise result (including the accepted region/requirement counts,
454
+ the resulting reference-side requirement adequacy: adequate, partial, or
455
+ inadequate, and whether applicability was declared) and exits 0. On an
456
+ unreadable file, an unsupported or undetectable format, invalid/out-of-bound
457
+ dimensions, an over-limit file size, an unresolvable --supersedes target, an
458
+ invalid region (missing/duplicate/malformed id, non-finite/negative/zero
459
+ geometry, a region extending outside the image, or more than the bounded
460
+ maximum region count), an invalid requirement (unsupported category/
461
+ property/measurement/relationship, a tolerance that is missing/inapplicable/
462
+ out of bounds, a reference to an unknown region id, a duplicate requirement
463
+ subject, or more than the bounded maximum requirement count), or invalid
464
+ applicability (an out-of-bound viewport, an invalid state label, an
465
+ unsupported authenticatedState value, or an empty applicability object),
466
+ prints structured diagnostics to stderr and exits nonzero.
465
467
  `;
466
- const APPROVE_REFERENCE_HELP = `Usage:
467
- my-frontend-observer approve-reference --reference <external-reference-artifact-root> --output <directory> [options]
468
-
469
- Required:
470
- --reference <path> Root directory of the already-imported
471
- external-reference artifact (the directory
472
- containing its manifest.json) to approve.
473
- --output <directory> Portable, relative output location for the newly
474
- persisted approved artifact.
475
-
476
- Options:
477
- --supersedes <path> Root directory of a prior external-reference
478
- artifact (imported or approved) that this approval
479
- explicitly supersedes. The prior artifact is never
480
- modified.
481
- --help Show this help.
482
-
483
- This is the only explicit reference-approval act in the observer - approval
484
- is never inferred from a successful import or from any later fidelity
485
- evaluation. Approving persists a brand-new artifact instance (a fresh
486
- referenceId sharing the imported artifact's referenceRequestId) that carries
487
- a reference back to the imported artifact's image rather than a second copy
488
- of its bytes; the imported artifact's own manifest is never modified. Any
489
- regions, requirements, and applicability already declared on the imported
490
- artifact are carried forward unchanged (not re-validated against new input,
491
- not re-derived) - approval never adds, removes, or edits regions,
492
- requirements, or applicability. Only a reference currently in the "imported"
493
- lifecycle state can be approved. On success, prints a concise result
494
- (including the carried-forward region/requirement counts, reference-side
495
- requirement adequacy, and whether applicability was declared) and exits 0.
496
- On an unreadable/malformed --reference target, a target that is not in the
497
- "imported" state, an unresolvable --supersedes target, or a persistence
498
- failure, prints structured diagnostics to stderr and exits nonzero.
468
+ const APPROVE_REFERENCE_HELP = `Usage:
469
+ my-frontend-observer approve-reference --reference <external-reference-artifact-root> --output <directory> [options]
470
+
471
+ Required:
472
+ --reference <path> Root directory of the already-imported
473
+ external-reference artifact (the directory
474
+ containing its manifest.json) to approve.
475
+ --output <directory> Portable, relative output location for the newly
476
+ persisted approved artifact.
477
+
478
+ Options:
479
+ --supersedes <path> Root directory of a prior external-reference
480
+ artifact (imported or approved) that this approval
481
+ explicitly supersedes. The prior artifact is never
482
+ modified.
483
+ --help Show this help.
484
+
485
+ This is the only explicit reference-approval act in the observer - approval
486
+ is never inferred from a successful import or from any later fidelity
487
+ evaluation. Approving persists a brand-new artifact instance (a fresh
488
+ referenceId sharing the imported artifact's referenceRequestId) that carries
489
+ a reference back to the imported artifact's image rather than a second copy
490
+ of its bytes; the imported artifact's own manifest is never modified. Any
491
+ regions, requirements, and applicability already declared on the imported
492
+ artifact are carried forward unchanged (not re-validated against new input,
493
+ not re-derived) - approval never adds, removes, or edits regions,
494
+ requirements, or applicability. Only a reference currently in the "imported"
495
+ lifecycle state can be approved. On success, prints a concise result
496
+ (including the carried-forward region/requirement counts, reference-side
497
+ requirement adequacy, and whether applicability was declared) and exits 0.
498
+ On an unreadable/malformed --reference target, a target that is not in the
499
+ "imported" state, an unresolvable --supersedes target, or a persistence
500
+ failure, prints structured diagnostics to stderr and exits nonzero.
499
501
  `;
500
- const EVALUATE_REFERENCE_FIDELITY_HELP = `Usage:
501
- my-frontend-observer evaluate-reference-fidelity --reference <external-reference-artifact-root> --candidate <observation-artifact-root> [options]
502
-
503
- Required:
504
- --reference <path> Root directory of an already-imported or already-
505
- approved external-reference artifact (the directory
506
- containing its manifest.json).
507
- --candidate <path> Root directory of the already-persisted candidate
508
- observation artifact to evaluate against it.
509
-
510
- Options:
511
- --bindings-file <json-file> Local JSON file of the form
512
- { "bindings": [ { "referenceRegion": "...",
513
- "runtimeTarget": "..." } ] } declaring which stable
514
- observer runtime target (a configured target name -
515
- see "observe" --target/--targets-file) explicitly
516
- corresponds to each reference region a selected
517
- requirement depends on. Never inferred from
518
- geometry, matching names, or source code - a
519
- binding exists only because this file declares it.
520
- Optional - omitting it (or supplying an empty
521
- "bindings" array) evaluates with no bindings at
522
- all, so every requirement whose subject depends on
523
- a reference region becomes "unavailable".
524
- --enforce Make a FAIL fidelity result produce a nonzero process exit
525
- status. A FAIL result is always printed identically with or
526
- without this flag - it changes only the process exit code,
527
- never the evaluation's content. Has no effect on a
528
- "not-evaluated" result (a reference-adequacy or compatibility
529
- blocker is never treated as a design mismatch).
530
- --help Show this help.
531
-
532
- This command never launches a browser, never re-resolves targets, and
533
- never recomputes reference regions/requirements/adequacy, compatibility, or
534
- bindings - it reads the already-persisted reference and candidate exactly
535
- as given, evaluates the supplied binding declarations, and evaluates every
536
- one of the reference's selected requirements exactly once. It persists
537
- nothing: the result exists only for this invocation. On success, prints a
538
- concise result (reference-side adequacy, compatibility state, the overall
539
- fidelity state - "not-evaluated"/"pass"/"fail" - and a pass/fail/unavailable
540
- requirement breakdown) and exits 0, unless --enforce is given and the
541
- fidelity state is "fail", in which case it exits nonzero. A "not-evaluated"
542
- result (reference adequacy inadequate, or reference/candidate
543
- incompatible) is a successful, structured evaluation outcome, never an
544
- execution error - it always exits 0. On invalid syntax, an unreadable/
545
- malformed --reference or --candidate target, a malformed --bindings-file,
546
- or an invalid/out-of-bound binding declaration, prints structured
547
- diagnostics to stderr and exits nonzero.
502
+ const EVALUATE_REFERENCE_FIDELITY_HELP = `Usage:
503
+ my-frontend-observer evaluate-reference-fidelity --reference <external-reference-artifact-root> --candidate <observation-artifact-root> [options]
504
+
505
+ Required:
506
+ --reference <path> Root directory of an already-imported or already-
507
+ approved external-reference artifact (the directory
508
+ containing its manifest.json).
509
+ --candidate <path> Root directory of the already-persisted candidate
510
+ observation artifact to evaluate against it.
511
+
512
+ Options:
513
+ --bindings-file <json-file> Local JSON file of the form
514
+ { "bindings": [ { "referenceRegion": "...",
515
+ "runtimeTarget": "..." } ] } declaring which stable
516
+ observer runtime target (a configured target name -
517
+ see "observe" --target/--targets-file) explicitly
518
+ corresponds to each reference region a selected
519
+ requirement depends on. Never inferred from
520
+ geometry, matching names, or source code - a
521
+ binding exists only because this file declares it.
522
+ Optional - omitting it (or supplying an empty
523
+ "bindings" array) evaluates with no bindings at
524
+ all, so every requirement whose subject depends on
525
+ a reference region becomes "unavailable".
526
+ --enforce Make a FAIL fidelity result produce a nonzero process exit
527
+ status. A FAIL result is always printed identically with or
528
+ without this flag - it changes only the process exit code,
529
+ never the evaluation's content. Has no effect on a
530
+ "not-evaluated" result (a reference-adequacy or compatibility
531
+ blocker is never treated as a design mismatch).
532
+ --help Show this help.
533
+
534
+ This command never launches a browser, never re-resolves targets, and
535
+ never recomputes reference regions/requirements/adequacy, compatibility, or
536
+ bindings - it reads the already-persisted reference and candidate exactly
537
+ as given, evaluates the supplied binding declarations, and evaluates every
538
+ one of the reference's selected requirements exactly once. It persists
539
+ nothing: the result exists only for this invocation. On success, prints a
540
+ concise result (reference-side adequacy, compatibility state, the overall
541
+ fidelity state - "not-evaluated"/"pass"/"fail" - and a pass/fail/unavailable
542
+ requirement breakdown) and exits 0, unless --enforce is given and the
543
+ fidelity state is "fail", in which case it exits nonzero. A "not-evaluated"
544
+ result (reference adequacy inadequate, or reference/candidate
545
+ incompatible) is a successful, structured evaluation outcome, never an
546
+ execution error - it always exits 0. On invalid syntax, an unreadable/
547
+ malformed --reference or --candidate target, a malformed --bindings-file,
548
+ or an invalid/out-of-bound binding declaration, prints structured
549
+ diagnostics to stderr and exits nonzero.
548
550
  `;
549
551
  function parseViewport(raw) {
550
552
  const match = /^(\d+)x(\d+)$/.exec(raw);