Maintain a persisted, re-readable control anchor so a long autonomous run survives context compaction without losing the plot — one file holding the mission, a plan pointer, a live cursor (done / in progress / next action), invariants, last-known-good state, and exact resume steps, updated after each step and re-read at the start of each turn. Use when starting or driving a multi-hour or multi-phase autonomous task, a self-driving loop, or any unattended run that will cross one or more automa...
Scanned 8/31/2026
Install via CLI
openskills install grimaldost/craft-collection---
name: compaction-survival
description: >
Maintain a persisted, re-readable control anchor so a long autonomous run
survives context compaction without losing the plot — one file holding the
mission, a plan pointer, a live cursor (done / in progress / next action),
invariants, last-known-good state, and exact resume steps, updated after each
step and re-read at the start of each turn. Use when starting or driving a
multi-hour or multi-phase autonomous task, a self-driving loop, or any
unattended run that will cross one or more automatic compactions or
context-window resets; on asks like "make sure compaction doesn't lose the
work", "keep state across auto-compact", "persist the current state so a reset
doesn't disrupt this", "this is a long autonomous run", or "resume cleanly
after a reset". The anchor is intra-actor state recovery — the same actor
re-reading its own working state across a discontinuity. Not for handing work
to a fresh context or a teammate (that is context-handoff's inter-actor
brief), not for post-hoc capture of what a finished session learned (that is
journaling-sessions), and not for tracking a short task that fits comfortably
in one context window. The /anchor command is the one-off snapshot entry
point; when the running session lacks the plugin surface entirely (stale
snapshot, harness without the skill menu), references/cold-start.md has the
by-hand recipe.
---
# Compaction Survival
A long autonomous run loses most often to this — the context that
held the plan gets compacted or reset, and the next turn resumes from a summary
that dropped the load-bearing detail. The defense is an anchor on disk that the
run re-reads and rewrites as it goes, so the plan lives in a file, not only in
the context window.
This is a **flexible** skill: the anchor's schema and update cadence adapt to
the task. What stays firm is small — the anchor is the single source of truth
for run state, re-read at the start of each turn and updated before the state
it describes can be lost.
## The anchor
One file, at a stable path the run can find again after a reset. It has two
tiers, split by a literal `<!-- anchor:tail -->` marker line: above it the live
**HEAD** — the only part the re-injection hook emits — and below it the
**TAIL**, which stays on disk. A marker-less anchor still injects whole, but
then a long run's live state is whatever the 8K bound keeps.
HEAD — bounded, rewritten in place. **The order below is the survival order.**
The injection spends its budget top-down and drops whole trailing sections,
naming them, so a section's position is its priority and putting one above
another demotes that other.
- **Mission** — the goal in a sentence or two, the hard constraints, and any
user instruction that constrains *mechanism* rather than outcome, quoted in
the user's own words with a stable id. Paraphrase is where an order dies:
once the wording is gone a substituted mechanism reads as a design choice.
A reversal of a standing rule is quoted the same way and names what it
supersedes; the old rule lives in other copies and will not overwrite itself.
- **Cursor** — done / in progress / **next action on resume**: one imperative
step plus the precondition to verify before it, rewritten in place as it
mutates. An unanswered question or approval is armed here for verbatim
re-ask after the reset. This is the part that earns the anchor.
- **Resume steps** — how a cold reader re-orients: read this file, check the
real state (version control log, the artifact on disk), continue from the
cursor. They run somewhere they were not authored, so write them in
**absolute paths** — a relative command does not fail after a restart, it
succeeds in the wrong place. Record the anchor's own absolute path where the
environment surfaces it next turn: an anchor that cannot be found is no anchor.
- **Invariants** — decisions and constraints that hold across the whole run, so
a post-compaction turn does not relitigate them.
- **Parallel tracks** — only when a peer run shares these trees: the other
track's anchor path and this track's never-touch surface, written before any
work. Disclose on every commit that touches shared surface, and route a
cross-track lesson into both anchors.
- **In-flight work** — background or async tasks the cursor depends on: their
ids, log paths, and a "do not relaunch over the same output" guard. A run that
fans out to background work records them here as first-class cursor state, so
each async boundary resumes idempotently instead of being re-derived.
- **Last-known-good** — the concrete recoverable state: commit hashes, branches
and PRs opened, tags pushed, the files written, the checkpoint reached.
- **Plan pointer** — where the full plan lives (a separate doc), so the anchor
stays a cursor, not a second copy of the plan.
TAIL — append-only, read on demand:
- **Decisions log** — why the non-obvious calls were made.
- **Folded history** — closed phases' one-line outcomes, resolved incidents.
## The protocol
1. **Create the anchor at the start of the run**, before the first irreversible
step, so there is something to resume from immediately. Arming is also the
sweep moment — read `anchor_inject.py --list-dormant <anchors dir>` and close
or adopt any track it names. It reaches what `close --stale` cannot: a track
abandoned mid-cursor never marks itself done.
2. **Update the cursor after each step or phase**, before moving on. State that
lives only in the context window is one compaction away from gone; write it
down while it is still true.
3. **Re-read the anchor at the start of each turn** — especially when a summary
has appeared or the context feels thinner than the work already done — the
signs of a compaction. Re-read before acting, not after. A
cursor is an Edit, so during tool outages it can lag reality by a phase; when
it disagrees with durable state (the version-control log, run ledgers), trust
the durable state.
4. **Write atomically and keep one anchor.** Overwrite the single file rather
than scattering state across several; a half-written or duplicated anchor is
worse than a terse one.
5. **Keep the HEAD bounded.** As a phase closes, fold its detail into a
one-line outcome in the TAIL, below the marker — a closed phase's spec, and
**the cursor's own done-list**, which is what actually accumulates.
6. **Make resume idempotent.** The resume steps let a fresh context recover the
run from the anchor and the real on-disk state alone; re-entering a
half-finished step checks the artifact before redoing it, so re-reading is
always safe. A stored recovery command (a ledger-count grep, a resume key)
is validated against the live artifact before the run goes unattended —
unchecked, it is a fabricated inference waiting to misfire.
7. **Close by stubbing, then renaming.** When the run ends, rewrite the anchor
to a minimal landed stub — status, a one-line outcome, resume: none — and
rename it `<name>.closed.md`. The rename is the only close signal the hook
honors: a prose "status: CLOSED" line does not stop re-injection, and a
full-ledger close overflows the injection budget on the next session. Close
at the moment the cycle ends; a track closed only in prose accumulates. And
close on the *deliverable*, not the session: if the session carries on into
new substantive work, arm the next anchor in the same breath — a closed
anchor beside a live session is an uncovered window. At
wind-down, `/anchor close --stale` sweeps the dir for anchors marked done
in-content but never renamed and offers the exact rename for each.
## Explicit surfaces
- Invoked directly (`/compaction-survival`), arm the protocol now: create or
refresh the anchor immediately from the current conversation state, then
follow the update-and-re-read cadence for the rest of the run.
- **`/anchor`** (session-workflow command) is the one-off backstop: a single
snapshot on demand, with or without this protocol armed — the deliberate
checkpoint before a manual `/compact`. It replaces asking in prose for the
state to be persisted; it does not replace the cadence, which is what
protects against *automatic* compactions that arrive unannounced.
- **Automatic re-injection** ships on; `SESSION_WORKFLOW_ANCHOR_HOOKS=0` opts
out. A SessionStart hook on `compact`, `resume`, `clear`, and `startup`
re-injects the newest **active** anchor's HEAD (to the tail marker) into fresh
context mechanically — the re-read step stops depending on the model
remembering the protocol. Without session-start hooks, the manual re-read at
each turn start is the whole mechanism. Over budget, the HEAD is spent
top-down on whole sections and the dropped ones are named, so the survival
order above is a policy the author sets rather than wherever the bytes ran
out. An anchor marked done in-content is de-ranked below live tracks, and the
injection names any other open anchors; the rename to `*.closed.md` remains
the only signal that stops injection entirely. An anchor untouched for 24h
injects as a short pointer — path, title, age, close command, and the cursor
it still asserts, which is the part a reader can check against reality.
`startup` (crash restart) injects only an anchor updated within 6h.
Anchor-less sessions pay nothing.
- **Cold start without the plugin surface** — a session whose plugin snapshot
predates the skill, or a harness whose menu omits it, arms everything by hand:
`references/cold-start.md` has the full recipe (the anchor file by hand, manual
hook registration, a verify-by-piping step). Because that recipe is unreachable
exactly when the skill is absent, keep the compact minimal contract — anchor
path, the `<!-- anchor:tail -->` split, a cursor with a next action, the
`.closed.md` rename — in the CLAUDE.md protocol snippet, where a menu-less
session still has it.
## Common failure modes
The seven recurring ones and what each costs: [`references/failure-modes.md`](references/failure-modes.md).
## Boundaries
The description names the three neighbours this is not. The discriminator worth
having in hand: a handoff is written once and read by someone else; an anchor is
rewritten continuously and read by the same run.
No comments yet. Be the first to comment!