dsh-anchor
August 26, 2026 · View on GitHub
Long-running sessions without limits. Every high-entropy tool action gets a pre-committed intent and immediate reconciliation; the anchor tree on disk is the session's source of truth. Crash the process, rescan the tree, adopt, continue — nothing is lost.
中文版见 README.zh-CN.md。
Why this exists
The mainstream answers to "long-running tasks" rely on two things: context compression (loses precision) and memory retrieval (loses consistency). Real incident history says otherwise: the main cause of failure is never "forgetting" — it is actions landing on wrong assumptions about the environment (uncontrolled side effects: corrupted code, killed wrong processes, leaked state).
dsh-anchor takes a different path: don't remember the past, lock down the future.
Before every action: intent (what I will do) + pre (environment fingerprint) = pre-commit
After every action: post (actual result) reconciled immediately → OK / DIVERGED
- Incidents surface in the moment, not in after-the-fact investigations
- The anchor tree = the session's progress truth: the session dies, the tree remains; a new session scans the tree, adopts, and continues (aligned with the official subagent cold-resume semantics, plus environment reconciliation it does not have)
- Maps to official public pain points: force-kill drops the write-behind tail (#483) → we flush to disk immediately with zero buffering; one bad log kills a session (#1593) → our source of truth is the directory structure; a broken anchor only costs that one step
Who is this for
- Operators of long sessions (tens to hundreds of steps) who have been bitten by "actions landing on wrong assumptions": code corrupted by edits, wrong processes killed, state leaked;
- People who want the progress truth back after a mid-session crash — the anchor tree lives outside the session log; cold start scans and adopts (clean / dirty / contaminated / fresh);
- People who need an audit trail — every high-entropy action's intent/pre/post lands on disk immediately; "expected vs actual at the time" is inspectable and reproducible.
Not for: short conversations of three to five steps — the sampling discipline (minimum gap 7) anchor cost would be wasted.
How it works
Mounted on official extension points, zero intrusion:
| Official seam | Our mount |
|---|---|
tools/pre-execute (pre-action waterfall) | anchorOpen: write intent + pre fingerprint |
tools/post-execute (post-action, before result materialization) | anchorClose: environment reconciliation + verdict |
Reconcile against the environment, not self-reports: for write/edit-class actions, reconciliation reads the disk to verify the real content (expected = the target content declared by parameters, measured = the actual bytes on disk) — the tool claiming success doesn't count; the anchor checks the environment.
Sampling discipline (measured-verdict hardened):
- High-entropy actions (file writes/processes/subtasks) are anchor-mandatory — the actions with the biggest side-effect entropy are locked down
- Minimum gap 7 — the no-gap form's overhead spikes (per-capture cost 98.6 → 25.1, measured)
- Low-entropy actions (reads/pure queries) run free — their failures are either harmless or propagate into a high-entropy action and surface there
- DIVERGED feedback: the moment of failure switches to panic mode (all-anchor); 3 consecutive OK steps restore normal — automatic switching between order track and chaos track
Anchor tree anatomy:
session-anchors/
├── 00027-write#27/ # one action = one anchor directory
│ ├── intent.json # pre-commit: action name + expected fingerprint
│ ├── pre.json # pre-action environment fingerprint (+ recorded process pids)
│ ├── post.json # post-action measurement
│ └── verdict # OK / DIVERGED (verdict at the moment)
└── ...
Quick start
# Install (git source, pinned tag)
dsh plugin --profile <name> add "github:Wang-Lin-Chang/dsh-anchor#v0.2.2"
Then mount it in the profile's cordis.patch.yml:
# cordis.patch.yml
- insert:
- name: 'dsh-anchor'
config:
anchorRoot: 'C:\path\to\session-anchors' # anchor tree root (source of truth)
minGap: 7 # sampling gap discipline (default 7)
After restart the plugin is on duty: every high-entropy tool action gets an anchor and immediate reconciliation. Cold start automatically scans the anchor tree for adoption adjudication.
import { apply } from 'dsh-anchor'
const service = apply(ctx, { anchorRoot: './data/session-anchors' })
service.report() // tree scan report (last complete anchor / dirty site / fingerprint chain)
service.adoptState // cold-start adoption verdict (clean/dirty/contaminated/fresh)
Acceptance evidence
All tests live in npm test (37 assertions green). Measured environment: Windows 11 Pro · Node 25.8.
| Suite | Verifies | Assertions |
|---|---|---|
| sampling | Sampling discipline (high-entropy lock / gap 7 / panic feedback / recovery) | 10 |
| plugin-anchor | Official seam mounting + environment reconciliation + no interception + cold start | 12 |
| plugin-adopt | Real process kill -9 → cross-process adoption → continued run with consistent terminal state | 7 |
| plugin-blind | Double-blind external pollution (independent process corrupts the environment, plugin unaware) | 8 |
Real-machine duty record (anchor tree excerpt from a real DSH instance):
00027-write#27 DIVERGED ← write to a read-only file blocked by EACCES; reconciliation read the disk and caught it on the spot
00028-pwsh#28 OK ← only 1 step since the last anchor, yet anchored = panic triggered (discipline overridden)
00029/30/31-read OK ← panic-mode low-entropy all-anchor ×3, each OK advances recovery
(reads after this: zero anchors) ← 3 OK steps recovered → low-entropy runs free again, zero false alarms
vs. dsh-witness
| dsh-witness | dsh-anchor | |
|---|---|---|
| Granularity | Task (one task one directory, five-state adoption) | Action (one action one anchor, verdict reconciliation) |
| Governs | Background task lifecycle | Session/agent long-running action supervision |
| Shared core | AnchorCore four primitives (open/close/recover/adopt) | The same core |
A task is just a "big action", an action is just a "small task" — both packages share one philosophy: the filesystem is the source of truth.
Honest boundaries
- Windows-first. Measured on Windows 11 + Node 25.8. The anchor tree protocol itself is cross-platform, but only the Windows real machine has verified it so far; untested platforms are not claimed.
- Reconciliation coverage v0: environment reconciliation currently covers
write/edit/create_file(reads the disk to verify); other tools use fallback reconciliation (checks for abnormal self-reports only). Extending the reconciler by tool type is the planned path. - Adoption v0 weak checks: cold-start adoption scans the tree for structural verdicts (clean/dirty/contaminated); the full form of environment-level diff verification exists in dsh-witness's task adoption, and full session-level environment verification is on the roadmap.
- The anchor is an observer, not a gate: failed reconciliation only marks DIVERGED and triggers denser sampling; it does not intercept tool execution (interception belongs to the official guard mechanism).
Development
npm test # 37 assertions: sampling 10 + plugin-anchor 12 + plugin-adopt 7 + plugin-blind 8
Requires: Node ≥ 22.5 (no dependency beyond node:sqlite, measured on 25.8), Windows PowerShell 5.1 (real-machine verification environment).
License
Apache-2.0