@dailephd/my-frontend-observer 0.8.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 (316) hide show
  1. package/CHANGELOG.md +397 -0
  2. package/LICENSE +21 -0
  3. package/README.md +255 -0
  4. package/dist/application/browserCaptureService.d.ts +11 -0
  5. package/dist/application/browserCaptureService.js +12 -0
  6. package/dist/application/browserCaptureService.js.map +1 -0
  7. package/dist/application/comparisonService.d.ts +56 -0
  8. package/dist/application/comparisonService.js +77 -0
  9. package/dist/application/comparisonService.js.map +1 -0
  10. package/dist/application/externalReferencePersistenceService.d.ts +75 -0
  11. package/dist/application/externalReferencePersistenceService.js +182 -0
  12. package/dist/application/externalReferencePersistenceService.js.map +1 -0
  13. package/dist/application/frontendContractEvaluationService.d.ts +49 -0
  14. package/dist/application/frontendContractEvaluationService.js +112 -0
  15. package/dist/application/frontendContractEvaluationService.js.map +1 -0
  16. package/dist/application/frontendContractPersistenceService.d.ts +56 -0
  17. package/dist/application/frontendContractPersistenceService.js +91 -0
  18. package/dist/application/frontendContractPersistenceService.js.map +1 -0
  19. package/dist/application/observationPersistence.d.ts +59 -0
  20. package/dist/application/observationPersistence.js +79 -0
  21. package/dist/application/observationPersistence.js.map +1 -0
  22. package/dist/application/projectCheckService.d.ts +3 -0
  23. package/dist/application/projectCheckService.js +169 -0
  24. package/dist/application/projectCheckService.js.map +1 -0
  25. package/dist/application/projectWorkflowService.d.ts +46 -0
  26. package/dist/application/projectWorkflowService.js +92 -0
  27. package/dist/application/projectWorkflowService.js.map +1 -0
  28. package/dist/application/referenceFidelityEvaluationService.d.ts +28 -0
  29. package/dist/application/referenceFidelityEvaluationService.js +45 -0
  30. package/dist/application/referenceFidelityEvaluationService.js.map +1 -0
  31. package/dist/artifacts/artifactReader.d.ts +19 -0
  32. package/dist/artifacts/artifactReader.js +36 -0
  33. package/dist/artifacts/artifactReader.js.map +1 -0
  34. package/dist/artifacts/artifactWriter.d.ts +25 -0
  35. package/dist/artifacts/artifactWriter.js +68 -0
  36. package/dist/artifacts/artifactWriter.js.map +1 -0
  37. package/dist/artifacts/comparisonArtifactReader.d.ts +18 -0
  38. package/dist/artifacts/comparisonArtifactReader.js +35 -0
  39. package/dist/artifacts/comparisonArtifactReader.js.map +1 -0
  40. package/dist/artifacts/comparisonArtifactWriter.d.ts +41 -0
  41. package/dist/artifacts/comparisonArtifactWriter.js +67 -0
  42. package/dist/artifacts/comparisonArtifactWriter.js.map +1 -0
  43. package/dist/artifacts/externalReferenceArtifactReader.d.ts +18 -0
  44. package/dist/artifacts/externalReferenceArtifactReader.js +35 -0
  45. package/dist/artifacts/externalReferenceArtifactReader.js.map +1 -0
  46. package/dist/artifacts/externalReferenceArtifactWriter.d.ts +44 -0
  47. package/dist/artifacts/externalReferenceArtifactWriter.js +77 -0
  48. package/dist/artifacts/externalReferenceArtifactWriter.js.map +1 -0
  49. package/dist/artifacts/frontendContractArtifactReader.d.ts +24 -0
  50. package/dist/artifacts/frontendContractArtifactReader.js +47 -0
  51. package/dist/artifacts/frontendContractArtifactReader.js.map +1 -0
  52. package/dist/artifacts/frontendContractArtifactWriter.d.ts +34 -0
  53. package/dist/artifacts/frontendContractArtifactWriter.js +70 -0
  54. package/dist/artifacts/frontendContractArtifactWriter.js.map +1 -0
  55. package/dist/artifacts/frontendContractEvaluationArtifactReader.d.ts +17 -0
  56. package/dist/artifacts/frontendContractEvaluationArtifactReader.js +34 -0
  57. package/dist/artifacts/frontendContractEvaluationArtifactReader.js.map +1 -0
  58. package/dist/artifacts/frontendContractEvaluationArtifactWriter.d.ts +32 -0
  59. package/dist/artifacts/frontendContractEvaluationArtifactWriter.js +58 -0
  60. package/dist/artifacts/frontendContractEvaluationArtifactWriter.js.map +1 -0
  61. package/dist/artifacts/types.d.ts +17 -0
  62. package/dist/artifacts/types.js +2 -0
  63. package/dist/artifacts/types.js.map +1 -0
  64. package/dist/browser/chromiumAdapter.d.ts +21 -0
  65. package/dist/browser/chromiumAdapter.js +204 -0
  66. package/dist/browser/chromiumAdapter.js.map +1 -0
  67. package/dist/browser/evidenceCapture.d.ts +62 -0
  68. package/dist/browser/evidenceCapture.js +500 -0
  69. package/dist/browser/evidenceCapture.js.map +1 -0
  70. package/dist/browser/scrollCapture.d.ts +32 -0
  71. package/dist/browser/scrollCapture.js +163 -0
  72. package/dist/browser/scrollCapture.js.map +1 -0
  73. package/dist/browser/types.d.ts +24 -0
  74. package/dist/browser/types.js +2 -0
  75. package/dist/browser/types.js.map +1 -0
  76. package/dist/cli.d.ts +8 -0
  77. package/dist/cli.js +2411 -0
  78. package/dist/cli.js.map +1 -0
  79. package/dist/domain/boundedAgentContext.d.ts +226 -0
  80. package/dist/domain/boundedAgentContext.js +355 -0
  81. package/dist/domain/boundedAgentContext.js.map +1 -0
  82. package/dist/domain/boundedAgentContextCorrelation.d.ts +74 -0
  83. package/dist/domain/boundedAgentContextCorrelation.js +441 -0
  84. package/dist/domain/boundedAgentContextCorrelation.js.map +1 -0
  85. package/dist/domain/boundedAgentContextIdentity.d.ts +26 -0
  86. package/dist/domain/boundedAgentContextIdentity.js +69 -0
  87. package/dist/domain/boundedAgentContextIdentity.js.map +1 -0
  88. package/dist/domain/boundedAgentContextProjection.d.ts +71 -0
  89. package/dist/domain/boundedAgentContextProjection.js +477 -0
  90. package/dist/domain/boundedAgentContextProjection.js.map +1 -0
  91. package/dist/domain/comparison.d.ts +220 -0
  92. package/dist/domain/comparison.js +350 -0
  93. package/dist/domain/comparison.js.map +1 -0
  94. package/dist/domain/comparisonEngine.d.ts +76 -0
  95. package/dist/domain/comparisonEngine.js +734 -0
  96. package/dist/domain/comparisonEngine.js.map +1 -0
  97. package/dist/domain/comparisonIdentity.d.ts +13 -0
  98. package/dist/domain/comparisonIdentity.js +46 -0
  99. package/dist/domain/comparisonIdentity.js.map +1 -0
  100. package/dist/domain/completion.d.ts +30 -0
  101. package/dist/domain/completion.js +22 -0
  102. package/dist/domain/completion.js.map +1 -0
  103. package/dist/domain/diagnostics.d.ts +17 -0
  104. package/dist/domain/diagnostics.js +77 -0
  105. package/dist/domain/diagnostics.js.map +1 -0
  106. package/dist/domain/evidence.d.ts +29 -0
  107. package/dist/domain/evidence.js +59 -0
  108. package/dist/domain/evidence.js.map +1 -0
  109. package/dist/domain/explicitState.d.ts +40 -0
  110. package/dist/domain/explicitState.js +54 -0
  111. package/dist/domain/explicitState.js.map +1 -0
  112. package/dist/domain/externalReference.d.ts +158 -0
  113. package/dist/domain/externalReference.js +167 -0
  114. package/dist/domain/externalReference.js.map +1 -0
  115. package/dist/domain/externalReferenceApplicability.d.ts +43 -0
  116. package/dist/domain/externalReferenceApplicability.js +52 -0
  117. package/dist/domain/externalReferenceApplicability.js.map +1 -0
  118. package/dist/domain/externalReferenceCompatibility.d.ts +40 -0
  119. package/dist/domain/externalReferenceCompatibility.js +48 -0
  120. package/dist/domain/externalReferenceCompatibility.js.map +1 -0
  121. package/dist/domain/externalReferenceFidelity.d.ts +171 -0
  122. package/dist/domain/externalReferenceFidelity.js +419 -0
  123. package/dist/domain/externalReferenceFidelity.js.map +1 -0
  124. package/dist/domain/externalReferenceIdentity.d.ts +38 -0
  125. package/dist/domain/externalReferenceIdentity.js +70 -0
  126. package/dist/domain/externalReferenceIdentity.js.map +1 -0
  127. package/dist/domain/externalReferenceImage.d.ts +35 -0
  128. package/dist/domain/externalReferenceImage.js +160 -0
  129. package/dist/domain/externalReferenceImage.js.map +1 -0
  130. package/dist/domain/externalReferenceRegionRelationships.d.ts +63 -0
  131. package/dist/domain/externalReferenceRegionRelationships.js +98 -0
  132. package/dist/domain/externalReferenceRegionRelationships.js.map +1 -0
  133. package/dist/domain/externalReferenceRegions.d.ts +65 -0
  134. package/dist/domain/externalReferenceRegions.js +105 -0
  135. package/dist/domain/externalReferenceRegions.js.map +1 -0
  136. package/dist/domain/externalReferenceRequirementIdentity.d.ts +12 -0
  137. package/dist/domain/externalReferenceRequirementIdentity.js +35 -0
  138. package/dist/domain/externalReferenceRequirementIdentity.js.map +1 -0
  139. package/dist/domain/externalReferenceRequirements.d.ts +215 -0
  140. package/dist/domain/externalReferenceRequirements.js +401 -0
  141. package/dist/domain/externalReferenceRequirements.js.map +1 -0
  142. package/dist/domain/externalReferenceRuntimeBinding.d.ts +146 -0
  143. package/dist/domain/externalReferenceRuntimeBinding.js +183 -0
  144. package/dist/domain/externalReferenceRuntimeBinding.js.map +1 -0
  145. package/dist/domain/frontendContractEvaluation.d.ts +57 -0
  146. package/dist/domain/frontendContractEvaluation.js +454 -0
  147. package/dist/domain/frontendContractEvaluation.js.map +1 -0
  148. package/dist/domain/frontendContractEvaluationArtifact.d.ts +65 -0
  149. package/dist/domain/frontendContractEvaluationArtifact.js +108 -0
  150. package/dist/domain/frontendContractEvaluationArtifact.js.map +1 -0
  151. package/dist/domain/frontendContractIdentity.d.ts +39 -0
  152. package/dist/domain/frontendContractIdentity.js +70 -0
  153. package/dist/domain/frontendContractIdentity.js.map +1 -0
  154. package/dist/domain/frontendContracts.d.ts +188 -0
  155. package/dist/domain/frontendContracts.js +260 -0
  156. package/dist/domain/frontendContracts.js.map +1 -0
  157. package/dist/domain/identity.d.ts +21 -0
  158. package/dist/domain/identity.js +47 -0
  159. package/dist/domain/identity.js.map +1 -0
  160. package/dist/domain/referenceCorrectionIdentity.d.ts +40 -0
  161. package/dist/domain/referenceCorrectionIdentity.js +77 -0
  162. package/dist/domain/referenceCorrectionIdentity.js.map +1 -0
  163. package/dist/domain/referenceCorrectionWorkflow.d.ts +160 -0
  164. package/dist/domain/referenceCorrectionWorkflow.js +165 -0
  165. package/dist/domain/referenceCorrectionWorkflow.js.map +1 -0
  166. package/dist/domain/referenceFidelityProjection.d.ts +65 -0
  167. package/dist/domain/referenceFidelityProjection.js +135 -0
  168. package/dist/domain/referenceFidelityProjection.js.map +1 -0
  169. package/dist/domain/relationships.d.ts +210 -0
  170. package/dist/domain/relationships.js +352 -0
  171. package/dist/domain/relationships.js.map +1 -0
  172. package/dist/domain/schema.d.ts +269 -0
  173. package/dist/domain/schema.js +442 -0
  174. package/dist/domain/schema.js.map +1 -0
  175. package/dist/domain/scrollEvidence.d.ts +51 -0
  176. package/dist/domain/scrollEvidence.js +134 -0
  177. package/dist/domain/scrollEvidence.js.map +1 -0
  178. package/dist/index.d.ts +114 -0
  179. package/dist/index.js +64 -0
  180. package/dist/index.js.map +1 -0
  181. package/dist/projectWorkflow/aliasCatalog.d.ts +21 -0
  182. package/dist/projectWorkflow/aliasCatalog.js +67 -0
  183. package/dist/projectWorkflow/aliasCatalog.js.map +1 -0
  184. package/dist/projectWorkflow/checkAcceptance.d.ts +25 -0
  185. package/dist/projectWorkflow/checkAcceptance.js +55 -0
  186. package/dist/projectWorkflow/checkAcceptance.js.map +1 -0
  187. package/dist/projectWorkflow/checkResult.d.ts +85 -0
  188. package/dist/projectWorkflow/checkResult.js +101 -0
  189. package/dist/projectWorkflow/checkResult.js.map +1 -0
  190. package/dist/projectWorkflow/projectConfig.d.ts +43 -0
  191. package/dist/projectWorkflow/projectConfig.js +84 -0
  192. package/dist/projectWorkflow/projectConfig.js.map +1 -0
  193. package/dist/projectWorkflow/projectDiscovery.d.ts +9 -0
  194. package/dist/projectWorkflow/projectDiscovery.js +20 -0
  195. package/dist/projectWorkflow/projectDiscovery.js.map +1 -0
  196. package/dist/projectWorkflow/projectPaths.d.ts +8 -0
  197. package/dist/projectWorkflow/projectPaths.js +23 -0
  198. package/dist/projectWorkflow/projectPaths.js.map +1 -0
  199. package/dist/request/paths.d.ts +14 -0
  200. package/dist/request/paths.js +33 -0
  201. package/dist/request/paths.js.map +1 -0
  202. package/dist/request/request.d.ts +111 -0
  203. package/dist/request/request.js +464 -0
  204. package/dist/request/request.js.map +1 -0
  205. package/dist/safety/policy.d.ts +14 -0
  206. package/dist/safety/policy.js +81 -0
  207. package/dist/safety/policy.js.map +1 -0
  208. package/dist/viewer/assets/index-CN_yb9Uf.css +1 -0
  209. package/dist/viewer/assets/index-D98S1_2d.js +9 -0
  210. package/dist/viewer/icons/icon-192.png +0 -0
  211. package/dist/viewer/icons/icon-512.png +0 -0
  212. package/dist/viewer/index.html +15 -0
  213. package/dist/viewer/manifest.webmanifest +1 -0
  214. package/dist/viewer/registerSW.js +1 -0
  215. package/dist/viewer/sw.js +1 -0
  216. package/dist/viewer/workbox-9c191d2f.js +1 -0
  217. package/dist/viewerServer/context.d.ts +48 -0
  218. package/dist/viewerServer/context.js +60 -0
  219. package/dist/viewerServer/context.js.map +1 -0
  220. package/dist/viewerServer/evidence/classify.d.ts +59 -0
  221. package/dist/viewerServer/evidence/classify.js +124 -0
  222. package/dist/viewerServer/evidence/classify.js.map +1 -0
  223. package/dist/viewerServer/evidence/comparisonView.d.ts +28 -0
  224. package/dist/viewerServer/evidence/comparisonView.js +43 -0
  225. package/dist/viewerServer/evidence/comparisonView.js.map +1 -0
  226. package/dist/viewerServer/evidence/contextSourceView.d.ts +25 -0
  227. package/dist/viewerServer/evidence/contextSourceView.js +20 -0
  228. package/dist/viewerServer/evidence/contextSourceView.js.map +1 -0
  229. package/dist/viewerServer/evidence/discovery.d.ts +31 -0
  230. package/dist/viewerServer/evidence/discovery.js +78 -0
  231. package/dist/viewerServer/evidence/discovery.js.map +1 -0
  232. package/dist/viewerServer/evidence/evaluationView.d.ts +32 -0
  233. package/dist/viewerServer/evidence/evaluationView.js +50 -0
  234. package/dist/viewerServer/evidence/evaluationView.js.map +1 -0
  235. package/dist/viewerServer/evidence/handles.d.ts +21 -0
  236. package/dist/viewerServer/evidence/handles.js +43 -0
  237. package/dist/viewerServer/evidence/handles.js.map +1 -0
  238. package/dist/viewerServer/evidence/index.d.ts +41 -0
  239. package/dist/viewerServer/evidence/index.js +82 -0
  240. package/dist/viewerServer/evidence/index.js.map +1 -0
  241. package/dist/viewerServer/evidence/limits.d.ts +27 -0
  242. package/dist/viewerServer/evidence/limits.js +28 -0
  243. package/dist/viewerServer/evidence/limits.js.map +1 -0
  244. package/dist/viewerServer/evidence/linkedEvidence.d.ts +43 -0
  245. package/dist/viewerServer/evidence/linkedEvidence.js +151 -0
  246. package/dist/viewerServer/evidence/linkedEvidence.js.map +1 -0
  247. package/dist/viewerServer/evidence/mediaResolver.d.ts +16 -0
  248. package/dist/viewerServer/evidence/mediaResolver.js +85 -0
  249. package/dist/viewerServer/evidence/mediaResolver.js.map +1 -0
  250. package/dist/viewerServer/evidence/observationView.d.ts +29 -0
  251. package/dist/viewerServer/evidence/observationView.js +46 -0
  252. package/dist/viewerServer/evidence/observationView.js.map +1 -0
  253. package/dist/viewerServer/evidence/pathSafety.d.ts +11 -0
  254. package/dist/viewerServer/evidence/pathSafety.js +31 -0
  255. package/dist/viewerServer/evidence/pathSafety.js.map +1 -0
  256. package/dist/viewerServer/evidence/projection.d.ts +55 -0
  257. package/dist/viewerServer/evidence/projection.js +152 -0
  258. package/dist/viewerServer/evidence/projection.js.map +1 -0
  259. package/dist/viewerServer/evidence/referenceView.d.ts +133 -0
  260. package/dist/viewerServer/evidence/referenceView.js +169 -0
  261. package/dist/viewerServer/evidence/referenceView.js.map +1 -0
  262. package/dist/viewerServer/httpServer.d.ts +27 -0
  263. package/dist/viewerServer/httpServer.js +381 -0
  264. package/dist/viewerServer/httpServer.js.map +1 -0
  265. package/dist/viewerServer/openBrowser.d.ts +7 -0
  266. package/dist/viewerServer/openBrowser.js +32 -0
  267. package/dist/viewerServer/openBrowser.js.map +1 -0
  268. package/dist/viewerServer/port.d.ts +16 -0
  269. package/dist/viewerServer/port.js +19 -0
  270. package/dist/viewerServer/port.js.map +1 -0
  271. package/dist/viewerServer/viewerService.d.ts +62 -0
  272. package/dist/viewerServer/viewerService.js +88 -0
  273. package/dist/viewerServer/viewerService.js.map +1 -0
  274. package/docs/ARCHITECTURE.md +1286 -0
  275. package/docs/CI_CD.md +250 -0
  276. package/docs/COMMANDS.md +972 -0
  277. package/docs/CONTRACTS.md +1856 -0
  278. package/docs/CURRENT_STATE.md +1049 -0
  279. package/docs/DEVELOPMENT.md +202 -0
  280. package/docs/DOCUMENTATION_PRESERVATION_POLICY.md +50 -0
  281. package/docs/PROJECT_DESCRIPTION.md +2221 -0
  282. package/docs/PROJECT_MILESTONES.md +2526 -0
  283. package/docs/PROJECT_OVERVIEW.md +150 -0
  284. package/docs/QUICKSTART.md +83 -0
  285. package/docs/RELEASE.md +27 -0
  286. package/docs/ROADMAP.md +641 -0
  287. package/docs/SECURITY.md +218 -0
  288. package/docs/WORKFLOWS.md +642 -0
  289. package/docs/plans/v0.8-implementation-plan.md +655 -0
  290. package/docs/plans/v0.8.1-cli-usability-patch-plan.md +505 -0
  291. package/docs/reports/v0.7-bounded-fidelity-context-prompt7.md +243 -0
  292. package/docs/reports/v0.7-implementation-completeness-documentation-reconciliation.md +497 -0
  293. package/docs/reports/v0.7-pre-release-readiness.md +337 -0
  294. package/docs/reports/v0.7-reference-binding-prompt5.md +223 -0
  295. package/docs/reports/v0.7-reference-compatibility-prompt4.md +234 -0
  296. package/docs/reports/v0.7-reference-correction-workflow-prompt8.md +222 -0
  297. package/docs/reports/v0.7-reference-fidelity-prompt6.md +216 -0
  298. package/docs/reports/v0.7-reference-foundation-prompt1.md +151 -0
  299. package/docs/reports/v0.7-reference-regions-prompt2.md +195 -0
  300. package/docs/reports/v0.7-reference-requirements-prompt3.md +217 -0
  301. package/docs/reports/v0.7-release-prep.md +423 -0
  302. package/docs/reports/v0.8-binding-fidelity-interaction-batch6.md +279 -0
  303. package/docs/reports/v0.8-bounded-context-correlation-batch7.md +233 -0
  304. package/docs/reports/v0.8-comparison-contract-inspection-batch4.md +279 -0
  305. package/docs/reports/v0.8-evidence-index-readers-batch2.md +247 -0
  306. package/docs/reports/v0.8-implementation-completeness-documentation-reconciliation.md +741 -0
  307. package/docs/reports/v0.8-integrated-viewer-acceptance-batch8.md +128 -0
  308. package/docs/reports/v0.8-observation-svg-inspection-batch3.md +223 -0
  309. package/docs/reports/v0.8-prerelease-readiness-cross-platform-security-code-rot.md +687 -0
  310. package/docs/reports/v0.8-reference-candidate-inspection-batch5.md +232 -0
  311. package/docs/reports/v0.8-viewer-runtime-pwa-batch1.md +278 -0
  312. package/docs/reports/v0.8.1-check-orchestration-prompt2.md +69 -0
  313. package/docs/reports/v0.8.1-implementation-completeness-documentation-reconciliation.md +114 -0
  314. package/docs/reports/v0.8.1-prerelease-readiness-cross-platform-security-code-rot.md +170 -0
  315. package/docs/reports/v0.8.1-project-workflow-foundation-prompt1.md +66 -0
  316. package/package.json +58 -0
