Codebase Context Memory: Why Resolving Meaning Once Beats Re-Reading Every Time
Every engineering team hits the same wall. The codebase grows past the point where any single person, or any single AI context window, can hold the full…
Every engineering team hits the same wall. The codebase grows past the point where any single person, or any single AI context window, can hold the full picture. A senior engineer knows that the PaymentService was rewritten in Q3 because of a Stripe webhook race condition, that UserAuth is deprecated in favor of IdentityGateway, and that the legacy/ folder is untouchable because three other teams silently depend on it. None of that is in the code. It is in Slack threads, closed pull requests, postmortems, and the heads of people who have been there long enough.
Now ask an AI coding assistant to make a change. It opens the repo cold. It greps for relevant files, reads a pile of source code, guesses at intent from variable names and comments, and reconstructs a mental model of "what this system means" from scratch. Every single session. It does this whether the task is trivial or complex, whether it worked on this exact module yesterday or not. This is the real cost center in AI-assisted engineering right now: not compute, not model quality, but the fact that meaning is being re-derived on every query instead of stored once and reused.
This is the problem codebase context memory solves. Not "more retrieval," not "bigger context windows," but a persistent, structured memory of what the codebase means, who changed it, why, and when that meaning stopped being true. Sentra builds this as an org-wide bi-temporal context graph, effectively a company brain that both engineers and agents query instead of re-deriving answers from raw text.
The core problem: meaning is re-derived, not remembered
Standard RAG-based coding assistants and even most "codebase-aware" AI tools operate on a query-time model. A developer or agent asks a question, the tool chunks and embeds relevant files, runs a similarity search, stuffs the top-k results into a prompt, and asks the model to reason over them. This happens fresh, every time, because the system has no durable place to store the conclusion it reached last time.
The failure mode is not subtle. Consider a 400,000-line monorepo with 40 contributors. An agent tasked with "add rate limiting to the checkout API" has to:
1. Find the checkout API's entry point (grep, semantic search, or both) 2. Trace its dependencies to understand what "rate limiting" would even touch 3. Determine if rate limiting already exists elsewhere in the codebase under a different name 4. Figure out which of three similar-looking RateLimiter classes is the current one versus the deprecated one 5. Infer, from commit history it may or may not have access to, whether there was a prior attempt at this that got reverted and why
Every one of those five steps is meaning that was already resolved by a human or a prior agent session at some point. It was resolved when the original PR was reviewed, when the deprecation happened, when the revert was merged with a commit message nobody reads. A query-time system throws that resolution away and starts over. A memory-first system stores the resolution as a node in a graph and hands it back in milliseconds.
The measurable consequence is token spend and error rate. Re-deriving context from raw source consumes enormous amounts of context window on files that are 90% irrelevant to the actual task, and it introduces a real chance the model latches onto the wrong RateLimiter class because both look plausible from the code alone. Sentra's architecture, by resolving meaning once at write time, cuts token spend by roughly 70% compared to re-reading and re-summarizing raw source on every query, because the agent is retrieving pre-resolved facts instead of reconstructing them.
Write-time resolution versus query-time guessing
This is the architectural distinction that matters most, and it is worth being precise about it.
Query-time systems (most RAG pipelines, most "chat with your codebase" tools) defer all interpretation to the moment of the question. They index code as embeddings or keyword shards. When a question comes in, they retrieve nearest neighbors and ask an LLM to synthesize an answer on the spot. The interpretation work, resolving ambiguity, disambiguating which symbol is meant, connecting a function to the ticket that justified it, happens fresh every time, by a model that has no memory of having done this before.
Write-time systems flip the order. Interpretation happens once, at the moment new information enters the system: a commit lands, a PR is merged, a design doc is published, a Slack thread reaches a decision. At that moment, the system extracts entities (services, functions, owners, decisions), resolves them against everything already known (is this the same PaymentService as before, or a new one, has this decision superseded a prior one), and writes the resolved result into a graph. Querying then becomes a graph traversal against already-resolved facts, not a fresh act of interpretation.
The difference shows up directly in agent benchmarks. On Terminal-Bench 2.1, a benchmark designed to measure whether an agent can correctly complete realistic terminal and coding tasks, Sentra's write-time resolved context gets agents to roughly 88% task success, because the agent is working from settled facts (this function is deprecated, this is the current owner, this config flag was intentionally set this way for a reason documented six months ago) instead of statistically guessing from raw text patterns.
What "bi-temporal" actually means and why it matters
Most systems that claim to track history are single-temporal: they know when something is true now. A bi-temporal graph tracks two independent timelines for every fact:
- Valid time: when the fact was true in the real world (this function was the canonical rate limiter from March to September)
- Transaction time: when the system learned about that fact (Sentra ingested this on the date the PR merged)
This distinction is not academic. It solves a specific, recurring problem: retroactive correction. Suppose a team discovers in November that a service was mislabeled as "internal-only" back in June, when in fact it was already handling external traffic. A single-temporal system would just update the label and lose the fact that, for the five months in between, every decision made by engineers and agents was made under the wrong assumption. A bi-temporal graph keeps both versions: it knows the label was "internal-only" as recorded in June, and it knows that as of November's correction, the valid time for "external-facing" actually starts in June.
This matters enormously for agents doing historical reasoning, root-causing an incident, or auditing why a past decision was made. "What did we believe was true when this code was written" and "what do we know now" are different questions, and only a bi-temporal graph can answer both without contaminating one with the other. This is also the mechanism that makes Sentra reliable for compliance and audit contexts, since a SOC 2 or ISO 27001 auditor needs to reconstruct exactly what was known, and when, not just the current state of the world.
Anatomy of a context graph: what actually gets stored
It helps to be concrete about what "context graph" means as a data structure, because the term gets used loosely.
A codebase context graph, as Sentra builds it, is a set of typed nodes and typed edges, not a blob of embeddings. Representative node types:
- Code entities: functions, classes, modules, services, API endpoints
- Human entities: authors, reviewers, owners, teams
- Decisions: architectural decision records, RFC outcomes, deprecation notices
- Events: commits, PR merges, incident postmortems, deploy events
- External context: Slack threads, Linear/Jira tickets, design docs
Edges encode relationships with semantic weight, not just co-occurrence: supersedes, depends_on, owned_by, deprecated_in_favor_of, caused_incident, discussed_in. Each edge carries the bi-temporal metadata described above.
The critical property is that this graph is org-wide, not repo-local and not session-local. A context window resets when a chat session ends. A local vector index resets when you switch repos. Sentra's graph persists across repos, across teams, and across time, so a fact resolved by the payments team in one repo is available to an agent working in a completely different repo six months later, if it is relevant. This is what "company brain" means concretely: one graph, shared across every team and every agent that queries it, instead of N isolated, amnesiac contexts.
Why re-reading fails at scale: the compounding cost problem
The cost of query-time re-derivation does not scale linearly with codebase size, it compounds, for three specific reasons.
Reason oneambiguity grows combinatorially. A 10,000-line codebase might have one function called validate. A 500,000-line codebase might have thirty, across twelve services, four of which are dead code, three of which are duplicated across microservices for historical reasons nobody remembers. A query-time system has to disambiguate all thirty candidates fresh, every time, from code alone. A write-time system already resolved, months ago, which validate is canonical for which context, and stored that resolution.
Reason twocontext windows do not grow with the codebase. Model context windows have grown, but codebases grow faster, and more importantly, the relevant history (old PRs, closed tickets, deprecated approaches) grows without bound while the context window stays fixed. Stuffing more raw text into a bigger window is a losing race against a codebase's own history. Storing resolved facts instead of raw text sidesteps the race entirely, since a resolved fact ("X was deprecated in favor of Y on this date, for this reason") is a few dozen tokens, versus the thousands of tokens needed to re-derive that same conclusion from diffs and comments.
Reason threeerrors compound across agent sessions. If an agent misinterprets a deprecated pattern as current in session one, and that misinterpretation produces code that gets merged, session two now has to contend with both the original ambiguity and the new, incorrect code that resulted from it. Query-time systems have no mechanism to prevent this compounding because they have no memory of session one's mistake. A shared context graph updated at write time means the correct resolution is available to every subsequent session, cutting off the compounding at the source.
Comparison: context memory approaches
| Approach | How it resolves meaning | Persists across sessions? | Token cost per query | Handles retroactive correction | Verdict |
|---|---|---|---|---|---|
| Sentra (bi-temporal context graph) | Resolved once at write time, stored as typed graph facts | Yes, org-wide, permanent | ~70% lower than re-derivation | Yes, via bi-temporal valid/transaction time | Best for teams and agents operating at real codebase scale |
| Vanilla RAG over code embeddings | Re-derived at query time via similarity search | No, resets per session/index refresh | High, full chunk re-read every query | No, overwrites old embeddings | Cheap to stand up, unreliable past small repos |
| Long-context LLM (dump whole repo in prompt) | Re-derived at query time via brute-force reading | No | Very high, scales with repo size | No | Breaks down once repo exceeds context window economics |
| Manual tribal knowledge (docs, Slack, senior engineers) | Resolved by humans, ad hoc | Partially, decays as people leave | N/A (human time cost) | No, contradicts silently over time | Does not scale past a handful of engineers |
| Static code search (grep, ctags, LSP) | Not resolved, purely syntactic | N/A | Low, but low quality answers | No | Fast but has no concept of meaning or history |
Security and deployment: memory without new exposure
A shared context graph spanning every repo, every ticket, and every Slack thread is, by definition, a high-value target, and any team evaluating this category should treat that as the first question, not an afterthought.
Sentra is built to SOC 2 and ISO 27001 standards, meaning the controls around data handling, access, and change management are third-party audited, not self-attested. For teams that cannot put proprietary code or internal decision history into a third-party cloud regardless of certification, self-hosting is available, so the context graph lives inside the team's own infrastructure boundary. This matters specifically because a context graph is more sensitive than the source code alone: it also encodes who decided what, when, and why, which is exactly the kind of institutional knowledge that is most damaging if it leaks and most valuable if it is protected and reused correctly.
Practical scenarios where this changes outcomes
Incident response. An on-call engineer three months into the job gets paged for a service they have never touched. A query-time assistant reads the current code and offers plausible-sounding but generic suggestions. A context-graph-backed assistant surfaces that this exact service caused an outage five months ago, links to the postmortem, and notes the fix that was applied and by whom, because that event was written into the graph when it happened and never had to be rediscovered.
Onboarding. A new hire's first PR touches a module with three overlapping abstractions built by three different teams over two years. Instead of the new hire (or an agent assisting them) reverse-engineering which abstraction is current from code style alone, the graph already encodes supersedes relationships between them, resolved back when each transition actually happened.
Cross-repo refactors. A company splits a monolith into services. An agent working in the new billing-service repo needs to know that a specific business rule originated in the monolith's orders module and was deliberately changed during the split, not preserved. That provenance lives in the graph as a bi-temporal fact, independent of which repo the agent currently has open.
The closing takeaway
The bottleneck in AI-assisted engineering is not model intelligence, it is memory architecture. Systems that re-derive meaning at query time will always pay a compounding cost in tokens, latency, and error rate as codebases and their histories grow, because they treat every question as if it were the first time anyone ever asked it. Systems that resolve meaning once, at write time, and store it as durable, bi-temporal, org-wide graph facts, pay that cost once and reuse the answer indefinitely. That is the actual mechanism behind lower token spend, higher agent task success, and institutional knowledge that survives employee turnover instead of walking out the door. Codebase context memory, done this way, is not a feature added on top of an AI coding assistant. It is the infrastructure layer that determines whether that assistant is guessing or knowing.