dsh-slice-agent-loop

September 3, 2026 · View on GitHub

English | 中文

Every turn, hand the model exactly the context it needs. No more, no less.

That sounds like common sense, but today's mainstream coding agents replay the entire conversation history back to the model every call: the excess is never trimmed, and what falls short can never be recovered. This plugin brings a slice loop built around that one sentence into the DeepSeek Harness: same harness, same model, same tools and persistence — only the agent loop is swapped, so in every comparison below the loop itself is the only variable.

Early beta; tracks DSH 0.1.2-alpha.4 (snapshotEvents, typert /api/<ns>/<method> RPC with cookie auth; the bundled bench drivers speak the new protocol).

One sentence, two constraints

ConstraintTranscript (full-history) status quo
No moreContext has an upper boundContext grows to the window limit, then compacts; attention dilutes, the bill grows with every turn
No lessInformation stays recoverableAfter compaction, detail is gone and cannot be brought back

Three structural problems of the transcript architecture: A · Context rot — the longer the context, the less the model gets out of each item in it; B · compaction beheads the session — summaries are lossy and irreversible, the original text is nowhere; C · cost grows quadratically with turns — every call resends the full history; cache discounts delay the blow-up but cannot beat volume.

The design: a tape, and recall

What the model sees each turn is not the conversation history but a working slice rebuilt for that turn:

ZoneNature
system prompt · tool schemasFrozen, byte-identical for the whole session (prefix-cache friendly)
SESSION TAPEAppend-only ledger of sealed turns: what was asked and done, file baselines with patches applied, replies
OPEN FILESCurrently open files, with sha256 anchors and edited markers
Current turn + tool observationsAppended within the turn — large tool results are condensed at insertion (see below) — sealed and archived at turn end

The tape looks like a transcript — append-only, cache-friendly — but every entry carries a hash and provenance. Long content is truncated at the cut with an exact marker, and the full text stays durable in the session log.

Recall is how "no less" is honored, in three tiers: recall_search finds which turn said something (scored search, tool-output flood excluded by default), recall_turn returns that turn verbatim, and recall_step(turn, step) returns one tool result in full when its condensed view is not enough. The tape and every condensed view leave a signpost at the cut pointing back to the original.

Transcript's problemThis plugin's answer
A · Context rotBounded peak: the model always works in a small context
B · Compaction lossFold without losing: the session log is fully durable, two-tier recall retrieves verbatim
C · Quadratic costEach turn carries only what that turn needs; the tape is append-only, so the prefix cache works

Two folds, two time scales

Slice folds history twice, at different moments:

FoldWhenWhat survives in contextWhat stays recoverable
Cross-turn (the tape)At turn endTurn digest, file baselines + patches, reply head/tailEverything, via recall_turn / recall_search
In-turn (insertion-time condensation, default since 2026-09)The moment a tool result enters the turnData/document reads: first and last lines plus every structured line, appendix blocks trimmed to their first few keys. Build/test/log output: every error, failure and warning with context, stack traces, summary lines. Source code and grep/glob results: never condensedThe full result, via recall_step(turn, step)

Why the in-turn fold is the lever: under DeepSeek's prefix cache a hit costs ~1/30 of a miss, so anything that rewrites earlier bytes (sliding windows, mid-turn sealing, per-step ledgers) pays the miss price every step and loses to an append-only stream. Within a turn the only cost left to cut is the size of each new result — so the stream stays append-only and each result is condensed once, on entry, never rewritten. Measured on a 45-node chain-migration turn (~300K tokens of reads): $0.135 → $0.024, 45/45 correct. The routing rules and their Headroom lineage are in docs/fold-content-routing.md.

Modes: mode: 'slice' (default) is everything above. mode: 'stream' (experimental, off by default) adds a per-turn constitution (the request plus rules extracted from the first files read) and a contract (host-side predicate checks on writes, with a bounce budget so a mis-extracted rule can interrupt at most once); it is the configuration that passes the rule-document ledger task (l2) reliably. mode: 'state' (hot-window world-state loop) is kept as an archived experiment — docs/world-state-loop.md. defaultReasoningEffort: 'low' is the plugin default (an explicit connection setting wins) — the effort ladder is in docs/effort-ladder.md.

