@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.
- package/CHANGELOG.md +397 -0
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/dist/application/browserCaptureService.d.ts +11 -0
- package/dist/application/browserCaptureService.js +12 -0
- package/dist/application/browserCaptureService.js.map +1 -0
- package/dist/application/comparisonService.d.ts +56 -0
- package/dist/application/comparisonService.js +77 -0
- package/dist/application/comparisonService.js.map +1 -0
- package/dist/application/externalReferencePersistenceService.d.ts +75 -0
- package/dist/application/externalReferencePersistenceService.js +182 -0
- package/dist/application/externalReferencePersistenceService.js.map +1 -0
- package/dist/application/frontendContractEvaluationService.d.ts +49 -0
- package/dist/application/frontendContractEvaluationService.js +112 -0
- package/dist/application/frontendContractEvaluationService.js.map +1 -0
- package/dist/application/frontendContractPersistenceService.d.ts +56 -0
- package/dist/application/frontendContractPersistenceService.js +91 -0
- package/dist/application/frontendContractPersistenceService.js.map +1 -0
- package/dist/application/observationPersistence.d.ts +59 -0
- package/dist/application/observationPersistence.js +79 -0
- package/dist/application/observationPersistence.js.map +1 -0
- package/dist/application/projectCheckService.d.ts +3 -0
- package/dist/application/projectCheckService.js +169 -0
- package/dist/application/projectCheckService.js.map +1 -0
- package/dist/application/projectWorkflowService.d.ts +46 -0
- package/dist/application/projectWorkflowService.js +92 -0
- package/dist/application/projectWorkflowService.js.map +1 -0
- package/dist/application/referenceFidelityEvaluationService.d.ts +28 -0
- package/dist/application/referenceFidelityEvaluationService.js +45 -0
- package/dist/application/referenceFidelityEvaluationService.js.map +1 -0
- package/dist/artifacts/artifactReader.d.ts +19 -0
- package/dist/artifacts/artifactReader.js +36 -0
- package/dist/artifacts/artifactReader.js.map +1 -0
- package/dist/artifacts/artifactWriter.d.ts +25 -0
- package/dist/artifacts/artifactWriter.js +68 -0
- package/dist/artifacts/artifactWriter.js.map +1 -0
- package/dist/artifacts/comparisonArtifactReader.d.ts +18 -0
- package/dist/artifacts/comparisonArtifactReader.js +35 -0
- package/dist/artifacts/comparisonArtifactReader.js.map +1 -0
- package/dist/artifacts/comparisonArtifactWriter.d.ts +41 -0
- package/dist/artifacts/comparisonArtifactWriter.js +67 -0
- package/dist/artifacts/comparisonArtifactWriter.js.map +1 -0
- package/dist/artifacts/externalReferenceArtifactReader.d.ts +18 -0
- package/dist/artifacts/externalReferenceArtifactReader.js +35 -0
- package/dist/artifacts/externalReferenceArtifactReader.js.map +1 -0
- package/dist/artifacts/externalReferenceArtifactWriter.d.ts +44 -0
- package/dist/artifacts/externalReferenceArtifactWriter.js +77 -0
- package/dist/artifacts/externalReferenceArtifactWriter.js.map +1 -0
- package/dist/artifacts/frontendContractArtifactReader.d.ts +24 -0
- package/dist/artifacts/frontendContractArtifactReader.js +47 -0
- package/dist/artifacts/frontendContractArtifactReader.js.map +1 -0
- package/dist/artifacts/frontendContractArtifactWriter.d.ts +34 -0
- package/dist/artifacts/frontendContractArtifactWriter.js +70 -0
- package/dist/artifacts/frontendContractArtifactWriter.js.map +1 -0
- package/dist/artifacts/frontendContractEvaluationArtifactReader.d.ts +17 -0
- package/dist/artifacts/frontendContractEvaluationArtifactReader.js +34 -0
- package/dist/artifacts/frontendContractEvaluationArtifactReader.js.map +1 -0
- package/dist/artifacts/frontendContractEvaluationArtifactWriter.d.ts +32 -0
- package/dist/artifacts/frontendContractEvaluationArtifactWriter.js +58 -0
- package/dist/artifacts/frontendContractEvaluationArtifactWriter.js.map +1 -0
- package/dist/artifacts/types.d.ts +17 -0
- package/dist/artifacts/types.js +2 -0
- package/dist/artifacts/types.js.map +1 -0
- package/dist/browser/chromiumAdapter.d.ts +21 -0
- package/dist/browser/chromiumAdapter.js +204 -0
- package/dist/browser/chromiumAdapter.js.map +1 -0
- package/dist/browser/evidenceCapture.d.ts +62 -0
- package/dist/browser/evidenceCapture.js +500 -0
- package/dist/browser/evidenceCapture.js.map +1 -0
- package/dist/browser/scrollCapture.d.ts +32 -0
- package/dist/browser/scrollCapture.js +163 -0
- package/dist/browser/scrollCapture.js.map +1 -0
- package/dist/browser/types.d.ts +24 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +2411 -0
- package/dist/cli.js.map +1 -0
- package/dist/domain/boundedAgentContext.d.ts +226 -0
- package/dist/domain/boundedAgentContext.js +355 -0
- package/dist/domain/boundedAgentContext.js.map +1 -0
- package/dist/domain/boundedAgentContextCorrelation.d.ts +74 -0
- package/dist/domain/boundedAgentContextCorrelation.js +441 -0
- package/dist/domain/boundedAgentContextCorrelation.js.map +1 -0
- package/dist/domain/boundedAgentContextIdentity.d.ts +26 -0
- package/dist/domain/boundedAgentContextIdentity.js +69 -0
- package/dist/domain/boundedAgentContextIdentity.js.map +1 -0
- package/dist/domain/boundedAgentContextProjection.d.ts +71 -0
- package/dist/domain/boundedAgentContextProjection.js +477 -0
- package/dist/domain/boundedAgentContextProjection.js.map +1 -0
- package/dist/domain/comparison.d.ts +220 -0
- package/dist/domain/comparison.js +350 -0
- package/dist/domain/comparison.js.map +1 -0
- package/dist/domain/comparisonEngine.d.ts +76 -0
- package/dist/domain/comparisonEngine.js +734 -0
- package/dist/domain/comparisonEngine.js.map +1 -0
- package/dist/domain/comparisonIdentity.d.ts +13 -0
- package/dist/domain/comparisonIdentity.js +46 -0
- package/dist/domain/comparisonIdentity.js.map +1 -0
- package/dist/domain/completion.d.ts +30 -0
- package/dist/domain/completion.js +22 -0
- package/dist/domain/completion.js.map +1 -0
- package/dist/domain/diagnostics.d.ts +17 -0
- package/dist/domain/diagnostics.js +77 -0
- package/dist/domain/diagnostics.js.map +1 -0
- package/dist/domain/evidence.d.ts +29 -0
- package/dist/domain/evidence.js +59 -0
- package/dist/domain/evidence.js.map +1 -0
- package/dist/domain/explicitState.d.ts +40 -0
- package/dist/domain/explicitState.js +54 -0
- package/dist/domain/explicitState.js.map +1 -0
- package/dist/domain/externalReference.d.ts +158 -0
- package/dist/domain/externalReference.js +167 -0
- package/dist/domain/externalReference.js.map +1 -0
- package/dist/domain/externalReferenceApplicability.d.ts +43 -0
- package/dist/domain/externalReferenceApplicability.js +52 -0
- package/dist/domain/externalReferenceApplicability.js.map +1 -0
- package/dist/domain/externalReferenceCompatibility.d.ts +40 -0
- package/dist/domain/externalReferenceCompatibility.js +48 -0
- package/dist/domain/externalReferenceCompatibility.js.map +1 -0
- package/dist/domain/externalReferenceFidelity.d.ts +171 -0
- package/dist/domain/externalReferenceFidelity.js +419 -0
- package/dist/domain/externalReferenceFidelity.js.map +1 -0
- package/dist/domain/externalReferenceIdentity.d.ts +38 -0
- package/dist/domain/externalReferenceIdentity.js +70 -0
- package/dist/domain/externalReferenceIdentity.js.map +1 -0
- package/dist/domain/externalReferenceImage.d.ts +35 -0
- package/dist/domain/externalReferenceImage.js +160 -0
- package/dist/domain/externalReferenceImage.js.map +1 -0
- package/dist/domain/externalReferenceRegionRelationships.d.ts +63 -0
- package/dist/domain/externalReferenceRegionRelationships.js +98 -0
- package/dist/domain/externalReferenceRegionRelationships.js.map +1 -0
- package/dist/domain/externalReferenceRegions.d.ts +65 -0
- package/dist/domain/externalReferenceRegions.js +105 -0
- package/dist/domain/externalReferenceRegions.js.map +1 -0
- package/dist/domain/externalReferenceRequirementIdentity.d.ts +12 -0
- package/dist/domain/externalReferenceRequirementIdentity.js +35 -0
- package/dist/domain/externalReferenceRequirementIdentity.js.map +1 -0
- package/dist/domain/externalReferenceRequirements.d.ts +215 -0
- package/dist/domain/externalReferenceRequirements.js +401 -0
- package/dist/domain/externalReferenceRequirements.js.map +1 -0
- package/dist/domain/externalReferenceRuntimeBinding.d.ts +146 -0
- package/dist/domain/externalReferenceRuntimeBinding.js +183 -0
- package/dist/domain/externalReferenceRuntimeBinding.js.map +1 -0
- package/dist/domain/frontendContractEvaluation.d.ts +57 -0
- package/dist/domain/frontendContractEvaluation.js +454 -0
- package/dist/domain/frontendContractEvaluation.js.map +1 -0
- package/dist/domain/frontendContractEvaluationArtifact.d.ts +65 -0
- package/dist/domain/frontendContractEvaluationArtifact.js +108 -0
- package/dist/domain/frontendContractEvaluationArtifact.js.map +1 -0
- package/dist/domain/frontendContractIdentity.d.ts +39 -0
- package/dist/domain/frontendContractIdentity.js +70 -0
- package/dist/domain/frontendContractIdentity.js.map +1 -0
- package/dist/domain/frontendContracts.d.ts +188 -0
- package/dist/domain/frontendContracts.js +260 -0
- package/dist/domain/frontendContracts.js.map +1 -0
- package/dist/domain/identity.d.ts +21 -0
- package/dist/domain/identity.js +47 -0
- package/dist/domain/identity.js.map +1 -0
- package/dist/domain/referenceCorrectionIdentity.d.ts +40 -0
- package/dist/domain/referenceCorrectionIdentity.js +77 -0
- package/dist/domain/referenceCorrectionIdentity.js.map +1 -0
- package/dist/domain/referenceCorrectionWorkflow.d.ts +160 -0
- package/dist/domain/referenceCorrectionWorkflow.js +165 -0
- package/dist/domain/referenceCorrectionWorkflow.js.map +1 -0
- package/dist/domain/referenceFidelityProjection.d.ts +65 -0
- package/dist/domain/referenceFidelityProjection.js +135 -0
- package/dist/domain/referenceFidelityProjection.js.map +1 -0
- package/dist/domain/relationships.d.ts +210 -0
- package/dist/domain/relationships.js +352 -0
- package/dist/domain/relationships.js.map +1 -0
- package/dist/domain/schema.d.ts +269 -0
- package/dist/domain/schema.js +442 -0
- package/dist/domain/schema.js.map +1 -0
- package/dist/domain/scrollEvidence.d.ts +51 -0
- package/dist/domain/scrollEvidence.js +134 -0
- package/dist/domain/scrollEvidence.js.map +1 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/projectWorkflow/aliasCatalog.d.ts +21 -0
- package/dist/projectWorkflow/aliasCatalog.js +67 -0
- package/dist/projectWorkflow/aliasCatalog.js.map +1 -0
- package/dist/projectWorkflow/checkAcceptance.d.ts +25 -0
- package/dist/projectWorkflow/checkAcceptance.js +55 -0
- package/dist/projectWorkflow/checkAcceptance.js.map +1 -0
- package/dist/projectWorkflow/checkResult.d.ts +85 -0
- package/dist/projectWorkflow/checkResult.js +101 -0
- package/dist/projectWorkflow/checkResult.js.map +1 -0
- package/dist/projectWorkflow/projectConfig.d.ts +43 -0
- package/dist/projectWorkflow/projectConfig.js +84 -0
- package/dist/projectWorkflow/projectConfig.js.map +1 -0
- package/dist/projectWorkflow/projectDiscovery.d.ts +9 -0
- package/dist/projectWorkflow/projectDiscovery.js +20 -0
- package/dist/projectWorkflow/projectDiscovery.js.map +1 -0
- package/dist/projectWorkflow/projectPaths.d.ts +8 -0
- package/dist/projectWorkflow/projectPaths.js +23 -0
- package/dist/projectWorkflow/projectPaths.js.map +1 -0
- package/dist/request/paths.d.ts +14 -0
- package/dist/request/paths.js +33 -0
- package/dist/request/paths.js.map +1 -0
- package/dist/request/request.d.ts +111 -0
- package/dist/request/request.js +464 -0
- package/dist/request/request.js.map +1 -0
- package/dist/safety/policy.d.ts +14 -0
- package/dist/safety/policy.js +81 -0
- package/dist/safety/policy.js.map +1 -0
- package/dist/viewer/assets/index-CN_yb9Uf.css +1 -0
- package/dist/viewer/assets/index-D98S1_2d.js +9 -0
- package/dist/viewer/icons/icon-192.png +0 -0
- package/dist/viewer/icons/icon-512.png +0 -0
- package/dist/viewer/index.html +15 -0
- package/dist/viewer/manifest.webmanifest +1 -0
- package/dist/viewer/registerSW.js +1 -0
- package/dist/viewer/sw.js +1 -0
- package/dist/viewer/workbox-9c191d2f.js +1 -0
- package/dist/viewerServer/context.d.ts +48 -0
- package/dist/viewerServer/context.js +60 -0
- package/dist/viewerServer/context.js.map +1 -0
- package/dist/viewerServer/evidence/classify.d.ts +59 -0
- package/dist/viewerServer/evidence/classify.js +124 -0
- package/dist/viewerServer/evidence/classify.js.map +1 -0
- package/dist/viewerServer/evidence/comparisonView.d.ts +28 -0
- package/dist/viewerServer/evidence/comparisonView.js +43 -0
- package/dist/viewerServer/evidence/comparisonView.js.map +1 -0
- package/dist/viewerServer/evidence/contextSourceView.d.ts +25 -0
- package/dist/viewerServer/evidence/contextSourceView.js +20 -0
- package/dist/viewerServer/evidence/contextSourceView.js.map +1 -0
- package/dist/viewerServer/evidence/discovery.d.ts +31 -0
- package/dist/viewerServer/evidence/discovery.js +78 -0
- package/dist/viewerServer/evidence/discovery.js.map +1 -0
- package/dist/viewerServer/evidence/evaluationView.d.ts +32 -0
- package/dist/viewerServer/evidence/evaluationView.js +50 -0
- package/dist/viewerServer/evidence/evaluationView.js.map +1 -0
- package/dist/viewerServer/evidence/handles.d.ts +21 -0
- package/dist/viewerServer/evidence/handles.js +43 -0
- package/dist/viewerServer/evidence/handles.js.map +1 -0
- package/dist/viewerServer/evidence/index.d.ts +41 -0
- package/dist/viewerServer/evidence/index.js +82 -0
- package/dist/viewerServer/evidence/index.js.map +1 -0
- package/dist/viewerServer/evidence/limits.d.ts +27 -0
- package/dist/viewerServer/evidence/limits.js +28 -0
- package/dist/viewerServer/evidence/limits.js.map +1 -0
- package/dist/viewerServer/evidence/linkedEvidence.d.ts +43 -0
- package/dist/viewerServer/evidence/linkedEvidence.js +151 -0
- package/dist/viewerServer/evidence/linkedEvidence.js.map +1 -0
- package/dist/viewerServer/evidence/mediaResolver.d.ts +16 -0
- package/dist/viewerServer/evidence/mediaResolver.js +85 -0
- package/dist/viewerServer/evidence/mediaResolver.js.map +1 -0
- package/dist/viewerServer/evidence/observationView.d.ts +29 -0
- package/dist/viewerServer/evidence/observationView.js +46 -0
- package/dist/viewerServer/evidence/observationView.js.map +1 -0
- package/dist/viewerServer/evidence/pathSafety.d.ts +11 -0
- package/dist/viewerServer/evidence/pathSafety.js +31 -0
- package/dist/viewerServer/evidence/pathSafety.js.map +1 -0
- package/dist/viewerServer/evidence/projection.d.ts +55 -0
- package/dist/viewerServer/evidence/projection.js +152 -0
- package/dist/viewerServer/evidence/projection.js.map +1 -0
- package/dist/viewerServer/evidence/referenceView.d.ts +133 -0
- package/dist/viewerServer/evidence/referenceView.js +169 -0
- package/dist/viewerServer/evidence/referenceView.js.map +1 -0
- package/dist/viewerServer/httpServer.d.ts +27 -0
- package/dist/viewerServer/httpServer.js +381 -0
- package/dist/viewerServer/httpServer.js.map +1 -0
- package/dist/viewerServer/openBrowser.d.ts +7 -0
- package/dist/viewerServer/openBrowser.js +32 -0
- package/dist/viewerServer/openBrowser.js.map +1 -0
- package/dist/viewerServer/port.d.ts +16 -0
- package/dist/viewerServer/port.js +19 -0
- package/dist/viewerServer/port.js.map +1 -0
- package/dist/viewerServer/viewerService.d.ts +62 -0
- package/dist/viewerServer/viewerService.js +88 -0
- package/dist/viewerServer/viewerService.js.map +1 -0
- package/docs/ARCHITECTURE.md +1286 -0
- package/docs/CI_CD.md +250 -0
- package/docs/COMMANDS.md +972 -0
- package/docs/CONTRACTS.md +1856 -0
- package/docs/CURRENT_STATE.md +1049 -0
- package/docs/DEVELOPMENT.md +202 -0
- package/docs/DOCUMENTATION_PRESERVATION_POLICY.md +50 -0
- package/docs/PROJECT_DESCRIPTION.md +2221 -0
- package/docs/PROJECT_MILESTONES.md +2526 -0
- package/docs/PROJECT_OVERVIEW.md +150 -0
- package/docs/QUICKSTART.md +83 -0
- package/docs/RELEASE.md +27 -0
- package/docs/ROADMAP.md +641 -0
- package/docs/SECURITY.md +218 -0
- package/docs/WORKFLOWS.md +642 -0
- package/docs/plans/v0.8-implementation-plan.md +655 -0
- package/docs/plans/v0.8.1-cli-usability-patch-plan.md +505 -0
- package/docs/reports/v0.7-bounded-fidelity-context-prompt7.md +243 -0
- package/docs/reports/v0.7-implementation-completeness-documentation-reconciliation.md +497 -0
- package/docs/reports/v0.7-pre-release-readiness.md +337 -0
- package/docs/reports/v0.7-reference-binding-prompt5.md +223 -0
- package/docs/reports/v0.7-reference-compatibility-prompt4.md +234 -0
- package/docs/reports/v0.7-reference-correction-workflow-prompt8.md +222 -0
- package/docs/reports/v0.7-reference-fidelity-prompt6.md +216 -0
- package/docs/reports/v0.7-reference-foundation-prompt1.md +151 -0
- package/docs/reports/v0.7-reference-regions-prompt2.md +195 -0
- package/docs/reports/v0.7-reference-requirements-prompt3.md +217 -0
- package/docs/reports/v0.7-release-prep.md +423 -0
- package/docs/reports/v0.8-binding-fidelity-interaction-batch6.md +279 -0
- package/docs/reports/v0.8-bounded-context-correlation-batch7.md +233 -0
- package/docs/reports/v0.8-comparison-contract-inspection-batch4.md +279 -0
- package/docs/reports/v0.8-evidence-index-readers-batch2.md +247 -0
- package/docs/reports/v0.8-implementation-completeness-documentation-reconciliation.md +741 -0
- package/docs/reports/v0.8-integrated-viewer-acceptance-batch8.md +128 -0
- package/docs/reports/v0.8-observation-svg-inspection-batch3.md +223 -0
- package/docs/reports/v0.8-prerelease-readiness-cross-platform-security-code-rot.md +687 -0
- package/docs/reports/v0.8-reference-candidate-inspection-batch5.md +232 -0
- package/docs/reports/v0.8-viewer-runtime-pwa-batch1.md +278 -0
- package/docs/reports/v0.8.1-check-orchestration-prompt2.md +69 -0
- package/docs/reports/v0.8.1-implementation-completeness-documentation-reconciliation.md +114 -0
- package/docs/reports/v0.8.1-prerelease-readiness-cross-platform-security-code-rot.md +170 -0
- package/docs/reports/v0.8.1-project-workflow-foundation-prompt1.md +66 -0
- package/package.json +58 -0
|
@@ -0,0 +1,1286 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## v0.8.1 project workflow
|
|
4
|
+
|
|
5
|
+
Versioned project configuration (`1.0.0` compatibility plus current `1.1.0`
|
|
6
|
+
acceptance input), upward discovery, centralized managed paths, and the atomic
|
|
7
|
+
alias catalog live under `src/projectWorkflow`. Aliases select exact canonical
|
|
8
|
+
artifact directories; they never replace artifact identities.
|
|
9
|
+
|
|
10
|
+
`src/application/projectCheckService.ts` composes the existing observation,
|
|
11
|
+
comparison, contract-evaluation, reference-reader, explicit-binding,
|
|
12
|
+
compatibility, and fidelity owners. `src/projectWorkflow/checkAcceptance.ts`
|
|
13
|
+
owns contained acceptance-input resolution and shared file-wrapper parsing.
|
|
14
|
+
`checkResult.ts` owns the bounded ephemeral projection, not a persisted check
|
|
15
|
+
artifact or evaluation engine. Status precedence is `BLOCKED`, then `FAIL`,
|
|
16
|
+
then `PASS` when all configured executable dimensions pass, then
|
|
17
|
+
`REVIEW_REQUIRED` when comparison is the only evidence. Canonical observations,
|
|
18
|
+
comparisons, and contract evaluations remain persisted; reference fidelity and
|
|
19
|
+
the workflow result remain in memory/presentation.
|
|
20
|
+
|
|
21
|
+
## Current package architecture
|
|
22
|
+
|
|
23
|
+
The current repository is one published TypeScript ESM package
|
|
24
|
+
(`@dailephd/my-frontend-observer@0.8.1`). The CLI remains
|
|
25
|
+
`my-frontend-observer`; the npm scope does not rename the product or artifact
|
|
26
|
+
identities.
|
|
27
|
+
|
|
28
|
+
- `src/cli.ts` is the real, thin public CLI parsing/dispatch/presentation
|
|
29
|
+
boundary for the current command surface (`observe`, `compare`,
|
|
30
|
+
`approve-baseline`, `save-change-contract`, `evaluate-contract`,
|
|
31
|
+
`import-reference`, `approve-reference`, `evaluate-reference-fidelity`);
|
|
32
|
+
argument parsing and output formatting only, per command - the commands do
|
|
33
|
+
not share domain semantics in the CLI. v0.6 added no new CLI command; v0.7
|
|
34
|
+
added the three external-reference commands.
|
|
35
|
+
- `src/index.ts` is the library entry point re-exporting the observer-owned
|
|
36
|
+
contracts/functions from every layer below, including the v0.6 bounded-agent-
|
|
37
|
+
context projection and runtime/static correlation surface, and the v0.7
|
|
38
|
+
external-reference/region/requirement/applicability/compatibility/binding/
|
|
39
|
+
fidelity/correction-workflow surface (`prepareReferenceCorrection`/
|
|
40
|
+
`reviewReferenceCorrectionAttempt` remain programmatic-only, with no CLI
|
|
41
|
+
command).
|
|
42
|
+
- `scripts/clean.mjs` safely removes only the project `dist/` directory.
|
|
43
|
+
- `scripts/check-docs.mjs` validates the canonical documentation foundation,
|
|
44
|
+
roadmap version presence, and the no-batches rule.
|
|
45
|
+
- TypeScript, ESLint, Vitest, and package configuration provide foundation
|
|
46
|
+
validation, now exercised by real product tests (`tests/unit/`,
|
|
47
|
+
`tests/browser/`).
|
|
48
|
+
|
|
49
|
+
Batch 1 added the observation domain/schema and safety-policy layer
|
|
50
|
+
(`src/domain/`, `src/request/`, `src/safety/`). Batch 2 added a real
|
|
51
|
+
Playwright Chromium browser adapter (`src/browser/`), a minimal application
|
|
52
|
+
seam invoking it (`src/application/`), and a deterministic browser
|
|
53
|
+
fixture/test boundary (`tests/fixtures/`, `tests/browser/`, run via
|
|
54
|
+
`npm run test:browser`). Batch 3 extended that single browser adapter with an
|
|
55
|
+
internal page/target measurement module (`src/browser/evidenceCapture.ts`)
|
|
56
|
+
that reads page and explicit-CSS-target evidence from the same live,
|
|
57
|
+
already-ready page used for the screenshot - no second browser/page is ever
|
|
58
|
+
opened, and Playwright objects still never leave `src/browser/`. Batch 4
|
|
59
|
+
added the artifact ownership boundary itself: `src/artifacts/artifactWriter.ts`
|
|
60
|
+
is the one canonical place that writes an observation to disk (temp
|
|
61
|
+
directory, then one atomic rename into `<outputLocation>/<observationId>/`),
|
|
62
|
+
and `src/application/observationPersistence.ts` assembles the frozen
|
|
63
|
+
`ObservationArtifact` from a browser-capture result before handing it to the
|
|
64
|
+
writer. The artifact layer has no Playwright dependency and is testable
|
|
65
|
+
without launching Chromium. Batch 5 completed the boundary chain: `src/cli.ts`
|
|
66
|
+
parses `observe` arguments (CLI-syntax errors only - e.g. malformed
|
|
67
|
+
`WIDTHxHEIGHT`), constructs a raw request, and hands it to the existing
|
|
68
|
+
Batch 1 `normalizeRequest`; on success it calls one new application-level use
|
|
69
|
+
case, `observe()` in `src/application/observationPersistence.ts`, which runs
|
|
70
|
+
the existing `runBrowserCapture` exactly once and, only on success, the
|
|
71
|
+
existing artifact writer exactly once, then returns a small observer-owned
|
|
72
|
+
`ApplicationObservationResult` (observation id, completion state, artifact
|
|
73
|
+
path, target/diagnostic counts) for the CLI to print. The CLI never imports
|
|
74
|
+
Playwright or the filesystem-write path directly. Batch 6 closed the
|
|
75
|
+
remaining real-Chromium coverage gap (a genuine navigation failure, distinct
|
|
76
|
+
from a readiness timeout or a pre-launch safety rejection) and validated the
|
|
77
|
+
packed npm tarball end to end in a clean consumer environment, independent
|
|
78
|
+
of the source checkout. At the end of the v0.1 implementation there was no
|
|
79
|
+
controlled-scroll or comparison behavior.
|
|
80
|
+
|
|
81
|
+
## Current v0.2 architecture (released/current architecture)
|
|
82
|
+
|
|
83
|
+
v0.2 extends the same architecture rather than adding a parallel one.
|
|
84
|
+
`src/request/request.ts` now owns a canonical `{name, locators}` target
|
|
85
|
+
model (`TargetLocator`, six frozen kinds) in place of the old CSS-only
|
|
86
|
+
shape; the legacy `{name, selector}` input still normalizes into it. The one
|
|
87
|
+
existing browser-side target resolver/measurement module,
|
|
88
|
+
`src/browser/evidenceCapture.ts`, was extended - not replaced - to resolve
|
|
89
|
+
all six locator kinds against the live page through a single Playwright
|
|
90
|
+
`Locator` per attempt, honor the frozen ordered-fallback/ambiguity/
|
|
91
|
+
unavailable-no-fallback contract, and converge every kind on the same
|
|
92
|
+
measurement path (`captureResolvedTargetRecord`); it additionally computes
|
|
93
|
+
bounded semantic state, derived landmark identity, and configured-target-
|
|
94
|
+
only DOM containment from the same already-resolved elements in the same
|
|
95
|
+
capture pass - no second browser/page, no second resolution algorithm.
|
|
96
|
+
`src/domain/schema.ts` extends `TargetEvidenceRecord`/`TargetResolution`
|
|
97
|
+
additively for schema `1.1.0`, with matching structural validation in
|
|
98
|
+
`isValidObservationArtifact`. `src/cli.ts` gained one CLI/input-boundary-
|
|
99
|
+
only addition, `--targets-file`: it reads and validates only the JSON root
|
|
100
|
+
wrapper (via the already-imported `node:fs`, never `node:fs/promises`) and
|
|
101
|
+
hands the parsed `targets` value into the existing `RawObservationRequest`/
|
|
102
|
+
`normalizeRequest()` path unchanged - there is no second application
|
|
103
|
+
observation use case, and Playwright objects still never leave
|
|
104
|
+
`src/browser/`. The artifact writer, application observation use case, and
|
|
105
|
+
overall boundary chain (`CLI → normalizeRequest → observe() →
|
|
106
|
+
runBrowserCapture → artifact writer`) are unchanged from v0.1.
|
|
107
|
+
|
|
108
|
+
## Current v0.3 architecture (released/current architecture)
|
|
109
|
+
|
|
110
|
+
v0.3 extends the same single-observation architecture again; it does not add
|
|
111
|
+
a second browser lifecycle, target resolver, or artifact path.
|
|
112
|
+
`src/request/request.ts` adds one optional `scrollScenario` field to
|
|
113
|
+
`NormalizedObservationRequest` (`ScrollScenario { action }`, exactly
|
|
114
|
+
`window-scroll-by` or `target-scroll-by`); `src/domain/schema.ts` adds the
|
|
115
|
+
matching bounded runtime evidence types (`ScrollRuntimeSnapshot`,
|
|
116
|
+
`ViewportRelationEvidence`, `OverflowEvidence`, `ScrollScenarioTransition`,
|
|
117
|
+
`ScrollOwnerInterpretation`) and structural validation for schema `1.2.0`
|
|
118
|
+
(additive over `1.1.0`). `src/domain/scrollEvidence.ts` holds the pure,
|
|
119
|
+
browser-independent derivations (viewport relation, actual overflow,
|
|
120
|
+
transitions, and `deriveScrollOwner`) so they are unit-testable without
|
|
121
|
+
Chromium. `src/browser/scrollCapture.ts` holds the one browser-side scenario
|
|
122
|
+
capture module: it reuses `evidenceCapture.ts#resolveConfiguredTargets` (now
|
|
123
|
+
exported) to resolve configured targets exactly once, captures an initial
|
|
124
|
+
`ScrollRuntimeSnapshot`, performs the one immediate scroll
|
|
125
|
+
(`window.scrollBy`/`element.scrollBy`, both `behavior: 'instant'`), waits
|
|
126
|
+
exactly two `requestAnimationFrame` cycles, and captures a final snapshot -
|
|
127
|
+
all inside `chromiumAdapter.ts#captureViewportInternal`'s existing single
|
|
128
|
+
navigate → ready → capture flow, strictly before the unchanged
|
|
129
|
+
screenshot/`capturePageEvidence`/`captureTargetEvidence` calls, so every
|
|
130
|
+
downstream capture (including a no-scenario request, which skips this block
|
|
131
|
+
entirely) describes only the final state. `src/cli.ts` gained one CLI/input-
|
|
132
|
+
boundary-only addition, `--scroll-scenario-file`: mirroring
|
|
133
|
+
`--targets-file`, it reads and validates only the file readability/JSON-
|
|
134
|
+
validity/non-array-object-root shape and hands the parsed value straight
|
|
135
|
+
into `RawObservationRequest.scrollScenario` - every scenario/action rule
|
|
136
|
+
(kind, deltas, target reference) stays owned by `normalizeRequest()`. There
|
|
137
|
+
is still one canonical `observe()` application use case and one artifact
|
|
138
|
+
writer; `scrollScenarioEvidence` is simply one more optional field on the
|
|
139
|
+
same `ObservationArtifact`.
|
|
140
|
+
|
|
141
|
+
## Current v0.4 architecture (released/current architecture)
|
|
142
|
+
|
|
143
|
+
v0.4 adds one new downstream pipeline that consumes `ObservationArtifact`
|
|
144
|
+
values rather than producing them - it never adds a second browser lifecycle,
|
|
145
|
+
target resolver, or observation engine:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
ObservationArtifact before ObservationArtifact after
|
|
149
|
+
\ /
|
|
150
|
+
`--------. .-------'
|
|
151
|
+
\ /
|
|
152
|
+
artifact reader (src/artifacts/artifactReader.ts)
|
|
153
|
+
↓
|
|
154
|
+
comparability evaluation (src/domain/comparisonEngine.ts)
|
|
155
|
+
↓
|
|
156
|
+
canonical relationship derivation, called for each side independently
|
|
157
|
+
(src/domain/relationships.ts#deriveLayoutRelationships)
|
|
158
|
+
↓
|
|
159
|
+
canonical comparison derivation
|
|
160
|
+
(src/domain/comparisonEngine.ts#compareObservations)
|
|
161
|
+
↓
|
|
162
|
+
ComparisonArtifact
|
|
163
|
+
↓
|
|
164
|
+
atomic comparison writer (src/artifacts/comparisonArtifactWriter.ts)
|
|
165
|
+
|
|
166
|
+
CLI `compare`
|
|
167
|
+
↓
|
|
168
|
+
application service only (src/application/comparisonService.ts)
|
|
169
|
+
↓
|
|
170
|
+
[reader → domain comparison → writer, as above]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`src/domain/relationships.ts` froze the layout-relationship contract and
|
|
174
|
+
implements the one canonical pure derivation,
|
|
175
|
+
`deriveLayoutRelationships(observation, options?)`: horizontal/vertical
|
|
176
|
+
order, area overlap, relative width, geometric fit, vertical sequencing,
|
|
177
|
+
page-width fit/exceeds, and a standalone `deriveTargetClipping(record)` -
|
|
178
|
+
all computed only from an already-captured `ObservationArtifact`'s own
|
|
179
|
+
`targetEvidence`/`pageEvidence`, never from a second browser query. DOM
|
|
180
|
+
containment is read directly from the existing v0.2 `TargetContainment`
|
|
181
|
+
evidence rather than re-derived, and stays a distinct concept from
|
|
182
|
+
geometric fit.
|
|
183
|
+
|
|
184
|
+
`src/domain/comparisonEngine.ts` implements the one canonical pure
|
|
185
|
+
before/after engine, `compareObservations(before, after, config?)`:
|
|
186
|
+
validates both source artifacts, evaluates comparability *before* any
|
|
187
|
+
rendered difference is calculated, calls `deriveLayoutRelationships` once
|
|
188
|
+
per side with the same tolerance, and derives target/page differences and
|
|
189
|
+
relationship changes. `src/artifacts/comparisonArtifactWriter.ts` persists
|
|
190
|
+
the result atomically (sibling temp directory, then one rename) as
|
|
191
|
+
`<outputLocation>/<comparisonId>/manifest.json` only - no screenshot is
|
|
192
|
+
copied; the manifest's `before`/`after` references point back to the
|
|
193
|
+
source observations' own `screenshot.path`. `src/application/
|
|
194
|
+
comparisonService.ts` is the one application-layer seam: `compareAndPersist`
|
|
195
|
+
takes two in-memory `ObservationArtifact`s and does exactly one comparison
|
|
196
|
+
plus exactly one persist; `compareAndPersistFromArtifactRoots` is a thin
|
|
197
|
+
wrapper that additionally reads both sides from disk via the existing
|
|
198
|
+
`src/artifacts/artifactReader.ts#readObservationArtifact` reader (itself
|
|
199
|
+
just a `manifest.json` parse plus the same `isValidObservationArtifact`
|
|
200
|
+
structural gate the writer uses).
|
|
201
|
+
|
|
202
|
+
`src/cli.ts` gained one new top-level command, `compare`
|
|
203
|
+
(`--before`/`--after`/`--output`/`--config-file`), implemented with the same
|
|
204
|
+
thin-CLI-boundary discipline as `observe`: `parseCompareArgs` handles only
|
|
205
|
+
argument shape/duplication, an optional `loadComparisonConfigFile` reads and
|
|
206
|
+
validates only file readability/JSON-validity/non-array-object-root (exactly
|
|
207
|
+
like `--targets-file`/`--scroll-scenario-file`), and the command body calls
|
|
208
|
+
`compareAndPersistFromArtifactRoots` exactly once. **The CLI's comparison
|
|
209
|
+
path never launches Chromium** - `src/cli.ts` imports nothing from
|
|
210
|
+
`src/browser/` or `src/artifacts/` (it only reaches persistence and artifact
|
|
211
|
+
reading indirectly, through the application-layer seam above), matching the
|
|
212
|
+
same import-boundary discipline already enforced for `observe`.
|
|
213
|
+
|
|
214
|
+
## Current v0.5 architecture (released/current architecture)
|
|
215
|
+
|
|
216
|
+
v0.5 adds one new downstream layer that consumes `ComparisonArtifact` values
|
|
217
|
+
(plus the source `ObservationArtifact` pair) rather than producing them - no
|
|
218
|
+
new browser lifecycle, target resolver, or comparison engine is added:
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
ObservationArtifact before + after
|
|
222
|
+
↓
|
|
223
|
+
existing v0.4 comparison/relationship pipeline (unchanged)
|
|
224
|
+
↓
|
|
225
|
+
ComparisonArtifact
|
|
226
|
+
↓ PersistentBaselineContract
|
|
227
|
+
| +
|
|
228
|
+
`------------------------→ PerChangeContract
|
|
229
|
+
↓
|
|
230
|
+
canonical contract evaluation
|
|
231
|
+
(src/domain/frontendContractEvaluation.ts#evaluateFrontendContract)
|
|
232
|
+
↓
|
|
233
|
+
clause results + unexpected changes + overall PASS/FAIL
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`src/domain/frontendContracts.ts` froze the contract/change-scope type,
|
|
237
|
+
constant, and structural-validator vocabulary (Batch 1); `src/domain/
|
|
238
|
+
frontendContractIdentity.ts` froze deterministic contract/baseline/clause
|
|
239
|
+
identity in the same canonicalize+sha256(+opaque-nonce) style as `src/domain/
|
|
240
|
+
comparisonIdentity.ts`. `src/domain/frontendContractEvaluation.ts#evaluateFrontendContract`
|
|
241
|
+
(Batch 2) is the one canonical pure evaluation entry point: it validates its
|
|
242
|
+
five inputs (before/after `ObservationArtifact`, `ComparisonArtifact`,
|
|
243
|
+
`PersistentBaselineContract`, `PerChangeContract`) are structurally coherent
|
|
244
|
+
and mutually consistent, calculates the active baseline clause set after
|
|
245
|
+
explicit supersession, detects bounded structural conflicts, evaluates every
|
|
246
|
+
active clause via the frozen 15-primitive vocabulary against the existing
|
|
247
|
+
`ComparisonArtifact`/`ObservationArtifact` evidence (never re-deriving
|
|
248
|
+
clipping/relationship/scroll-owner facts), classifies unaccounted-for
|
|
249
|
+
`ComparisonArtifact.differences` entries as `unexpected`, and derives one
|
|
250
|
+
overall `PASS`/`FAIL` verdict. It performs no I/O, launches no browser, and
|
|
251
|
+
persists nothing - `src/domain/frontendContractEvaluation.ts` itself remains
|
|
252
|
+
untouched by the persistence layer below (Batch 3).
|
|
253
|
+
|
|
254
|
+
Batch 3 adds the persistence/application boundary around this frozen domain,
|
|
255
|
+
without redefining it:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
ComparisonArtifact (read via new src/artifacts/comparisonArtifactReader.ts)
|
|
259
|
+
+
|
|
260
|
+
PersistentBaselineContract / PerChangeContract
|
|
261
|
+
(read/written via src/artifacts/frontendContractArtifactReader.ts / ...Writer.ts)
|
|
262
|
+
↓
|
|
263
|
+
src/application/frontendContractEvaluationService.ts#evaluateAndPersist
|
|
264
|
+
↓
|
|
265
|
+
evaluateFrontendContract() [called exactly once, unmodified]
|
|
266
|
+
↓
|
|
267
|
+
src/domain/frontendContractEvaluationArtifact.ts
|
|
268
|
+
(minimal additive persisted envelope around the frozen result)
|
|
269
|
+
↓
|
|
270
|
+
src/artifacts/frontendContractEvaluationArtifactWriter.ts
|
|
271
|
+
(atomic write, exactly once on a structurally constructible result)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`evaluateAndPersistFromArtifactRoots` is the CLI-facing wrapper, reading
|
|
275
|
+
before/after observations through the existing `readObservationArtifact` (no
|
|
276
|
+
second observation reader), the comparison and both contract classes
|
|
277
|
+
through the new readers, then delegating to `evaluateAndPersist` exactly
|
|
278
|
+
once - mirroring `application/comparisonService.ts#compareAndPersistFromArtifactRoots`'s
|
|
279
|
+
own thin-wrapper shape.
|
|
280
|
+
|
|
281
|
+
Batch 4 exposes this through the same thin-CLI boundary already established
|
|
282
|
+
by `observe`/`compare`:
|
|
283
|
+
|
|
284
|
+
```text
|
|
285
|
+
src/cli.ts (argument parsing, JSON-file-shape checks, help/output formatting,
|
|
286
|
+
exit-code selection only)
|
|
287
|
+
↓
|
|
288
|
+
src/application/frontendContractPersistenceService.ts#approveAndPersistBaseline
|
|
289
|
+
src/application/frontendContractPersistenceService.ts#persistPerChangeContract
|
|
290
|
+
src/application/frontendContractEvaluationService.ts#evaluateAndPersistFromArtifactRoots
|
|
291
|
+
↓
|
|
292
|
+
domain validators (isValidPersistentBaselineContract / isValidPerChangeContract)
|
|
293
|
+
+ artifact readers/writers (Batch 3)
|
|
294
|
+
+ evaluateFrontendContract() (Batch 2, unmodified)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Three new top-level commands - `approve-baseline`, `save-change-contract`,
|
|
298
|
+
`evaluate-contract` - each parse only CLI-syntax concerns (duplicate/missing
|
|
299
|
+
flags, JSON-file readability/parseability/object-root shape) and delegate to
|
|
300
|
+
exactly one application-layer call; `src/cli.ts` imports no artifact writer/
|
|
301
|
+
reader module and no browser code, matching the existing `observe`/`compare`
|
|
302
|
+
import-boundary discipline exactly. `approveAndPersistBaseline` adds the one
|
|
303
|
+
new coherence check Batch 3 did not need: verifying a baseline contract's
|
|
304
|
+
frozen `sourceObservation` reference actually matches the supplied
|
|
305
|
+
observation artifact before persisting - explicit approval only, never
|
|
306
|
+
inferred from a `compare` or `evaluate-contract` result. `--enforce` on
|
|
307
|
+
`evaluate-contract` is applied only after evaluation and persistence have
|
|
308
|
+
already completed; it selects the process exit status for an already-final
|
|
309
|
+
`FAIL` result and is never part of any identity or persisted field.
|
|
310
|
+
|
|
311
|
+
## Current v0.6 architecture (released as `0.6.0`)
|
|
312
|
+
|
|
313
|
+
v0.6 adds one new downstream, read-only layer that consumes existing v0.1-v0.5
|
|
314
|
+
evidence (`ObservationArtifact`, `ComparisonArtifact`,
|
|
315
|
+
`PersistentBaselineContract`/`PerChangeContract`, and evaluation results)
|
|
316
|
+
plus caller-supplied bounded static candidate evidence - it adds no new
|
|
317
|
+
browser lifecycle, target resolver, observation/comparison/contract engine,
|
|
318
|
+
or persisted artifact family:
|
|
319
|
+
|
|
320
|
+
```text
|
|
321
|
+
ObservationArtifact(s) + ComparisonArtifact + contract/evaluation evidence
|
|
322
|
+
↓
|
|
323
|
+
src/domain/boundedAgentContextProjection.ts#projectBoundedAgentContext
|
|
324
|
+
↓
|
|
325
|
+
BoundedRuntimeTargetProjection
|
|
326
|
+
(page/viewport identity, stable targets, geometry, runtime behavior,
|
|
327
|
+
relationships, before/after differences, contract results,
|
|
328
|
+
requested/expected-dependent/protected/preserved scope reused verbatim
|
|
329
|
+
from src/domain/frontendContracts.ts, diagnostics, artifact/screenshot
|
|
330
|
+
references, provenance, adequacy, omission, truncation)
|
|
331
|
+
↓
|
|
332
|
+
src/domain/boundedAgentContextCorrelation.ts
|
|
333
|
+
#deriveRuntimeStaticCorrelations / #attachRuntimeStaticCorrelations
|
|
334
|
+
↓
|
|
335
|
+
RuntimeStaticCorrelation[] (correlated / ambiguous / unavailable,
|
|
336
|
+
competing candidates preserved verbatim - never collapsed to one owner)
|
|
337
|
+
↓
|
|
338
|
+
src/index.ts (public export/correlation boundary only)
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`src/domain/boundedAgentContext.ts` freezes the bounded-projection and
|
|
342
|
+
correlation type/constant vocabulary (`Adequacy`, `ADEQUACY_REASON_CODES`,
|
|
343
|
+
`OmissionRecord`, `TruncationRecord`, `BOUNDED_AGENT_CONTEXT_ARTIFACT_KIND`,
|
|
344
|
+
schema `1.0.0`). `src/domain/boundedAgentContextIdentity.ts` derives a
|
|
345
|
+
deterministic logical identity distinct from a fresh per-execution instance
|
|
346
|
+
identity, in the same canonicalize+hash style as
|
|
347
|
+
`comparisonIdentity.ts`/`frontendContractIdentity.ts`.
|
|
348
|
+
`boundedAgentContextProjection.ts` performs no browser I/O and re-derives
|
|
349
|
+
nothing already owned upstream - it reads already-captured artifacts and
|
|
350
|
+
reuses the existing v0.4 relationship/comparison evidence and v0.5
|
|
351
|
+
change-scope clause types directly. `boundedAgentContextCorrelation.ts`
|
|
352
|
+
accepts only plain, caller-supplied candidate static-evidence records; it has
|
|
353
|
+
**no** dependency on `@dailephd/my-dev-kit`, since the audit that preceded
|
|
354
|
+
implementation found no generic static-side retrieval capability actually
|
|
355
|
+
missing (see `docs/ROADMAP.md` v0.6 "Dependency direction" - the "determine
|
|
356
|
+
whether my-dev-kit requires a static-side change" step concluded no).
|
|
357
|
+
Runtime target identity is carried through this module verbatim; the module
|
|
358
|
+
never adds a `sourceOwner`/`causedBy`-shaped field, preserving the
|
|
359
|
+
architectural rule that runtime identity never silently becomes source
|
|
360
|
+
ownership.
|
|
361
|
+
|
|
362
|
+
This layer is a programmatic export/correlation boundary only: `src/index.ts`
|
|
363
|
+
re-exports its full type/function surface, but there is no new CLI command,
|
|
364
|
+
no `src/artifacts/boundedAgentContext*` writer/reader, and no orchestrator or
|
|
365
|
+
lab code in this repository - those remain separate sibling-repository
|
|
366
|
+
responsibilities per the Milestone 6 ownership split in
|
|
367
|
+
`docs/PROJECT_MILESTONES.md`.
|
|
368
|
+
|
|
369
|
+
## v0.7 (released as `0.7.0`), v0.8 (released as `0.8.0`), and planned v0.9–v0.10 reference-evidence architecture constraints
|
|
370
|
+
|
|
371
|
+
The external visual-reference capability (v0.7) is released as package
|
|
372
|
+
version `0.7.0` - see "v0.7 Prompt 1" through "v0.7 Prompt 8" below for the
|
|
373
|
+
actual architecture, and `docs/CURRENT_STATE.md` for release state. It
|
|
374
|
+
extends the existing v0.1-v0.6 evidence architecture rather than becoming a
|
|
375
|
+
UI-only feature or a parallel visual-comparison stack. v0.8 (interactive
|
|
376
|
+
viewer) is released as package version `0.8.0`. v0.9 (structured visual
|
|
377
|
+
annotation) and v0.10 (full graphical human-LLM workflow) remain future and
|
|
378
|
+
unimplemented; the constraints below apply to that still-future work.
|
|
379
|
+
|
|
380
|
+
The evidence domains remain distinct:
|
|
381
|
+
|
|
382
|
+
```text
|
|
383
|
+
runtime observation A ↔ runtime observation B
|
|
384
|
+
→ existing before/after comparison
|
|
385
|
+
|
|
386
|
+
approved baseline/per-change contract ↔ candidate runtime evidence
|
|
387
|
+
→ existing canonical contract evaluation
|
|
388
|
+
|
|
389
|
+
external visual reference ↔ candidate runtime evidence
|
|
390
|
+
→ reference applicability + structured fidelity evaluation (v0.7,
|
|
391
|
+
released as `0.7.0` - see "v0.7 Prompt 4" and "v0.7 Prompt 6" below)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
An external reference is not an `ObservationArtifact`, and a reference region
|
|
395
|
+
is not a runtime target. The released v0.7 implementation preserves explicit
|
|
396
|
+
identity and provenance for the reference image/version, reference regions,
|
|
397
|
+
applicable viewport/theme/application state, authored requirements, tolerances,
|
|
398
|
+
approval/supersession state, and reference-region/runtime-target bindings.
|
|
399
|
+
Bindings are explicit and evaluate to `bound`, `ambiguous`, or `unavailable`;
|
|
400
|
+
they never silently become source ownership.
|
|
401
|
+
|
|
402
|
+
The non-UI reference model and structured reference-vs-candidate evaluation
|
|
403
|
+
were established in v0.7 before v0.8. v0.8 may render side-by-side images,
|
|
404
|
+
overlays, measurements, bindings, provenance, and fidelity results, but it must
|
|
405
|
+
consume those existing engines and must not invent a second reference model or
|
|
406
|
+
evaluation engine. v0.9 may author annotations against either runtime
|
|
407
|
+
screenshots or external references, but both coordinate/identity domains remain
|
|
408
|
+
explicit and feed the same canonical contract/change-scope semantics. v0.10
|
|
409
|
+
combines both visual entry modes with the existing correction loop.
|
|
410
|
+
|
|
411
|
+
Where a reference requirement is executable, it uses the existing v0.5
|
|
412
|
+
requested/expected-dependent/protected/preserved semantics. Informational or
|
|
413
|
+
unassessed reference evidence remains non-executable until explicitly selected.
|
|
414
|
+
There is no reference-only PASS/FAIL taxonomy.
|
|
415
|
+
|
|
416
|
+
The released reference evaluation reuses existing relationship/value
|
|
417
|
+
conventions where they mean the same thing and adds distinct reference-owned
|
|
418
|
+
units only where the image evidence requires them. v0.7 does not use pixel or
|
|
419
|
+
image-region similarity as a success mechanism; a later bounded similarity
|
|
420
|
+
feature may supplement structured evidence if separately designed, but it must
|
|
421
|
+
not replace browser-authoritative runtime geometry, canonical contract
|
|
422
|
+
evaluation, or explicit relationship evidence.
|
|
423
|
+
|
|
424
|
+
Candidate rendering still uses the one existing Chromium observation engine.
|
|
425
|
+
The observer remains non-mutating. `my-dev-kit` remains the static/source
|
|
426
|
+
evidence owner, and the v0.6 correlation/bounded-context boundary remains the
|
|
427
|
+
route for attaching relevant source evidence to reference-driven correction
|
|
428
|
+
packets. Heavy reference image bytes are referenced rather than copied into
|
|
429
|
+
every downstream context/evaluation record.
|
|
430
|
+
|
|
431
|
+
Theme, application-state, viewport, and authenticated-state applicability are
|
|
432
|
+
checked before reference fidelity is interpreted through the released v0.7
|
|
433
|
+
compatibility path, which reuses v0.4 comparability conventions. If reference
|
|
434
|
+
and candidate do not represent compatible intended states, the result is
|
|
435
|
+
explicitly incompatible/incomparable rather than a fabricated visual difference
|
|
436
|
+
set. v0.8, released as package version `0.8.0`, displays this result exactly
|
|
437
|
+
as required rather than redefining the state model - see "v0.8 Batch 5"
|
|
438
|
+
below.
|
|
439
|
+
|
|
440
|
+
The constraints above were carried out by the actual v0.7 implementation
|
|
441
|
+
described in "v0.7 Prompt 1" through "v0.7 Prompt 8" below: explicit
|
|
442
|
+
identity/provenance, applicability/compatibility, region-to-target bindings,
|
|
443
|
+
requested/expected-dependent/protected/preserved reuse, and the non-mutating
|
|
444
|
+
Chromium/correlation boundaries all remain as constrained here. v0.8 (see
|
|
445
|
+
"v0.8 Batch 1" through "v0.8 Batch 8" below) applied them unchanged; they
|
|
446
|
+
continue to apply unchanged to the still-future v0.9-v0.10 work.
|
|
447
|
+
|
|
448
|
+
The exact public artifact names, schema versions, persistence layout, supported
|
|
449
|
+
image formats, coordinate model, requirement/tolerance primitives, and fidelity
|
|
450
|
+
behavior were frozen by the actual v0.7 implementation below, not by earlier
|
|
451
|
+
planning language. Style/asset-similarity mechanisms remain future unless
|
|
452
|
+
separately implemented.
|
|
453
|
+
|
|
454
|
+
## v0.8 Batch 1 (Viewer runtime and PWA foundation) — implemented
|
|
455
|
+
|
|
456
|
+
Batch 1 of the frozen `docs/plans/v0.8-implementation-plan.md` establishes
|
|
457
|
+
only the viewer runtime/build shell — no evidence indexing, artifact reading,
|
|
458
|
+
or evidence UI. It does not implement any of the v0.7-derived reference/
|
|
459
|
+
fidelity/binding display constraints above; those remain future work for
|
|
460
|
+
later v0.8 batches, which must consume this runtime boundary rather than
|
|
461
|
+
redefine it.
|
|
462
|
+
|
|
463
|
+
```text
|
|
464
|
+
my-frontend-observer view [--root <evidence-root>]
|
|
465
|
+
|
|
|
466
|
+
v
|
|
467
|
+
thin CLI dispatch (src/cli.ts: parseViewArgs/runViewCommand)
|
|
468
|
+
|
|
|
469
|
+
v
|
|
470
|
+
viewer application seam (src/viewerServer/viewerService.ts: startViewer)
|
|
471
|
+
|
|
|
472
|
+
v
|
|
473
|
+
Node local server, loopback-only (src/viewerServer/httpServer.ts)
|
|
474
|
+
|
|
|
475
|
+
+---------------------+----------------------+
|
|
476
|
+
| |
|
|
477
|
+
v v
|
|
478
|
+
built viewer assets (dist/viewer) GET /api/status
|
|
479
|
+
(React + TypeScript + Vite PWA) (session/root identity only)
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
- **Node server boundary** (`src/viewerServer/`): binds only to `127.0.0.1`
|
|
483
|
+
on one fixed default port (`4319`, `src/viewerServer/port.ts`); serves only
|
|
484
|
+
the built viewer assets plus the one read-only status endpoint; resolves
|
|
485
|
+
every requested path against the built assets root and fails closed on any
|
|
486
|
+
path that would resolve outside it; accepts no write HTTP methods; performs
|
|
487
|
+
no artifact reading, browser observation, or mutation. `--root` is
|
|
488
|
+
validated operationally (exists, is a directory) and exposed only as an
|
|
489
|
+
opaque status string — it is never interpreted as Observer evidence in this
|
|
490
|
+
batch.
|
|
491
|
+
- **Browser application** (`viewer/`): a React + TypeScript + Vite app, built
|
|
492
|
+
independently of `src/` via `viewer/tsconfig.json` and `viewer/vite.config.ts`,
|
|
493
|
+
output to `dist/viewer` inside the existing package `dist` allowlist (no
|
|
494
|
+
second npm package). Renders an honest foundation shell only — product
|
|
495
|
+
identity, live session status via `/api/status`, and placeholder
|
|
496
|
+
navigation/workspace/details regions — never fabricated evidence.
|
|
497
|
+
- **PWA**: `vite-plugin-pwa` generates a web app manifest (`standalone`
|
|
498
|
+
display, stable `start_url`/`scope`, installability icons) and a service
|
|
499
|
+
worker that precaches only the built application shell. It declares no
|
|
500
|
+
`runtimeCaching` rules, so future evidence/media/API routes remain
|
|
501
|
+
network/server-backed rather than silently served as stale cached truth
|
|
502
|
+
when the local server is unavailable (enforced by
|
|
503
|
+
`tests/unit/viewerPwaBuild.test.ts`, which asserts on the actual built
|
|
504
|
+
`sw.js`, not a hand-written approximation). An install affordance appears
|
|
505
|
+
only when the browser actually fires `beforeinstallprompt`; its absence is
|
|
506
|
+
shown honestly, never as a disabled-looking fake control.
|
|
507
|
+
- **CLI**: `view [--root <evidence-root>] [--port <n>] [--no-open]` remains a
|
|
508
|
+
thin dispatcher — it parses syntax, delegates once to `startViewer`, prints
|
|
509
|
+
the URL/root, and optionally best-effort opens the system browser (failure
|
|
510
|
+
there is never fatal to server startup). All v0.1-v0.7 commands are
|
|
511
|
+
unchanged.
|
|
512
|
+
|
|
513
|
+
This batch introduces no second observer, relationship engine, comparison
|
|
514
|
+
engine, contract engine, reference model, or bounded-context builder — there
|
|
515
|
+
is nothing yet for the viewer to consume beyond its own runtime identity.
|
|
516
|
+
|
|
517
|
+
## v0.8 Batch 2 (Evidence indexing, canonical readers, and lazy data boundary) — implemented
|
|
518
|
+
|
|
519
|
+
Batch 2 adds the safe, read-only data boundary between existing on-disk
|
|
520
|
+
Observer evidence and the Batch 1 viewer runtime, entirely under
|
|
521
|
+
`src/viewerServer/evidence/`. It introduces no new persisted artifact family,
|
|
522
|
+
no schema migration, and no second validator — every recognized candidate is
|
|
523
|
+
decided exclusively by the existing canonical reader/validator for its
|
|
524
|
+
family (`src/artifacts/*Reader.ts`).
|
|
525
|
+
|
|
526
|
+
```text
|
|
527
|
+
GET /api/index bounded discovery + classification -> metadata only
|
|
528
|
+
GET /api/artifacts/<handle> one canonical-reader read, on demand -> full projection
|
|
529
|
+
GET /api/media/<handle>/<role> one resolved, contained media file, streamed on demand
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
- **Discovery** (`evidence/discovery.ts`): a bounded, deterministic walk
|
|
533
|
+
beneath `--root` that opens only files literally named `manifest.json` (the
|
|
534
|
+
one filename every current persisted family uses) — no other file is ever
|
|
535
|
+
read or classified, so arbitrary files can never become evidence merely by
|
|
536
|
+
existing under the root. Directory entries that are symlinks/junctions are
|
|
537
|
+
never followed. Bounds (`evidence/limits.ts`): traversal depth 6,
|
|
538
|
+
directories visited 2000, candidate manifests 1000, index records 500,
|
|
539
|
+
manifest read size 2,000,000 bytes — chosen after inspecting that every
|
|
540
|
+
current writer produces a shallow `<outputLocation>/<id>/manifest.json`
|
|
541
|
+
shape (see `docs/CONTRACTS.md`), not a deep tree.
|
|
542
|
+
- **Classification is not validation** (`evidence/classify.ts`): peeks only
|
|
543
|
+
`artifactKind`/`schemaVersion` (plus, where the shared kind is ambiguous,
|
|
544
|
+
tries each existing reader/validator in turn — e.g. baseline vs. per-change
|
|
545
|
+
contract) to decide *which* existing canonical reader to call; the reader's
|
|
546
|
+
own structural validator remains the sole authority. Six honest, mutually
|
|
547
|
+
exclusive states: `supported`, `unsupported-version`, `invalid-structure`,
|
|
548
|
+
`unrecognized-kind`, `malformed-json`, `unreadable` — never collapsed into
|
|
549
|
+
one boolean, and never conflated with an artifact's own `completion`
|
|
550
|
+
state (passed through separately, only for the families that carry one:
|
|
551
|
+
observation and external-reference). A manifest declaring the
|
|
552
|
+
`bounded-agent-context` kind is classified `unrecognized-kind`: v0.6/v0.7
|
|
553
|
+
never added a disk writer/reader for that family (confirmed via direct
|
|
554
|
+
source inspection and `@dailephd/my-dev-kit` search), so Batch 2 does not
|
|
555
|
+
invent persistence-shaped handling for it.
|
|
556
|
+
- **Viewer handles** (`evidence/handles.ts`, `evidence/pathSafety.ts`): a
|
|
557
|
+
handle is a family-prefixed, percent-encoded, root-relative directory path
|
|
558
|
+
— never a raw filesystem path accepted from the browser. Every route that
|
|
559
|
+
accepts a handle re-decodes and re-resolves it against the evidence root,
|
|
560
|
+
re-checks containment, and re-classifies that one candidate before serving
|
|
561
|
+
anything; a handle whose backing directory or manifest no longer matches
|
|
562
|
+
what was indexed fails closed as unknown, never stale.
|
|
563
|
+
- **Ephemeral projection** (`evidence/projection.ts`): `EvidenceMetadataRecord`
|
|
564
|
+
(bounded, `/api/index`-shaped: handle, family, support state, logical id,
|
|
565
|
+
schema version, completion where applicable, media availability summary,
|
|
566
|
+
a handful of related ids) and `EvidenceArtifactDetail` (the already-
|
|
567
|
+
validated domain object, wrapped with `handle`/`family` — no new evidence
|
|
568
|
+
schema, no recomputation, no persistence).
|
|
569
|
+
- **Media resolution** (`evidence/mediaResolver.ts`): `screenshot` (observation),
|
|
570
|
+
`image` (imported external reference), and `source-image` (approved
|
|
571
|
+
external reference) are the only three recognized roles. An approved
|
|
572
|
+
reference's image is never assumed to live in the approved artifact's own
|
|
573
|
+
directory — its `sourceReference.referenceId` is looked up against the
|
|
574
|
+
current index to find the actual owning imported artifact
|
|
575
|
+
(`evidence/index.ts#findImportedReferenceDir`), exactly matching the v0.7
|
|
576
|
+
reference-ownership contract in `docs/CONTRACTS.md`. A genuinely missing
|
|
577
|
+
screenshot/image/source artifact is reported as 404, never fabricated.
|
|
578
|
+
- **PWA cache boundary preserved, not re-verified from scratch**: every new
|
|
579
|
+
route lives under `/api/`, already covered by Batch 1's
|
|
580
|
+
`denylist:[/^\/api\//]` navigation-fallback rule — no new `runtimeCaching`
|
|
581
|
+
entry was needed or added (`tests/unit/viewerPwaBuild.test.ts` asserts this
|
|
582
|
+
against the real built `sw.js`).
|
|
583
|
+
- **Minimal UI** (`viewer/src/hooks/useEvidenceIndex.ts`,
|
|
584
|
+
`useArtifactDetail.ts`, `components/EvidenceList.tsx`,
|
|
585
|
+
`ArtifactPreview.tsx`): a bounded evidence list (metadata-first) plus
|
|
586
|
+
on-demand full-artifact loading on selection, with every support state
|
|
587
|
+
shown honestly. No screenshot rendering, SVG overlay, or comparison/
|
|
588
|
+
contract/reference visualization exists yet — that begins in Batch 3.
|
|
589
|
+
|
|
590
|
+
## v0.8 Batch 3 (Runtime observation inspection and SVG overlays) — implemented
|
|
591
|
+
|
|
592
|
+
Batch 3 makes one already-supported `ObservationArtifact` (Batch 2's data
|
|
593
|
+
boundary, unchanged) genuinely understandable: a real screenshot, SVG target
|
|
594
|
+
overlays in the observation's own canonical coordinate domain, target
|
|
595
|
+
selection/inspection, and canonical layout-relationship display. No second
|
|
596
|
+
relationship engine, no client-side evidence derivation, no new persisted
|
|
597
|
+
artifact.
|
|
598
|
+
|
|
599
|
+
**Coordinate audit (the load-bearing decision for this batch)**: target
|
|
600
|
+
geometry (`TargetGeometry.x/y/width/height`) is captured via
|
|
601
|
+
`el.getBoundingClientRect()` (`src/browser/evidenceCapture.ts`) - CSS pixels,
|
|
602
|
+
relative to the current viewport's top-left, at the same live page state the
|
|
603
|
+
screenshot is taken from. The screenshot itself is `page.screenshot({type:
|
|
604
|
+
'png'})` (`src/browser/chromiumAdapter.ts`), Playwright's default
|
|
605
|
+
(non-fullPage) mode, against a browser context created with no
|
|
606
|
+
`deviceScaleFactor` override (`browser.newContext({viewport})`) - so it
|
|
607
|
+
defaults to `1`, meaning every observation this repository can currently
|
|
608
|
+
produce has a screenshot whose raw PNG pixel dimensions equal
|
|
609
|
+
`requestConfig.viewport.width × requestConfig.viewport.height` exactly (1
|
|
610
|
+
CSS pixel = 1 PNG pixel). `requestConfig.viewport` (a required, strongly-typed
|
|
611
|
+
field on every valid `ObservationArtifact`, distinct from the loosely-typed
|
|
612
|
+
`pageEvidence` bag) is therefore the canonical, always-present source for the
|
|
613
|
+
SVG display frame.
|
|
614
|
+
|
|
615
|
+
**SVG coordinate model** (`viewer/src/components/TargetOverlaySvg.tsx`): the
|
|
616
|
+
`<svg>` root's `viewBox` is `0 0 {requestConfig.viewport.width}
|
|
617
|
+
{requestConfig.viewport.height}` - the exact frame `getBoundingClientRect()`
|
|
618
|
+
already used. The screenshot loads into a `<image>` element filling that same
|
|
619
|
+
viewBox (`preserveAspectRatio="none"`, since the two frames are already
|
|
620
|
+
pixel-identical). Target `<rect>` elements use `geometry.x/y/width/height`
|
|
621
|
+
completely unchanged - no rounding, no `devicePixelRatio` multiplication, no
|
|
622
|
+
clamping; geometry lying partly outside the viewBox is drawn at its real
|
|
623
|
+
coordinates and clipped only by the SVG root's default `overflow: hidden`
|
|
624
|
+
(a display-only effect, verified never to touch the underlying evidence
|
|
625
|
+
value - `tests/unit/observationCoordinateMapping.test.ts`). This is robust
|
|
626
|
+
even if a future capture path used a different `deviceScaleFactor`: the
|
|
627
|
+
`<image>`/viewBox scaling is presentation-only browser behavior, never a
|
|
628
|
+
manual pixel calculation in this codebase. `devicePixelRatio` (captured as
|
|
629
|
+
`pageEvidence.devicePixelRatio`) is shown as informational observation-level
|
|
630
|
+
evidence only and is never consulted for any geometry calculation.
|
|
631
|
+
|
|
632
|
+
**Server additions** (`src/viewerServer/evidence/observationView.ts`, one new
|
|
633
|
+
route `GET /api/observations/<handle>/relationships`): the only new
|
|
634
|
+
server-side computation this batch adds is one thin, defense-in-depth-wrapped
|
|
635
|
+
call to the existing canonical, pure `deriveLayoutRelationships` (`src/domain/
|
|
636
|
+
relationships.ts`) - never a second relationship predicate implementation.
|
|
637
|
+
Mirrors the exact handle-decode → contained-dir-resolve → re-classify
|
|
638
|
+
discipline `loadArtifactByHandle`/`resolveMedia` already established in
|
|
639
|
+
Batch 2; a handle for a non-`observation` family or a non-`supported`
|
|
640
|
+
candidate is rejected (`409`) before derivation is even attempted. The
|
|
641
|
+
existing `GET /api/artifacts/<handle>` (full `ObservationArtifact`) and
|
|
642
|
+
`GET /api/media/<handle>/screenshot` (Batch 2, unchanged) remain the only
|
|
643
|
+
other data sources the observation workspace uses - no new artifact
|
|
644
|
+
projection endpoint was needed, since the full validated domain object
|
|
645
|
+
already contains everything the target/observation inspector displays.
|
|
646
|
+
|
|
647
|
+
**Client-side presentation only** (`viewer/src/observation/targetOrder.ts`,
|
|
648
|
+
`viewer/src/components/{ObservationWorkspace,TargetList,TargetOverlaySvg,
|
|
649
|
+
ObservationInspector,EvidenceFieldView}.tsx`): React selects, orders
|
|
650
|
+
(by the observation's own authored `requestConfig.targets` order, not
|
|
651
|
+
incidental object-key order), and formats already-fetched canonical fields.
|
|
652
|
+
It never resolves targets, computes relationships, or derives
|
|
653
|
+
visibility/overflow/scroll-owner semantics - `deriveLayoutRelationships`
|
|
654
|
+
runs exclusively on the server (above). An unresolved target (`not-found`/
|
|
655
|
+
`ambiguous`/`unavailable`) is selectable from the target list and shown
|
|
656
|
+
honestly in the inspector, but never receives a fabricated `<rect>` -
|
|
657
|
+
`orderedTargets()`'s `hasGeometry` flag is `true` only when
|
|
658
|
+
`geometry.state` is `'available'` or `'partial'`.
|
|
659
|
+
|
|
660
|
+
**Selection**: viewer presentation state only (React `useState`, reset on
|
|
661
|
+
observation change), never persisted, synchronized in both directions
|
|
662
|
+
between the target list, the SVG `<rect>` (`role="button"`, keyboard-
|
|
663
|
+
operable), and the inspector via the target's existing stable `name`.
|
|
664
|
+
|
|
665
|
+
**Overlay toggles**: geometry, labels (disabled when geometry is off), and
|
|
666
|
+
relationships - each independently toggleable and purely presentational
|
|
667
|
+
(hiding/showing already-rendered elements), never altering the underlying
|
|
668
|
+
evidence or the fetched artifact/graph.
|
|
669
|
+
|
|
670
|
+
**PWA cache boundary preserved**: the new `/api/observations/*` route lives
|
|
671
|
+
under the same `/api/` prefix Batch 1's `navigateFallbackDenylist` already
|
|
672
|
+
denylists - no service-worker configuration change was needed
|
|
673
|
+
(`tests/unit/viewerPwaBuild.test.ts` asserts this against the real built
|
|
674
|
+
`sw.js`).
|
|
675
|
+
|
|
676
|
+
## v0.8 Batch 4 (Before/after comparison and contract/change-scope inspection) — implemented
|
|
677
|
+
|
|
678
|
+
Batch 4 exposes the existing v0.4 `ComparisonArtifact` and v0.5
|
|
679
|
+
`FrontendContractEvaluationArtifact` through the viewer, entirely under
|
|
680
|
+
`src/viewerServer/evidence/{linkedEvidence,comparisonView,evaluationView}.ts`
|
|
681
|
+
and `viewer/src/components/{ComparisonWorkspace,EvaluationWorkspace,
|
|
682
|
+
ComparisonObservationPane,ClauseResultRow}.tsx`. **`compareObservations` and
|
|
683
|
+
`evaluateFrontendContract` are never called anywhere in this batch** - every
|
|
684
|
+
displayed comparison/evaluation field is read unchanged from its persisted
|
|
685
|
+
artifact via the existing Batch 2 `GET /api/artifacts/<handle>`.
|
|
686
|
+
|
|
687
|
+
- **Exact linked-evidence resolution** (`evidence/linkedEvidence.ts`): given
|
|
688
|
+
a `ComparisonSourceObservationReference`/`FrontendContractObservationReference`,
|
|
689
|
+
a `comparisonId`+`comparisonRequestId` pair, or a `baselineId`/`contractId`,
|
|
690
|
+
resolves the matching indexed artifact by **exact identity only**
|
|
691
|
+
(`observationId`+`requestId`+`producer.version`+`observationSchemaVersion`
|
|
692
|
+
for observations; the id fields themselves for comparisons/contracts) -
|
|
693
|
+
never by folder name, screenshot filename, URL, target-set, or geometry
|
|
694
|
+
similarity. Zero matches → `missing`; two or more exact matches →
|
|
695
|
+
`ambiguous` (never silently picks one). Mirrors the exact bounded-walk
|
|
696
|
+
pattern Batch 2's `findImportedReferenceDir` already established.
|
|
697
|
+
- **Two additive, read-only routes**: `GET /api/comparisons/<handle>/view`
|
|
698
|
+
(resolves the comparison's `before`/`after`) and
|
|
699
|
+
`GET /api/evaluations/<handle>/view` (resolves `comparison`, `baseline`,
|
|
700
|
+
`change`, `before`, `after`) - both under `/api/`, both GET/HEAD-only, both
|
|
701
|
+
returning only resolved-handle-or-missing-or-ambiguous status, never a
|
|
702
|
+
duplicated copy of the linked artifact's own payload (the browser fetches
|
|
703
|
+
that separately through the existing `GET /api/artifacts/<handle>`, reusing
|
|
704
|
+
Batch 2's on-demand-loading contract exactly).
|
|
705
|
+
- **Before/after visual reuse, not reimplementation**: `ComparisonObservationPane.tsx`
|
|
706
|
+
is built entirely from Batch 3's existing lower-level primitives
|
|
707
|
+
(`useArtifactDetail`, `orderedTargets`, `TargetOverlaySvg`) - no second
|
|
708
|
+
screenshot-loading, coordinate-transform, or geometry-rendering code
|
|
709
|
+
exists. The comparison's own persisted `relationshipsBefore`/
|
|
710
|
+
`relationshipsAfter` are passed directly into `TargetOverlaySvg`'s existing
|
|
711
|
+
`relationships` prop - never recomputed via `deriveLayoutRelationships`.
|
|
712
|
+
`TargetOverlaySvg` gained one small additive, optional `highlightNames`
|
|
713
|
+
prop (alongside the existing single-select `selected`) so a
|
|
714
|
+
relationship-subject difference or a two-target contract primitive
|
|
715
|
+
(`targets-do-not-overlap`, `target-fits-inside`, etc.) can emphasize both
|
|
716
|
+
named targets at once without changing Batch 3's existing single-select
|
|
717
|
+
interaction contract.
|
|
718
|
+
- **Difference/relationship-change/clause presentation is evidence display,
|
|
719
|
+
not re-derivation**: `ComparisonWorkspace.tsx` renders `differences`,
|
|
720
|
+
`relationshipChanges`, `configurationChanges` (kept visually distinct from
|
|
721
|
+
appeared/disappeared runtime differences), and `expectedDependencyEvidence`
|
|
722
|
+
exactly as persisted, labeling dependency outcomes as explicit non-causal
|
|
723
|
+
evidence. `comparability` (comparable/comparable-with-warnings/incomparable
|
|
724
|
+
plus blocking/warning/unassessed reasons) is shown honestly; an
|
|
725
|
+
`incomparable` result is visually unmistakable
|
|
726
|
+
(`.comparability-banner--incomparable`).
|
|
727
|
+
- **Clause joining by exact `clauseId` only** (`EvaluationWorkspace.tsx`):
|
|
728
|
+
baseline clauses (from the linked `PersistentBaselineContract`) and
|
|
729
|
+
per-change clauses (from the linked `PerChangeContract`) are joined to the
|
|
730
|
+
evaluation's `clauseResults` by exact id - never by target/primitive-shape/
|
|
731
|
+
category/position. A `clauseId` absent from both loaded contracts is shown
|
|
732
|
+
as an honest "unresolved clause definition", never fabricated. Baseline
|
|
733
|
+
clause active/superseded status comes exclusively from the evaluation
|
|
734
|
+
artifact's own `activeBaselineClauseIds`/`supersededBaselineClauseIds` -
|
|
735
|
+
never recomputed from clause overlap. `pass`/`fail`/`unavailable`/
|
|
736
|
+
`conflict` are preserved exactly (never collapsed to a boolean);
|
|
737
|
+
`unavailable` shows its reason, `conflict` shows its reason and
|
|
738
|
+
`conflictingClauseIds`.
|
|
739
|
+
- **Overall verdict is authoritative and unmistakable**: `overallVerdict`
|
|
740
|
+
(`PASS`/`FAIL`) is rendered directly from the artifact, in a large
|
|
741
|
+
`.overall-verdict--PASS`/`.overall-verdict--FAIL` banner - the UI never
|
|
742
|
+
computes it from visible rows. The required safety case (a `requested`
|
|
743
|
+
clause `pass` alongside a `protected`/`preserved` clause `fail` still
|
|
744
|
+
producing overall `FAIL`) and the all-pass case are both proven against
|
|
745
|
+
real, canonically-evaluated fixtures (`tests/support/evidenceFixtures.ts#writeFullPipelineFixture`/
|
|
746
|
+
`writeAllPassPipelineFixture`) in real Chromium
|
|
747
|
+
(`tests/browser/comparisonEvaluationWorkspace.test.ts`) - `overallVerdict`
|
|
748
|
+
is never hand-edited to construct either demonstration.
|
|
749
|
+
- **Target/relationship cross-highlighting uses only explicit canonical
|
|
750
|
+
identity**: `primitiveTargetNames()` (`viewer/src/contract/clauseTargets.ts`)
|
|
751
|
+
extracts a contract primitive's named target field(s) (`target`, `targetA`/
|
|
752
|
+
`targetB`, `target`+`container`, `subjectTarget`/`relatedTarget`) by an
|
|
753
|
+
exhaustive switch over `ContractPrimitiveKind` - page-level primitives
|
|
754
|
+
(`document-width-fits-viewport`, `scroll-owner-is-document`) return no
|
|
755
|
+
names, so clicking them never fabricates a target highlight.
|
|
756
|
+
- **PWA cache boundary preserved**: both new routes live under `/api/`,
|
|
757
|
+
already covered by Batch 1's `navigateFallbackDenylist`; verified against
|
|
758
|
+
the real built `sw.js`.
|
|
759
|
+
|
|
760
|
+
## v0.8 Batch 5 (External reference and reference/candidate inspection) — implemented
|
|
761
|
+
|
|
762
|
+
- **Reference indexing/media already existed (Batch 2), unchanged**: the
|
|
763
|
+
`external-reference-imported`/`external-reference-approved` families,
|
|
764
|
+
`GET /api/media/<handle>/image` (imported), and
|
|
765
|
+
`GET /api/media/<handle>/source-image` (approved, resolved through
|
|
766
|
+
`findImportedReferenceDir`'s exact `referenceId` walk) were already built
|
|
767
|
+
in Batch 2 and required no change here - Batch 5 only adds the visual
|
|
768
|
+
workspace consuming them.
|
|
769
|
+
- **Two new additive, read-only routes**
|
|
770
|
+
(`src/viewerServer/evidence/referenceView.ts`):
|
|
771
|
+
`GET /api/references/<handle>/view` derives the selected reference's own
|
|
772
|
+
region-relationship graph (`deriveReferenceRegionRelationships`) and
|
|
773
|
+
requirement adequacy (`deriveReferenceRequirementAdequacy`) - both pure
|
|
774
|
+
functions over the artifact's own persisted `regions`/`requirements`,
|
|
775
|
+
never persisted, never a second derivation engine (mirrors Batch 3's
|
|
776
|
+
`getObservationRelationships` server-side-derivation pattern).
|
|
777
|
+
`GET /api/references/<handle>/candidate/<handle>/view` evaluates
|
|
778
|
+
reference/candidate compatibility through the existing canonical
|
|
779
|
+
`evaluateReferenceCandidateCompatibility` (never a second, viewer-owned
|
|
780
|
+
compatibility model) and separately lists every existing
|
|
781
|
+
`FrontendContractEvaluationArtifact` whose own persisted `after` reference
|
|
782
|
+
exactly identifies the candidate, for explicit, never-auto-selected
|
|
783
|
+
optional display.
|
|
784
|
+
- **Reference-image SVG coordinate model is a genuinely distinct domain from
|
|
785
|
+
the candidate's runtime SVG** (`ReferenceRegionOverlaySvg.tsx`): `viewBox`
|
|
786
|
+
is the reference image's own pixel dimensions (never the candidate's CSS
|
|
787
|
+
viewport, never devicePixelRatio-multiplied); each region's canonical
|
|
788
|
+
`{x, y, width, height}` is rendered unchanged. Because this is a different
|
|
789
|
+
coordinate domain and data source from `TargetOverlaySvg` (runtime CSS
|
|
790
|
+
pixels, `TargetGeometry`), it is a separate, sibling component rather than
|
|
791
|
+
a parameterization of the existing one - reuse would have silently
|
|
792
|
+
conflated the two domains. The candidate side, in contrast, reuses Batch
|
|
793
|
+
3/4's exact `ComparisonObservationPane`/`TargetOverlaySvg` machinery
|
|
794
|
+
unchanged (a synthetic `{status:'resolved', handle}` `LinkStatus` is
|
|
795
|
+
constructed once a candidate is explicitly chosen).
|
|
796
|
+
- **Reference region selection and runtime target selection are two
|
|
797
|
+
independent, never-synchronized selection domains**
|
|
798
|
+
(`ReferenceWorkspace.tsx`): selecting a reference region never selects or
|
|
799
|
+
highlights a runtime target, even when both happen to share the same
|
|
800
|
+
string name (proven with a real Chromium fixture deliberately naming both
|
|
801
|
+
`"header"` - `tests/browser/referenceCandidateWorkspace.test.ts`, Case E).
|
|
802
|
+
No binding connector/highlight-across-panes exists in this batch - that is
|
|
803
|
+
Batch 6's explicit-binding-interaction scope.
|
|
804
|
+
- **Compatibility vs. reference adequacy vs. candidate fidelity are kept
|
|
805
|
+
strictly distinct, never conflated**: compatibility
|
|
806
|
+
(`comparable`/`comparable-with-warnings`/`incomparable` plus
|
|
807
|
+
blocking/warning/unassessed reasons) comes only from
|
|
808
|
+
`evaluateReferenceCandidateCompatibility`; reference-side requirement
|
|
809
|
+
adequacy (`adequate`/`partial`/`inadequate`) comes only from
|
|
810
|
+
`deriveReferenceRequirementAdequacy`; candidate fidelity is never computed
|
|
811
|
+
in this batch at all - the UI always shows an explicit "not evaluated in
|
|
812
|
+
this batch" note rather than ever implying a fidelity PASS from a
|
|
813
|
+
compatibility PASS or an adequate reference (task §32/§33 boundary,
|
|
814
|
+
`evaluateReferenceCandidateFidelity` is never imported/called anywhere in
|
|
815
|
+
Batch 5).
|
|
816
|
+
- **Optional contract/evaluation context is opt-in, never inferred**
|
|
817
|
+
(`ReferenceWorkspace.tsx`): when the reference/candidate view lists more
|
|
818
|
+
than one exactly-matching evaluation artifact, the developer must
|
|
819
|
+
explicitly pick one from a `<select>` - the newest/first match is never
|
|
820
|
+
silently chosen, and with zero selected the candidate's contract status
|
|
821
|
+
reads "not selected/not available", never a fabricated PASS.
|
|
822
|
+
- **Imported vs. approved image ownership preserved exactly as Batch 2 built
|
|
823
|
+
it**: an imported reference's image is fetched from its own directory; an
|
|
824
|
+
approved reference's image is fetched from its exact imported source via
|
|
825
|
+
`sourceReference.referenceId`, never assumed co-located, never
|
|
826
|
+
duplicated - proven with a real Chromium fixture asserting the two
|
|
827
|
+
`<image href>` values resolve to the `image`/`source-image` roles
|
|
828
|
+
respectively (Cases A/B).
|
|
829
|
+
- **PWA cache boundary preserved**: both new routes live under `/api/`,
|
|
830
|
+
already covered by Batch 1's `navigateFallbackDenylist`; verified against
|
|
831
|
+
the real built `sw.js` (no new `registerRoute`, no `/api/references`
|
|
832
|
+
precache entry).
|
|
833
|
+
|
|
834
|
+
## v0.8 Batch 6 (Explicit-binding interaction, zoom/pan, conditional lock, and on-demand reference fidelity) — implemented
|
|
835
|
+
|
|
836
|
+
- **`view --bindings-file <json-file>`**: reuses the exact same operational
|
|
837
|
+
binding-file wrapper parser (`loadBindingsFile` in `src/cli.ts`) that
|
|
838
|
+
`evaluate-reference-fidelity --bindings-file` already used - one shared
|
|
839
|
+
parser, never a second divergent one. The file is read once at startup;
|
|
840
|
+
its declarations become `ViewerServerState.bindingDeclarations` (an opaque
|
|
841
|
+
`unknown[]` until validated against a specific reference); the file path
|
|
842
|
+
itself is never persisted, returned, or exposed to the browser. Reference-
|
|
843
|
+
specific declaration validity (region existence, shape) is deferred to the
|
|
844
|
+
moment a reference is actually selected server-side, via the existing
|
|
845
|
+
canonical `isValidReferenceRuntimeBindingDeclarations` - never checked at
|
|
846
|
+
startup without a reference.
|
|
847
|
+
- **Two new additive, read-only routes**
|
|
848
|
+
(`src/viewerServer/evidence/referenceView.ts`):
|
|
849
|
+
`GET /api/references/<handle>/candidate/<handle>/bindings` validates the
|
|
850
|
+
session's declarations against the selected reference and calls the
|
|
851
|
+
existing canonical `evaluateReferenceRuntimeBindings` exactly once.
|
|
852
|
+
`GET /api/references/<handle>/candidate/<handle>/fidelity` is the explicit
|
|
853
|
+
on-demand fidelity trigger - calls the existing canonical
|
|
854
|
+
`evaluateReferenceCandidateFidelity` exactly once, using the exact same
|
|
855
|
+
session declarations, so its embedded `bindings` field and the `/bindings`
|
|
856
|
+
route's own result always structurally agree for identical inputs (same
|
|
857
|
+
pure function, same arguments). Neither route persists anything; both are
|
|
858
|
+
`GET` (idempotent, deterministic, ephemeral over already-selected explicit
|
|
859
|
+
input) - no mutation route was added.
|
|
860
|
+
- **`deriveCoordinateScale` exported additively** from
|
|
861
|
+
`externalReferenceFidelity.ts` (previously module-private) - Batch 6's
|
|
862
|
+
view-lock eligibility reuses this exact function unchanged (same formula,
|
|
863
|
+
same `ASPECT_RATIO_MAPPING_TOLERANCE`, same no-applicable-viewport
|
|
864
|
+
failure) rather than a second aspect-ratio/scale implementation. The
|
|
865
|
+
existing `GET /api/references/<handle>/candidate/<handle>/view` route now
|
|
866
|
+
additionally returns `coordinateMapping: DeriveCoordinateScaleResult` -
|
|
867
|
+
purely a function of the reference, independent of the candidate.
|
|
868
|
+
- **Explicit-binding cross-selection uses only canonical
|
|
869
|
+
`ReferenceRuntimeBindingResult.referenceRegion`/`.runtimeTarget` fields**
|
|
870
|
+
(`ReferenceWorkspace.tsx`): selecting a `bound` reference region
|
|
871
|
+
highlights (via `TargetOverlaySvg`'s existing Batch 4 `highlightNames`
|
|
872
|
+
prop - never the primary `selected`/`aria-pressed` target) its exact
|
|
873
|
+
declared runtime target; selecting a runtime target highlights every
|
|
874
|
+
region whose `bound` result names it (many-to-one, via a new additive
|
|
875
|
+
`highlightRegionIds` prop on `ReferenceRegionOverlaySvg`, matching
|
|
876
|
+
`TargetOverlaySvg`'s established highlight pattern). `ambiguous`/
|
|
877
|
+
`unavailable` results never cross-select. Proven with a real equal-name
|
|
878
|
+
("header" region + "header" target) Chromium fixture: no cross-selection
|
|
879
|
+
without an explicit declaration, real cross-selection with one.
|
|
880
|
+
- **Zoom/pan is a repository-owned, presentation-only hook**
|
|
881
|
+
(`viewer/src/hooks/useZoomPan.ts`): bounded `[1x, 8x]` scale, `×1.25`/
|
|
882
|
+
`÷1.25` step, expressed as one `{scale, focalX, focalY}` triple in the
|
|
883
|
+
pane's own source-coordinate frame (reference-image pixels or candidate
|
|
884
|
+
CSS pixels - never rewritten). Renders via an SVG `viewBox` override
|
|
885
|
+
(additive `viewBoxOverride`/`svgRef`/pointer-handler props on
|
|
886
|
+
`TargetOverlaySvg`/`ReferenceRegionOverlaySvg`, defaulting to Batch 3/5's
|
|
887
|
+
exact prior behavior when omitted) - image and overlay stay one
|
|
888
|
+
transformed unit automatically since both live inside the same `<svg>`
|
|
889
|
+
root, and native SVG hit-testing means selection keeps working correctly
|
|
890
|
+
under zoom/pan with no extra coordinate math. Panning uses the SVG
|
|
891
|
+
element's own `getScreenCTM()` to convert screen-space pointer deltas into
|
|
892
|
+
source-space deltas - reuses the browser's native transform rather than a
|
|
893
|
+
custom aspect-ratio-aware pixel calculation - and only engages (calling
|
|
894
|
+
`setPointerCapture`) once the pointer has moved past a small threshold, so
|
|
895
|
+
an ordinary click on a region/target rect is never hijacked into a
|
|
896
|
+
phantom drag. Fit and Reset are the same fitted-1x/centered default (task
|
|
897
|
+
§26 - no second presentation-only default was introduced).
|
|
898
|
+
- **View lock reuses one single shared state, never two independently
|
|
899
|
+
synchronized states**: `ReferenceWorkspace.tsx` owns `refZoom`/`candZoom`
|
|
900
|
+
directly (always-controlled `useZoomPan` calls) and each pane's zoom/pan
|
|
901
|
+
action handler updates both states in one synchronous call when locked -
|
|
902
|
+
no reactive effect watches one pane's state to update the other, so no
|
|
903
|
+
feedback-loop risk exists. Lock is available only when a candidate is
|
|
904
|
+
selected, compatibility is not `incomparable`, and `coordinateMapping.ok`
|
|
905
|
+
is `true`; any change to that eligibility (including selecting a
|
|
906
|
+
different reference/candidate) immediately disables lock and shows an
|
|
907
|
+
actionable reason. Synchronization converts a candidate CSS-pixel focal
|
|
908
|
+
point/scale into reference-image-pixel space (and back) using only
|
|
909
|
+
`coordinateMapping.scale.scaleX`/`scaleY` - the exact same canonical
|
|
910
|
+
factor `deriveCoordinateScale` already produces, applied as a straight
|
|
911
|
+
multiply/divide (its own algebraic inverse), never a second mapping rule.
|
|
912
|
+
- **Contract/fidelity independence is never collapsed into one status**:
|
|
913
|
+
the existing Batch 5 "Optional contract/evaluation context" section
|
|
914
|
+
(unchanged) and the new on-demand `ReferenceFidelityPanel` are two
|
|
915
|
+
separate sections rendering two separate canonical results
|
|
916
|
+
(`FrontendContractEvaluationArtifact.overallVerdict` and
|
|
917
|
+
`ReferenceCandidateFidelityEvaluation.state`) side by side; when both are
|
|
918
|
+
present, an explicit note states that fidelity does not override an
|
|
919
|
+
active contract failure. No new coordinator/aggregate verdict is computed
|
|
920
|
+
anywhere in this batch.
|
|
921
|
+
- **PWA cache boundary preserved**: both new routes live under `/api/`,
|
|
922
|
+
already covered by Batch 1's `navigateFallbackDenylist`.
|
|
923
|
+
|
|
924
|
+
## v0.8 Batch 7 (Bounded agent context, correlation, provenance, and raw evidence navigation) — implemented
|
|
925
|
+
|
|
926
|
+
- **Bounded agent context remains programmatic-only**: no filesystem writer
|
|
927
|
+
was added for `BoundedAgentContextArtifact` (it is still not an
|
|
928
|
+
Observer-evidence-root artifact family - `src/viewerServer/evidence/classify.ts`'s
|
|
929
|
+
"known but unreadered kind" comment is unchanged). `view --context-file
|
|
930
|
+
<json-file>` reads exactly one already-serialized
|
|
931
|
+
`BoundedAgentContextArtifact` value directly (no wrapper object) as
|
|
932
|
+
explicit, session-only viewer input - read once at startup
|
|
933
|
+
(`src/cli.ts#loadContextFile`, mirroring `loadBindingsFile`'s exact
|
|
934
|
+
read/size-bound/parse shape), classified by
|
|
935
|
+
`src/viewerServer/context.ts#classifyContextFileContent` (reuses the
|
|
936
|
+
existing canonical `isValidBoundedAgentContextArtifact` - never a second
|
|
937
|
+
validator), and held only in `ViewerServerState.context` for the life of
|
|
938
|
+
the process. The file's size is bounded by the existing Batch 2
|
|
939
|
+
`MAX_MANIFEST_CANDIDATE_BYTES` (2,000,000 bytes) rather than a second
|
|
940
|
+
bound, since a context artifact's own frozen numeric caps already make it
|
|
941
|
+
far smaller in any realistic case.
|
|
942
|
+
- **Three honest session states, never coerced into one another**: `'none'`
|
|
943
|
+
(no `--context-file`; every Batch 1-6 feature stays fully available),
|
|
944
|
+
`'unsupported-version'` (recognized `artifactKind`, a `schemaVersion`
|
|
945
|
+
other than the current one - the viewer still starts, showing this
|
|
946
|
+
state explicitly rather than either failing or misinterpreting the
|
|
947
|
+
fields), and `'valid'` (structurally validated current-schema context).
|
|
948
|
+
Every other problem (unreadable file, wrong `artifactKind`, a
|
|
949
|
+
structurally invalid *current*-schema artifact) fails viewer startup
|
|
950
|
+
clearly - an explicitly supplied file is never silently ignored.
|
|
951
|
+
- **`GET /api/context`** (`httpServer.ts`) returns the session's exact
|
|
952
|
+
classified state; for `'valid'`, it additionally returns
|
|
953
|
+
`sourceResolution` - the result of resolving
|
|
954
|
+
`artifact.sources` against the current evidence root by **exact
|
|
955
|
+
canonical identity only**
|
|
956
|
+
(`src/viewerServer/evidence/contextSourceView.ts`, reusing/extending
|
|
957
|
+
Batch 4's `linkedEvidence.ts` resolver pattern with three additive
|
|
958
|
+
functions: `resolveObservationById` (bare `observationId`, the only
|
|
959
|
+
identity a context source reference actually carries),
|
|
960
|
+
`resolveEvaluationByIdentity`, and `resolveReferenceByIdentity`). Zero
|
|
961
|
+
matches → `missing`; two or more → `ambiguous` (never silently picks
|
|
962
|
+
one) - the same discipline every other Batch 4/5 resolver already
|
|
963
|
+
established.
|
|
964
|
+
- **Raw structured evidence reuses the existing Batch 2 artifact-detail
|
|
965
|
+
route unchanged**: `RawEvidenceViewer.tsx` calls the existing
|
|
966
|
+
`useArtifactDetail`/`GET /api/artifacts/<handle>` for any exactly-resolved
|
|
967
|
+
source - no second full-artifact retrieval mechanism, no local filesystem
|
|
968
|
+
read, no arbitrary path accepted from the browser.
|
|
969
|
+
`EvidenceReference.path` values are always displayed as plain provenance
|
|
970
|
+
text, never passed to `fs.readFile`/`path.resolve`/a static file server.
|
|
971
|
+
- **Bounded runtime targets, adequacy, omissions, truncations, and
|
|
972
|
+
correlation are rendered exactly as the validated artifact states them** -
|
|
973
|
+
never recomputed, never boolean-collapsed
|
|
974
|
+
(`ContextWorkspace.tsx`): `Adequacy.state`
|
|
975
|
+
(`adequate`/`partial`/`inadequate`) and reasons are shown verbatim;
|
|
976
|
+
absent bounded-target fields render "not included in this bounded
|
|
977
|
+
context", never a fabricated falsy/zero value; `required: true`
|
|
978
|
+
omissions/truncations render in a visually distinct
|
|
979
|
+
`.context-required-loss` block, separate from optional ones;
|
|
980
|
+
`correlations` absent renders "Static correlation not included in this
|
|
981
|
+
context" - never "unavailable" (that status is reserved for a real
|
|
982
|
+
per-target `RuntimeStaticCorrelationRecord` with zero candidates).
|
|
983
|
+
`correlated`/`ambiguous`/`unavailable` are preserved exactly; a
|
|
984
|
+
`correlated` record's one candidate is labeled "Correlated candidate", an
|
|
985
|
+
`ambiguous` record shows **every** supplied candidate with none visually
|
|
986
|
+
promoted, and `unavailable` fabricates zero candidates - matching the
|
|
987
|
+
frozen `CORRELATION_STATUSES` invariants
|
|
988
|
+
(`domain/boundedAgentContext.ts`) the validator itself already enforces.
|
|
989
|
+
All new UI text was audited against ownership/edit-authorization language
|
|
990
|
+
(no "owner"/"source owner"/"owned by") - correlation is presented as
|
|
991
|
+
evidence, never as edit authorization.
|
|
992
|
+
- **Context-target ↔ runtime-target interaction never infers source
|
|
993
|
+
ownership**: selecting a bounded target or a correlation record uses only
|
|
994
|
+
exact `targetId`/`runtimeTargetId` string matching; for each *exactly
|
|
995
|
+
resolved* source observation, `SourceObservationTargetCheck` checks
|
|
996
|
+
membership in that observation's own already-fetched `targetEvidence`
|
|
997
|
+
(a plain lookup over already-loaded JSON, never a new derivation) and, if
|
|
998
|
+
more than one resolved source observation contains the same target id,
|
|
999
|
+
lists all of them rather than picking one.
|
|
1000
|
+
- **Bounded reference-fidelity projection is never recomputed, and is kept
|
|
1001
|
+
visibly distinct from a live on-demand evaluation**: absent `fidelity`
|
|
1002
|
+
renders "Reference fidelity not included in this bounded context" - never
|
|
1003
|
+
implied as passing. When present, `mismatches` and `protectedContext` are
|
|
1004
|
+
rendered in separate sections from the artifact's own fields exactly as
|
|
1005
|
+
supplied; a `state: 'not-evaluated'` blocked projection always shows
|
|
1006
|
+
`blockedBy` prominently and never renders an empty mismatch list as "no
|
|
1007
|
+
problems". When the context's `referenceId`/`candidateObservationId`
|
|
1008
|
+
exactly resolve within the current evidence root, `ContextWorkspace.tsx`
|
|
1009
|
+
embeds the existing, unchanged Batch 6 `ReferenceFidelityPanel` (the same
|
|
1010
|
+
on-demand `evaluateReferenceCandidateFidelity` trigger) directly beneath
|
|
1011
|
+
the bounded projection, labeled "Bounded context fidelity projection"
|
|
1012
|
+
above and "Current on-demand fidelity evaluation" below - two separate,
|
|
1013
|
+
clearly labeled evidence instances, never silently merged or replaced.
|
|
1014
|
+
- **No runtime rebuild of context or correlation, and no my-dev-kit
|
|
1015
|
+
execution from the shipped viewer**: grep-verified - `projectBoundedAgentContext(`,
|
|
1016
|
+
`deriveRuntimeStaticCorrelations(`, and `attachRuntimeStaticCorrelations(`
|
|
1017
|
+
appear nowhere under `src/viewerServer/` or `viewer/src/` (only in test/
|
|
1018
|
+
fixture-generation code, per the frozen plan's explicit test-fixture
|
|
1019
|
+
exception); no `child_process`/`npx @dailephd/my-dev-kit` invocation
|
|
1020
|
+
exists in the viewer server or browser bundle.
|
|
1021
|
+
- **PWA cache boundary preserved**: `GET /api/context` lives under `/api/`,
|
|
1022
|
+
already covered by Batch 1's `navigateFallbackDenylist`.
|
|
1023
|
+
|
|
1024
|
+
## v0.8 Batch 8 (Integrated viewer acceptance, PWA hardening, and packaged proof) — implemented
|
|
1025
|
+
|
|
1026
|
+
Batch 8 is the final v0.8 implementation batch. It is integration/hardening,
|
|
1027
|
+
not a new architecture layer: no new API route, no new CLI flag, and no new
|
|
1028
|
+
canonical-engine call site were added. See
|
|
1029
|
+
`docs/reports/v0.8-integrated-viewer-acceptance-batch8.md` for the full
|
|
1030
|
+
record.
|
|
1031
|
+
|
|
1032
|
+
- **Closed three named real-browser coverage gaps**, each proved against the
|
|
1033
|
+
actual built viewer through the actual loopback server, never a hand-edited
|
|
1034
|
+
fixture verdict: many reference regions bound to one runtime target all
|
|
1035
|
+
cross-highlight together (the pre-existing target→regions loop in
|
|
1036
|
+
`ReferenceWorkspace.tsx` already iterated every matching binding - the gap
|
|
1037
|
+
was in real-browser proof, not in the derivation); reference-fidelity
|
|
1038
|
+
`fail` alongside a genuine frontend-contract `PASS` for the same candidate
|
|
1039
|
+
display independently (the pre-existing independence note in
|
|
1040
|
+
`ReferenceWorkspace.tsx` was already verdict-agnostic); a bounded context
|
|
1041
|
+
whose sources include two observations sharing a stable target id lists
|
|
1042
|
+
every matching source observation (the pre-existing
|
|
1043
|
+
`SourceObservationTargetCheck` in `ContextWorkspace.tsx` already checked
|
|
1044
|
+
membership per source independently, never picking one).
|
|
1045
|
+
- **One real accessibility defect found and fixed**: a cross-highlighted,
|
|
1046
|
+
non-selected region/target `<rect>` (`TargetOverlaySvg.tsx`,
|
|
1047
|
+
`ReferenceRegionOverlaySvg.tsx`) exposed no accessible state distinguishing
|
|
1048
|
+
it from a plain unselected rect - `aria-pressed` correctly stayed `false`
|
|
1049
|
+
(it is not the primary single-selection), but nothing else communicated
|
|
1050
|
+
the highlight to assistive technology. Fixed by adding
|
|
1051
|
+
`data-highlighted="true"` and an `aria-label` suffix
|
|
1052
|
+
(`" (highlighted: related to current selection)"`) when highlighted and
|
|
1053
|
+
not selected, leaving `aria-pressed` semantics untouched.
|
|
1054
|
+
- **First live-browser PWA proof suite** (`tests/browser/pwaHardening.test.ts`):
|
|
1055
|
+
real service-worker registration and activation against the built shell;
|
|
1056
|
+
the manifest fetched and confirmed `display: "standalone"`; zero Cache
|
|
1057
|
+
Storage entries under any `/api/` pathname after normal use, confirming
|
|
1058
|
+
the `navigateFallbackDenylist` boundary holds live, not just in the built
|
|
1059
|
+
`sw.js` regex; and the hard server-down gate - after the server is closed
|
|
1060
|
+
and the same page reloaded, the app shell still renders from the precache,
|
|
1061
|
+
but the evidence-dependent surface shows the explicit
|
|
1062
|
+
`.evidence-list__error` "Evidence index unavailable" state, with the
|
|
1063
|
+
previously-visible evidence asserted absent. Install-control is proven
|
|
1064
|
+
only via synthetic `beforeinstallprompt` dispatch (a genuine browser
|
|
1065
|
+
install prompt was not observed under automation). Standalone-mode CDP
|
|
1066
|
+
display-mode emulation was attempted but not observed to take effect -
|
|
1067
|
+
recorded honestly, never overstated as actual OS-level installation proof.
|
|
1068
|
+
- **Packaged-candidate proof**: `npm pack` → clean consumer install (outside
|
|
1069
|
+
the repository) → the actually-installed CLI executable (not repo
|
|
1070
|
+
`dist/cli.js`) → the installed `view` server → real Chromium against the
|
|
1071
|
+
packaged/installed server, not a source-checkout dev server. Read-only
|
|
1072
|
+
evidence-hash proof (SHA-256 of every file in the exercised evidence root,
|
|
1073
|
+
taken before and after the packaged-browser session) confirmed no
|
|
1074
|
+
mutation and no new viewer-created artifact anywhere in the evidence root.
|
|
1075
|
+
- **Re-confirmed the no-second-engine invariant** across all eight batches by
|
|
1076
|
+
re-running the exact `grep -rn` audit from earlier batches - unchanged
|
|
1077
|
+
findings, no duplicate evidence engine exists.
|
|
1078
|
+
|
|
1079
|
+
## Retained v0.1 architecture constraints
|
|
1080
|
+
|
|
1081
|
+
v0.1 planning preserved these approved boundaries without treating module
|
|
1082
|
+
names from the historical run as mandatory:
|
|
1083
|
+
|
|
1084
|
+
```text
|
|
1085
|
+
thin command-line boundary
|
|
1086
|
+
↓
|
|
1087
|
+
reusable observation engine/application layer
|
|
1088
|
+
↓
|
|
1089
|
+
browser automation boundary
|
|
1090
|
+
↓
|
|
1091
|
+
observer-owned runtime evidence
|
|
1092
|
+
|
|
1093
|
+
observer-owned domain/schema
|
|
1094
|
+
↓
|
|
1095
|
+
artifact ownership boundary
|
|
1096
|
+
|
|
1097
|
+
deterministic fixture/test boundary
|
|
1098
|
+
↓
|
|
1099
|
+
browser-level validation
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
Use one browser engine implementation, keep browser logic out of presentation,
|
|
1103
|
+
avoid speculative plugin/multi-browser abstractions, and keep observed
|
|
1104
|
+
applications external. Versions before v0.6 did not add runtime coupling to
|
|
1105
|
+
sibling ecosystem projects. v0.6 adds only explicit bounded context and
|
|
1106
|
+
correlation/export contracts within this repository, preserving independent
|
|
1107
|
+
ownership; orchestrator-consumption and lab-compatibility work are separate
|
|
1108
|
+
sibling-repository deliverables, not part of this repository's architecture.
|
|
1109
|
+
|
|
1110
|
+
The text/config-driven coding-agent workflow and the non-UI external-reference
|
|
1111
|
+
evidence foundation are operational as of v0.7. The viewer and annotation
|
|
1112
|
+
layers must consume the same canonical observation, relationship, comparison,
|
|
1113
|
+
contract, change-scope, reference, correlation, and context boundaries rather
|
|
1114
|
+
than creating parallel engines. The concrete implementation plan and module
|
|
1115
|
+
layout for each future version must be designed only after that version's
|
|
1116
|
+
planning workflow inspects the current repositories.
|
|
1117
|
+
|
|
1118
|
+
v0.7 Prompt 1 implements only the bottom of that external-reference stack: a
|
|
1119
|
+
new, standalone `ExternalReferenceArtifact` evidence root
|
|
1120
|
+
(`src/domain/externalReference.ts`, `externalReferenceImage.ts`,
|
|
1121
|
+
`externalReferenceIdentity.ts`, `src/artifacts/externalReferenceArtifact{Writer,Reader}.ts`,
|
|
1122
|
+
`src/application/externalReferencePersistenceService.ts`) with its own
|
|
1123
|
+
identity, provenance, bounded image metadata, and a two-state
|
|
1124
|
+
(`imported`/`approved`) lifecycle - see `docs/CONTRACTS.md` "v0.7 Prompt 1
|
|
1125
|
+
external-reference artifact contract" for the exact shape. It follows the
|
|
1126
|
+
same identity/persistence/diagnostics/export conventions as every existing
|
|
1127
|
+
artifact family (deterministic canonicalize-then-sha256 request identity,
|
|
1128
|
+
nonce-based fresh instance identity, atomic temp-dir-then-rename persistence,
|
|
1129
|
+
the shared `DIAGNOSTIC_CODES` vocabulary) without reusing or duplicating the
|
|
1130
|
+
observation, comparison, or contract engines themselves - an external
|
|
1131
|
+
reference is desired-design evidence, never an `ObservationArtifact`, an
|
|
1132
|
+
approved baseline, or a runtime target.
|
|
1133
|
+
|
|
1134
|
+
v0.7 Prompt 2 adds explicit reference regions and reusable reference-region
|
|
1135
|
+
relationships on top of that foundation (`domain/externalReferenceRegions.ts`,
|
|
1136
|
+
`externalReferenceRegionRelationships.ts`) - see `docs/CONTRACTS.md` "v0.7
|
|
1137
|
+
Prompt 2 explicit reference regions and relationships" for the exact shape.
|
|
1138
|
+
The relationship-derivation predicates are reused verbatim (now exported
|
|
1139
|
+
additively) from `domain/relationships.ts` rather than reimplemented, so
|
|
1140
|
+
reference-region geometry and runtime-target geometry can never diverge on
|
|
1141
|
+
the same underlying formula; only the geometry-only relationship families
|
|
1142
|
+
apply, since a static image exposes no DOM, scroll, or viewport evidence.
|
|
1143
|
+
v0.7 Prompt 3 adds selected design requirements, tolerance semantics, and
|
|
1144
|
+
reference-evidence adequacy on top of that region model
|
|
1145
|
+
(`domain/externalReferenceRequirements.ts`,
|
|
1146
|
+
`externalReferenceRequirementIdentity.ts`) - see `docs/CONTRACTS.md` "v0.7
|
|
1147
|
+
Prompt 3 selected design requirements, tolerance semantics, and
|
|
1148
|
+
reference-evidence adequacy" for the exact shape. Requirement categories are
|
|
1149
|
+
the exact v0.5 `AuthoredChangeScopeCategory` vocabulary, imported directly
|
|
1150
|
+
rather than reinvented, since that type carries no runtime-only coupling of
|
|
1151
|
+
its own; tolerance is a genuinely new, reference-owned type (never a reuse
|
|
1152
|
+
of `frontendContracts.ts`'s runtime/CSS-pixel-implicit `ContractTolerance`);
|
|
1153
|
+
and reference-evidence adequacy is a small, independently-owned vocabulary
|
|
1154
|
+
distinct from `boundedAgentContext.ts`'s runtime/static-correlation
|
|
1155
|
+
`Adequacy`. A region property or derived relationship is never promoted to
|
|
1156
|
+
an executable requirement automatically - only explicit user/configuration
|
|
1157
|
+
selection does that.
|
|
1158
|
+
|
|
1159
|
+
v0.7 Prompt 4 adds explicit reference applicability
|
|
1160
|
+
(`domain/externalReferenceApplicability.ts`) and observation-side explicit
|
|
1161
|
+
state identity (`domain/explicitState.ts`, shared by both artifact
|
|
1162
|
+
families), plus one new pure domain module,
|
|
1163
|
+
`domain/externalReferenceCompatibility.ts`, that evaluates whether a
|
|
1164
|
+
candidate `ObservationArtifact` describes the same frontend state as a
|
|
1165
|
+
given `ExternalReferenceArtifact` - see `docs/CONTRACTS.md` "v0.7 Prompt 4
|
|
1166
|
+
reference applicability and candidate-state compatibility" for the exact
|
|
1167
|
+
shape. This is page/state-level only, never geometry or fidelity, and
|
|
1168
|
+
remains a wholly separate concern from Prompt 3's reference-evidence
|
|
1169
|
+
adequacy - the two can independently disagree (an adequate reference can be
|
|
1170
|
+
incomparable against a given candidate, and vice versa). Rather than
|
|
1171
|
+
inventing a second comparability engine, Prompt 4 extracts one new exported
|
|
1172
|
+
pure helper from v0.4's own `domain/comparisonEngine.ts`
|
|
1173
|
+
(`assessOptionalComparabilityDimension`) and reuses it from both v0.4's
|
|
1174
|
+
`evaluateComparability` (Observation-vs-Observation) and the new
|
|
1175
|
+
`evaluateReferenceCandidateCompatibility` (Reference-vs-Observation) - the
|
|
1176
|
+
one additive behavior change to v0.4 itself is that `evaluateComparability`
|
|
1177
|
+
now assesses (rather than always reporting unassessed) theme/authenticated-
|
|
1178
|
+
state/application-state whenever both observations declare
|
|
1179
|
+
`requestConfig.explicitState`, while every historical/legacy observation
|
|
1180
|
+
pair retains the exact prior unassessed-only behavior. No new persisted
|
|
1181
|
+
artifact kind is introduced for the compatibility result; it is a pure,
|
|
1182
|
+
on-demand function of two already-persisted artifacts.
|
|
1183
|
+
|
|
1184
|
+
v0.7 Prompt 5 adds explicit reference-region <-> runtime-target binding
|
|
1185
|
+
(`domain/externalReferenceRuntimeBinding.ts`) - see `docs/CONTRACTS.md`
|
|
1186
|
+
"v0.7 Prompt 5 explicit reference-region <-> runtime-target binding" for
|
|
1187
|
+
the exact shape. It answers only "which stable v0.2 runtime target does
|
|
1188
|
+
this candidate observation resolve for each explicitly declared reference
|
|
1189
|
+
region", strictly downstream of Prompt 4's compatibility gate (reused
|
|
1190
|
+
verbatim, never duplicated) and strictly upstream of v0.6's own
|
|
1191
|
+
runtime/static correlation - the two identity domains (a Prompt 2
|
|
1192
|
+
`ReferenceRegion.id` and a v0.2 `NamedTarget.name`) never collapse into
|
|
1193
|
+
each other, and this stage stops at the runtime target, never reaching
|
|
1194
|
+
source ownership. Following v0.6's uncertainty discipline
|
|
1195
|
+
(`domain/boundedAgentContextCorrelation.ts`), binding never guesses through
|
|
1196
|
+
ambiguity - an ambiguously or unavailably resolved v0.2 target is reported
|
|
1197
|
+
as such, never silently treated as bound - though the actual per-status
|
|
1198
|
+
mapping (`bound`/`ambiguous`/`unavailable`) is binding's own, independently
|
|
1199
|
+
owned vocabulary, not a reuse of v0.6's `correlated`/`ambiguous`/
|
|
1200
|
+
`unavailable` correlation-status semantics (a different evidence boundary:
|
|
1201
|
+
correlation ranks *static candidates* for one runtime target, whereas
|
|
1202
|
+
binding resolves *one runtime target's own existence* for one declared
|
|
1203
|
+
correspondence). No second target resolver, no browser execution, and no
|
|
1204
|
+
new persisted artifact family were introduced; neither
|
|
1205
|
+
`ExternalReferenceArtifact` nor `ObservationArtifact` is mutated to carry a
|
|
1206
|
+
binding result, since a reference may later be evaluated against several
|
|
1207
|
+
candidates and an observation against several references.
|
|
1208
|
+
|
|
1209
|
+
v0.7 Prompt 6 adds structured reference-vs-candidate fidelity evaluation
|
|
1210
|
+
(`domain/externalReferenceFidelity.ts`, `application/referenceFidelityEvaluationService.ts`,
|
|
1211
|
+
and the `evaluate-reference-fidelity` CLI command) - the first point in this
|
|
1212
|
+
stack where a reference's authored expectation is compared against live
|
|
1213
|
+
candidate evidence. See `docs/CONTRACTS.md` "v0.7 Prompt 6 structured
|
|
1214
|
+
reference-vs-candidate fidelity evaluation" for the exact shape. It is
|
|
1215
|
+
downstream of every prior v0.7 prompt and reuses each verbatim: Prompt 3's
|
|
1216
|
+
`deriveReferenceRequirementAdequacy`/`deriveReferenceRequirementExpectation`/
|
|
1217
|
+
`deriveReferenceRequirementMeasurement` (never redefined), Prompt 4's
|
|
1218
|
+
`evaluateReferenceCandidateCompatibility` (a hard gate, never duplicated),
|
|
1219
|
+
and Prompt 5's `evaluateReferenceRuntimeBindings` (the sole source of
|
|
1220
|
+
runtime-target identity - no automatic binding, no second target resolver).
|
|
1221
|
+
It also reuses v0.4's `deriveLayoutRelationships` for runtime relationship
|
|
1222
|
+
evidence, scoped to the exact requested relationship family (the same
|
|
1223
|
+
Prompt 3 bug-fix precedent). The one genuinely new problem this prompt
|
|
1224
|
+
solves is the reference-image-pixel <-> CSS-pixel coordinate mapping: a
|
|
1225
|
+
single explicit, deterministic full-frame scale derived from
|
|
1226
|
+
`reference.applicability.viewport` and the reference image's own
|
|
1227
|
+
dimensions, with a tiny independent aspect-ratio-coherence check (never a
|
|
1228
|
+
design tolerance) gating whether that mapping exists at all. No new
|
|
1229
|
+
persisted artifact family, no browser execution, and no source-ownership
|
|
1230
|
+
attribution - this is reference fidelity only, a separate concern from any
|
|
1231
|
+
later v0.5 baseline/per-change contract result or v0.7 overall verdict.
|
|
1232
|
+
|
|
1233
|
+
v0.7 Prompt 7 adds bounded reference-fidelity projection into the existing
|
|
1234
|
+
v0.6 bounded-agent-context architecture (`domain/referenceFidelityProjection.ts`,
|
|
1235
|
+
plus additive extensions to `domain/boundedAgentContext.ts`,
|
|
1236
|
+
`domain/boundedAgentContextIdentity.ts`, and
|
|
1237
|
+
`domain/boundedAgentContextProjection.ts`) - see `docs/CONTRACTS.md` "v0.7
|
|
1238
|
+
Prompt 7 bounded reference-fidelity projection and v0.6 bounded-agent-
|
|
1239
|
+
context integration" for the exact shape. `projectBoundedAgentContext`
|
|
1240
|
+
itself, not a new parallel context system, gains one new optional input (an
|
|
1241
|
+
already-computed Prompt 6 fidelity evaluation): fidelity-relevant runtime
|
|
1242
|
+
targets fold into the exact same required/permitted-target-allocation,
|
|
1243
|
+
evidence-tiering, omission/truncation, and adequacy machinery v0.5 contract
|
|
1244
|
+
clauses already compete in, and a new `fidelity?` field on
|
|
1245
|
+
`BoundedAgentContextArtifact` (mirroring `correlations?`'s own additive,
|
|
1246
|
+
non-version-bumping precedent from v0.6 Batch 3) carries a bounded,
|
|
1247
|
+
priority-ordered selection of Prompt 6's non-passing requirement results
|
|
1248
|
+
plus passing protected/preserved context. No second bounded-context
|
|
1249
|
+
architecture, no recomputation of Prompt 2-6/v0.4/v0.5 logic, and no change
|
|
1250
|
+
to v0.6's own runtime/static correlation (`deriveRuntimeStaticCorrelations`/
|
|
1251
|
+
`attachRuntimeStaticCorrelations` are untouched and reused exactly as
|
|
1252
|
+
before) - a caller joins fidelity, target, and correlation evidence by the
|
|
1253
|
+
one stable v0.2 runtime target id all three already share. Every new field
|
|
1254
|
+
is optional and additive; a pre-Prompt-7 caller supplying no fidelity
|
|
1255
|
+
evidence receives byte-identical output, including logical identity.
|
|
1256
|
+
|
|
1257
|
+
v0.7 Prompt 8 adds the first complete, controlled end-to-end external-
|
|
1258
|
+
reference correction workflow (`domain/referenceCorrectionWorkflow.ts`,
|
|
1259
|
+
`domain/referenceCorrectionIdentity.ts`) - see `docs/CONTRACTS.md` "v0.7
|
|
1260
|
+
Prompt 8 controlled end-to-end external-reference coding-agent correction
|
|
1261
|
+
workflow" for the exact shape. This is a narrowly-scoped coordinator, not a
|
|
1262
|
+
second workflow engine: it exposes exactly two pure operations -
|
|
1263
|
+
`prepareReferenceCorrection` (pre-change evidence -> a bounded coding-agent
|
|
1264
|
+
handoff, built from Prompt 1/3/4/5/6/7's existing engines) and
|
|
1265
|
+
`reviewReferenceCorrectionAttempt` (a fresh post-edit candidate -> one
|
|
1266
|
+
composed overall result, built from v0.4's `compareObservations`, v0.7
|
|
1267
|
+
Prompt 6's `evaluateReferenceCandidateFidelity`, and v0.5's
|
|
1268
|
+
`evaluateFrontendContract`) - with an explicit, un-automatable seam between
|
|
1269
|
+
them where an external implementation actor edits target source. Overall
|
|
1270
|
+
`'pass'` requires both reference fidelity `'pass'` and v0.5 contract
|
|
1271
|
+
evaluation `'PASS'` - matching the selected design reference is necessary
|
|
1272
|
+
but never sufficient, so a candidate that visually satisfies the reference
|
|
1273
|
+
while regressing an active protected or preserved contract clause still
|
|
1274
|
+
resolves to overall `'fail'`. Review identity is a deterministic hash of
|
|
1275
|
+
`{referenceRequestId, baselineObservationId, baselineContractId,
|
|
1276
|
+
baselineContractClauses, changeContractId, changeContractClauses,
|
|
1277
|
+
bindingDeclarations}`; attempt identity is a deterministic hash of
|
|
1278
|
+
`{reviewRequestId, candidateObservationId}`. `reviewReferenceCorrectionAttempt`
|
|
1279
|
+
rejects any call whose supplied `reviewRequestId` does not match what its own
|
|
1280
|
+
baseline/contract/reference/binding inputs recompute - the mechanism that
|
|
1281
|
+
makes "every attempt evaluates against the same approved baseline" an
|
|
1282
|
+
enforced invariant, not just a documented one. No new persisted artifact
|
|
1283
|
+
family, no CLI surface, and - most importantly - no code path anywhere in
|
|
1284
|
+
this module (or anything it calls) that opens, parses, or writes a target
|
|
1285
|
+
source file: real candidate capture remains the caller's own responsibility
|
|
1286
|
+
through the existing, unmodified real-Chromium observation pipeline.
|