1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages

Add relationship-aware graph flow

This commit is contained in:
Andraxion 2026-07-24 23:40:47 -04:00
parent 9bd41c5982
commit 440ca7510f
11 changed files with 567 additions and 80 deletions

View file

@ -91,12 +91,20 @@ class VisualizationTests(unittest.TestCase):
viewport_logic = script.split("function viewportForPositions", 1)[1].split(
"function selectNode", 1
)[0]
relation_constants = script.split("const relationStyles", 1)[1].split("const $", 1)[0]
relation_logic = script.split("function relationHash", 1)[1].split(
"function applyViewport", 1
)[0]
topology_logic = script.split("function analyzeTopology", 1)[1].split(
"function renderNeighborhood", 1
)[0]
harness = (
"const defaultViewport = Object.freeze({x: -600, y: -410, width: 1200, height: 820});\n"
"function viewportForPositions"
"const relationStyles"
+ relation_constants
+ "function relationHash"
+ relation_logic
+ "function viewportForPositions"
+ viewport_logic
+ "function analyzeTopology"
+ topology_logic
@ -141,6 +149,42 @@ const centered = viewportCenteredOn(
if (centered.width !== 500 || centered.height !== 300) fail("center preserves zoom");
if (centered.x !== positions.get("child-two").x - 250) fail("center x");
if (centered.y !== positions.get("child-two").y - 150) fail("center y");
if (relationStyle("calls").family !== "Execution") fail("calls family");
if (relationStyle("reads").flow !== "reverse") fail("reads flow direction");
if (relationStyle("documents").flow !== null) fail("documents excluded from flow");
if (relationStyle("unknown_relation").family !== "Other") fail("fallback relation family");
const flowData = {
root: "primary",
depth: 2,
nodes: [
{node_id: "primary"},
{node_id: "caller"},
{node_id: "dependency"},
{node_id: "reader"},
{node_id: "document"},
],
edges: [
{source_id: "caller", relation: "calls", target_id: "primary"},
{source_id: "primary", relation: "depends_on", target_id: "dependency"},
{source_id: "primary", relation: "reads", target_id: "reader"},
{source_id: "document", relation: "documents", target_id: "primary"},
],
};
const flow = buildFlowGraph(flowData);
const flowIds = new Set(flow.nodes.map((node) => node.node_id));
if (!flowIds.has("caller") || !flowIds.has("dependency") || !flowIds.has("reader")) {
fail("upstream flow membership");
}
if (flowIds.has("document")) fail("evidence leaked into flow");
const flowPositions = layoutFlow(flow.nodes, flow.root, flow.topology);
if (flowPositions.get("primary").x !== 0) fail("flow destination position");
if (flowPositions.get("caller").x >= flowPositions.get("primary").x) {
fail("flow upstream direction");
}
const dependencyEdge = flow.edges.find((edge) => edge.relation === "depends_on");
if (dependencyEdge.source_id !== "dependency" || dependencyEdge.target_id !== "primary") {
fail("dependency semantic reversal");
}
"""
)
result = subprocess.run(
@ -188,6 +232,8 @@ if (centered.y !== positions.get("child-two").y - 150) fail("center y");
self.assertIn('id="view-nodes"', html)
self.assertIn('id="view-flow"', html)
self.assertIn('id="neighborhood-sections"', html)
self.assertIn('id="relationship-key"', html)
self.assertIn('id="relationship-key-list"', html)
self.assertNotIn('id="details"', html)
self.assertIn(".empty[hidden] { display: none; }", html)
self.assertIn("html, body { height: 100%; overflow: hidden; }", html)
@ -204,11 +250,19 @@ if (centered.y !== positions.get("child-two").y - 150) fail("center y");
self.assertIn("beginDialogDrag", html)
self.assertIn('setupPanelResizer("left")', html)
self.assertIn('setupPanelResizer("right")', html)
self.assertIn("Primary focus", html)
self.assertIn("Edge & context", html)
self.assertIn("Focus node", html)
self.assertIn("Outgoing paths", html)
self.assertIn("Incoming & lateral", html)
self.assertNotIn(">Children<", html)
self.assertIn("distanceShade", html)
self.assertIn("viewportForPositions", html)
self.assertIn("centerSelectedNode", html)
self.assertIn("relationStyles", html)
self.assertIn("appendRelationMarker", html)
self.assertIn("renderRelationshipKey", html)
self.assertIn("semanticFlowEdge", html)
self.assertIn("buildFlowGraph", html)
self.assertIn("layoutFlow", html)
self.assertIn("filterByDescriptor", html)
self.assertIn("api(`filter?${params}`)", html)
self.assertIn('setViewMode("flow")', html)