mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
fix(javascript): preserve graph facts across omissions and versions
Omit absent inventory facts without erasing explicit unknowns. Compare canonical file occurrences by source path and digest while preserving complete container provenance in observations and Evidence. Consolidate candidate-capacity fixtures around unresolved alternatives and update inventory coverage and source-occurrence oracles. Preserve resource, identity, relationship uncertainty, cancellation, and transfer regressions.
This commit is contained in:
@@ -80,6 +80,9 @@ const contextFor = (
|
||||
graph_sha256: SHA256,
|
||||
},
|
||||
nodes: [{ artifact_id: `art_${SHA256}`, sha256: SHA256, size: 1 }],
|
||||
// These fixtures model complete directory traversal; source-analysis gaps
|
||||
// remain on the individual files and do not imply missing inventory paths.
|
||||
coverage: { scope: "root", status: "complete" },
|
||||
} as unknown as ArtifactInventorySnapshot;
|
||||
const fileSet = {
|
||||
files: [file],
|
||||
@@ -157,6 +160,47 @@ describe("skipped JavaScript parse reporting", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves omitted inventory facts on an unavailable artifact", () => {
|
||||
const file = skippedFile();
|
||||
const base = contextFor(file, analysisFor([]));
|
||||
const context: JavaScriptArtifactGraphContext = {
|
||||
...base,
|
||||
fileSet: {
|
||||
...base.fileSet,
|
||||
files: [],
|
||||
unavailable_relevant_files: [
|
||||
{
|
||||
path: file.path,
|
||||
container_sha256: file.container_sha256,
|
||||
sha256: null,
|
||||
bytes: null,
|
||||
inventory_artifact_id: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
addJavaScriptArtifactFiles(context);
|
||||
const entry = context.accumulator
|
||||
.nodes()
|
||||
.find(
|
||||
({ identity }) =>
|
||||
identity.strategy === "canonical-path" && identity.path === file.path,
|
||||
);
|
||||
expect(entry?.observations[0]?.properties).toEqual({
|
||||
path: file.path,
|
||||
entry_sha256: null,
|
||||
bytes: null,
|
||||
inventory_artifact_id: null,
|
||||
content_available: false,
|
||||
});
|
||||
expect(
|
||||
context.accumulator
|
||||
.edges()
|
||||
.find(({ target_node_id }) => target_node_id === entry?.node_id)
|
||||
?.properties,
|
||||
).toEqual({ path: file.path, content_available: false });
|
||||
});
|
||||
|
||||
it.each([false, true])(
|
||||
"retains possible setter owners independently of proven imports (possible owner: %s)",
|
||||
(possibleOwner) => {
|
||||
|
||||
@@ -390,8 +390,12 @@ const addUnavailableArtifactEntries = (
|
||||
...(file.inventory_occurrence_id === undefined
|
||||
? {}
|
||||
: { inventory_occurrence_id: file.inventory_occurrence_id }),
|
||||
hash_status: file.hash_status,
|
||||
artifact_kind: file.artifact_kind,
|
||||
...(file.hash_status === undefined
|
||||
? {}
|
||||
: { hash_status: file.hash_status }),
|
||||
...(file.artifact_kind === undefined
|
||||
? {}
|
||||
: { artifact_kind: file.artifact_kind }),
|
||||
...(file.kind === undefined ? {} : { kind: file.kind }),
|
||||
content_available: false,
|
||||
},
|
||||
@@ -414,7 +418,9 @@ const addUnavailableArtifactEntries = (
|
||||
properties: {
|
||||
path: file.path,
|
||||
content_available: false,
|
||||
hash_status: file.hash_status,
|
||||
...(file.hash_status === undefined
|
||||
? {}
|
||||
: { hash_status: file.hash_status }),
|
||||
},
|
||||
evidence: artifactObservationEvidence({
|
||||
sha256: file.container_sha256,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { primitiveByteExpansionSource } from "../../../tests/fixtures/javascriptPrimitiveExpansion.js";
|
||||
import {
|
||||
primitiveByteExpansionSource,
|
||||
primitiveCandidateExpansionExpression,
|
||||
} from "../../../tests/fixtures/javascriptPrimitiveExpansion.js";
|
||||
import { graphForJavaScript as graphFor } from "../../../tests/fixtures/javascriptSemanticGraph.js";
|
||||
import * as t from "@babel/types";
|
||||
import { expect, it } from "vitest";
|
||||
@@ -250,8 +253,7 @@ it("keeps dynamic calls explicit and returns complete deterministic results", ()
|
||||
});
|
||||
|
||||
it("preserves primitive candidate budget unknowns in semantic graph coverage", () => {
|
||||
const term = '(true ? "a" : "b")';
|
||||
const source = `const answer = ${Array.from({ length: 20 }, () => term).join(" + ")};`;
|
||||
const source = `const answer = ${primitiveCandidateExpansionExpression()};`;
|
||||
const ir = analyzeJavaScriptSemantics(source);
|
||||
const graph = graphFor(source, ir);
|
||||
|
||||
@@ -287,8 +289,7 @@ it("preserves derived string-byte limit reasons in semantic graph unknowns", ()
|
||||
});
|
||||
|
||||
it("retains resource-limit reasons at nested object property slots", () => {
|
||||
const term = '(true ? "a" : "b")';
|
||||
const source = `const answer = { nested: { value: ${Array.from({ length: 20 }, () => term).join(" + ")} } };`;
|
||||
const source = `const answer = { nested: { value: ${primitiveCandidateExpansionExpression()} } };`;
|
||||
const ir = analyzeJavaScriptSemantics(source);
|
||||
const graph = graphFor(source, ir);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user