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:
Kaoru0822andClaude Opus 5.5 committed 2026-10-22 02:20:21 +00:00
1 parent 719d56ebfe
commit e308f35c43
3 files changed
+266 -35

No files matched your search

+5 -1
View File
@@ -106,7 +106,11 @@ nodes. REA evaluates compatible static candidates conservatively:
that disagreement. If a mapped candidate's digest is unavailable and no
mapped content match is known, the comparison remains `unknown`.
6. Missing authorization mappings and incomplete or truncated input coverage
remain unknown or truncated rather than becoming absence claims.
remain unknown or truncated rather than becoming absence claims. A runtime
location with no automatic artifact-root or caller-declared mapping into
any layer, and no unique content match, is `unknown` with
`no-authorized-location-mapping`, with or without captured bytes. Only a
mapped location can be `unmatched` with `no-static-content-match`.
Every successful cross-layer `observed_as` edge has
`authority: cross-layer-reconciliation` and `state: inferred`. The underlying
@@ -77,14 +77,13 @@ const reconcileEntity = (
reason: "runtime-location-unresolved",
candidates: [],
});
const locations = candidatesWithLocation(entity, index, layers);
const { locations, mapped } = locateEntity(entity, index, layers);
if (entity.sourceSha256 !== null)
return reconcileCapturedSource(
entity,
entity.sourceSha256,
return reconcileCapturedSource(entity, entity.sourceSha256, {
locations,
mapped,
index,
);
});
const location = locations.at(0);
if (locations.length === 1 && location !== undefined) {
@@ -103,20 +102,40 @@ const reconcileEntity = (
reason: "ambiguous-static-candidates",
candidates: locations.map(({ candidate }) => candidate),
});
const mapped = layers.some(
(layer) => mappedRuntimePaths(layer, entity).length > 0,
);
return unresolved(entity, {
status: mapped ? "unmatched" : "unknown",
basis: "none",
confidence: "unknown",
reason: mapped
? "no-static-content-match"
: "no-authorized-location-mapping",
candidates: [],
});
return withoutStaticCandidate(entity, mapped, "unknown");
};
/**
* Classify an entity with no qualifying static candidate. Absence is claimed
* only beneath an automatic or caller-declared mapping; without one, the
* runtime location has no authorized static counterpart and stays unknown.
* Captured bytes compared against every static digest support a high-confidence
* absence; a location-only absence does not.
*/
const withoutStaticCandidate = (
entity: RuntimeReconciliationEntity,
mapped: boolean,
absenceConfidence: JavaScriptRuntimeReconciliationItem["confidence"],
): EvaluatedMatch =>
unresolved(
entity,
mapped
? {
status: "unmatched",
basis: "none",
confidence: absenceConfidence,
reason: "no-static-content-match",
candidates: [],
}
: {
status: "unknown",
basis: "none",
confidence: "unknown",
reason: "no-authorized-location-mapping",
candidates: [],
},
);
interface LocatedCandidate {
readonly candidate: StaticRuntimeCandidate;
readonly mapping: MappedRuntimePath;
@@ -125,8 +144,15 @@ interface LocatedCandidate {
const reconcileCapturedSource = (
entity: RuntimeReconciliationEntity,
sourceSha256: string,
locations: readonly LocatedCandidate[],
index: CandidateIndex,
{
locations,
mapped,
index,
}: {
readonly locations: readonly LocatedCandidate[];
readonly mapped: boolean;
readonly index: CandidateIndex;
},
): EvaluatedMatch => {
// A known mapped candidate owns the comparison. Unrelated equal bytes cannot
// repair a disagreement or establish the content of a candidate without a digest.
@@ -176,23 +202,19 @@ const reconcileCapturedSource = (
candidates: locations.map(({ candidate: located }) => located),
});
}
return unresolved(entity, {
status: "unmatched",
basis: "none",
confidence: "high",
reason: "no-static-content-match",
candidates: [],
});
return withoutStaticCandidate(entity, mapped, "high");
};
const candidatesWithLocation = (
const locateEntity = (
entity: RuntimeReconciliationEntity,
index: CandidateIndex,
layers: readonly ParsedStaticLayer[],
): LocatedCandidate[] => {
): { readonly locations: LocatedCandidate[]; readonly mapped: boolean } => {
const located = new Map<string, LocatedCandidate>();
let mapped = false;
for (const layer of layers)
for (const mapping of mappedRuntimePaths(layer, entity))
for (const mapping of mappedRuntimePaths(layer, entity)) {
mapped = true;
for (const candidate of [
...(index.byLayerCategoryPath.get(
layerCategoryPathKey(layer.layerId, entity.staticKind, mapping.path),
@@ -215,12 +237,16 @@ const candidatesWithLocation = (
const key = candidateKey(candidate);
if (!located.has(key)) located.set(key, { candidate, mapping });
}
return [...located.values()].sort((left, right) =>
compareUnicodeCodePoints(
candidateKey(left.candidate),
candidateKey(right.candidate),
}
return {
locations: [...located.values()].sort((left, right) =>
compareUnicodeCodePoints(
candidateKey(left.candidate),
candidateKey(right.candidate),
),
),
);
mapped,
};
};
const indexCandidates = (
@@ -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",
});
},
);