From f90d40720f92ee083ae7e44e8924a397973791ed Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Sat, 24 Oct 2026 08:00:55 +0800 Subject: [PATCH] refactor: retire redundant parsing and workflow facades Keep Mach-O UUID interpretation at reconciliation, environment values at the details owner, and inventory scope admission at the public operation. Remove the obsolete UUID scalar, duplicate DSH dispatch, two intermediate inventory exports, and unused body-cutoff predicate. Keep test resource scopes explicit and cover oversized bodies through the real comparison workflow. Correct stale DSH invalid-result assertions and model DMG cancellation with the command owner, retaining an opaque AbortError control and mount cleanup checks. --- .../ClientRegistrationEnvironment.ts | 8 - .../environment/environmentCompare.test.ts | 8 +- .../environmentCompareBody.test.ts | 59 +++++- .../environment/environmentCompareProbe.ts | 4 - src/artifacts/inventory/ArtifactInventory.ts | 13 +- src/artifacts/inventory/scanCanonical.ts | 9 - src/native/parsers/otool.ts | 13 -- .../artifactInventorySnapshot.test.ts | 30 ++- .../filesystem/asarInventoryFreshness.test.ts | 60 +++--- .../filesystem/dshClientConfiguration.test.ts | 9 +- .../native/nativeDmgArtifactReader.test.ts | 200 ++++++++++-------- .../native/nativeInventory.golden.test.ts | 4 +- tests/fixtures/artifactInventory.ts | 18 +- 13 files changed, 245 insertions(+), 190 deletions(-) diff --git a/src/application/ClientRegistrationEnvironment.ts b/src/application/ClientRegistrationEnvironment.ts index ddd11b406d..604bc30993 100644 --- a/src/application/ClientRegistrationEnvironment.ts +++ b/src/application/ClientRegistrationEnvironment.ts @@ -66,14 +66,6 @@ export const clientRegistrationEnvironment = ( validation: "fragment" | "effective" = "effective", platform: NodeJS.Platform = process.platform, ): Result>, ConfigurationError> => { - if (parsed?.dialect === "dsh") { - const environment = dshDocument(parsed.document).environment( - overrides, - validation, - platform, - ); - return environment.ok ? ok(environment.value.values) : environment; - } const details = clientRegistrationEnvironmentDetails( parsed, overrides, diff --git a/src/application/environment/environmentCompare.test.ts b/src/application/environment/environmentCompare.test.ts index 0c189cea3f..7c2676ce4f 100644 --- a/src/application/environment/environmentCompare.test.ts +++ b/src/application/environment/environmentCompare.test.ts @@ -36,7 +36,7 @@ import { parameterScopes, } from "./environmentCompareMatch.js"; import type { EnvironmentManifestTool } from "./environmentSource.js"; -import { isCut, probeRequests } from "./environmentCompareProbe.js"; +import { probeRequests } from "./environmentCompareProbe.js"; import { parseCaptureEvidence } from "./environmentSource.js"; const fixture = environmentStateServeFixture(timedCaptureEvidence(BOOK_ROWS)); @@ -410,12 +410,6 @@ describe("what the comparison translates and learns", () => { ).toBe(0); }); - it("compares a large binary body only by status, as it does large text", () => { - expect(isCut({ kind: "base64", encoded: "AAAA", whole: false })).toBe(true); - expect(isCut({ kind: "base64", encoded: "AAAA", whole: true })).toBe(false); - expect(isCut({ kind: "cut", text: "a" })).toBe(true); - }); - it("translates mapped ids in query values except those that page a list", () => { const call = matchProbeRequest(extraSource.manifest, { method: "GET", diff --git a/src/application/environment/environmentCompareBody.test.ts b/src/application/environment/environmentCompareBody.test.ts index a6e934705f..2535b688ce 100644 --- a/src/application/environment/environmentCompareBody.test.ts +++ b/src/application/environment/environmentCompareBody.test.ts @@ -10,18 +10,20 @@ import { environmentStateServeFixture, } from "../../../tests/fixtures/environmentServe.js"; import { compareEnvironment } from "./environmentCompare.js"; +import { REPLAY_BODY_LIMIT_BYTES } from "./environmentSource.js"; const responseCapture = ( text: string, base64?: string, mimeType = "application/octet-stream", + status = 200, ): ReturnType => { const capture = environmentManifestCaptureFixture([ { startedDateTime: "2026-10-17T18:00:00.000Z", request: { method: "GET", url: "http://app.example/api/blob" }, response: { - status: 200, + status, content: { mimeType, text, @@ -81,6 +83,61 @@ describe("environment comparison response representation", () => { ).toBe(true); }); + it.each([ + { representation: "binary", status: 200 }, + { representation: "binary", status: 503 }, + { representation: "text", status: 200 }, + { representation: "text", status: 503 }, + ] as const)( + "compares a retained $representation body beyond the replay limit by status only ($status)", + ({ representation, status }) => { + const recorded = responseCapture("different recorded body"); + const text = + representation === "binary" + ? Buffer.alloc(REPLAY_BODY_LIMIT_BYTES + 8, 0xff).toString("base64") + : "é".repeat(REPLAY_BODY_LIMIT_BYTES / 2 + 4); + const probe = responseCapture( + text, + representation === "binary" ? text : undefined, + representation === "binary" ? "application/octet-stream" : "text/plain", + status, + ); + const result = compare(recorded, probe); + const equal = status === 200; + expect(result.probes).toMatchObject([ + { + steps: 1, + equal: equal ? 1 : 0, + normalised: { large_bodies: 1, unobserved_bodies: 0 }, + results: [ + { + live_status: status, + env_status: 200, + equal, + categories: equal ? [] : ["status"], + differences: equal + ? [] + : [ + { + category: "status", + pointer: "", + live: "503", + env: "200", + }, + ], + }, + ], + }, + ]); + expect(result.summary).toMatchObject({ + steps: 1, + equal: equal ? 1 : 0, + categories: { status: equal ? 0 : 1, value: 0 }, + normalised: { large_bodies: 1, unobserved_bodies: 0 }, + }); + }, + ); + it("does not conflate a JSON string value with identical plain text", () => { const json = responseCapture('"hello"', undefined, "application/json"); const text = responseCapture("hello"); diff --git a/src/application/environment/environmentCompareProbe.ts b/src/application/environment/environmentCompareProbe.ts index 4b6cc90711..da08ef12d4 100644 --- a/src/application/environment/environmentCompareProbe.ts +++ b/src/application/environment/environmentCompareProbe.ts @@ -93,10 +93,6 @@ export const requestBody = ( : text; }; -/** A replay body the server cut at its size limit. */ -export const isCut = (body: ReplayedBody): boolean => - body.kind === "cut" || (body.kind === "base64" && !body.whole); - /** The application's answer as an environment answer carries it: JSON, text, or null when it is empty; a body the probe did not record is marked. */ const liveAnswer = ( method: string, diff --git a/src/artifacts/inventory/ArtifactInventory.ts b/src/artifacts/inventory/ArtifactInventory.ts index 582c970f1f..26cad6f905 100644 --- a/src/artifacts/inventory/ArtifactInventory.ts +++ b/src/artifacts/inventory/ArtifactInventory.ts @@ -14,18 +14,11 @@ export const inventoryArtifact = async ( inputPath: string, options: ArtifactInventoryOptions, ): Promise => { - const snapshot = await scanArtifactInventory(inputPath, options); - return artifactInventoryResultSchema.parse(snapshot); -}; - -/** Scan an artifact once and retain the complete immutable graph for projection. */ -export const scanArtifactInventory = async ( - inputPath: string, - options: ArtifactInventoryOptions, -): Promise => - options.resourceScope.run(() => + const snapshot = await options.resourceScope.run(() => scanArtifactInventoryInScope(inputPath, options), ); + return artifactInventoryResultSchema.parse(snapshot); +}; export const scanArtifactInventoryInScope = async ( inputPath: string, diff --git a/src/artifacts/inventory/scanCanonical.ts b/src/artifacts/inventory/scanCanonical.ts index ebded85cf3..e905bdcd5d 100644 --- a/src/artifacts/inventory/scanCanonical.ts +++ b/src/artifacts/inventory/scanCanonical.ts @@ -50,15 +50,6 @@ import { type ArtifactInventoryOptions, } from "./types.js"; -export const scanCanonicalArtifactInventory = async ( - path: string, - options: ArtifactInventoryOptions, - readerFactory: typeof createReader = createReader, -): Promise => - options.resourceScope.run(() => - scanCanonicalArtifactInventoryInScope(path, options, readerFactory), - ); - export const scanCanonicalArtifactInventoryInScope = async ( path: string, options: ArtifactInventoryOptions, diff --git a/src/native/parsers/otool.ts b/src/native/parsers/otool.ts index 3028709fae..d3dc96781b 100644 --- a/src/native/parsers/otool.ts +++ b/src/native/parsers/otool.ts @@ -45,7 +45,6 @@ interface ParsedLoadCommands { sdk: string | null; tools: Array<{ name: string; version: string }>; }>; - uuid: string | null; readonly flags: Set; readonly omittedDependencyCommands: string[]; } @@ -158,7 +157,6 @@ export const parseOtoolLoadCommands = (raw: string) => { endian: header.cpuType === null ? null : cpuEndian(header.cpuType), fileType: header.fileType, flags: [...state.flags].sort(), - uuid: state.uuid, commands: state.commands, segments: state.segments, dependencies: state.dependencies, @@ -286,7 +284,6 @@ const createLoadCommandState = ( dependencies: [], entrypoints: [], builds: [], - uuid: null, flags: new Set(headerFlags ?? []), omittedDependencyCommands: [], }); @@ -310,7 +307,6 @@ const parseLoadCommand = (block: string, state: ParsedLoadCommands): void => { kind, fields, }); - collectUuid(kind, fields, state); collectEntrypoint(kind, fields, state); collectBuild(kind, block, fields, state); collectDependency(kind, fields, state); @@ -379,15 +375,6 @@ const scalarFields = (kind: string): readonly string[] => { return common; }; -const collectUuid = ( - kind: string, - fields: Readonly>, - state: ParsedLoadCommands, -): void => { - if (kind === "LC_UUID") - state.uuid = stringField(fields, "uuid") ?? state.uuid; -}; - const collectEntrypoint = ( kind: string, fields: Readonly>, diff --git a/tests/boundary/filesystem/artifactInventorySnapshot.test.ts b/tests/boundary/filesystem/artifactInventorySnapshot.test.ts index a5c470cec3..6802051cf0 100644 --- a/tests/boundary/filesystem/artifactInventorySnapshot.test.ts +++ b/tests/boundary/filesystem/artifactInventorySnapshot.test.ts @@ -15,7 +15,7 @@ import { import { ArtifactResourceScope } from "../../../src/artifacts/ArtifactResourceScope.js"; import { AsarArtifactReader } from "../../../src/artifacts/AsarArtifactReader.js"; import { DirectoryArtifactReader } from "../../../src/artifacts/DirectoryArtifactReader.js"; -import { scanCanonicalArtifactInventory as scanCanonicalArtifactInventoryOwned } from "../../../src/artifacts/inventory/scanCanonical.js"; +import { scanCanonicalArtifactInventoryInScope } from "../../../src/artifacts/inventory/scanCanonical.js"; import { scanArtifactInventory } from "../../fixtures/artifactInventory.js"; import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js"; @@ -59,11 +59,15 @@ describe("artifact inventory snapshot", () => { }); }, }; - const failure = await scanCanonicalArtifactInventoryOwned( - root, - { resourceScope }, - () => reader, - ).catch((cause: unknown) => cause); + const failure = await resourceScope + .run(() => + scanCanonicalArtifactInventoryInScope( + root, + { resourceScope }, + () => reader, + ), + ) + .catch((cause: unknown) => cause); expect(failure).toBeInstanceOf(ArtifactReaderFailure); if (!(failure instanceof ArtifactReaderFailure)) throw failure instanceof Error @@ -156,11 +160,15 @@ it("unwinds every nested traversal and preserves its primary failure", async () close: () => directory.close(), }; - const failure = await scanCanonicalArtifactInventoryOwned( - bundle, - { resourceScope }, - () => reader, - ).catch((cause: unknown) => cause); + const failure = await resourceScope + .run(() => + scanCanonicalArtifactInventoryInScope( + bundle, + { resourceScope }, + () => reader, + ), + ) + .catch((cause: unknown) => cause); expect(failure).toMatchObject({ reason: "integrity", message: "primary nested member failure", diff --git a/tests/boundary/filesystem/asarInventoryFreshness.test.ts b/tests/boundary/filesystem/asarInventoryFreshness.test.ts index 7174d96473..f1ecc1b310 100644 --- a/tests/boundary/filesystem/asarInventoryFreshness.test.ts +++ b/tests/boundary/filesystem/asarInventoryFreshness.test.ts @@ -10,7 +10,7 @@ import { ArtifactResourceScope } from "../../../src/artifacts/ArtifactResourceSc import { DirectoryArtifactReader } from "../../../src/artifacts/DirectoryArtifactReader.js"; import { inventoryArtifact } from "../../fixtures/artifactInventory.js"; import { AsarArtifactReader } from "../../../src/artifacts/AsarArtifactReader.js"; -import { scanCanonicalArtifactInventory as scanCanonicalArtifactInventoryOwned } from "../../../src/artifacts/inventory/scanCanonical.js"; +import { scanCanonicalArtifactInventoryInScope } from "../../../src/artifacts/inventory/scanCanonical.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; const CONTENT = "module.exports = 42;\n"; @@ -226,27 +226,29 @@ describe("ASAR captured-byte identity", () => { onTestFinished(() => resourceScope.close()); try { await expect( - scanCanonicalArtifactInventoryOwned( - fixture.bundle, - { resourceScope }, - () => ({ - format: directory.format, - entries: (signal) => directory.entries(signal), - provenance: () => directory.provenance(), - close: () => directory.close(), - async open(entry, signal) { - const source = await directory.open(entry, signal); - return Readable.from( - (async function* () { - yield* source; - await fixture.replace(); - expect((await lstat(fixture.archive)).size).toBe( - originalSize, - ); - })(), - ); - }, - }), + resourceScope.run(() => + scanCanonicalArtifactInventoryInScope( + fixture.bundle, + { resourceScope }, + () => ({ + format: directory.format, + entries: (signal) => directory.entries(signal), + provenance: () => directory.provenance(), + close: () => directory.close(), + async open(entry, signal) { + const source = await directory.open(entry, signal); + return Readable.from( + (async function* () { + yield* source; + await fixture.replace(); + expect((await lstat(fixture.archive)).size).toBe( + originalSize, + ); + })(), + ); + }, + }), + ), ), ).rejects.toMatchObject({ reason: "integrity", @@ -310,11 +312,15 @@ describe("ASAR captured-byte identity", () => { const resourceScope = new ArtifactResourceScope(); onTestFinished(() => resourceScope.close()); try { - const failure: unknown = await scanCanonicalArtifactInventoryOwned( - fixture.archive, - { resourceScope }, - () => reader, - ).catch((cause: unknown) => cause); + const failure: unknown = await resourceScope + .run(() => + scanCanonicalArtifactInventoryInScope( + fixture.archive, + { resourceScope }, + () => reader, + ), + ) + .catch((cause: unknown) => cause); expect(failure).toMatchObject({ cleanup: { resources: [attempts[0]] }, partialObservation: { diff --git a/tests/boundary/filesystem/dshClientConfiguration.test.ts b/tests/boundary/filesystem/dshClientConfiguration.test.ts index ec7f2e5cdb..2ab9d38e45 100644 --- a/tests/boundary/filesystem/dshClientConfiguration.test.ts +++ b/tests/boundary/filesystem/dshClientConfiguration.test.ts @@ -1788,8 +1788,9 @@ describe("DeepSeek Harness runtime environment validation", () => { { HOPPER_LOADER_ARGS_JSON: "{" }, command, ), - ).rejects.toMatchObject({ - settings: [{ setting: "HOPPER_LOADER_ARGS_JSON" }], + ).resolves.toMatchObject({ + status: "invalid", + remediation: expect.stringContaining("HOPPER_LOADER_ARGS_JSON"), }); await expect( inspectClientConfiguration( @@ -1797,8 +1798,8 @@ describe("DeepSeek Harness runtime environment validation", () => { { REA_GHIDRA_LANGUAGE_ID: "" }, command, ), - ).rejects.toMatchObject({ - settings: [{ setting: "REA_GHIDRA_LANGUAGE_ID" }], + ).resolves.toMatchObject({ + status: "invalid", }); expect( await inspectClientConfiguration( diff --git a/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts b/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts index 8ac69daae7..ecc87ff129 100644 --- a/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts +++ b/tests/boundary/providers/native/nativeDmgArtifactReader.test.ts @@ -13,7 +13,10 @@ import { build } from "plist"; import { describe, expect, it, onTestFinished, vi } from "vitest"; import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js"; -import { execFileOutput } from "../../../../src/process/ExecFileOutput.js"; +import { + ExecFileOutputCancelledError, + execFileOutput, +} from "../../../../src/process/ExecFileOutput.js"; import { ArtifactReaderFailure, type ArtifactEntry, @@ -26,7 +29,7 @@ import { NativeDmgArtifactReader, type NativeDmgHost, } from "../../../../src/artifacts/NativeDmgArtifactReader.js"; -import { scanCanonicalArtifactInventory } from "../../../../src/artifacts/inventory/scanCanonical.js"; +import { scanCanonicalArtifactInventoryInScope } from "../../../../src/artifacts/inventory/scanCanonical.js"; const createAttachedReader = async ( path: string, @@ -219,19 +222,23 @@ describe("DMG inventory reader ownership", () => { let closeCalls = 0; const resourceScope = new ArtifactResourceScope(); onTestFinished(() => resourceScope.close()); - const failure = await scanCanonicalArtifactInventory( - path, - { resourceScope }, - (inputPath, _format, environment) => { - reader = new NativeDmgArtifactReader(inputPath, environment, host); - const closeReader = reader.close.bind(reader); - reader.close = () => { - closeCalls += 1; - return closeReader(); - }; - return reader; - }, - ).catch((cause: unknown) => cause); + const failure = await resourceScope + .run(() => + scanCanonicalArtifactInventoryInScope( + path, + { resourceScope }, + (inputPath, _format, environment) => { + reader = new NativeDmgArtifactReader(inputPath, environment, host); + const closeReader = reader.close.bind(reader); + reader.close = () => { + closeCalls += 1; + return closeReader(); + }; + return reader; + }, + ), + ) + .catch((cause: unknown) => cause); expect(failure).toMatchObject({ reason: "format", @@ -938,80 +945,97 @@ describe("DMG attach fallback recovery", () => { }); describe("DMG attach cancellation and preexisting mounts", () => { - it("waits for an aborted attach result before discovering and detaching its mount", async () => { - const calls: string[][] = []; - const controller = new AbortController(); - const mount = createMountFixture(); - let markAttachStarted = (): void => {}; - const attachStarted = new Promise((resolveStarted) => { - markAttachStarted = resolveStarted; - }); - let attached = false; - let mountPoint: string | undefined; - const host: NativeDmgHost = { - async run(arguments_, signal) { - calls.push([...arguments_]); - if (arguments_[0] === "info") - return { - stdout: - !attached || mountPoint === undefined - ? emptyInfoPlist - : infoPlist("/tmp/image.dmg", [ - { - "dev-entry": "/dev/disk21", - "mount-point": mountPoint, - }, - ]), - exitCode: 0, - }; - if (arguments_[0] === "detach") { - attached = false; - return { stdout: "", exitCode: 0 }; - } - if (arguments_[0] !== "attach") return { stdout: "", exitCode: 0 }; - mountPoint = join(mount.rememberRoot(arguments_), "Fixture"); - markAttachStarted(); - return new Promise((_, reject) => { - signal?.addEventListener( - "abort", - () => { - void mkdir(mountPoint ?? "").then(async () => { - attached = true; - await writeFile( - join(mountPoint ?? "", "hello.txt"), - "after exit", - ); - reject( - Object.assign(new Error("attach aborted"), { - name: "AbortError", - }), - ); - }); - }, - { once: true }, - ); - }); - }, - }; + it.each(["owned cancellation", "opaque AbortError"] as const)( + "waits for an aborted attach result before discovering and detaching its mount (%s)", + async (kind) => { + const calls: string[][] = []; + const controller = new AbortController(); + const reason = { request: "cancel DMG attach" }; + const commandFailure = + kind === "owned cancellation" + ? new ExecFileOutputCancelledError(reason) + : Object.assign(new Error("attach aborted"), { name: "AbortError" }); + const mount = createMountFixture(); + let markAttachStarted = (): void => {}; + const attachStarted = new Promise((resolveStarted) => { + markAttachStarted = resolveStarted; + }); + let attached = false; + let mountPoint: string | undefined; + const host: NativeDmgHost = { + async run(arguments_, signal) { + calls.push([...arguments_]); + if (arguments_[0] === "info") + return { + stdout: + !attached || mountPoint === undefined + ? emptyInfoPlist + : infoPlist("/tmp/image.dmg", [ + { + "dev-entry": "/dev/disk21", + "mount-point": mountPoint, + }, + ]), + exitCode: 0, + }; + if (arguments_[0] === "detach") { + attached = false; + return { stdout: "", exitCode: 0 }; + } + if (arguments_[0] !== "attach") return { stdout: "", exitCode: 0 }; + mountPoint = join(mount.rememberRoot(arguments_), "Fixture"); + markAttachStarted(); + return new Promise((_, reject) => { + signal?.addEventListener( + "abort", + () => { + void mkdir(mountPoint ?? "").then(async () => { + attached = true; + await writeFile( + join(mountPoint ?? "", "hello.txt"), + "after exit", + ); + reject(commandFailure); + }); + }, + { once: true }, + ); + }); + }, + }; - const creating = createAttachedReader( - "/tmp/image.dmg", - process.env, - controller.signal, - host, - ); - await attachStarted; - controller.abort(); - await expect(creating).rejects.toMatchObject({ reason: "cancelled" }); - expect(calls.map(([operation]) => operation)).toEqual([ - "verify", - "info", - "attach", - "info", - "detach", - ]); - expect(calls).toContainEqual(["detach", "/dev/disk21"]); - }); + const creating = createAttachedReader( + "/tmp/image.dmg", + process.env, + controller.signal, + host, + ); + await attachStarted; + controller.abort(reason); + const failure: unknown = await creating.catch((cause: unknown) => cause); + if (!(failure instanceof ArtifactReaderFailure)) + throw new Error("Expected the settled attach failure"); + expect(failure.reason).toBe( + kind === "owned cancellation" ? "cancelled" : "unavailable", + ); + expect(failure.cause).toBe(commandFailure); + if (kind === "owned cancellation") + expect(failure.cancellation?.reason).toBe(reason); + else expect(failure.cancellation).toBeUndefined(); + expect(calls.map(([operation]) => operation)).toEqual([ + "verify", + "info", + "attach", + "info", + "detach", + ]); + expect(calls).toContainEqual(["detach", "/dev/disk21"]); + expect(attached).toBe(false); + await expect(realpath(mount.root() ?? "")).rejects.toMatchObject({ + code: "ENOENT", + }); + }, + ); it("leaves a preexisting outside-root mount attached", async () => { const calls: string[][] = []; diff --git a/tests/boundary/providers/native/nativeInventory.golden.test.ts b/tests/boundary/providers/native/nativeInventory.golden.test.ts index 64407bb426..ffc1915e2f 100644 --- a/tests/boundary/providers/native/nativeInventory.golden.test.ts +++ b/tests/boundary/providers/native/nativeInventory.golden.test.ts @@ -663,7 +663,9 @@ Load command 1 ); expect(parsed.commands[0]?.fields.name).toBe(`${installName} (offset 24)`); expect(parsed.dependencies).toEqual([]); - expect(parsed.uuid).toBe("01234567-89AB-CDEF-0123-456789ABCDEF"); + expect(parsed.commands[1]?.fields.uuid).toBe( + "01234567-89AB-CDEF-0123-456789ABCDEF", + ); }, ); it.each(["weak-def", "absolute", "literal suffix"])( diff --git a/tests/fixtures/artifactInventory.ts b/tests/fixtures/artifactInventory.ts index 776d55fbea..4ec030a50b 100644 --- a/tests/fixtures/artifactInventory.ts +++ b/tests/fixtures/artifactInventory.ts @@ -4,9 +4,9 @@ import { ArtifactReaderFailure } from "../../src/artifacts/ArtifactReader.js"; import { classifyAndHashRoot as classifyAndHashRootOwned } from "../../src/artifacts/inventory/classify.js"; import { inventoryArtifact as inventoryArtifactOwned, - scanArtifactInventory as scanArtifactInventoryOwned, + scanArtifactInventoryInScope, } from "../../src/artifacts/inventory/ArtifactInventory.js"; -import { scanCanonicalArtifactInventory as scanCanonicalArtifactInventoryOwned } from "../../src/artifacts/inventory/scanCanonical.js"; +import { scanCanonicalArtifactInventoryInScope } from "../../src/artifacts/inventory/scanCanonical.js"; import type { createReader } from "../../src/artifacts/inventory/reader.js"; import { materializeArtifactInventory as materializeArtifactInventoryOwned, @@ -43,7 +43,9 @@ export const scanArtifactInventory = ( options: InventoryOptions = {}, ) => withArtifactResourceScope((resourceScope) => - scanArtifactInventoryOwned(path, { ...options, resourceScope }), + resourceScope.run(() => + scanArtifactInventoryInScope(path, { ...options, resourceScope }), + ), ); export const scanCanonicalArtifactInventory = ( @@ -52,10 +54,12 @@ export const scanCanonicalArtifactInventory = ( readerFactory?: typeof createReader, ) => withArtifactResourceScope((resourceScope) => - scanCanonicalArtifactInventoryOwned( - path, - { ...options, resourceScope }, - readerFactory, + resourceScope.run(() => + scanCanonicalArtifactInventoryInScope( + path, + { ...options, resourceScope }, + readerFactory, + ), ), );