Skip to content

fix(search): index grep symbols by file path - #705

Open
pei711 wants to merge 1 commit into
trailhq:mainfrom
pei711:fix/702-index-grep-symbols-by-file-path
Open

pei711 wants to merge 1 commit into
trailhq:mainfrom
pei711:fix/702-index-grep-symbols-by-file-path

Conversation

@pei711

@pei711 pei711 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

grepGraph scanned every graph node once per indexed file while assigning hits to symbols. This builds a symbol-span index by path once per query and reuses each file's bucket, preserving existing grouping with linear graph lookup.

Validation: node --import tsx --test test/search-grep.test.ts (14 passed), node_modules/.bin/tsc -p tsconfig.json --noEmit, and git diff origin/main...HEAD --check passed. Ubuntu CI and Node 24 checks pass. Windows CI has one unrelated failure in unchanged test/skills-prompt-attacks.test.ts:197 (4,000 passed, 98 skipped); the branch changes only the grep implementation and its test. The local full suite also could not build three native grammar checks because make is unavailable and had two unrelated baseline assertion failures.

Closes #702.

@trailhq-graft

trailhq-graft Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

🌱 graft blast radius

1 area changed → 4 areas can be affected. 7 dependent symbols, depth 2.
Tests: 1 area updated its tests.
Tag: @shhdwi — 5 of 5 areas · @anirudhkumar-nanonets — 4 of 5 areas · @qoole — Workspace Grep

flowchart TB
  A0(("Tool Invocation<br/>3 symbols"))
  A1(("Workspace Grep<br/>2 symbols"))
  A2(("CLI Entry Point<br/>1 symbol"))
  A3(("Grep CLI<br/>1 symbol"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1,A2,A3 reached;
Loading
Can be affected Symbols Nearest hop Reached from
Tool Invocation 3 src/mcp/tools.ts:L250-L336 callSingleTool — calls, depth 1 Graph Search
Workspace Grep 2 src/graph/workspace.ts:L564-L604 federateGrep — calls, depth 1 Graph Search
CLI Entry Point 1 src/cli.ts:L1-L2705 cli.ts — calls, depth 2 Graph Search
Grep CLI 1 src/search/grep-cli.ts:L95-L127 runGrepCommand — calls, depth 1 Graph Search
Who knows this code — 3 people across 5 areas
Area Who knows it
Graph Search · changed @anirudhkumar-nanonets — 3 commits, last 3mo ago · @shhdwi — 2 commits, last 4d ago
Tool Invocation · affected @shhdwi — 17 commits, last 5d ago · @anirudhkumar-nanonets — 8 commits, last 6d ago
Workspace Grep · affected @shhdwi — 8 commits, last 13d ago · @qoole — 3 commits, last 5d ago
CLI Entry Point · affected @anirudhkumar-nanonets — 61 commits, last 5d ago · @shhdwi — 47 commits, last today
Grep CLI · affected @anirudhkumar-nanonets — 5 commits, last 6d ago · @shhdwi — 4 commits, last 13d ago

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

All 7 dependent symbols, grouped by area

Tool Invocation — 3 symbols in 1 file

  • src/mcp/tools.ts:L250-L336 — callSingleTool (calls, depth 1)
    309: const body = renderMatches(direction, depth > 1, matches, (m) => byId.get(m.id) ?? []);
  • src/mcp/tools.ts:L156-L202 — callWorkspaceTool (calls, depth 2)
  • src/mcp/tools.ts:L219-L247 — callTool (calls, depth 2)

Workspace Grep — 2 symbols in 2 files

  • src/graph/workspace.ts:L564-L604 — federateGrep (calls, depth 1)
    579: const r = grepGraph(graph, join(root, child), pattern, {
  • src/graph/workspace-cli.ts:L115-L132 — runWorkspaceGrep (calls, depth 2)

CLI Entry Point — 1 symbol in 1 file

  • src/cli.ts:L1-L2705 — cli.ts (calls, depth 2)
    728: console.log(` ${rel}/ is git-ignored (added automatically), a local cache; teammates run \`${cmd("graft build")}\` to get their own.`);

Grep CLI — 1 symbol in 1 file

  • src/search/grep-cli.ts:L95-L127 — runGrepCommand (calls, depth 1)
    106: result = grepGraph(graph, root, pattern, { ignoreCase: opts.ignoreCase, fixed: opts.fixed, in: opts.in });
Test signal per changed area — 1 ✓

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • ✓ Graph Search — 1 of 2 reached · 1 test file changed here: test/search-grep.test.ts
    • not reached: symbolsByPath
4 test suites also reference this code

5 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.

  • test/regression-single-repo.test.ts
  • test/search-user-regexp.test.ts
  • test/utf16-source.test.ts
  • test/workspace.test.ts

graft blast · origin/main...HEAD · depth 2 · 2 changed files

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Oct 27, 2026

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.

graft grep / graft_find_all is O(files × nodes): symbolsOf rescans the whole graph per file

1 participant