Skip to content

Fan-in queries are blind to markdown and shell references #1831

Description

@cdeust

What problem does this solve?

Markdown docs and shell scripts reference other repo files constantly: a coding-standards doc links the modules it governs, a script sources a helper library or invokes a sibling tool. None of that becomes graph edges today. CBM_LANG_MARKDOWN exists in language detection (src/discover/language.c) but no pipeline pass consumes it, and shell files get no reference extraction either.

Concrete, reproducible case on a public repo: cdeust/zetetic-team-subagents (Shell Markdown heavy). The two most-referenced files there are rules/coding-standards.md (173 references from other files) and tools/memory-tool.sh (171), both counted by exact grep. Both have zero inbound edges in the graph, so a "which file has the highest fan-in" question gets answered with a Python file instead, an undershoot of roughly 17x, delivered with citations. I hit this in an A/B retrieval benchmark I ran in August with independently verified scoring: the failure mode is "grounded but wrong", and it is invisible from inside a session.

Proposed solution

A pre-dump pass modeled on pass_configlink.c (same shape: strategies with per-strategy confidence, operating on the graph buffer before dump), emitting REFERENCES_FILE edges between existing File nodes only. Unresolvable targets are dropped, the pass never invents nodes. Targets resolve against the referencing file's directory and the repo root; repeated references between the same file pair collapse into one edge carrying strategy, confidence and count.

To respect the 500-line PR guidance I split the work into two reviewable increments, both implemented and tested on my fork:

  1. Markdown (cdeust/codebase-memory-mcp branch feat/doclinks-markdown): inline links, backtick paths, bare path mentions, plus the shared infrastructure (path normalization, resolution, dedupe) and pipeline/incremental registration. Pass is 495 lines, tests 313 mirroring test_configlink.c (real files in a tmpdir, File nodes in a gbuf, assert edges).
  2. Shell (branch feat/doclinks-shell, stacked on 1): source path / . path lines and repo-relative script invocations, 218 lines including tests.

Validation on both: scripts/build.sh clean; focused serial runner (doclinks, configlink, pipeline, edge_structural, lang_contract suites) green under ASan/UBSan (340 and 342 tests respectively); cppcheck clean on the new files with the repo's flags; commits DCO signed-off. Good public test beds: cdeust/zetetic-team-subagents for the extreme case, and this repository itself (README/CONTRIBUTING link real files, scripts/ sources helpers).

One open question: is REFERENCES_FILE the right edge type name for you, or would you rather fold it into an existing kind? Happy to adjust before opening PR 1.

Alternatives considered

  • Full markdown symbol extraction (heading nodes, doc sections): heavier, different question; file-level reference edges are what fan-in needs and stay cheap.
  • Treating this in query-land (e.g. grep at question time): loses the persistent-graph advantage and doesn't fix fan-in answers.
  • A tree-sitter markdown grammar pass: overkill for link extraction; the vendored grammar set doesn't need to grow for this.

Confirmations

  • I searched existing issues and this is not a duplicate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestparsing/qualityGraph extraction bugs, false positives, missing edges

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions