fix(markdown): stop a bare word from linking to a lone method by lab1207 · Pull Request #4616 · Graphify-Labs/graphify · GitHub
Skip to content

fix(markdown): stop a bare word from linking to a lone method - #4616

Open
lab1207 wants to merge 2 commits into
Graphify-Labs:v8from
lab1207:fix/bare-mention-not-a-method
Open

lab1207 wants to merge 2 commits into
Graphify-Labs:v8from
lab1207:fix/bare-mention-not-a-method

Conversation

@lab1207

@lab1207 lab1207 commented Oct 21, 2026 •

Copy link
Copy Markdown

What

A parenthesis-less code span in Markdown no longer resolves to a lone method on an unrelated class.

The bare-mention branch of resolve_markdown_mentions matched any single callable carrying the label, and a method's _symbol_label drops the leading dot (Client.render → render). So prose like `redis` or `data` linked to a method the sentence never named, producing a bogus INFERRED (0.95) references edge:

`redis` the server  ──references──▶  Client.redis()   # wrong

Fix

For a bare, qualifier-less mention, a method candidate is kept only when one of the method's owner classes is itself named in the same document — the primary proposal in #4609, which preserves successWithWarnings written beside HandlerResult. The span text already rides in context, so the resolver distinguishes redis from redis(); a real call site writes the parentheses and is unaffected. A bare word still resolves to a free function or a class.

  • graphify/markdown_resolution.py: in the bare branch, filter out method candidates whose owner class is not named; add _owning_class / _owner_is_mentioned helpers, and a per-document set of the names each document cites.
  • tests/test_markdown_code_spans.py: three regression tests — a bare word does not resolve to a lone method (and a paren call still does), a method stays resolvable when its owner class is named alongside it, and a class named in a different document does not keep the edge.

Verification

I could not collect the graphify test suite here: the environment has no tree_sitter, so import graphify.extract fails at collection. This is a pre-existing environment gap, not related to the change; CI is the judge.

To verify the resolver rule itself, I drove resolve_markdown_mentions directly with a stub tree_sitter and hand-built nodes/edges matching what extract emits (a _callable_class class, a method owned via a method edge, and a free function):

  • lone method + paren-less bare word → no edge ✅
  • lone method + redis() (parens) → edge ✅
  • lone method + owner class named alongside it → edge ✅
  • owner class named in a different document → no edge ✅ (this one failed before the per-document scoping, and the regression test covers it)

AI authorship

Prepared with MiniMax M3.1 Flash Free via the opencode agent harness (minimax-m3.1-flash-free).

Closes #4609.

A parenthesis-less code span (`redis`, `data`) resolved to any single
callable carrying that label, including a method owned by an unrelated
class. The result was a bogus INFERRED `references` edge from the prose
to a method the sentence never named: `redis` the server linked to a lone
`redis()` on `Client`.

A bare, qualifier-less mention now keeps a method candidate only when one
of the method's owner classes is itself named in the same document
(`successWithWarnings` written beside `HandlerResult` keeps its edge);
`redis` with no owner cited does not. The span text in `context` tells
`redis` from `redis()`: a real call site writes the parentheses and is
unaffected. A bare word still resolves to a free function or a class.

Closes Graphify-Labs#4609.
@lab1207
lab1207 requested a review from safishamsi as a code owner October 21, 2026 06:44
@github-actions

Copy link
Copy Markdown

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

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Not checked: tests were not run; formal verification proved 0 of 1 changed function(s) (1 sampled, not proven).

Formal verification. PR-changed functions: 1/1 verified (0 proven, 1 may-equivalent, 0 distinguished) · 0 not verified.


Graphify review — findings

Tightens markdown mention resolution so a bare, parenthesis-less word like redis no longer links to a lone redis() method on an unrelated class. The method match survives only when its owning class is also named among the mentions (HandlerResult beside successWithWarnings), and free functions, classes and any name() call written with parentheses resolve as before. The owner check builds its set of cited names in resolve_markdown_mentions from all mentions, so the "named alongside it" test can be satisfied by a class cited in a different document rather than only the citing one.

Worth a look

  • Owner-class mention set spans every document, not just the citing one — graphify/markdown_resolution.py:200 · Escalate · medium
    • NOT verified (no proof, no reproducing execution) — needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 465 functions depend on the 39 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: resolve_markdown_mentions() — 1 callers, 9 callees

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

Test selection

Test selection

2 of 436 test file(s) selected (0%) via static blast radius.

  • tests/test_markdown_code_spans.py — impact, changed-test
  • tests/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.

Docs that may be stale (advisory)

…and 10 more.

Formal verification

No difference found (not proven): No behavior difference found in resolve\_markdown\_mentions (not a proof).

The verifier ran both versions of resolve\_markdown\_mentions 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).

The set of names a document cites was built from every mention in the
corpus, so a class named in a different document could satisfy the
owner check for a bare method name here. Scope it per document: the
owner class has to be named in the document that cites the method.
@lab1207

lab1207 commented Oct 21, 2026

Copy link
Copy Markdown
Author

This branch has not been deployed

No deployments
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.

[Bug]: markdown mentions: a bare lowercase word in a code span links to an unrelated method that carries that name

1 participant