fix(javascript): keep unmapped captured runtime scripts unknown

A captured script whose bytes matched no static digest was reported as
high-confidence unmatched even when no automatic or caller-declared
mapping applied to its location in any static layer. The matcher now
computes mapping presence once while locating candidates and shares one
no-candidate classification between the captured-source and source-free
branches, so an unmapped location stays unknown with
no-authorized-location-mapping and is not counted as unmatched.

Fixes #6061.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822
2026-10-22 02:20:21 +00:00
parent 719d56ebfe
commit e308f35c43
3 changed files with 266 additions and 35 deletions
@@ -229,3 +229,204 @@ it("keeps unavailable mapped digests unknown instead of borrowing unrelated matc
reason: "static-or-runtime-coverage-incomplete",
});
});
const UNRELATED = "export const unrelated = 17;\n";
type LayerSetup = {
readonly root: string;
readonly mapping: "none" | "explicit";
};
/** Reconcile one captured script, located at absent.js under live, against layers. */
const reconcileCapturedScript = async (input: {
readonly layers: readonly LayerSetup[];
readonly live: string;
readonly source: string;
readonly includeWorker?: boolean;
}) => {
const result = reconcileJavaScriptRuntime(
parseRuntimeReconciliationInput(
reconcileJavaScriptRuntimeInputSchema.parse({
static_layers: await Promise.all(
input.layers.map(async ({ root, mapping }, index) => ({
role: (["application", "cache", "assets"] as const)[index],
analysis: await analyzeFixture(root),
runtime_mappings:
mapping === "explicit"
? [{ kind: "file-root", root: input.live, artifact_prefix: "" }]
: [],
})),
),
runtime_observations: [
electronRuntimeEvidence(input.live, input.source, {
scriptFile: "absent.js",
includeWorker: input.includeWorker ?? false,
}),
],
}),
),
);
const item = (kind: string) =>
result.reconciliations.find(({ entity_kind }) => entity_kind === kind);
return { result, script: item("script"), worker: item("worker") };
};
it("keeps an unmapped captured script without a content match unknown", async () => {
const root = await applicationFixture();
const live = await createTestTempDirectory("rea-runtime-unmapped-");
const { result, script, worker } = await reconcileCapturedScript({
layers: [{ root, mapping: "none" }],
live,
source: UNRELATED,
includeWorker: true,
});
const unknown = {
status: "unknown",
basis: "none",
confidence: "unknown",
reason: "no-authorized-location-mapping",
static_layer_id: null,
static_node_id: null,
candidate_static_count: 0,
};
expect(script).toMatchObject(unknown);
// A source-free worker at an unmapped location shares the same rule.
expect(worker).toMatchObject(unknown);
expect(result.summary).toMatchObject({ matched: 0, unmatched: 0 });
expect(
result.graph.edges.some(({ relation }) => relation === "observed_as"),
).toBe(false);
});
it.each(["explicit", "implicit-root"] as const)(
"reports a mapped captured script without a content match as unmatched (%s)",
async (mapping) => {
const root = await applicationFixture();
const live =
mapping === "explicit"
? await createTestTempDirectory("rea-runtime-mapped-absent-")
: root;
const { result, script } = await reconcileCapturedScript({
layers: [{ root, mapping: mapping === "explicit" ? "explicit" : "none" }],
live,
source: UNRELATED,
});
expect(script).toMatchObject({
status: "unmatched",
basis: "none",
confidence: "high",
reason: "no-static-content-match",
candidate_static_count: 0,
});
expect(result.summary.unmatched).toBe(1);
},
);
it.each([
["only the second", ["none", "explicit"], "unmatched"],
["only the first", ["explicit", "none"], "unmatched"],
["neither", ["none", "none"], "unknown"],
] as const)(
"classifies an unmatched captured script when %s of two layers maps it",
async (_label, mappings, status) => {
const live = await createTestTempDirectory("rea-runtime-layer-mapping-");
const { script } = await reconcileCapturedScript({
layers: await Promise.all(
mappings.map(async (mapping) => ({
root: await applicationFixture(),
mapping,
})),
),
live,
source: UNRELATED,
});
expect(script).toMatchObject({
status,
reason:
status === "unknown"
? "no-authorized-location-mapping"
: "no-static-content-match",
});
},
);
it.each([
[1, "matched", "unique-content-match"],
[2, "ambiguous", "ambiguous-static-candidates"],
] as const)(
"keeps unmapped content-only correspondence with %i digest candidates",
async (copies, status, reason) => {
const live = await createTestTempDirectory("rea-runtime-unmapped-content-");
const { result, script } = await reconcileCapturedScript({
layers: await Promise.all(
Array.from({ length: copies }, async () => {
const root = await applicationFixture();
await writeFile(join(root, "other.js"), CAPTURED);
return { root, mapping: "none" as const };
}),
),
live,
source: CAPTURED,
});
expect(script).toMatchObject({
status,
basis: copies === 1 ? "content-sha256" : "none",
reason,
candidate_static_count: copies,
});
expect(result.summary.unmatched).toBe(0);
},
);
it.each([
["https://example.test/assets/absent.js", "unmatched"],
["https://other.test/assets/absent.js", "unknown"],
] as const)(
"applies URL-prefix mapping presence to captured script %s",
async (url, status) => {
const root = await applicationFixture();
const parsed = parseRuntimeReconciliationInput(
reconcileJavaScriptRuntimeInputSchema.parse({
static_layers: [
{
role: "application",
analysis: await analyzeFixture(root),
runtime_mappings: [
{
kind: "url-prefix",
prefix: "https://example.test/assets/",
artifact_prefix: "",
},
],
},
],
runtime_observations: [
electronRuntimeEvidence(root, UNRELATED, { includeWorker: false }),
],
}),
);
// Model a URL-located capture at the matcher boundary; browser and
// Inspector projections supply URL locations to the same classifier.
const entities = projectRuntimeCaptures(parsed.captures).entities.map(
(entity) =>
entity.kind === "script"
? { ...entity, location: { kind: "url" as const, value: url } }
: entity,
);
const result = reconcileRuntimeEntities({
entities,
candidates: collectStaticRuntimeCandidates(parsed.layers),
layers: parsed.layers,
});
expect(
result.items.find(({ entity_kind }) => entity_kind === "script"),
).toMatchObject({
status,
confidence: status === "unknown" ? "unknown" : "high",
reason:
status === "unknown"
? "no-authorized-location-mapping"
: "no-static-content-match",
});
},
);