* feat: versioned snapshot refs with MCP auto-pinning
Refs are positional indexes into the latest stored session tree; #1093's
coarse snapshotRefsStale marker warns honestly but cannot say WHICH tree
a ref came from. Give the session a monotonically increasing
snapshotGeneration, advanced wherever the stored tree is replaced: the
setSessionSnapshot choke point and the snapshot/diff command path that
bypasses it.
Token economy (non-negotiable): the snapshot tree output is unchanged —
plain e12 refs on every node. Ref-issuing responses (snapshot command,
find ref outputs) carry the generation ONCE as the additive
refsGeneration field. Ref-consuming commands (press/click/fill/longpress/
get/wait) accept both forms: plain @E12 keeps today's behavior including
the coarse #1093 warning; pinned @E12~s3 is clean when the generation
matches the stored tree, gets a precise warning naming both generations
when it does not, and a malformed suffix is INVALID_ARGS with a grammar
hint. Warn-only this release — tightening comes later per the compat
ladder.
The MCP layer auto-pins at zero token cost: it sees snapshot/find
responses before the model does, remembers the last refsGeneration per
session name, and rewrites plain @ref tool arguments to the pinned form
before forwarding. The model never sees or types suffixes; with no
remembered generation, refs pass through unpinned (never guess).
Replay parsing and script writing strip and IGNORE pins — generations
are meaningless outside the session that minted them.
Refs #1076
* docs: CONTEXT.md vocabulary for ref generation pins
Moved from #1097 per the review sequencing note: the term lands with
the behavior it describes.
* docs: teach the ref pin syntax in CLI help
MCP agents get pins transparently (auto-pinning), but CLI-driving
agents only ever met the coarse warning — refsGeneration arrived in
snapshot responses with nothing explaining it, making pins an
undiscoverable feature on the primary agent surface. One help line in
the agent loop guidance closes that; warnings stay short (they fire
repeatedly, teaching belongs in once-read surfaces).
* fix: per-ref MCP pin provenance and seeded generations
Review findings on the first cut:
1. The MCP layer kept ONE refsGeneration per session, so after
snapshot(s12) -> find(s13) a plain @e37 from the pre-find snapshot got
pinned ~s13 and read as current — recreating the find-blessing hole at
the pinning layer. Replace it with per-ref provenance:
Map<pinScope, Map<refBody, generation>>, scoped by state dir + session
name (stateDir is a per-call MCP config field, so one server process
can face multiple daemons). Merge-only updates: refs present in a
ref-issuing response (snapshot nodes, digest refs, the find ref) move
to its generation; absent refs KEEP their older pins — an old pin on a
replaced tree is what makes the daemon warn. Never-issued refs pass
through unpinned; an issuing response without refsGeneration clears
the scope; memory bounded to the ~1000 most recently issued pins.
2. Generations were per-lifetime counters from 1, so a reopened
session's ~s1 collided silently with the previous lifetime's. Seed
the first bump at a random 6-digit base (crypto randomInt):
cross-lifetime collisions become ~1e-6 — probabilistic (seeded), not
identity-based, documented on the field. Pin format unchanged;
within-lifetime comparisons stay exact.
Tests: the MCP blessing scenario (pre-find ref stays pinned to ITS
generation), the daemon half in the provider scenario (find must not
bless a pre-find pin), reopen/reseed at unit + handler level, state-dir
scope isolation, digest-ref merging; generation fixtures made
seed-agnostic (relative bumps, echo the observed seed).
Refs #1076
Follow-up to a week of agent-driven work (the ADR 0011 arc, the Bluesky dogfood, and ~20 worker PRs): refocus the agent-facing docs on what is expensive to rediscover, and delete what any model inspects in one
rg.AGENTS.md (net ~flat in lines, much denser in value)
Deleted: the Routing and Command Family Lookup prose maps — several entries had already drifted from the code (interaction handlers moved, response construction moved), and post-ADR-0008/0011 every fact in them lives in a parity-tested registry. Replaced with a pointer block naming the four registries as the things to read.
Added — the two sections a fresh model cannot cheaply reconstruct:
Revised — module size strategy: the LOC caps stay as tripwires, but the unit is reframed as questions per file (rg → one bounded whole-file read), and the rules gain: 1:1 test-topology mirroring with the integration-aggregation exemption removed — data:
interaction.test.tsis 3,408 lines and the platform index tests 3,291/2,735 precisely because tests were exempt, and they are where agents bleed the most tokens; sibling fixture modules over repeated inline literals (the contract suite is the model); claim collocation (coverage manifests, registry cells, decision-site comments); barrels only at package boundaries.Updated: tsgo typecheck; the dev-loop staleness triple including the adopted-runner trap (shutdown hands off a runner that keeps serving the old Swift binary — a classic false negative when verifying runner changes); Gatekeeper first-node-exec stall; DEVICE_IN_USE signature; the contention-flake verification protocol; two new gate steps on the add-a-flag checklist.
CONTEXT.md
Vocabulary for the ADR 0011 domain (dispatch path, guarantee cell, owned waiver, parity table, coverage manifest, delegation-on-error, ref generation pin) and an architecture paragraph pairing ADR 0011 with ADR 0008.
docs/adr
0011 flipped to Accepted (implemented through Layer 3); new README index with "read this when…" routing and the rule that registries beat ADR prose when they disagree.