@dailephd/my-frontend-observer 0.9.1 → 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 (150) hide show
  1. package/CHANGELOG.md +490 -471
  2. package/LICENSE +21 -21
  3. package/README.md +375 -357
  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/application/visualChangeAgentHandoffService.d.ts +28 -0
  11. package/dist/application/visualChangeAgentHandoffService.js +111 -0
  12. package/dist/application/visualChangeAgentHandoffService.js.map +1 -0
  13. package/dist/application/visualChangeProjectWorkflowService.d.ts +95 -0
  14. package/dist/application/visualChangeProjectWorkflowService.js +376 -0
  15. package/dist/application/visualChangeProjectWorkflowService.js.map +1 -0
  16. package/dist/application/visualChangeReviewService.d.ts +50 -0
  17. package/dist/application/visualChangeReviewService.js +69 -0
  18. package/dist/application/visualChangeReviewService.js.map +1 -0
  19. package/dist/application/visualChangeWorkflowPersistenceService.d.ts +26 -0
  20. package/dist/application/visualChangeWorkflowPersistenceService.js +15 -0
  21. package/dist/application/visualChangeWorkflowPersistenceService.js.map +1 -0
  22. package/dist/artifacts/visualChangeWorkflowArtifactReader.d.ts +9 -0
  23. package/dist/artifacts/visualChangeWorkflowArtifactReader.js +47 -0
  24. package/dist/artifacts/visualChangeWorkflowArtifactReader.js.map +1 -0
  25. package/dist/artifacts/visualChangeWorkflowArtifactWriter.d.ts +20 -0
  26. package/dist/artifacts/visualChangeWorkflowArtifactWriter.js +41 -0
  27. package/dist/artifacts/visualChangeWorkflowArtifactWriter.js.map +1 -0
  28. package/dist/cli.js +9 -7
  29. package/dist/cli.js.map +1 -1
  30. package/dist/domain/visualChangeAgentHandoff.d.ts +82 -0
  31. package/dist/domain/visualChangeAgentHandoff.js +80 -0
  32. package/dist/domain/visualChangeAgentHandoff.js.map +1 -0
  33. package/dist/domain/visualChangeAgentHandoffSerialization.d.ts +2 -0
  34. package/dist/domain/visualChangeAgentHandoffSerialization.js +11 -0
  35. package/dist/domain/visualChangeAgentHandoffSerialization.js.map +1 -0
  36. package/dist/domain/visualChangeCycle.d.ts +8 -0
  37. package/dist/domain/visualChangeCycle.js +7 -0
  38. package/dist/domain/visualChangeCycle.js.map +1 -0
  39. package/dist/domain/visualChangeWorkflow.d.ts +125 -0
  40. package/dist/domain/visualChangeWorkflow.js +109 -0
  41. package/dist/domain/visualChangeWorkflow.js.map +1 -0
  42. package/dist/domain/visualChangeWorkflowIdentity.d.ts +5 -0
  43. package/dist/domain/visualChangeWorkflowIdentity.js +24 -0
  44. package/dist/domain/visualChangeWorkflowIdentity.js.map +1 -0
  45. package/dist/index.d.ts +21 -1
  46. package/dist/index.js +12 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/projectWorkflow/projectPaths.d.ts +3 -0
  49. package/dist/projectWorkflow/projectPaths.js +7 -0
  50. package/dist/projectWorkflow/projectPaths.js.map +1 -1
  51. package/dist/viewer/assets/index-DglJ6f28.css +1 -0
  52. package/dist/viewer/assets/index-DsODREY5.js +9 -0
  53. package/dist/viewer/index.html +15 -15
  54. package/dist/viewer/sw.js +1 -1
  55. package/dist/viewerServer/evidence/classify.d.ts +3 -1
  56. package/dist/viewerServer/evidence/classify.js +10 -0
  57. package/dist/viewerServer/evidence/classify.js.map +1 -1
  58. package/dist/viewerServer/evidence/handles.js +1 -0
  59. package/dist/viewerServer/evidence/handles.js.map +1 -1
  60. package/dist/viewerServer/evidence/projection.d.ts +5 -0
  61. package/dist/viewerServer/evidence/projection.js +19 -0
  62. package/dist/viewerServer/evidence/projection.js.map +1 -1
  63. package/dist/viewerServer/evidence/visualChangeWorkflowView.d.ts +31 -0
  64. package/dist/viewerServer/evidence/visualChangeWorkflowView.js +36 -0
  65. package/dist/viewerServer/evidence/visualChangeWorkflowView.js.map +1 -0
  66. package/dist/viewerServer/httpServer.js +323 -1
  67. package/dist/viewerServer/httpServer.js.map +1 -1
  68. package/dist/viewerServer/referenceApproval.d.ts +22 -0
  69. package/dist/viewerServer/referenceApproval.js +42 -0
  70. package/dist/viewerServer/referenceApproval.js.map +1 -0
  71. package/dist/viewerServer/referenceVisualChangeAuthoring.d.ts +28 -0
  72. package/dist/viewerServer/referenceVisualChangeAuthoring.js +134 -0
  73. package/dist/viewerServer/referenceVisualChangeAuthoring.js.map +1 -0
  74. package/dist/viewerServer/runtimeVisualChangeAuthoring.d.ts +33 -0
  75. package/dist/viewerServer/runtimeVisualChangeAuthoring.js +81 -0
  76. package/dist/viewerServer/runtimeVisualChangeAuthoring.js.map +1 -0
  77. package/dist/viewerServer/visualChangeAuthoring.d.ts +46 -0
  78. package/dist/viewerServer/visualChangeAuthoring.js +63 -0
  79. package/dist/viewerServer/visualChangeAuthoring.js.map +1 -0
  80. package/dist/viewerServer/visualChangeHandoff.d.ts +23 -0
  81. package/dist/viewerServer/visualChangeHandoff.js +31 -0
  82. package/dist/viewerServer/visualChangeHandoff.js.map +1 -0
  83. package/dist/viewerServer/visualChangeReview.d.ts +30 -0
  84. package/dist/viewerServer/visualChangeReview.js +46 -0
  85. package/dist/viewerServer/visualChangeReview.js.map +1 -0
  86. package/docs/ARCHITECTURE.md +1394 -1373
  87. package/docs/CI_CD.md +349 -327
  88. package/docs/COMMANDS.md +1035 -1012
  89. package/docs/CONTRACTS.md +1971 -1926
  90. package/docs/CURRENT_STATE.md +1277 -1238
  91. package/docs/DEVELOPMENT.md +240 -237
  92. package/docs/DOCUMENTATION_PRESERVATION_POLICY.md +50 -50
  93. package/docs/PROJECT_DESCRIPTION.md +2248 -2224
  94. package/docs/PROJECT_MILESTONES.md +2681 -2558
  95. package/docs/PROJECT_OVERVIEW.md +200 -191
  96. package/docs/QUICKSTART.md +100 -96
  97. package/docs/RELEASE.md +37 -33
  98. package/docs/ROADMAP.md +1105 -1033
  99. package/docs/SECURITY.md +297 -275
  100. package/docs/WORKFLOWS.md +806 -770
  101. package/docs/plans/v0.10-implementation-plan.md +1509 -0
  102. package/docs/plans/v0.8-implementation-plan.md +655 -655
  103. package/docs/plans/v0.8.1-cli-usability-patch-plan.md +505 -505
  104. package/docs/plans/v0.9-implementation-plan.md +1529 -1529
  105. package/docs/plans/v0.9.1-implementation-plan.md +468 -468
  106. package/docs/reports/v0.10-batch1-visual-change-workflow-foundation.md +102 -0
  107. package/docs/reports/v0.10-batch2-project-composition-check-recording.md +103 -0
  108. package/docs/reports/v0.10-batch3-viewer-visual-change-workspace.md +93 -0
  109. package/docs/reports/v0.10-batch4-actual-frontend-entry.md +59 -0
  110. package/docs/reports/v0.10-batch5-reference-driven-entry.md +238 -0
  111. package/docs/reports/v0.10-batch6-coding-agent-handoff.md +85 -0
  112. package/docs/reports/v0.10-batch7-correction-review-acceptance.md +145 -0
  113. package/docs/reports/v0.10-batch8-integrated-acceptance.md +109 -0
  114. package/docs/reports/v0.10-implementation-completeness-documentation-reconciliation.md +344 -0
  115. package/docs/reports/v0.10-pre-release-readiness.md +120 -0
  116. package/docs/reports/v0.10-release-preparation.md +70 -0
  117. package/docs/reports/v0.10.1-project-check-baseline-context-implementation.md +86 -0
  118. package/docs/reports/v0.7-bounded-fidelity-context-prompt7.md +243 -243
  119. package/docs/reports/v0.7-implementation-completeness-documentation-reconciliation.md +497 -497
  120. package/docs/reports/v0.7-pre-release-readiness.md +337 -337
  121. package/docs/reports/v0.7-reference-binding-prompt5.md +223 -223
  122. package/docs/reports/v0.7-reference-compatibility-prompt4.md +234 -234
  123. package/docs/reports/v0.7-reference-correction-workflow-prompt8.md +222 -222
  124. package/docs/reports/v0.7-reference-fidelity-prompt6.md +216 -216
  125. package/docs/reports/v0.7-reference-foundation-prompt1.md +151 -151
  126. package/docs/reports/v0.7-reference-regions-prompt2.md +195 -195
  127. package/docs/reports/v0.7-reference-requirements-prompt3.md +217 -217
  128. package/docs/reports/v0.7-release-prep.md +423 -423
  129. package/docs/reports/v0.8-binding-fidelity-interaction-batch6.md +279 -279
  130. package/docs/reports/v0.8-bounded-context-correlation-batch7.md +233 -233
  131. package/docs/reports/v0.8-comparison-contract-inspection-batch4.md +279 -279
  132. package/docs/reports/v0.8-evidence-index-readers-batch2.md +247 -247
  133. package/docs/reports/v0.8-implementation-completeness-documentation-reconciliation.md +741 -741
  134. package/docs/reports/v0.8-integrated-viewer-acceptance-batch8.md +128 -128
  135. package/docs/reports/v0.8-observation-svg-inspection-batch3.md +223 -223
  136. package/docs/reports/v0.8-prerelease-readiness-cross-platform-security-code-rot.md +687 -687
  137. package/docs/reports/v0.8-reference-candidate-inspection-batch5.md +232 -232
  138. package/docs/reports/v0.8-viewer-runtime-pwa-batch1.md +278 -278
  139. package/docs/reports/v0.8.1-implementation-completeness-documentation-reconciliation.md +114 -114
  140. package/docs/reports/v0.8.1-prerelease-readiness-cross-platform-security-code-rot.md +170 -170
  141. package/docs/reports/v0.9-architecture-retrieval.md +14 -37
  142. package/docs/reports/v0.9-final-pre-release-readiness.md +209 -209
  143. package/docs/reports/v0.9-final-readiness-corrections.md +530 -530
  144. package/docs/reports/v0.9-pre-release-readiness.md +169 -169
  145. package/docs/reports/v0.9.1-batch1-pwa-hard-gate-isolation.md +359 -359
  146. package/docs/reports/v0.9.1-batch2-hard-gate-validation-integration.md +262 -262
  147. package/docs/reports/v0.9.1-pre-release-readiness.md +206 -206
  148. package/package.json +59 -59
  149. package/dist/viewer/assets/index-BN41MI7m.css +0 -1
  150. package/dist/viewer/assets/index-CkKXnlrI.js +0 -9
