@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
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta name="theme-color" content="#0f172a" />
|
|
7
|
+
<title>my-frontend-observer Viewer</title>
|
|
8
|
+
<link rel="icon" type="image/png" href="/icons/icon-192.png" />
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-D98S1_2d.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CN_yb9Uf.css">
|
|
11
|
+
<link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"my-frontend-observer Viewer","short_name":"Observer Viewer","description":"Local-first interactive viewer for my-frontend-observer runtime evidence.","start_url":"/","display":"standalone","background_color":"#0f172a","theme_color":"#0f172a","lang":"en","scope":"/","icons":[{"src":"icons/icon-192.png","sizes":"192x192","type":"image/png"},{"src":"icons/icon-512.png","sizes":"512x512","type":"image/png"}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('/sw.js', { scope: '/' })})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,r)=>{const o=e||("document"in self?document.currentScript.src:"")||location.href;if(i[o])return;let c={};const t=e=>n(e,o),d={module:{uri:o},exports:c,require:t};i[o]=Promise.all(s.map(e=>d[e]||t(e))).then(e=>(r(...e),c))}}define(["./workbox-9c191d2f"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"registerSW.js",revision:"1872c500de691dce40960bb85481de07"},{url:"manifest.webmanifest",revision:"230563056861fe6705b913b3df23b258"},{url:"index.html",revision:"5cb88d42b2c80bd6eb33a9928a9463d9"},{url:"icons/icon-512.png",revision:"e92e70cceb9b8d7f52ea0cfe9099e7de"},{url:"icons/icon-192.png",revision:"175e5f2a92d509b08ccf2a917bb400f6"},{url:"assets/index-D98S1_2d.js",revision:null},{url:"assets/index-CN_yb9Uf.css",revision:null},{url:"icons/icon-192.png",revision:"175e5f2a92d509b08ccf2a917bb400f6"},{url:"icons/icon-512.png",revision:"e92e70cceb9b8d7f52ea0cfe9099e7de"},{url:"manifest.webmanifest",revision:"230563056861fe6705b913b3df23b258"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"),{denylist:[/^\/api\//]}))});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
define(["exports"],function(t){"use strict";try{self["workbox:core:7.4.0"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:7.4.0"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class i{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class r extends i{constructor(t,e,s){super(({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)},e,s)}}class o{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map(e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})}));t.waitUntil(s),t.ports&&t.ports[0]&&s.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:i,route:r}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let o=r&&r.handler;const c=t.method;if(!o&&this.i.has(c)&&(o=this.i.get(c)),!o)return;let a;try{a=o.handle({url:s,request:t,event:e,params:i})}catch(t){a=Promise.reject(t)}const h=r&&r.catchHandler;return a instanceof Promise&&(this.o||h)&&(a=a.catch(async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:i})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n})),a}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const i=this.t.get(s.method)||[];for(const r of i){let i;const o=r.match({url:t,sameOrigin:e,request:s,event:n});if(o)return i=o,(Array.isArray(i)&&0===i.length||o.constructor===Object&&0===Object.keys(o).length||"boolean"==typeof o)&&(i=void 0),{route:r,params:i}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let c;const a=()=>(c||(c=new o,c.addFetchListener(),c.addCacheListener()),c);function h(t,e,n){let o;if("string"==typeof t){const s=new URL(t,location.href);o=new i(({url:t})=>t.href===s.href,e,n)}else if(t instanceof RegExp)o=new r(t,e,n);else if("function"==typeof t)o=new i(t,e,n);else{if(!(t instanceof i))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});o=t}return a().registerRoute(o),o}const u={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},l=t=>[u.prefix,t,u.suffix].filter(t=>t&&t.length>0).join("-"),f=t=>t||l(u.precache),w=t=>t||l(u.runtime);function d(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:7.4.0"]&&_()}catch(t){}function p(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const i=new URL(n,location.href),r=new URL(n,location.href);return i.searchParams.set("__WB_REVISION__",e),{cacheKey:i.href,url:r.href}}class y{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class g{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.h.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.h=t}}let R;async function m(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const i=t.clone(),r={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},o=function(){if(void 0===R){const t=new Response("");if("body"in t)try{new Response(t.body),R=!0}catch(t){R=!1}R=!1}return R}()?i.body:await i.blob();return new Response(o,r)}function v(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class q{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}const U=new Set;try{self["workbox:strategies:7.4.0"]&&_()}catch(t){}function L(t){return"string"==typeof t?new Request(t):t}class b{constructor(t,e){this.u={},Object.assign(this,e),this.event=e.event,this.l=t,this.p=new q,this.R=[],this.m=[...t.plugins],this.v=new Map;for(const t of this.m)this.v.set(t,{});this.event.waitUntil(this.p.promise)}async fetch(t){const{event:e}=this;let n=L(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const i=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const r=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.l.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:r,response:t});return t}catch(t){throw i&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:i.clone(),request:r.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=L(t);let s;const{cacheName:n,matchOptions:i}=this.l,r=await this.getCacheKey(e,"read"),o=Object.assign(Object.assign({},i),{cacheName:n});s=await caches.match(r,o);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:i,cachedResponse:s,request:r,event:this.event})||void 0;return s}async cachePut(t,e){const n=L(t);var i;await(i=0,new Promise(t=>setTimeout(t,i)));const r=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(o=r.url,new URL(String(o),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var o;const c=await this.q(e);if(!c)return!1;const{cacheName:a,matchOptions:h}=this.l,u=await self.caches.open(a),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const i=v(e.url,s);if(e.url===i)return t.match(e,n);const r=Object.assign(Object.assign({},n),{ignoreSearch:!0}),o=await t.keys(e,r);for(const e of o)if(i===v(e.url,s))return t.match(e,n)}(u,r.clone(),["__WB_REVISION__"],h):null;try{await u.put(r,l?c.clone():c)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of U)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:a,oldResponse:f,newResponse:c.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.u[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=L(await t({mode:e,request:n,event:this.event,params:this.params}));this.u[s]=n}return this.u[s]}hasCallback(t){for(const e of this.l.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.l.plugins)if("function"==typeof e[t]){const s=this.v.get(e),n=n=>{const i=Object.assign(Object.assign({},n),{state:s});return e[t](i)};yield n}}waitUntil(t){return this.R.push(t),t}async doneWaiting(){for(;this.R.length;){const t=this.R.splice(0),e=(await Promise.allSettled(t)).find(t=>"rejected"===t.status);if(e)throw e.reason}}destroy(){this.p.resolve(null)}async q(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class C{constructor(t={}){this.cacheName=w(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,i=new b(this,{event:e,request:s,params:n}),r=this.U(i,s,e);return[r,this.L(r,i,s,e)]}async U(t,e,n){let i;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(i=await this._(e,t),!i||"error"===i.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const r of t.iterateCallbacks("handlerDidError"))if(i=await r({error:s,event:n,request:e}),i)break;if(!i)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))i=await s({event:n,request:e,response:i});return i}async L(t,e,s,n){let i,r;try{i=await t}catch(r){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:i}),await e.doneWaiting()}catch(t){t instanceof Error&&(r=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:i,error:r}),e.destroy(),r)throw r}}class E extends C{constructor(t={}){t.cacheName=f(t.cacheName),super(t),this.C=!1!==t.fallbackToNetwork,this.plugins.push(E.copyRedirectedCacheableResponsesPlugin)}async _(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.O(t,e):await this.N(t,e))}async N(t,e){let n;const i=e.params||{};if(!this.C)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=i.integrity,r=t.integrity,o=!r||r===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?r||s:void 0})),s&&o&&"no-cors"!==t.mode&&(this.P(),await e.cachePut(t,n.clone()))}return n}async O(t,e){this.P();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}P(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==E.copyRedirectedCacheableResponsesPlugin&&(n===E.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(E.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}E.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},E.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await m(t):t};class O{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.j=new Map,this.k=new Map,this.K=new Map,this.l=new E({cacheName:f(t),plugins:[...e,new g({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.l}precache(t){this.addToCacheList(t),this.T||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.T=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:i}=p(n),r="string"!=typeof n&&n.revision?"reload":"default";if(this.j.has(i)&&this.j.get(i)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.j.get(i),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.K.has(t)&&this.K.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:i});this.K.set(t,n.integrity)}if(this.j.set(i,t),this.k.set(i,r),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return d(t,async()=>{const e=new y;this.strategy.plugins.push(e);for(const[e,s]of this.j){const n=this.K.get(s),i=this.k.get(e),r=new Request(e,{integrity:n,cache:i,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:r,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}})}activate(t){return d(t,async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.j.values()),n=[];for(const i of e)s.has(i.url)||(await t.delete(i),n.push(i.url));return{deletedURLs:n}})}getURLsToCacheKeys(){return this.j}getCachedURLs(){return[...this.j.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.j.get(e.href)}getIntegrityForCacheKey(t){return this.K.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}let x;const N=()=>(x||(x=new O),x);class P extends i{constructor(t,e){super(({request:s})=>{const n=t.getURLsToCacheKeys();for(const i of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:i}={}){const r=new URL(t,location.href);r.hash="",yield r.href;const o=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some(t=>t.test(s))&&t.searchParams.delete(s);return t}(r,e);if(yield o.href,s&&o.pathname.endsWith("/")){const t=new URL(o.href);t.pathname+=s,yield t.href}if(n){const t=new URL(o.href);t.pathname+=".html",yield t.href}if(i){const t=i({url:r});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(i);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}},t.strategy)}}t.NavigationRoute=class extends i{constructor(t,{allowlist:e=[/./],denylist:s=[]}={}){super(t=>this.W(t),t),this.M=e,this.S=s}W({url:t,request:e}){if(e&&"navigate"!==e.mode)return!1;const s=t.pathname+t.search;for(const t of this.S)if(t.test(s))return!1;return!!this.M.some(t=>t.test(s))}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const e=f();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter(s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t);return await Promise.all(s.map(t=>self.caches.delete(t))),s})(e).then(t=>{}))})},t.clientsClaim=function(){self.addEventListener("activate",()=>self.clients.claim())},t.createHandlerBoundToURL=function(t){return N().createHandlerBoundToURL(t)},t.precacheAndRoute=function(t,e){!function(t){N().precache(t)}(t),function(t){const e=N();h(new P(e,t))}(e)},t.registerRoute=h});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { BoundedAgentContextArtifact } from '../domain/boundedAgentContext.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reuses the existing Batch 2 bounded manifest-read size limit
|
|
4
|
+
* (`MAX_MANIFEST_CANDIDATE_BYTES`, 2,000,000 bytes) rather than inventing a
|
|
5
|
+
* second bound: a `BoundedAgentContextArtifact` is, by its own frozen
|
|
6
|
+
* contract, already far smaller than that in any realistic case (at most 25
|
|
7
|
+
* targets, 25 correlation records with at most 5 candidates each, 15
|
|
8
|
+
* fidelity mismatches, etc. - see `src/domain/boundedAgentContext.ts`'s own
|
|
9
|
+
* `MAX_*` constants) - the same "generous headroom, never an arbitrarily
|
|
10
|
+
* large read" rationale applies unchanged.
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_CONTEXT_FILE_BYTES = 2000000;
|
|
13
|
+
/**
|
|
14
|
+
* Session state for the bounded-agent-context the viewer was explicitly
|
|
15
|
+
* started with. `'none'` when no `--context-file` was supplied at all -
|
|
16
|
+
* every Batch 1-6 feature remains fully available in this state, and the
|
|
17
|
+
* viewer never fabricates a context nor infers one from currently-selected
|
|
18
|
+
* evidence. `'unsupported-version'` is a distinct, honest state for a
|
|
19
|
+
* recognized-kind context whose `schemaVersion` is not the currently
|
|
20
|
+
* supported one - never coerced into (or displayed as) the current shape.
|
|
21
|
+
*/
|
|
22
|
+
export type ContextSessionState = {
|
|
23
|
+
status: 'none';
|
|
24
|
+
} | {
|
|
25
|
+
status: 'unsupported-version';
|
|
26
|
+
foundSchemaVersion: string;
|
|
27
|
+
} | {
|
|
28
|
+
status: 'valid';
|
|
29
|
+
artifact: BoundedAgentContextArtifact;
|
|
30
|
+
};
|
|
31
|
+
export type ClassifyContextFileResult = {
|
|
32
|
+
ok: true;
|
|
33
|
+
state: ContextSessionState;
|
|
34
|
+
} | {
|
|
35
|
+
ok: false;
|
|
36
|
+
error: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Classifies one already-parsed JSON value as an explicit `--context-file`
|
|
40
|
+
* root (task §12: the file *is* one `BoundedAgentContextArtifact` value
|
|
41
|
+
* directly - no wrapper object). Fails closed (a startup error, per task
|
|
42
|
+
* §17) on a non-object root, a wrong `artifactKind`, or a current-schema
|
|
43
|
+
* artifact that is structurally invalid. A recognized kind with a
|
|
44
|
+
* different, non-current `schemaVersion` is reported as the honest
|
|
45
|
+
* `'unsupported-version'` state rather than a failure (task §16) - the
|
|
46
|
+
* caller (`runViewCommand`) still starts the viewer in that case.
|
|
47
|
+
*/
|
|
48
|
+
export declare function classifyContextFileContent(parsed: unknown): ClassifyContextFileResult;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.8 Batch 7: the narrowest possible viewer-session context-input
|
|
3
|
+
* boundary. `BoundedAgentContextArtifact` remains programmatic-only in the
|
|
4
|
+
* current product workflow (no filesystem writer/reader contract exists for
|
|
5
|
+
* it as an Observer evidence-root artifact family - see
|
|
6
|
+
* `src/viewerServer/evidence/classify.ts`'s own comment on the "known but
|
|
7
|
+
* unreadered" kind) - this module does not change that. It only inspects
|
|
8
|
+
* and validates an explicit, caller-supplied JSON value (the parsed
|
|
9
|
+
* contents of an operator-supplied `--context-file`) against the existing
|
|
10
|
+
* canonical `isValidBoundedAgentContextArtifact` - never a second validator,
|
|
11
|
+
* never a normalization/rewrite of the supplied value, never a call to
|
|
12
|
+
* `projectBoundedAgentContext` or any correlation-derivation function.
|
|
13
|
+
*
|
|
14
|
+
* Byte-reading and JSON parsing remain owned by `src/cli.ts` (mirroring the
|
|
15
|
+
* existing `loadBindingsFile` boundary exactly); this module receives only
|
|
16
|
+
* the already-parsed JSON value.
|
|
17
|
+
*/
|
|
18
|
+
import { BOUNDED_AGENT_CONTEXT_ARTIFACT_KIND, BOUNDED_AGENT_CONTEXT_SCHEMA_VERSION, isValidBoundedAgentContextArtifact } from '../domain/boundedAgentContext.js';
|
|
19
|
+
/**
|
|
20
|
+
* Reuses the existing Batch 2 bounded manifest-read size limit
|
|
21
|
+
* (`MAX_MANIFEST_CANDIDATE_BYTES`, 2,000,000 bytes) rather than inventing a
|
|
22
|
+
* second bound: a `BoundedAgentContextArtifact` is, by its own frozen
|
|
23
|
+
* contract, already far smaller than that in any realistic case (at most 25
|
|
24
|
+
* targets, 25 correlation records with at most 5 candidates each, 15
|
|
25
|
+
* fidelity mismatches, etc. - see `src/domain/boundedAgentContext.ts`'s own
|
|
26
|
+
* `MAX_*` constants) - the same "generous headroom, never an arbitrarily
|
|
27
|
+
* large read" rationale applies unchanged.
|
|
28
|
+
*/
|
|
29
|
+
export const MAX_CONTEXT_FILE_BYTES = 2_000_000;
|
|
30
|
+
function isPlainObject(value) {
|
|
31
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Classifies one already-parsed JSON value as an explicit `--context-file`
|
|
35
|
+
* root (task §12: the file *is* one `BoundedAgentContextArtifact` value
|
|
36
|
+
* directly - no wrapper object). Fails closed (a startup error, per task
|
|
37
|
+
* §17) on a non-object root, a wrong `artifactKind`, or a current-schema
|
|
38
|
+
* artifact that is structurally invalid. A recognized kind with a
|
|
39
|
+
* different, non-current `schemaVersion` is reported as the honest
|
|
40
|
+
* `'unsupported-version'` state rather than a failure (task §16) - the
|
|
41
|
+
* caller (`runViewCommand`) still starts the viewer in that case.
|
|
42
|
+
*/
|
|
43
|
+
export function classifyContextFileContent(parsed) {
|
|
44
|
+
if (!isPlainObject(parsed)) {
|
|
45
|
+
return { ok: false, error: '--context-file root must be a JSON object representing one BoundedAgentContextArtifact value directly (no wrapper object)' };
|
|
46
|
+
}
|
|
47
|
+
if (parsed.artifactKind !== BOUNDED_AGENT_CONTEXT_ARTIFACT_KIND) {
|
|
48
|
+
return { ok: false, error: `--context-file artifactKind must be "${BOUNDED_AGENT_CONTEXT_ARTIFACT_KIND}"; found ${JSON.stringify(parsed.artifactKind)}` };
|
|
49
|
+
}
|
|
50
|
+
if (parsed.schemaVersion !== BOUNDED_AGENT_CONTEXT_SCHEMA_VERSION) {
|
|
51
|
+
const foundSchemaVersion = typeof parsed.schemaVersion === 'string' ? parsed.schemaVersion : 'unknown';
|
|
52
|
+
return { ok: true, state: { status: 'unsupported-version', foundSchemaVersion } };
|
|
53
|
+
}
|
|
54
|
+
const validation = isValidBoundedAgentContextArtifact(parsed);
|
|
55
|
+
if (!validation.valid) {
|
|
56
|
+
return { ok: false, error: `--context-file is not a structurally valid current (schemaVersion ${BOUNDED_AGENT_CONTEXT_SCHEMA_VERSION}) bounded-agent-context artifact: ${validation.reason}` };
|
|
57
|
+
}
|
|
58
|
+
return { ok: true, state: { status: 'valid', artifact: parsed } };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/viewerServer/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,mCAAmC,EAAE,oCAAoC,EAAE,kCAAkC,EAAE,MAAM,kCAAkC,CAAC;AAGjK;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAkBhD,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACxD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2HAA2H,EAAE,CAAC;IAC3J,CAAC;IACD,IAAI,MAAM,CAAC,YAAY,KAAK,mCAAmC,EAAE,CAAC;QAChE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wCAAwC,mCAAmC,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;IAC5J,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,KAAK,oCAAoC,EAAE,CAAC;QAClE,MAAM,kBAAkB,GAAG,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;QACvG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,EAAE,CAAC;IACpF,CAAC;IACD,MAAM,UAAU,GAAG,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,qEAAqE,oCAAoC,qCAAqC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;IACjM,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAgD,EAAE,EAAE,CAAC;AAC9G,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ObservationArtifact } from '../../domain/schema.js';
|
|
2
|
+
import type { ComparisonArtifact } from '../../domain/comparison.js';
|
|
3
|
+
import type { PersistentBaselineContract, PerChangeContract } from '../../domain/frontendContracts.js';
|
|
4
|
+
import type { FrontendContractEvaluationArtifact } from '../../domain/frontendContractEvaluationArtifact.js';
|
|
5
|
+
import type { ExternalReferenceArtifact } from '../../domain/externalReference.js';
|
|
6
|
+
export type ArtifactFamily = 'observation' | 'comparison' | 'baseline-contract' | 'change-contract' | 'contract-evaluation' | 'external-reference-imported' | 'external-reference-approved';
|
|
7
|
+
/**
|
|
8
|
+
* Honest, independent viewer-loading/support state - deliberately distinct
|
|
9
|
+
* from any artifact's own `completion`/evidence-state semantics (see
|
|
10
|
+
* ClassifiedRecord.artifact for the latter, when the kind carries one).
|
|
11
|
+
*/
|
|
12
|
+
export type ViewerSupportState = 'supported' | 'unsupported-version' | 'invalid-structure' | 'unrecognized-kind' | 'malformed-json' | 'unreadable';
|
|
13
|
+
type FamilyArtifact = {
|
|
14
|
+
observation: ObservationArtifact;
|
|
15
|
+
comparison: ComparisonArtifact;
|
|
16
|
+
'baseline-contract': PersistentBaselineContract;
|
|
17
|
+
'change-contract': PerChangeContract;
|
|
18
|
+
'contract-evaluation': FrontendContractEvaluationArtifact;
|
|
19
|
+
'external-reference-imported': ExternalReferenceArtifact;
|
|
20
|
+
'external-reference-approved': ExternalReferenceArtifact;
|
|
21
|
+
};
|
|
22
|
+
/** Per-family discriminated union (not a generically-indexed field) so switching on `family` correctly narrows `artifact`'s type. */
|
|
23
|
+
type SupportedRecord = {
|
|
24
|
+
[K in ArtifactFamily]: {
|
|
25
|
+
supportState: 'supported';
|
|
26
|
+
family: K;
|
|
27
|
+
artifact: FamilyArtifact[K];
|
|
28
|
+
};
|
|
29
|
+
}[ArtifactFamily];
|
|
30
|
+
export type ClassifiedRecord = SupportedRecord | {
|
|
31
|
+
supportState: 'unsupported-version';
|
|
32
|
+
family: ArtifactFamily;
|
|
33
|
+
foundSchemaVersion: string;
|
|
34
|
+
supportedSchemaVersion: string;
|
|
35
|
+
} | {
|
|
36
|
+
supportState: 'invalid-structure';
|
|
37
|
+
family: ArtifactFamily | undefined;
|
|
38
|
+
reason: string;
|
|
39
|
+
} | {
|
|
40
|
+
supportState: 'unrecognized-kind';
|
|
41
|
+
foundArtifactKind: string | undefined;
|
|
42
|
+
} | {
|
|
43
|
+
supportState: 'malformed-json';
|
|
44
|
+
reason: string;
|
|
45
|
+
} | {
|
|
46
|
+
supportState: 'unreadable';
|
|
47
|
+
reason: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Classification is not validation (frozen plan §10): this function reads
|
|
51
|
+
* bounded manifest bytes, parses JSON, and peeks only `artifactKind`/
|
|
52
|
+
* `schemaVersion` to decide *which* existing canonical reader to try - the
|
|
53
|
+
* canonical reader's own structural validator remains the sole authority on
|
|
54
|
+
* whether a candidate is actually a valid instance of that family. This
|
|
55
|
+
* function never accepts a candidate that its dispatched reader rejects, and
|
|
56
|
+
* never invents a result the reader did not itself produce.
|
|
57
|
+
*/
|
|
58
|
+
export declare function classifyManifest(manifestPath: string): Promise<ClassifiedRecord>;
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { ARTIFACT_KIND, SCHEMA_VERSION } from '../../domain/schema.js';
|
|
3
|
+
import { readObservationArtifact } from '../../artifacts/artifactReader.js';
|
|
4
|
+
import { COMPARISON_ARTIFACT_KIND, COMPARISON_SCHEMA_VERSION } from '../../domain/comparison.js';
|
|
5
|
+
import { readComparisonArtifact } from '../../artifacts/comparisonArtifactReader.js';
|
|
6
|
+
import { CONTRACT_ARTIFACT_KIND, CONTRACT_SCHEMA_VERSION } from '../../domain/frontendContracts.js';
|
|
7
|
+
import { readPersistentBaselineContract, readPerChangeContract } from '../../artifacts/frontendContractArtifactReader.js';
|
|
8
|
+
import { EVALUATION_ARTIFACT_KIND, EVALUATION_SCHEMA_VERSION } from '../../domain/frontendContractEvaluationArtifact.js';
|
|
9
|
+
import { readFrontendContractEvaluationArtifact } from '../../artifacts/frontendContractEvaluationArtifactReader.js';
|
|
10
|
+
import { EXTERNAL_REFERENCE_ARTIFACT_KIND, EXTERNAL_REFERENCE_SCHEMA_VERSION } from '../../domain/externalReference.js';
|
|
11
|
+
import { readExternalReferenceArtifact } from '../../artifacts/externalReferenceArtifactReader.js';
|
|
12
|
+
import { MAX_MANIFEST_CANDIDATE_BYTES } from './limits.js';
|
|
13
|
+
function isPlainObject(value) {
|
|
14
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Classification is not validation (frozen plan §10): this function reads
|
|
18
|
+
* bounded manifest bytes, parses JSON, and peeks only `artifactKind`/
|
|
19
|
+
* `schemaVersion` to decide *which* existing canonical reader to try - the
|
|
20
|
+
* canonical reader's own structural validator remains the sole authority on
|
|
21
|
+
* whether a candidate is actually a valid instance of that family. This
|
|
22
|
+
* function never accepts a candidate that its dispatched reader rejects, and
|
|
23
|
+
* never invents a result the reader did not itself produce.
|
|
24
|
+
*/
|
|
25
|
+
export async function classifyManifest(manifestPath) {
|
|
26
|
+
let size;
|
|
27
|
+
try {
|
|
28
|
+
size = (await stat(manifestPath)).size;
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
32
|
+
return { supportState: 'unreadable', reason: `could not stat candidate manifest: ${message}` };
|
|
33
|
+
}
|
|
34
|
+
if (size > MAX_MANIFEST_CANDIDATE_BYTES) {
|
|
35
|
+
return { supportState: 'unreadable', reason: `candidate manifest exceeds the bounded size limit (${MAX_MANIFEST_CANDIDATE_BYTES} bytes)` };
|
|
36
|
+
}
|
|
37
|
+
let raw;
|
|
38
|
+
try {
|
|
39
|
+
raw = await readFile(manifestPath, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
43
|
+
return { supportState: 'unreadable', reason: `could not read candidate manifest: ${message}` };
|
|
44
|
+
}
|
|
45
|
+
let parsed;
|
|
46
|
+
try {
|
|
47
|
+
parsed = JSON.parse(raw);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
51
|
+
return { supportState: 'malformed-json', reason: message };
|
|
52
|
+
}
|
|
53
|
+
if (!isPlainObject(parsed)) {
|
|
54
|
+
return { supportState: 'unrecognized-kind', foundArtifactKind: undefined };
|
|
55
|
+
}
|
|
56
|
+
const kind = typeof parsed.artifactKind === 'string' ? parsed.artifactKind : undefined;
|
|
57
|
+
const version = typeof parsed.schemaVersion === 'string' ? parsed.schemaVersion : undefined;
|
|
58
|
+
switch (kind) {
|
|
59
|
+
case ARTIFACT_KIND: {
|
|
60
|
+
if (version !== SCHEMA_VERSION) {
|
|
61
|
+
return { supportState: 'unsupported-version', family: 'observation', foundSchemaVersion: version ?? 'unknown', supportedSchemaVersion: SCHEMA_VERSION };
|
|
62
|
+
}
|
|
63
|
+
const read = await readObservationArtifact(manifestPath);
|
|
64
|
+
if (!read.ok)
|
|
65
|
+
return { supportState: 'invalid-structure', family: 'observation', reason: read.reason };
|
|
66
|
+
return { supportState: 'supported', family: 'observation', artifact: read.artifact };
|
|
67
|
+
}
|
|
68
|
+
case COMPARISON_ARTIFACT_KIND: {
|
|
69
|
+
if (version !== COMPARISON_SCHEMA_VERSION) {
|
|
70
|
+
return { supportState: 'unsupported-version', family: 'comparison', foundSchemaVersion: version ?? 'unknown', supportedSchemaVersion: COMPARISON_SCHEMA_VERSION };
|
|
71
|
+
}
|
|
72
|
+
const read = await readComparisonArtifact(manifestPath);
|
|
73
|
+
if (!read.ok)
|
|
74
|
+
return { supportState: 'invalid-structure', family: 'comparison', reason: read.reason };
|
|
75
|
+
return { supportState: 'supported', family: 'comparison', artifact: read.artifact };
|
|
76
|
+
}
|
|
77
|
+
case CONTRACT_ARTIFACT_KIND: {
|
|
78
|
+
if (version !== CONTRACT_SCHEMA_VERSION) {
|
|
79
|
+
return { supportState: 'unsupported-version', family: 'baseline-contract', foundSchemaVersion: version ?? 'unknown', supportedSchemaVersion: CONTRACT_SCHEMA_VERSION };
|
|
80
|
+
}
|
|
81
|
+
// Two structurally distinct persisted shapes share one artifactKind/schemaVersion (contractClass discriminates) -
|
|
82
|
+
// the canonical validators, not this classifier, decide which one (if either) a candidate actually is.
|
|
83
|
+
const baseline = await readPersistentBaselineContract(manifestPath);
|
|
84
|
+
if (baseline.ok)
|
|
85
|
+
return { supportState: 'supported', family: 'baseline-contract', artifact: baseline.contract };
|
|
86
|
+
const change = await readPerChangeContract(manifestPath);
|
|
87
|
+
if (change.ok)
|
|
88
|
+
return { supportState: 'supported', family: 'change-contract', artifact: change.contract };
|
|
89
|
+
return { supportState: 'invalid-structure', family: undefined, reason: `matches neither baseline nor per-change contract shape (baseline: ${baseline.reason}; change: ${change.reason})` };
|
|
90
|
+
}
|
|
91
|
+
case EVALUATION_ARTIFACT_KIND: {
|
|
92
|
+
if (version !== EVALUATION_SCHEMA_VERSION) {
|
|
93
|
+
return { supportState: 'unsupported-version', family: 'contract-evaluation', foundSchemaVersion: version ?? 'unknown', supportedSchemaVersion: EVALUATION_SCHEMA_VERSION };
|
|
94
|
+
}
|
|
95
|
+
const read = await readFrontendContractEvaluationArtifact(manifestPath);
|
|
96
|
+
if (!read.ok)
|
|
97
|
+
return { supportState: 'invalid-structure', family: 'contract-evaluation', reason: read.reason };
|
|
98
|
+
return { supportState: 'supported', family: 'contract-evaluation', artifact: read.artifact };
|
|
99
|
+
}
|
|
100
|
+
case EXTERNAL_REFERENCE_ARTIFACT_KIND: {
|
|
101
|
+
if (version !== EXTERNAL_REFERENCE_SCHEMA_VERSION) {
|
|
102
|
+
return {
|
|
103
|
+
supportState: 'unsupported-version',
|
|
104
|
+
family: 'external-reference-imported',
|
|
105
|
+
foundSchemaVersion: version ?? 'unknown',
|
|
106
|
+
supportedSchemaVersion: EXTERNAL_REFERENCE_SCHEMA_VERSION,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const read = await readExternalReferenceArtifact(manifestPath);
|
|
110
|
+
if (!read.ok)
|
|
111
|
+
return { supportState: 'invalid-structure', family: undefined, reason: read.reason };
|
|
112
|
+
const family = read.artifact.lifecycle.state === 'approved' ? 'external-reference-approved' : 'external-reference-imported';
|
|
113
|
+
return { supportState: 'supported', family, artifact: read.artifact };
|
|
114
|
+
}
|
|
115
|
+
default:
|
|
116
|
+
// Includes both a genuinely unknown string and the known-but-unreadered
|
|
117
|
+
// `my-frontend-observer/bounded-agent-context` kind (see frozen plan
|
|
118
|
+
// §8: no disk reader/writer exists for that family - inventing
|
|
119
|
+
// persistence-shaped handling for it here would fabricate support that
|
|
120
|
+
// does not exist).
|
|
121
|
+
return { supportState: 'unrecognized-kind', foundArtifactKind: kind };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../../src/viewerServer/evidence/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LinkStatus } from './linkedEvidence.js';
|
|
2
|
+
export type ComparisonViewResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
before: LinkStatus;
|
|
5
|
+
after: LinkStatus;
|
|
6
|
+
} | {
|
|
7
|
+
ok: false;
|
|
8
|
+
reason: 'unknown-handle';
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
reason: 'not-a-comparison';
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
reason: 'not-currently-loadable';
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Batch 4's one additive server-side computation for comparisons: resolves
|
|
18
|
+
* the persisted `ComparisonArtifact`'s `before`/`after` source-observation
|
|
19
|
+
* references (exact identity only, `linkedEvidence.ts`) against the current
|
|
20
|
+
* evidence root. Never calls `compareObservations` - the persisted
|
|
21
|
+
* `ComparisonArtifact` (differences, relationshipsBefore/After,
|
|
22
|
+
* comparability, etc.) remains authoritative and is fetched unchanged
|
|
23
|
+
* through the existing Batch 2 `GET /api/artifacts/<handle>`; this endpoint
|
|
24
|
+
* only answers "where are its source observations, if anywhere in this
|
|
25
|
+
* root". Same handle-decode -> contained-dir-resolve -> re-classify
|
|
26
|
+
* discipline as `observationView.ts`/`mediaResolver.ts`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getComparisonView(root: string, handle: string): Promise<ComparisonViewResult>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { classifyManifest } from './classify.js';
|
|
4
|
+
import { decodeArtifactHandle } from './handles.js';
|
|
5
|
+
import { resolveContainedDir } from './pathSafety.js';
|
|
6
|
+
import { resolveObservationByReference } from './linkedEvidence.js';
|
|
7
|
+
/**
|
|
8
|
+
* Batch 4's one additive server-side computation for comparisons: resolves
|
|
9
|
+
* the persisted `ComparisonArtifact`'s `before`/`after` source-observation
|
|
10
|
+
* references (exact identity only, `linkedEvidence.ts`) against the current
|
|
11
|
+
* evidence root. Never calls `compareObservations` - the persisted
|
|
12
|
+
* `ComparisonArtifact` (differences, relationshipsBefore/After,
|
|
13
|
+
* comparability, etc.) remains authoritative and is fetched unchanged
|
|
14
|
+
* through the existing Batch 2 `GET /api/artifacts/<handle>`; this endpoint
|
|
15
|
+
* only answers "where are its source observations, if anywhere in this
|
|
16
|
+
* root". Same handle-decode -> contained-dir-resolve -> re-classify
|
|
17
|
+
* discipline as `observationView.ts`/`mediaResolver.ts`.
|
|
18
|
+
*/
|
|
19
|
+
export async function getComparisonView(root, handle) {
|
|
20
|
+
const decoded = decodeArtifactHandle(handle);
|
|
21
|
+
if (!decoded.ok)
|
|
22
|
+
return { ok: false, reason: 'unknown-handle' };
|
|
23
|
+
const dir = resolveContainedDir(root, decoded.relativeDir);
|
|
24
|
+
if (dir === undefined)
|
|
25
|
+
return { ok: false, reason: 'unknown-handle' };
|
|
26
|
+
try {
|
|
27
|
+
const dirInfo = await stat(dir);
|
|
28
|
+
if (!dirInfo.isDirectory())
|
|
29
|
+
return { ok: false, reason: 'unknown-handle' };
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { ok: false, reason: 'unknown-handle' };
|
|
33
|
+
}
|
|
34
|
+
const classified = await classifyManifest(join(dir, 'manifest.json'));
|
|
35
|
+
if (classified.supportState !== 'supported')
|
|
36
|
+
return { ok: false, reason: 'not-currently-loadable' };
|
|
37
|
+
if (classified.family !== 'comparison')
|
|
38
|
+
return { ok: false, reason: 'not-a-comparison' };
|
|
39
|
+
const { artifact } = classified;
|
|
40
|
+
const [before, after] = await Promise.all([resolveObservationByReference(root, artifact.before), resolveObservationByReference(root, artifact.after)]);
|
|
41
|
+
return { ok: true, before, after };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=comparisonView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparisonView.js","sourceRoot":"","sources":["../../../src/viewerServer/evidence/comparisonView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AASpE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,MAAc;IAClE,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAEhE,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAEtE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IACtE,IAAI,UAAU,CAAC,YAAY,KAAK,WAAW;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;IACpG,IAAI,UAAU,CAAC,MAAM,KAAK,YAAY;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAEzF,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC;IAChC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,6BAA6B,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,6BAA6B,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEvJ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.8 Batch 7: resolves a validated `BoundedAgentContextArtifact.sources`
|
|
3
|
+
* block against the current evidence root by exact canonical identity only
|
|
4
|
+
* (never pathname/name/similarity heuristics), reusing `linkedEvidence.ts`'s
|
|
5
|
+
* established resolver pattern (Batch 4/5) - every lookup here is a bounded
|
|
6
|
+
* discovery walk that matches on the exact identity fields the source
|
|
7
|
+
* reference actually carries. Never calls `compareObservations`,
|
|
8
|
+
* `evaluateFrontendContract`, `projectBoundedAgentContext`, or any
|
|
9
|
+
* correlation-derivation function.
|
|
10
|
+
*/
|
|
11
|
+
import type { BoundedAgentContextSourceReferences } from '../../domain/boundedAgentContext.js';
|
|
12
|
+
import type { LinkStatus } from './linkedEvidence.js';
|
|
13
|
+
export interface ContextSourceResolution {
|
|
14
|
+
/** One resolution per `sources.observationIds` entry, in the same order. */
|
|
15
|
+
observations: {
|
|
16
|
+
observationId: string;
|
|
17
|
+
link: LinkStatus;
|
|
18
|
+
}[];
|
|
19
|
+
comparison?: LinkStatus;
|
|
20
|
+
baselineContract?: LinkStatus;
|
|
21
|
+
changeContract?: LinkStatus;
|
|
22
|
+
evaluation?: LinkStatus;
|
|
23
|
+
reference?: LinkStatus;
|
|
24
|
+
}
|
|
25
|
+
export declare function resolveContextSources(root: string, sources: BoundedAgentContextSourceReferences): Promise<ContextSourceResolution>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { resolveObservationById, resolveComparisonByIdentity, resolveBaselineContractById, resolveChangeContractById, resolveEvaluationByIdentity, resolveReferenceByIdentity } from './linkedEvidence.js';
|
|
2
|
+
export async function resolveContextSources(root, sources) {
|
|
3
|
+
const [observationLinks, comparison, baselineContract, changeContract, evaluation, reference] = await Promise.all([
|
|
4
|
+
Promise.all(sources.observationIds.map(async (observationId) => ({ observationId, link: await resolveObservationById(root, observationId) }))),
|
|
5
|
+
sources.comparisonId !== undefined && sources.comparisonRequestId !== undefined ? resolveComparisonByIdentity(root, sources.comparisonId, sources.comparisonRequestId) : Promise.resolve(undefined),
|
|
6
|
+
sources.baselineContractId !== undefined ? resolveBaselineContractById(root, sources.baselineContractId) : Promise.resolve(undefined),
|
|
7
|
+
sources.changeContractId !== undefined ? resolveChangeContractById(root, sources.changeContractId) : Promise.resolve(undefined),
|
|
8
|
+
sources.evaluationId !== undefined && sources.evaluationRequestId !== undefined ? resolveEvaluationByIdentity(root, sources.evaluationId, sources.evaluationRequestId) : Promise.resolve(undefined),
|
|
9
|
+
sources.referenceId !== undefined && sources.referenceRequestId !== undefined ? resolveReferenceByIdentity(root, sources.referenceId, sources.referenceRequestId) : Promise.resolve(undefined),
|
|
10
|
+
]);
|
|
11
|
+
return {
|
|
12
|
+
observations: observationLinks,
|
|
13
|
+
...(comparison !== undefined ? { comparison } : {}),
|
|
14
|
+
...(baselineContract !== undefined ? { baselineContract } : {}),
|
|
15
|
+
...(changeContract !== undefined ? { changeContract } : {}),
|
|
16
|
+
...(evaluation !== undefined ? { evaluation } : {}),
|
|
17
|
+
...(reference !== undefined ? { reference } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=contextSourceView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextSourceView.js","sourceRoot":"","sources":["../../../src/viewerServer/evidence/contextSourceView.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAY3M,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY,EAAE,OAA4C;IACpG,MAAM,CAAC,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAChH,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9I,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QACnM,OAAO,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QACrI,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,yBAAyB,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QAC/H,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,mBAAmB,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;QACnM,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;KAC/L,CAAC,CAAC;IAEH,OAAO;QACL,YAAY,EAAE,gBAAgB;QAC9B,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface DiscoveredManifest {
|
|
2
|
+
/** Absolute path to the candidate `manifest.json` file. */
|
|
3
|
+
absolutePath: string;
|
|
4
|
+
/** Absolute path to its containing directory (the artifact's own root). */
|
|
5
|
+
absoluteDir: string;
|
|
6
|
+
/** Root-relative, forward-slash-normalized directory path - display/handle material only, never trusted for filesystem access without re-resolution+containment-check. */
|
|
7
|
+
relativeDir: string;
|
|
8
|
+
}
|
|
9
|
+
export interface DiscoveryResult {
|
|
10
|
+
manifests: DiscoveredManifest[];
|
|
11
|
+
/** True if MAX_MANIFEST_CANDIDATES, MAX_DIRECTORIES_VISITED, or MAX_DISCOVERY_DEPTH was hit before the walk completed naturally. */
|
|
12
|
+
truncated: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Bounded, deterministic, symlink-safe walk beneath `root` looking only for
|
|
16
|
+
* files literally named `manifest.json` (the one filename every current
|
|
17
|
+
* persisted artifact family uses - see src/artifacts/*Writer.ts). No other
|
|
18
|
+
* filename is ever opened or classified, so arbitrary files
|
|
19
|
+
* (`package.json`, `.env`, source files, unrelated JSON) can never become
|
|
20
|
+
* evidence merely by existing under the root.
|
|
21
|
+
*
|
|
22
|
+
* Security properties:
|
|
23
|
+
* - directory entries that are symbolic links or reparse points/junctions
|
|
24
|
+
* (`dirent.isSymbolicLink()`) are never followed, so discovery can never
|
|
25
|
+
* leave the resolved root via a symlink;
|
|
26
|
+
* - traversal depth, directories visited, and candidate manifests found are
|
|
27
|
+
* all independently bounded (see limits.ts) - discovery always terminates
|
|
28
|
+
* and never depends on filesystem enumeration order for its *result set*
|
|
29
|
+
* (see the caller-side deterministic sort in index.ts).
|
|
30
|
+
*/
|
|
31
|
+
export declare function discoverManifests(root: string): Promise<DiscoveryResult>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { join, relative, sep } from 'node:path';
|
|
3
|
+
import { MAX_DIRECTORIES_VISITED, MAX_DISCOVERY_DEPTH, MAX_MANIFEST_CANDIDATES } from './limits.js';
|
|
4
|
+
function toPosixRelative(root, absoluteDir) {
|
|
5
|
+
const rel = relative(root, absoluteDir);
|
|
6
|
+
return rel === '' ? '.' : rel.split(sep).join('/');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Bounded, deterministic, symlink-safe walk beneath `root` looking only for
|
|
10
|
+
* files literally named `manifest.json` (the one filename every current
|
|
11
|
+
* persisted artifact family uses - see src/artifacts/*Writer.ts). No other
|
|
12
|
+
* filename is ever opened or classified, so arbitrary files
|
|
13
|
+
* (`package.json`, `.env`, source files, unrelated JSON) can never become
|
|
14
|
+
* evidence merely by existing under the root.
|
|
15
|
+
*
|
|
16
|
+
* Security properties:
|
|
17
|
+
* - directory entries that are symbolic links or reparse points/junctions
|
|
18
|
+
* (`dirent.isSymbolicLink()`) are never followed, so discovery can never
|
|
19
|
+
* leave the resolved root via a symlink;
|
|
20
|
+
* - traversal depth, directories visited, and candidate manifests found are
|
|
21
|
+
* all independently bounded (see limits.ts) - discovery always terminates
|
|
22
|
+
* and never depends on filesystem enumeration order for its *result set*
|
|
23
|
+
* (see the caller-side deterministic sort in index.ts).
|
|
24
|
+
*/
|
|
25
|
+
export async function discoverManifests(root) {
|
|
26
|
+
const manifests = [];
|
|
27
|
+
let directoriesVisited = 0;
|
|
28
|
+
let truncated = false;
|
|
29
|
+
async function walk(dir, depth) {
|
|
30
|
+
if (truncated)
|
|
31
|
+
return;
|
|
32
|
+
if (depth > MAX_DISCOVERY_DEPTH) {
|
|
33
|
+
truncated = true;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (directoriesVisited >= MAX_DIRECTORIES_VISITED) {
|
|
37
|
+
truncated = true;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
directoriesVisited += 1;
|
|
41
|
+
let entries;
|
|
42
|
+
try {
|
|
43
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Unreadable directory (permissions, race with external deletion): skip silently, not a discovery failure.
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Deterministic child ordering regardless of filesystem enumeration order.
|
|
50
|
+
entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
if (truncated)
|
|
53
|
+
return;
|
|
54
|
+
if (entry.isSymbolicLink())
|
|
55
|
+
continue; // never follow symlinks/junctions/reparse points, for files or directories
|
|
56
|
+
if (entry.isDirectory()) {
|
|
57
|
+
await walk(join(dir, entry.name), depth + 1);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (entry.isFile() && entry.name === 'manifest.json') {
|
|
61
|
+
if (manifests.length >= MAX_MANIFEST_CANDIDATES) {
|
|
62
|
+
truncated = true;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
manifests.push({
|
|
66
|
+
absolutePath: join(dir, entry.name),
|
|
67
|
+
absoluteDir: dir,
|
|
68
|
+
relativeDir: toPosixRelative(root, dir),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
await walk(root, 0);
|
|
74
|
+
// Final deterministic ordering of the result set itself, independent of traversal order.
|
|
75
|
+
manifests.sort((a, b) => (a.relativeDir < b.relativeDir ? -1 : a.relativeDir > b.relativeDir ? 1 : 0));
|
|
76
|
+
return { manifests, truncated };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=discovery.js.map
|