Skip to content

fix(export): colour and filter graph.html edges by relation - #2237

Open
SyedFahad7 wants to merge 2 commits into
Graphify-Labs:v8from
SyedFahad7:fix/2088-graph-html-edge-styles
Open

fix(export): colour and filter graph.html edges by relation#2237
SyedFahad7 wants to merge 2 commits into
Graphify-Labs:v8from
SyedFahad7:fix/2088-graph-html-edge-styles

Conversation

@SyedFahad7

Copy link
Copy Markdown
Contributor

Summary

Fixes #2088.

graph.html drew every edge the same, so you had to hover to tell calls from contains / 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 but calls and you get the call graph.

Also scopes toggleAllCommunities to #legend so a second panel cannot get its checkboxes rewritten. Skipped on the aggregated >node-limit view.

Test plan

  • Open a normal graph.html — Connection Types panel present, edges look like before until you enable colouring
  • Enable colouring; untick contains / imports — call graph readable
  • Reload — colouring preference sticks via localStorage
  • Aggregated community view — no Connection Types panel
  • uv run pytest tests/test_export.py -q -k to_html

Copilot AI review requested due to automatic review settings July 27, 2026 12:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 localStorage and GRAPHIFY_EDGE_TYPES / to_html(edge_types=...).
  • Scope toggleAllCommunities DOM queries to #legend to 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.

Comment on lines 483 to +487
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,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@cursor
cursor Bot force-pushed the fix/2088-graph-html-edge-styles branch from 0b4c21c to 6de98d9 Compare August 28, 2026 23:55

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

graph.html: no way to tell calls from imports/contains at a glance

2 participants