diff --git a/src/domain/javascript/javascriptSemanticGraph.ts b/src/domain/javascript/javascriptSemanticGraph.ts index 6908af2a19..ce7eb6ae85 100644 --- a/src/domain/javascript/javascriptSemanticGraph.ts +++ b/src/domain/javascript/javascriptSemanticGraph.ts @@ -19,15 +19,11 @@ import { JAVASCRIPT_SEMANTIC_RELATION_FAMILIES, JAVASCRIPT_SEMANTIC_RELATION_FAMILY, javaScriptSemanticFingerprintInputSchema, - javaScriptSemanticFingerprintSchema, javaScriptSemanticGraphInputSchema, javaScriptSemanticGraphRecordSchema, javaScriptSemanticNodeInputSchema, - javaScriptSemanticNodeSchema, javaScriptSemanticRelationInputSchema, - javaScriptSemanticRelationSchema, javaScriptSemanticUnknownInputSchema, - javaScriptSemanticUnknownSchema, type JavaScriptSemanticGraphInput, type JavaScriptSemanticGraphNode, type JavaScriptSemanticGraphRelation, @@ -132,10 +128,10 @@ export const createJavaScriptSemanticGraphNode = ( application_node_ids: uniqueSorted(parsed.application_node_ids), evidence: evidenceContexts.intern(parsed.evidence), }; - return javaScriptSemanticNodeSchema.parse({ + return { ...semantic, node_id: javaScriptSemanticNodeId(semantic), - }); + }; }; /** Normalize one semantic relationship and derive its exact identifier. */ @@ -148,10 +144,10 @@ export const createJavaScriptSemanticGraphRelation = ( ...parsed, evidence: evidenceContexts.intern(parsed.evidence), }; - return javaScriptSemanticRelationSchema.parse({ + return { ...semantic, relation_id: `jsrg_relation_${digestCanonicalValue(semantic, "JavaScript semantic graph")}`, - }); + }; }; /** Normalize one unresolved semantic frontier and derive its identifier. */ @@ -166,10 +162,10 @@ export const createJavaScriptSemanticGraphUnknown = ( candidate_node_ids: uniqueSorted(parsed.candidate_node_ids), evidence: evidenceContexts.intern(parsed.evidence), }; - return javaScriptSemanticUnknownSchema.parse({ + return { ...semantic, unknown_id: `jsrg_unknown_${digestCanonicalValue(semantic, "JavaScript semantic graph")}`, - }); + }; }; /** Normalize one function fingerprint and derive its component commitment. */ @@ -191,7 +187,7 @@ export const createJavaScriptSemanticFingerprint = ( semantic.components, "JavaScript semantic graph", ); - return javaScriptSemanticFingerprintSchema.parse({ + return { ...semantic, fingerprint_sha256: fingerprintSha256, fingerprint_id: `jsrg_fingerprint_${digestCanonicalValue( @@ -202,7 +198,7 @@ export const createJavaScriptSemanticFingerprint = ( }, "JavaScript semantic graph", )}`, - }); + }; }; type GraphRecord = z.infer; diff --git a/src/domain/javascript/javascriptSemanticGraphQuery.test.ts b/src/domain/javascript/javascriptSemanticGraphQuery.test.ts index 363cf29ad2..9a99872d4f 100644 --- a/src/domain/javascript/javascriptSemanticGraphQuery.test.ts +++ b/src/domain/javascript/javascriptSemanticGraphQuery.test.ts @@ -140,6 +140,44 @@ it("accepts semantic module paths longer than the former schema ceiling", () => ).toBe(modulePath); }); +it("captures caller-owned node identity, properties, and provenance", () => { + const contexts = new JavaScriptSemanticEvidenceContextRegistry(); + const input = { + kind: "literal", + identity: { + artifact_sha256: SHA, + module_path: "bundle.js", + source_range: null, + role_key: "literal", + }, + function_node_id: null, + application_node_ids: [], + label: "literal", + properties: { nested: ["original"] }, + evidence: evidence(), + }; + const captured = createJavaScriptSemanticGraphNode(input, contexts); + const expected = structuredClone(captured); + const expectedEvidence = structuredClone(input.evidence); + + input.identity.module_path = "replaced.js"; + input.properties.nested[0] = "replaced"; + input.evidence.limitations.push("later mutation"); + if (input.evidence.location.available) + input.evidence.location.value = { + kind: "artifact-path", + path: "replaced.js", + }; + + expect(captured).toEqual(expected); + expect( + resolveJavaScriptSemanticEvidence( + { evidence_contexts: contexts.contexts }, + captured.evidence, + ), + ).toEqual(expectedEvidence); +}); + const fixtureInput = (withUnknown = false): JavaScriptSemanticGraphInput => { const evidenceContexts = new JavaScriptSemanticEvidenceContextRegistry(); const module = node("module", "module", {}, evidenceContexts);