Introduction¶
Running long tasks in DSH (DeepSeek Harness) will eventually hit the problem of the context window being filled. The default compaction strategy is to compress the oldest segment into a summary when the window gets close to the limit. This causes two practical issues in long tasks: triggering too late (waiting until 80% of the window is used before acting), and the fact that the compression itself requires replaying the entire history, meaning the request is already right at the limit. After compression, new and old content are mixed into a single summary, making it hard for the model to distinguish between what just happened and what happened ten turns ago as background.
The plugin introduced below, btyg123/dsh-memory-ladder, changes the organization method: context is layered by age, each layer has its own budget, the newest round always has the most space, and the further back, the thinner it gets. It is maintained by BTYG123, licensed under MIT, and categorized as Memory.
What is it¶
One-sentence positioning: A DSH bundle plugin that replaces the default strategy as a compression backend. It inherits @deepseek-ai/dsh-compaction-basic’s BasicCompactionEngine, only replacing the trigger strategy and summarize(). The compression transaction (locks, shrinkage checks, surface replacement) still comes from the upstream.
It is not a backup tool, nor is it lossless compression. The README explicitly states “It saves capacity, not information itself,” and secondary details are discarded as layers descend.
How Layered Budgets are Calculated¶
Let the context window of the routing model be T. The budget for each layer is as follows:
| Layer | Content | Budget |
|---|---|---|
| Latest Round | All raw messages after the last checkpoint | T/3 |
| Previous Round | Summary compressed from the previous round | T/6 |
| Previous-Previous Round | Summary from even further back | T/12 |
| … | Halved for each deeper layer | T/(3·2^d) |
Therefore, the ratio between the Latest Round and the Previous Round stays stable at 2:1. v0.2 is also constrained by maxSummaryTokens: when the total budget of the hierarchy exceeds the summary output space, the summary layers are scaled down geometrically, and checkpoint framework space is preserved.
v0.2 Added Original Message Archiving¶
The new version preserves the original layered sleep transaction and writes the text of user, assistant, and tool messages into a separate archive for the current session before compression. Afterwards, based on the user’s question, it retrieves the original text that has left the context and provides it to the model via Harness’s dynamic context interface; it does not directly rewrite the frozen model request.
Key Behaviors:
- The default archive location is
.dsh-memory-ladder/under the session working directory; filenames use SHA-256 of the session ID. - Original messages retain Message ID, role, and order. Duplicate compression does not archive the same message again.
- System instructions, old checkpoints, and runtime context are not archived.
- Archiving is local plaintext state and will not be automatically uploaded to other services; the selected excerpts will be sent to the current model provider with the next model request.
archiveRecall: falsedisables both archive writing and retrieval. Resuming the same session ID can continue reading the archive; forking to a new session ID will not automatically copy the parent session’s archive.
What Happens During a Sleep¶
Following the README’s logic, a sleep consists of four steps:
- The token count of the Latest Round reaches
T/3(or the model reports context overflow). - A model call rewrites “Old Ladder + This Round’s Raw Records” into a new Ladder: Old Tier 0 becomes New Tier 1, shifting down layer by layer, with the deepest layer falling into the archive link.
- The transaction replaces the obscured entire history with a single user message (
surfaceOp: replace), while the original events remain in the session logs for replay. - This round continues from the new ladder.
The manual command /compact reuses the same path, simply skipping the threshold judgment.
Installation¶
The prerequisite is that dsh’s plugin command depends on pnpm. The official command given in the README is:
npm i -g pnpm
# Method 1: Plugin Manager (Recommended, tested)
dsh plugin --profile <your profile> add git+https://github.com/BTYG123/dsh-memory-ladder.git
After installation, dsh-memory-ladder is automatically added to dsh.profile.bundles of that profile.
Method two is to manually put it in node_modules in the profile and patch to disable the official compression backend and insert this plugin:
- id: compaction-basic
disabled: true
- insert:
- id: memory-ladder
name: 'dsh-memory-ladder'
This step cannot be skipped. ctx.compaction only accepts one implementation; mounting two backends simultaneously will cause a service "compaction" has been registered error at startup. The bundle’s patch includes the disable step; manual installation requires adding it yourself.
Configuration¶
Configuration items are listed according to the README’s configuration table, with all fields and default values as given in the original text:
# Sleep trigger line: percentage of the window occupied by the latest round
newestFraction: 1/3
# Maximum number of layers the ladder can describe
tierCount: 6
# Deeper layers below this budget are merged into archive links
minTierTokens: 200
# Output upper limit for the sleep request
maxSummaryTokens: 8192
# If the compressible span is smaller than this, skip directly to avoid wasting a model call
minCompactionTokens: 512
# Leave empty to inherit the provider/model of the most recent routing
summarizationProvider: ""
summarizationModel: ""
# false only keeps manual compression
auto: true
# Archive original text before compression, retrieve based on question in the next step
archiveRecall: true
# Archive directory, relative to session working directory, can also be set to absolute path
archiveDirectory: .dsh-memory-ladder
# Upper limit in UTF-8 bytes for context retrieved each time, including source info and framework
recallMaxBytes: 4096
Compatibility¶
The verification environment written in the README is @deepseek-ai/dsh@0.2.1-rc.5 + Node 22/24, with peerDependencies pinned to 0.2.1-rc.5. Two points need attention:
- This repository’s installation root fixes a known set validation memory exhaustion vulnerability via
overrides.zod = 4.6.6. npm does not automatically apply overrides inside dependency packages to the host project; when installed as a bundle, the Zod version must still be managed uniformly by the Harness host. compactRegion()is the public contract and relatively stable; constructor and base class fields are implementation details and upstream refactoring may cause this package to break.
Known Limitations¶
These are limitations explicitly listed in the README and worth understanding before deployment:
- Cannot compress a single ultra-long message. A 50k token assistant output is an indivisible unit; surface compression cannot fix this, which is a fundamental limitation of compression seams.
- Cannot compress the session after the archive is full.
archiveMaxBytes(default 32 MiB) is a hard limit. When full, it throwsARCHIVE_CAPACITY, and the compression transaction refuses to replace the original message. The consequence is that this session fails every subsequent sleep and the context keeps growing; you need to increase the limit, rotate the archive, or turn offarchiveRecall. For long-running sessions, it is recommended to raise this to 64–128 MiB in advance. - Sleep itself costs a model call. If the summary is longer than the original text, the transaction refuses to commit and logs a failure; dense sleeping will increase input costs.
- It is not lossless. To be lossless, increase
newestFractionor don’t use this plugin. - Summary quality depends on the model. Facts cannot be verified locally to ensure faithful preservation.
Benchmarks¶
In a 20-minute CrowdStrike incident investigation in the README, two window strategies for the same policy were compared:
Default T/3 (1M window) |
32k equivalent window | |
|---|---|---|
| Trigger line | 349,525 token | 10,905 token |
| Peak context | 185,359 token | 32,636 token |
| Sleep count | 0 | 10 |
| Session surface nodes | 266 | 142 |
| Output | 41 KB / 23 sources | 16 KB / 10 sources |
In 12 synthetic case studies (96 questions per model), Flash improved from 76/96 to 90/96, and Pro improved from 84/96 to 91/96; costs increased by about 32%/31% relative to the original, and decreased by about 28%/34% relative to the full history (full history still achieved 96/96). This is a quality/cost trade-off under specific compression pressure, not a proof that it is optimal for all long tasks. The README also retains a failed ablation group and per-question error logs.
Suitable Scenarios and Notes¶
Suitable scenarios: Long tasks where prioritizing “what happened recently” is needed, while accepting remote detail decay, and being willing to pay an extra model fee for summaries. Scenarios expecting lossless compression or expecting compression to be completely error-free are not suitable.
Additionally, the plugin runs with the current dsh process permissions. It is a bundle with its own cordis.patch.yml, which will disable compaction-basic and insert its own implementation at startup. You should read the source code and patch beforehand to confirm this matches your profile expectations. The license is MIT; see the repository LICENSE for attribution. The directory page is a third-party community site and has no official affiliation with DeepSeek or Hypersphere.
Conclusion¶
Its value lies in changing “when to compress and how detailed” to be determined by layered budgets, rather than waiting until the window is almost full to clear it all at once. The cost is the model call for every sleep, the archive capacity limit, and remote detail decay; all three need to be traded off in the configuration.
Directory Page: https://www.skillhub.cn/plugins/BTYG123/dsh-memory-ladder
Repository: https://github.com/BTYG123/dsh-memory-ladder