mirror of
https://github.com/morluto/rea
synced 2026-10-26 22:28:27 -04:00
4d980d0176
Keep positive topology differences separate from unpaired neighbor identity. Preserve exact content pairing and source observations, report unresolved relationships without inventing incomplete inventory, and omit comparison edges when no substantive difference was observed. Validated with 45 focused domain/CLI/MCP tests, nine expanded domain controls, check:fast, and docs:check. Clean baseline fails seven controls and passes two positive controls. Controlled static fixtures only; no target execution or large-bundle profiling. Refs #4681
230 lines
6.8 KiB
TypeScript
230 lines
6.8 KiB
TypeScript
import { expect, it } from "vitest";
|
|
import {
|
|
artifactEvidence,
|
|
completeCoverage,
|
|
fixtureNode,
|
|
} from "./javascriptApplicationGraph.fixture.js";
|
|
import {
|
|
createJavaScriptApplicationGraph,
|
|
createJavaScriptApplicationEdge,
|
|
type JavaScriptApplicationGraph,
|
|
} from "./javascriptApplicationGraph.js";
|
|
import { compareJavaScriptApplicationVersions } from "./javascriptApplicationVersionComparison.js";
|
|
|
|
const graph = (
|
|
sha: string,
|
|
peers: "ambiguous" | "unique" | "unmatched",
|
|
options: {
|
|
relation?: "imports" | "invokes";
|
|
target?: "peer-one" | "peer-two";
|
|
direction?: "in" | "out";
|
|
content?: string;
|
|
partial?: true;
|
|
} = {},
|
|
) => {
|
|
const evidence = artifactEvidence(sha, "main.js");
|
|
const nodes = ["main", "peer-one", "peer-two"].map((key) =>
|
|
fixtureNode(
|
|
"javascript-module",
|
|
{
|
|
strategy: "artifact-local-key",
|
|
stability: "artifact-version",
|
|
artifact_sha256: sha,
|
|
namespace: "module",
|
|
key,
|
|
},
|
|
key === "main" ? "main" : "peer",
|
|
{
|
|
source_sha256:
|
|
key === "main"
|
|
? (options.content ?? "d".repeat(64))
|
|
: peers === "ambiguous"
|
|
? "c".repeat(64)
|
|
: peers === "unique"
|
|
? (key === "peer-one" ? "e" : "f").repeat(64)
|
|
: (key === "peer-one" ? "1" : "2").repeat(64),
|
|
...(key === "main"
|
|
? {
|
|
structural_fingerprint_sha256: "9".repeat(64),
|
|
structural_fingerprint_algorithm: "fixture",
|
|
}
|
|
: {}),
|
|
},
|
|
evidence,
|
|
),
|
|
);
|
|
const main = nodes[0],
|
|
target = nodes[options.target === "peer-two" ? 2 : 1];
|
|
if (main === undefined || target === undefined)
|
|
throw new Error("Missing fixture nodes");
|
|
return {
|
|
main,
|
|
graph: createJavaScriptApplicationGraph({
|
|
schema: "JavaScriptApplicationGraph",
|
|
root_node_ids: [main.node_id],
|
|
nodes,
|
|
edges: [
|
|
createJavaScriptApplicationEdge({
|
|
source_node_id:
|
|
options.direction === "in" ? target.node_id : main.node_id,
|
|
target_node_id:
|
|
options.direction === "in" ? main.node_id : target.node_id,
|
|
relation: options.relation ?? "imports",
|
|
properties: {},
|
|
evidence,
|
|
}),
|
|
],
|
|
coverage: options.partial
|
|
? { ...completeCoverage, status: "partial", omitted_count: null }
|
|
: completeCoverage,
|
|
limitations: options.partial ? ["Controlled incomplete inventory."] : [],
|
|
}),
|
|
};
|
|
};
|
|
const compare = (
|
|
left: ReturnType<typeof graph>,
|
|
right: ReturnType<typeof graph>,
|
|
) => {
|
|
const result = compareJavaScriptApplicationVersions({
|
|
left: {
|
|
evidenceId: `ev_${"1".repeat(64)}`,
|
|
rootArtifactSha256: "a".repeat(64),
|
|
graph: left.graph,
|
|
},
|
|
right: {
|
|
evidenceId: `ev_${"2".repeat(64)}`,
|
|
rootArtifactSha256: "b".repeat(64),
|
|
graph: right.graph,
|
|
},
|
|
leftNativeEvidence: [],
|
|
rightNativeEvidence: [],
|
|
});
|
|
const item = result.items.find(
|
|
(item) => item.left_node_id === left.main.node_id,
|
|
);
|
|
if (item === undefined) throw new Error("Missing main comparison item");
|
|
return { result, item };
|
|
};
|
|
|
|
it.each(["ambiguous", "unmatched"] as const)(
|
|
"keeps %s neighbor alignment unknown despite complete inventories",
|
|
(peers) => {
|
|
const { result, item } = compare(
|
|
graph("a".repeat(64), "ambiguous"),
|
|
graph("b".repeat(64), peers),
|
|
);
|
|
expect(item).toMatchObject({
|
|
status: "unknown",
|
|
dimensions: [],
|
|
match: {
|
|
status: "matched",
|
|
basis: "exact-module-source-digest",
|
|
confidence: "exact",
|
|
},
|
|
});
|
|
expect(item.limitations.join(" ")).toMatch(
|
|
/relationship.*identity.*unresolved/iu,
|
|
);
|
|
expect(item.limitations.join(" ")).not.toContain(
|
|
"Incomplete graph coverage",
|
|
);
|
|
expect(result.coverage.status).toBe("complete-within-inputs");
|
|
expect(
|
|
result.graph.edges.filter((edge) => edge.relation === "changed_from"),
|
|
).toEqual([]);
|
|
expect(result.graph.nodes).toHaveLength(6);
|
|
if (peers === "ambiguous") {
|
|
expect(result.summary).toEqual({
|
|
unchanged: 0,
|
|
added: 0,
|
|
removed: 0,
|
|
changed: 0,
|
|
unknown: 5,
|
|
});
|
|
expect(
|
|
result.items.filter((i) => i.match.status === "ambiguous"),
|
|
).toHaveLength(4);
|
|
}
|
|
},
|
|
);
|
|
|
|
it("keeps equal relationships to uniquely paired peers unchanged", () => {
|
|
const { item } = compare(
|
|
graph("a".repeat(64), "unique"),
|
|
graph("b".repeat(64), "unique"),
|
|
);
|
|
expect(item).toMatchObject({ status: "unchanged", dimensions: [] });
|
|
expect(item.limitations).toEqual([]);
|
|
});
|
|
|
|
it.each([{ relation: "invokes" as const }, { direction: "in" as const }])(
|
|
"retains positive relation/direction differences beside unknown peer identity %j",
|
|
(options) => {
|
|
const { item } = compare(
|
|
graph("a".repeat(64), "ambiguous"),
|
|
graph("b".repeat(64), "ambiguous", options),
|
|
);
|
|
expect(item).toMatchObject({
|
|
status: "changed",
|
|
dimensions: ["relationships"],
|
|
});
|
|
expect(item.limitations.join(" ")).toMatch(
|
|
/relationship.*identity.*unresolved/iu,
|
|
);
|
|
},
|
|
);
|
|
|
|
it("reports a resolved target change", () => {
|
|
const { item } = compare(
|
|
graph("a".repeat(64), "unique"),
|
|
graph("b".repeat(64), "unique", { target: "peer-two" }),
|
|
);
|
|
expect(item).toMatchObject({
|
|
status: "changed",
|
|
dimensions: ["relationships"],
|
|
});
|
|
});
|
|
|
|
it("preserves definite content change alongside unresolved relationships", () => {
|
|
const { item } = compare(
|
|
graph("a".repeat(64), "ambiguous"),
|
|
graph("b".repeat(64), "ambiguous", { content: "8".repeat(64) }),
|
|
);
|
|
expect(item).toMatchObject({
|
|
status: "changed",
|
|
dimensions: ["content", "properties"],
|
|
match: { basis: "structural-fingerprint" },
|
|
});
|
|
expect(item.limitations.join(" ")).toMatch(
|
|
/relationship.*identity.*unresolved/iu,
|
|
);
|
|
});
|
|
|
|
it.each(["imports", "invokes"] as const)(
|
|
"keeps partial inventory and neighbor identity uncertainty distinct (%s)",
|
|
(relation) => {
|
|
const { result, item } = compare(
|
|
graph("a".repeat(64), "ambiguous"),
|
|
graph("b".repeat(64), "ambiguous", { partial: true, relation }),
|
|
);
|
|
expect(item).toMatchObject({
|
|
status: "unknown",
|
|
dimensions:
|
|
relation === "imports" ? ["coverage"] : ["relationships", "coverage"],
|
|
});
|
|
const changes = result.graph.edges.filter(
|
|
(edge) => edge.relation === "changed_from",
|
|
);
|
|
expect(changes).toHaveLength(relation === "imports" ? 0 : 1);
|
|
if (relation === "invokes")
|
|
expect(changes[0]).toMatchObject({
|
|
properties: { status: "unknown" },
|
|
evidence: { coverage: { status: "partial" } },
|
|
});
|
|
expect(item.limitations.join(" ")).toContain("Incomplete graph coverage");
|
|
expect(item.limitations.join(" ")).toMatch(
|
|
/relationship.*identity.*unresolved/iu,
|
|
);
|
|
},
|
|
);
|