Repository navigation
feat(html): add Hide orphans toggle to graph.html - #4863
afrianluthfan wants to merge 1 commit into
Conversation
Adds a "Hide orphans" checkbox next to Select All in the Communities panel. When checked, nodes with degree 0 in the rendered graph are hidden. Community filtering and the orphan toggle now share one predicate, isNodeHidden(), so re-showing a community keeps its orphans hidden while the toggle is on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for the pull request, @afrianluthfan. A maintainer will review it soon. Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions. A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic. |
There was a problem hiding this comment.
Graphify reviewed this change.
No issues found by static checks — no coupling regressions or blocking issues in the code graph. That is not the same as safe to merge: see what was not checked.
Not checked: tests were not run; formal verification proved 0 of 3 changed function(s) (1 sampled, not proven).
Formal verification. 2 change(s) alter behavior, breaking input(s) attached. PR-changed functions: 3/3 verified (0 proven, 1 may-equivalent, 2 distinguished) · 0 not verified.
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;\\n\\n// HTML\-escape helper — prevents XSS when injecting graph data into innerHTML\\nfunction esc\(s\) \{\\n return…. 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 a "Hide orphans" checkbox to the graph.html legend controls, off by default, that hides nodes with zero edges in the rendered graph. Community visibility now goes through a single isNodeHidden predicate (community filtered out, or orphan with the toggle on), so the Select All and per-community checkboxes no longer un-hide orphans while the toggle is active. New tests check the checkbox's default state, the zero-degree values in the rendered node data, and that every visibility update uses the shared predicate.
No blocking issues surfaced. 1 lower-confidence candidate did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 519 functions depend on the 19 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
to_html()— 31 callers, 11 callees
Verification — 519 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: 81 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
8 of 470 test file(s) selected (2%) via static blast radius.
tests/test_export.py— impacttests/test_export_direction.py— impacttests/test_html_hide_orphans.py— impact, changed-testtests/test_html_script_breakout.py— impacttests/test_html_theme.py— impacttests/test_labeling.py— impacttests/test_pipeline.py— impacttests/test_watch.py— impact
Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.
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;\\n\\n// HTML\-escape helper — prevents XSS when injecting graph data into innerHTML\\nfunction esc\(s\) \{\\n return…. 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.
· 1 more finding(s) on lines outside this diff (see the check run).
What does this PR do?
Adds a "Hide orphans" checkbox to
graph.html, next to "Select All" in the Communities panel. When checked, nodes with degree 0 in the rendered graph are hidden. It is off by default, so the default output looks the same as before.Community filtering and the new toggle both set the vis
hiddenflag, so they now share one predicate,isNodeHidden(n):The per-community checkbox and
toggleAllCommunities()callisNodeHidden()and no longer writehidden: !cb.checked/hidden: hidedirectly. Without this, re-showing a community would un-hide its orphans while the toggle is on.Hyperedge hulls already skip hidden nodes (
network.getPositionsreturns nothing for them), so they need no change.Type of change
Verification & Invariants
Visibility is one function of (community filter state, orphan toggle state). Toggling either control in any order gives the same result. The default render is unchanged apart from the new unchecked control.
Limitations:
to_html. A node whose only edge is a self-loop has degree 2 and stays visible.How was this tested?
tests/test_html_hide_orphans.py(3 tests): orphan degree inRAW_NODES, checkbox present and unchecked by default, and every visibility update goes throughisNodeHidden(). 2 of the 3 fail onupstream/v8.I also checked it manually in headless Chromium (Playwright) on a 12-node graph with two orphans. Toggle on hid exactly the 2 orphans. They stayed hidden after a community off/on and after Select All off/on. Toggle off showed everything again.
The 8 failures are in
tests/test_ext_tagged_id_clash.pyandtests/test_skill_no_backtick_substitution.py. They fail the same way on a cleanupstream/v8checkout in my environment, so they are unrelated to this change.Graphify-specific checklist
uv run python -m tools.skillgen --bless) when changing their source fragments. (Not touched.)🤖 Generated with Claude Code