From 31e8492fafc91438bc0c6e5a5cc40c989a6fc5b8 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Tue, 27 Oct 2026 01:26:06 +0800 Subject: [PATCH] refactor(artifacts): centralize completed snapshot observations Normalize completed stable-file path, digest and length in one shared observation owner. Migrate thirteen identical provider projections while preserving their selected paths, schema checks and cleanup composition. Keep specialized metadata and worker reply observations at their existing owners. Validation: shared real-descriptor coverage and provider lifecycle tests passed; build, typecheck, lint and formatting passed. --- src/apkSignature/apkSignatureFailures.ts | 15 +++---------- src/artifacts/StableArtifactObservation.ts | 21 ++++++++++++++++++ src/erlang/BeamProvider.ts | 19 ++++------------ src/firmware/devicetree/DevicetreeProvider.ts | 20 ++++------------- src/go/GoBinaryProvider.ts | 22 ++++--------------- src/native/apple/AppleIpsProvider.ts | 19 ++++------------ src/native/elf/ElfNotesProvider.ts | 19 ++++------------ src/native/elf/KernelModuleProvider.ts | 19 ++++------------ src/native/exports/NativeExportsProvider.ts | 19 ++++------------ src/native/pe/PeCertificatesProvider.ts | 19 ++++------------ src/native/pe/PeImportsProvider.ts | 19 ++++------------ src/native/pe/PeLoadConfigProvider.ts | 22 ++++--------------- src/native/pe/PeResourcesProvider.ts | 19 ++++------------ src/python/PythonPycProvider.ts | 19 ++++------------ 14 files changed, 72 insertions(+), 199 deletions(-) create mode 100644 src/artifacts/StableArtifactObservation.ts diff --git a/src/apkSignature/apkSignatureFailures.ts b/src/apkSignature/apkSignatureFailures.ts index 12ac3854a2..eec744d4c8 100644 --- a/src/apkSignature/apkSignatureFailures.ts +++ b/src/apkSignature/apkSignatureFailures.ts @@ -1,5 +1,4 @@ import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; -import { completedStableArtifact } from "../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -7,7 +6,7 @@ import { bindArtifactFileCleanup, } from "../artifacts/ArtifactFileOperation.js"; import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../artifacts/StableArtifactObservation.js"; import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import { AnalysisError } from "../domain/analysisErrorBase.js"; import { @@ -130,16 +129,8 @@ export const apkSignatureFailure = ( path: string, ): AnalysisError => { const primary = primaryFailure(artifactFilePrimaryFacts(cause), path); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/artifacts/StableArtifactObservation.ts b/src/artifacts/StableArtifactObservation.ts new file mode 100644 index 0000000000..f177d947f0 --- /dev/null +++ b/src/artifacts/StableArtifactObservation.ts @@ -0,0 +1,21 @@ +import { + fileSnapshotPartialObservationSchema, + type FileSnapshotPartialObservation, +} from "../domain/fileSnapshotObservation.js"; +import { completedStableArtifact } from "./readStableArtifact.js"; + +/** Completed file identity survives finalization; it does not establish decoded content. */ +export const completedStableArtifactObservation = ( + cause: unknown, + path: string, +): FileSnapshotPartialObservation | undefined => { + const snapshot = completedStableArtifact(cause); + return snapshot === undefined + ? undefined + : fileSnapshotPartialObservationSchema.parse({ + kind: "file-snapshot-hash", + path, + sha256: snapshot.sha256, + bytes: snapshot.bytes.length, + }); +}; diff --git a/src/erlang/BeamProvider.ts b/src/erlang/BeamProvider.ts index 28ed4648c2..049f916516 100644 --- a/src/erlang/BeamProvider.ts +++ b/src/erlang/BeamProvider.ts @@ -1,8 +1,5 @@ import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; -import { - completedStableArtifact, - readStableArtifact, -} from "../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -12,7 +9,7 @@ import { } from "../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../artifacts/StableArtifactObservation.js"; import type { BeamPort } from "../application/erlang/BeamPort.js"; import type { ExecutionOptions } from "../application/AnalysisProvider.js"; import { ArtifactOperationError } from "../domain/artifactOperationError.js"; @@ -207,16 +204,8 @@ const beamFailurePrimary = ( const beamFailure = (cause: unknown, input: InspectErlangBeamInput) => { const primary = beamFailurePrimary(artifactFilePrimaryFacts(cause), input); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/firmware/devicetree/DevicetreeProvider.ts b/src/firmware/devicetree/DevicetreeProvider.ts index 104aff0f79..5d4a42938f 100644 --- a/src/firmware/devicetree/DevicetreeProvider.ts +++ b/src/firmware/devicetree/DevicetreeProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - completedStableArtifact, - readStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -27,7 +24,7 @@ import { MAX_DEVICETREE_FILE_BYTES, type InspectDevicetreeInput, } from "../../domain/firmware/devicetree.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import { err, ok } from "../../domain/result.js"; import { ProviderCleanupError } from "../../domain/providerCleanupError.js"; import { DEVICETREE_PROVIDER } from "../../domain/investigationProviders.js"; @@ -202,17 +199,8 @@ const devicetreeFailure = (cause: unknown, input: InspectDevicetreeInput) => { artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - // The one stable read completed before finalization failed; keep its identity. - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/go/GoBinaryProvider.ts b/src/go/GoBinaryProvider.ts index 33ace70772..2df40bf65c 100644 --- a/src/go/GoBinaryProvider.ts +++ b/src/go/GoBinaryProvider.ts @@ -1,8 +1,5 @@ import { isSelectedRegularFileError } from "../filesystem/RegularFile.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -40,7 +37,7 @@ import { BinaryFormatFailure, BinaryResourceFailure, } from "../native/metadata/BinaryContainer.js"; -import { fileSnapshotPartialObservationSchema } from "../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../artifacts/StableArtifactObservation.js"; /** Bundled format reader identity; embedded compiler versions are separate observed facts. */ export const GO_BINARY_PROVIDER_IDENTITY = { @@ -150,19 +147,8 @@ const failureForPrimary = ( const failureFor = (cause: unknown, path: string): AnalysisError => { const primary = failureForPrimary(artifactFilePrimaryFacts(cause), path); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) { - // This inspect boundary acquires exactly one StableArtifactSnapshot before - // metadata decoding. Completion describes that read, not a decoded report. - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); - } + const observation = completedStableArtifactObservation(cause, path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/apple/AppleIpsProvider.ts b/src/native/apple/AppleIpsProvider.ts index 7db127b149..8fadd76561 100644 --- a/src/native/apple/AppleIpsProvider.ts +++ b/src/native/apple/AppleIpsProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -13,7 +10,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { AppleIpsPort } from "../../application/binaryDiagnostics/AppleIpsPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; @@ -282,16 +279,8 @@ const appleIpsFailure = ( artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/elf/ElfNotesProvider.ts b/src/native/elf/ElfNotesProvider.ts index c755069b3c..663cd8dd20 100644 --- a/src/native/elf/ElfNotesProvider.ts +++ b/src/native/elf/ElfNotesProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -12,7 +9,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { ElfNotesPort } from "../../application/binaryDiagnostics/ElfNotesPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { ArtifactOperationError } from "../../domain/artifactOperationError.js"; @@ -244,16 +241,8 @@ const elfNotesFailure = (cause: unknown, input: InspectElfNotesInput) => { artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/elf/KernelModuleProvider.ts b/src/native/elf/KernelModuleProvider.ts index 21d85b55d9..c0e6833c85 100644 --- a/src/native/elf/KernelModuleProvider.ts +++ b/src/native/elf/KernelModuleProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -12,7 +9,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { KernelModulePort } from "../../application/binaryDiagnostics/KernelModulePort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { ArtifactOperationError } from "../../domain/artifactOperationError.js"; @@ -239,16 +236,8 @@ const kernelModuleFailure = ( artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/exports/NativeExportsProvider.ts b/src/native/exports/NativeExportsProvider.ts index 6daef0dac6..bbd04773a8 100644 --- a/src/native/exports/NativeExportsProvider.ts +++ b/src/native/exports/NativeExportsProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -13,7 +10,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { NativeExportsPort } from "../../application/binaryDiagnostics/NativeExportsPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; @@ -206,16 +203,8 @@ const nativeExportsFailure = ( artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/pe/PeCertificatesProvider.ts b/src/native/pe/PeCertificatesProvider.ts index 287daf6fe0..02571cce3d 100644 --- a/src/native/pe/PeCertificatesProvider.ts +++ b/src/native/pe/PeCertificatesProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -12,7 +9,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { PeCertificatesPort } from "../../application/binaryDiagnostics/PeCertificatesPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { ArtifactOperationError } from "../../domain/artifactOperationError.js"; @@ -196,16 +193,8 @@ const peCertificatesFailure = ( artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/pe/PeImportsProvider.ts b/src/native/pe/PeImportsProvider.ts index aa0e932b5a..bc8528a976 100644 --- a/src/native/pe/PeImportsProvider.ts +++ b/src/native/pe/PeImportsProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -13,7 +10,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { PeImportsPort } from "../../application/binaryDiagnostics/PeImportsPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; @@ -249,16 +246,8 @@ const peImportsFailure = ( artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/pe/PeLoadConfigProvider.ts b/src/native/pe/PeLoadConfigProvider.ts index 055578bc9a..b88f93e7e1 100644 --- a/src/native/pe/PeLoadConfigProvider.ts +++ b/src/native/pe/PeLoadConfigProvider.ts @@ -1,9 +1,6 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -16,7 +13,7 @@ import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorClean import type { PeLoadConfigPort } from "../../application/binaryDiagnostics/PeLoadConfigPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { AnalysisError } from "../../domain/analysisErrorBase.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import { AnalysisAccessDeniedError, AnalysisArtifactChangedError, @@ -226,19 +223,8 @@ const peLoadConfigFailure = ( artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) { - // This inspect boundary acquires exactly one StableArtifactSnapshot before - // parsing. Completion describes that read, not a decoded report. - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); - } + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/native/pe/PeResourcesProvider.ts b/src/native/pe/PeResourcesProvider.ts index b524ac7982..13dfaa6369 100644 --- a/src/native/pe/PeResourcesProvider.ts +++ b/src/native/pe/PeResourcesProvider.ts @@ -1,10 +1,7 @@ import { isSelectedRegularFileError } from "../../filesystem/RegularFile.js"; import { fixedNativeAllowance } from "../../domain/native/nativeDeadlines.js"; import { ArtifactReaderFailure } from "../../artifacts/ArtifactReader.js"; -import { - readStableArtifact, - completedStableArtifact, -} from "../../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../../artifacts/readStableArtifact.js"; import { artifactFilePrimaryFacts, type ArtifactFilePrimaryFacts, @@ -13,7 +10,7 @@ import { } from "../../artifacts/ArtifactFileOperation.js"; import { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../../artifacts/StableArtifactObservation.js"; import type { PeResourcesPort } from "../../application/binaryDiagnostics/PeResourcesPort.js"; import type { ExecutionOptions } from "../../application/AnalysisProvider.js"; import { ArtifactOperationError } from "../../domain/artifactOperationError.js"; @@ -216,16 +213,8 @@ const peResourcesFailure = (cause: unknown, input: InspectPeResourcesInput) => { artifactFilePrimaryFacts(cause), input, ); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError( diff --git a/src/python/PythonPycProvider.ts b/src/python/PythonPycProvider.ts index 461fc9e12a..56295d6fb8 100644 --- a/src/python/PythonPycProvider.ts +++ b/src/python/PythonPycProvider.ts @@ -6,13 +6,10 @@ import { bindArtifactFileCleanup, } from "../artifacts/ArtifactFileOperation.js"; import { ArtifactReaderFailure } from "../artifacts/ArtifactReader.js"; -import { - completedStableArtifact, - readStableArtifact, -} from "../artifacts/readStableArtifact.js"; +import { readStableArtifact } from "../artifacts/readStableArtifact.js"; import { ArtifactResourceScope } from "../artifacts/ArtifactResourceScope.js"; import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js"; -import { fileSnapshotPartialObservationSchema } from "../domain/fileSnapshotObservation.js"; +import { completedStableArtifactObservation } from "../artifacts/StableArtifactObservation.js"; import type { PythonPycPort } from "../application/python/PythonPycPort.js"; import type { ExecutionOptions } from "../application/AnalysisProvider.js"; import { AnalysisError } from "../domain/analysisErrorBase.js"; @@ -168,16 +165,8 @@ const failureForPrimary = ( const failureFor = (cause: unknown, input: InspectPythonPycInput) => { const primary = failureForPrimary(artifactFilePrimaryFacts(cause), input); - const snapshot = completedStableArtifact(cause); - if (snapshot !== undefined) - primary.retainPartialObservation( - fileSnapshotPartialObservationSchema.parse({ - kind: "file-snapshot-hash", - path: input.path, - sha256: snapshot.sha256, - bytes: snapshot.bytes.length, - }), - ); + const observation = completedStableArtifactObservation(cause, input.path); + if (observation !== undefined) primary.retainPartialObservation(observation); if (!(cause instanceof ArtifactReaderFailure) || cause.cleanup === undefined) return primary; const cleanup = new ProviderCleanupError(