@@ -0,0 +1,972 @@
1
+ # Commands
2
+
3
+ ## v0.8.1 common workflow
4
+
5
+ `init --url <loopback-url> [--viewport WIDTHxHEIGHT] [--target id=selector ... | --targets-file file] [--default-baseline alias] [--replace]` creates schema-`1.1.0` project configuration; schema `1.0.0` remains readable and forbids `acceptance`. Schema `1.1.0` may add exactly:
6
+
7
+ ```json
8
+ {
9
+ "acceptance": {
10
+ "comparisonConfigFile": "config/comparison.json",
11
+ "contract": {
12
+ "baselineArtifact": ".frontend-observer/evidence/contracts/baseline/<id>",
13
+ "changeArtifact": ".frontend-observer/evidence/contracts/change/<id>"
14
+ },
15
+ "reference": {
16
+ "approvedArtifact": ".frontend-observer/evidence/references/approved/<id>",
17
+ "bindingsFile": "config/reference-bindings.json"
18
+ }
19
+ }
20
+ }
21
+ ```
22
+
23
+ Every acceptance path is portable and project-relative and is realpath-checked
24
+ before use. Both contract paths are required together. The reference must be
25
+ explicitly approved; bindings are explicit and default to an empty collection.
26
+ `comparisonConfigFile` uses the existing `compare --config-file` format.
27
+
28
+ `capture <alias> [--replace]` creates immutable canonical evidence. `current`
29
+ is reserved for `check`. `check [<baseline>] [--json]` resolves the explicit
30
+ alias or `defaultBaseline`, captures a new immutable `current`, compares it
31
+ canonically, and evaluates configured contract/reference acceptance. Its exact
32
+ exit codes are:
33
+
34
+ ```text
35
+ PASS 0
36
+ FAIL 1
37
+ REVIEW_REQUIRED 2
38
+ BLOCKED 3
39
+ ```
40
+
41
+ Comparison alone is evidence and returns `REVIEW_REQUIRED`, even with zero
42
+ differences. `--json` emits exactly one bounded schema-`1.0.0` document and
43
+ never embeds screenshots or complete artifacts. `view [--root path]` uses
44
+ project evidence and aliases when root is omitted and preserves standalone
45
+ behavior when supplied. Advanced commands below remain supported.
46
+
47
+ ## Product command surface
48
+
49
+ `node dist/cli.js observe` (or `my-frontend-observer observe` once installed
50
+ as a bin) captures one bounded, loopback-only browser observation and
51
+ persists it as a portable artifact.
52
+
53
+ ```text
54
+ my-frontend-observer observe --url <loopback-url> [options]
55
+ ```
56
+
57
+ Required:
58
+
59
+ - `--url <url>` — loopback target URL (`http`/`https`; `localhost`,
60
+ `127.x.x.x`, or `::1` only - enforced by the existing request/safety
61
+ contracts, not by CLI-local logic).
62
+
63
+ Options:
64
+
65
+ - `--viewport <WIDTHxHEIGHT>` — e.g. `1280x720`. Malformed syntax (missing
66
+ `x`, non-numeric, empty side) is rejected before any browser launches;
67
+ in-range bounds are enforced by the existing request validator.
68
+ - `--target <id=css-selector>` — an explicit CSS-shorthand observation
69
+ target. Repeatable; order is preserved. Parsed on the *first* `=` only, so
70
+ a selector containing `=` survives intact, e.g.
71
+ `--target action=button[data-state="active"]`. Cannot be combined with
72
+ `--targets-file`.
73
+ - `--targets-file <json-file>` — loads structured semantic observation
74
+ targets from a local JSON file instead of `--target`. Cannot be combined
75
+ with `--target`. See "Structured semantic targets" below.
76
+ - `--scroll-scenario-file <json-file>` — loads one bounded runtime scroll
77
+ scenario from a local JSON file. May be combined with either `--target` or
78
+ `--targets-file` (it is independent of target configuration). See "Scroll
79
+ scenario (`--scroll-scenario-file`)" below.
80
+ - `--state-file <json-file>` — loads explicit, caller-declared frontend
81
+ state identity (`theme`, `applicationState`, `authenticatedState`) from a
82
+ local JSON file. Never inferred by the observer from screenshot pixels,
83
+ CSS, DOM, or URLs - this is caller-declared metadata only, used solely for
84
+ later comparability/compatibility evaluation (see "v0.7 Prompt 4 reference
85
+ applicability and candidate-state compatibility" in `docs/CONTRACTS.md`).
86
+ Independent of every other flag.
87
+ - `--output <directory>` — portable, relative output location for the
88
+ observation artifact (same contract as the request's `outputLocation`; no
89
+ drive letter, no leading `/`, no `..` segments).
90
+ - `--timeout <ms>` — overall request timeout in milliseconds.
91
+ - `--help` — show `observe` usage.
92
+
93
+ Also available: `--help` / `-h` (top-level usage) and `--version` (prints the
94
+ actual package version).
95
+
96
+ On success the command prints exactly:
97
+
98
+ ```text
99
+ Observation: <observation-id>
100
+ State: <complete|partial|warning|fatal|invalid-request>
101
+ Artifact: <artifact-root-path>
102
+ Targets: <configured-target-count>
103
+ Diagnostics: <diagnostic-count>
104
+ ```
105
+
106
+ and exits `0` for a validly persisted observation - including one whose
107
+ `State` truthfully reports `partial` (e.g. a missing or ambiguous target)
108
+ - or exits nonzero for invalid CLI syntax, a request the existing validator
109
+ rejects, an unsafe/failed navigation with no persistable artifact, or a
110
+ failed artifact write. No progress output is printed during a normal
111
+ capture. CLI-syntax errors (e.g. a missing `--url`) print as `error:
112
+ <message>` followed by `observe` usage; request/capture/persistence
113
+ diagnostics print one per line as `[code] message`.
114
+
115
+ ### Structured semantic targets (`--targets-file`)
116
+
117
+ **Current status: shipped as part of the published `my-frontend-observer@0.3.0`
118
+ package.** `--target` (CSS shorthand) remains fully supported alongside it.
119
+
120
+ `--targets-file <json-file>` is the public entry point to the v0.2 canonical
121
+ target/locator model established in `src/request/request.ts`. It supplies
122
+ the same `targets` collection that `--target` supplies, just in structured
123
+ form; both converge on the same `normalizeRequest()` validation and the same
124
+ downstream browser resolver - there is no separate semantic observation path.
125
+
126
+ File format (the exact, first frozen structure - the root object supports
127
+ only the `targets` field; any other top-level field is rejected):
128
+
129
+ ```json
130
+ {
131
+ "targets": [
132
+ {
133
+ "name": "primary-navigation",
134
+ "locators": [
135
+ { "kind": "role", "role": "navigation", "name": "Primary" },
136
+ { "kind": "id", "value": "nav" }
137
+ ]
138
+ },
139
+ {
140
+ "name": "workspace",
141
+ "locators": [
142
+ { "kind": "data-attribute", "attribute": "data-region", "value": "workspace" }
143
+ ]
144
+ }
145
+ ]
146
+ }
147
+ ```
148
+
149
+ Each target has a stable `name` and an ordered `locators` array (1-5
150
+ entries; order is the fallback order - the first locator that resolves
151
+ uniquely wins, an ambiguous or unevaluable locator stops immediately without
152
+ trying the next one). Each locator is one of the six frozen kinds:
153
+
154
+ - `{ "kind": "role", "role": "<string>", "name"?: "<string>" }`
155
+ - `{ "kind": "id", "value": "<string>" }`
156
+ - `{ "kind": "data-attribute", "attribute": "data-*", "value": "<string>" }`
157
+ - `{ "kind": "semantic-element", "tag": "<one of the frozen structural tags>" }`
158
+ - `{ "kind": "css", "selector": "<string>" }`
159
+ - `{ "kind": "text", "text": "<exact string>" }`
160
+
161
+ `--targets-file` itself only validates that the file is readable, is valid
162
+ JSON, and has an object root containing exactly a `targets` field - every
163
+ target/locator-internal rule (bounds, per-kind required fields, supported
164
+ values) is enforced by the same `normalizeRequest()` validator `--target`
165
+ already goes through, so both input modes produce identical diagnostics for
166
+ equivalent mistakes.
167
+
168
+ The path may be relative (resolved from the current working directory) or
169
+ absolute; it is operational input only - it never affects the observation's
170
+ request identity and is never written into `manifest.json`.
171
+
172
+ Example:
173
+
174
+ ```powershell
175
+ my-frontend-observer observe `
176
+ --url http://localhost:3000/ `
177
+ --viewport 1280x720 `
178
+ --targets-file .\targets.json `
179
+ --output observations
180
+ ```
181
+
182
+ ### Scroll scenario (`--scroll-scenario-file`)
183
+
184
+ **Current status: shipped as part of the published `my-frontend-observer@0.3.0`
185
+ package.** Observation schema is `1.2.0`.
186
+
187
+ `--scroll-scenario-file <json-file>` is the public entry point to the v0.3
188
+ runtime scroll-scenario contract established in `src/request/request.ts`
189
+ (`ScrollScenario`/`ScrollAction`) and executed in `src/browser/`. It supplies
190
+ exactly the value of the normalized request's `scrollScenario` field - the
191
+ file root *is* the scenario object itself, with no wrapper field (unlike
192
+ `--targets-file`'s `{ "targets": [...] }` root).
193
+
194
+ A request supports **zero or one** scroll scenario. There are exactly two
195
+ supported action kinds:
196
+
197
+ Window scrolling:
198
+
199
+ ```json
200
+ {
201
+ "action": {
202
+ "kind": "window-scroll-by",
203
+ "deltaX": 0,
204
+ "deltaY": 600
205
+ }
206
+ }
207
+ ```
208
+
209
+ Target scrolling (the `target` value must be the stable `name` of one of the
210
+ observation's own configured targets - never a CSS selector, DOM id, or
211
+ source symbol):
212
+
213
+ ```json
214
+ {
215
+ "action": {
216
+ "kind": "target-scroll-by",
217
+ "target": "tool-workspace",
218
+ "deltaX": 0,
219
+ "deltaY": 400
220
+ }
221
+ }
222
+ ```
223
+
224
+ `deltaX`/`deltaY` are signed integers bounded to `[-20000, 20000]`; at least
225
+ one must be non-zero (both zero is rejected). Every scroll/action rule -
226
+ supported action kind, required fields, delta types/bounds, the both-zero
227
+ rule, and the stable-target-name reference for `target-scroll-by` - is
228
+ enforced by the same `normalizeRequest()` validator used everywhere else, not
229
+ duplicated in CLI code; `--scroll-scenario-file` itself only validates that
230
+ the file is readable, is valid JSON, and has a non-array object root.
231
+
232
+ The observer performs the requested scroll immediately (no smooth-scroll
233
+ animation), waits exactly two `requestAnimationFrame` cycles, and captures a
234
+ final runtime snapshot - the same final state that the observation's ordinary
235
+ `pageEvidence`, `targetEvidence`, and `screenshot.png` describe. The actual
236
+ resulting scroll position is browser-authoritative and may be clamped by
237
+ document/element boundaries; a scenario that produces no movement (already at
238
+ a boundary, or a non-scrollable target) is still a valid, successfully
239
+ persisted observation, never a fabricated failure.
240
+
241
+ Usable with either target input mode:
242
+
243
+ ```powershell
244
+ my-frontend-observer observe `
245
+ --url http://localhost:3000/ `
246
+ --target workspace=.workspace `
247
+ --scroll-scenario-file .\scroll.json `
248
+ --output observations
249
+ ```
250
+
251
+ ```powershell
252
+ my-frontend-observer observe `
253
+ --url http://localhost:3000/ `
254
+ --targets-file .\targets.json `
255
+ --scroll-scenario-file .\scroll.json `
256
+ --output observations
257
+ ```
258
+
259
+ `--target` and `--targets-file` remain mutually exclusive with each other,
260
+ exactly as before; `--scroll-scenario-file` is independent of both and is
261
+ never itself a third mutually-exclusive target mode. `window-scroll-by`
262
+ requires no configured target at all.
263
+
264
+ The path may be relative (resolved from the current working directory) or
265
+ absolute; it is operational input only - like `--targets-file`'s path, it
266
+ never affects the observation's request identity and is never written into
267
+ `manifest.json`. Two different scenario files with identical content produce
268
+ the same `requestId`; only the requested scenario *configuration*
269
+ participates in identity, never the runtime outcome (actual scroll
270
+ distance, clamping, or scroll-owner result).
271
+
272
+ If a `target-scroll-by` scenario's configured action target cannot be
273
+ uniquely resolved at runtime (missing, ambiguous, or otherwise unavailable),
274
+ the scroll is not performed, no movement is fabricated, and the observation
275
+ persists honestly - typically as `partial` - carrying the same
276
+ `target-missing`/`target-ambiguous`/`browser-evidence-unavailable` diagnostic
277
+ that any other unresolved configured target would produce.
278
+
279
+ ## `compare`
280
+
281
+ **Current status: shipped as part of the published `my-frontend-observer@0.4.0`
282
+ package.** Comparison schema is `1.0.0`, independent of and never reused for
283
+ the observation schema (`1.2.0`).
284
+
285
+ `my-frontend-observer compare` (or `node dist/cli.js compare` from a source
286
+ checkout) reads two already-persisted observation artifacts and derives
287
+ before/after evidence purely from their existing content:
288
+
289
+ ```text
290
+ my-frontend-observer compare --before <observation-artifact-root> --after <observation-artifact-root> --output <directory> [options]
291
+ ```
292
+
293
+ Required:
294
+
295
+ - `--before <path>` — root directory of the "before" persisted observation
296
+ artifact (the directory containing its `manifest.json`, as produced by
297
+ `observe`).
298
+ - `--after <path>` — root directory of the "after" persisted observation
299
+ artifact.
300
+ - `--output <directory>` — portable, relative output location for the
301
+ comparison artifact (same contract as `observe --output`).
302
+
303
+ Options:
304
+
305
+ - `--config-file <json-file>` — loads a comparison configuration directly
306
+ (no wrapper field): `{ "geometryTolerancePx": <0-10>,
307
+ "expectedDependencies": [...] }`. Without it, `geometryTolerancePx`
308
+ defaults to `0.5` CSS px with no declared dependencies. As with
309
+ `--targets-file`/`--scroll-scenario-file`, `--config-file` only validates
310
+ file readability, JSON validity, and a non-array object root; every
311
+ semantic rule (tolerance bounds, dependency property/direction
312
+ vocabulary, dependency source marker) is enforced by the same domain
313
+ validator the comparison engine itself uses.
314
+ - `--help` — show `compare` usage.
315
+
316
+ **Comparison never launches a browser.** It reads two manifests through the
317
+ existing observation-artifact reader, runs the pure comparison engine, and
318
+ persists a portable `manifest.json` — no navigation, no target
319
+ re-resolution, no Chromium process.
320
+
321
+ On success the command prints exactly:
322
+
323
+ ```text
324
+ Comparison: <comparison-id>
325
+ State: <comparable|comparable-with-warnings|incomparable>
326
+ Artifact: <comparison-artifact-root>
327
+ Differences: <count>
328
+ Relationship changes: <count>
329
+ Diagnostics: <count>
330
+ ```
331
+
332
+ and exits `0` — **including when `State` is `incomparable`**: comparison
333
+ determining that two observations should not be treated as equivalent
334
+ frontend states is itself a successful outcome, not a failure. The command
335
+ exits nonzero only for invalid CLI syntax, an unreadable/malformed/
336
+ structurally-invalid source artifact, invalid comparison configuration, or
337
+ a failed artifact write.
338
+
339
+ ### Comparability
340
+
341
+ Before any rendered difference is calculated, the engine evaluates whether
342
+ the two observations are comparable at all:
343
+
344
+ - **Hard incompatibilities** (force `incomparable`): different logical page
345
+ URL, different viewport, different browser engine, or a mismatched scroll
346
+ scenario configuration (no scenario vs. a scenario, or two different
347
+ scenario configurations).
348
+ - **Warnings** (still `comparable-with-warnings`, comparison proceeds):
349
+ different producer package version, different browser version, or a
350
+ changed/added/removed configured target.
351
+ - **Unassessed dimensions** the observer does not yet model (theme,
352
+ authenticated state, application state) are always recorded, never
353
+ silently claimed identical.
354
+
355
+ An `incomparable` result still persists a structurally valid
356
+ `ComparisonArtifact`: the comparability reasons are recorded, and ordinary
357
+ rendered differences/relationship changes stay empty rather than fabricated.
358
+
359
+ ### Difference and relationship evidence
360
+
361
+ For a `comparable`/`comparable-with-warnings` result, the manifest's
362
+ `differences` and `relationshipChanges` arrays carry structured before/
363
+ after evidence: appeared/disappeared targets (only for a stable target name
364
+ configured on both sides — a target added/removed from configuration is
365
+ recorded separately as a `configurationChanges` entry, never fabricated as
366
+ appeared/disappeared), moved/resized targets, visibility changes, clipping
367
+ changes, actual dimensional overflow changes, DOM containment changes,
368
+ page-size changes, scroll-owner changes, and layout-relationship
369
+ transitions (e.g. `does-not-overlap` → `overlaps`, or
370
+ `document-width-fits-viewport` → `document-width-exceeds-viewport`) reused
371
+ verbatim from the same canonical relationship engine `observe` output feeds
372
+ Batch 2's `deriveLayoutRelationships`.
373
+
374
+ ### Explicit dependency evidence (non-causal)
375
+
376
+ `--config-file`'s `expectedDependencies` lets you declare an expected
377
+ layout relationship such as "`navigation.width` decreases →
378
+ `workspace.width` increases" using only the frozen `x`/`y`/`width`/`height`
379
+ property vocabulary and `increase`/`decrease`/`change`/`unchanged`
380
+ direction vocabulary. Each declaration is evaluated independently against
381
+ the two observations and persists exactly one outcome: `consistent`,
382
+ `not-observed`, `contradictory-to-declaration`, or `unavailable`. **The
383
+ observer never infers a dependency from co-change, and never emits a
384
+ causal claim, a PASS/FAIL verdict, or a change-contract decision** — v0.4
385
+ produces comparison evidence; whether that evidence satisfies some
386
+ contract is v0.5+ scope.
387
+
388
+ ### Path privacy
389
+
390
+ `--before`, `--after`, `--config-file`, and `--output` are operational
391
+ filesystem input only. None of them affect `comparisonRequestId`, and none
392
+ of them are written into the persisted manifest — the manifest instead
393
+ retains logical source references (`observationId`, `requestId`,
394
+ `producer`, `observationSchemaVersion`, and the source `screenshot.path`).
395
+ Two semantically identical observation/config pairs read from different
396
+ filesystem locations produce the same `comparisonRequestId`; each execution
397
+ still gets a fresh `comparisonId`.
398
+
399
+ ### Source observations remain immutable
400
+
401
+ Comparison is read-only with respect to its inputs: it never modifies
402
+ either source observation's `manifest.json` or `screenshot.png`, and it
403
+ never copies screenshot bytes into the comparison directory — the
404
+ comparison artifact directory contains `manifest.json` only.
405
+
406
+ Example:
407
+
408
+ ```powershell
409
+ node dist/cli.js compare `
410
+ --before observations/<before-id> `
411
+ --after observations/<after-id> `
412
+ --output comparisons `
413
+ --config-file .\comparison-config.json
414
+ ```
415
+
416
+ ## `approve-baseline`
417
+
418
+ **Current status: shipped as part of the published `my-frontend-observer@0.5.0`
419
+ package.** Frontend contract schema is `1.0.0`, independent of the
420
+ observation (`1.2.0`) and comparison (`1.0.0`) schemas.
421
+
422
+ `my-frontend-observer approve-baseline` is the *only* baseline-approval
423
+ operation in the observer — approval is never inferred from a successful
424
+ comparison or evaluation, and no command automatically supersedes or selects
425
+ a baseline. It explicitly approves and persists one already-authored
426
+ `PersistentBaselineContract` against the observation it claims to approve:
427
+
428
+ ```text
429
+ my-frontend-observer approve-baseline --observation <observation-artifact-root> --contract-file <json-file> --output <directory>
430
+ ```
431
+
432
+ Required:
433
+
434
+ - `--observation <path>` — root directory of the persisted observation
435
+ artifact this baseline claims to approve (read through the existing
436
+ observation-artifact reader).
437
+ - `--contract-file <json-file>` — local JSON file containing one raw
438
+ `PersistentBaselineContract` (no wrapper field). As with `--config-file`,
439
+ only file readability/JSON-validity/non-array-object-root is checked here;
440
+ every structural rule (artifact kind, schema version, clause shape) is
441
+ enforced by the existing frozen domain validator.
442
+ - `--output <directory>` — portable, relative output location for the
443
+ baseline artifact.
444
+
445
+ Before persisting, the application layer verifies the contract's frozen
446
+ `sourceObservation` reference (`observationId`, `requestId`, `producer`,
447
+ `observationSchemaVersion`) actually matches the supplied observation
448
+ artifact's stable identity — approving a baseline against an unrelated
449
+ observation is rejected, even if both artifacts are individually valid. Any
450
+ `supersedesBaselineId` already authored in the contract is preserved exactly
451
+ as supplied; this command never discovers a prior baseline, infers
452
+ supersession, or deletes anything.
453
+
454
+ On success the command prints exactly:
455
+
456
+ ```text
457
+ Baseline: <baseline-id>
458
+ State: approved
459
+ Artifact: <baseline-artifact-root>
460
+ Clauses: <count>
461
+ Supersedes: <baseline-id|none>
462
+ ```
463
+
464
+ and exits `0`. It exits nonzero for invalid CLI syntax, an unreadable/
465
+ malformed/structurally-invalid contract file, a `PerChangeContract` passed
466
+ where a baseline is expected, a source-observation mismatch, an existing
467
+ artifact collision (baseline identities are never overwritten), or a failed
468
+ artifact write.
469
+
470
+ ## `save-change-contract`
471
+
472
+ **Current status: shipped as part of the published `my-frontend-observer@0.5.0`
473
+ package.**
474
+
475
+ `my-frontend-observer save-change-contract` validates and persists one
476
+ already-authored `PerChangeContract` so it can later be evaluated — this is
477
+ persistence only, never approval:
478
+
479
+ ```text
480
+ my-frontend-observer save-change-contract --contract-file <json-file> --output <directory>
481
+ ```
482
+
483
+ Required:
484
+
485
+ - `--contract-file <json-file>` — local JSON file containing one raw
486
+ `PerChangeContract` (no wrapper field).
487
+ - `--output <directory>` — portable, relative output location for the
488
+ change-contract artifact.
489
+
490
+ Domain/application validation rejects a `PersistentBaselineContract` passed
491
+ here, malformed clauses, an unsupported authored category, an authored
492
+ `category: "unexpected"` (the derived-only fifth classification can never be
493
+ authored as a permission), and invalid tolerance/mode fields — none of this
494
+ is duplicated in CLI code. Any `supersedesBaselineClauseIds` already
495
+ authored on a clause is preserved exactly; resolving those references
496
+ against a particular baseline remains `evaluate-contract`'s responsibility.
497
+
498
+ On success the command prints exactly:
499
+
500
+ ```text
501
+ Change contract: <contract-id>
502
+ Artifact: <contract-artifact-root>
503
+ Clauses: <count>
504
+ Supersedes baseline clauses: <count>
505
+ ```
506
+
507
+ and exits `0`. It exits nonzero for invalid CLI syntax, an unreadable/
508
+ malformed/structurally-invalid contract file, a persistent baseline contract
509
+ passed here, an existing artifact collision, or a failed artifact write.
510
+
511
+ ## `evaluate-contract`
512
+
513
+ **Current status: shipped as part of the published `my-frontend-observer@0.5.0`
514
+ package.** Frontend contract evaluation artifact schema is `1.0.0`, its own
515
+ independent family.
516
+
517
+ `my-frontend-observer evaluate-contract` executes the canonical Batch 2
518
+ evaluator against already-persisted evidence/contracts and persists the
519
+ result:
520
+
521
+ ```text
522
+ my-frontend-observer evaluate-contract --before <observation-artifact-root> --after <observation-artifact-root> --comparison <comparison-artifact-root> --baseline <baseline-contract-artifact-root> --change <per-change-contract-artifact-root> --output <directory> [--enforce]
523
+ ```
524
+
525
+ Required:
526
+
527
+ - `--before <path>` / `--after <path>` — root directories of the persisted
528
+ before/after observation artifacts.
529
+ - `--comparison <path>` — root directory of the already-persisted comparison
530
+ artifact for that before/after pair.
531
+ - `--baseline <path>` — root directory of the already-approved baseline
532
+ contract artifact.
533
+ - `--change <path>` — root directory of the already-persisted per-change
534
+ contract artifact.
535
+ - `--output <directory>` — portable, relative output location for the
536
+ evaluation artifact.
537
+
538
+ Options:
539
+
540
+ - `--enforce` — makes a `FAIL` verdict produce a nonzero process exit
541
+ status. A `FAIL` evaluation is always persisted and printed identically
542
+ with or without this flag; `--enforce` changes only the process exit code
543
+ — never evaluation identity, contents, or persistence.
544
+
545
+ **`evaluate-contract` never launches a browser, never re-resolves targets,
546
+ and never recomputes comparison or relationship evidence** — it reads the
547
+ already-persisted before/after observations and comparison exactly as given
548
+ (through the existing observation-artifact reader and a new comparison
549
+ reader) and calls the canonical `evaluateFrontendContract` exactly once.
550
+
551
+ A `FAIL` verdict (a found regression or unsatisfied contract clause) is a
552
+ successful, persisted evaluation outcome — not an execution error. On
553
+ success (evaluation constructed and persisted, verdict `PASS`, or verdict
554
+ `FAIL` without `--enforce`), the command prints exactly:
555
+
556
+ ```text
557
+ Evaluation: <evaluation-id>
558
+ Verdict: <PASS|FAIL>
559
+ Artifact: <evaluation-artifact-root>
560
+ Clauses: <total-clause-result-count>
561
+ Unexpected: <unexpected-change-count>
562
+ Enforced: <yes|no>
563
+ ```
564
+
565
+ and exits `0`; with `--enforce` and verdict `FAIL`, it prints the same
566
+ result and exits nonzero. It exits nonzero and persists nothing for invalid
567
+ CLI syntax or an unreadable/malformed/incoherent source artifact (evaluation
568
+ could not even be constructed) — distinct from a legitimate persisted `FAIL`.
569
+
570
+ The evaluation artifact directory contains `manifest.json` only — no
571
+ screenshot is copied. Operational `--before`/`--after`/`--comparison`/
572
+ `--baseline`/`--change`/`--output` paths never enter the persisted
573
+ `evaluationRequestId` or any other semantic field; two semantically
574
+ identical evaluations invoked from different filesystem locations share the
575
+ same `evaluationRequestId` even though each execution gets a fresh
576
+ `evaluationId`.
577
+
578
+ ## `evaluate-reference-fidelity`
579
+
580
+ **Current status: shipped as part of the published `my-frontend-observer@0.7.0`
581
+ package.** No new artifact
582
+ family or schema version — this command persists nothing.
583
+
584
+ `my-frontend-observer evaluate-reference-fidelity` evaluates whether an
585
+ already-persisted candidate observation satisfies an external reference's
586
+ selected design requirements, gated by reference adequacy (v0.7 Prompt 3),
587
+ reference/candidate compatibility (v0.7 Prompt 4), and explicit
588
+ region-to-target bindings (v0.7 Prompt 5):
589
+
590
+ ```text
591
+ my-frontend-observer evaluate-reference-fidelity --reference <external-reference-artifact-root> --candidate <observation-artifact-root> [--bindings-file <json-file>] [--enforce]
592
+ ```
593
+
594
+ Required:
595
+
596
+ - `--reference <path>` — root directory of an already-imported or
597
+ already-approved external-reference artifact.
598
+ - `--candidate <path>` — root directory of the already-persisted candidate
599
+ observation artifact to evaluate against it.
600
+
601
+ Options:
602
+
603
+ - `--bindings-file <json-file>` — local JSON file of the form
604
+ `{ "bindings": [ { "referenceRegion": "...", "runtimeTarget": "..." } ] }`
605
+ declaring which stable observer runtime target (a configured target name)
606
+ explicitly corresponds to each reference region a selected requirement
607
+ depends on. Never inferred from geometry, matching names, or source code.
608
+ Optional — omitting it evaluates with no bindings at all, so every
609
+ requirement whose subject depends on a reference region becomes
610
+ `unavailable`.
611
+ - `--enforce` — makes a `fail` fidelity state produce a nonzero process
612
+ exit status. A `fail` result is always printed identically with or
613
+ without this flag; `--enforce` changes only the process exit code, never
614
+ the result's content, and has no effect on a `not-evaluated` result.
615
+
616
+ **This command never launches a browser, never re-resolves targets, and
617
+ never recomputes reference regions/requirements/adequacy, compatibility, or
618
+ bindings** — it reads the already-persisted reference and candidate exactly
619
+ as given and evaluates every selected requirement exactly once via
620
+ `evaluateReferenceCandidateFidelity`.
621
+
622
+ A `not-evaluated` result (reference adequacy inadequate, or reference/
623
+ candidate incompatible) and a `fail` result (a found design mismatch) are
624
+ both successful, structured evaluation outcomes — not execution errors. On
625
+ success, the command prints exactly:
626
+
627
+ ```text
628
+ Reference: <referenceId>
629
+ Candidate: <candidateObservationId>
630
+ Adequacy: <adequate|partial|inadequate>
631
+ Compatibility: <comparable|comparable-with-warnings|incomparable>
632
+ State: <not-evaluated|pass|fail>
633
+ Blocked by: <reference-inadequate|incompatible>
634
+ Requirements: <count> (pass: <n>, fail: <n>, unavailable: <n>)
635
+ Enforced: <yes|no>
636
+ ```
637
+
638
+ (`Compatibility`/`Blocked by` are printed only when computed/applicable)
639
+ and exits `0`, unless `--enforce` is given and the state is `fail`, in
640
+ which case it exits nonzero. It exits nonzero and persists nothing for
641
+ invalid CLI syntax, an unreadable/malformed `--reference`/`--candidate`
642
+ target, a malformed `--bindings-file`, or an invalid/out-of-bound binding
643
+ declaration.
644
+
645
+ ## `import-reference`
646
+
647
+ **Current status: shipped as part of the published `my-frontend-observer@0.7.0`
648
+ package.** Persists a new `ExternalReferenceArtifact` in the
649
+ `imported` lifecycle state (external-reference schema `1.0.0`).
650
+
651
+ ```text
652
+ my-frontend-observer import-reference <image-file> --output <directory> [options]
653
+ ```
654
+
655
+ Required:
656
+
657
+ - `<image-file>` — local path to a PNG, JPEG, or WebP external
658
+ design-reference image.
659
+ - `--output <directory>` — portable, relative output location for the
660
+ external-reference artifact.
661
+
662
+ Options:
663
+
664
+ - `--label <text>` — optional human-readable label, stored as pure
665
+ provenance — never part of the reference's logical identity.
666
+ - `--supersedes <path>` — root directory of a prior external-reference
667
+ artifact (imported or approved) that this import explicitly supersedes.
668
+ The prior artifact is never modified.
669
+ - `--regions-file <json-file>` — local JSON file of the form
670
+ `{ "regions": [...] }` declaring explicit, meaningful reference-image
671
+ regions (id plus a `{x, y, width, height}` rectangle in reference-image
672
+ pixels, origin at the image's top-left corner). Optional — a reference
673
+ imported without this flag behaves exactly as in v0.7 Prompt 1. Region
674
+ content participates in the reference's logical identity; the file path
675
+ itself never does.
676
+ - `--requirements-file <json-file>` — local JSON file of the form
677
+ `{ "requirements": [...] }` declaring explicit, user-selected design
678
+ requirements over the regions above — what actually matters for later
679
+ candidate evaluation, never inferred merely because a region
680
+ property/relationship exists. Each requirement has a `category`
681
+ (`requested` | `expected-dependent` | `protected` | `preserved` —
682
+ `unexpected` is never authorable), a `subject` (a region property, a
683
+ region-to-region relationship, or a derived two-region measurement), and
684
+ — for property/measurement subjects — a `tolerance` (`exact` |
685
+ `absolute-reference-px` | `percent`; relationship subjects must omit
686
+ tolerance). Requires `--regions-file` (or an already-present region set)
687
+ supplying every region a requirement refers to. Optional — a reference
688
+ imported without this flag behaves exactly as in v0.7 Prompt 1/2.
689
+ Requirement content participates in the reference's logical identity.
690
+ - `--applicability-file <json-file>` — local JSON file declaring the
691
+ runtime frontend state this reference is intended to represent:
692
+ `{ "viewport": { "width", "height" }, "theme": "...", "applicationState":
693
+ "...", "authenticatedState": "authenticated"|"unauthenticated" }` (each
694
+ field independently optional; at least one required). `viewport` here is
695
+ the CSS-pixel runtime viewport the design represents — distinct from the
696
+ reference image's own pixel dimensions, which are never assumed equal.
697
+ Never inferred from the image — caller-declared metadata only, used for
698
+ later reference/candidate compatibility evaluation (see
699
+ [CONTRACTS.md](CONTRACTS.md) "v0.7 Prompt 4"). Optional — a reference
700
+ imported without this flag behaves exactly as in v0.7 Prompt 1/2/3.
701
+ Applicability content participates in the reference's logical identity.
702
+
703
+ Detects the image format from its header bytes only (never from the file
704
+ extension), reads its pixel dimensions from the same bounded header bytes
705
+ (never decoding pixel data), and persists a new external-reference artifact
706
+ in the `imported` lifecycle state — importing never approves it. On
707
+ success, prints a concise result (including the accepted region/requirement
708
+ counts, the resulting reference-side requirement adequacy — `adequate`,
709
+ `partial`, or `inadequate` — and whether applicability was declared) and
710
+ exits `0`. On an unreadable file, an unsupported or undetectable format,
711
+ invalid/out-of-bound dimensions, an over-limit file size, an unresolvable
712
+ `--supersedes` target, an invalid region, an invalid requirement, or invalid
713
+ applicability, prints structured diagnostics to stderr and exits nonzero.
714
+
715
+ ## `approve-reference`
716
+
717
+ **Current status: shipped as part of the published `my-frontend-observer@0.7.0`
718
+ package.** Persists a new
719
+ `ExternalReferenceArtifact` in the `approved` lifecycle state
720
+ (external-reference schema `1.0.0`).
721
+
722
+ ```text
723
+ my-frontend-observer approve-reference --reference <external-reference-artifact-root> --output <directory> [options]
724
+ ```
725
+
726
+ Required:
727
+
728
+ - `--reference <path>` — root directory of the already-imported
729
+ external-reference artifact (the directory containing its
730
+ `manifest.json`) to approve.
731
+ - `--output <directory>` — portable, relative output location for the
732
+ newly persisted approved artifact.
733
+
734
+ Options:
735
+
736
+ - `--supersedes <path>` — root directory of a prior external-reference
737
+ artifact (imported or approved) that this approval explicitly
738
+ supersedes. The prior artifact is never modified.
739
+
740
+ This is the only explicit reference-approval act in the observer — approval
741
+ is never inferred from a successful import or from any later fidelity
742
+ evaluation. Approving persists a brand-new artifact instance (a fresh
743
+ `referenceId` sharing the imported artifact's `referenceRequestId`) that
744
+ carries a reference back to the imported artifact's image rather than a
745
+ second copy of its bytes; the imported artifact's own manifest is never
746
+ modified. Any regions, requirements, and applicability already declared on
747
+ the imported artifact are carried forward unchanged (not re-validated
748
+ against new input, not re-derived) — approval never adds, removes, or edits
749
+ regions, requirements, or applicability. Only a reference currently in the
750
+ `imported` lifecycle state can be approved. On success, prints a concise
751
+ result (including the carried-forward region/requirement counts,
752
+ reference-side requirement adequacy, and whether applicability was
753
+ declared) and exits `0`. On an unreadable/malformed `--reference` target, a
754
+ target that is not in the `imported` state, an unresolvable `--supersedes`
755
+ target, or a persistence failure, prints structured diagnostics to stderr
756
+ and exits nonzero.
757
+
758
+ ## `view`
759
+
760
+ **Current status: v0.8.1 viewer behavior is released as package
761
+ `@dailephd/my-frontend-observer@0.8.1`.** Starts one
762
+ loopback-only Node viewer server and serves the same React + TypeScript +
763
+ Vite application to a normal browser or an installed Progressive Web App.
764
+ `--root` is used as a bounded, read-only evidence-discovery root: the server
765
+ exposes a metadata-first `GET /api/index` of recognized Observer evidence
766
+ beneath it, an on-demand `GET /api/artifacts/<handle>` for one selected
767
+ supported artifact, an on-demand `GET /api/media/<handle>/<role>` for its
768
+ owned/referenced media, an on-demand `GET /api/observations/<handle>/relationships`
769
+ (existing canonical `deriveLayoutRelationships(...)`), `GET /api/comparisons/<handle>/view`
770
+ and `GET /api/evaluations/<handle>/view` (exact-identity linked-evidence
771
+ resolution), `GET /api/references/<handle>/view` (region-relationship graph
772
+ and requirement adequacy, plus — new this batch — `coordinateMapping`, the
773
+ exact result of the existing canonical `deriveCoordinateScale(reference)`,
774
+ used only to gate view-lock eligibility), and
775
+ `GET /api/references/<handle>/candidate/<handle>/view` (page/state-level
776
+ compatibility plus optional matching-evaluation handles). New this batch:
777
+ `GET /api/references/<handle>/candidate/<handle>/bindings` validates the
778
+ session's explicit binding declarations against the selected reference and
779
+ calls the existing canonical `evaluateReferenceRuntimeBindings` exactly
780
+ once, and `GET /api/references/<handle>/candidate/<handle>/fidelity` is the
781
+ explicit on-demand trigger that calls the existing canonical
782
+ `evaluateReferenceCandidateFidelity` exactly once — never a second copy of a
783
+ linked artifact's own payload, never a recomputed
784
+ `compareObservations`/`evaluateFrontendContract`/
785
+ `deriveReferenceRegionRelationships`/`deriveReferenceRequirementAdequacy`/
786
+ `evaluateReferenceCandidateCompatibility` result, and both new routes are
787
+ plain `GET` (deterministic, ephemeral, never persisted). New this batch:
788
+ `GET /api/context` returns the viewer session's bounded-agent-context state
789
+ established at startup by an optional `--context-file` (below) — `none` (no
790
+ file supplied), `unsupported-version` (a recognized `artifactKind` with a
791
+ `schemaVersion` this viewer does not currently support — shown honestly,
792
+ never coerced), or the validated current context plus `sourceResolution`,
793
+ the exact-identity resolution of its `sources` against the current evidence
794
+ root (reusing/extending the Batch 4 `linkedEvidence.ts` resolver pattern) —
795
+ see `docs/ARCHITECTURE.md` "v0.8 Batch 2" through "v0.8 Batch 7" for the
796
+ exact discovery bounds, classification model, coordinate mapping, and
797
+ handle/media/linked-evidence-resolution contracts.
798
+
799
+ Selecting a supported `observation` record shows the Batch 3 screenshot/SVG
800
+ workspace. Selecting a supported `comparison` record shows the Batch 4
801
+ before/after side-by-side workspace. Selecting a supported
802
+ `contract-evaluation` record shows the Batch 4 clause-result/overall-verdict
803
+ workspace. Selecting a supported `external-reference-imported`/
804
+ `external-reference-approved` record shows the reference image with region
805
+ overlays in the reference image's own pixel coordinate domain, selected
806
+ requirements/tolerances/adequacy/applicability/lifecycle/provenance/
807
+ supersession, and, once a candidate observation is **explicitly** selected
808
+ (never auto-selected), that candidate side by side using the reused Batch
809
+ 3/4 runtime screenshot/SVG machinery plus the real canonical compatibility
810
+ result. New this batch: both panes support independent, bounded (`1x`–`8x`)
811
+ zoom and pointer-drag pan (Fit/Reset controls included) that never rewrites
812
+ any evidence coordinate — only when explicit binding declarations were
813
+ supplied (`--bindings-file`, below) and the selected reference/candidate
814
+ resolve a real canonical `bound` result does selecting a reference region
815
+ cross-highlight its exact declared runtime target (and selecting a runtime
816
+ target cross-highlight every region that names it) — `ambiguous`/
817
+ `unavailable` results and undeclared regions/targets never cross-select,
818
+ even when their names happen to match. A "Lock view" control synchronizes
819
+ both panes' zoom/pan in source-space (via the exact `coordinateMapping`
820
+ scale factor) but is enabled only when a candidate is selected,
821
+ compatibility is not `incomparable`, and `coordinateMapping.ok` is `true` —
822
+ otherwise it stays disabled with an actionable reason, and any change to
823
+ that eligibility (including switching reference/candidate) turns it off
824
+ immediately. An explicit "Evaluate Fidelity" action calls the fidelity
825
+ endpoint on demand (never automatically) and displays the canonical
826
+ `not-evaluated`/`pass`/`fail` state, `blockedBy`, and every requirement
827
+ result's status/numeric-or-relationship fields with correct unit labels
828
+ (reference-image pixels vs. raw candidate CSS pixels) exactly as returned —
829
+ alongside, never merged into, any selected existing contract-evaluation's
830
+ own `overallVerdict`. A dedicated "Bounded context" mode (toggled from the
831
+ viewer header, alongside the normal "Evidence" mode) shows: context
832
+ identity/profile/adequacy/reason codes; every bounded runtime target's
833
+ included fields (absent fields read "not included in this bounded context",
834
+ never a fabricated falsy value); source references with their exact
835
+ resolution status and, for each exactly-resolved source, one-click
836
+ navigation back to its existing Batch 3/4/5 viewer surface plus a "View raw
837
+ structured evidence" panel reusing the existing `GET /api/artifacts/<handle>`
838
+ route unchanged; omissions/truncations with required loss visually
839
+ distinguished from optional loss; runtime/static correlation — `correlated`
840
+ (its one candidate, labeled "Correlated candidate", never "owner"),
841
+ `ambiguous` (every supplied candidate, none visually promoted), or
842
+ `unavailable` (zero fabricated candidates) — exactly as the artifact states,
843
+ or "Static correlation not included in this context" when the `correlations`
844
+ field itself is absent (never reported as `unavailable`); and the bounded
845
+ reference-fidelity projection (`mismatches`/`protectedContext`/`blockedBy`)
846
+ alongside — never merged into — a live, separately-triggered Batch 6
847
+ on-demand fidelity evaluation for the same reference/candidate, when both
848
+ are available. This mode never calls `projectBoundedAgentContext`,
849
+ `deriveRuntimeStaticCorrelations`, or `attachRuntimeStaticCorrelations` —
850
+ only the exact context the session was started with is ever displayed.
851
+ Every other evidence family still shows the bounded metadata/raw-payload
852
+ view established in Batch 2. Every route remains strictly read-only: no
853
+ artifact is ever created, modified, or interpreted beyond its existing
854
+ canonical reader/validator; no binding, fidelity, or bounded-context
855
+ artifact is ever persisted; bounded agent context remains a programmatic-
856
+ only Observer contract — this command adds no way to generate, save, or
857
+ write one; and no batch in this lineage recomputes an "overall" verdict
858
+ spanning contract and fidelity — they remain two independent,
859
+ separately-displayed evidence dimensions.
860
+
861
+ ```text
862
+ my-frontend-observer view [--root <evidence-root>] [--bindings-file <json-file>] [--context-file <json-file>] [options]
863
+ ```
864
+
865
+ Without `--root`, `view` discovers the nearest initialized project and uses
866
+ its managed evidence root plus ephemeral alias metadata. With `--root`, it
867
+ uses standalone evidence-root behavior and does not require a project or
868
+ catalog.
869
+
870
+ Options:
871
+
872
+ - `--root <path>` — local evidence-root directory the viewer session
873
+ represents. Validated operationally (must exist and be a directory); this
874
+ command never reads or interprets any Observer artifacts under it beyond
875
+ the bounded discovery/classification the routes above describe.
876
+
877
+ Options:
878
+
879
+ - `--bindings-file <json-file>` — local JSON file of the form
880
+ `{ "bindings": [ { "referenceRegion": "...", "runtimeTarget": "..." } ] }`
881
+ — the exact same operational wrapper format, and the exact same shared
882
+ parser, as `evaluate-reference-fidelity --bindings-file`. Read once at
883
+ startup; unreadable/invalid-JSON/wrong-wrapper-shape fails startup
884
+ clearly (no server is started). Reference-specific validity (region
885
+ existence) is checked only once a reference is actually selected in the
886
+ viewer, never at startup. The declarations become session-only viewer
887
+ input: never persisted, never written into any Observer artifact, and the
888
+ file's own path is never exposed to the browser. Omit to run with no
889
+ binding declarations — the viewer remains fully usable; reference/runtime
890
+ cross-selection simply stays disabled and fidelity may still be
891
+ explicitly evaluated with an empty declaration collection.
892
+ - `--context-file <json-file>` — local JSON file containing exactly one
893
+ `BoundedAgentContextArtifact` value directly (no wrapper object). Read
894
+ once at startup and validated through the existing canonical
895
+ `isValidBoundedAgentContextArtifact` — never a second validator. Explicit,
896
+ session-only viewer input: held only in server memory, never persisted,
897
+ never written into any Observer artifact, and the file's own path is
898
+ never exposed to the browser. Bounded agent context remains
899
+ programmatic-only as an Observer-produced contract — this command does
900
+ not add a way to generate, save, or write one; the viewer never rebuilds
901
+ it (`projectBoundedAgentContext` is never called at runtime) and never
902
+ derives or re-derives runtime/static correlation
903
+ (`deriveRuntimeStaticCorrelations`/`attachRuntimeStaticCorrelations` are
904
+ never called at runtime) — it only displays the exact context it was
905
+ given. A recognized `artifactKind` with a `schemaVersion` other than the
906
+ currently supported one (`1.0.0`) starts the viewer showing an honest
907
+ "unsupported version" context state rather than failing. An unreadable
908
+ file, invalid JSON, a non-object root, the wrong `artifactKind`, or a
909
+ structurally invalid current-schema artifact fails startup clearly (no
910
+ server is started). Omit to run with no bounded context supplied — the
911
+ viewer remains fully usable; the "Bounded context" mode reports that none
912
+ was supplied. May be freely combined with `--bindings-file`.
913
+ - `--port <n>` — TCP port to bind, in `[0, 65535]`. Defaults to `4319`
914
+ (chosen after checking that no fixture or test in this repository binds a
915
+ fixed port — see `tests/fixtures/server.ts`, which always uses `0`/
916
+ OS-assigned). An explicit alternate port is a different web origin than
917
+ the default; an installed PWA is not portable across origins. If the
918
+ requested port is already in use, the command fails with an actionable
919
+ diagnostic — it never silently falls back to a different port.
920
+ - `--no-open` — do not attempt to open the system default browser after the
921
+ server starts. Auto-open is a best-effort convenience only: its failure is
922
+ never fatal and never affects server startup success.
923
+ - `--help` — show `view` usage.
924
+
925
+ The server binds only to `127.0.0.1` (never `0.0.0.0`), serves only the
926
+ built viewer application assets plus the bounded, read-only `/api/*`
927
+ endpoints described above, and never exposes the supplied evidence root as a
928
+ generic static directory or arbitrary filesystem path. It accepts no write
929
+ methods and mutates nothing. On success,
930
+ prints the viewer URL and keeps running (serving the viewer) until
931
+ interrupted. On invalid syntax, a missing/non-directory `--root`, an
932
+ invalid `--port`, an invalid `--bindings-file`, an invalid `--context-file`
933
+ (other than a recognized-kind future `schemaVersion`, which starts
934
+ normally), or a port already in use, prints structured diagnostics to
935
+ stderr and exits nonzero without starting a server.
936
+
937
+ ## Foundation commands
938
+
939
+ - `npm install` — install dependencies (includes the `playwright` runtime
940
+ dependency since Batch 2).
941
+ - `npx playwright install chromium` — install the Chromium binary once per
942
+ machine (see `docs/DEVELOPMENT.md`).
943
+ - `npm run typecheck` — run TypeScript no-emit checking.
944
+ - `npm run lint` — lint the repository and scripts.
945
+ - `npm test` — run the fast unit suite (`tests/unit/`).
946
+ - `npm run test:browser` — run the real-Chromium integration suite
947
+ (`tests/browser/`), including a real `observe` end-to-end test against the
948
+ deterministic local fixture.
949
+ - `npm run test:security` — run only the safety-relevant subset of the suite
950
+ (`tests/unit/policy.test.ts` plus the real-Chromium enforcement cases in
951
+ `tests/browser/chromiumAdapter.test.ts`: unsafe initial target, prohibited
952
+ redirect, prohibited subresource request, and browser cleanup around
953
+ safety/navigation failure) — a discoverable entry point for security
954
+ review tooling; it is a subset of, not a replacement for, `npm test` and
955
+ `npm run test:browser`.
956
+ - `npm run build` — clean, then compile `src/` (including `src/cli.ts`) to
957
+ `dist/`, then build the viewer web app (`viewer/`) with Vite into
958
+ `dist/viewer/` (v0.8 Batch 1). Both outputs ship inside the existing
959
+ `dist` package allowlist — there is no second npm package.
960
+ - `npm run typecheck` also type-checks the browser-side viewer project
961
+ (`viewer/tsconfig.json`) in addition to `tsconfig.json`, since the viewer's
962
+ DOM/JSX-targeting TypeScript config is intentionally separate from the
963
+ Node-only `src/` compilation.
964
+ - `npm run check:docs` — validate canonical documents and roadmap structure.
965
+ - `npm pack --dry-run` — inspect the public package's tarball inventory
966
+ before publishing. The real tarball has been installed and exercised in a
967
+ clean temporary consumer directory (real Chromium install, real `observe`
968
+ run, real artifact) on Windows, Linux, and macOS as part of v0.1
969
+ validation, again for v0.2's packed semantic `--targets-file` behavior,
970
+ and again for v0.3's packed `--scroll-scenario-file` window/target scroll
971
+ behavior (`scripts/ci/runPackedObservationSmoke.mjs`); this is local
972
+ package validation, not a release/publication step.