Code graph

Four queries over the workshop's own index — precise for Go, heuristic elsewhere, with a confidence on every edge.

What it is#

Four questions the index can answer, each with an agent tool and a human command.

Question MCP tool Human command Answers with
Show me this function's body code_snippet orch symbols snippet <name> {symbol, start_line, end_line, body, file_bytes}
Who calls it, and what does it call? trace_path orch symbols trace <name> {root, nodes, edges}, a confidence per edge
What does this change break? impact orch symbols impact [path...] {paths, touched, callers, edges}
What does this repo look like? architecture orch symbols arch {dirs, edges} by directory

trace_path takes an optional direction (callers, callees or both) and a depth from 1 to 5, defaulting to 2. impact with no arguments reads your own checkout's changes; give it paths[], a symbol, or a git_range to ask about something else. code_snippet returns at most max_lines lines, 120 by default.

Your own code is always readable#

The caller's project comes from its session — a dispatched worker's seat names both its project and its worktree — or, for a Chair, from the project argument or cwd. The index stores a path relative to the root that indexed it plus the project it belongs to, never an absolute path, so one index answers the Chair from the project checkout and a worker from its worktree. All four tools return local (untagged) symbols there.

"Shared symbols only" is a rule about crossing a boundary, not about reading your own checkout: only project: naming a different project is limited to orch:export symbols, and an unpublished one is refused in as many words.

Every reply has a ceiling#

A reply is tokens paid for on the turn it arrives and on every turn it stays in context, so each tool has a hard byte budget and degrades into it instead of overflowing:

Tool Ceiling Gives up, in order
trace_path 2,000 B edges, then all but the five best-ranked nodes, then a hint
impact 3,000 B edges, then hop-2 callers, then a hint
architecture 4,000 B edges, then the top-symbol list, then a hint
code_snippet body + 200 B the body itself is capped at 6 KB above max_lines

Rows are ranked by how many references point at them and capped at limit (20 by default); a capped list carries has_more: true and a cursor to resume from. verbose: true returns the full uncapped shape. A name that misses answers {found: false, hint, did_you_mean} — never a raw error, because a raw error is what sends an agent back to grep.

Why it exists#

Reading a whole file to find one function is the most expensive habit an agent has. A snippet by line range costs a fraction of it, and a call graph answers "who else uses this?" in one round-trip instead of a dozen greps. Orchemax already parses every file it indexes, so the graph is a by-product rather than a second tool to install and keep in sync.

Precise for Go, heuristic elsewhere#

Every edge carries a confidence, and the number is the honest part:

Confidence How the edge was resolved
1.0 The Go resolver matched an import, or the file itself
0.7 The Go resolver matched a receiver type
0.4 The generic tokenizer matched a bare Name( against the symbol table of the same language

So Go is precise and the other twenty-eight langspec languages are heuristic — a 0.4 edge is a plausible call, not a proven one. A name that resolves to no indexed symbol is dropped rather than stored, so a traversal never walks into a dangling edge.

  Go source ---> go/ast resolver ---> edges at 1.0 / 0.7
  other langs -> langspec regex   ---> symbols, then tokenizer edges at 0.4
                     |
                     v
              symbol_refs table  --> trace_path / impact / architecture

What it does not see#

The index sees symbols with a signature — functions, types, methods, classes. It is blind to constants, table names, schema flags and any name that lives inside a string. For those, grep is still the right tool. An empty result is a real answer, not a failure: it means no match, so you may create the thing locally — but do not invent a duplicate of a name you already know is shared.

How it relates to the rest#

  • The index is the same one the shared code law populates: shared scope for tagged symbols, local for everything else. Search answers shared only; the graph reads both.
  • code_snippet and trace_path record the bytes they returned against the size of the file they stood in for. Those totals surface as a graph block in orch usage, content-free.

Nothing to run here#

The graph is queried, not built: registering and indexing a folder fills it. orch index re-scans the whole workspace — every registered project and shared path, and orch inventory checks those folders against what the index actually holds.