Make Plato a layer an agent can reach for on every query and trust — by closing a quiet staleness hole and reusing work only when it can prove the work is still current. The foundation the rest of the grounding layer sits on.
Draft for Robert’s annotation · not approved · no building yet
01
The hole we’re closing (read this first)
The first time an agent asks Plato anything in a session, Plato builds its whole picture of the repo — on a big repo, a couple of minutes — and then freezes it for the rest of the session. Every later question is answered from that frozen picture. Fast, but with one quiet problem: if a commit lands, a branch is switched, or a file is edited after that first build, Plato keeps serving the old picture, still stamped “in‑sync.”
For a layer whose whole promise is “you can stop double‑checking,” that is the worst kind of failure — a stale answer wearing a fresh label, just time‑delayed. It doesn’t lie loudly; it goes stale silently until someone restarts it. An agent that leans on Plato mid‑session can be handed it and never know.
R1 (the rule): Plato never serves a picture it cannot prove is current. The proof is recomputation, not memory — and any doubt rebuilds rather than reuses.
02
Decisions locked
From the frontier scan — which I re‑checked against our own code, not its say‑so.
Mechanism
Two cheap git checks, not a new engine
The scan found we already run the field’s correct model. The famous incremental‑computation engine would mean a rewrite and would re‑open a way to serve stale. So the whole slice is two small checks on top of what’s built.
Scope
Phase 1 now · Phase 2 only if measured‑needed
Phase 1 (revalidate before reuse) closes the hole and wins the common case. Phase 2 (rebuild only what changed) is the elaborate part — built only if a full rebuild on a change is actually too slow.
Posture
Prove‑or‑rebuild, never reuse on faith
A held picture is served only after proving it’s still current (HEAD unchanged, tree clean). Every other state — HEAD moved, tree dirty, anything unresolved — rebuilds. Fail‑closed.
03
What’s already right — and the two pieces we add
The correctness floor is on disk. This slice adds reuse‑safely and rebuild‑cheaply on top.
have it
The correctness floor
Plato re‑derives its picture from the committed code and re‑checks each answer against the live commit. This is what makes it honest today — it just does it the slow way, every time, then freezes.
↓
the build · P1
Gate A — revalidate before reuse
Before serving the held picture, one cheap check: has HEAD moved, is the tree dirty? Nothing changed → serve it, instantly and proven current. Something changed → rebuild. This closes the hole and makes repeat questions fast.
↓
measure‑gated · P2
Gate B — rebuild only what changed
When HEAD moved, git’s own diff is a complete, free list of what changed. Rebuild just those files plus whoever imports them; carry the rest forward. Built only if Phase 1’s full rebuild is too slow in practice.
04
What happens when an agent asks
The path of a single query — after this slice.
A question arrives.“What’s the blast radius of this file?” — any of the structural queries.
The cheap check (Gate A) — the load‑bearing step.One quick look: is the held picture still for the current commit, with a clean tree? This is the difference between honest‑and‑fast and the old frozen‑and‑stale.
Nothing changed → serve instantly.Reuse the held picture — now proven current, not assumed. This is the common case in a session, and it goes from a full rebuild to a single check.
Something changed → rebuild first.Phase 1 rebuilds the whole picture (always correct). Phase 2, if we build it, rebuilds only the changed files and whoever imports them.
Answer — always honestly labeled.The currency stamp reflects the true state. A moved HEAD or a dirty tree is never dressed up as “in‑sync.”
05
The rules that must hold
Reuse only on proof
The held picture is served only after a positive check that it matches the current commit and a clean tree. There is no other reuse path.
No stale “in‑sync”
A moved HEAD or a dirty tree can never be served with a fresh label. Behind is labeled behind; dirty is labeled dirty.
When in doubt, rebuild
Anything that can’t be proven unchanged — an unresolved import, an input from another repo — rebuilds, never carries forward.
The proof still recomputes
The existing recompute‑and‑compare check at read time is untouched. Reuse never bypasses it.
06
Honest hard problems
Phase 2 under‑rebuild (the one real risk)
An exporter drops a symbol; an importer’s own text didn’t change but its import now points at nothing. Rebuilding only changed files would serve that importer stale. Guard: rebuild importers too, and a mandatory deliberate‑break test that must go red. Phase 1 has no such risk — it rebuilds everything.
Two questions mid‑rebuild
Concurrent queries while a rebuild runs must never see a half‑built or stale picture. One rebuild, awaited by all.
The dirty‑tree shortcut
A dirty tree doesn’t change the committed picture, only the label — but Phase 1 keeps it simple and rebuilds rather than reasoning about partial dirtiness. No stale‑clean ever served.
The cross‑repo edge
Git’s free “what changed” list is complete only within one repo. A dependency that reaches into another repo can’t be proven current by this repo’s diff — so it fails closed and rebuilds.
07
Phasing
P1
Revalidate before reuse (Gate A)
The must. Closes the staleness hole and wins the common speed case. Small — a check wrapped around the existing build.
Measure
Is Phase 2 even needed?
On a real repo, measure repeat‑query latency (should drop to one quick check) and full‑rebuild‑on‑change latency. If the rebuild is fast enough, stop here.
P2
Rebuild only what changed (Gate B)
Built only if the measurement says the full rebuild misses the bar. Carries the under‑rebuild risk — gated behind the deliberate‑break test.
08
How we’ll know it works
The headline test: build the picture, land a commit mid‑session, ask again — the answer must reflect the new commit (or rebuild), never a stale “in‑sync.” Plus deliberate‑break tests that each must go red when the guard is removed: the exporter‑drops‑a‑symbol case (Phase 2), a branch switch, an uncommitted edit (served with an honest dirty label), and a repeat‑query that proves the held picture is reused with zero rebuild. Done = every one passes, the full gate stays green, and the speed win is measured from raw — not asserted.
09
Open questions — the red‑pen targets
1 ★
Scope.
Phase 1 now, and Phase 2 only if a measurement says the full rebuild is too slow? (My recommendation — Phase 1 closes the hole and is small; don’t build Phase 2 on faith.)
2 ★
Dirty‑tree contract.
When the working tree has uncommitted edits: answer the committed picture with an honest “dirty” label (today’s behavior), or refuse to answer until it’s clean? I lean label, not refuse.
3
Cross‑repo boundary.
Confirm: a dependency that crosses into another repo fails closed (rebuilds), never carried forward on this repo’s diff.
4
Dirty fast‑path (Phase 2 detail).
When dirty, refresh just the label over the held committed picture (cheap), or do a full rebuild? Only matters once Phase 2 exists.
10
The machinery (for the builder)
This page is the decision layer. The builder’s layer — exact integration points, the revalidating‑memo logic, the diff‑driven rebuild, the fail‑closed triggers, the gate legs — lives in the Markdown source, fenced below Layer 1.