package/docs/WORKFLOWS.md CHANGED
@@ -1,770 +1,806 @@
1
- # Workflows
2
-
3
- Cross-repository composition is centralized in [my-dev-kit's ecosystem guide](https://github.com/dailephd/my-dev-kit/blob/main/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md), especially the [command-surface compatibility map](https://github.com/dailephd/my-dev-kit/blob/main/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md#915-command-surface-compatibility-map). That map covers static-to-runtime correlation, Lab tutorial/reference handoffs, Orchestrator consumption, and combinations that are deliberately not direct artifact pipes.
4
-
5
- ## Project and coding-agent workflow
6
-
7
- ```text
8
- init
9
- capture baseline
10
- implement frontend change outside Observer
11
- check baseline --json
12
- if FAIL:
13
- use returned canonical runtime failure evidence
14
- correct frontend source outside Observer
15
- run the identical check again
16
- finish only after PASS
17
- view
18
- ```
19
-
20
- Observer reports evidence and acceptance. The external human, coding agent, or
21
- orchestrator edits source; Observer never does. With no executable contract or
22
- approved reference, successful comparison yields `REVIEW_REQUIRED`, not PASS.
23
-
24
- ## Current validation workflow
25
-
26
- ```text
27
- install dependencies (npm install; npx playwright install chromium)
28
- → validate types and lint
29
- → run the fast unit suite (npm test)
30
- → run the real-Chromium integration suite (npm run test:browser)
31
- → build the CLI/library entries (npm run build)
32
- → validate documentation (npm run check:docs)
33
- ```
34
-
35
- ## Current observation workflow (supported in 0.9.0)
36
-
37
- The real `observe` workflow remains supported in the current published
38
- `my-frontend-observer@0.9.0` package. Its browser-observation behavior was
39
- established in earlier releases; later project/viewer releases compose it
40
- rather than replacing it. It accepts target configuration through either of
41
- two input paths, plus one optional runtime scroll scenario:
42
-
43
- ```text
44
- CLI arguments (--url, --viewport, --output, --timeout, exactly one of:
45
- one-or-more --target <id=css-selector>
46
- or --targets-file <json-file>,
47
- plus optionally --scroll-scenario-file <json-file>)
48
- → (--targets-file only: read + validate the local JSON root wrapper)
49
- → (--scroll-scenario-file only: read + validate the local JSON root shape -
50
- a non-array object; the file supplies RawObservationRequest.scrollScenario
51
- directly, with no wrapper field)
52
- → request construction (same RawObservationRequest either way)
53
- → normalizeRequest() - producing canonical {name, locators} targets and
54
- validating the optional scrollScenario (supported action kind, delta
55
- bounds/both-zero rule, stable target-name reference)
56
- → application observation use case (src/application/observationPersistence.ts#observe)
57
- → Chromium capture: launch, safe navigation, readiness, then - only if a
58
- scenario was configured - resolve configured targets once, capture an
59
- initial ScrollRuntimeSnapshot, perform the one immediate scroll
60
- (window.scrollBy/element.scrollBy, behavior: "instant"), wait exactly two
61
- requestAnimationFrame cycles, capture a final ScrollRuntimeSnapshot and
62
- derive transition/scroll-owner evidence; then screenshot and page/target
63
- evidence (resolving all six locator kinds through the single canonical
64
- resolver, plus semantic state/landmark/containment evidence), from the
65
- same live page - exactly once, always describing the final state
66
- → atomic artifact persistence (manifest.json + screenshot.png), schema
67
- 1.2.0 - exactly once, only on a successful capture; scrollScenarioEvidence
68
- is simply one more optional manifest field, never a separate file
69
- → concise CLI result (Observation/State/Artifact/Targets/Diagnostics)
70
- → process exit status (0 for a persisted observation, including one whose
71
- state honestly reports "partial"; nonzero otherwise)
72
- ```
73
-
74
- A request with no scroll scenario is unaffected: no extra snapshots, no
75
- scroll, no extra animation-frame wait, unchanged request identity.
76
-
77
- This is exercised by `runCli()`-level tests, real-Chromium end-to-end tests
78
- (`tests/browser/cliObserve.test.ts`, `tests/browser/windowScrollScenario.test.ts`,
79
- `tests/browser/targetScrollScenario.test.ts`), built `node dist/cli.js
80
- observe ...` runs against the deterministic local fixture
81
- (`scripts/dev/builtCliTargetsFileSmoke.mjs` for the semantic `--targets-file`
82
- path, `scripts/dev/builtCliScrollScenarioSmoke.mjs` for the scroll-scenario
83
- path), and the real `npm pack` tarball installed and run from a clean
84
- temporary consumer directory outside the repository, on Windows, Linux, and
85
- macOS (`scripts/ci/runPackedObservationSmoke.mjs`) - the same workflow,
86
- independent of the source checkout.
87
-
88
- ## Current comparison workflow (supported in 0.9.0)
89
-
90
- **Current status: shipped originally as part of
91
- `my-frontend-observer@0.4.0` and remains supported in `0.9.0`.** This is a
92
- separate workflow from the observation workflow above - it consumes two
93
- already-persisted observation artifacts rather than producing one, and it
94
- never launches a browser:
95
-
96
- ```text
97
- two prior real "observe" invocations, each producing its own persisted
98
- ObservationArtifact (before, after) - unrelated to this workflow itself
99
- → CLI arguments (--before <root>, --after <root>, --output <directory>,
100
- optionally --config-file <json-file>)
101
- → (--config-file only: read + validate the local JSON root shape - a
102
- non-array object; the file supplies ComparisonConfig directly, with no
103
- wrapper field)
104
- → read + validate both observation artifacts (src/artifacts/artifactReader.ts,
105
- the same isValidObservationArtifact structural gate the writer uses)
106
- → application comparison use case
107
- (src/application/comparisonService.ts#compareAndPersistFromArtifactRoots
108
- → compareAndPersist)
109
- → pure comparison derivation (src/domain/comparisonEngine.ts#compareObservations):
110
- comparability first, then - only if comparable/comparable-with-warnings -
111
- deriveLayoutRelationships for each side plus target/page differences,
112
- relationship changes, and explicit non-causal dependency evidence
113
- → atomic comparison-artifact persistence (manifest.json only, no copied
114
- screenshots), schema 1.0.0 - exactly once, for every comparability
115
- outcome including "incomparable"
116
- → concise CLI result (Comparison/State/Artifact/Differences/Relationship
117
- changes/Diagnostics)
118
- → process exit status (0 for any successfully computed and persisted
119
- comparison, including "incomparable"; nonzero only for invalid
120
- syntax/unreadable or invalid source artifacts/invalid configuration/a
121
- failed write)
122
- ```
123
-
124
- Source observations are never modified by this workflow. Operational paths
125
- (`--before`/`--after`/`--config-file`/`--output`) never affect
126
- `comparisonRequestId` and are never written into the persisted manifest.
127
-
128
- This is exercised by `runCli()`-level tests
129
- (`tests/unit/cli.test.ts`, `tests/unit/cliCompareOrchestration.test.ts`,
130
- `tests/unit/cliCompareEndToEnd.test.ts`), a real-Chromium end-to-end test
131
- (`tests/browser/cliCompare.test.ts`), built `node dist/cli.js compare ...`
132
- runs against real persisted observations from the deterministic local
133
- fixture (`scripts/dev/builtCliCompareSmoke.mjs`), and packed-tarball
134
- validation of the installed `compare` command
135
- (`scripts/ci/runPackedObservationSmoke.mjs` - see `docs/CI_CD.md`).
136
-
137
- ## Current frontend contract workflow (supported in 0.9.0)
138
-
139
- This text/config-driven workflow shipped in `0.5.0` and remains supported in
140
- `0.9.0`. It is layered downstream of the two workflows above - it does not
141
- replace them. The complete v0.7 coding-agent workflow (the external-reference
142
- evidence foundation and end-to-end correction loop) is layered on top of
143
- it - see "Current external-reference foundation workflow" and "Current
144
- reference correction workflow" below; baseline selection here remains
145
- caller-supplied:
146
-
147
- ```text
148
- observe before
149
- observe after
150
- compare
151
- ↓
152
- approve baseline (approve-baseline --observation <before-root>
153
- --contract-file <PersistentBaselineContract.json> --output <dir>)
154
- ↓
155
- save per-change contract (save-change-contract
156
- --contract-file <PerChangeContract.json> --output <dir>)
157
- ↓
158
- evaluate contract (evaluate-contract --before <root> --after <root>
159
- --comparison <root> --baseline <root> --change <root> --output <dir>
160
- [--enforce])
161
- ↓
162
- persisted evaluation artifact (schema 1.0.0, its own independent family):
163
- clause results (pass/fail/unavailable/conflict), unexpected changes,
164
- overall PASS/FAIL
165
- ```
166
-
167
- `approve-baseline` is the only baseline-approval act; a successful `compare`
168
- or a `PASS` evaluation never approves or supersedes a baseline
169
- automatically. `evaluate-contract` never launches a browser and never
170
- recomputes comparison/relationship evidence - it calls the canonical
171
- `evaluateFrontendContract` exactly once against the supplied evidence and
172
- persists exactly one evaluation artifact, whether the verdict is `PASS` or
173
- `FAIL`. `--enforce` affects only the process exit status for a `FAIL`
174
- verdict, never the persisted evidence itself.
175
-
176
- This is exercised by `runCli()`-level tests
177
- (`tests/unit/cliFrontendContracts.test.ts`), a built `node dist/cli.js`
178
- smoke that needs no Chromium
179
- (`scripts/dev/builtCliFrontendContractsSmoke.mjs`), a real-Chromium
180
- end-to-end test (`tests/browser/cliFrontendContracts.test.ts`), and a
181
- real-Chromium built-CLI smoke
182
- (`scripts/dev/builtCliFrontendContractsBrowserSmoke.mjs` - see
183
- `docs/DEVELOPMENT.md`). The real-browser coverage proves both a fully
184
- successful contract change and the "milestone signature" failure (a locally
185
- successful requested change coexisting with a genuine protected-property
186
- regression and a genuine preserved-invariant regression) against actual
187
- rendered geometry, not hand-constructed artifacts. It is also part of
188
- packed-tarball validation: `scripts/ci/runPackedObservationSmoke.mjs`
189
- exercises the installed candidate's `approve-baseline`/`save-change-contract`/
190
- `evaluate-contract` commands against real installed-candidate `observe`/
191
- `compare` evidence, proven on Windows, Linux, and macOS (see
192
- `docs/CI_CD.md`).
193
-
194
- ## Current bounded agent context workflow (released as `0.6.0`)
195
-
196
- This is a programmatic (library-only) workflow, not a CLI command - it
197
- consumes already-persisted v0.1-v0.5 evidence in-process rather than reading
198
- artifact roots from disk:
199
-
200
- ```text
201
- already-captured evidence (ObservationArtifact(s), ComparisonArtifact,
202
- PersistentBaselineContract/PerChangeContract, evaluation results)
203
- → projectBoundedAgentContext(...)
204
- (src/domain/boundedAgentContextProjection.ts)
205
- → BoundedRuntimeTargetProjection: bounded geometry/behavior/relationships/
206
- differences/contract-scope evidence, adequacy, omission, truncation
207
- → deriveRuntimeStaticCorrelations(...) / attachRuntimeStaticCorrelations(...)
208
- (src/domain/boundedAgentContextCorrelation.ts), given caller-supplied
209
- candidate static evidence
210
- → RuntimeStaticCorrelation[] (correlated / ambiguous / unavailable -
211
- competing candidates remain visible, never collapsed to one owner)
212
- → consumed programmatically via the public export surface (src/index.ts) -
213
- by an external orchestrator or coding-agent workflow outside this
214
- repository, not by a new my-frontend-observer CLI command
215
- ```
216
-
217
- This is exercised by unit tests covering the projection and correlation
218
- modules (happy path, boundedness at exact/one-over/large-overflow limits,
219
- immutability, malformed-input fail-closed behavior, adequacy/omission/
220
- truncation reporting, and correlation status invariants/determinism/
221
- deduplication). See `docs/CONTRACTS.md` "v0.6 bounded agent context and
222
- correlation contract" for the exact shape.
223
-
224
- **v0.7 Prompt 7 addition (released as `0.7.0`):** `projectBoundedAgentContext`
225
- now optionally accepts an already-computed v0.7 Prompt 6
226
- `ReferenceCandidateFidelityEvaluation` (`fidelity`) alongside its existing
227
- v0.1-v0.5 evidence inputs - never recomputed, never a second fidelity
228
- engine:
229
-
230
- ```text
231
- already-computed evaluateReferenceCandidateFidelity(...) result
232
- → projectBoundedAgentContext({ ..., fidelity, fidelityRequired? })
233
- → projectReferenceFidelity(...) (src/domain/referenceFidelityProjection.ts):
234
- selects/prioritizes/bounds Prompt 6's non-passing requirement results
235
- (failed-required, then unavailable-required, then other non-pass) plus
236
- passing protected/preserved context, and contributes their bound v0.2
237
- runtime target ids to the exact same required/permitted-target
238
- allocation contract clauses already compete in
239
- → BoundedAgentContextArtifact.fidelity: bounded mismatches/protectedContext
240
- + adequacy/compatibility/state pass-through from Prompt 6, folded into
241
- the same omissions/truncations/adequacy computation as every other
242
- evidence source (a blocked "not-evaluated" fidelity is never silently
243
- reported as "no problems")
244
- → still consumed programmatically only, unchanged - no CLI surface
245
- ```
246
-
247
- Absent `fidelity`, output is unaffected - identical to the pre-Prompt-7
248
- behavior described above, including logical identity. See
249
- `docs/CONTRACTS.md` "v0.7 Prompt 7 bounded reference-fidelity projection and
250
- v0.6 bounded-agent-context integration" for the full contract.
251
-
252
- ## Current external-reference foundation workflow (released as `0.7.0`)
253
-
254
- This is the foundation layer only - identity, provenance, bounded image
255
- metadata, a two-state lifecycle, (Prompt 2) explicit reference regions plus
256
- reusable geometry relationships, (Prompt 3) selected design requirements,
257
- tolerance semantics, and reference-evidence adequacy, (Prompt 4) explicit
258
- reference applicability (viewport/theme/application-state/authenticated-
259
- state) and reference/candidate compatibility, and (Prompt 5) explicit
260
- reference-region <-> runtime-target binding, for one externally supplied
261
- design-reference image. Structured fidelity-evaluation behavior (Prompt 6)
262
- follows further below in this section, and it never launches a browser or
263
- reads/writes any observation, comparison, or contract artifact:
264
-
265
- ```text
266
- import-reference <image-file> --output <dir> [--label] [--supersedes <root>] [--regions-file <json-file>] [--requirements-file <json-file>] [--applicability-file <json-file>]
267
- → format detection from header/magic bytes only (png/jpeg/webp; never a
268
- caller-declared extension), dimension parsing from the same bounded header
269
- bytes (never a pixel decode), byte-length and dimension bounds checked
270
- → (--regions-file only: read + validate the local JSON root shape - an
271
- object with exactly a "regions" property - then validate each region's id/
272
- rectangle and the collection's bounds/uniqueness/image-boundary rules)
273
- → (--requirements-file only: read + validate the local JSON root shape - an
274
- object with exactly a "requirements" property - then validate each
275
- requirement's category/subject/tolerance shape, compute its
276
- content-derived requirementId, and validate the collection's bounds/
277
- region-existence/duplicate-subject rules against the regions above)
278
- → (--applicability-file only: read + validate the local JSON root shape -
279
- the raw, unwrapped applicability object, no wrapper property - then
280
- validate its optional viewport/theme/applicationState/authenticatedState
281
- fields; caller-declared only, never inferred from the image)
282
- → (--supersedes only: read + validate the referenced prior external-reference
283
- artifact through the same reader the writer's counterpart uses)
284
- → deterministic referenceRequestId (pure function of {imageSha256, format,
285
- width, height, supersedesReferenceId, regions?, requirements?,
286
- applicability?} only) + fresh referenceId
287
- → atomic persistence of one "imported" ExternalReferenceArtifact:
288
- manifest.json (+ regions/requirements/applicability, when supplied) + its
289
- own copy of the reference image, schema 1.0.0 - lifecycle.state is always
290
- "imported"; import never approves
291
- ↓
292
- approve-reference --reference <imported-artifact-root> --output <dir> [--supersedes <root>]
293
- → read + validate the target through the existing reader; refuse anything
294
- not currently in the "imported" lifecycle state
295
- → persist a brand-new "approved" ExternalReferenceArtifact instance (same
296
- referenceRequestId, fresh referenceId) carrying a sourceReference back to
297
- the imported artifact's image - no image bytes are copied again, any
298
- regions/requirements/applicability are carried forward verbatim (never
299
- re-validated/re-derived), and the imported artifact's own manifest is
300
- never modified
301
- ```
302
-
303
- `approve-reference` is the only explicit reference-approval act - it is never
304
- inferred from a successful import. Supersession (`--supersedes`) is
305
- represented only as a forward pointer on the newer artifact; the artifact it
306
- supersedes is never rewritten, so prior reference evidence remains immutable
307
- regardless of how many later references supersede it. Region/requirement/
308
- applicability content (added/removed/moved/resized/renamed regions;
309
- added/removed/changed requirements or tolerances; a changed applicability
310
- declaration) is identity-bearing, so a differently-structured reference is
311
- always a distinct logical reference, never a silent rewrite of an existing
312
- one.
313
-
314
- Separately, `observe` gained an optional `--state-file <json-file>` (the
315
- raw, unwrapped `{theme?, applicationState?, authenticatedState?}` object -
316
- caller-declared only, never inferred), persisted as
317
- `requestConfig.explicitState` on the resulting `ObservationArtifact` and
318
- folded into that observation's own request identity. A pure, synchronous
319
- domain function, `evaluateReferenceCandidateCompatibility(reference,
320
- candidate)`, then answers "does this reference describe the same frontend
321
- state as this candidate observation?" by comparing
322
- `reference.applicability` against `candidate.requestConfig`
323
- (viewport/explicitState) - reusing v0.4's own comparability result/reason
324
- vocabulary and its underlying per-dimension comparison rule rather than
325
- inventing a parallel model. This produces no persisted artifact of its own;
326
- it is a pure function callers invoke on two already-persisted artifacts. See
327
- `docs/CONTRACTS.md` "v0.7 Prompt 4 reference applicability and
328
- candidate-state compatibility" for the full contract.
329
-
330
- Building on that gate, a second pure, synchronous domain function,
331
- `evaluateReferenceRuntimeBindings(reference, candidate, declarations)`,
332
- answers "which stable v0.2 runtime target does this candidate resolve for
333
- each explicitly declared reference region?" `declarations` is explicit
334
- user/configuration input (`{referenceRegion, runtimeTarget}` pairs) - never
335
- inferred from geometry, matching names, or source code. It runs the Prompt
336
- 4 compatibility gate first (reused, never duplicated): an `incomparable`
337
- reference/candidate pair produces zero evaluated bindings, the blocker
338
- visible only through the embedded `compatibility` field. Otherwise each
339
- declaration is resolved against the candidate's own already-captured
340
- `requestConfig.targets`/`targetEvidence` only - no browser, no second
341
- target resolver - using the same `targetPresence` classification v0.4's own
342
- `evaluateComparability` already relies on, yielding `bound`/`ambiguous`/
343
- `unavailable` per declaration. Like compatibility, this produces no
344
- persisted artifact of its own and mutates neither the reference nor the
345
- candidate. See `docs/CONTRACTS.md` "v0.7 Prompt 5 explicit reference-region
346
- <-> runtime-target binding" for the full contract.
347
-
348
- Reference-region relationships (`deriveReferenceRegionRelationships()`) are
349
- a separate, pure, on-demand derivation over an artifact's own `regions` -
350
- not part of the persisted manifest - reusing the same geometry-only
351
- relationship families (`left-of`/`above`/`overlaps`/`wider-than`/
352
- `fits-inside`/`follows-vertically`, etc.) that
353
- `deriveLayoutRelationships` derives for runtime targets. A reference
354
- relationship is a fact about the reference image's geometry only, never a
355
- design requirement or a pass/fail verdict.
356
-
357
- Selected design requirements (`ExternalReferenceRequirement`) are the
358
- explicit user/configuration layer on top of that reference evidence - a
359
- region property, a region-to-region relationship, or a derived two-region
360
- measurement, tagged with one of v0.5's four authored categories
361
- (`requested`/`expected-dependent`/`protected`/`preserved`) and (except for
362
- relationship subjects) a reference-image-pixel or percent tolerance. Nothing
363
- promotes a property or relationship to a requirement automatically.
364
- Reference-evidence adequacy (`deriveReferenceRequirementAdequacy()`) reports
365
- only whether the reference side itself supports every selected requirement -
366
- `adequate`/`partial`/`inadequate`, never a numeric score, never a claim
367
- about runtime/candidate availability.
368
-
369
- Finally, `evaluate-reference-fidelity --reference <root> --candidate <root>
370
- [--bindings-file <json-file>] [--enforce]` is the first command in this
371
- stack that actually compares a reference's selected requirements against
372
- live candidate evidence:
373
-
374
- ```text
375
- evaluate-reference-fidelity --reference <root> --candidate <root> [--bindings-file <json-file>] [--enforce]
376
- → (--bindings-file only: read + validate the local JSON root shape - an
377
- object with exactly a "bindings" property - the still-unvalidated
378
- declarations are handed straight through)
379
- → read the reference and candidate artifacts through their existing readers
380
- → evaluateReferenceCandidateFidelity(reference, candidate, bindings):
381
- reference/candidate/binding-declaration structural validation
382
- → Prompt 3 reference adequacy (inadequate -> "not-evaluated", no
383
- ordinary result fabricated)
384
- → Prompt 4 compatibility (incomparable -> "not-evaluated")
385
- → Prompt 5 binding evaluation (ambiguous/unavailable/undeclared binding ->
386
- the dependent requirement is "unavailable", never guessed)
387
- → per requirement: reference-image-pixel <-> CSS-pixel coordinate mapping
388
- (from reference.applicability.viewport and the image's own dimensions;
389
- no viewport or an incoherent aspect ratio -> numeric requirements
390
- "unavailable", never a fabricated result) then a Prompt-3-tolerance
391
- comparison (region-property/region-measurement subjects) or a
392
- family-scoped v0.4 relationship comparison (region-relationship
393
- subjects)
394
- → overall state: "pass" only when every requirement result is "pass";
395
- any "fail"/"unavailable" forces "fail"
396
- ```
397
-
398
- This produces no persisted artifact - the structured result exists only for
399
- this invocation, printed as a concise summary (reference adequacy,
400
- compatibility state, overall fidelity state, and a pass/fail/unavailable
401
- requirement breakdown). `--enforce` mirrors `evaluate-contract`'s exact
402
- precedent: it changes only the process exit status for an already-computed
403
- `fail` result, never its content, and never affects a `not-evaluated`
404
- result (always exits 0 - a blocked evaluation is a successful, honest
405
- outcome, not a design mismatch). See `docs/CONTRACTS.md` "v0.7 Prompt 6
406
- structured reference-vs-candidate fidelity evaluation" for the full
407
- contract.
408
-
409
- This is exercised by unit tests covering the pure image-format/dimension
410
- boundary, region geometry/validation, reference-region relationship
411
- derivation, requirement validation/measurement derivation/reference-
412
- expectation derivation/adequacy, identity (including region- and
413
- requirement-content/order sensitivity), the domain validator, writer/reader
414
- round-trip symmetry, the application-level import/approve use cases,
415
- coordinate-mapping/tolerance/relationship fidelity evaluation (every
416
- behavior in the Prompt 6 report's behavior model, including the exact
417
- worked 2x-scale example from the task specification), and `runCli()`-level
418
- CLI coverage (no Chromium involved - see `tests/unit/externalReference*.test.ts`,
419
- `tests/unit/cliExternalReference.test.ts`, and
420
- `tests/unit/cliEvaluateReferenceFidelity.test.ts`).
421
-
422
- ## Current reference correction workflow (released as `0.7.0`)
423
-
424
- The first complete, controlled correction cycle - a programmatic (library-
425
- only) workflow, exactly like the v0.6 bounded-context workflow above, with
426
- one explicit, un-automatable seam where an external implementation actor
427
- edits target source:
428
-
429
- ```text
430
- approved ExternalReferenceArtifact + approved baseline ObservationArtifact
431
- + active PersistentBaselineContract + PerChangeContract + binding
432
- declarations + current (pre-change) ObservationArtifact
433
- → prepareReferenceCorrection(...) (src/domain/referenceCorrectionWorkflow.ts)
434
- → evaluateReferenceCandidateFidelity(...) (v0.7 Prompt 6, reused)
435
- → not-evaluated (inadequate reference / incompatible state)?
436
- → { status: 'blocked-not-evaluated' } - no fabricated handoff
437
- → otherwise: projectBoundedAgentContext({ ..., fidelity }) (v0.7 Prompt 7/v0.6, reused)
438
- → { status: 'handoff-ready', handoff: ReferenceCorrectionHandoff }
439
- ↓
440
- EXTERNAL implementation actor edits target source (never observer code)
441
- ↓
442
- fresh real-Chromium candidate ObservationArtifact
443
- (existing observe()/runBrowserCapture pipeline, reused unchanged)
444
- ↓
445
- reviewReferenceCorrectionAttempt(...)
446
- → compareObservations(baseline, candidate) (v0.4, reused)
447
- → evaluateReferenceCandidateFidelity(reference, candidate, bindings) (Prompt 6, reused)
448
- → evaluateFrontendContract({ before: baseline, after: candidate, comparison, baseline: baselineContract, change: changeContract }) (v0.5, reused)
449
- → overall: 'not-evaluated' iff fidelity not-evaluated; else 'pass' iff
450
- fidelity PASS AND contract evaluation PASS; else 'fail'
451
- ↓
452
- FAIL? → prepareReferenceCorrection(..., currentObservation: <this failed candidate>)
453
- derives a FRESH bounded handoff from the newest failed evidence
454
- ↓
455
- external correction → fresh candidate → review again (caller-controlled, never automatic)
456
- ↓
457
- PASS? → approvalEligible: true (a plain flag) - explicit
458
- approve-baseline/approve-reference remain the caller's own,
459
- separate, unautomated actions
460
- ```
461
-
462
- Every attempt (`reviewReferenceCorrectionAttempt` call) evaluates against
463
- the *same* supplied approved baseline - there is no attempt-to-attempt
464
- comparison path - and `reviewRequestId` (a deterministic hash of
465
- `{referenceRequestId, baselineObservationId, baselineContractId,
466
- baselineContractClauses, changeContractId, changeContractClauses,
467
- bindingDeclarations}`) is recomputed and checked on every review call. The
468
- contract clause contents are identity-bearing as well as the caller-authored
469
- contract ids, so a same-id contract with different clauses cannot be silently
470
- substituted between attempts. Attempt identity (`attemptId`, a deterministic
471
- hash of `{reviewRequestId, candidateObservationId}`) distinguishes every
472
- candidate execution without ever using a timestamp; because both workflow
473
- functions are pure, a returned attempt result can never be overwritten by a
474
- later call - callers that keep every result they receive have a complete,
475
- immutable attempt history for free.
476
-
477
- This is exercised by unit tests covering preparation (valid handoff,
478
- unapproved-reference rejection, inadequate-reference and incompatible-state
479
- blocking, ambiguous-binding handling, review-identity determinism),
480
- attempt review (all four overall-composition cases - both PASS, reference
481
- FAIL, contract FAIL including a protected regression, and not-evaluated -
482
- plus reviewRequestId coherence, attempt-identity determinism/distinctness,
483
- `priorAttemptId` traceability, and input immutability), and a real-Chromium
484
- end-to-end suite (`tests/browser/referenceCorrectionWorkflow.test.ts`)
485
- proving: an initial genuine design mismatch measured against real rendered
486
- geometry; a controlled, deterministic, test-only "external actor" (living
487
- entirely outside `src/`) editing a disposable copy of a tracked HTML
488
- fixture template and the observer capturing the change through the
489
- unmodified real browser pipeline; a full success correction; a protected-
490
- regression case where the candidate visually satisfies the reference but a
491
- real Chromium-observed element becomes hidden, still producing overall
492
- `FAIL`; a two-attempt correction iteration with both attempts remaining
493
- distinct and traceable to the same baseline; and a blocking case
494
- (incompatible reference/candidate viewport) that never produces a handoff.
495
- The tracked fixture template is verified byte-identical before and after
496
- the proof - only its disposable, repository-local copy is ever edited. See
497
- `docs/CONTRACTS.md` "v0.7 Prompt 8 controlled end-to-end external-reference
498
- coding-agent correction workflow" for the full contract.
499
-
500
- ## Current interactive viewer workflow (v0.8, released as `0.8.0`)
501
-
502
- v0.7 (text/config-driven coding-agent change review, the external
503
- visual-reference evidence foundation, structured reference-vs-candidate
504
- fidelity evaluation, and the end-to-end correction workflow) is released as
505
- package version `0.7.0` - see "Current external-reference foundation
506
- workflow" and "Current reference correction workflow" above, and
507
- `docs/CURRENT_STATE.md` for release state. v0.8 adds an interactive local
508
- viewer over that same evidence, released as package version `0.8.0`:
509
-
510
- ```text
511
- my-frontend-observer view --root <evidence-root>
512
- [--bindings-file <json-file>] [--context-file <json-file>]
513
- → one loopback-only (127.0.0.1) Node server, default port 4319
514
- → metadata-first evidence discovery (GET /api/index)
515
- → canonical artifact readers, on-demand (full artifact/media fetched only
516
- once explicitly selected)
517
- → viewer modes:
518
- observation (screenshot + SVG target overlays, geometry/semantics/
519
- visibility/overflow/scroll/relationships)
520
- comparison/contracts (before/after side-by-side, clause results, overall
521
- verdict)
522
- reference/candidate (reference image + region overlays, explicit
523
- candidate selection, compatibility/adequacy/applicability)
524
- bounded context (only when --context-file was supplied)
525
- → served to a normal browser or an installed Progressive Web App
526
- ```
527
-
528
- Where `--bindings-file` is supplied:
529
-
530
- ```text
531
- --bindings-file { "bindings": [{ "referenceRegion", "runtimeTarget" }] }
532
- → explicit binding evaluation (evaluateReferenceRuntimeBindings, the same
533
- canonical function evaluate-reference-fidelity uses)
534
- → binding-driven cross-selection (selecting a bound reference region
535
- highlights every runtime target it names; selecting a bound runtime
536
- target highlights every reference region that names it)
537
- → on-demand fidelity evaluation ("Evaluate Fidelity" action, never
538
- automatic), shown independently alongside any selected contract
539
- evaluation - neither overrides the other
540
- ```
541
-
542
- Where `--context-file` is supplied:
543
-
544
- ```text
545
- --context-file <one BoundedAgentContextArtifact value, no wrapper>
546
- → canonical bounded-context inspection: identity, adequacy, omissions/
547
- truncations (required loss visually distinct from optional loss),
548
- runtime/static correlation (correlated/ambiguous/unavailable)
549
- → provenance: exact-identity resolution of the context's source references
550
- against the current evidence root
551
- → safe navigation to the raw structured evidence behind a resolved source
552
- ```
553
-
554
- The viewer is optional: every CLI/programmatic workflow above remains
555
- independently functional without it. The viewer never modifies target
556
- source or any Observer evidence artifact; never runs
557
- `@dailephd/my-dev-kit`; never rebuilds a bounded context
558
- (`projectBoundedAgentContext` is not called at runtime) or its correlation
559
- (`deriveRuntimeStaticCorrelations`/`attachRuntimeStaticCorrelations` are not
560
- called at runtime) - it only displays the exact context and bindings it was
561
- started with. See `docs/COMMANDS.md#view` for the full flag reference and
562
- `docs/ARCHITECTURE.md` "v0.8 Batch 1" through "v0.8 Batch 8" for the
563
- implementation record.
564
-
565
- ## Current visual annotation workflow (released in 0.9.0)
566
-
567
- v0.9 visual annotation is released in `@dailephd/my-frontend-observer@0.9.0`.
568
- Authoring works only in the
569
- project-aware viewer (`my-frontend-observer view` inside an initialized
570
- project). `view --root <root>` inspects the same evidence read-only.
571
-
572
- ### Runtime visual flow
573
-
574
- ```text
575
- project-aware view
576
- → select a runtime observation
577
- → draw a point, rectangle, line, arrow, or note (runtime CSS pixels)
578
- → explicitly associate a runtime target or canonical runtime relationship
579
- → choose candidate intent (inspect, move, resize, remove, or preserve)
580
- → explicitly confirm the intent
581
- → save an immutable VisualAnnotationArtifact
582
- → select confirmed supported intent (move, resize, or preserve)
583
- → promote into a normal canonical PerChangeContract
584
- → optionally, explicitly activate that contract for project check
585
- → existing check and the existing contract evaluator produce the verdict
586
- ```
587
-
588
- Notes and `inspect` intent stay informational. A free mark with no explicit
589
- association never becomes a target association or a contract clause.
590
- Confirmed `remove` intent is saved but cannot be promoted, because the current
591
- contract vocabulary has no target-absent primitive. The promotion categories
592
- are the existing requested, expected-dependent, protected, and preserved
593
- categories. `unexpected` stays evaluator-derived.
594
-
595
- ### Reference visual flow
596
-
597
- ```text
598
- project-aware view
599
- → select an imported or approved external reference
600
- → draw marks (reference-image pixels)
601
- → explicitly associate a reference region or canonical region relationship
602
- → choose a candidate region create or refine, or a candidate reference
603
- requirement (region-property, region-relationship, or region-measurement)
604
- → explicitly confirm the intent
605
- → save an immutable VisualAnnotationArtifact
606
- → select confirmed materializable items
607
- → materialize a new imported external-reference revision that supersedes the
608
- source reference
609
- → explicit approval stays separate (the existing approve-reference command)
610
- ```
611
-
612
- Informational and asset-sensitive intent is never materialized. The source
613
- reference and its image are never changed. The new revision reuses the exact
614
- source image bytes, keeps the source regions, requirements, applicability, and
615
- label, and is never approved automatically. Project reference acceptance is
616
- not changed.
617
-
618
- ### Revisions and missing sources
619
-
620
- Editing a saved annotation and saving again creates a child revision that
621
- supersedes its parent. Saving another child from a stale parent fails with a
622
- conflict and keeps the draft. If a saved annotation's source evidence
623
- disappears, the annotation stays inspectable and its source is reported as
624
- `unavailable`. No replacement source is guessed.
625
-
626
- v0.10 correction orchestration (automatic coding-agent runs, rerender loops,
627
- and automatic approvals) is not implemented.
628
-
629
- ## Developer tutorial-generation workflow (v0.9 demo, not a product command)
630
-
631
- This is a contributor workflow for producing the v0.9 tutorial videos. It is
632
- not part of the product, and Observer has no `tutorial` command.
633
-
634
- ```text
635
- Observer demo and scenario (examples/v09-demo/)
636
- ↓
637
- generate TutorialTargetContractV1 (generate-tutorial-target.mjs)
638
- ↓
639
- my-dev-kit-lab tutorial validate
640
- ↓
641
- my-dev-kit-lab tutorial run
642
- ↓
643
- disposable target (prepared through canonical Observer commands)
644
- ↓
645
- WebM + screenshots + SRT/VTT + Markdown + manifest
646
- ```
647
-
648
- Ownership boundary:
649
-
650
- 1. Observer owns the demo application, the four scenario files, the
651
- target-contract generator, and the prepare command. Prepare builds each
652
- disposable project only through the canonical Observer CLI: `init`,
653
- `capture baseline`, `approve-baseline`, `save-change-contract`,
654
- `import-reference`, and `approve-reference`, as the scenario needs.
655
- 2. `@dailephd/my-dev-kit-lab@0.4.9` owns everything tutorial-specific: scenario
656
- validation, process lifecycle, the browser session, the cursor, callouts,
657
- video recording, subtitles, Markdown, and the tutorial manifest. It is an
658
- external tool run through `npx`, not an Observer dependency.
659
- 3. The tutorial drives the ordinary project-aware viewer through real pointer,
660
- keyboard and select input. Native `<select>` values are chosen with the
661
- lab's `select-option` action, which names the HTML option value, so no step
662
- depends on how a platform steps a dropdown. Correctness is proved by reading
663
- the canonical evidence the run wrote into the disposable target, not by the
664
- video.
665
-
666
- Steps:
667
-
668
- ```powershell
669
- npm run build
670
- node examples/v09-demo/scripts/generate-tutorial-target.mjs `
671
- --scenario observer-v09-runtime-contract `
672
- --out .my-dev-kit-workflow/adhoc/target-contract.json
673
- npx --yes @dailephd/my-dev-kit-lab@0.4.9 tutorial validate `
674
- --scenario examples/v09-demo/tutorials/02-runtime-intent-contract.json `
675
- --target-contract .my-dev-kit-workflow/adhoc/target-contract.json --json
676
- npx --yes @dailephd/my-dev-kit-lab@0.4.9 tutorial run `
677
- --scenario examples/v09-demo/tutorials/02-runtime-intent-contract.json `
678
- --target-contract .my-dev-kit-workflow/adhoc/target-contract.json `
679
- --out <run directory outside the repository> --json
680
- ```
681
-
682
- Generate the contract immediately before each run, because its loopback ports
683
- are only known to be free when they are chosen. Send `--out` outside the
684
- repository. The run result's `status` must be `passed` and its
685
- `cleanupErrors` must be empty. The demo and scenarios are not in the npm
686
- package. See `examples/v09-demo/README.md` for details and maintenance notes.
687
-
688
- ## Visual workflow progression (v0.9 implemented, v0.10 future)
689
-
690
- The sequence on top of the v0.7/v0.8 foundation above preserves the current
691
- engines and lets graphical interfaces consume rather than invent the reference
692
- model. v0.9 is released as `0.9.0`. v0.10 is still future:
693
-
694
- ```text
695
- stable targets and bounded runtime behavior
696
- → relationships and before/after comparison (released - see above)
697
- → safe-change contracts (contract model, evaluation, persistence, and CLI
698
- released as 0.5.0 - see above; baseline approval remains a single explicit
699
- command, not a policy engine)
700
- → bounded agent context plus runtime/static correlation (released as
701
- `0.6.0` - see above; orchestrator/lab-side ecosystem integration is
702
- separate sibling-repository work, not part of this repository)
703
- → v0.7 text/config-driven coding-agent change review
704
- + external visual-reference evidence foundation
705
- + structured reference-vs-candidate fidelity evaluation
706
- + end-to-end correction workflow (released as `0.7.0` - see above)
707
- → v0.8 interactive viewer with reference/candidate inspection (released as
708
- package version `0.8.0` - see "Current interactive viewer workflow" above)
709
- → v0.9 structured visual annotation on runtime screenshots and references
710
- (released as `0.9.0` - see "Current visual annotation workflow" above)
711
- → v0.10 full visual human–LLM workflow with both actual-frontend-driven and
712
- reference-driven entry modes
713
- ```
714
-
715
- ### v0.7 reference-driven correction flow (released as `0.7.0`)
716
-
717
- The non-graphical reference path, now released exactly as originally
718
- planned, is:
719
-
720
- ```text
721
- external visual reference
722
- → explicit reference identity/provenance
723
- + bounded reference regions and reusable geometry relationships
724
- + selected design requirements, tolerance semantics, and reference-
725
- evidence adequacy
726
- + explicit applicability/theme/viewport compatibility
727
- (all implemented - see "Current external-reference foundation workflow"
728
- above)
729
- → explicit reference-region ↔ runtime-target binding (implemented - v0.7
730
- Prompt 5)
731
- → candidate rendered through the existing Chromium observation engine
732
- → structured reference-vs-candidate evaluation
733
- → bounded measurable fidelity mismatches
734
- → relevant bounded runtime/static context
735
- → external coding agent modifies source
736
- → rerender
737
- → reevaluate reference fidelity
738
- + rerun before/after comparison
739
- + rerun per-change and persistent baseline contracts
740
- → PASS or actionable fidelity/regression failure
741
- ```
742
-
743
- This does not turn an imported image into an observation or approved baseline.
744
- Reference design vs candidate remains distinct from before vs after comparison.
745
- Executable reference requirements reuse the existing canonical requested/
746
- expected-dependent/protected/preserved semantics. Informational reference detail
747
- may remain non-executable. Pixel/image similarity can supplement structured
748
- geometry/relationship/style evidence where reliable, but it never becomes
749
- the only success criterion.
750
-
751
- Theme, application state, viewport, and other applicability dimensions are
752
- checked before reference fidelity is interpreted. A mismatched reference and
753
- candidate state yields an explicit incompatible/incomparable outcome rather
754
- than fabricated visual failures.
755
-
756
- The v0.7 coding-agent workflow and reference foundation are released as
757
- part of this repository and work without the v0.8 viewer or v0.9
758
- annotation system. v0.8, released as `0.8.0`, consumes the v0.7
759
- reference/evaluation model exactly as required - it does not create a second
760
- UI-only one (see "Current interactive viewer workflow" above). v0.9,
761
- released as `0.9.0`, preserves the same constraint: promotion and
762
- materialization go through the existing canonical contract and
763
- external-reference services.
764
-
765
- ## Current release workflow
766
-
767
- The published package is `@dailephd/my-frontend-observer@0.9.1`; install it
768
- with npm and use the `my-frontend-observer` CLI. The ordinary workflow is
769
- `init`, `capture baseline`, `check baseline`, then `view`. Existing sections
770
- below retain the historical low-level and viewer workflows for compatibility.
1
+ # Workflows
2
+
3
+ Cross-repository composition is centralized in [my-dev-kit's ecosystem guide](https://github.com/dailephd/my-dev-kit/blob/main/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md), especially the [command-surface compatibility map](https://github.com/dailephd/my-dev-kit/blob/main/docs/ECOSYSTEM_DEVELOPMENT_WORKFLOWS.md#915-command-surface-compatibility-map). That map covers static-to-runtime correlation, Lab tutorial/reference handoffs, Orchestrator consumption, and combinations that are deliberately not direct artifact pipes.
4
+
5
+ ## Project and coding-agent workflow
6
+
7
+ ```text
8
+ init
9
+ capture baseline
10
+ implement frontend change outside Observer
11
+ check baseline --json
12
+ if FAIL:
13
+ use returned canonical runtime failure evidence
14
+ correct frontend source outside Observer
15
+ run the identical check again
16
+ finish only after PASS
17
+ view
18
+ ```
19
+
20
+ Observer reports evidence and acceptance. The external human, coding agent, or
21
+ orchestrator edits source; Observer never does. With no executable contract or
22
+ approved reference, successful comparison yields `REVIEW_REQUIRED`, not PASS.
23
+
24
+ ## Current validation workflow
25
+
26
+ ```text
27
+ install dependencies (npm install; npx playwright install chromium)
28
+ → validate types and lint
29
+ → run the fast unit suite (npm test)
30
+ → run the real-Chromium integration suite (npm run test:browser)
31
+ → build the CLI/library entries (npm run build)
32
+ → validate documentation (npm run check:docs)
33
+ ```
34
+
35
+ ## Current observation workflow (supported in 0.9.0)
36
+
37
+ The real `observe` workflow remains supported in the current published
38
+ `my-frontend-observer@0.9.0` package. Its browser-observation behavior was
39
+ established in earlier releases; later project/viewer releases compose it
40
+ rather than replacing it. It accepts target configuration through either of
41
+ two input paths, plus one optional runtime scroll scenario:
42
+
43
+ ```text
44
+ CLI arguments (--url, --viewport, --output, --timeout, exactly one of:
45
+ one-or-more --target <id=css-selector>
46
+ or --targets-file <json-file>,
47
+ plus optionally --scroll-scenario-file <json-file>)
48
+ → (--targets-file only: read + validate the local JSON root wrapper)
49
+ → (--scroll-scenario-file only: read + validate the local JSON root shape -
50
+ a non-array object; the file supplies RawObservationRequest.scrollScenario
51
+ directly, with no wrapper field)
52
+ → request construction (same RawObservationRequest either way)
53
+ → normalizeRequest() - producing canonical {name, locators} targets and
54
+ validating the optional scrollScenario (supported action kind, delta
55
+ bounds/both-zero rule, stable target-name reference)
56
+ → application observation use case (src/application/observationPersistence.ts#observe)
57
+ → Chromium capture: launch, safe navigation, readiness, then - only if a
58
+ scenario was configured - resolve configured targets once, capture an
59
+ initial ScrollRuntimeSnapshot, perform the one immediate scroll
60
+ (window.scrollBy/element.scrollBy, behavior: "instant"), wait exactly two
61
+ requestAnimationFrame cycles, capture a final ScrollRuntimeSnapshot and
62
+ derive transition/scroll-owner evidence; then screenshot and page/target
63
+ evidence (resolving all six locator kinds through the single canonical
64
+ resolver, plus semantic state/landmark/containment evidence), from the
65
+ same live page - exactly once, always describing the final state
66
+ → atomic artifact persistence (manifest.json + screenshot.png), schema
67
+ 1.2.0 - exactly once, only on a successful capture; scrollScenarioEvidence
68
+ is simply one more optional manifest field, never a separate file
69
+ → concise CLI result (Observation/State/Artifact/Targets/Diagnostics)
70
+ → process exit status (0 for a persisted observation, including one whose
71
+ state honestly reports "partial"; nonzero otherwise)
72
+ ```
73
+
74
+ A request with no scroll scenario is unaffected: no extra snapshots, no
75
+ scroll, no extra animation-frame wait, unchanged request identity.
76
+
77
+ This is exercised by `runCli()`-level tests, real-Chromium end-to-end tests
78
+ (`tests/browser/cliObserve.test.ts`, `tests/browser/windowScrollScenario.test.ts`,
79
+ `tests/browser/targetScrollScenario.test.ts`), built `node dist/cli.js
80
+ observe ...` runs against the deterministic local fixture
81
+ (`scripts/dev/builtCliTargetsFileSmoke.mjs` for the semantic `--targets-file`
82
+ path, `scripts/dev/builtCliScrollScenarioSmoke.mjs` for the scroll-scenario
83
+ path), and the real `npm pack` tarball installed and run from a clean
84
+ temporary consumer directory outside the repository, on Windows, Linux, and
85
+ macOS (`scripts/ci/runPackedObservationSmoke.mjs`) - the same workflow,
86
+ independent of the source checkout.
87
+
88
+ ## Current comparison workflow (supported in 0.9.0)
89
+
90
+ **Current status: shipped originally as part of
91
+ `my-frontend-observer@0.4.0` and remains supported in `0.9.0`.** This is a
92
+ separate workflow from the observation workflow above - it consumes two
93
+ already-persisted observation artifacts rather than producing one, and it
94
+ never launches a browser:
95
+
96
+ ```text
97
+ two prior real "observe" invocations, each producing its own persisted
98
+ ObservationArtifact (before, after) - unrelated to this workflow itself
99
+ → CLI arguments (--before <root>, --after <root>, --output <directory>,
100
+ optionally --config-file <json-file>)
101
+ → (--config-file only: read + validate the local JSON root shape - a
102
+ non-array object; the file supplies ComparisonConfig directly, with no
103
+ wrapper field)
104
+ → read + validate both observation artifacts (src/artifacts/artifactReader.ts,
105
+ the same isValidObservationArtifact structural gate the writer uses)
106
+ → application comparison use case
107
+ (src/application/comparisonService.ts#compareAndPersistFromArtifactRoots
108
+ → compareAndPersist)
109
+ → pure comparison derivation (src/domain/comparisonEngine.ts#compareObservations):
110
+ comparability first, then - only if comparable/comparable-with-warnings -
111
+ deriveLayoutRelationships for each side plus target/page differences,
112
+ relationship changes, and explicit non-causal dependency evidence
113
+ → atomic comparison-artifact persistence (manifest.json only, no copied
114
+ screenshots), schema 1.0.0 - exactly once, for every comparability
115
+ outcome including "incomparable"
116
+ → concise CLI result (Comparison/State/Artifact/Differences/Relationship
117
+ changes/Diagnostics)
118
+ → process exit status (0 for any successfully computed and persisted
119
+ comparison, including "incomparable"; nonzero only for invalid
120
+ syntax/unreadable or invalid source artifacts/invalid configuration/a
121
+ failed write)
122
+ ```
123
+
124
+ Source observations are never modified by this workflow. Operational paths
125
+ (`--before`/`--after`/`--config-file`/`--output`) never affect
126
+ `comparisonRequestId` and are never written into the persisted manifest.
127
+
128
+ This is exercised by `runCli()`-level tests
129
+ (`tests/unit/cli.test.ts`, `tests/unit/cliCompareOrchestration.test.ts`,
130
+ `tests/unit/cliCompareEndToEnd.test.ts`), a real-Chromium end-to-end test
131
+ (`tests/browser/cliCompare.test.ts`), built `node dist/cli.js compare ...`
132
+ runs against real persisted observations from the deterministic local
133
+ fixture (`scripts/dev/builtCliCompareSmoke.mjs`), and packed-tarball
134
+ validation of the installed `compare` command
135
+ (`scripts/ci/runPackedObservationSmoke.mjs` - see `docs/CI_CD.md`).
136
+
137
+ ## Current frontend contract workflow (supported in 0.9.0)
138
+
139
+ This text/config-driven workflow shipped in `0.5.0` and remains supported in
140
+ `0.9.0`. It is layered downstream of the two workflows above - it does not
141
+ replace them. The complete v0.7 coding-agent workflow (the external-reference
142
+ evidence foundation and end-to-end correction loop) is layered on top of
143
+ it - see "Current external-reference foundation workflow" and "Current
144
+ reference correction workflow" below; baseline selection here remains
145
+ caller-supplied:
146
+
147
+ ```text
148
+ observe before
149
+ observe after
150
+ compare
151
+ ↓
152
+ approve baseline (approve-baseline --observation <before-root>
153
+ --contract-file <PersistentBaselineContract.json> --output <dir>)
154
+ ↓
155
+ save per-change contract (save-change-contract
156
+ --contract-file <PerChangeContract.json> --output <dir>)
157
+ ↓
158
+ evaluate contract (evaluate-contract --before <root> --after <root>
159
+ --comparison <root> --baseline <root> --change <root> --output <dir>
160
+ [--enforce])
161
+ ↓
162
+ persisted evaluation artifact (schema 1.0.0, its own independent family):
163
+ clause results (pass/fail/unavailable/conflict), unexpected changes,
164
+ overall PASS/FAIL
165
+ ```
166
+
167
+ `approve-baseline` is the only baseline-approval act; a successful `compare`
168
+ or a `PASS` evaluation never approves or supersedes a baseline
169
+ automatically. `evaluate-contract` never launches a browser and never
170
+ recomputes comparison/relationship evidence - it calls the canonical
171
+ `evaluateFrontendContract` exactly once against the supplied evidence and
172
+ persists exactly one evaluation artifact, whether the verdict is `PASS` or
173
+ `FAIL`. `--enforce` affects only the process exit status for a `FAIL`
174
+ verdict, never the persisted evidence itself.
175
+
176
+ This is exercised by `runCli()`-level tests
177
+ (`tests/unit/cliFrontendContracts.test.ts`), a built `node dist/cli.js`
178
+ smoke that needs no Chromium
179
+ (`scripts/dev/builtCliFrontendContractsSmoke.mjs`), a real-Chromium
180
+ end-to-end test (`tests/browser/cliFrontendContracts.test.ts`), and a
181
+ real-Chromium built-CLI smoke
182
+ (`scripts/dev/builtCliFrontendContractsBrowserSmoke.mjs` - see
183
+ `docs/DEVELOPMENT.md`). The real-browser coverage proves both a fully
184
+ successful contract change and the "milestone signature" failure (a locally
185
+ successful requested change coexisting with a genuine protected-property
186
+ regression and a genuine preserved-invariant regression) against actual
187
+ rendered geometry, not hand-constructed artifacts. It is also part of
188
+ packed-tarball validation: `scripts/ci/runPackedObservationSmoke.mjs`
189
+ exercises the installed candidate's `approve-baseline`/`save-change-contract`/
190
+ `evaluate-contract` commands against real installed-candidate `observe`/
191
+ `compare` evidence, proven on Windows, Linux, and macOS (see
192
+ `docs/CI_CD.md`).
193
+
194
+ ## Current bounded agent context workflow (released as `0.6.0`)
195
+
196
+ This is a programmatic (library-only) workflow, not a CLI command - it
197
+ consumes already-persisted v0.1-v0.5 evidence in-process rather than reading
198
+ artifact roots from disk:
199
+
200
+ ```text
201
+ already-captured evidence (ObservationArtifact(s), ComparisonArtifact,
202
+ PersistentBaselineContract/PerChangeContract, evaluation results)
203
+ → projectBoundedAgentContext(...)
204
+ (src/domain/boundedAgentContextProjection.ts)
205
+ → BoundedRuntimeTargetProjection: bounded geometry/behavior/relationships/
206
+ differences/contract-scope evidence, adequacy, omission, truncation
207
+ → deriveRuntimeStaticCorrelations(...) / attachRuntimeStaticCorrelations(...)
208
+ (src/domain/boundedAgentContextCorrelation.ts), given caller-supplied
209
+ candidate static evidence
210
+ → RuntimeStaticCorrelation[] (correlated / ambiguous / unavailable -
211
+ competing candidates remain visible, never collapsed to one owner)
212
+ → consumed programmatically via the public export surface (src/index.ts) -
213
+ by an external orchestrator or coding-agent workflow outside this
214
+ repository, not by a new my-frontend-observer CLI command
215
+ ```
216
+
217
+ This is exercised by unit tests covering the projection and correlation
218
+ modules (happy path, boundedness at exact/one-over/large-overflow limits,
219
+ immutability, malformed-input fail-closed behavior, adequacy/omission/
220
+ truncation reporting, and correlation status invariants/determinism/
221
+ deduplication). See `docs/CONTRACTS.md` "v0.6 bounded agent context and
222
+ correlation contract" for the exact shape.
223
+
224
+ **v0.7 Prompt 7 addition (released as `0.7.0`):** `projectBoundedAgentContext`
225
+ now optionally accepts an already-computed v0.7 Prompt 6
226
+ `ReferenceCandidateFidelityEvaluation` (`fidelity`) alongside its existing
227
+ v0.1-v0.5 evidence inputs - never recomputed, never a second fidelity
228
+ engine:
229
+
230
+ ```text
231
+ already-computed evaluateReferenceCandidateFidelity(...) result
232
+ → projectBoundedAgentContext({ ..., fidelity, fidelityRequired? })
233
+ → projectReferenceFidelity(...) (src/domain/referenceFidelityProjection.ts):
234
+ selects/prioritizes/bounds Prompt 6's non-passing requirement results
235
+ (failed-required, then unavailable-required, then other non-pass) plus
236
+ passing protected/preserved context, and contributes their bound v0.2
237
+ runtime target ids to the exact same required/permitted-target
238
+ allocation contract clauses already compete in
239
+ → BoundedAgentContextArtifact.fidelity: bounded mismatches/protectedContext
240
+ + adequacy/compatibility/state pass-through from Prompt 6, folded into
241
+ the same omissions/truncations/adequacy computation as every other
242
+ evidence source (a blocked "not-evaluated" fidelity is never silently
243
+ reported as "no problems")
244
+ → still consumed programmatically only, unchanged - no CLI surface
245
+ ```
246
+
247
+ Absent `fidelity`, output is unaffected - identical to the pre-Prompt-7
248
+ behavior described above, including logical identity. See
249
+ `docs/CONTRACTS.md` "v0.7 Prompt 7 bounded reference-fidelity projection and
250
+ v0.6 bounded-agent-context integration" for the full contract.
251
+
252
+ ## Current external-reference foundation workflow (released as `0.7.0`)
253
+
254
+ This is the foundation layer only - identity, provenance, bounded image
255
+ metadata, a two-state lifecycle, (Prompt 2) explicit reference regions plus
256
+ reusable geometry relationships, (Prompt 3) selected design requirements,
257
+ tolerance semantics, and reference-evidence adequacy, (Prompt 4) explicit
258
+ reference applicability (viewport/theme/application-state/authenticated-
259
+ state) and reference/candidate compatibility, and (Prompt 5) explicit
260
+ reference-region <-> runtime-target binding, for one externally supplied
261
+ design-reference image. Structured fidelity-evaluation behavior (Prompt 6)
262
+ follows further below in this section, and it never launches a browser or
263
+ reads/writes any observation, comparison, or contract artifact:
264
+
265
+ ```text
266
+ import-reference <image-file> --output <dir> [--label] [--supersedes <root>] [--regions-file <json-file>] [--requirements-file <json-file>] [--applicability-file <json-file>]
267
+ → format detection from header/magic bytes only (png/jpeg/webp; never a
268
+ caller-declared extension), dimension parsing from the same bounded header
269
+ bytes (never a pixel decode), byte-length and dimension bounds checked
270
+ → (--regions-file only: read + validate the local JSON root shape - an
271
+ object with exactly a "regions" property - then validate each region's id/
272
+ rectangle and the collection's bounds/uniqueness/image-boundary rules)
273
+ → (--requirements-file only: read + validate the local JSON root shape - an
274
+ object with exactly a "requirements" property - then validate each
275
+ requirement's category/subject/tolerance shape, compute its
276
+ content-derived requirementId, and validate the collection's bounds/
277
+ region-existence/duplicate-subject rules against the regions above)
278
+ → (--applicability-file only: read + validate the local JSON root shape -
279
+ the raw, unwrapped applicability object, no wrapper property - then
280
+ validate its optional viewport/theme/applicationState/authenticatedState
281
+ fields; caller-declared only, never inferred from the image)
282
+ → (--supersedes only: read + validate the referenced prior external-reference
283
+ artifact through the same reader the writer's counterpart uses)
284
+ → deterministic referenceRequestId (pure function of {imageSha256, format,
285
+ width, height, supersedesReferenceId, regions?, requirements?,
286
+ applicability?} only) + fresh referenceId
287
+ → atomic persistence of one "imported" ExternalReferenceArtifact:
288
+ manifest.json (+ regions/requirements/applicability, when supplied) + its
289
+ own copy of the reference image, schema 1.0.0 - lifecycle.state is always
290
+ "imported"; import never approves
291
+ ↓
292
+ approve-reference --reference <imported-artifact-root> --output <dir> [--supersedes <root>]
293
+ → read + validate the target through the existing reader; refuse anything
294
+ not currently in the "imported" lifecycle state
295
+ → persist a brand-new "approved" ExternalReferenceArtifact instance (same
296
+ referenceRequestId, fresh referenceId) carrying a sourceReference back to
297
+ the imported artifact's image - no image bytes are copied again, any
298
+ regions/requirements/applicability are carried forward verbatim (never
299
+ re-validated/re-derived), and the imported artifact's own manifest is
300
+ never modified
301
+ ```
302
+
303
+ `approve-reference` is the only explicit reference-approval act - it is never
304
+ inferred from a successful import. Supersession (`--supersedes`) is
305
+ represented only as a forward pointer on the newer artifact; the artifact it
306
+ supersedes is never rewritten, so prior reference evidence remains immutable
307
+ regardless of how many later references supersede it. Region/requirement/
308
+ applicability content (added/removed/moved/resized/renamed regions;
309
+ added/removed/changed requirements or tolerances; a changed applicability
310
+ declaration) is identity-bearing, so a differently-structured reference is
311
+ always a distinct logical reference, never a silent rewrite of an existing
312
+ one.
313
+
314
+ Separately, `observe` gained an optional `--state-file <json-file>` (the
315
+ raw, unwrapped `{theme?, applicationState?, authenticatedState?}` object -
316
+ caller-declared only, never inferred), persisted as
317
+ `requestConfig.explicitState` on the resulting `ObservationArtifact` and
318
+ folded into that observation's own request identity. A pure, synchronous
319
+ domain function, `evaluateReferenceCandidateCompatibility(reference,
320
+ candidate)`, then answers "does this reference describe the same frontend
321
+ state as this candidate observation?" by comparing
322
+ `reference.applicability` against `candidate.requestConfig`
323
+ (viewport/explicitState) - reusing v0.4's own comparability result/reason
324
+ vocabulary and its underlying per-dimension comparison rule rather than
325
+ inventing a parallel model. This produces no persisted artifact of its own;
326
+ it is a pure function callers invoke on two already-persisted artifacts. See
327
+ `docs/CONTRACTS.md` "v0.7 Prompt 4 reference applicability and
328
+ candidate-state compatibility" for the full contract.
329
+
330
+ Building on that gate, a second pure, synchronous domain function,
331
+ `evaluateReferenceRuntimeBindings(reference, candidate, declarations)`,
332
+ answers "which stable v0.2 runtime target does this candidate resolve for
333
+ each explicitly declared reference region?" `declarations` is explicit
334
+ user/configuration input (`{referenceRegion, runtimeTarget}` pairs) - never
335
+ inferred from geometry, matching names, or source code. It runs the Prompt
336
+ 4 compatibility gate first (reused, never duplicated): an `incomparable`
337
+ reference/candidate pair produces zero evaluated bindings, the blocker
338
+ visible only through the embedded `compatibility` field. Otherwise each
339
+ declaration is resolved against the candidate's own already-captured
340
+ `requestConfig.targets`/`targetEvidence` only - no browser, no second
341
+ target resolver - using the same `targetPresence` classification v0.4's own
342
+ `evaluateComparability` already relies on, yielding `bound`/`ambiguous`/
343
+ `unavailable` per declaration. Like compatibility, this produces no
344
+ persisted artifact of its own and mutates neither the reference nor the
345
+ candidate. See `docs/CONTRACTS.md` "v0.7 Prompt 5 explicit reference-region
346
+ <-> runtime-target binding" for the full contract.
347
+
348
+ Reference-region relationships (`deriveReferenceRegionRelationships()`) are
349
+ a separate, pure, on-demand derivation over an artifact's own `regions` -
350
+ not part of the persisted manifest - reusing the same geometry-only
351
+ relationship families (`left-of`/`above`/`overlaps`/`wider-than`/
352
+ `fits-inside`/`follows-vertically`, etc.) that
353
+ `deriveLayoutRelationships` derives for runtime targets. A reference
354
+ relationship is a fact about the reference image's geometry only, never a
355
+ design requirement or a pass/fail verdict.
356
+
357
+ Selected design requirements (`ExternalReferenceRequirement`) are the
358
+ explicit user/configuration layer on top of that reference evidence - a
359
+ region property, a region-to-region relationship, or a derived two-region
360
+ measurement, tagged with one of v0.5's four authored categories
361
+ (`requested`/`expected-dependent`/`protected`/`preserved`) and (except for
362
+ relationship subjects) a reference-image-pixel or percent tolerance. Nothing
363
+ promotes a property or relationship to a requirement automatically.
364
+ Reference-evidence adequacy (`deriveReferenceRequirementAdequacy()`) reports
365
+ only whether the reference side itself supports every selected requirement -
366
+ `adequate`/`partial`/`inadequate`, never a numeric score, never a claim
367
+ about runtime/candidate availability.
368
+
369
+ Finally, `evaluate-reference-fidelity --reference <root> --candidate <root>
370
+ [--bindings-file <json-file>] [--enforce]` is the first command in this
371
+ stack that actually compares a reference's selected requirements against
372
+ live candidate evidence:
373
+
374
+ ```text
375
+ evaluate-reference-fidelity --reference <root> --candidate <root> [--bindings-file <json-file>] [--enforce]
376
+ → (--bindings-file only: read + validate the local JSON root shape - an
377
+ object with exactly a "bindings" property - the still-unvalidated
378
+ declarations are handed straight through)
379
+ → read the reference and candidate artifacts through their existing readers
380
+ → evaluateReferenceCandidateFidelity(reference, candidate, bindings):
381
+ reference/candidate/binding-declaration structural validation
382
+ → Prompt 3 reference adequacy (inadequate -> "not-evaluated", no
383
+ ordinary result fabricated)
384
+ → Prompt 4 compatibility (incomparable -> "not-evaluated")
385
+ → Prompt 5 binding evaluation (ambiguous/unavailable/undeclared binding ->
386
+ the dependent requirement is "unavailable", never guessed)
387
+ → per requirement: reference-image-pixel <-> CSS-pixel coordinate mapping
388
+ (from reference.applicability.viewport and the image's own dimensions;
389
+ no viewport or an incoherent aspect ratio -> numeric requirements
390
+ "unavailable", never a fabricated result) then a Prompt-3-tolerance
391
+ comparison (region-property/region-measurement subjects) or a
392
+ family-scoped v0.4 relationship comparison (region-relationship
393
+ subjects)
394
+ → overall state: "pass" only when every requirement result is "pass";
395
+ any "fail"/"unavailable" forces "fail"
396
+ ```
397
+
398
+ This produces no persisted artifact - the structured result exists only for
399
+ this invocation, printed as a concise summary (reference adequacy,
400
+ compatibility state, overall fidelity state, and a pass/fail/unavailable
401
+ requirement breakdown). `--enforce` mirrors `evaluate-contract`'s exact
402
+ precedent: it changes only the process exit status for an already-computed
403
+ `fail` result, never its content, and never affects a `not-evaluated`
404
+ result (always exits 0 - a blocked evaluation is a successful, honest
405
+ outcome, not a design mismatch). See `docs/CONTRACTS.md` "v0.7 Prompt 6
406
+ structured reference-vs-candidate fidelity evaluation" for the full
407
+ contract.
408
+
409
+ This is exercised by unit tests covering the pure image-format/dimension
410
+ boundary, region geometry/validation, reference-region relationship
411
+ derivation, requirement validation/measurement derivation/reference-
412
+ expectation derivation/adequacy, identity (including region- and
413
+ requirement-content/order sensitivity), the domain validator, writer/reader
414
+ round-trip symmetry, the application-level import/approve use cases,
415
+ coordinate-mapping/tolerance/relationship fidelity evaluation (every
416
+ behavior in the Prompt 6 report's behavior model, including the exact
417
+ worked 2x-scale example from the task specification), and `runCli()`-level
418
+ CLI coverage (no Chromium involved - see `tests/unit/externalReference*.test.ts`,
419
+ `tests/unit/cliExternalReference.test.ts`, and
420
+ `tests/unit/cliEvaluateReferenceFidelity.test.ts`).
421
+
422
+ ## Current reference correction workflow (released as `0.7.0`)
423
+
424
+ The first complete, controlled correction cycle - a programmatic (library-
425
+ only) workflow, exactly like the v0.6 bounded-context workflow above, with
426
+ one explicit, un-automatable seam where an external implementation actor
427
+ edits target source:
428
+
429
+ ```text
430
+ approved ExternalReferenceArtifact + approved baseline ObservationArtifact
431
+ + active PersistentBaselineContract + PerChangeContract + binding
432
+ declarations + current (pre-change) ObservationArtifact
433
+ → prepareReferenceCorrection(...) (src/domain/referenceCorrectionWorkflow.ts)
434
+ → evaluateReferenceCandidateFidelity(...) (v0.7 Prompt 6, reused)
435
+ → not-evaluated (inadequate reference / incompatible state)?
436
+ → { status: 'blocked-not-evaluated' } - no fabricated handoff
437
+ → otherwise: projectBoundedAgentContext({ ..., fidelity }) (v0.7 Prompt 7/v0.6, reused)
438
+ → { status: 'handoff-ready', handoff: ReferenceCorrectionHandoff }
439
+ ↓
440
+ EXTERNAL implementation actor edits target source (never observer code)
441
+ ↓
442
+ fresh real-Chromium candidate ObservationArtifact
443
+ (existing observe()/runBrowserCapture pipeline, reused unchanged)
444
+ ↓
445
+ reviewReferenceCorrectionAttempt(...)
446
+ → compareObservations(baseline, candidate) (v0.4, reused)
447
+ → evaluateReferenceCandidateFidelity(reference, candidate, bindings) (Prompt 6, reused)
448
+ → evaluateFrontendContract({ before: baseline, after: candidate, comparison, baseline: baselineContract, change: changeContract }) (v0.5, reused)
449
+ → overall: 'not-evaluated' iff fidelity not-evaluated; else 'pass' iff
450
+ fidelity PASS AND contract evaluation PASS; else 'fail'
451
+ ↓
452
+ FAIL? → prepareReferenceCorrection(..., currentObservation: <this failed candidate>)
453
+ derives a FRESH bounded handoff from the newest failed evidence
454
+ ↓
455
+ external correction → fresh candidate → review again (caller-controlled, never automatic)
456
+ ↓
457
+ PASS? → approvalEligible: true (a plain flag) - explicit
458
+ approve-baseline/approve-reference remain the caller's own,
459
+ separate, unautomated actions
460
+ ```
461
+
462
+ Every attempt (`reviewReferenceCorrectionAttempt` call) evaluates against
463
+ the *same* supplied approved baseline - there is no attempt-to-attempt
464
+ comparison path - and `reviewRequestId` (a deterministic hash of
465
+ `{referenceRequestId, baselineObservationId, baselineContractId,
466
+ baselineContractClauses, changeContractId, changeContractClauses,
467
+ bindingDeclarations}`) is recomputed and checked on every review call. The
468
+ contract clause contents are identity-bearing as well as the caller-authored
469
+ contract ids, so a same-id contract with different clauses cannot be silently
470
+ substituted between attempts. Attempt identity (`attemptId`, a deterministic
471
+ hash of `{reviewRequestId, candidateObservationId}`) distinguishes every
472
+ candidate execution without ever using a timestamp; because both workflow
473
+ functions are pure, a returned attempt result can never be overwritten by a
474
+ later call - callers that keep every result they receive have a complete,
475
+ immutable attempt history for free.
476
+
477
+ This is exercised by unit tests covering preparation (valid handoff,
478
+ unapproved-reference rejection, inadequate-reference and incompatible-state
479
+ blocking, ambiguous-binding handling, review-identity determinism),
480
+ attempt review (all four overall-composition cases - both PASS, reference
481
+ FAIL, contract FAIL including a protected regression, and not-evaluated -
482
+ plus reviewRequestId coherence, attempt-identity determinism/distinctness,
483
+ `priorAttemptId` traceability, and input immutability), and a real-Chromium
484
+ end-to-end suite (`tests/browser/referenceCorrectionWorkflow.test.ts`)
485
+ proving: an initial genuine design mismatch measured against real rendered
486
+ geometry; a controlled, deterministic, test-only "external actor" (living
487
+ entirely outside `src/`) editing a disposable copy of a tracked HTML
488
+ fixture template and the observer capturing the change through the
489
+ unmodified real browser pipeline; a full success correction; a protected-
490
+ regression case where the candidate visually satisfies the reference but a
491
+ real Chromium-observed element becomes hidden, still producing overall
492
+ `FAIL`; a two-attempt correction iteration with both attempts remaining
493
+ distinct and traceable to the same baseline; and a blocking case
494
+ (incompatible reference/candidate viewport) that never produces a handoff.
495
+ The tracked fixture template is verified byte-identical before and after
496
+ the proof - only its disposable, repository-local copy is ever edited. See
497
+ `docs/CONTRACTS.md` "v0.7 Prompt 8 controlled end-to-end external-reference
498
+ coding-agent correction workflow" for the full contract.
499
+
500
+ ## Current interactive viewer workflow (v0.8, released as `0.8.0`)
501
+
502
+ v0.7 (text/config-driven coding-agent change review, the external
503
+ visual-reference evidence foundation, structured reference-vs-candidate
504
+ fidelity evaluation, and the end-to-end correction workflow) is released as
505
+ package version `0.7.0` - see "Current external-reference foundation
506
+ workflow" and "Current reference correction workflow" above, and
507
+ `docs/CURRENT_STATE.md` for release state. v0.8 adds an interactive local
508
+ viewer over that same evidence, released as package version `0.8.0`:
509
+
510
+ ```text
511
+ my-frontend-observer view --root <evidence-root>
512
+ [--bindings-file <json-file>] [--context-file <json-file>]
513
+ → one loopback-only (127.0.0.1) Node server, default port 4319
514
+ → metadata-first evidence discovery (GET /api/index)
515
+ → canonical artifact readers, on-demand (full artifact/media fetched only
516
+ once explicitly selected)
517
+ → viewer modes:
518
+ observation (screenshot + SVG target overlays, geometry/semantics/
519
+ visibility/overflow/scroll/relationships)
520
+ comparison/contracts (before/after side-by-side, clause results, overall
521
+ verdict)
522
+ reference/candidate (reference image + region overlays, explicit
523
+ candidate selection, compatibility/adequacy/applicability)
524
+ bounded context (only when --context-file was supplied)
525
+ → served to a normal browser or an installed Progressive Web App
526
+ ```
527
+
528
+ Where `--bindings-file` is supplied:
529
+
530
+ ```text
531
+ --bindings-file { "bindings": [{ "referenceRegion", "runtimeTarget" }] }
532
+ → explicit binding evaluation (evaluateReferenceRuntimeBindings, the same
533
+ canonical function evaluate-reference-fidelity uses)
534
+ → binding-driven cross-selection (selecting a bound reference region
535
+ highlights every runtime target it names; selecting a bound runtime
536
+ target highlights every reference region that names it)
537
+ → on-demand fidelity evaluation ("Evaluate Fidelity" action, never
538
+ automatic), shown independently alongside any selected contract
539
+ evaluation - neither overrides the other
540
+ ```
541
+
542
+ Where `--context-file` is supplied:
543
+
544
+ ```text
545
+ --context-file <one BoundedAgentContextArtifact value, no wrapper>
546
+ → canonical bounded-context inspection: identity, adequacy, omissions/
547
+ truncations (required loss visually distinct from optional loss),
548
+ runtime/static correlation (correlated/ambiguous/unavailable)
549
+ → provenance: exact-identity resolution of the context's source references
550
+ against the current evidence root
551
+ → safe navigation to the raw structured evidence behind a resolved source
552
+ ```
553
+
554
+ The viewer is optional: every CLI/programmatic workflow above remains
555
+ independently functional without it. The viewer never modifies target
556
+ source or any Observer evidence artifact; never runs
557
+ `@dailephd/my-dev-kit`; never rebuilds a bounded context
558
+ (`projectBoundedAgentContext` is not called at runtime) or its correlation
559
+ (`deriveRuntimeStaticCorrelations`/`attachRuntimeStaticCorrelations` are not
560
+ called at runtime) - it only displays the exact context and bindings it was
561
+ started with. See `docs/COMMANDS.md#view` for the full flag reference and
562
+ `docs/ARCHITECTURE.md` "v0.8 Batch 1" through "v0.8 Batch 8" for the
563
+ implementation record.
564
+
565
+ ## Current visual annotation workflow (released in 0.9.0)
566
+
567
+ v0.9 visual annotation is released in `@dailephd/my-frontend-observer@0.9.0`.
568
+ Authoring works only in the
569
+ project-aware viewer (`my-frontend-observer view` inside an initialized
570
+ project). `view --root <root>` inspects the same evidence read-only.
571
+
572
+ ### Runtime visual flow
573
+
574
+ ```text
575
+ project-aware view
576
+ → select a runtime observation
577
+ → draw a point, rectangle, line, arrow, or note (runtime CSS pixels)
578
+ → explicitly associate a runtime target or canonical runtime relationship
579
+ → choose candidate intent (inspect, move, resize, remove, or preserve)
580
+ → explicitly confirm the intent
581
+ → save an immutable VisualAnnotationArtifact
582
+ → select confirmed supported intent (move, resize, or preserve)
583
+ → promote into a normal canonical PerChangeContract
584
+ → optionally, explicitly activate that contract for project check
585
+ → existing check and the existing contract evaluator produce the verdict
586
+ ```
587
+
588
+ Notes and `inspect` intent stay informational. A free mark with no explicit
589
+ association never becomes a target association or a contract clause.
590
+ Confirmed `remove` intent is saved but cannot be promoted, because the current
591
+ contract vocabulary has no target-absent primitive. The promotion categories
592
+ are the existing requested, expected-dependent, protected, and preserved
593
+ categories. `unexpected` stays evaluator-derived.
594
+
595
+ ### Reference visual flow
596
+
597
+ ```text
598
+ project-aware view
599
+ → select an imported or approved external reference
600
+ → draw marks (reference-image pixels)
601
+ → explicitly associate a reference region or canonical region relationship
602
+ → choose a candidate region create or refine, or a candidate reference
603
+ requirement (region-property, region-relationship, or region-measurement)
604
+ → explicitly confirm the intent
605
+ → save an immutable VisualAnnotationArtifact
606
+ → select confirmed materializable items
607
+ → materialize a new imported external-reference revision that supersedes the
608
+ source reference
609
+ → explicit approval stays separate (the existing approve-reference command)
610
+ ```
611
+
612
+ Informational and asset-sensitive intent is never materialized. The source
613
+ reference and its image are never changed. The new revision reuses the exact
614
+ source image bytes, keeps the source regions, requirements, applicability, and
615
+ label, and is never approved automatically. Project reference acceptance is
616
+ not changed.
617
+
618
+ ### Revisions and missing sources
619
+
620
+ Editing a saved annotation and saving again creates a child revision that
621
+ supersedes its parent. Saving another child from a stale parent fails with a
622
+ conflict and keeps the draft. If a saved annotation's source evidence
623
+ disappears, the annotation stays inspectable and its source is reported as
624
+ `unavailable`. No replacement source is guessed.
625
+
626
+ v0.10 correction orchestration (automatic coding-agent runs, rerender loops,
627
+ and automatic approvals) is not implemented.
628
+
629
+ ## Developer tutorial-generation workflow (v0.9 demo, not a product command)
630
+
631
+ This is a contributor workflow for producing the v0.9 tutorial videos. It is
632
+ not part of the product, and Observer has no `tutorial` command.
633
+
634
+ ```text
635
+ Observer demo and scenario (examples/v09-demo/)
636
+ ↓
637
+ generate TutorialTargetContractV1 (generate-tutorial-target.mjs)
638
+ ↓
639
+ my-dev-kit-lab tutorial validate
640
+ ↓
641
+ my-dev-kit-lab tutorial run
642
+ ↓
643
+ disposable target (prepared through canonical Observer commands)
644
+ ↓
645
+ WebM + screenshots + SRT/VTT + Markdown + manifest
646
+ ```
647
+
648
+ Ownership boundary:
649
+
650
+ 1. Observer owns the demo application, the four scenario files, the
651
+ target-contract generator, and the prepare command. Prepare builds each
652
+ disposable project only through the canonical Observer CLI: `init`,
653
+ `capture baseline`, `approve-baseline`, `save-change-contract`,
654
+ `import-reference`, and `approve-reference`, as the scenario needs.
655
+ 2. `@dailephd/my-dev-kit-lab@0.4.9` owns everything tutorial-specific: scenario
656
+ validation, process lifecycle, the browser session, the cursor, callouts,
657
+ video recording, subtitles, Markdown, and the tutorial manifest. It is an
658
+ external tool run through `npx`, not an Observer dependency.
659
+ 3. The tutorial drives the ordinary project-aware viewer through real pointer,
660
+ keyboard and select input. Native `<select>` values are chosen with the
661
+ lab's `select-option` action, which names the HTML option value, so no step
662
+ depends on how a platform steps a dropdown. Correctness is proved by reading
663
+ the canonical evidence the run wrote into the disposable target, not by the
664
+ video.
665
+
666
+ Steps:
667
+
668
+ ```powershell
669
+ npm run build
670
+ node examples/v09-demo/scripts/generate-tutorial-target.mjs `
671
+ --scenario observer-v09-runtime-contract `
672
+ --out .my-dev-kit-workflow/adhoc/target-contract.json
673
+ npx --yes @dailephd/my-dev-kit-lab@0.4.9 tutorial validate `
674
+ --scenario examples/v09-demo/tutorials/02-runtime-intent-contract.json `
675
+ --target-contract .my-dev-kit-workflow/adhoc/target-contract.json --json
676
+ npx --yes @dailephd/my-dev-kit-lab@0.4.9 tutorial run `
677
+ --scenario examples/v09-demo/tutorials/02-runtime-intent-contract.json `
678
+ --target-contract .my-dev-kit-workflow/adhoc/target-contract.json `
679
+ --out <run directory outside the repository> --json
680
+ ```
681
+
682
+ Generate the contract immediately before each run, because its loopback ports
683
+ are only known to be free when they are chosen. Send `--out` outside the
684
+ repository. The run result's `status` must be `passed` and its
685
+ `cleanupErrors` must be empty. The demo and scenarios are not in the npm
686
+ package. See `examples/v09-demo/README.md` for details and maintenance notes.
687
+
688
+ ## Complete v0.10 visual-change workflow (released)
689
+
690
+ The sequence on top of the v0.7/v0.8 foundation above preserves the current
691
+ engines and lets graphical interfaces consume rather than invent the reference
692
+ model. v0.9 is released as `0.9.0`; v0.10 is implemented in the repository
693
+ and is released as `0.10.0`.
694
+
695
+ Actual-frontend entry starts in project-aware `view`: open a runtime
696
+ observation, draw and explicitly associate a mark, author and confirm runtime
697
+ intent, save it, select confirmed intent, and create an inactive visual-change
698
+ workflow. Reference entry opens one exact approved reference, saves confirmed
699
+ reference intent against that instance, selects an exact baseline observation,
700
+ authors explicit region-to-runtime bindings, and creates an inactive reference
701
+ workflow.
702
+
703
+ Both modes then share the same human-controlled loop:
704
+
705
+ ```text
706
+ explicit Activate
707
+ -> Prepare handoff
708
+ -> external actor edits source outside Observer
709
+ -> Run check (the canonical check <baseline> --json operation)
710
+ -> immutable pending attempt
711
+ -> Request correction, Accept latest PASS, or Abandon
712
+ -> optional governance recording only after a separate canonical approval
713
+ -> optional explicit Restore acceptance
714
+ ```
715
+
716
+ The controlling invariants are `DRAW != DECIDE`, `CONFIRM !=
717
+ PROMOTE/MATERIALIZE`, `PROMOTE/MATERIALIZE != ACTIVATE`, `PASS != ACCEPT`, and
718
+ `ACCEPT != GOVERNANCE`.
719
+
720
+ Project-aware `check` reads and validates its selected immutable baseline
721
+ before capturing `current`. It keeps URL, viewport, targets, and ordinary
722
+ capture settings from `frontend-observer.json`, while replaying only the
723
+ baseline observation's optional `scrollScenario` and caller-declared
724
+ `explicitState` through the canonical request and browser capture path. The
725
+ project config schema, `init`, and normal `capture` do not accept those
726
+ low-level fields. `explicitState` replay preserves the baseline's comparison
727
+ identity only; it does not establish theme, application, or authentication
728
+ state in the browser.
729
+
730
+ ```text
731
+ stable targets and bounded runtime behavior
732
+ → relationships and before/after comparison (released - see above)
733
+ → safe-change contracts (contract model, evaluation, persistence, and CLI
734
+ released as 0.5.0 - see above; baseline approval remains a single explicit
735
+ command, not a policy engine)
736
+ → bounded agent context plus runtime/static correlation (released as
737
+ `0.6.0` - see above; orchestrator/lab-side ecosystem integration is
738
+ separate sibling-repository work, not part of this repository)
739
+ → v0.7 text/config-driven coding-agent change review
740
+ + external visual-reference evidence foundation
741
+ + structured reference-vs-candidate fidelity evaluation
742
+ + end-to-end correction workflow (released as `0.7.0` - see above)
743
+ → v0.8 interactive viewer with reference/candidate inspection (released as
744
+ package version `0.8.0` - see "Current interactive viewer workflow" above)
745
+ → v0.9 structured visual annotation on runtime screenshots and references
746
+ (released as `0.9.0` - see "Current visual annotation workflow" above)
747
+ → v0.10 full visual human–LLM workflow with both actual-frontend-driven and
748
+ reference-driven entry modes
749
+ ```
750
+
751
+ ### v0.7 reference-driven correction flow (released as `0.7.0`)
752
+
753
+ The non-graphical reference path, now released exactly as originally
754
+ planned, is:
755
+
756
+ ```text
757
+ external visual reference
758
+ → explicit reference identity/provenance
759
+ + bounded reference regions and reusable geometry relationships
760
+ + selected design requirements, tolerance semantics, and reference-
761
+ evidence adequacy
762
+ + explicit applicability/theme/viewport compatibility
763
+ (all implemented - see "Current external-reference foundation workflow"
764
+ above)
765
+ → explicit reference-region ↔ runtime-target binding (implemented - v0.7
766
+ Prompt 5)
767
+ → candidate rendered through the existing Chromium observation engine
768
+ → structured reference-vs-candidate evaluation
769
+ → bounded measurable fidelity mismatches
770
+ → relevant bounded runtime/static context
771
+ → external coding agent modifies source
772
+ → rerender
773
+ → reevaluate reference fidelity
774
+ + rerun before/after comparison
775
+ + rerun per-change and persistent baseline contracts
776
+ → PASS or actionable fidelity/regression failure
777
+ ```
778
+
779
+ This does not turn an imported image into an observation or approved baseline.
780
+ Reference design vs candidate remains distinct from before vs after comparison.
781
+ Executable reference requirements reuse the existing canonical requested/
782
+ expected-dependent/protected/preserved semantics. Informational reference detail
783
+ may remain non-executable. Pixel/image similarity can supplement structured
784
+ geometry/relationship/style evidence where reliable, but it never becomes
785
+ the only success criterion.
786
+
787
+ Theme, application state, viewport, and other applicability dimensions are
788
+ checked before reference fidelity is interpreted. A mismatched reference and
789
+ candidate state yields an explicit incompatible/incomparable outcome rather
790
+ than fabricated visual failures.
791
+
792
+ The v0.7 coding-agent workflow and reference foundation are released as
793
+ part of this repository and work without the v0.8 viewer or v0.9
794
+ annotation system. v0.8, released as `0.8.0`, consumes the v0.7
795
+ reference/evaluation model exactly as required - it does not create a second
796
+ UI-only one (see "Current interactive viewer workflow" above). v0.9,
797
+ released as `0.9.0`, preserves the same constraint: promotion and
798
+ materialization go through the existing canonical contract and
799
+ external-reference services.
800
+
801
+ ## Current release workflow
802
+
803
+ The current published package is `@dailephd/my-frontend-observer@0.10.1`; install it
804
+ with npm and use the `my-frontend-observer` CLI. The ordinary workflow is
805
+ `init`, `capture baseline`, `check baseline`, then `view`. Existing sections
806
+ below retain the historical low-level and viewer workflows for compatibility.