@dailephd/my-frontend-observer 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +490 -479
  2. package/LICENSE +21 -21
  3. package/README.md +375 -365
  4. package/dist/application/projectCheckService.d.ts +6 -0
  5. package/dist/application/projectCheckService.js +8 -1
  6. package/dist/application/projectCheckService.js.map +1 -1
  7. package/dist/application/projectWorkflowService.d.ts +7 -2
  8. package/dist/application/projectWorkflowService.js +10 -3
  9. package/dist/application/projectWorkflowService.js.map +1 -1
  10. package/dist/cli.js +510 -510
  11. package/dist/viewer/index.html +13 -13
  12. package/dist/viewer/sw.js +1 -1
  13. package/docs/ARCHITECTURE.md +1394 -1385
  14. package/docs/CI_CD.md +349 -338
  15. package/docs/COMMANDS.md +1035 -1026
  16. package/docs/CONTRACTS.md +1971 -1960
  17. package/docs/CURRENT_STATE.md +1277 -1252
  18. package/docs/DEVELOPMENT.md +240 -237
  19. package/docs/DOCUMENTATION_PRESERVATION_POLICY.md +50 -50
  20. package/docs/PROJECT_DESCRIPTION.md +2248 -2224
  21. package/docs/PROJECT_MILESTONES.md +2681 -2558
  22. package/docs/PROJECT_OVERVIEW.md +200 -196
  23. package/docs/QUICKSTART.md +100 -100
  24. package/docs/RELEASE.md +37 -36
  25. package/docs/ROADMAP.md +1105 -1034
  26. package/docs/SECURITY.md +297 -297
  27. package/docs/WORKFLOWS.md +806 -796
  28. package/docs/plans/v0.10-implementation-plan.md +1509 -1509
  29. package/docs/plans/v0.8-implementation-plan.md +655 -655
  30. package/docs/plans/v0.8.1-cli-usability-patch-plan.md +505 -505
  31. package/docs/plans/v0.9-implementation-plan.md +1529 -1529
  32. package/docs/plans/v0.9.1-implementation-plan.md +468 -468
  33. package/docs/reports/v0.10-batch1-visual-change-workflow-foundation.md +102 -102
  34. package/docs/reports/v0.10-batch2-project-composition-check-recording.md +103 -103
  35. package/docs/reports/v0.10-batch3-viewer-visual-change-workspace.md +93 -93
  36. package/docs/reports/v0.10-batch4-actual-frontend-entry.md +59 -59
  37. package/docs/reports/v0.10-batch5-reference-driven-entry.md +238 -238
  38. package/docs/reports/v0.10-batch6-coding-agent-handoff.md +85 -85
  39. package/docs/reports/v0.10-batch7-correction-review-acceptance.md +145 -145
  40. package/docs/reports/v0.10-batch8-integrated-acceptance.md +109 -109
  41. package/docs/reports/v0.10-implementation-completeness-documentation-reconciliation.md +344 -344
  42. package/docs/reports/v0.10-pre-release-readiness.md +120 -120
  43. package/docs/reports/v0.10-release-preparation.md +70 -70
  44. package/docs/reports/v0.10.1-project-check-baseline-context-implementation.md +86 -0
  45. package/docs/reports/v0.7-bounded-fidelity-context-prompt7.md +243 -243
  46. package/docs/reports/v0.7-implementation-completeness-documentation-reconciliation.md +497 -497
  47. package/docs/reports/v0.7-pre-release-readiness.md +337 -337
  48. package/docs/reports/v0.7-reference-binding-prompt5.md +223 -223
  49. package/docs/reports/v0.7-reference-compatibility-prompt4.md +234 -234
  50. package/docs/reports/v0.7-reference-correction-workflow-prompt8.md +222 -222
  51. package/docs/reports/v0.7-reference-fidelity-prompt6.md +216 -216
  52. package/docs/reports/v0.7-reference-foundation-prompt1.md +151 -151
  53. package/docs/reports/v0.7-reference-regions-prompt2.md +195 -195
  54. package/docs/reports/v0.7-reference-requirements-prompt3.md +217 -217
  55. package/docs/reports/v0.7-release-prep.md +423 -423
  56. package/docs/reports/v0.8-binding-fidelity-interaction-batch6.md +279 -279
  57. package/docs/reports/v0.8-bounded-context-correlation-batch7.md +233 -233
  58. package/docs/reports/v0.8-comparison-contract-inspection-batch4.md +279 -279
  59. package/docs/reports/v0.8-evidence-index-readers-batch2.md +247 -247
  60. package/docs/reports/v0.8-implementation-completeness-documentation-reconciliation.md +741 -741
  61. package/docs/reports/v0.8-integrated-viewer-acceptance-batch8.md +128 -128
  62. package/docs/reports/v0.8-observation-svg-inspection-batch3.md +223 -223
  63. package/docs/reports/v0.8-prerelease-readiness-cross-platform-security-code-rot.md +687 -687
  64. package/docs/reports/v0.8-reference-candidate-inspection-batch5.md +232 -232
  65. package/docs/reports/v0.8-viewer-runtime-pwa-batch1.md +278 -278
  66. package/docs/reports/v0.8.1-implementation-completeness-documentation-reconciliation.md +114 -114
  67. package/docs/reports/v0.8.1-prerelease-readiness-cross-platform-security-code-rot.md +170 -170
  68. package/docs/reports/v0.9-architecture-retrieval.md +14 -37
  69. package/docs/reports/v0.9-final-pre-release-readiness.md +209 -209
  70. package/docs/reports/v0.9-final-readiness-corrections.md +530 -530
  71. package/docs/reports/v0.9-pre-release-readiness.md +169 -169
  72. package/docs/reports/v0.9.1-batch1-pwa-hard-gate-isolation.md +359 -359
  73. package/docs/reports/v0.9.1-batch2-hard-gate-validation-integration.md +262 -262
  74. package/docs/reports/v0.9.1-pre-release-readiness.md +206 -206
  75. package/package.json +59 -59
package/dist/cli.js CHANGED
@@ -25,528 +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 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.
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.
154
154
  `;
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.
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.
166
166
  `;
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.
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.
175
175
  `;
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.
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.
188
188
  `;
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.
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.
247
247
  `;
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.
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.
285
285
  `;
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.
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.
319
319
  `;
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.
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.
346
346
  `;
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.
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.
384
384
  `;
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.
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.
467
467
  `;
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.
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.
501
501
  `;
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.
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.
550
550
  `;
551
551
  function parseViewport(raw) {
552
552
  const match = /^(\d+)x(\d+)$/.exec(raw);