Measurements: two arms, head to head

default = DSH's stock transcript loop (with calibrated compaction); slice = this plugin. Same harness, same tools, one round on each of two model generations: deepseek-v4-flash (0731) and deepseek-v4-pro (0813). Prices use the sheet effective 2026-08-16, at off-peak rates: flash miss $0.22/M · hit $0.007/M · output $0.66/M; pro $0.66 / $0.022 / $1.98 (peak doubles every rate, so relative deltas are unchanged). The new sheet narrows both cache discounts to ~1/30 (formerly flash 1/50, pro 1/120). Per-call ledgers kept, every number recomputable; results below report both rounds.

① Long-horizon loads · both arms × both models

The bounded slice's home turf is the long session — a transcript's cost and peak grow with every turn, a slice's do not. Two long-horizon scenarios (16-turn compaction amnesia · 76-turn context flood), each cell flash / pro:

ScenarioArmVerifier (flash / pro)Price (flash / pro)Peak (flash / pro)
s13 (16 turns)slice✓ / ✓$0.0241 / $0.090016K / 17K
default✓ / ✓$0.0296 / $0.085259K / 40K
s10 (76-turn flood)slice✓ zero loss / ✓ zero loss$0.1529 / $0.616332K / 43K
default✓ / ✗ early timeline LOST$0.3755 / $0.7682378K / 42K

The two s10 rounds together are the transcript dilemma caught whole. Flash round: default's compaction can't keep up with the flood, the peak ratchets to 378K — everything stays in context, every quiz passes, but the context is out of control. Pro round: compaction works properly (peak sawtooths 40→34→39→40, bounded at the threshold) — and it costs the early timeline that lived only in history: the verifier fails the run. Unbounded peak or lossy forgetting: a transcript must pick one. Slice, both rounds: bounded peak + zero loss, at 59% / 20% lower price. The short s13 scenario's price swings with the pricing structure (slice -18% under flash, +6% under pro); the peak advantage (2.4–3.7×) does not.

Amendment (2026-08) — the flash-round default cell above is invalidated: a config-name drift (compact-basiccompaction-basic) had silently disabled that arm's compaction, which is exactly why its peak ratcheted to 378K while "keeping everything". Re-run with compaction correctly calibrated and verified firing, the flash default fails the verifier too (3 planted facts lost; peak 96K sawtooth). Both model generations now resolve the dilemma the same way: once compaction actually runs, the transcript pays with lossy forgetting. Slice cells re-validated unchanged on the rewritten schema.

