@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,687 @@
1
+ # v0.8 Pre-Release Readiness: Cross-Platform, Security, and Code-Rot Audit
2
+
3
+ ## 1. Purpose and scope
4
+
5
+ This report is the formal pre-release readiness audit for v0.8 (Interactive
6
+ Local Observation Viewer), following the completed and documentation-
7
+ reconciled implementation (Batches 1-8) and its entry-gate audit. This stage
8
+ is **pre-release readiness** - not release preparation, not version bump, not
9
+ publication. Package metadata remains `0.7.0` throughout and at the end of
10
+ this stage.
11
+
12
+ ## 2. Entry gate
13
+
14
+ Required predecessor report:
15
+ `docs/reports/v0.8-implementation-completeness-documentation-reconciliation.md`
16
+
17
+ Read in full. Its final verdict is
18
+ `PASS_V08_HARDENED_DOCUMENTATION_AND_IMPLEMENTATION_COMPLETENESS_AUDIT`, its
19
+ batch-gate matrix (§15) shows all 8 batches `Confirmed`/`PASS`, and its
20
+ next-stage decision (§36) is `READY_FOR_V08_PRERELEASE_READINESS`. Entry gate
21
+ satisfied.
22
+
23
+ ## 3. Starting repository state
24
+
25
+ - Branch: `master`
26
+ - Starting HEAD: `b75a68f0bc4e8d16b582e8aa28aaf831ed496ec1` ("docs: reconcile
27
+ v0.8 implementation and documentation")
28
+ - `origin/master`: `a1de8ac01e1367b60021cb04226f56369fa2debb`
29
+ - Ahead/behind at start: 9 ahead, 0 behind; `git merge-base --is-ancestor
30
+ origin/master HEAD` exited 0 (no divergence)
31
+ - `package.json` version / `package-lock.json` version /
32
+ `package-lock.json` `packages[''].version`: `0.7.0` / `0.7.0` / `0.7.0`
33
+ - Working tree clean
34
+
35
+ ## 4. Workflow filesystem policy
36
+
37
+ All generated readiness state lives under:
38
+ `.my-dev-kit-workflow/v0.8/prerelease-readiness/` (`tmp/`, `cache/npm/`,
39
+ `logs/`, `audit/`, `security/`, `code-rot/`, `pack/`, `consumer/`,
40
+ `fixtures/`, `smoke/`, `pwa-profile/`, `my-dev-kit-index/`, `ci/`). Nothing
41
+ was written to `C:`, Downloads, a prior batch workflow root, or a sibling
42
+ `my-frontend-observer.my-dev-kit-workflow` directory. Prior workflow roots
43
+ (Batches 1-8, the documentation-reconciliation audit) were inspected but not
44
+ migrated, deleted, or repurposed.
45
+
46
+ ## 5. Readiness architecture audit
47
+
48
+ Public behavior was traced end to end: CLI command (`observe`, `compare`,
49
+ `approve-baseline`, `save-change-contract`, `evaluate-contract`,
50
+ `import-reference`, `approve-reference`, `evaluate-reference-fidelity`,
51
+ `view`) -> package entry point (`src/cli.ts`) -> domain/application engine ->
52
+ tests -> packed validation. For `view`: `src/viewerServer/viewerService.ts`
53
+ -> `httpServer.ts` route handlers -> `evidence/*` (discovery, classify,
54
+ mediaResolver, observationView, comparisonView, evaluationView,
55
+ referenceView, contextSourceView) -> `viewer/src` React components -> PWA
56
+ service worker (`vite-plugin-pwa`). No gap found between documented public
57
+ behavior and actual implementation. `PASS`.
58
+
59
+ ## 6. Duplicate-engine audit
60
+
61
+ Checked for a second implementation of each canonical engine named in the
62
+ task (`deriveLayoutRelationships`, `compareObservations`,
63
+ `evaluateFrontendContract`, `evaluateReferenceCandidateCompatibility`,
64
+ `evaluateReferenceRuntimeBindings`, `evaluateReferenceCandidateFidelity`,
65
+ `projectBoundedAgentContext`, `deriveRuntimeStaticCorrelations`). Each has
66
+ exactly one domain-layer definition. `evaluateReferenceCandidateFidelity`
67
+ also has a distinct `evaluateReferenceCandidateFidelityFromArtifactRoots` in
68
+ the application layer - a thin artifact-reading wrapper around the same
69
+ domain function, matching this codebase's established layering (mirrors
70
+ `evaluateAndPersistFromArtifactRoots` elsewhere), not a duplicate
71
+ implementation. `PASS`, no findings.
72
+
73
+ ## 7. `my-dev-kit` retrieval
74
+
75
+ `npx @dailephd/my-dev-kit@latest index/search` was not available in this
76
+ execution environment (no network path to that package in the sandbox this
77
+ task ran in). Retrieval and architecture mapping were instead performed
78
+ directly against the repository with `git grep`, `Grep`, and manual read-
79
+ through of `src/`, `viewer/src/`, `scripts/`, and `.github/workflows/`,
80
+ covering the same surfaces the mandated searches target (CLI/package
81
+ surface, viewer server/security, canonical engines, PWA, CI, potential rot).
82
+ `MY_DEV_KIT_INDEX`: not produced (tool unavailable); the architecture and
83
+ code-rot audits below are the substitute evidence.
84
+
85
+ ## 8. Baseline local validation (before corrections)
86
+
87
+ Run against the starting HEAD, in order:
88
+
89
+ | Command | Result |
90
+ |---|---|
91
+ | `npm run typecheck` | PASS, clean |
92
+ | `npm run lint` | PASS, clean |
93
+ | `npm test` | PASS - 63 files, 1156 tests |
94
+ | `npm run build` | PASS |
95
+ | `npm run check:docs` | PASS - 17 required files |
96
+ | `npm run test:browser` | PASS, but one test (`referenceBindingFidelityWorkspace.test.ts`) failed reproducibly on reruns under full-suite parallel load (see §14, Flakes) |
97
+ | `npm run test:security` | PASS, but scope gap identified (see §9) |
98
+
99
+ ## 9. v0.8 cross-platform packed-viewer readiness gap (found and closed)
100
+
101
+ `.github/workflows/pre-release-readiness.yml`'s matrix job ran only
102
+ `scripts/ci/runPackedObservationSmoke.mjs` - installed-tarball proof of
103
+ `observe`/`compare` only, never the v0.8 viewer. `npm run test:security`
104
+ covered only `tests/unit/policy.test.ts` +
105
+ `tests/browser/chromiumAdapter.test.ts` (pre-v0.8 browser-navigation
106
+ policy) - none of the viewer/evidence-server security surface.
107
+
108
+ `CI_READINESS_GAP_FOUND: YES`. Closed by:
109
+
110
+ - **`scripts/ci/runPackedViewerSmoke.mjs`** (new): installs the exact
111
+ candidate tarball into a clean consumer, builds real evidence (one
112
+ observation with two resolved targets, one imported external reference
113
+ with a region, one approved reference) entirely through the installed
114
+ CLI, builds a real `BoundedAgentContextArtifact` through the installed
115
+ package's exported `projectBoundedAgentContext` (never hand-edited),
116
+ starts the installed `view` command with `--bindings-file` and
117
+ `--context-file`, and in real Chromium proves: loopback-only binding;
118
+ read-only API (`POST`/`PUT`/`PATCH`/`DELETE` -> 405 on every route);
119
+ `/api/status` and `/api/index`; encoded-path-traversal rejection against
120
+ both the media route and the asset-fallback route; the SVG target overlay
121
+ renders against real media; the reference view renders; no page-level
122
+ fatal error; service-worker registration/activation; the PWA manifest
123
+ (`standalone` display); the API-never-cached-as-authoritative boundary
124
+ (`caches.keys()`/`cache.keys()` inspected directly); and the hard
125
+ server-down stale-evidence gate (kill the viewer process, reload, confirm
126
+ `/api/index` is unreachable rather than silently serving prior data).
127
+ Readiness/CI infrastructure only - listed under neither `package.json`
128
+ `files` nor referenced by any shipped `dist` output.
129
+ - Wired into `pre-release-readiness.yml`'s existing matrix step sequence,
130
+ immediately after the pre-existing observation smoke, preserving that
131
+ step unchanged and using the same downloaded/verified candidate tarball.
132
+ - `npm run test:security` expanded to also run
133
+ `tests/unit/viewerServer.test.ts`, `viewerEvidenceServer.test.ts`,
134
+ `referenceViewerServer.test.ts`, `contextViewerServer.test.ts`,
135
+ `paths.test.ts`, `evidenceDiscovery.test.ts`, and
136
+ `tests/browser/pwaHardening.test.ts` (all pre-existing coverage that
137
+ simply wasn't wired into this script before).
138
+
139
+ `CI_CHANGES`: `.github/workflows/pre-release-readiness.yml` (added one step
140
+ + one artifact-upload path, matrix architecture unchanged - still exactly
141
+ one candidate tarball built once, verified by SHA-256 on every runner, no
142
+ platform packs its own); `package.json` `test:security` script expanded.
143
+
144
+ ## 10. Security audit
145
+
146
+ ### 10.1 A confirmed, fixed finding: symlinked media file escape
147
+
148
+ **SEC-1 (CRITICAL, fixed).** `src/viewerServer/evidence/mediaResolver.ts`'s
149
+ `checkExists()` used `fs.stat()`, which follows symlinks. The upstream
150
+ containment check (`resolveContainedFile`) only proves the *filename* is a
151
+ safe bare name inside an already-contained artifact directory - it never
152
+ proves that filename isn't itself a symlink/junction whose target resolves
153
+ outside the evidence root. A crafted evidence directory containing, e.g., a
154
+ `screenshot.png` that is actually a symlink to an arbitrary file elsewhere on
155
+ disk would have that file's real content served through
156
+ `/api/media/<handle>/screenshot`.
157
+
158
+ This was undetectable on the Windows development machine this repository's
159
+ Batches 1-8 and the entry-gate audit were built on (creating a file symlink
160
+ there requires a privilege this account lacks - confirmed `EPERM`), which is
161
+ exactly why the entry-gate report (§35) carried it forward as an untested
162
+ risk rather than a resolved one. A new regression test
163
+ (`tests/unit/viewerEvidenceServer.test.ts`, "a media filename that is itself
164
+ a symlink/junction...") creates such a symlink and asserts the linked
165
+ content is never served; it no-ops (with an explicit `EPERM`/`ENOSYS`
166
+ assertion) where symlink creation isn't permitted, and ran for real on the
167
+ Linux CI matrix job, where it caught the vulnerability on the first CI run
168
+ of the un-fixed candidate.
169
+
170
+ **Fix**: `checkExists()` now uses `fs.lstat()` and rejects any entry that
171
+ isn't `isFile()` - a symlink's `lstat().isFile()` is `false`, so the media
172
+ route now refuses to serve through a symlinked filename at all, closing the
173
+ escape without weakening any legitimate behavior. Verified: the regression
174
+ test passed on the Linux and macOS matrix runners in the corrected candidate
175
+ CI run (see §13); Windows still no-ops on this specific test (symlink
176
+ creation unsupported for this account) but the fix itself is
177
+ platform-agnostic (`lstat` behaves identically everywhere) and the
178
+ Windows-specific traversal/absolute-path tests in the same file continue to
179
+ pass.
180
+
181
+ ### 10.2 Loopback network security
182
+
183
+ `src/viewerServer/httpServer.ts`'s server is created via plain
184
+ `node:http.createServer` and bound explicitly to `127.0.0.1` by
185
+ `viewerService.ts`/`port.ts` (never `0.0.0.0`, `::`, or a LAN address).
186
+ Verified by live listener behavior, not source inspection alone: both the
187
+ local packed-viewer smoke and the CI packed-viewer smoke (all three
188
+ platforms) assert `viewerUrl.startsWith('http://127.0.0.1:')` against the
189
+ actual bound socket address. `tests/unit/viewerServer.test.ts` additionally
190
+ asserts the reported URL and default-host behavior directly. `PASS`.
191
+
192
+ ### 10.3 Observer/browser security regression (pre-existing, re-verified)
193
+
194
+ `npm run test:security` (expanded, see §9) reruns `policy.test.ts` (http/
195
+ https-only, loopback-only, credential-bearing-URL rejection) and
196
+ `chromiumAdapter.test.ts` (redirect/subresource/popup/download/timeout/
197
+ cleanup/target-immutability behavior) unchanged. Both pass. No weakening of
198
+ existing security behavior was made to accommodate viewer work. `PASS`.
199
+
200
+ ### 10.4 Viewer filesystem boundary
201
+
202
+ Re-proven via `tests/unit/viewerEvidenceServer.test.ts` and
203
+ `tests/unit/viewerServer.test.ts`: evidence-root containment (`../`
204
+ rejection, encoded-`../` rejection, absolute Windows-path rejection,
205
+ absolute POSIX-path rejection, unknown-handle rejection, no generic
206
+ file-server behavior for repository/source files), plus the new
207
+ symlink/junction-escape regression from §10.1. `SYMLINK_JUNCTION_SECURITY`:
208
+ `PASS` (Linux/macOS CI, real symlink), `NOT_SUPPORTED_ON_CURRENT_LOCAL_PLATFORM`
209
+ (this Windows dev machine's account). `PASS` overall.
210
+
211
+ ### 10.5 `EvidenceReference`/static-candidate non-path semantics
212
+
213
+ `EvidenceReference.path` values and `file:...`/`symbol:...` static
214
+ correlation candidate ids are only ever used as opaque display/provenance
215
+ strings in `viewer/src` and `src/domain/*` - grepped for any
216
+ `fs.`/`open`/`require`/dynamic-import use of these fields; none found. They
217
+ are never resolved as filesystem paths, URLs, shell input, or source-open
218
+ targets. `PASS`.
219
+
220
+ ### 10.6 `--bindings-file` / `--context-file` security
221
+
222
+ Both are explicit local CLI inputs read once at startup
223
+ (`loadBindingsFile`/`loadContextFile` in `src/cli.ts`), parsed as JSON,
224
+ structurally validated (`isValidBoundedAgentContextArtifact` for context;
225
+ the bindings wrapper shape for bindings), held only in server memory
226
+ (`ViewerServerState`), never persisted, never rewritten, and never exposed
227
+ as a browser-controllable path - no `/api/` route accepts a replacement file
228
+ path for either. Confirmed live in the packed-viewer smoke (both flags
229
+ accepted, both file contents reflected only through their respective `/api/`
230
+ views). `PASS`.
231
+
232
+ ### 10.7 Dynamic code/command execution audit
233
+
234
+ `git grep` for `eval(`, `new Function(`, `vm.`, `child_process`, `exec(`,
235
+ `execFile(`, `spawn(`, `shell:\s*true` across `src/`, `viewer/`, `scripts/`,
236
+ `tests/`:
237
+
238
+ - `src/viewerServer/openBrowser.ts` uses `child_process.spawn()` with a
239
+ fixed command (`cmd`/`open`/`xdg-open`) and an args array containing only
240
+ the viewer's own constructed loopback URL - never evidence- or
241
+ user-controlled input, no shell. Best-effort convenience only (failure is
242
+ non-fatal). **Not security-critical.**
243
+ - `scripts/ci/*.mjs`, `scripts/dev/*.mjs`, and `tests/browser/*.test.ts` use
244
+ `child_process.spawn`/`execFileSync` with fixed commands/args
245
+ (`npm`/`npx`/`node`) for build/test orchestration only - readiness/dev/test
246
+ infrastructure, never shipped in the package (`files` allowlist), never
247
+ fed attacker- or evidence-controlled strings. **Dev/test-only exposure,
248
+ non-blocking.**
249
+ - All other `.exec(` matches are `RegExp.prototype.exec` (false positives
250
+ of the grep pattern), not code execution.
251
+
252
+ No production/runtime code path allows evidence, request, or reference
253
+ content to become executable code or shell command text. `PASS`.
254
+
255
+ ### 10.8 CORS/origin audit
256
+
257
+ No `Access-Control-Allow-Origin` (or any other CORS) header is set anywhere
258
+ in `httpServer.ts` - confirmed by direct grep of every `writeHead` call
259
+ site. The viewer relies entirely on the browser's same-origin policy against
260
+ its own loopback origin. `PASS`.
261
+
262
+ ### 10.9 Security headers
263
+
264
+ `httpServer.ts` sets `content-type` and `cache-control: no-store` on every
265
+ dynamic response, and `content-type`/`content-length`/`cache-control` on
266
+ media/asset responses, but sets no `X-Content-Type-Options`,
267
+ `Content-Security-Policy`, or frame-embedding header. Given this is a
268
+ strictly loopback-only server serving only its own built assets (no
269
+ third-party content, no user-supplied HTML rendering, no cross-origin
270
+ exposure per §10.8), this is a low-risk gap, not an exploitable one.
271
+ **Deferred, non-blocking**: adding `X-Content-Type-Options: nosniff` (and
272
+ possibly a same-origin-only CSP) would be a reasonable focused addition for
273
+ a future hardening pass, but is not required for this stage's PASS and was
274
+ not added here to keep this stage's change surface narrow. `SECURITY_HEADER_AUDIT`:
275
+ justified current state (no critical/high gap; low-risk item recorded for
276
+ follow-up).
277
+
278
+ ### 10.10 Read-only API audit
279
+
280
+ Every `/api/*` route is reached through one shared method gate at the very
281
+ top of `handleRequest()`: any method other than `GET`/`HEAD` returns `405`
282
+ with `Allow: GET, HEAD` before any route-specific logic runs. This was
283
+ verified directly (not just by source inspection) against every route
284
+ family via the packed-viewer smoke's read-only-API loop
285
+ (`POST`/`PUT`/`PATCH`/`DELETE` against `/api/status`, all returning `405`)
286
+ and via `tests/unit/viewerServer.test.ts`/`viewerEvidenceServer.test.ts`'s
287
+ explicit write-method-rejection tests. No route mutates evidence; there is
288
+ no write path anywhere in the viewer server. `PASS`.
289
+
290
+ | Route | Methods | Input source | Mutation |
291
+ |---|---|---|---|
292
+ | `/api/status` | GET/HEAD | none | none |
293
+ | `/api/index` | GET/HEAD | evidence root (read) | none |
294
+ | `/api/artifacts/:handle` | GET/HEAD | opaque handle | none |
295
+ | `/api/media/:handle/:role` | GET/HEAD | opaque handle+role | none |
296
+ | `/api/observations/:handle/relationships` | GET/HEAD | opaque handle | none |
297
+ | `/api/comparisons/:handle/view` | GET/HEAD | opaque handle | none |
298
+ | `/api/evaluations/:handle/view` | GET/HEAD | opaque handle | none |
299
+ | `/api/references/:handle/view` | GET/HEAD | opaque handle | none |
300
+ | `/api/references/:ref/candidate/:cand/view` | GET/HEAD | opaque handles | none |
301
+ | `/api/references/:ref/candidate/:cand/bindings` | GET/HEAD | opaque handles + session bindings | none |
302
+ | `/api/references/:ref/candidate/:cand/fidelity` | GET/HEAD | opaque handles + session bindings | none |
303
+ | `/api/context` | GET/HEAD | session context state | none |
304
+
305
+ ### 10.11 PWA cache-storage boundary
306
+
307
+ `tests/browser/pwaHardening.test.ts` (real service worker, real Chromium)
308
+ and the packed-viewer smoke (direct `caches.keys()`/`cache.keys()`
309
+ inspection after real `/api/status` and `/api/index` fetches) both confirm
310
+ no `/api/*` response - status, index, artifact JSON, media, bindings,
311
+ fidelity, or context - is ever present in service-worker cache storage.
312
+ `vite.config.ts`'s workbox config declares zero `runtimeCaching` rules and
313
+ denylists `/^\/api\//` from the navigation fallback. `PASS`.
314
+
315
+ ### 10.12 Server-down stale-evidence hard gate
316
+
317
+ Repeated in both `pwaHardening.test.ts` (source-checkout, all platforms via
318
+ `npm run test:security`) and the new packed-viewer smoke (installed
319
+ candidate, all three CI platforms): start viewer -> load evidence -> service
320
+ worker active -> kill the server process -> reload the cached shell ->
321
+ `/api/index` unreachable -> no stale evidence presented as current.
322
+ `SERVER_DOWN_STALE_EVIDENCE: PASS` on Windows, Linux, and macOS against the
323
+ exact same candidate tarball (see §13).
324
+
325
+ ### 10.13 Package path/privacy audit
326
+
327
+ Grepped persisted-manifest and viewer-response code paths for
328
+ `bindingsFilePath`/`contextFilePath`/`targetsFilePath`/
329
+ `scrollScenarioFilePath`/`WORKFLOW_ROOT`/consumer-install-path/npm-cache-path
330
+ leakage. `runPackedObservationSmoke.mjs`'s existing assertions already
331
+ proved targets-file/scroll-scenario-file paths never leak into persisted
332
+ manifests; the same discipline holds for the viewer (bindings/context file
333
+ paths are read once at CLI startup and never attached to any `/api/`
334
+ response body - confirmed by reading `httpServer.ts`'s response payloads,
335
+ none of which include the file-path fields at all). `PASS`.
336
+
337
+ ### 10.14 Secret/credential audit
338
+
339
+ `git ls-files` shows no `.env`, `.pem`, `.key`, or `id_rsa*` files tracked.
340
+ `git grep` (case-insensitive) for private-key headers, and
341
+ `api_key`/`password`/`secret` literal-assignment patterns across tracked
342
+ source (excluding markdown and the lockfile) returned zero matches.
343
+ `.gitignore` already excludes `.my-dev-kit-workflow/`, `node_modules/`,
344
+ `dist/`, `*.tgz`. `PASS`.
345
+
346
+ ### 10.15 Dependency security audit
347
+
348
+ `npm audit --json` (all) and `npm audit --omit=dev --json` (runtime only)
349
+ were run before and after remediation:
350
+
351
+ | | Before | After |
352
+ |---|---|---|
353
+ | `npm audit` (all) | 2 moderate (both `vitest`/`@vitest/mocker`, path-traversal-in-mock-redirect) | **0** |
354
+ | `npm audit --omit=dev` (runtime) | 0 | 0 |
355
+
356
+ The runtime dependency tree (`playwright` is the only production
357
+ dependency) had zero findings throughout. The two moderate findings were
358
+ dev-only (`vitest`), with a compatible non-major fix available
359
+ (`vitest@4.1.11`). Applied (`npm install vitest@4.1.11 --save-exact`); full
360
+ local validation reran clean afterward (§12); no public contract changed.
361
+ Raw audit JSON stored under `.my-dev-kit-workflow/v0.8/prerelease-readiness/security/`.
362
+
363
+ **`BLOCKING_SECURITY_FINDINGS`: NONE** (SEC-1 above was found and fixed
364
+ within this stage, before candidate freeze; it is not an unresolved
365
+ blocker).
366
+
367
+ ## 11. Dependency freshness (code-rot: `STALE_DEPENDENCY`)
368
+
369
+ `npm outdated --json`, classified:
370
+
371
+ | Package | Current -> Latest | Classification |
372
+ |---|---|---|
373
+ | `vitest` | 4.1.11 (patched) -> 5.0.0 | Major; `LOW_RISK_STALE`, deferred (no security requirement beyond the patch already applied; a major bump is out of this stage's narrow-hardening scope) |
374
+ | `playwright` (runtime dep) | 1.62.1 -> 1.63.0 | Minor, same declared range (`^1.62.1`); `npm audit --omit=dev` clean; `LOW_RISK_STALE`, deferred (no forcing security issue) |
375
+ | `react`, `react-dom` | 19.2.8 -> 19.3.0 | Minor; `LOW_RISK_STALE`, deferred |
376
+ | `vite` | 8.2.2 -> 8.3.0 | Minor; `LOW_RISK_STALE`, deferred |
377
+ | `eslint`, `typescript-eslint` | minor version behind | `LOW_RISK_STALE`, deferred |
378
+ | `typescript` | 6.0.3 -> 7.0.2 | Major; `LOW_RISK_STALE`, deferred (a major TS upgrade is explicitly out of this stage's scope per task §43/100) |
379
+
380
+ No dependency is unsupported/EOL for its declared environment.
381
+ `UNSUPPORTED_EOL_DEPENDENCIES: NONE`. No further updates were made beyond
382
+ the security-driven `vitest` patch, per the "do not churn dependencies for
383
+ cosmetic freshness" instruction.
384
+
385
+ ## 12. Node engine / compatibility
386
+
387
+ `package.json` `engines.node`: `>=24`. This machine and the CI candidate job
388
+ both resolved Node `v24.11.0`/`24` respectively (CI: exact `node --version`
389
+ recorded per job, see §13's table). `MINIMUM_SUPPORTED_NODE_TEST: PASS`
390
+ (Node 24, the declared minimum, is what the existing CI matrix already
391
+ runs - `.github/workflows/pre-release-readiness.yml` pins `node-version:
392
+ '24'` throughout). The existing CI workflow does not additionally test a
393
+ newer floating Node line; adding one was not done in this stage to avoid
394
+ CI-architecture changes beyond the packed-viewer-smoke gap this stage was
395
+ scoped to close (task §98 forbids matrix redesign). `CURRENT_NODE_COMPATIBILITY:
396
+ NOT_REQUIRED` (not exercised beyond the declared minimum in this stage).
397
+
398
+ ## 13. Cross-platform CI validation
399
+
400
+ Two candidate cycles ran (within the task's two-correction-cycle limit):
401
+
402
+ ### 13.1 Cycle 1 - `55299e5` (initial candidate)
403
+
404
+ Pushed to `validation/v0.8-pre-release-readiness`, triggering run
405
+ [`34503201007`](https://github.com/dailephd/my-frontend-observer/actions/runs/34503201007).
406
+ **Result: FAILED at the candidate job** (`npm test`), before any tarball was
407
+ built or any matrix runner started (matrix job correctly skipped - no
408
+ platform built its own candidate).
409
+
410
+ Two real failures, both invisible on this session's Windows development
411
+ machine:
412
+
413
+ 1. The new symlink-escape regression test (§10.1) failed on Linux - it
414
+ *should* fail against the un-fixed `mediaResolver.ts`; this is exactly
415
+ the vulnerability being proven, not a test defect.
416
+ 2. `tests/unit/viewerPwaBuild.test.ts`'s denylist-pattern assertion failed
417
+ against an unminified `sw.js`/~2x-larger JS bundle. Root-caused to ten
418
+ test files' `beforeAll` build-fallback hooks (`if (!existsSync(dist))
419
+ execFileSync('npx', ['vite','build',...], { env: {...process.env} })`)
420
+ inheriting vitest's own `NODE_ENV=test` into the child build process.
421
+ This fallback path had never actually executed end-to-end in any prior
422
+ local session (`dist/` always pre-existed locally from an earlier
423
+ `npm run build`), so it silently carried this latent defect until a
424
+ genuinely fresh CI checkout exercised it for the first time.
425
+
426
+ Classified: **(1) security defect** (the exact gap this test suite exists
427
+ to close) and **(2) reproducible product/test-infrastructure defect** - not
428
+ flakes (see §14 for the actual flakes found and their evidence), not
429
+ infrastructure/platform unavailability. Both are `NEEDS_CORRECTION`-class
430
+ findings that were corrected within this stage's allowed retry budget.
431
+
432
+ ### 13.2 Correction
433
+
434
+ - `src/viewerServer/evidence/mediaResolver.ts`: `stat` -> `lstat`, reject
435
+ non-regular-file entries (§10.1).
436
+ - All ten `beforeAll` build-fallback hooks: added explicit
437
+ `NODE_ENV: 'production'` to the spawned `vite build`'s `env`.
438
+ - `tests/unit/viewerPwaBuild.test.ts`: relaxed the denylist-pattern regex to
439
+ tolerate minifier whitespace variation without weakening the semantic
440
+ assertion (the literal `/^\/api\//` denylist source must still be
441
+ present).
442
+
443
+ Full local validation reran clean (typecheck, lint, 1157 unit tests, build,
444
+ docs check, 178 browser tests, expanded security suite - see §14 for one
445
+ genuine local-only flake found and fixed along the way). Local packed-viewer
446
+ smoke rerun against a freshly rebuilt local tarball: `PASS`.
447
+
448
+ Committed as `d8eb0fc2b652ecf05a8c778b7ab5f1c32c18a3e9`
449
+ ("fix: harden v0.8 pre-release security and build reproducibility").
450
+ `validation/v0.8-pre-release-readiness` fast-forwarded and pushed.
451
+
452
+ ### 13.3 Cycle 2 - `d8eb0fc` (corrected candidate) - PASS
453
+
454
+ Run
455
+ [`34504220423`](https://github.com/dailephd/my-frontend-observer/actions/runs/34504220423),
456
+ head SHA `d8eb0fc2b652ecf05a8c778b7ab5f1c32c18a3e9` (verified to match the
457
+ validated candidate commit). **Conclusion: `success`.**
458
+
459
+ | Job | Conclusion |
460
+ |---|---|
461
+ | Package exact candidate (Linux, Node 24) | success (typecheck, lint, 1157 unit tests, 178 browser tests, expanded security suite, build, docs check, pack, SHA-256, upload - all steps green) |
462
+ | `ubuntu-latest` exact-candidate smoke | success |
463
+ | `macos-latest` exact-candidate smoke | success |
464
+ | `windows-latest` exact-candidate smoke | success |
465
+
466
+ Exactly one `candidate-package` artifact was uploaded (no duplicate/
467
+ independently-packed candidates), plus one `smoke-summary-<os>` artifact per
468
+ platform. Downloaded and inspected all four.
469
+
470
+ **Candidate tarball**: `my-frontend-observer-0.7.0.tgz`
471
+ **Candidate SHA-256** (as recorded by the candidate job and independently
472
+ recomputed locally after download - identical):
473
+ `b80729bc64b3b01378effd2b8aa3b7743ccedc46b3148ba0b1ff1ae5a4b68c55`
474
+
475
+ | Platform | Node version | Packed observation smoke | Packed viewer smoke | PWA/browser proof |
476
+ |---|---|---|---|---|
477
+ | Windows | v24.19.0 | PASS | PASS | PASS |
478
+ | Linux | v24.20.0 | PASS | PASS | PASS |
479
+ | macOS (arm64) | v24.20.0 | PASS | PASS | PASS |
480
+
481
+ Each platform's `viewer-smoke-summary.json` independently confirms:
482
+ `packageVersion: "0.7.0"`, loopback `viewerUrl`, `readOnlyApiOk`,
483
+ `traversalRejected`, `svgOverlayRendered`, `screenshotMediaLoaded`,
484
+ `referenceViewRendered`, `noPageErrors`, `serviceWorkerRegistered`,
485
+ `pwaManifestOk`, `apiNeverCached`, `serverDownStaleEvidenceGatePassed`, all
486
+ `true`, `result: "PASS"` - the exact same candidate tarball on all three
487
+ operating systems. Each platform's `smoke-summary.json` (pre-existing
488
+ observation/compare smoke) likewise shows `comparableCompareOk`,
489
+ `comparisonPathPrivacyPassed`, and `v05HelpCommandsExposed` all `true` -
490
+ pre-v0.8 packed workflows remain valid on the same candidate.
491
+
492
+ **`ACTUAL_OS_PWA_INSTALLATION_AUTOMATED: NO`** - each platform's smoke
493
+ proves manifest reachability, service-worker registration/activation, and
494
+ the cache-storage boundary at the browser level (real Chromium via
495
+ Playwright); none of the three CI runners attempt an actual OS-level "Add to
496
+ Home Screen"/installed-app launch, matching the entry-gate report's
497
+ already-documented boundary (browser-level CDP proof, not genuine platform
498
+ install).
499
+
500
+ **Cross-platform filesystem behavior**: the packed-viewer smoke exercises
501
+ evidence-root resolution, media-path handling, `--bindings-file`/
502
+ `--context-file` input, and traversal rejection identically on Windows and
503
+ POSIX runners via the same script logic (no OS-conditional assumptions in
504
+ `scripts/ci/runPackedViewerSmoke.mjs`); all three passed. `PASS`.
505
+
506
+ ## 14. Flakes
507
+
508
+ One genuine, evidence-backed local flake was found and fixed (not left
509
+ undiagnosed):
510
+
511
+ **`referenceBindingFidelityWorkspace.test.ts`** ("lock is also disabled for
512
+ a compatible-but-incoherent-aspect-ratio pair"): failed reproducibly on full
513
+ local `npm run test:browser` reruns (2 of the first 3 runs, under this
514
+ session's Windows machine's parallel-Chromium resource contention), passed
515
+ every time in isolation. Root cause: it asserted on `body` text immediately
516
+ after `expect.poll(() => lockButton.isEnabled()).toBe(false)` resolved - but
517
+ the button is *also* disabled while compatibility is still asynchronously
518
+ evaluating ("Evaluating compatibility..."), before the real settled reason
519
+ text appears. Fixed by polling the settled body text itself
520
+ (`expect.poll(() => page.textContent('body'), {...}).toContain(...)`)
521
+ instead of a single post-poll read. Verified stable across three subsequent
522
+ clean full-suite reruns (both default and reduced-worker-count local runs),
523
+ and passed on all three CI platforms in the final candidate run.
524
+
525
+ No other flake was observed or is being carried forward undiagnosed. The two
526
+ Cycle-1 failures (§13.1) were **not** flakes - both were reproducible,
527
+ root-caused, and fixed as real defects, per the task's flake-policy
528
+ distinction (a failure classified as a flake requires no deterministic
529
+ defect being found; both of those had one).
530
+
531
+ ## 15. Code-rot audit
532
+
533
+ ### 15.1 Search sweep
534
+
535
+ `git grep` across `src/`, `viewer/`, `scripts/` for
536
+ `TODO|FIXME|HACK|XXX|TEMPORARY|REMOVE AFTER|DEPRECATED|deprecated`: **zero
537
+ matches.** Across `tests/` for
538
+ `test\.skip|describe\.skip|it\.skip|test\.only|describe\.only|it\.only`:
539
+ **zero matches.** Across `src/`/`viewer/` for
540
+ `placeholder|legacy|compatibility shim|temporary workaround`
541
+ (case-insensitive): all matches are either (a) genuine, intentional
542
+ empty/loading-state UI text (the `.placeholder-note` CSS class used
543
+ throughout `viewer/src/components/*` for honest "No X recorded"/"Loading…"
544
+ states - not stale scaffolding, a consistent and still-current design
545
+ pattern), or (b) one doc-comment use of "legacy" correctly describing the
546
+ CSS-shorthand `--target` flag's continued-support status relative to the
547
+ canonical `--targets-file`/`locators` shape - accurate, not stale.
548
+
549
+ ### 15.2 Findings ledger
550
+
551
+ | ID | Category | File/path | Evidence | Risk | Disposition | Change made | Tests | Blocking |
552
+ |---|---|---|---|---|---|---|---|---|
553
+ | ROT-1 | `STALE_PLACEHOLDER` | `viewer/src/components/ArtifactPreview.tsx:25` | The empty-selection message read "No observation, comparison, contract, or reference viewing is implemented yet" - false since Batches 3-5 shipped exactly those workspaces (imported and rendered two lines below in the same file) | Low (user-visible, misleading) | `CORRECT` | Message simplified to "Select evidence from the list to load it on demand."; the one test asserting the stale string (`viewerShell.test.ts`) updated to match | `tests/browser/viewerShell.test.ts` reruns green | Non-blocking (readiness-narrow doc/text fix) |
554
+ | ROT-2 | `STALE_TEST` (over-fit assertion) | `tests/unit/viewerPwaBuild.test.ts:63` | Regex asserted on exact minified-output whitespace (`denylist:[/^\/api\//]`), fragile against minifier-environment variation | Low (test robustness, not product) | `CORRECT` | Regex relaxed to tolerate whitespace while preserving the semantic assertion | Green on Windows and CI Linux | Non-blocking |
555
+ | ROT-3 | `OBSOLETE_SCRIPT` (candidate, not acted on) | `scripts/dev/*.mjs` (5 files) | Not referenced by any `package.json` script name; manual dev-invocation only | Low | `KEEP_WITH_JUSTIFICATION` - each is a distinct manual dev smoke (compare, frontend-contracts unit+browser, scroll-scenario, targets-file) with no newer script providing equivalent coverage; not proven dead | None | N/A | Non-blocking |
556
+ | ROT-4 | `DEAD_CODE` (checked, none found) | repository-wide `src/**/*.ts` | Every non-test `.ts` file under `src/` has at least one cross-reference from `src/`, `viewer/`, `tests/`, or `scripts/` (checked via basename cross-reference sweep) | N/A | N/A - no finding | None | N/A | N/A |
557
+ | ROT-5 | `DUPLICATE_IMPLEMENTATION` (checked, none found) | canonical engines (§6) | One definition each; the one apparent second `evaluateReferenceCandidateFidelity*` match is a legitimate application-layer artifact-reading wrapper, not a duplicate | N/A | N/A - no finding | None | N/A | N/A |
558
+ | ROT-6 | `UNUSED_DEPENDENCY` (checked, none found) | `package.json` deps/devDeps | Every declared dependency has at least one config/source/tooling reference (`vite`: 95 files via config+build; `vitest`: 91 files; `playwright`: 20 files including production `src/browser/chromiumAdapter.ts`; all others similarly referenced) | N/A | N/A - no finding | None | N/A | N/A |
559
+ | ROT-7 | `STALE_CONFIG` (checked, none found) | `tsconfig.json`, `viewer/tsconfig.json`, `eslint.config.js` | `include`/`exclude` globs match only current, existing paths; no reference to a deleted directory | N/A | N/A - no finding | None | N/A | N/A |
560
+
561
+ No `TODO_FIXME_FINDINGS`, no `SKIPPED_DISABLED_TEST_FINDINGS`, no
562
+ `UNUSED_EXPORT_FINDINGS` beyond what's already covered by ROT-4/ROT-6.
563
+ `CODE_ROT_BLOCKERS: NONE`.
564
+
565
+ ### 15.3 Package/build/export audit
566
+
567
+ Clean-build proof: `rm -rf node_modules && npm ci && npm run build`
568
+ (prebuild's `scripts/clean.mjs` removes stale `dist` first, non-destructively
569
+ - no Git-level cleanup used) produced the same `dist/cli.js`, `dist/index.js`
570
+ (both referenced correctly by `package.json` `bin`/`exports`),
571
+ `dist/viewerServer/**`, and `dist/viewer/**` (PWA manifest/service
572
+ worker/icons) confirmed present in both `npm pack --dry-run --json` and the
573
+ actual packed tarball (see §16). No obsolete path in `files`/`bin`/
574
+ `exports`. `PASS`.
575
+
576
+ ## 16. Package audit
577
+
578
+ ### 16.1 Local dry-run and content audit
579
+
580
+ `npm pack --dry-run --json`: 285 files, ~3.0 MB unpacked. Inspected the full
581
+ file list: required v0.8 assets present (`dist/cli.js`, `dist/index.js`,
582
+ `dist/viewerServer/**`, `dist/viewer/**` including
583
+ `manifest.webmanifest`/`sw.js`/icons). No accidental content: zero matches
584
+ for `.my-dev-kit-workflow`, tarballs, logs, smoke data, browser profiles,
585
+ temporary binding/context files, coverage output, Git metadata, or local
586
+ caches. `docs/` (all `docs/*.md` including `docs/reports/*`) is intentionally
587
+ shipped per the pre-existing `files: ["dist", "README.md", "CHANGELOG.md",
588
+ "docs"]` allowlist - carried unchanged from v0.7, not a v0.8-introduced
589
+ defect. `UNEXPECTED_PACKED_FILES: NONE`. `PACKAGE_DRY_RUN: PASS`,
590
+ `PACKAGE_CONTENT_AUDIT: PASS`, `REQUIRED_VIEWER_PACKAGE_ASSETS: PASS`.
591
+
592
+ ### 16.2 Local actual tarball smoke
593
+
594
+ Built at `.my-dev-kit-workflow/v0.8/prerelease-readiness/pack/`
595
+ (`npm pack` with explicit destination `cwd`). SHA-256 (pre-correction
596
+ candidate, superseded by the CI-authoritative hash in §13.3 after the
597
+ correction commit):
598
+ `c5dfb7f93ddc90b984e22b2cae03e36c9bfe96d6875812f238b2c02b3291978a` (initial);
599
+ recomputed after the security/build-reproducibility fix and reran the local
600
+ packed-viewer smoke clean (§13.2). Installed into
601
+ `.my-dev-kit-workflow/v0.8/prerelease-readiness/consumer/` via
602
+ `scripts/ci/runPackedViewerSmoke.mjs` itself (which performs this install/
603
+ verify/run sequence): package identity, `bin`, `dist/viewer/**` all
604
+ resolved correctly from the consumer's own `node_modules`, never this
605
+ repository's `src/`/`dist/`. `--version`, `--help`, `view --help` all
606
+ correct. Viewer launched and passed the full local smoke assertion list
607
+ (§13.2). `LOCAL_PACKED_CANDIDATE_PATH`:
608
+ `.my-dev-kit-workflow/v0.8/prerelease-readiness/pack/my-frontend-observer-0.7.0.tgz`.
609
+ `LOCAL_CLEAN_CONSUMER: PASS`, `LOCAL_INSTALLED_CLI: PASS`,
610
+ `LOCAL_INSTALLED_VIEWER: PASS`.
611
+
612
+ The CI candidate job's tarball (§13.3) is the authoritative cross-platform
613
+ candidate; this local tarball is corroborating evidence only, per task
614
+ policy.
615
+
616
+ ## 17. Package version invariant
617
+
618
+ Checked before candidate freeze, after CI PASS, and immediately before this
619
+ report's commit - all three times: `package.json` version, `package-lock.json`
620
+ version, and `package-lock.json` `packages[''].version` were all `0.7.0`.
621
+ Unchanged throughout this entire stage.
622
+
623
+ ## 18. Repository hygiene
624
+
625
+ Both commits (`55299e5`, `d8eb0fc`) staged only their exact intended files
626
+ (never `git add -A`); `git diff --check` was run before each (only benign
627
+ LF/CRLF line-ending warnings, no real whitespace errors); `git status
628
+ --short` showed no untracked pollution before either commit. No tarball,
629
+ log, npm cache, consumer install, Chromium profile, or CI-downloaded
630
+ artifact was ever staged. `REPOSITORY_POLLUTION_CHECK: PASS`.
631
+
632
+ ## 19. Release-state invariant
633
+
634
+ No npm publication, no git tag, no GitHub Release, no push to `master`, no
635
+ version bump occurred at any point in this stage. The only remote push was
636
+ the `validation/v0.8-pre-release-readiness` branch (twice: initial push, then
637
+ a fast-forward to the corrected candidate) - readiness infrastructure only,
638
+ never merged, never tagged.
639
+
640
+ ## 20. Remaining non-blocking risks
641
+
642
+ - `X-Content-Type-Options`/CSP headers are not set on viewer responses
643
+ (§10.9) - low risk given the loopback-only, same-origin, no-third-party-
644
+ content design; worth a focused follow-up but not blocking.
645
+ - Several devDependencies (and `typescript`, a major version behind) are
646
+ stale but not security-required or EOL (§11) - deferred per "do not churn
647
+ dependencies for cosmetic freshness."
648
+ - `scripts/dev/*.mjs` (5 files) were not proven dead but also not
649
+ independently re-verified as still-invoked by any documented workflow in
650
+ this stage; kept with justification (§15.2, ROT-3) rather than removed.
651
+ - The CI Linux job resolved a newer Node 24 patch (v24.20.0/v24.19.0) than
652
+ this session's local Windows Node (v24.11.0); all are within the declared
653
+ `>=24` range and no incompatibility was observed, but the workflow does
654
+ not separately test the single newest stable Node line beyond its pinned
655
+ `'24'` (§12) - unchanged from the pre-existing CI architecture, not a
656
+ regression introduced here.
657
+
658
+ None of these rise to a blocking finding under this stage's PASS criteria.
659
+
660
+ ## 21. Final local validation (before candidate freeze, restated)
661
+
662
+ Rerun immediately before the corrected candidate commit (`d8eb0fc`) and
663
+ again confirmed clean after: `npm run typecheck`, `npm run lint`, `npm test`
664
+ (1157 tests), `npm run build`, `npm run check:docs`, `npm run test:browser`
665
+ (178 tests, stable across three consecutive full reruns), `npm run
666
+ test:security` (80 + 70 tests), `npm pack --dry-run --json`, `git diff
667
+ --check`. All passed.
668
+
669
+ ## 22. Verdict
670
+
671
+ **`PASS_READY_FOR_RELEASE_PREP`**
672
+
673
+ Entry-gate audit passed; source-checkout validation passes; security
674
+ validation passes with one real finding found and fixed within this stage
675
+ (SEC-1, symlink media escape) and no remaining blocking finding; code-rot
676
+ audit completed with one text fix and one test-robustness fix, no blocking
677
+ finding; dependencies have no blocking unsupported/security issue (0
678
+ findings after the `vitest` patch); package dry-run and local packed smoke
679
+ pass; CI produced exactly one candidate tarball, SHA-256 verified identical
680
+ on every platform; Windows, Linux, and macOS all pass, including the v0.8
681
+ packed viewer and its PWA/server-down hard gate; pre-v0.8 packed workflows
682
+ remain valid on the same candidate; the one reproducible CI failure cycle
683
+ was root-caused and corrected (not silently retried); the one genuine local
684
+ flake was diagnosed and fixed, not ignored; package version remains `0.7.0`
685
+ throughout; no publication/version-bump/tag/release action occurred.
686
+
687
+ `NEXT_STAGE_READINESS`: **`READY_FOR_V08_RELEASE_PREP`**