fix(export): colour and filter graph.html edges by relation - #2237
fix(export): colour and filter graph.html edges by relation#2237SyedFahad7 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the HTML exporter (graph.html) to make edge relations visually distinguishable and filterable, addressing #2088 by adding a “Connection Types” sidebar panel and per-relation coloring (opt-in by default).
Changes:
- Add a Connection Types panel to color edges by relation and toggle relation visibility; initial coloring state is controlled via
localStorageandGRAPHIFY_EDGE_TYPES/to_html(edge_types=...). - Scope
toggleAllCommunitiesDOM queries to#legendto prevent unintended checkbox manipulation in other panels. - Sanitize edge relation labels on export and propagate them into the embedded JSON for safe client-side use.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| community_labels: dict[int, str] | None = None, | ||
| member_counts: dict[int, int] | None = None, | ||
| node_limit: int | None = None, | ||
| learning_overlay: dict | None = None, | ||
| edge_types: bool | None = None, |
There was a problem hiding this comment.
fair — pushed a small follow-up covering panel present/absent + edge_types / GRAPHIFY_EDGE_TYPES defaults.
Every edge was drawn the same, so calls drowned in contains/imports. Add a Connection Types sidebar (off-by-default colouring, per-relation checkboxes, localStorage + GRAPHIFY_EDGE_TYPES / edge_types=). Also scope toggleAllCommunities to #legend so a second panel cannot steal its state. Fixes Graphify-Labs#2088
Assert the panel ships on normal graphs, stays off for aggregated views, and that edge_types= / GRAPHIFY_EDGE_TYPES set EDGE_TYPES_COLOR_DEFAULT.
0b4c21c to
6de98d9
Compare
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. 2 change(s) alter behavior, breaking input(s) attached.
Behavior changes: \_html\_script changes behavior, here is the input that shows it.
The verifier found a concrete input on which \_html\_script behaves differently before and after the change. If that change is intended, ship it; if not, this is your bug.
Guarantee: This difference was REPRODUCED, the verifier actually ran both versions on that input and saw them disagree. It is real, not an artifact.
Evidence: On input \{"nodes\_json":"''","edges\_json":"''","legend\_json":"'\\\\x00'"\}, the old code produced '\<script\>\\nconst RAW\_NODES = ;\\nconst RAW\_EDGES = ;\\nconst LEGEND = \\x00;\\n\\n// HTML\-escape helper — prevents XSS when injecting graph data into innerHTML\\nfunction esc\(s\) \{\\n return… but the new code produces '\<script\>\\nconst RAW\_NODES = ;\\nconst RAW\_EDGES = ;\\nconst LEGEND = \\x00;\\nconst SHOW\_EDGE\_TYPES = false;\\nconst EDGE\_TYPES\_COLOR\_DEFAULT = false;\\n\\n// HTML\-escape helper — prevent…. Paste that input straight into a regression test.
Behavior changes: \_html\_styles changes behavior, here is the input that shows it.
The verifier found a concrete input on which \_html\_styles behaves differently before and after the change. If that change is intended, ship it; if not, this is your bug.
Guarantee: This is a sound refutation from a mathematical proof (SMT solver, over a bounded input domain): a concrete input on which the two versions provably differ.
Graphify review — findings
Adds an opt-in "Connection Types" panel to the interactive HTML graph export that colours and filters edges by relation, with per-relation checkboxes, stable colours (fixed palette plus a hashed fallback for unknown relations), and a persist-to-localStorage toggle for whether colouring starts on. Colouring defaults off, controlled by the edge_types argument to to_html or the GRAPHIFY_EDGE_TYPES env var via _edge_types_default; the panel is suppressed entirely on aggregated community meta-graphs where the "relation" is just a weight label. Also scopes the community show/hide-all handlers to #legend so the new panel's reused .legend-* classes aren't clobbered, and sanitizes/falls back empty relation labels to unknown.
No blocking issues surfaced. 6 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 406 functions depend on the 135 functions this change touches.
Health — this change adds coupling hotspots:
- new:
_rebuild_code()— 98 callers, 50 callees - new:
dispatch_command()— 2 callers, 122 callees - new:
to_html()— 20 callers, 12 callees - new:
run_pipeline()— 8 callers, 13 callees - new:
watch()— 5 callers, 7 callees - new:
_reconcile_graph_html()— 6 callers, 5 callees - new:
test_poisoned_manifest_is_healed()— 0 callers, 6 callees
Verification — 406 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 156 function(s) in the blast radius were not formally verified this run
Formal verification
Behavior changes: \_html\_script changes behavior, here is the input that shows it.
The verifier found a concrete input on which \_html\_script behaves differently before and after the change. If that change is intended, ship it; if not, this is your bug.
Guarantee: This difference was REPRODUCED, the verifier actually ran both versions on that input and saw them disagree. It is real, not an artifact.
Evidence: On input \{"nodes\_json":"''","edges\_json":"''","legend\_json":"'\\\\x00'"\}, the old code produced '\<script\>\\nconst RAW\_NODES = ;\\nconst RAW\_EDGES = ;\\nconst LEGEND = \\x00;\\n\\n// HTML\-escape helper — prevents XSS when injecting graph data into innerHTML\\nfunction esc\(s\) \{\\n return… but the new code produces '\<script\>\\nconst RAW\_NODES = ;\\nconst RAW\_EDGES = ;\\nconst LEGEND = \\x00;\\nconst SHOW\_EDGE\_TYPES = false;\\nconst EDGE\_TYPES\_COLOR\_DEFAULT = false;\\n\\n// HTML\-escape helper — prevent…. Paste that input straight into a regression test.
Behavior changes: \_html\_styles changes behavior, here is the input that shows it.
The verifier found a concrete input on which \_html\_styles behaves differently before and after the change. If that change is intended, ship it; if not, this is your bug.
Guarantee: This is a sound refutation from a mathematical proof (SMT solver, over a bounded input domain): a concrete input on which the two versions provably differ.
No difference found (not proven): No behavior difference found in to\_html (not a proof).
The verifier ran both versions of to\_html on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.
Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.
Note: An input the sampler did not try could still differ.
· 7 more finding(s) on lines outside this diff (see the check run).
Summary
Fixes #2088.
graph.htmldrew every edge the same, so you had to hover to tellcallsfromcontains/imports. Adds a Connection Types panel next to the community legend: colour swatch, count, checkbox per relation. Colouring is off by default (localStorage+GRAPHIFY_EDGE_TYPES/edge_types=to start on). Untick everything butcallsand you get the call graph.Also scopes
toggleAllCommunitiesto#legendso a second panel cannot get its checkboxes rewritten. Skipped on the aggregated >node-limit view.Test plan
graph.html— Connection Types panel present, edges look like before until you enable colouringcontains/imports— call graph readablelocalStorageuv run pytest tests/test_export.py -q -k to_html