Results update — 2026-08-24 → 31 (rewritten schema)

  • Schema rewritten DSH-native: 19 ported regions → 4 fed segments + 2 fixed slots; the fidelity ladder / elasticity controller / Python golden parity retired (−3.4K lines). Kernel prompt 12.7k → 1.9k chars; ask/ reply truncation now keeps head AND tail with exact cut markers; a plugin contribution registry (ctx.sliceContext) lets plugins feed the slice without the loop knowing them.
  • Retention series (7 new paired scenarios + re-runs; same model & effort both arms; per-call ledgers): slice 12/12, transcript 10/12 — both transcript losses are compaction-destroys-history (the s10 flood, and a 3.4KB verbatim-restore scenario where slice recovered via a self-directed recall_turn — first benchmark-level proof the recall path is load-bearing, not decoration).
  • 1M-window cost (product-default compaction 0.8/0.16; the transcript arm genuinely climbs to 764–779K and crosses twice; 74 turns ≈ 2M tok content): slice −27% (pure input flood) / −39% (flood + real coding work). The differential is the transcript's per-cycle history re-reads (≈ W²/2Δ ≈ 10M cache tokens/cycle) plus summarization billed as output.
  • Honest cons, measured: light/short sessions cost +5–46% on slice — reasoning generation runs 2–5× (visible text equal; the price of re-orienting against a compiled dossier plus verify-don't-trust epistemics). Crossover ≈ the transcript's first compaction. Single-turn (Ralph-style) work gains nothing: within a turn this loop is a transcript.
  • Reasoning-passback refuted from both sides: feeding old chains onto the tape → reasoning +42%; stripping the transcript's native reasoning_content passback (471 strips) → −25%, run still passes. Old reasoning in context is cost, never continuation; the transcript's thrift comes from trusting its own narrative — the exact failure mode this loop removes. Wiring kept behind SLICE_REASONING_TAPE=1.
  • Archives: results/20260826-retention, results/20260827-cost1m, results/20260831-reasoning-ab in the companion workspace, plus a per-request viewer (build-request-viewer.mjs) that renders exactly what each arm sent the model, turn by turn.

Results update — 2026-09-01 (header dedup refuted)

The composition rule (tape composition == OPEN FILES hash ⇒ edit directly) is stated three times per turn: kernel (cached) + FILES_HDR + NOW footer (both per-turn paid text). An A/B deduplicated the two paid restatements (−21% paid fixed text, ~80 tok/turn) against four pre-declared behavior gates on s10 (76 turns) + n1, dual runs each arm. Result: rejected. Cross-turn composition trust held in both arms (kernel's single teaching site is sufficient for the rule itself: 0–2 cross-turn re-reads everywhere) — but the restatements turn out to damp same-turn post-edit verification re-reads: control 10/10 redundant re-reads across two runs, dedup 25/15. The paid repetition is not teaching the rule; it is suppressing re-read paranoia, worth more than the ~80 tok/turn it costs. Cost delta was −7–9% in dedup's favor and did not override the behavior gate. Decision recorded in docs/adr/0001-keep-header-restatements.md; ledgers in results/20260901-header-dedup/; branch feature/header-dedup left unmerged as the artifact.

Results update — 2026-09-03 (in-turn fold · three arms)

Conditions: flash, adapter-default effort (high), no step cap (250), full tool stack (bash/grep/glob); the default arm's numbers are recomputed from the August session logs at the same price sheet; single runs unless noted. Full tables and the environment audit: docs/slice-fold-multiturn.md.

Scenariodefault (Aug)slice, Aug build (no in-turn fold)slice, now (in-turn fold)
s1 long-horizon debug (6 turns)✓ $0.091✓ $0.074✓ $0.068
s2 task-DAG scheduler (10)✓ $0.081✓ $0.094✓ $0.120
s3 interval algebra (10)✓ $0.051✓ $0.087✓ $0.081
s13 amnesia (16)✓ $0.030✓ $0.026✓ $0.021
s14b recall ladder (17)✓ $0.031✓ $0.029✓ $0.025
s10 flood (76) 3 facts lost · $0.250✓ $0.164✓ zero loss · $0.157
CB-20 retrieval (19 paired)fileR 0.761 · $0.541 · 19/20fileR 0.816 · $0.602 · 20/20fileR 0.749 · $0.482 · 20/20
l1 chain migration (1 turn, ~300K read)✓ $0.135✓ $0.142$0.024–0.031
l2 ledger posting (rule doc + running state)✓ $0.124✓ $0.050✓/✗ without a constitution; mode: 'stream' 3/3 at $0.0285

Readings: 9/9 on the multi-turn set (default 8/9); memory and flood loads −21–37%; retrieval −11% at parity recall against default (−4–7pp against the August slice build, confounded with kernel changes); single-turn heavy reads −80%. Coding tasks split from −25% to +61%: the output tax — after each per-turn rebuild the model re-reasons and re-runs tests — is a property of the slice architecture, not of the fold, which never triggers on source code.

② Amnesia re-enactment · both arms · eviction-verified

24 benchmark numbers produced by the agent's own script run, existing only in tool output — before the exam: the numbers never enter any reply (turn 1 explicitly asks only to confirm the run), the source samples are deleted on first run (nothing on disk), and a dilution flood forces default's compaction to rewrite history multiple times. The exam has two tiers: first no hint at all, then an explicit "you produced these numbers yourself in this session — go check the records."

ModelArmEvictionNo-hint tierExplicit tierTrapPeakPriceWall
flashslice✓ 0/1624/2424/24no fabrication ✓21.5K$0.0521222s
default✓ 0/160/2424/24no fabrication ✓51.9K$0.0910569s
proslice✓ 0/1624/2424/24no fabrication ✓22.1K$0.1692383s
default✓ 0/1624/2424/24no fabrication ✓33.4K$0.46122014s

Both arms share the same durable substrate — DSH persists the full session log, so recovery is possible in principle for either. The difference is affordance, and it changes shape with model strength. On flash: given the neutral exam, slice spontaneously ran recall_search → recall_turn (the tape leaves signposts at every cut) and recovered within the turn; default searched the workspace, found nothing, and wrote UNKNOWN as instructed (zero fabrication, duly recorded) — until the explicit tier, where it zstd-decompressed its own session jsonl and dug the values out. Pro is strong enough that default performs that forensic dig unprompted — so the gap moves from whether recovery happens to what it costs: the same 24/24 takes slice 3 requests (383s / $0.169) and default 32 requests (2014s / $0.461) — 2.7× the price, 5.2× the wall clock. "Recoverable" and "goes and recovers" are separated by one layer of tools and signposts; the stronger the model, the more that layer shows up as pure efficiency.

③ CB-20 precision retrieval · both arms

ContextBench (given a real issue, the agent retrieves the code locations the fix depends on): a 20-question subset of the official 50-question benchmark. Paired comparison n=19 — default timed out (20 min) on one question in each round (different questions; both finished by slice in minutes):

Metric (19-question paired mean)slice flashdefault flashslice prodefault pro
fileRecall0.8160.7610.7520.780
spanRecall0.8470.7720.7940.811
filePrecision0.2270.2290.2440.212
F1 · file-level (from means)0.3550.3530.3680.333
F1 · file-level (macro)0.3420.3230.3430.327
total price$0.6021$0.5414$1.3603$1.7318
completion20/2019/2020/2019/20

The two generations swap the recall lead (slice +5.5pp under flash, default +2.8pp under pro), but slice wins F1 and completion on both, and pulls ahead on precision under pro (+3.2pp); price flips from +11% under flash to -21% under pro — pro's output is expensive ($1.98/M), and default's longer sessions and extra steps cost more on an expensive model. The re-read discipline a bounded slice forces stays an advantage on retrieval across both generations.

Per-question detail · flash (19 paired: recall / span / F1 / price)
Question (Multi-SWE-Bench)slice R/span/F1default R/span/F1slice $default $
c__0f94ce4d1.00/1.00/0.361.00/1.00/0.260.06010.0597
c__1ac60ce91.00/1.00/0.251.00/1.00/0.200.01600.0237
c__b9b452620.33/0.30/0.170.33/0.30/0.130.11180.0627
c__cdbc58901.00/1.00/0.221.00/1.00/0.180.03000.0267
cpp__6a4e21e90.67/0.63/0.220.67/0.25/0.400.03630.0283
cpp__7c9ef76c0.67/0.97/0.330.33/0.93/0.180.01940.0276
cpp__bca55dea1.00/1.00/0.640.29/0.14/0.210.04380.0206
cpp__fe080aac0.50/0.87/0.330.50/0.87/0.250.02580.0342
go__0498ad7f1.00/1.00/0.291.00/1.00/0.180.01750.0341
go__0b78ed501.00/1.00/0.671.00/1.00/1.000.01500.0095
go__0f79e39c1.00/1.00/0.501.00/1.00/0.500.01350.0094
go__1384380d0.67/0.39/0.420.67/0.51/0.320.03020.0764
go__1ba303a50.67/0.92/0.360.67/0.92/0.440.03650.0389
go__250649eb1.00/1.00/0.501.00/1.00/0.570.00990.0129
go__2a889a1d1.00/1.00/0.291.00/1.00/0.290.02990.0088
go__2c512ec30.00/0.00/0.000.00/0.00/0.000.03150.0171
go__3d1b31451.00/1.00/0.501.00/1.00/0.290.01370.0270
go__3d85271b1.00/1.00/0.221.00/1.00/0.220.01620.0106
go__3deeea9c1.00/1.00/0.221.00/0.75/0.500.04490.0131

Unpaired timeout: c__8bffb1b1 (default timed out at 20 minutes; slice finished in 137s, R/span 1.00/1.00, $0.0213).

Per-question detail · pro (19 paired: recall / span / F1 / price)
Question (Multi-SWE-Bench)slice R/span/F1default R/span/F1slice $default $
c__0f94ce4d0.40/0.65/0.170.80/0.85/0.330.14460.1326
c__8bffb1b11.00/1.00/0.441.00/1.00/0.360.04850.0906
c__b9b452620.33/0.30/0.400.33/0.30/0.200.05010.1579
c__cdbc58901.00/1.00/0.201.00/1.00/0.180.05150.1199
cpp__6a4e21e90.67/0.49/0.160.33/0.15/0.130.14110.0947
cpp__7c9ef76c0.33/0.93/0.120.67/0.97/0.270.12400.1051
cpp__bca55dea0.71/0.56/0.450.86/0.86/0.360.11440.1728
cpp__fe080aac0.50/0.87/0.360.50/0.71/0.290.06480.0763
go__0498ad7f1.00/1.00/0.401.00/1.00/0.290.04860.0551
go__0b78ed501.00/1.00/0.671.00/1.00/0.400.04150.1038
go__0f79e39c1.00/1.00/0.401.00/1.00/0.500.03460.0257
go__1384380d0.67/0.36/0.470.67/0.66/0.440.09760.0872
go__1ba303a50.67/0.92/0.440.67/0.92/0.360.06040.1281
go__250649eb1.00/1.00/0.571.00/1.00/0.500.06300.0348
go__2a889a1d1.00/1.00/0.221.00/1.00/0.400.03930.0603
go__2c512ec30.00/0.00/0.000.00/0.00/0.000.06430.0902
go__3d1b31451.00/1.00/0.291.00/1.00/0.290.05450.0501
go__3d85271b1.00/1.00/0.401.00/1.00/0.400.02590.0266
go__3deeea9c1.00/1.00/0.331.00/1.00/0.500.09150.1201

Unpaired timeout: c__1ac60ce9 (default timed out at 20 minutes; slice finished in 949s, R/span 1.00/1.00, $0.1222).

Defects and directions

transcript vs slice, stated fairly

Everything below is priced on the same sheet (flash off-peak: miss $0.22/M · hit $0.007/M · output $0.66/M). Same-code, same-day comparisons exist for l1/l2, n1–n3 and one s4 cell; the multi-turn s-series and CB-20 transcript numbers are August sessions recomputed, on a slightly different host. Every cell is a single run and repeats of one configuration move ±30%, so anything inside 15% is a tie.

Task shapetranscriptsliceReading
Single-turn heavy read (l1, ~300K tokens)✓ $0.135✓ $0.024–0.031slice −80%; the in-turn fold is decisive
Flood / memory (s10 · s13 · s14b)✗ $0.250 · ✓ $0.030 · ✓ $0.031✓ $0.157 · ✓ $0.021 · ✓ $0.025slice −21% to −37%; only s10 separates the arms on correctness (compaction lost 3 planted facts)
Multi-turn coding (s1 · s4)✓ $0.091 · ✓ $0.143✓ $0.068 · ✓ $0.125slice −12% to −25%
Multi-turn coding (s2 · s3)✓ $0.081 · ✓ $0.051✓ $0.120 · ✓ $0.081transcript 32–38% cheaper: after every per-turn rebuild the model re-reasons and re-runs tests, 1.7–2× the output tokens; the August slice build showed the same, so this is the architecture, not the fold
Small-file multi-turn (n2 · n3)✓ $0.012 · ✓ $0.020✓ $0.012 · ✓ $0.019tie
Rule document + running state (l2)✓ $0.124✓/✗ $0.030slice drifted to the wrong output directory in 3 of 4 runs without a constitution; mode: 'stream' passes 3/3 at $0.0285
CB-20 retrieval (19 paired)fileR 0.761 · $0.541 · 19/20fileR 0.749 · $0.482 · 20/20recall at parity (span 0.803 vs 0.772), slice −11%, per-instance F1 9:8

Peak context: transcript reaches 59–96K on s13/s10 and 302–330K on l1/l2; slice stays at 11–33K on the multi-turn set and 42–52K on l1/l2 after the fold. A small peak does not save money by itself under a 1/30 cache discount — it buys no window limit, no compaction and no rot; in this suite rot never appeared and compaction loss appeared once (s10), but that once was real.

The price sheet is the premise. With no cache discount (hit priced as miss), l1 becomes $1.81 vs $0.31, n2 $0.088 vs $0.025, n3 $0.174 vs $0.038 — slice 3–6× cheaper across the board. DeepSeek's 1/30 discount is the whole reason transcript keeps up on short tasks.

Where transcript wins: short interactive coding sessions under DeepSeek pricing (cheaper, equally correct); the fewest moving parts; nothing "present but unseen" inside the window; complete engineering coverage. If your sessions are tens of turns with small files, transcript shows no visible disadvantage.

Slice's inherent risks: recall depends on the model reaching for it — proven under controlled pressure (s10, s14b), near zero on everyday loads; the fold changes what the model sees (CB-20 file recall 0.749 vs 0.816 on the August build, confounded with kernel changes); rule-document tasks need the constitution; more mechanism means more surface for failure, and the plugin is early.

Hard conclusions: long sessions, floods, heavy reads and log-dense tasks belong to slice — correctness not worse, cost −21% to −80%, bounded peak; short multi-turn coding under DeepSeek pricing belongs to transcript; on any provider with a shallow cache discount slice wins broadly. Soft conclusions (need same-code reruns with three runs per cell): the +48–61% on s2/s3 and the 4–7pp CB-20 recall gap may be half noise and version drift.

Defects

DefectWhat it is, measuredDirection
1 · Coding tasks pay an output taxThe slice is rebuilt every turn, so on coding loads the model re-reasons and re-runs tests after each rebuild: s2/s3 cost +48–61% against default with 1.7–2× the output tokens, while s1/s4 come in −12–25%. Input-side, the in-turn fold settled the cache question: an append-only stream that condenses each new result beats every rewrite-history design under a 1/30 cache discount (l1: −80%).Tape rounds 2–3, 2026-09-03 (now the default): rent-or-buy anchoring (read twice / touched twice), collapsing a turn's edits, and full bases with read pointers bring s2 to a median $0.085 over nine runs (old slice 0.120, transcript 0.081) and s1 to 0.050 (0.068), memory scenarios at parity, all green. The same full-base shape loses on 8–12-file working sets (s4/s5/s6, six samples all above the old shape): with the whole working set in front of it the model does the work in its head, and reasoning at effort high costs more than a few extra tool steps — hence the baseMaxFiles switch back to the old shape beyond 4 tracked files. Turn-start reasoning is 2–4× the transcript's and does not depend on seed size (r = 0.01 over 241 turn starts); a snapshot-semantics header cut tape-interpretation from a third to a tenth of it without lowering the total. Carrying old reasoning was refuted a second time. Next: three runs per cell, and shapes with 5–7 files.
5 · In-turn condensation trades a little retrieval breadth for bytesCB-20 file recall 0.749 vs 0.816 on the August build (confounded with kernel and host changes), 20/20 completion, −20% price. Condensation never touches source code or grep results; its rules were tuned on logs and dossiers.--no-fold ablation on today's build; error-first log rules and structured-line rules are the two knobs.
6 · Rule-document tasks need the constitutionWithout it the model drifted to a wrong output directory in 3 of 4 l2 runs; mode: 'stream' passes 3/3 and costs the same.Decide whether stream becomes the default for long single-turn tasks; keep it opt-in for interactive sessions (short turns pay for extraction and gain nothing).
1b · Folding without the sliceThe in-turn fold is the one universal saving (l1 −80%) and it never needed the tape. @dsh-external/dsh-slice-agent-loop/fold is a standalone plugin that mounts on the stock transcript loop: at each pre-step it condenses the tool results that just landed and shadows the originals with tool/result surface replacements (the compaction pruner's own mechanism); the durable log keeps the originals and expand_result returns them. Standalone repo: TT-Wang/dsh-tool-result-fold; see docs/tool-result-fold.md.Measured same-day against the stock loop: l1 0.023 vs 0.135 (−83%, 45/45, peak 43K vs 331K), s13 and s2 neutral (nothing to fold on coding loads), all green. Recommended product default: transcript + fold; the slice tape only for sessions the transcript would have to compact.
2 · The recall channel depends on the model reaching for itHistory is byte-recoverable, and spontaneous recall under controlled pressure is proven (test ②); but on everyday coding loads active recall is near zero (most information fits tape capacity and push covers it), and cross-session "continue from yesterday" cold starts remain a risk.Make recall habitual on everyday loads and cold starts; agent memory is still frontier territory, work scheduled.
3 · Retrieval breadth vs. the frugal kernel is still being balancedThe current kernel buys precision and price at some recall-breadth regression against the previous build.Kernel A/B iteration continues.
4 · Still an early plugin overallCovers the web profile's agent-loop surface today; settings-panel alignment, the subagent ecosystem, and TUI are catching up. The core mechanisms (sealing, audit events, two-tier recall) are validated by the three test groups above.An engineering-coverage problem, not a technical-difficulty one.

Install

dsh plugin --profile web add "github:TT-Wang/dsh-slice-agent-loop#main"

Or from a local checkout: git clone then dsh plugin --profile web add . Restart web afterwards — bundles are composed at boot.

The bundled patch disables the stock loop and compaction — the bounded rebuild replaces both. If your composition carries an agent-loop-invariant row, remove it: a rebuilt slice cannot equal the derived history byte-for-byte, and this plugin refuses to load beside that assertion.

Configuration

keydefault
maxStepsPerTurn50hard ceiling on continuation steps per turn
maxParallelToolCalls10parallel tool bodies per step; since DSH 0811 this also caps subagent fan-out
defaultReasoningEffort'low'effort injected when the connection sets none; 'inherit' keeps the adapter default
digest{ enabled: true, minChars: 1500, logMinChars: 512, … }in-turn condensation policy (docs/fold-content-routing.md); enabled: false restores the August behavior
mode'slice''stream' adds constitution + contract; 'state' is the archived hot-window experiment
state{ pinSteps: 2, extractAtStep: 3, enforceFromStep: 8, contractBounceBudget: 1, sideEffort: 'off' }stream/state knobs
inTurnSeal{ enabled: false }mid-turn sealing experiment (not worth it under cache pricing)
tape{ readBases: true, readBasesMinReads: 2, newFileMinTouches: 2, readPointer: true, anchor: 'base', baseMaxFiles: 4, baseMaxChars: 60000, collapseEdits: true, gcSupersededBases: false }tape shape. Rent-or-buy rules (checked against 89 historical sessions): a read-only file is anchored once read in 2 turns; a file this session created is anchored on its second touch; a turn's repeated edits of one file collapse to the final state. Working-set switch: while the tape tracks ≤ baseMaxFiles files, edited files re-land as full bases and a full read of a tape-current file answers with a pointer (wins on 1–4-file coding loops); beyond that the tape falls back to patch-or-base without pointers (wins on 8–12-file working sets). baseMaxChars caps a single full base. Opt-in: gcSupersededBases (one current base per file in the seed), rebaseAfterPatches, replyHeadChars/replyTailChars, checkInDigest

Set them from your profile's cordis.patch.yml, targeting the existing row by id (- id: slice-agent-loop + config:).

Development

npm install --legacy-peer-deps   # the @deepseek-ai/* peers are unpublished
npm run link:dsh                 # symlink them from your dsh checkout
npm run typecheck && npm test

lib/ is committed (git-source installs run no build) — npm run build before pushing. Real-model smoke: npm run e2e:recall (needs DEEPSEEK_API_KEY in env).

Benchmarks (DEEPSEEK_API_KEY and SLICE_CALL_LEDGER_DIR in env): run the environment probe first, then any scenarios-snapshot scenario:

npx tsx scripts/run-scenario.mts results/20260902-multiturn/scenarios-snapshot/z0_env_smoke --arm slice-noseal --tools full --ledger-dir results/probe
npx tsx scripts/run-scenario.mts <scenario-dir> --arm transcript|slice-noseal|stream --effort low|inherit --max-steps 250 --tools full --ledger-dir results/<batch>

--effort inherit --max-steps 250 --tools full reproduces the August conditions; every ledger records the effort, step cap and tool list that actually took effect. scripts/h2h-sessions.py recomputes usage from ~/.dsh/sessions, scripts/mt-report.py builds the comparison table, scripts/cb20-dsh.mjs drives CB-20 against a running web profile. Design notes: docs/fold-content-routing.md, docs/slice-fold-multiturn.md, docs/world-state-loop.md, docs/effort-ladder.md, docs/in-turn-slicing.md, docs/miss-attribution.md.

License

BSD-3-Clause — see LICENSE.