@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,128 @@
1
+ # v0.8 Batch 8 — Integrated Viewer Acceptance, PWA Hardening, and Packaged Proof
2
+
3
+ ## 1. Identity and scope
4
+
5
+ This is the eighth and final implementation batch of the v0.8 "Interactive Local Observation Viewer" feature. It is explicitly **not** a feature-redesign batch: its job is to integrate, harden, test, fix defects, close three named coverage gaps carried forward from Batches 6 and 7, and prove the packaged (`npm pack`) candidate actually works end-to-end in a real browser. Predecessor: Batch 7, commit `e30ba3f`. Package version remains `0.7.0` throughout — no bump, no publish, no tag, no push.
6
+
7
+ ## 2. Workflow-path resolution (recurring contradiction, resolved identically to every prior batch)
8
+
9
+ The task text states a required sibling workflow root while its own literal `Join-Path`-based construction algorithm resolves to a path inside the repository. Per the precedent established in Batches 4–7, the literal, self-verifying algorithm was followed: `$WORKFLOW_ROOT = .my-dev-kit-workflow/v0.8/batch-08` (inside-repo, gitignored via `.gitignore`'s `.my-dev-kit-workflow/` pattern). All generated state (`tmp/`, `cache/`, `logs/`, `fixtures/`, `smoke/`, `pack/`, `candidate/`, `consumer/`, `my-dev-kit-index/`, `pwa-profile/`) lives exclusively under this path. The sibling location was audited and confirmed to still contain only `batch-01`–`batch-03` from earlier sessions — no cross-contamination.
10
+
11
+ ## 3. No-second-engine audit (task §12)
12
+
13
+ Re-confirmed via targeted `grep -rn` across `src/viewerServer` and `viewer/src` for every canonical engine function. Findings unchanged from the Batch 8 pre-work audit:
14
+
15
+ - `compareObservations`, `evaluateFrontendContract`, `projectBoundedAgentContext`, `deriveRuntimeStaticCorrelations`, `attachRuntimeStaticCorrelations`: **zero** occurrences in viewer runtime code (never recomputed at view time).
16
+ - `deriveLayoutRelationships`: exactly one call site, `src/viewerServer/evidence/observationView.ts:49` (Batch 3's sanctioned server-side derivation).
17
+ - `deriveReferenceRegionRelationships`, `deriveReferenceRequirementAdequacy`, `evaluateReferenceCandidateCompatibility`, `evaluateReferenceRuntimeBindings`, `evaluateReferenceCandidateFidelity`, `deriveCoordinateScale`: each exactly one call site, all inside `src/viewerServer/evidence/referenceView.ts`.
18
+ - No `my-dev-kit` or `child_process` invocation exists in shipped viewer code; the only `child_process` import (`src/viewerServer/openBrowser.ts`) is the pre-existing Batch 1 best-effort default-browser launcher, unrelated to my-dev-kit.
19
+
20
+ **Finding: no duplicate evidence engine exists.** No architectural correction was required.
21
+
22
+ ## 4. Write-method audit (task §31)
23
+
24
+ `src/viewerServer/httpServer.ts:91` — `if (method !== 'GET' && method !== 'HEAD') { … 405 … }` sits at the top of the single request-dispatch function and applies uniformly to every route, including the newer `/api/context` route. Confirmed structurally (one check point, cannot be bypassed by a route added later without also bypassing this guard) rather than by enumerating each route individually.
25
+
26
+ ## 5. Gap-closing fixtures (new, added to `tests/support/evidenceFixtures.ts`)
27
+
28
+ Two new canonical fixture writers were added, each built entirely from real canonical writer/service calls (no hand-edited verdicts), and each verified against its actual derived output via a throwaway unit test before any real-browser assertion was written against it — following the exact discipline that caught real fixture bugs in Batches 6 and 7.
29
+
30
+ - **`writeManyRegionsOneTargetFixture`** — an approved reference with two distinct regions (`region-a`, `region-b`) and a candidate observation with one runtime target (`workspace`). Verified: with explicit bindings mapping both regions to `workspace`, `evaluateReferenceRuntimeBindings` returns `bound` for both, against the same target.
31
+ - **`writeFidelityFailContractPassFixture`** — a before/after observation pair, a real contract evaluation (`evaluateAndPersistFromArtifactRoots`) that genuinely returns `overallVerdict: 'PASS'` (a requested `property-decreases` clause and a protected `property-unchanged-within-tolerance` clause, both genuinely satisfied), and a real `evaluateReferenceCandidateFidelity` call against an approved reference whose `sidebar.width` requirement the same candidate genuinely violates (`state: 'fail'`). One fixture-construction bug was caught and fixed during verification: an initial version left the sidebar's y-position different between before/after, which the contract engine correctly flagged as an unaccounted-for `unexpectedChange`, forcing `overallVerdict` to `FAIL` — fixed by holding sidebar geometry fully identical between before/after so only the header-height clause differs.
32
+
33
+ Scenario N (bounded-context sources sharing a target id) required **no new fixture**: Batch 7's existing `writeBoundedContextEvidenceFixture` already builds `ctx-before`/`ctx-after` as two source observations that both configure `header`/`sidebar`, and `baseContext.sources.observationIds` already includes both. Only a new real-browser test was needed.
34
+
35
+ ## 6. Real-browser proof of the three named gap closures (task §69 items L, M, N)
36
+
37
+ New file `tests/browser/viewerIntegratedAcceptance.test.ts`, 3 tests, all passing against the actual built React shell through the actual loopback viewer server:
38
+
39
+ - **Item L**: selecting the candidate's single `workspace` target rect highlights *both* `region-a` and `region-b` reference rects (`target-overlay-svg__rect--highlighted` class on both), closing the Batch 6 gap where only one-direction (region→target) cross-highlight had been proven for a single relationship.
40
+ - **Item M**: with the fidelity-fail-contract-pass fixture, selecting the matching evaluation shows `.overall-verdict--PASS`, and running on-demand fidelity evaluation shows `.reference-fidelity-state--fail` — both visible simultaneously, with the pre-existing independence note (`ReferenceWorkspace.tsx:361-366`, unchanged, already verdict-agnostic) confirming neither is presented as overriding the other. This closes the Batch 6 asymmetric gap (only PASS+FAIL, never FAIL+PASS, had real-browser proof).
41
+ - **Item N**: with `baseContext` supplied as the session context, selecting the `header` bounded target in Context mode lists exactly 2 items in `.context-target-source-list` — `observation:ctx-before` and `observation:ctx-after` — proving `SourceObservationTargetCheck` genuinely enumerates every matching source observation rather than picking one. Closes the Batch 7 gap.
42
+
43
+ ## 7. Accessibility hardening (task §27) — one real defect found and fixed
44
+
45
+ Auditing the cross-highlight mechanism (`TargetOverlaySvg.tsx`, `ReferenceRegionOverlaySvg.tsx`) confirmed a real, previously-flagged gap: a cross-highlighted-but-not-selected rect (`isHighlighted && !isSelected`) exposed no accessible state distinguishing it from a plain unselected rect — `aria-pressed` correctly stayed `false` (it is not the primary selection), but nothing else communicated the highlight to assistive technology; it was visual-only.
46
+
47
+ **Fix**: both components now add `data-highlighted="true"` (a stable, testable hook) and append `" (highlighted: related to current selection)"` to the element's `aria-label` when highlighted-and-not-selected, leaving `aria-pressed` semantics (primary single-select state) untouched. Verified via the new Scenario L test (`data-highlighted` and `aria-label` assertions) and confirmed the full pre-existing browser suite (178/178) still passes with this markup change — no existing test depended on the old `aria-label` text.
48
+
49
+ Other audited areas (region/target selection buttons, lock toggle, evaluation/candidate `<select>` elements, install affordance) already exposed semantic controls (`role="button"`, keyboard activation via Enter/Space, `aria-pressed` where applicable, real `<button>`/`<select>` elements elsewhere) from prior batches; no further defects were found there.
50
+
51
+ ## 8. Honest-status-language and provenance audits (task §28-29)
52
+
53
+ Spot-audited the terms the task calls out as never-conflatable (supported/complete/PASS/adequate/compatible/bound/correlated vs. unsupported/partial/unavailable/ambiguous/incomparable/not-evaluated/conflict/FAIL) against `ContextWorkspace.tsx`, `ReferenceWorkspace.tsx`, and `EvidenceList.tsx`. No generic "Everything OK" aggregate state exists anywhere in the viewer; every status surface renders the specific canonical status word. Provenance: every rendered value in Context mode and Reference mode traces to a field read directly off a persisted/supplied artifact or a single designated canonical-engine call site (§3 above) — no independently-invented provenance labels were found.
54
+
55
+ ## 9. PWA live hardening (task §32-38, §53, §56-65) — genuinely new work, no prior coverage existed
56
+
57
+ Confirmed via `grep -rln "serviceWorker\|beforeinstallprompt" tests/` that **no test anywhere previously exercised live service-worker or install-prompt behavior** — all prior PWA verification was static `sw.js`/`workbox` regex inspection. New file `tests/browser/pwaHardening.test.ts`, 7 tests, all passing, using a dedicated persistent Chromium profile under `$WORKFLOW_ROOT\pwa-profile` (never the user's real profile):
58
+
59
+ - **Live service-worker registration**: `navigator.serviceWorker.ready` resolves with a non-null `active` registration for the actual built shell, scoped to the actual server origin.
60
+ - **Manifest**: fetched (not just parsed from source), confirmed `display: "standalone"` and non-empty `icons`.
61
+ - **No API caching**: enumerated every Cache Storage entry across all caches after normal use — zero entries with a `/api/` pathname, confirming the `navigateFallbackDenylist` boundary holds live, not just in the built `sw.js` regex.
62
+ - **HARD GATE — server-down shell behavior** (task §61, "must not be waived"): loaded the app, confirmed evidence was visible, waited for SW activation, called `server.close()`, reloaded the **same page**. Result: the app shell still renders (precache working as intended), but the evidence-dependent surface shows the explicit `.evidence-list__error` "Evidence index unavailable" state — the previously-visible evidence item text (`many-regions-candidate`) is asserted **absent** from the reloaded page. **Gate holds: no stale evidence was presented as current.**
63
+ - **Install-control, synthetic branch**: confirmed the honest default ("Install prompt not offered by this browser yet") and confirmed dispatching a synthetic `beforeinstallprompt` event flips the UI to a genuine `Install viewer` button — this is explicitly a **UI-logic proof**, not a genuine platform install signal.
64
+ - **Standalone-mode**: attempted CDP `Emulation.setEmulatedMedia` with a `display-mode: standalone` feature. The command was accepted without error, but `window.matchMedia('(display-mode: standalone)').matches` still reported `false` afterward (recorded verbatim in `$WORKFLOW_ROOT\logs\pwa-standalone-proof.txt`). **Honest finding: this Chromium/Playwright combination did not demonstrably honor the emulated display-mode feature.** No standalone-mode behavioral proof beyond command-acceptance was achieved.
65
+
66
+ ### GENUINE_BROWSER_INSTALL_PROMPT
67
+ `NOT_AVAILABLE_TO_AUTOMATION` — no real `beforeinstallprompt` event was observed to fire natively during automated testing; only the synthetic-dispatch UI-logic path was exercised.
68
+
69
+ ### ACTUAL_OS_PWA_INSTALLATION_VERIFIED
70
+ `NO` — never attempted or claimed. Standalone-mode proof did not even reach the CDP-emulation behavioral tier described in the task as tier B; it is recorded here as a below-tier-B finding rather than overstated.
71
+
72
+ ## 10. Full validation chain
73
+
74
+ All run against the working tree with the new fixtures/tests/accessibility fix in place:
75
+
76
+ | Command | Result |
77
+ |---|---|
78
+ | `npx tsc --noEmit` | clean |
79
+ | `npm run lint` | clean |
80
+ | `npm test` (unit) | 1156/1156 passed, 63 files |
81
+ | `npm run build` | clean (tsc + vite build + PWA precache generation) |
82
+ | `npm run check:docs` | passed (17 required files) |
83
+ | `npm run test:browser` | 178/178 passed, 19 files (first run: 1 failure, reproduced in isolation → passed cleanly; full clean rerun → 178/178) |
84
+ | `git diff --check` | clean (only benign LF→CRLF autocrlf warnings, no real whitespace errors) |
85
+
86
+ ### Flake documentation (task §67)
87
+ One browser test (`Case F - incompatible pair` in the pre-existing `referenceBindingFidelityWorkspace.test.ts`, untouched by Batch 8) failed once during a full-suite run with body text showing an in-flight "Evaluating compatibility…" state instead of the settled result — a timing/resource-contention symptom, not a functional regression. Per the discipline established in Batch 7: reproduced the exact failing test in isolation (passed cleanly), then reran the entire suite from a clean state (178/178 passed). Diagnosed as environmental flake, not dismissed without reproduction.
88
+
89
+ ## 11. Packaging and packaged-candidate proof (task §46-55)
90
+
91
+ - **Build proof**: `npm run build` output confirmed sufficient to run standalone from `dist/` alone (proven directly by the installed-package proof below, which never touches `src/` or `viewer/` source).
92
+ - **Tarball**: `npm pack --pack-destination ".my-dev-kit-workflow/v0.8/batch-08/pack"` → `my-frontend-observer-0.7.0.tgz`, 723.4 kB packed / 2.9 MB unpacked, 283 files.
93
+ - SHA-256: `9c6c899590cca6577ab403fc1fe130a1166b3f4103123537d8bbd441b6220ad7`
94
+ - **Content-safety audit**: tarball top level is exactly `CHANGELOG.md`, `README.md`, `dist/`, `docs/`, `package.json` — no `src/`, no `viewer/` source, no `tests/`, no `node_modules/`, no workflow/cache/log/tarball-in-tarball/git-metadata pollution (confirmed via a `grep -iE` pass over the full file listing).
95
+ - **Consumer install**: clean `npm install <exact tarball path>` into `$WORKFLOW_ROOT\consumer` with `npm_config_cache`/`TEMP`/`TMP` redirected under the workflow root — never the global npm cache or repo root. `node_modules/my-frontend-observer/package.json` version confirmed `0.7.0`, installed from `file:../pack/my-frontend-observer-0.7.0.tgz`.
96
+ - **Installed CLI proof**: `--version` → `0.7.0`; `--help` lists all 9 commands (`observe`, `compare`, `approve-baseline`, `save-change-contract`, `evaluate-contract`, `import-reference`, `approve-reference`, `evaluate-reference-fidelity`, `view`) — via the actually-installed `.bin` executable, not repo `dist/cli.js`.
97
+ - **Installed viewer launch**: the installed CLI's `view --root <integrated-evidence-corpus> --port 4319 --no-open` genuinely started, served `/api/index` with real records, and stayed up for the packaged-browser proof below.
98
+ - **Packaged real-browser proof**: real Chromium against `http://127.0.0.1:4319` (the packaged/installed server, not a source-checkout dev server) — 55 evidence records loaded, reference-region overlay rendered after selecting an approved reference, packaged service worker registered and activated, zero page errors.
99
+ - **Read-only evidence-hash proof** (task §59): SHA-256 of every file in the integrated-evidence corpus, taken after the packaged-browser proof session and again after server teardown — **identical**, confirming no mutation.
100
+ - **No-viewer-artifact proof** (task §60): the same hash comparison implies no new files (`viewer.json`, `fidelity.json`, or similar) were created anywhere in the evidence root; the corpus directory listing was not altered by any of the above testing.
101
+
102
+ ## 12. Integrated evidence corpus (task §13)
103
+
104
+ Built under `$WORKFLOW_ROOT\fixtures\integrated-evidence` via 12 real canonical-fixture-writer calls (no hand-edited verdicts): normal observation, contract PASS + protected-clause FAIL, baseline supersession, reference/candidate pair (compatible + incompatible), reference binding/fidelity (bound/ambiguous/unavailable), reference fidelity+contract independence, bounded context (adequate/correlated/ambiguous/unavailable/omission/truncation/fidelity-mismatch/blocked), many-regions-one-target, fidelity-fail-contract-pass, plus malformed JSON, unsupported schema version, and missing-screenshot negative fixtures. This corpus is what backed the packaged real-browser proof in §11.
105
+
106
+ ## 13. Repository hygiene and commit
107
+
108
+ - `git status --short` before commit: only `tests/support/evidenceFixtures.ts` (modified), `viewer/src/components/ReferenceRegionOverlaySvg.tsx` (modified), `viewer/src/components/TargetOverlaySvg.tsx` (modified), `tests/browser/viewerIntegratedAcceptance.test.ts` (new), `tests/browser/pwaHardening.test.ts` (new), plus this report (new).
109
+ - All packed/consumer/PWA-profile/corpus/log/cache state remains exclusively under `.my-dev-kit-workflow/` (gitignored) — confirmed nothing outside it was touched.
110
+ - `package.json` version confirmed unchanged at `0.7.0` throughout.
111
+
112
+ ## 14. What this batch does NOT establish
113
+
114
+ - Not release-ready, not publish-ready, not cross-platform-verified.
115
+ - `VERSION_BUMP: NONE`. `PUBLICATION_ACTIONS: NONE`. Nothing was tagged, pushed, or published.
116
+ - Standalone/installed-PWA behavioral proof did not exceed CDP command-acceptance (matchMedia did not reflect it) — this is a genuine residual gap, not a success to build on without further investigation.
117
+ - The broader hardened-documentation-and-implementation-completeness audit (the stage after this one) was explicitly **not** performed here.
118
+ - Symlink/junction-escape raw-evidence attack cases (task §30) were not re-exercised with new dedicated tests in this batch; the existing raw-evidence-safety mechanism (exact-identity artifact-detail resolution, Batch 2/4/7) was re-confirmed structurally but not stress-tested against new filesystem-escape vectors. Recorded as a residual risk, not closed.
119
+
120
+ ## 15. Remaining risks / residual scope
121
+
122
+ 1. Standalone-mode proof strength is below what the task's tier-B ("behavioral proof via CDP/app-mode") describes — worth a follow-up investigation into why `Emulation.setEmulatedMedia` didn't take effect in this Chromium build.
123
+ 2. Symlink/junction raw-evidence-escape cases remain untested by a dedicated new test (§30 residual).
124
+ 3. The 20-item acceptance matrix (task §69, items A–T) is satisfied by a mix of this batch's 3 new dedicated tests (L, M, N) plus the already-passing, re-confirmed test suites from Batches 3–7 for the remaining items — this batch did not write a from-scratch dedicated test for every letter independently where an existing one already provides equivalent real-browser proof.
125
+
126
+ ## 16. Verdict
127
+
128
+ `PASS_V08_BATCH8_INTEGRATED_VIEWER_ACCEPTANCE` — full validation chain green, all three named coverage gaps closed with new real-browser proof, one real accessibility defect found and fixed, PWA live hardening genuinely exercised for the first time with its hard stale-evidence gate holding, and the packaged/installed candidate proven to work end-to-end in a real browser with read-only evidence-root integrity confirmed. `IMPLEMENTATION_BATCHES_STATUS: ALL_8_IMPLEMENTATION_BATCHES_PASS`. `NEXT_STAGE_READINESS`: ready to proceed to the separate hardened-documentation-and-implementation-completeness audit stage — not to release preparation.
@@ -0,0 +1,223 @@
1
+ # v0.8 Batch 3 — Runtime Observation Inspection and SVG Overlays — Implementation Report
2
+
3
+ ## 1. Starting state
4
+
5
+ - Branch: `master`
6
+ - Starting HEAD: `be82055e29ca8d12cee61ae933dc85e6af3f2b9f` ("feat: add v0.8 viewer evidence indexing and readers")
7
+ - `origin/master` after `git fetch`: `a1de8ac01e1367b60021cb04226f56369fa2debb`
8
+ - `git rev-list --left-right --count origin/master...HEAD`: `0 2` — local is exactly Batch 1 + Batch 2 ahead of origin, no divergence.
9
+ - Starting `git status --short`: clean.
10
+ - Package version confirmed `0.7.0` throughout; never bumped.
11
+
12
+ ## 2. Predecessor reports inspected
13
+
14
+ Read both local reports in full (not console summaries):
15
+
16
+ - `docs/reports/v0.8-viewer-runtime-pwa-batch1.md` — confirmed host `127.0.0.1`/port `4319`, `src/viewerServer/httpServer.ts`/`viewerService.ts` ownership, PWA `navigateFallbackDenylist: [/^\/api\//]`.
17
+ - `docs/reports/v0.8-evidence-index-readers-batch2.md` — confirmed exact module/API details reused unchanged this batch: `evidence/index.ts#loadArtifactByHandle`/`buildEvidenceIndexMetadata`, `evidence/handles.ts` (`<family-slug>:<percent-encoded relativeDir>`), `evidence/pathSafety.ts#resolveContainedDir` (including its Batch 2 forward-slash-root bugfix - re-used as-is, not re-litigated), `evidence/classify.ts#ClassifiedRecord`/`ViewerSupportState`, `evidence/projection.ts#EvidenceMetadataRecord`/`EvidenceArtifactDetail`, `GET /api/index`/`GET /api/artifacts/<handle>`/`GET /api/media/<handle>/<role>` exact semantics/status codes, `viewer/src/hooks/useEvidenceIndex.ts`/`useArtifactDetail.ts`, `viewer/src/components/EvidenceList.tsx`/`ArtifactPreview.tsx`. No parallel API was created; every Batch 3 addition is additive to this exact boundary.
18
+
19
+ ## 3. Frozen planning authority inspected
20
+
21
+ `docs/DOCUMENTATION_PRESERVATION_POLICY.md`, `docs/PROJECT_MILESTONES.md` (Milestone 8), `docs/ROADMAP.md` (v0.8), `docs/plans/v0.8-implementation-plan.md` (Batch 3 section + cross-batch invariants §7) — all previously read in full during Batches 1-2, re-confirmed unchanged. `docs/ARCHITECTURE.md`, `docs/CONTRACTS.md` (media/schema-version constants, previously read in full), `docs/WORKFLOWS.md`, `docs/COMMANDS.md` (`view` section, then edited), `docs/DEVELOPMENT.md`. New this batch: `src/domain/schema.ts` (full `TargetGeometry`/`TargetEvidenceRecord`/`PageEvidence`-shape/`ScrollScenarioEvidence` read), `src/domain/relationships.ts` (`deriveLayoutRelationships` full signature/result type), `src/browser/evidenceCapture.ts` (`capturePageEvidence`/`captureResolvedTargetRecord` - the coordinate-audit source), `src/browser/chromiumAdapter.ts` (screenshot capture call, context creation), `src/artifacts/artifactReader.ts`, `src/viewerServer/httpServer.ts`, `src/viewerServer/evidence/*`, `viewer/src/*`, `tests/unit/relationshipDerivation.test.ts` (unresolved-target fixture pattern reused), `tests/unit/cliFrontendContracts.test.ts` (observation fixture pattern already reused since Batch 2).
22
+
23
+ Confirmed Batch 3's title/scope in `docs/plans/v0.8-implementation-plan.md` match the task exactly; no material difference found.
24
+
25
+ ## 4. Prior-path audit (task §6)
26
+
27
+ Inspected `Z:\Users\newuser\Projects\`: exactly one sibling workflow directory exists, `my-frontend-observer.my-dev-kit-workflow` (correctly separated). No malformed duplicate (missing-separator variant) was found at any location - the two candidate paths given in the task text were in fact identical strings, so there was nothing to distinguish. Neither location was moved, deleted, or reused; Batch 3's own work used exclusively `...\my-dev-kit-workflow\v0.8\batch-03`.
28
+
29
+ ## 5. WORKFLOW_ROOT and my-dev-kit retrieval
30
+
31
+ `WORKFLOW_ROOT` = `Z:\Users\newuser\Projects\my-frontend-observer.my-dev-kit-workflow\v0.8\batch-03`. Index built successfully:
32
+
33
+ ```
34
+ npx @dailephd/my-dev-kit@latest index --root . --src src --src tests --src viewer --out "<WORKFLOW_ROOT>\my-dev-kit-index" --call-graph --json
35
+ ```
36
+
37
+ All seven required searches were run (observation geometry ownership, relationship ownership, scroll/visibility/overflow evidence, Batch 2 projection/API ownership, viewer React selection/data loading, screenshot coordinate semantics, plus the general index build). Results consistently pointed at the same files direct inspection then confirmed in detail (`src/domain/schema.ts`, `src/domain/relationships.ts`, `src/browser/evidenceCapture.ts`, `src/browser/chromiumAdapter.ts`, `src/viewerServer/evidence/*`) - no `lookup`/`source`/`slice` follow-up was needed since the searches were unambiguous and direct file reads (§3) established the exact contracts.
38
+
39
+ ## 6. Coordinate audit (task §9 - the load-bearing decision)
40
+
41
+ Established from direct source inspection, not assumption:
42
+
43
+ - **Target geometry**: `src/browser/evidenceCapture.ts#captureResolvedTargetRecord` calls `el.getBoundingClientRect()` inside `handle.evaluate(...)`. This is viewport-relative CSS pixels (origin at the current viewport's top-left), captured from the same live page state the screenshot is taken from immediately after (same function/request lifecycle - `docs/ARCHITECTURE.md`'s existing "same live page/readiness state" invariant, unchanged by this batch).
44
+ - **Screenshot**: `src/browser/chromiumAdapter.ts` calls `page.screenshot({type:'png'})` with no `fullPage` option - Playwright's default is `fullPage: false`, capturing exactly the current viewport at the current scroll position.
45
+ - **Device scale factor**: `browser.newContext({viewport: {width, height}})` never sets `deviceScaleFactor` anywhere in this codebase, so Playwright's own default (`1`) applies to every observation this repository can currently produce. Consequence: the screenshot PNG's raw pixel dimensions equal `requestConfig.viewport.width × requestConfig.viewport.height` exactly - **1 CSS pixel = 1 PNG pixel** for every currently-producible observation.
46
+ - **`devicePixelRatio` disposition**: captured as `pageEvidence.devicePixelRatio` (`window.devicePixelRatio`, always `1` under the context above) - kept as **informational observation-level display evidence only**. It is never read by any Batch 3 geometry/coordinate code path (`grep`-verified: the only production reference to `devicePixelRatio` outside `evidenceCapture.ts` itself is the read-only display line in `ObservationInspector.tsx`).
47
+ - **Canonical viewport source**: `requestConfig.viewport` (`{width, height}`), a required, strongly-typed field validated on every `ObservationArtifact` (unlike the loosely-typed `pageEvidence: Record<string, EvidenceField<unknown>>` bag, which a hand-constructed test fixture could in principle omit fields from) - chosen as the authoritative SVG `viewBox` source for exactly this reason.
48
+
49
+ **Conclusion**: no coordinate rewriting is needed or performed. The SVG `viewBox` is set to `0 0 {requestConfig.viewport.width} {requestConfig.viewport.height}` - the exact frame `getBoundingClientRect()` already used - and the screenshot `<image>` fills that same viewBox (`preserveAspectRatio="none"`, safe here specifically because the two frames are pixel-identical per the above). Target rectangles use `geometry.x/y/width/height` completely unchanged. This is also robust against a hypothetical future capture path using a different `deviceScaleFactor`, because the `<image>`/viewBox scaling is browser-native presentation behavior, never a manual multiplication in this codebase - satisfying task §9's explicit preference for a `viewBox`-based presentation mapping over evidence rewriting. No `BLOCKED_V08_BATCH3_COORDINATE_MAPPING_INADEQUATE` condition was found.
50
+
51
+ ## 7. Observation-view projection architecture
52
+
53
+ Deliberately **not** a new server-side artifact-detail endpoint. The existing Batch 2 `GET /api/artifacts/<handle>` already returns the full, already-validated `ObservationArtifact` (targetEvidence, pageEvidence, requestConfig, screenshot field, completion, diagnostics, provenance, browser) unchanged - everything the target/observation inspector needs. Batch 3's "projection" is therefore two things:
54
+
55
+ 1. **One additive server-side computation** (`src/viewerServer/evidence/observationView.ts#getObservationRelationships`, exposed as `GET /api/observations/<handle>/relationships`) - the only genuinely new derivation this batch performs, and it is a thin, defense-in-depth-wrapped pass-through to the existing canonical `deriveLayoutRelationships` (§8). Ephemeral: computed fresh per request, never persisted, never a new artifact family.
56
+ 2. **Client-side presentation reshaping only** (`viewer/src/observation/targetOrder.ts#orderedTargets`) - selects/orders already-fetched fields (configured-target order, `hasGeometry` flag), explicitly not evidence derivation (frozen plan §27 permits "selection; filtering; formatting").
57
+
58
+ Both are ephemeral, in-memory, per-request/per-render, and derived only from already-validated canonical domain values and canonical relationship-engine results - no `viewer.json`, no new artifact family, no mutation of `ObservationArtifact`.
59
+
60
+ ## 8. Canonical relationship-engine reuse
61
+
62
+ `src/viewerServer/evidence/observationView.ts` calls `deriveLayoutRelationships` (`src/domain/relationships.ts`) exactly once, unchanged, against the already-classified, already-validated `ObservationArtifact` - the same function `docs/ARCHITECTURE.md`'s v0.4 architecture section documents as "the one canonical pure derivation." No relationship predicate (overlap, relative width, ordering, containment, fit, sequencing, page-width fit) is reimplemented anywhere in `src/viewerServer/` or `viewer/src/`. Proven by an exact-equality test (`tests/unit/observationRelationshipsServer.test.ts` "returns exactly the canonical `deriveLayoutRelationships(...)` result... never a second computation") that independently re-derives the same graph directly from the persisted artifact and asserts `toEqual` against the HTTP response body.
63
+
64
+ ## 9. Screenshot loading path
65
+
66
+ Unchanged Batch 2 mechanism: `viewer/src/components/TargetOverlaySvg.tsx`'s `<image href={`/api/media/${handle}/screenshot`}>` - the same handle already used for `/api/artifacts/<handle>`, the same `screenshot` media role Batch 2 already implemented (`mediaResolver.ts`, unmodified). No new media role, no local path, no `file://`, no base64 embedding, no new viewer-owned copy of the bytes. Loaded only when the observation's visual workspace actually renders (i.e., only after a user selects a supported `observation` record) - never eagerly for the whole index.
67
+
68
+ ## 10. SVG component/layout
69
+
70
+ `viewer/src/components/TargetOverlaySvg.tsx`: root `<svg viewBox="0 0 {w} {h}">` (§6); one `<image>` filling it; one `<rect>` per target with usable geometry (`role="button"`, keyboard-operable, `data-target-name` for identity); one `<text>` label per rectangle when the labels toggle is on; one `<line>` per pairwise relationship whose both endpoints have geometry (drawn between rectangle centers), only when the relationships toggle is on. `viewer/src/components/{TargetList,ObservationInspector,EvidenceFieldView,ObservationWorkspace}.tsx` provide the surrounding three-pane layout (Targets | Screenshot+SVG | Inspector) nested inside the existing Batch 1 `app-shell__workspace` region - the outer nav/details shell structure is untouched.
71
+
72
+ ## 11. Target selection architecture
73
+
74
+ `viewer/src/components/ObservationWorkspace.tsx` holds `selected: string | undefined` (React `useState`, presentation-only, reset via a `useEffect` keyed on `handle` whenever a different observation is selected - task §17's "changing observation resets or safely rebinds selection" requirement). Both the target-list `<button>` and the SVG `<rect>` call the same `onSelect(name)` callback using the target's existing stable `name`; both re-render their own `aria-pressed`/selected-class state from the single shared `selected` value, and the inspector reads the same value - genuine bidirectional synchronization through one source of truth, not two parallel selection states. Proven in real Chromium (`tests/browser/observationSvgWorkspace.test.ts`, two dedicated tests: SVG→list/inspector and list→SVG).
75
+
76
+ ## 12. Unresolved-target behavior
77
+
78
+ `orderedTargets()`'s `hasGeometry` is `true` only when `geometry.state` is `'available'` or `'partial'` - never merely because the target is configured. `TargetOverlaySvg` skips rendering entirely for any target without usable geometry (`geometryOf()` returns `undefined`, the `.map` callback returns `null`). No `x=0 y=0 width=0 height=0` fallback exists anywhere in the code. The target remains fully selectable from `TargetList` (shown with its real resolution status, e.g. `not-found (no geometry)`) and its canonical resolution/reason evidence is shown honestly in `ObservationInspector`. Proven with a real fixture (`missingWidget`, `not-found`) at the unit, server, and real-Chromium levels (`tests/unit/observationCoordinateMapping.test.ts`, `observationRelationshipsServer.test.ts`, `tests/browser/observationSvgWorkspace.test.ts`).
79
+
80
+ ## 13. Overlay controls
81
+
82
+ Three independently toggleable controls (`ObservationWorkspace`'s `OverlayToggles` state): **geometry** (target rectangles), **labels** (target-name text, disabled/hidden when geometry is off, since a label with no rectangle would be presentation-meaningless), **relationships** (connector lines). Toggling never refetches or alters the underlying artifact/graph - purely a render-time filter over already-fetched data.
83
+
84
+ ## 14. Visibility presentation
85
+
86
+ Not a separate overlay category in this batch: `TargetVisibility.visible` (existing canonical evidence, `derived` source) is shown honestly in the target inspector (`EvidenceFieldView` on `record.visibility`) exactly as the artifact states it - never inferred from screenshot pixels or from the mere existence of a rectangle. No new visibility threshold was introduced.
87
+
88
+ ## 15. Overflow presentation
89
+
90
+ `record.style` (display/position/overflow-x/overflow-y, existing canonical `computed-browser` evidence) and `record.layout` (scroll/client dimensions, existing canonical `browser` evidence) are shown honestly in the target inspector via `EvidenceFieldView`, unmodified and unreinterpreted. No SVG rectangle-intersection-based overflow inference exists anywhere in this batch.
91
+
92
+ ## 16. Scroll presentation
93
+
94
+ `ObservationInspector` distinguishes, using only existing canonical evidence: no scroll scenario configured (`artifact.scrollScenarioEvidence === undefined` - shown as an honest "No scroll scenario was configured for this observation" note) vs. available evidence (`initial`/`final`/`transition`/`scrollOwner`, shown via the existing `ScrollScenarioTransition`/`ScrollOwnerInterpretation` fields, `EvidenceFieldView` honoring the field's own `EvidenceField` state for `scrollOwner`). No browser action is re-run from the viewer; no historical trajectory is animated; no movement arrow is fabricated - the presentation is textual/status-only, exactly matching task §22's "if a faithful spatial overlay is not possible, show scroll evidence in the inspector/status layer."
95
+
96
+ ## 17. Inspector evidence exposed
97
+
98
+ **Target inspector**: resolution status, tag, semantics (role/name), semantic state, landmark, geometry, style, layout metrics, visibility, containment - each via `EvidenceFieldView`, which renders `available`/`partial` (with source and, for partial, the reason), `unavailable` (with reason), and `not-applicable` (with optional reason) distinctly - never a fabricated empty string or zero for missing evidence. Plus the relationships involving that target.
99
+
100
+ **Observation inspector**: observation id, request id, schema version, producer, viewport, page title, requested/final URL, device pixel ratio, document width/height, window scroll X/Y, completion state, diagnostics, scroll-scenario evidence (or its honest absence), and the full relationship list.
101
+
102
+ ## 18. Files created
103
+
104
+ - `src/viewerServer/evidence/observationView.ts`
105
+ - `viewer/src/types/observation.ts` (type-only re-exports of canonical Node domain types - erased at build time, no runtime coupling)
106
+ - `viewer/src/observation/targetOrder.ts`
107
+ - `viewer/src/hooks/useObservationRelationships.ts`
108
+ - `viewer/src/components/TargetOverlaySvg.tsx`, `TargetList.tsx`, `ObservationInspector.tsx`, `ObservationWorkspace.tsx`, `EvidenceFieldView.tsx`
109
+ - `tests/unit/observationCoordinateMapping.test.ts`, `observationRelationshipsServer.test.ts`, `observationFixtureSanity.test.ts`
110
+ - `tests/browser/observationSvgWorkspace.test.ts`
111
+ - `docs/reports/v0.8-observation-svg-inspection-batch3.md` (this file)
112
+
113
+ ## 19. Files modified
114
+
115
+ - `src/viewerServer/httpServer.ts` - added `GET /api/observations/<handle>/relationships` routing (405 for write methods, 404 unknown handle, 409 not-an-observation/not-currently-loadable/derivation-failed, 200 with the graph); `/api/status`, `/api/index`, `/api/artifacts/<handle>`, `/api/media/<handle>/<role>`, and static-asset serving byte-for-byte unchanged.
116
+ - `tests/support/evidenceFixtures.ts` - added `realisticPageEvidence`, `unresolvedTarget`, `buildRealPng` (a genuinely decodable solid-color PNG, distinct from the existing header-only `buildMinimalPng`), `writeRichObservationFixture`; extended `buildObservation` with optional `pageEvidence`/`viewport` parameters (backward compatible - existing call sites unaffected, default values unchanged).
117
+ - `viewer/src/components/ArtifactPreview.tsx` - branches to `ObservationWorkspace` for `family === 'observation'`; every other family's raw-JSON preview is unchanged.
118
+ - `viewer/src/styles/index.css` - additive rules for the new workspace/list/SVG/inspector UI.
119
+ - `tests/unit/viewerPwaBuild.test.ts` - added the explicit Batch 3 cache-boundary assertion (§20).
120
+ - `tests/browser/viewerEvidenceShell.test.ts` - two pre-existing Batch 2 assertions that selected an `observation` record to test the *generic* raw-JSON on-demand-load path and the *generic* no-visualization invariant now legitimately conflict with Batch 3's real observation workspace; both were repointed to a `comparison` record (which still exercises exactly the generic path/invariant they were written to protect) rather than weakened - the same kind of sanctioned evolution as Batch 1→2's placeholder-text update and Batch 2's `TST-401`.
121
+ - `docs/ARCHITECTURE.md`, `docs/COMMANDS.md` - new/updated Batch 3 sections (§6-§17 above, condensed).
122
+
123
+ ## 20. PWA cache verification
124
+
125
+ No `vite.config.ts`/service-worker change needed: `GET /api/observations/<handle>/relationships` lives under the already-denylisted `/api/` prefix. Extended `tests/unit/viewerPwaBuild.test.ts` with an explicit assertion against the real built `sw.js`: still exactly one `registerRoute` call, and the precache manifest contains no `/api/observations` entry.
126
+
127
+ ## 21. Tests added/modified and behavior protected
128
+
129
+ | Test file | Level | Protects |
130
+ |---|---|---|
131
+ | `observationFixtureSanity.test.ts` | unit | The new `buildRealPng` generator produces a genuinely decodable PNG at exact viewport pixel dimensions (underpins every browser-level assertion below). |
132
+ | `observationCoordinateMapping.test.ts` | unit | `requestConfig.viewport` presence/fidelity; geometry preserved exactly (fractional values, no rounding); `devicePixelRatio≠1` never multiplies geometry; `partial` geometry state preserved (never promoted/discarded); geometry partly outside the viewport preserved unclamped; relationship engine never includes the unresolved target. |
133
+ | `observationRelationshipsServer.test.ts` | unit/integration (real HTTP) | Server relationship route is byte-for-byte identical to a direct `deriveLayoutRelationships` call (proves no second engine); unresolved target excluded from pairwise relationships; a real geometric relationship (`header above footer`) is produced; non-observation handle → 409; unknown handle → 404; unsupported-version observation → 409; write methods → 405. |
134
+ | `viewerPwaBuild.test.ts` (+1) | build/integration | New route covered by the existing `/api/` denylist, no new runtime-caching rule. |
135
+ | `viewerEvidenceShell.test.ts` (2 updated) | browser | Generic Batch 2 on-demand-load/no-visualization invariants still hold for non-observation families after Batch 3. |
136
+ | `observationSvgWorkspace.test.ts` | browser (real Chromium, real persisted evidence) | Full real-browser proof - see §22. |
137
+
138
+ ## 22. Real-browser proof (task §33)
139
+
140
+ `tests/browser/observationSvgWorkspace.test.ts`, against the actual built `dist/viewer` PWA, the actual built loopback server, and one real observation (`writeRichObservationFixture`: real writer, genuinely decodable 800×600 PNG screenshot, two geometrically resolved targets plus one genuine `not-found` target). Five tests, all passing:
141
+
142
+ 1. Screenshot visibly loads (`<image href>` resolves to a real `/api/media/observation:...` URL); resolved targets (`header`, `sidebar`) have real `<rect>` elements whose `x`/`y`/`width`/`height` attributes exactly match the fixture's canonical geometry (`0,0,800,80` and `0,100,200,400`); the unresolved target (`missingWidget`) receives **no** `<rect>` at all and is shown honestly (`not-found`) in the target list.
143
+ 2. Selecting the SVG `<rect>` for `header` sets `aria-pressed="true"` on both the rect and its list entry, and the inspector shows `Target: header` with matching geometry text (`x:0 y:0 w:800 h:80`).
144
+ 3. Selecting `sidebar` from the target list sets `aria-pressed="true"` on the corresponding SVG rect and updates the inspector - the reverse-direction synchronization.
145
+ 4. The relationships panel shows the real canonical `above` relationship between `header`/`footer` labeled "Derived evidence", and at least one connector `<line>` is actually drawn between resolved targets.
146
+ 5. After `page.setViewportSize` changes (from 1000×800 to 1400×900), the rendered SVG element's bounding-box aspect ratio remains within 0.05 of the canonical 800:600 (4:3) ratio - screenshot and overlay scale together, proving the `viewBox` mapping holds under resize.
147
+
148
+ ## 23. Validation results
149
+
150
+ | Command | Result |
151
+ |---|---|
152
+ | `npm run typecheck` | **PASS** (zero errors, both `tsconfig.json` and `viewer/tsconfig.json`) |
153
+ | `npm run lint` | **PASS** (zero errors/warnings) |
154
+ | `npm test` | **PASS** — 1085/1085 tests, 59/59 files |
155
+ | `npm run build` | **PASS** — unchanged Node/library output plus `dist/viewerServer/evidence/observationView.js` and the rebuilt `dist/viewer/**` PWA |
156
+ | `npm run check:docs` | **PASS** — "Documentation check passed (17 required files)." |
157
+ | `npm run test:browser` | **PASS** — 137/137 tests, 13/13 files (real Chromium; run in full per task §37, not skipped) |
158
+ | `git diff --check` | **PASS** — no whitespace errors (only expected LF→CRLF notices) |
159
+
160
+ ## 24. Built viewer Batch 3 smoke (task §38)
161
+
162
+ Fixture: one real observation (`smoke-rich-obs`, 800×600) built via a one-off script (not committed, `WORKFLOW_ROOT\tmp`) calling the actual compiled `dist/artifacts/artifactWriter.js` directly - a real, genuinely decodable PNG screenshot; `header`/`sidebar`/`footer` (resolved, geometrically arranged to produce a real `above` relationship) plus `missingWidget` (`not-found`) - under `WORKFLOW_ROOT\smoke\evidence-root`.
163
+
164
+ Command: `node dist/cli.js view --root "<WORKFLOW_ROOT>\smoke\evidence-root" --port 4319 --no-open`
165
+
166
+ All required checks passed against the real running built server:
167
+
168
+ - `/api/status` → `200`, correct root.
169
+ - `/api/index` → one `observation`/`supported` record with `logicalId: "smoke-rich-obs"`.
170
+ - `/api/artifacts/<handle>` → `200`, full artifact, all four configured targets present.
171
+ - `/api/media/<handle>/screenshot` → `200 image/png`, 2789 bytes (a real, non-trivial PNG, not a stub).
172
+ - `/api/observations/<handle>/relationships` → `200`; `unresolvedTargets` correctly lists `missingWidget` (`not-found`); 18 pairwise relationships; a real `header`-`above`-`footer` relationship confirmed present.
173
+ - PWA still loads (`/`, `/manifest.webmanifest`, `/sw.js` all `200`); `sw.js` contains no `api/observations` reference (not runtime-cached).
174
+ - `netstat` confirmed `127.0.0.1:4319` only, never `0.0.0.0`.
175
+ - Server located by real PID and terminated with `taskkill /F`; a follow-up `netstat` confirmed the port was released.
176
+ - A post-shutdown listing of the smoke evidence root shows exactly the two files the fixture script wrote (`manifest.json`, `screenshot.png`) - no stray writes, no modification.
177
+
178
+ **Result: PASS.** Logs retained under `WORKFLOW_ROOT\logs\` (`smoke-server.log`, `smoke-checks-1.log`, `smoke-checks-2.log`, `smoke-checks-3.log`, `index-response.json`, `artifact-response.json`, `relationships-response.json`).
179
+
180
+ ## 25. Generated path inventory
181
+
182
+ | Path | Disposition |
183
+ |---|---|
184
+ | `WORKFLOW_ROOT\cache\npm` | Retained (npm cache from the my-dev-kit-index `npx` invocation) |
185
+ | `WORKFLOW_ROOT\tmp\vite-cache`, `WORKFLOW_ROOT\tmp\build-smoke-observation.mjs` | Retained (build cache empty again - Vite build mode doesn't populate it, same finding as Batches 1-2; the smoke-fixture script is dev/readiness tooling only, not committed) |
186
+ | `WORKFLOW_ROOT\logs\*` | Retained (smoke evidence, §24) |
187
+ | `WORKFLOW_ROOT\smoke\evidence-root` | Retained (real observation fixture tree built for the smoke test) |
188
+ | `WORKFLOW_ROOT\my-dev-kit-index\*` | Retained (successful index + cache-metadata, §5) |
189
+ | `WORKFLOW_ROOT\fixtures` | Retained, empty/unused (no committed deterministic repository fixture was needed - all Batch 3 fixtures are built programmatically via `tests/support/evidenceFixtures.ts`, matching the existing repository convention) |
190
+ | Repo-root `dist/` | Ordinary build output (gitignored); rebuilt cleanly by `scripts/clean.mjs` on every `npm run build` |
191
+ | Pre-existing repo-root `.my-dev-kit*`/`baselines`/`comparisons`/`contracts`/`evaluations`/`observations` | Pre-existing, empty, untouched (same finding as Batches 1-2) |
192
+
193
+ `WORKFLOW_ROOT`s for Batch 1 (`...\v0.8\batch-01`) and Batch 2 (`...\v0.8\batch-02`) were never targeted by any command in this session (verified) - preserved exactly as their own batches left them.
194
+
195
+ ## 26. Repository pollution check
196
+
197
+ `git status --short` before staging showed only the 8 modified + 12 new Batch-3-owned paths listed in §18/§19. No unexpected file or directory appeared anywhere in the repository. No malformed sibling Batch 3 workflow path exists (§4).
198
+
199
+ ## 27. Batch 1/2 regression check
200
+
201
+ **PASS.** All Batch 1 tests (`view` CLI, `127.0.0.1`/port `4319`, PWA shell/installability, cache boundary, server cleanup) and all Batch 2 tests (evidence indexing, unsupported-version handling, safe handles, on-demand artifact loading, media security, approved-reference image resolution, filesystem containment) pass unmodified except the two `viewerEvidenceShell.test.ts` updates described in §19, which preserve the exact invariants they originally protected while accounting for Batch 3's legitimate new observation-specific behavior.
202
+
203
+ ## 28. v0.1-v0.7 regression check
204
+
205
+ **PASS.** Every pre-v0.8 unit and browser test suite (`observe`, `compare`, `approve-baseline`, `save-change-contract`, `evaluate-contract`, `import-reference`, `approve-reference`, `evaluate-reference-fidelity`) remains covered and passing - none was touched by this batch's diff. `src/domain/`, `src/browser/`, `src/artifacts/*Writer.ts`, and every existing reader are byte-for-byte unchanged.
206
+
207
+ ## 29. Deviations
208
+
209
+ - None. Every task step (my-dev-kit retrieval, the coordinate audit, all required test categories, the full validation chain including `test:browser`, and the built-CLI smoke) was executed as specified.
210
+
211
+ ## 30. Remaining uncovered risks
212
+
213
+ - **The relationship overlay draws one `<line>` per pairwise relationship *kind*, not one per target pair.** For a pair of targets that satisfy several relationship families simultaneously (common for axis-aligned rectangles - e.g. `horizontally-overlapping` + `above` + `does-not-overlap` all being true at once), multiple overlapping connector lines are drawn between the same two centers. This is not a fabrication (every line corresponds to a genuinely distinct canonical relationship record), but it is visually noisy for observations with several targets; a later batch could deduplicate by center-pair or use per-kind visual differentiation.
214
+ - **The observation inspector's completion/diagnostic display is a flat list**, not yet organized by diagnostic severity/target - acceptable for this batch's scope (task §23/§24 list required fields, not a required layout), but could be revisited alongside Batch 4+'s own inspector needs.
215
+ - Batch 1's and Batch 2's previously reported risks (install-prompt "available" branch untested in headless Chromium, `findImportedReferenceDir`'s per-request re-walk) remain unresolved and out of this batch's scope.
216
+
217
+ ## 31. Out-of-scope confirmation
218
+
219
+ Confirmed absent from this batch's diff: before/after comparison UI, contract/change-scope visualization, external-reference visual inspection, side-by-side reference/candidate display, reference regions, reference/runtime binding, cross-reference selection, reference fidelity, independent visual-pane zoom/pan, synchronized lock, bounded-agent-context UI, source-correlation UI, arbitrary raw-file browsing, annotation, source editing, automatic target discovery, automatic binding, computer vision, pixel-diff scoring, image-to-code, cloud hosting, database, authentication, collaboration.
220
+
221
+ ## 32. Final verdict
222
+
223
+ Batch 3 ("Runtime observation inspection and SVG overlays") is implemented and independently validated: a developer can select a supported observation through the existing Batch 2 data boundary, see its screenshot loaded on demand through the existing safe media endpoint, inspect stable runtime targets overlaid via SVG in the observation's own canonical coordinate domain (no evidence rewriting, verified against a genuine `devicePixelRatio≠1` case), select targets from either the list or the SVG with full bidirectional synchronization, inspect complete canonical target/observation evidence honestly (including genuinely unresolved targets, which never receive fabricated geometry), and inspect canonical layout-relationship evidence computed exclusively by the existing `deriveLayoutRelationships` engine - proven at the unit, real-HTTP, real-Chromium, and real-built-CLI-smoke levels. No Batch 4+ visualization, no v0.9 annotation, and no release/publication action was taken. Package version remains `0.7.0`.