Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Re-anchor on the durable record (current-track, live owner thread, pending-questions, relay, build_log) before acting on anything that depends on earlier context. Read, do not recall.
.claude/skills/sonichi-context-reconstruct/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 57% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 69% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 141% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 31% | 0% |
Goal: never act on lost/eroded memory of the ongoing work. The agent can be interrupted, compacted, or run dozens of interleaved cron passes and still pick up exactly where the thread left off — without the owner re-reminding it.
Why a skill, not a script: a hardcoded bundler (fixed N reads, one channel, fixed depth) is rigid — and easy to skip (narrate "re-anchor" then assert from memory anyway). The fix isn't a rigid script; it's flexible judgment + practice. This file is living — improve it whenever a reconstruction misses.
Before interpreting or acting on anything that depends on earlier context, READ the durable record. Don't recall — read. A "re-anchor" you claim but don't actually read is the failure.
Read the current-track record FIRST — <workspace>/hosts/<hostname>/current-track.md (this skill owns it; see "Maintain" below). Resolve <hostname> with bash scripts/sutando-config.sh host-label, the same way pending-questions.md does. Legacy fallback: if that file is absent but <workspace>/state/current-track.md exists, read the legacy path and migrate it to the per-host path on the next write — the flat path was shared across hosts and is being retired (#2567). It's the fast anchor: the current main-track goal, the active sub-task, and the live open decisions. This is what's missing when "continue your main track" gets guessed — the goal must be a pinned record, not inferred from luck.
Then, as the situation needs (pick what's relevant; skip what isn't):
python3 src/discord-read.py <channel_id> --serving <task channel_id> when serving a task (the contextNotFrom gate runs before the fetch), or --operator on autonomous passes with no serving context (Discord), telegram task [Replying to…] quotes (Telegram has no history fetch). Go as deep as the thread needs with --until <id|iso> — not a fixed message count. If unsure which channel is live, check the most recent task's channel_id / state/last-owner-activity.json.pending-questions.md.relay/relay-*.md.build_log.md tail.Effective > exhaustive: read enough to make this message/decision stand on its own, then stop.
The skill both uses and maintains <workspace>/hosts/<hostname>/current-track.md (NOT the legacy flat state/current-track.md — writing there again re-creates the cross-host delivery of one host's anchor onto another at the same local path; see the 2026-08-03 practice-log entry below, which retracts the "clobber"/data-loss framing this line used to carry) — the owner doesn't dictate its content and the agent doesn't invent it from memory; it's derived from the reconstruction:
Compare what you read against what you think is true. Where they differ, trust the record. If the current track is a still-open owner thread, continue THAT.
When the thing in front of you isn't self-contained — terse ("y", "no", "?", a pronoun), a reply, refers to something not stated, or you're resuming after a gap/compaction. Keyed on the message/situation, not on felt confidence (felt confidence is what fails — the agent is confidently wrong).
reanchor.sh was rejected for being rigid + skippable. Open problem: making "actually read" reliable (it's a habit, not a one-liner). Iterate as misses happen.state/current-track.md first and MAINTAINS it (derive from the record, don't dictate/invent). Seeded the file from the durable record. Closes the "reconstructs context but not the persistent goal" gap.name:/description:. A skill that isn't discoverable can't be invoked, and step 0.7 then no-ops silently — no error, no warning, indistinguishable from having run. Whenever this skill is changed, the check that matters is an actual Skill-tool invocation, not the file's presence on disk.<workspace>/hosts/<hostname>/current-track.md, not the flat state/current-track.md. The flat path was added to the shipped carrier set by #2534 and is shared across hosts, so two cores write the same vault path and a peer's anchor is delivered into your working copy. hosts/<label>/ is already carried by hosts/*/, so the per-host path needs no carrier entry and cannot collide — structurally impossible rather than correctly configured (#2568, merged 2026-08-03T12:44:58Z; refinement credit: Sutando-Mini).⚠ CORRECTED 2026-08-04 — this entry previously said "after a live data loss" and claimed a peer "overwrote this host's 1056-line anchor … three writes, all destructive". THAT IS FALSE, and Chi corrected it. The vault uses per-host branches (host/<host>/<wsid>): a host only ever merges a peer INTO its own branch and never writes to the peer's. Checked afterwards — both branches were byte-identical, and this host's index referenced 263 memory files against the discarded copy's 262, a strict superset with nothing missing. Sutando-Pro independently confirmed it from the file's own two-commit history. The correction is written into src/health-check.py (see the UNSAFE_TO_READD comment, ~line 1396), which is the authority.
The guidance is unchanged — do not re-add the flat path — but the reason is cross-host CONTENT DELIVERY on a shared path, NOT data loss. Keeping the wrong reason here mattered: this file is loaded on every proactive-loop pass via step 0.7, so it re-taught a claim the owner had already retracted, and on 2026-08-04 I repeated "destroyed a 1056-line anchor" back to Chi from it. A retraction has to reach the file that gets read, not only the file that learned it.
Note the 2026-06-25 entry above is left as written — it was true then.
plausible partial result. Every entry above assumes the agent is the unreliable part, and the fix is always go read the durable record. This one is about the record's reader being unreliable, and it defeats the whole step silently.
A history read returned only messages from a recent cutoff onward — at every limit up to 1000 — while a local archive held months of earlier traffic from the same source. Probed with known ids from before the cutoff: 0 returned, with a positive control confirming the id field was populated on every message it did return, so the zero was absence rather than an empty field.
The property to carry: an agent cannot distinguish a plausible partial result from a complete one. A windowed read and a genuinely short thread are the same object from inside. So step 0.7's "reconstruct the live thread" can report success while returning almost nothing, and felt compliance is exactly as unreliable here as felt confidence is everywhere else in this file.
What to do instead. When a reconstruction returns fewer items than the situation implies, treat the shortfall as unexplained until something outside that reader accounts for it. Three cheap discriminating probes, in order:
flag is just returned == requested, it is not a truncation signal at all.
window returning fewer results proves the reader is not enumerating.
thing you are about to name.
Probe 3 is where the second mistake lives. An outside record is not automatically trustworthy:
matches items that merely quote the identifier, which silently widens the population.
>= the event time, and its tail is brutal. Calibrated over2678 files carrying both a declared timestamp and an mtime: median lag +1s, maximum lag 8.1 days. An excellent proxy almost always and catastrophically wrong occasionally — the worst possible shape, because a small sample lands in the well-behaved majority and reads as confirmation. Quote a max, never a rate: measured across three populations the tail frequency spans two orders of magnitude (0.1% / 5.5% / 20%), so the rate is a property of the corpus, not of the archive. Name the corpus and the filter with any such number.
files still carried a declared timestamp that the current schema had dropped. That is usually where calibration data hides when the present has none.
And "two independent methods" must mean methods with different FAILURE MODES, not two invocations. Two calls that share a cutoff, a corpus, or a path convention can agree perfectly while omitting the same thing. Independence is semantic, and the only way to establish it is to have seen the two disagree on a case where you know the answer.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | fail→fail | 3,243 | 7,765 | +139% | 1 | 1 | 0% | 469 | 3,303 | +604% | 0 | 0 | — |
case-04 | fail→pass | 10,500 | 8,039 | -23% | 1 | 1 | 0% | 1,710 | 4,142 | +142% | 0 | 0 | — |
case-09 | fail→pass | 11,660 | 2,335 | -80% | 1 | 1 | 0% | 1,967 | 3,086 | +57% | 0 | 0 | — |
case-01 | fail→fail | 5,853 | 9,303 | +59% | 1 | 1 | 0% | 887 | 2,952 | +233% | 0 | 0 | — |
case-02 | fail→fail | 5,414 | 5,822 | +8% | 1 | 1 | 0% | 320 | 2,978 | +831% | 0 | 0 | — |
case-05 | pass→pass | 10,782 | 4,191 | -61% | 1 | 1 | 0% | 1,786 | 3,511 | +97% | 0 | 0 | — |
case-06 | fail→pass | 11,354 | 2,390 | -79% | 1 | 1 | 0% | 1,789 | 3,026 | +69% | 0 | 0 | — |
case-07 | fail→pass | 7,779 | 4,631 | -40% | 1 | 1 | 0% | 1,484 | 3,576 | +141% | 0 | 0 | — |
case-08 | fail→pass | 14,273 | 2,639 | -82% | 1 | 1 | 0% | 2,378 | 3,127 | +31% | 0 | 0 | — |
case-10 | fail→fail | 10,283 | 5,821 | -43% | 1 | 1 | 0% | 1,829 | 3,755 | +105% | 0 | 0 | — |
case-11 | fail→pass | 8,424 | 2,941 | -65% | 1 | 1 | 0% | 1,373 | 3,169 | +131% | 0 | 0 | — |
case-12 | pass→pass | 7,035 | 2,934 | -58% | 1 | 1 | 0% | 1,027 | 3,143 | +206% | 0 | 0 | — |
case-13 | fail→pass | 10,378 | 2,792 | -73% | 1 | 1 | 0% | 1,675 | 3,142 | +88% | 0 | 0 | — |
case-19 | pass→pass | 16,181 | 9,790 | -39% | 1 | 1 | 0% | 2,611 | 4,433 | +70% | 0 | 0 | — |
case-14 | fail→pass | 10,556 | 3,741 | -65% | 1 | 1 | 0% | 1,725 | 3,205 | +86% | 0 | 0 | — |
case-15 | fail→fail | 15,493 | 8,247 | -47% | 1 | 1 | 0% | 2,454 | 4,005 | +63% | 0 | 0 | — |
case-16 | pass→pass | 11,054 | 4,919 | -56% | 1 | 1 | 0% | 2,000 | 3,329 | +66% | 0 | 0 | — |
case-17 | fail→pass | 11,051 | 4,433 | -60% | 1 | 1 | 0% | 1,487 | 3,394 | +128% | 0 | 0 | — |
case-18 | fail→pass | 9,851 | 7,576 | -23% | 1 | 1 | 0% | 1,313 | 3,848 | +193% | 0 | 0 | — |
case-20 | pass→pass | 7,675 | 4,444 | -42% | 1 | 1 | 0% | 1,513 | 3,517 | +132% | 0 | 0 | — |
case-21 | fail→fail | 6,211 | 5,442 | -12% | 1 | 1 | 0% | 1,280 | 3,770 | +195% | 0 | 0 | — |
case-22 | pass→pass | 8,181 | 8,830 | +8% | 1 | 1 | 0% | 1,422 | 4,283 | +201% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +45 percentage points is the difference between those two pass rates over the 19 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/23/2026 | +36% |
Other measured skills in the registry, with their headline benchmark lift.