Skip to content

Orbit Graph — Vision

Mirrored from docs/design/orbit-graph/3_vision.md. Edit the source document in the repository, not this generated page.

Forward-looking design space for orbit-graph. Everything below is hypothesis, not commitment. Items here do not carry task IDs because they are not yet scheduled; if an item lands, the task reference appears in 2_design.md when that doc is updated.

Current contracts and the V1 plan live in 2_design.md and GRAPH_SPEC.md.


The most consequential follow-on. V1 is read-only; agents edit files via normal tools and the graph reflects the result. A writeable graph would let agents perform structural edits at the graph level — rename across all resolved callers, replace a function body, move a symbol between files — and have the graph compile those edits into source patches.

A sketch of the V2 shape (pulled from the previous GRAPH_DESIGN.md, folded into this section on 2026-05-24):

Source files
│ extract (orbit-graph-extract)
Graph (SQLite, derived)
│ overlay (in-memory WorkingGraph)
Working Graph (per-process, ephemeral)
│ compile (patch compiler)
Source Patches
│ commit (atomic temp-file + rename)
Source files (modified)

Five named transitions; each lives in one module. The V1 read model is deliberately compatible: per-worktree DB, qualified-name resolution, ephemeral symbol IDs all carry forward without a schema break.

V2 edit set (proposed):

OperationPayloadCompiles to
Renametarget, new_nameReplace identifier at definition + every resolved reference
ReplaceBodytarget, new_bodyReplace text between the symbol’s body span
DeletetargetRemove symbol span; warn on remaining references
InsertAfteranchor, sourceInsert text after the anchor’s end span
Movetarget, dest_fileDelete from source, insert into dest, update imports

V2 concurrency model (proposed): optimistic, file-grained, no locks. Two agents stage independent edits; on commit, each verifies the affected files’ content_hash hasn’t shifted since extraction. First commit wins; the second is rejected and the agent re-plans against fresh state. Working graphs are in-memory and never collide because they’re per-process.

Open V2 questions:

  • How are edits exposed to non-Rust callers? An MCP orbit.graph.stage / orbit.graph.commit pair is the obvious surface, but the payload shape for Rename vs ReplaceBody differs enough that one tool with a union type may be awkward.
  • Should the working graph be persistable across processes? V1’s answer is no — ephemeral, per session. But agents on long tasks may want to stage many edits and commit at the end of the session.
  • Cross-language renames are out of V2’s scope. A Rust symbol’s TypeScript binding stays untouched unless V3 adds cross-language refs (§1.2).

A Rust function called from TypeScript via N-API or napi-rs is two unrelated nodes in V1. Possible approaches: a pluggable “reference provider” trait with LSP as one backend, or a smaller specific-purpose binding-extractor that recognizes a handful of FFI patterns (napi-rs #[napi] macros, neon cx.export_function, pyo3 #[pyfunction]). The smaller targeted approach is more aligned with the structural-only ceiling V1 sets.

search is FTS5 only in V1 — fast, deterministic, exact-string. A semantic overlay (vector embeddings of symbol docstrings + signatures) would help with intent-shaped queries like “where do we rate-limit requests?” Storage is the easy part; the harder questions are which embedding model is acceptable to ship, and how to express the union of FTS + semantic results without surprising agents who expect exact-match behaviour.

If five worktrees on the same machine share unchanged files, V1 re-extracts five times. A shared content-addressed cache layer (keyed on blake3(file_bytes) || extractor_version) could deduplicate; the cost is reintroducing some of the complexity V1 deleted. Worth doing only if multi-worktree users complain.

notify has known issues on Linux with mass-rename operations (e.g. git checkout of a branch that moved 100 files). V1’s hard freshness barrier is explicit sync; watcher errors schedule a conservative auto sync, and SyncPolicy::Windowed remains available only for callers that cannot run a watcher. We should still measure stale-result reports and event-miss patterns.

V1 expects the MCP server to keep a Graph handle open across calls (5ms per-call open cost is significant on a hot tool). Worth benchmarking: does the open handle accumulate cost over a long session (SQLite page cache, file descriptors)? Recycling on a TTL would be a safety valve if so.

KnowledgePack in orbit-knowledge mixes query, budget, and prompt assembly. Lifting it into a separate orbit-context crate is the right shape — orbit-graph stays a query API, orbit-context owns budget-shaped output for prompt windows. Out of scope for the V1 migration, but the seam is preserved (the public Rust API in 2_design.md §8 returns structured types, not prompt-shaped strings).


  • orbit-knowledge is the immediate predecessor and the system being replaced. Its design is documented at docs/design/knowledge-graph/. The V1 spec (GRAPH_SPEC.md§1) enumerates the specific failures driving the rewrite.
  • orbit-search is the cross-cutting search surface that fronts task / doc / learning / ADR queries. orbit graph search should plug into the same retrieval shape so agents don’t learn two query languages.

Not pursued. LSP servers are stateful, process-local, and tuned for IDE UX (hover text, rename previews) rather than token-efficient prompt assembly. Reusing rust-analyzer or tsserver as a backend would bring in heavy dependencies, stateful daemons that complicate the per-worktree model, and result shapes designed for humans. The structural ceiling that tree-sitter imposes is the right trade for an agent-facing index — what we don’t know is honestly modeled by the confidence ladder.

SCIP (Sourcegraph’s code intelligence index) is a precedent for “treat code intelligence as a derived, regenerable index.” Orbit Graph differs by being per-worktree rather than cross-repo, by skipping precise type-aware analyses in favour of the confidence ladder, and by integrating with agent skill workflows rather than a code-search UI.

Tree-sitter itself is the parsing backbone in both V1 and V2.

The reframe in GRAPH_SPEC.md §2 — “the graph is a derived index, not a source of truth” — borrows from git’s own model: blobs are immutable, refs are cheap pointers, and any working tree can be reconstructed from the object database. Orbit Graph reuses the shape (one SQLite file = one snapshot, regenerable from disk) without reusing the mechanism (no objects, no refs, no merge model).


  • Per-worktree DB as the concurrency model. Most code-intelligence systems are workspace-scoped and pay for locking or transactional coordination. Per-worktree state plus WAL is a structurally simpler answer that fits agent workflows (worktree-per-task is already the norm in Orbit).
  • Confidence as schema. Most graphs treat ambiguity as a footnote — “results may be approximate.” Encoding exact / import_resolved / same_module / fuzzy_name as a column with a documented ordering lets agents make filtering decisions explicit instead of hoping the underlying index made the right call.
  • Structural-only ceiling, honestly drawn. Refusing trait dispatch / macro expansion / cross-language resolution in V1 (and saying so loudly in the contract) means the parts we do promise are reliable. Agents that need ground truth fall back to rg; the graph doesn’t try to be a compiler.
  • Selector grammar as a stable public surface. The selector parser lives in the extract crate, not the storage crate, so it survives storage redesigns. Skills can address symbols by selector across V1, V2, and beyond.


  • [ORB-00377] moved watcher-backed graph reads from open question to the V1 design contract; the remaining watcher concern is operational reliability measurement.

Resolve any task above with orbit task show <ID> or git log --grep=<ID>.