Skip to content

fix(report): wrap labels in code spans so identifiers don't trip markdown linters (#3147) - #3267

Open
yotamleo wants to merge 1 commit into
Graphify-Labs:v8from
yotamleo:fix/report-wrap-labels-in-code-spans
Open

fix(report): wrap labels in code spans so identifiers don't trip markdown linters (#3147)#3267
yotamleo wants to merge 1 commit into
Graphify-Labs:v8from
yotamleo:fix/report-wrap-labels-in-code-spans

Conversation

@yotamleo

@yotamleo yotamleo commented Sep 1, 2026

Copy link
Copy Markdown

What

graphify/report.py emits node/community/hyperedge labels as bare text at
four sites in GRAPH_REPORT.md, even though every other section in the same
file (God Nodes, Ambiguous Edges, Import Cycles, the isolated-node list)
already wraps labels in backticks. When a corpus has snake_case identifiers
(_scan_redirects, my_var_name), the generated report contains raw
intraword underscores outside any code span. Markdown linters flag those as
unbalanced emphasis — on the exact identifier text a reader needs in order to
look the node up. This is visible today in the repo's own tracked worked
example, worked/httpx/GRAPH_REPORT.md:

### Community 5 - "Community 5"
Cohesion: 0.28
Nodes (3): build_url_with_params(), flatten_queryparams(), primitive_value_to_str()

Closes #3147.

The fix

Wrapped labels in backticks at the four remaining sites, matching the
God-Nodes/Ambiguous-Edges precedent already in the file:

  1. Community Hubs (Navigation), non-Obsidian branch — the community label.
  2. Hyperedges — the hyperedge's own label/id (bolded), and each node label
    in its member list (wrapped per-item and joined, not one span around the
    whole comma-joined string).
  3. Community heading (### Community N - "label") — the label, nested
    inside the existing quotes.
  4. Communities node list (Nodes (N): ...) — each label wrapped
    individually before joining.

Nothing else changed — no refactor, no touching of the sites that already
wrap.

Judgment calls

  • Community heading (site 3). Backticks inside a markdown heading are
    legal and render as code; the alternative the issue raises is
    backslash-escaping the underscore instead. I went with backticks because
    it's the convention already used everywhere else in this file, and
    backslash-escaping would be a second, inconsistent escaping style. I
    grepped the codebase (including wiki.py and the Obsidian/HTML exporters)
    for anything that parses ### Community ... back out of the generated
    report — nothing does. tests/test_report_gap_thresholds.py only regexes
    the "### Community " prefix to count sections, which is unaffected by
    what follows it. Happy to switch to escaping if a maintainer prefers it for
    heading readability.
  • Hyperedges (site 2). Nested the label's backticks inside the existing
    bold (**\label`**) rather than replacing bold with code — this is also needed for the id-fallback case (h.get('label', h.get('id', ''))`), since
    hyperedge ids are frequently snake_case themselves. The node list is
    wrapped per-label and then joined, not wrapped as a single span around the
    whole string, so linters don't see one giant token.
  • Labels containing a backtick. None of the existing wrapped sites in
    this file (God Nodes, Ambiguous Edges, isolated nodes) escape an embedded
    backtick either, so this fix doesn't invent new escaping machinery for that
    case — it matches the existing house style and has the same limitation.
  • worked/httpx/GRAPH_REPORT.md. This tracked example still shows the
    old, unwrapped output. I checked .github/workflows/ and found no job that
    regenerates or diffs the worked/ examples (the skillgen-check job only
    validates generated skill files under graphify/; release-graph.yml
    builds a fresh self-graph, not the worked/ fixtures). So I left it
    untouched rather than regenerating an artifact nothing checks.

Verification

Wrote the regression tests first and confirmed they failed against a pristine
origin/v8 checkout (33362d9):

uv run --frozen pytest tests/test_report.py -q
# 6 failed, 15 passed

(One of the six was an existing test, test_report_hubs_are_plain_text_by_default,
whose assertion had to be updated in place — it pinned the exact pre-fix
unwrapped hub-label string.)

After applying the fix, the same file is green:

uv run --frozen pytest tests/test_report.py -q
# 21 passed

Scoped suite:

uv run --frozen pytest tests/test_report.py tests/test_report_gap_thresholds.py -q
# 25 passed

Full suite, fix branch vs. a pristine origin/v8 checkout (Windows machine;
pre-existing failures are symlink-privilege, cp1252-console and missing
optional-dependency tests unrelated to this change):

fix branch:     17 failed, 5255 passed, 43 skipped
pristine v8:    17 failed, 5250 passed, 43 skipped

diff of the two FAILED line sets (sorted) is empty — the same 17 tests
fail on both, byte-for-byte. Zero introduced, zero fixed. The 5-test gap in
the passed count is exactly the 5 new tests this PR adds.

Lint:

uv run --frozen ruff check graphify/report.py    # All checks passed!
uv run --frozen ruff check tests/test_report.py  # All checks passed!
uv run --frozen python -m tools.skillgen --check # check OK: 134 artifact(s) match

…down linters (Graphify-Labs#3147)

Four sites in GRAPH_REPORT.md emitted node/community/hyperedge labels as
bare text while every other section (God Nodes, Ambiguous Edges, Import
Cycles, the isolated-node list) already wraps labels in backticks. A
corpus with snake_case identifiers produced raw intraword underscores
outside any code span, which markdown linters flag as unbalanced
emphasis on the exact identifier text a reader needs to look the node up.

Wrapped labels at the four remaining sites to match the file's existing
convention: the Community Hubs list, both the hyperedge label/id and its
per-node list, the Community heading, and the Communities node list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@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. No changes could be formally verified in this run.


Graphify review — findings

Wraps the four report sites that emitted bare labels — community hub list items, hyperedge labels and their member nodes, community headings, and per-community node lists — in backtick code spans, matching the other label sites so snake_case identifiers no longer produce intraword underscores that markdown linters flag as unbalanced emphasis. Adds tests covering each site plus the hyperedge id fallback when a hyperedge has no label.

No blocking issues surfaced. 2 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 344 functions depend on the 38 functions this change touches.

Health — this change adds coupling hotspots:

  • new: _rebuild_code() — 113 callers, 50 callees
  • new: generate() — 37 callers, 7 callees
  • new: dispatch_command() — 2 callers, 123 callees
  • new: run_pipeline() — 8 callers, 13 callees
  • new: make_inputs() — 14 callers, 5 callees
  • new: watch() — 5 callers, 7 callees
  • new: load_learning_for_report() — 4 callers, 3 callees
  • new: test_report_shows_avg_confidence_for_inferred() — 0 callers, 7 callees
  • …and 2 more — each is listed as a finding

Verification — 344 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: 179 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify generate.

The verifier did not have enough to check generate, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 200 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly ValueError — names the real obstacle, not a sampling gap)

· 10 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_REPORT.md: community and hyperedge labels emit unescaped underscores outside code spans

1 participant