{
  "access": "public",
  "type": "reference",
  "format": "markdown",
  "title": "Manifold: A Token-Efficient Coding Agent",
  "url": "https://labs.datagrout.ai/papers/manifold",
  "summary": "Coding agents have converged on an architecture: an LLM-driven loop that searches files, reads code, edits, runs tests, and iterates. It is general but token-expensive and brittle. Most of every turn re-acquires context the agent has already seen, because nothing maintains a queryable model of the codebase; most of its failures are drift: reinventing code that exists, contradicting conventions it never saw, and emitting edits that silently destroy what they touch.\n\nManifold is a coding agent organized around a different primitive. A **node** is a bounded satisfy-loop whose controller is symbolic (a deterministic check decides whether the goal is met and whether to continue) and whose language model is *lateral*: one tool among several, invoked single-shot for the work only it can do. The codebase is lensed once into a Logic Cell, a persistent fact base of functions, calls, and structure, and navigation is queries over those facts. Before writing, an **orient** node asks the fact base what already exists near the goal, so the agent extends rather than reinvents; after writing, a **verify** node runs the project's own checks, and a bounded refine loop repairs failures.\n\nTwo disciplines follow. The model never authors diffs inside the node loop: it emits complete file contents or anchored replacements, and a deterministic layer derives the diff, scoped to the files the agent touched (the MCP `apply_diff` path and the TUI diff-approval path apply externally supplied unified diffs, outside that loop). And the agent never edits the user's tree: work happens in a forked workspace with explicit merge semantics, so every change is inspectable, reversible, and attributable before it lands.",
  "topics": [
    "coding-agents",
    "code-navigation",
    "symbolic-verification",
    "token-economics",
    "prolog"
  ],
  "content_markdown": "## Abstract\n\nCoding agents have converged on an architecture: an LLM-driven loop that searches files, reads code, edits, runs tests, and iterates. It is general but token-expensive and brittle. Most of every turn re-acquires context the agent has already seen, because nothing maintains a queryable model of the codebase; most of its failures are drift: reinventing code that exists, contradicting conventions it never saw, and emitting edits that silently destroy what they touch.\n\nManifold is a coding agent organized around a different primitive. A **node** is a bounded satisfy-loop whose controller is symbolic (a deterministic check decides whether the goal is met and whether to continue) and whose language model is *lateral*: one tool among several, invoked single-shot for the work only it can do. The codebase is lensed once into a Logic Cell, a persistent fact base of functions, calls, and structure, and navigation is queries over those facts. Before writing, an **orient** node asks the fact base what already exists near the goal, so the agent extends rather than reinvents; after writing, a **verify** node runs the project's own checks, and a bounded refine loop repairs failures.\n\nTwo disciplines follow. The model never authors diffs inside the node loop: it emits complete file contents or anchored replacements, and a deterministic layer derives the diff, scoped to the files the agent touched (the MCP `apply_diff` path and the TUI diff-approval path apply externally supplied unified diffs, outside that loop). And the agent never edits the user's tree: work happens in a forked workspace with explicit merge semantics, so every change is inspectable, reversible, and attributable before it lands.\n\n---\n\n## Problem Landscape\n\n### The Grep Tax\n\nA coding agent processing a non-trivial change reads far more tokens than it emits, often by two orders of magnitude, and most of those reads are searches: find references, read the file, re-read the file that was truncated, check the imports, find the tests. Each happens because no layer maintains a queryable structural model of the code; the agent and the file system are the only two layers, and the LLM performs every join between them, every session, from scratch.\n\n### Drift Is the Expensive Failure\n\nToken cost is visible; drift is worse. In a large codebase, an agent that cannot cheaply answer \"does something like this already exist?\" writes a second implementation, a third naming convention, a parallel helper: each plausible alone, collectively corrosive. Drift survives review because each instance looks reasonable in isolation. The root cause is the grep tax: exploring is expensive, so the agent explores less than correctness requires.\n\n### LLM-Authored Diffs Fail Structurally\n\nUnified diffs generated by language models fail to apply at high rates: line numbers drift, context lines are misremembered, and patch formats are corrupted into apply-time errors or, worse, silently wrong hunks. A related failure is the stub rewrite: asked to modify a large file, a model returns a shortened version that drops most of the original. Both are properties of asking a stochastic generator to produce position-sensitive formats.\n\n### Sessions Forget\n\nConventional agents rebuild context every session and compact it mid-session, losing the understanding of prior work. The codebase model, the conversation history, and the record of what was tried all live in a context window whose contents evaporate.\n\n---\n\n## Design Principles\n\n### 1. Lens Once, Query Forever\n\nA codebase is lensed into a Logic Cell by structural analysis: functions, call edges, modules, files, visibility, and line positions become persistent facts. Lensing is incremental: version-control deltas identify which files changed, so re-lensing costs only the delta and renames are tracked rather than re-derived. Once asserted, structural questions (\"what calls this?\", \"what exists near this concept?\") are queries rather than searches, though today's orient step issues one bulk export and matches client-side (see Navigating the Lens).\n\nThe lens is **Invariant**, the engine behind *Consequential Analysis: Semantic Verification of AI-Generated Code*. It parses source with tree-sitter and emits Prolog facts: a `function` per definition carrying its module, name, arity, visibility, and start line; a `module` per file with its qualified name and path; named call edges (`calls_external`) and module dependencies (`depends_on`), with the lensed commit stamped on each fact. Invariant is published on crates.io as `invariant-core` and `invariant-cli` under the Elastic-2.0 license, and its CLI lenses, queries, and intent-checks a repository on its own. Manifold does not shell out to that binary; it depends on `invariant-core` as a library and drives the analyzer in-process, batching the emitted facts into the cell, so nothing needs to be on the user's path. When the platform's `invariant.code_lens` enrichment is reachable, it layers identifier-resolved call edges and semantic facts on the local structural baseline; the navigation rules below read both schemas.\n\n### 2. The Controller Is Symbolic; the Model Is Lateral\n\nA node loops until a deterministic condition is satisfied or a bounded budget is exhausted. The satisfaction check is not a model judgment; for a coding node it is the project's own verify command exiting cleanly. The model is a tool the controller dispatches for generation and interpretation, one call at a time, with the controller deciding what happens next, so cost, termination, and auditability stay in the symbolic layer where they can be guaranteed.\n\n### 3. Orient Before Acting\n\nEvery code turn begins by querying the lens for code related to the goal. Orient distinguishes three situations: not lensed (the agent cannot check, and says so), lensed with nothing similar (safe to add new code), or related code exists (prefer extending it). The intended contract is that all three answers reach the model; today only the occupied case is injected into the generation context, as an explicit instruction to extend rather than reinvent, while the unmapped case reaches the operator log in the CLI and nothing in the MCP path, and the mapped-and-empty case is not injected. This is anti-drift at the moment of authorship, not at review time.\n\n### 4. The Model Never Authors Diffs\n\nGeneration produces end-states: complete file contents, or anchored search/replace edits whose anchor must match exactly once. A deterministic layer applies them, rejects edits whose anchors are missing or ambiguous (feeding the rejection into the next refine round), guards against stub rewrites that would discard most of an existing file, and derives the final diff with the version-control system, scoped to the files the agent wrote, so build artifacts never contaminate the attributed change.\n\n### 5. Work Happens in a Fork\n\nThe agent operates in a workspace forked from the project, never in the user's tree. Merging back is an explicit, moded operation: stage the changes for the user's own commit, commit them, merge with history preserved, or apply them to the target tree as a worktree; exporting a patch is a recipe over the fork, not a mode. Each mode defines what happens to the workspace afterward. Sequential turns stack disjoint staged changes awaiting one human decision; overlapping changes are refused by name.\n\n```mermaid\nstateDiagram-v2\n    [*] --> Forked: clone the project locally, drop remotes, tag manifold-base\n    Forked --> Working: build turns write and commit in the fork\n    Working --> Working: later turns stack on the same fork\n    Working --> Reviewed: review diff from manifold-base to the working tree\n    Working --> [*]: reject, reset to manifold-base\n    Reviewed --> Staged: stage mode, squashed into the index, user commits\n    Reviewed --> Committed: commit mode, one squash commit\n    Reviewed --> Merged: merge mode, agent history kept behind a merge commit\n    Reviewed --> Patched: worktree mode, plain patch, nothing staged\n    Reviewed --> Refused: target already has staged edits to the same files\n    Staged --> Forked: workspace re-forked from committed truth\n    Patched --> Forked: workspace re-forked from committed truth\n    Committed --> Working: manifold-base retagged to HEAD\n    Merged --> Working: manifold-base retagged to HEAD\n```\n\n*The fork is created once, accumulates turns, and leaves only through one of four named merge modes, each of which decides how the workspace is reconciled afterward.*\n\n---\n\n## Architecture\n\n### The Node\n\nA node is the unit of agent work: a goal, a bounded loop, a symbolic controller, and a report. The shipped nodes:\n\n- **orient**: extract goal keywords (with a deterministic fallback requiring no inference), query the lens, and report existing related code with its call graph\n- **verify/refine**: run the project's verify command; on failure, dispatch the model once for proposed edits, apply them under the edit discipline, and re-verify; repeat within an attempt budget\n- **code**: orient, then implement with orient's findings injected, then (where a verify command and workspace exist) verify/refine. This paper calls that composition a build turn. The separate `run` path orients and then orchestrates an agent plan with no verify loop; it is not a build\n\n```mermaid\nflowchart TB\n    goal[\"goal\"] --> orient[\"orient<br/>keywords, then a lens query\"]\n    lens[\"lens facts<br/>functions, calls, files\"] --> orient\n    orient -. \"unmapped: cannot check (operator log; not injected today)\" .-> act\n    orient -. \"mapped and empty: safe to add (not injected today)\" .-> act\n    orient -- \"mapped and occupied: extend these\" --> act\n    subgraph M[\"language model, one call per round\"]\n        act[\"act<br/>emits end-states: full files<br/>or anchored search and replace\"]\n        refine[\"refine<br/>given the failure and<br/>the rejected edits\"]\n    end\n    act --> apply[\"apply<br/>anchor must match once<br/>stub rewrites rejected\"]\n    refine --> apply\n    apply --> verify[\"verify<br/>run the project check\"]\n    verify -- \"pass\" --> diff[\"version control derives the diff<br/>scoped to touched files\"]\n    verify -- \"fail, budget left\" --> refine\n    verify -- \"budget exhausted\" --> unsat[\"unsatisfied<br/>reported, not merged\"]\n```\n\n*One code turn: everything outside the shaded box is the symbolic controller, and the model is dispatched single-shot for authorship only.*\n\nEvery node reports in one intermediate representation, a small vocabulary of events (node started, step with status, fact observed, node finished with a satisfaction verdict), so coding nodes, orientation nodes, and conversational turns render alike in any surface and a composed turn is the concatenation of its parts with costs summed. Today a node returns its events as a finished batch (streaming is next), and the code path's verify report carries its own shape alongside them. The event record is the audit trail.\n\n### Navigating the Lens\n\nLens facts are raw material; navigation is a rule pack over them. The platform ships `manifold_nav`, a Prolog module imported into every Logic Cell, callable from any namespace that holds lensed facts, with reserved names a user rule cannot shadow: position and neighborhood (`nav_file`, `nav_line`, `nav_end_line`, `nav_neighbors`, `nav_outline`), callers and callees resolved through either call-edge schema (`nav_callers`, `nav_callees`, `nav_ext_calls`), bounded impact as a breadth-first walk over callers (`nav_impact`), name search and exact definition lookup (`nav_search`, `nav_def`), module topology (`nav_module_deps`, `nav_module_funcs`, `nav_files`), and rolled-up profiles (`nav_context`, `nav_func_report`, `nav_stats`). None is a search over text; each is a proof over facts already in the cell.\n\n```prolog\n% what already exists near the goal: names containing the keyword, with locations\n?- nav_search(\"invoice\", Ids), maplist(nav_context, Ids, Ctxs).\n% who calls this function: the set that breaks if its contract changes\n?- nav_callers(invoice_total_1, Callers).\n% what it calls: the contracts it depends on\n?- nav_callees(invoice_total_1, Callees).\n% bounded impact: transitive callers within two hops\n?- nav_impact(invoice_total_1, 2, Affected).\n% the file's table of contents, so the edit lands beside its siblings\n?- nav_outline('src/billing/invoice.rs', Sigs).\n% fan-in hotspots: functions with ten or more callers\n?- nav_func(Id), nav_callers(Id, Cs), length(Cs, N), N >= 10.\n% orphans: private functions nobody calls\n?- nav_func(Id), nav_vis(Id, private), nav_callers(Id, []).\n```\n\nThe orient pass turns answers like these into one of three findings. If the namespace holds no lens facts, the project is unmapped and the agent cannot check; if the keyword search returns nothing against a populated lens, the ground is mapped and empty and new code is safe to add; if it returns matches, the ground is occupied, and the matches with their callers and callees are what the agent should extend. Only the occupied finding is injected into the model's context today, as described under Design Principle 3. The queries above are all available through `logic.query` with a Prolog goal; the Rust client's orient step does not issue them yet, instead performing one `logic.export` of the lens-tagged facts and computing the keyword match and one-hop caller and callee lists locally. The broader vocabulary of *Cartographic Navigation* is where this subsection points.\n\n### Two Substrates\n\nManifold operates on two kinds of codebase through one navigation model.\n\n**File codebases** are lensed into facts, and edits flow through the workspace discipline above.\n\n**Reactor applications** are applications whose \"codebase\" *is* a Logic Cell namespace of facts and rules; they need no lens. Reading the code is reflecting on the namespace; modifying it is asserting rules, each validated and certified before admission; testing is querying; deployment is immediate because the facts are the runtime. Only the provenance of the facts differs.\n\n### Building a Reactor Application\n\nA reactor application is a namespace of admitted rules on the substrate of *Logic Cells: A Persistent Prolog Substrate for Governed Agents*, with its interface derived from the same cell rather than written beside it. A rule becomes an endpoint when facts on the rule entity say so: `attribute(Rule, api_exposed, true)` publishes it, and a mode string such as `\"+invoice:atom, -result:list\"` is the contract, binding the `+` arguments from the request and returning the `-` arguments as the response, alongside a verb and an auth posture (`none`, `bearer`, or `password`, the last two failing closed until a credential is provisioned). The platform serves the rule at `GET|POST /apps/:app/:rule`, evaluates the goal inside the cell's safe-goal sandbox, and answers 429 when the app's compute ration is exhausted. Smart Panels are the other half: `smart_panel.publish` compiles a declaration into `panel/3`, `panel_prop/3`, and `panel_source/3` facts in the cell's `_panels` namespace, and a panel's source is a goal that re-runs on every read, so the interface renders the fact base rather than a copy of it. The app's home page lists published panels as pages and exposed rules as endpoints, both read from the cell.\n\nManifold builds one with the same build turn, but the end-state differs: instead of file contents, the model's output is packaged into pending changes of kind assert facts, constrain rule, retract facts, install battery, or publish panel, each staged in the approval pane that reviews file diffs. On approval the assertion or constraint is submitted to the cell, whose admission validates and certifies it, and the returned certificate id is stamped onto the change; a panel change dispatches its `smart_panel.publish` parameters verbatim. Each pending change also carries gate results, and the approval policy can auto-approve a change whose gates all pass; populating those gates from the platform's response, and carrying the certificate on `.api` responses, is the intended contract rather than what the platform returns today.\n\n```mermaid\nflowchart TB\n    goal[\"goal\"] --> turn[\"code turn<br/>orient, then generate\"]\n    turn --> rules[\"pending changes<br/>assert, constrain, retract\"]\n    turn --> panels[\"pending change<br/>publish panel\"]\n    rules --> admit[\"Logic Cell namespace<br/>certified admission, ctc id\"]\n    panels --> pub[\"_panels facts<br/>panel, panel_prop, panel_source\"]\n    admit --> api[\"rule endpoints<br/>/apps/:app/:rule\"]\n    pub --> sp[\"panels<br/>/:app/:panel.sp\"]\n    api --> gate[\"published contract<br/>modes, verb, auth, ration\"]\n    gate --> web[\"web renderer\"]\n    sp --> web\n    sp --> tui[\"Manifold TUI and GUI<br/>panel pane\"]\n```\n\n*A reactor build: the same turn, ending in rules and panel facts in a cell rather than files, served as endpoints and panels and rendered both on the web and inside Manifold.*\n\n### The Client as a Panel Host\n\nThe same panel model renders inside Manifold. The terminal UI's Smart Panels pane lists the published panels of the connected cell, shows a selected panel's kind, namespace, source goal, and field count, and draws a bar preview of its data rows; a refresh re-reads the cell, so a panel Manifold publishes in one turn is visible in the client on the next without a rebuild. The desktop surface renders the full panel model through the shared `datagrout-panels` egui renderer, forms included, and `manifold serve` opens a published panel at its hosted `.sp` address. Outside the hosted renderer, `manifold reactor serve` runs a local server that serves published panels at `/<panel>.sp` alongside `/api/query` and `/api/action` proxies into the cell, `manifold reactor export` writes standalone HTML, and `manifold reactor build` scaffolds a desktop wrapper. The client is extended by what it builds, today by hosting and previewing panels published to the cell; treating panels as first-class runtime extensions of the workbench is intended, not shipped.\n\n### Memory Without Compaction\n\nConversation history is not compacted; it is persisted. Each turn's content is stored as facts in a per-session namespace and embedded, and subsequent turns hydrate a constant-size window of the most relevant prior turns by semantic retrieval. The context window stays flat regardless of session length, and \"what did we decide about X?\" is answered by retrieval rather than by hoping the summary kept it.\n\n### Deployments\n\nOne engine serves several surfaces: a terminal UI, a desktop application, a headless CLI, and an MCP server that exposes the agent's capabilities as tools any MCP client can drive: lens, query, code, review, merge. The MCP surface makes Manifold *composable*: a capability other agents drive, as the next section shows. The surfaces follow the platform's fact-derived interface model: panes are facts rendered by whichever runtime is present, so the workbench is built from the same panel system its Reactor targets use.\n\n---\n\n## Composition: An Agent Driving an Agent\n\nThe MCP surface lets a governed plan drive Manifold as a subordinate capability. In production use, a small supervising agent on the Agentsmith runtime (see *Agentsmith: A Symbolically-Grounded Agent Architecture*) executes a typed plan whose steps are orient, optionally lens, code, and a review breakout, routing Manifold-addressed steps to a Manifold instance and platform-addressed steps to the DataGrout gateway. Today the supervisor holds those two clients side by side; folding them into one composite client is the intended shape of the SDK's client trait. The supervisor owns the plan, the trace, and the merge decision; Manifold owns the editing discipline and the workspace safety model.\n\n```mermaid\nsequenceDiagram\n    participant S as Supervisor plan\n    participant X as Composite client\n    participant M as Manifold MCP\n    participant G as DataGrout gateway\n    S->>X: orient step\n    X->>M: orient against the lens\n    M-->>X: existing related code\n    opt project not yet lensed\n        S->>X: lens step\n        X->>M: lens the workspace\n        M->>G: assert structural facts\n    end\n    S->>X: code step\n    X->>M: code, orient plus implement plus verify and refine\n    M-->>X: satisfied or not, diff, attempts\n    S->>X: review breakout\n    X->>M: review diff from manifold-base\n    M-->>X: trace and verdict\n    X-->>S: trace and verdict\n    alt build satisfied\n        S->>X: merge with the chosen mode\n        X->>M: merge with the chosen mode\n    else build unsatisfied\n        S-->>S: refuse to merge\n    end\n```\n\n*A supervising plan drives Manifold as one capability among several, addressing Manifold and the gateway through the client layer, and keeps the merge decision for itself.*\n\nThe supervisor can refuse to merge an unsatisfied build. A follow-up turn (\"the review flagged the error path; harden it\") is a second plan against a fresh fork, stacking its staged changes beside the first's. And because the supervisor is substrate-agnostic, the same pattern drives non-coding plans: the identical runtime has seeded facts, asserted rules, and exposed a Logic Cell rule as a live public API endpoint — a working micro-application built and verified without a file of conventional code.\n\n---\n\n## Cost Model\n\nThe token-saving structure is a composition of mechanisms:\n\n- **Navigation is a query.** \"What exists near this goal?\" is answered from the lens in one round-trip, replacing exploratory file reads.\n- **Orientation is front-loaded.** Preventing a reinvention costs a query; discovering one in review costs a rewrite.\n- **Generation is single-shot per attempt.** The refine loop dispatches the model once per round with the concrete failure in hand, rather than running an open conversation.\n- **Anchored edits shrink both directions.** The model receives the relevant context, not the file, and emits the replacement, not the file; the verify loop makes minimality safe, since a bad splice fails the check and enters refine.\n- **Memory is retrieved, not replayed.** Constant-window hydration replaces linear context growth.\n\nWith small, precise contexts the economics should invert in favor of stronger models, since a better model on a small context costs less than a weaker model's failed rounds; the measurement is pending.\n\n---\n\n## Comparison with Conventional Coding Agents\n\n| Dimension | Conventional loop | Manifold |\n|---|---|---|\n| Codebase model | None; files re-read per session | Persistent lens facts, incrementally updated |\n| Control | LLM decides next action | Symbolic controller; LLM lateral |\n| Anti-drift | Review-time, human | Authorship-time, orient node |\n| Edit format | LLM-authored diffs | End-states; deterministic diff derivation |\n| Change safety | Edits user's tree | Forked workspace, moded merge |\n| Session memory | Compaction | Constant-window semantic retrieval |\n| Verification | Model self-assessment + tests | Project's own checks as the satisfaction predicate |\n| Composability | Application | MCP capability drivable by other agents |\n\n---\n\n## Limitations and Trade-Offs\n\n**The verify command is the oracle.** A node is only as sound as the project's checks; a codebase with weak tests gets weak satisfaction guarantees, and the loop will confidently satisfy a check that does not capture the goal's intent.\n\n**The lens covers structure, not semantics.** Call graphs and definitions are extracted deterministically; what a function *means* is not in the fact base. Structural neighbors are usually, though not always, the semantic ones.\n\n**Single-shot generation trades conversation for auditability.** The model carries no multi-turn working state within a node; each round is a fresh dispatch with explicit context. The loop's state lives in the controller, where it is inspectable, rather than in the model, where it is not.\n\n**One agent per workspace.** Concurrency is handled by isolation and merge discipline, not shared awareness. Two agents on the same repository work in separate forks and reconcile at merge, like two developers.\n\n---\n\n## Future Directions\n\n### Shared Structural Awareness Across Agents\n\nThe lens gives every agent the same facts about *committed* code; it does not yet share *in-flight* changes. Asserting each workspace's structural deltas into a shared namespace would let concurrent agents query for overlap before renaming, deleting, or changing signatures: coordination through the fact base rather than merge conflicts.\n\nThe Reactor substrate sharpens this: when the codebase *is* a cell, work-in-progress is already cloud-resident. Agents on different namespaces can share structures before anything resembling a commit exists, and merging becomes a reconciliation over typed facts and certified rules that the substrate can check, rather than a text-level diff whose conflicts surface at integration time. Version control becomes what the platform already treats it as: an audit trail, not the medium of collaboration.\n\n### Impact-Guided Verification\n\nThe lens's call-graph facts support bounded impact queries today; connecting them to test selection (run exactly the tests that exercise the transitive callers of what changed) would make the verify step's cost proportional to the change rather than the codebase. This composes with the structural review pass of *Consequential Analysis: Semantic Verification of AI-Generated Code*.\n\n### Navigation as a First-Class Instrument\n\nOrientation today serves the build loop. The same fact base supports the broader navigational vocabulary of topology, reachability, and subsystem boundaries developed in *Cartographic Navigation*, turning the lens from a lookup table into territory an agent explores before deciding where to work.\n\n### Forensic Turns\n\nWhen a change fails in ways the refine loop cannot repair, the accumulated facts are the material *Forensic Inference: Structured Agent Reasoning Over Accumulated Facts* operates on: structure from the lens, observations from the failed rounds, results from verification. A forensic node that plants and queries facts about its own failed attempts is the natural escalation.\n\n---\n\n*This document describes the conceptual architecture of Manifold. Edit-grammar specifics, guard thresholds, workspace bookkeeping, and lens schemas are part of the operational implementation and are not specified here.*\n",
  "last_updated": "2026-07-01T00:00:00Z"
}