Skip to the content.

R3 placement dual-write: one structure, two projections

Status: derivation contract for rung R3 of the zero-knob automatic-context epic #2198 — issue #2201. Spine: CONCEPT-AUTOMATIC-CONTEXT-2026-07-01.md (§R3, §L4). This note ships no code — like the parent spine it binds already-shipped surfaces into one contract and specifies the smallest code increment plus the witness that would close #2201. It is the design half; the internal/promptmmu / internal/cachemeta code dispatch is the other half (named under What remains below).

Horizon classification (the intake this note repairs)

R3/#2201 is gen/now + managed-context + prompt-caching, milestone Generation G0 - Now / Immediate — not needs-triage.

The gap (grounded, at HEAD)

Prefix stability is discipline, not contract. Three surfaces already speak the same nouns but derive their spans independently:

Nothing derives cache_control positions and the stable residency segments from one structure, so a residency edit (a splice/prune boundary) can land inside a SegStable span and silently bust warmth — law L4 violated at the prefix boundary, invisibly.

The contract: one derived structure

R3 is satisfied when a single value is the source of truth both sides read:

  1. The residency plan is the structure. BreakpointPlan.ProtectedPrefix already names the stable leading run in segment coordinates. R3 adds the dual projection: the only legal cache_control breakpoint position is the ProtectedPrefix.End boundary (end-exclusive segment index), i.e. a breakpoint sits between the last protected segment and the first mutable one — never inside a SegStable / non-evictable (syspromptmmu.NonEvictable) span. Placement is a read of the plan, not a second derivation.
  2. A stable-segment set falls out of the same plan. The protected span plus any SegStable/SegToolSchema segment and any syspromptmmu spine/policy (TierSpine/TierPolicy) segment form the stable set: the byte ranges a transform must carry verbatim. SegSealed is already handled (refusal rule 3, UnsafeToCompact); R3 extends the same refusal shape to a stable-segment edit.

The one-structure test: PlanBreakpoints output, and nothing else, decides both “where may a breakpoint sit” and “which segments are immutable this turn.”

The advisory shadow-mode check (change nothing, log the would-be violation)

The first increment is advisory (L7: advisory first, gate later). Define a pure check with a closed reason vocabulary, in the same style as promptmmu.UnsafeSpan:

CheckStableEdit(plan BreakpointPlan, edit Span) → (ok bool, reason string)

The two derivation test targets (the #2201 done condition’s unit half)

The derivation is unit-tested against the two transforms that actually edit the prefix today, asserting each is correctly classified:

The witness

R3’s live witness is already scraped: the fak_harness_coherence_events_total{event=...} family (internal/gateway/harness_coherence.go), folding compactcohere.PrefixEvent (internal/compactcohere/compactcohere.go). The fak-attributed break events are fak_cut (EventFakCut) and fak_world_break (EventFakWorldBreak). R3 is witnessed when, on a real guard session:

fak_harness_coherence_events_total{event="fak_cut"}        == 0
fak_harness_coherence_events_total{event="fak_world_break"} == 0

while event="harness_rewrite" (and the prune/shed counters) keep firing on the same session — fak-attributed prefix breaks are zero while shed/prune stay active. A non-zero fak-attributed count is a real L4 violation the shadow log must have attributed line-by-line.

What remains (the code + live-session gate — the honest fence)

This note is the design contract only. To close #2201 a code dispatch on the promptmmu/cachemeta lane must:

  1. Add CheckStableEdit (pure, closed reason set) beside PlanBreakpoints, and the shadow-mode log attribution at the two call sites (#555 splice, promptmmu prune).
  2. Land the unit test against those two transforms (fails before the check exists, passes after) — the achievable half of the done condition.
  3. Run the shadow mode on a real guard session and show the two fak-attributed counters at 0 while harness_rewrite fires — the half that needs a live session on real hardware (a host capability not present on the native-Windows dev box, where even go test routes through WSL).

Until (3) has a captured witness, #2201 is not yet: the derivation and its unit test are landable now; the live shadow-mode/metric witness is the gate that remains.

Next checkable step

Dispatch the promptmmu-lane code increment above; check go test ./internal/promptmmu -run StableEdit for the unit half, then a guarded session’s /metrics scrape for the two fak_harness_coherence counters.