Contents
A plugin-first harness can break a plugin through two channels: the binary itself, and the points where plugins attach. This post reads DeepSeek Harness (dsh) as a worked example of how one project documents both. In the material reviewed we found no versioning policy; what the docs do provide is a service map, a stated compatibility rule, and a release history of plugin-facing changes. Reading those together is the exercise here, and every versioning lesson drawn from them is ours.
Two disclosures shape everything below: this review is a reading of published sources, not a hands-on or measured comparison; and in the excerpts reviewed we found no stable public API version or semver policy for dsh, so none is claimed.
What the capability-seams doc provides
The DeepSeek Harness capability-seams doc tags each service in the harness with one of four role values: core, seam, bundle, or service. Those four tag values are the doc’s. The doc’s intro also names the four kinds in words: “a core spine service, a swappable capability seam, a bundle/composition point, or a standalone service”. What is our inference is the pairing of each phrase to a tag, based on order and usage, since the doc does not state that mapping explicitly — and the versioning column is ours entirely.
| Role tag (per the doc) | Matching phrase from the doc’s intro (our pairing) | Versioning trade (our interpretation, hedged) |
|---|---|---|
core | Core spine service | Can reach many dependents when it breaks — though several core rows list no consumers (ctx.sessionController, ctx.schedule, ctx.goals) |
seam | Swappable capability seam | Consistent with the ctx.lsp row’s fixed-operation description (our inference); ctx.shell notes it can replace bash-local without touching consumers |
bundle | Bundle / composition point | Wiring changes can affect profiles, though the ctx.agentLoop row says extensions depend on dsh-agent events and services rather than on that package |
service | Standalone service | Fewer coupling points in some cases — but ctx.actionCards and ctx.translator do list consumers |
The doc tags roles; it does not assign a versioning cost to any of them. That is what the right-hand column is for, and the counter-examples in it are why each cell is hedged rather than stated as a pattern.
The binary side: compatibility is checked first against a declared range, when a plugin declares one
The releases page states an explicit rule for third-party plugin version compatibility. The DeepSeek Harness releases page records in both its dsh-v0.2.1-rc.1 and dsh-v0.2.1-alpha.4 notes that third-party plugin version compatibility is judged first by engines.dsh — a plugin’s declaration of which dsh versions it supports — with the pre-existing rules applying when it is undeclared, and adds that plugin authors should check that their declaration covers the DSH versions they support. We did not verify how uniformly the field is honored in practice.
So a plugin has two channels to track: the seams it attaches to, and the declared engines.dsh range it tolerates. In our reading, the service map describes the attachment points, and the release notes describe a first-priority check on the binary side.
How the seams stay classified: a hybrid, script-backed map
The doc is not purely generated. Its maintenance note reads: “Maintenance mode: hybrid: services are discovered from Cordis declarations; interface/implementation/consumer roles are classified in scripts/gen-doc-graphs.ts with a completeness guard.” The file header also marks the output as generated and not to be edited by hand.
Our reading of the split: the note’s three roles (interface, implementation, consumer) describe per-service package relationships, while the four core/seam/bundle/service tags are a separate axis; the note does not say where those tags are assigned. And our inference, labeled as such: a map assembled by a script with a completeness guard can be re-checked whenever it is regenerated, which a paragraph cannot. The doc states that the guard exists; it does not say what the guard checks, so we claim no more than that.
Case study: removing ./invariant changed the extension surface
The dsh-v0.2.1-rc.1 section of the releases page records the removal of runtime invariant plugins and each package’s ./invariant export, and states that developers who used those diagnostic entry points must adjust their extensions or custom profiles. The removal deleted a whole export surface rather than one function; our reading is that this makes it breaking for the extension surface rather than an internal refactor.
The rc.1 notes are not the only plugin-facing changes in the release history. The dsh-v0.2.2-alpha.2 notes record changes involving tools.resolve, a migration to async retained Session-projection handles (with legacy paths still compatible under deprecation notices), and a rerouting ban on agent/request. At retrieval on 2026-10-30, the releases list showed dsh-v0.2.1-rc.5 (published 2026-10-30) as its newest tag, ahead of dsh-v0.2.2-alpha.2 (2026-10-28). Collectively the notes show the pattern this post is about: plugin-facing surfaces get changed and removed, and the release notes are where that is recorded.
The counter-case: the LSP seam’s fixed-operation design
The ctx.lsp row in the capability-seams doc describes “provider registration and selection plus normalized query execution over exactly four operations”, and notes that the seam “offers no protocol escape hatch, so a backend translates into the normalized request and result”. Our interpretation: a small, enumerable surface like that is easier to keep compatible across releases than one that accepts arbitrary payloads, because the set of things a caller can depend on is finite and checkable.
Our proposal, stated as ours: growth on a seam like this should be a declared version change rather than a quiet extension, since a fixed operation set keeps growth visible in a declared range, where open-payload surfaces make that visibility harder. As further reading, and not a verified comparison: the MCP tools specification and the MCP security best practices are linked here only. We did not review either for this post, and no claim in it rests on them.
The workflow engine seam
The ctx.workflowEngine row is tagged seam. It lists workflow as the owning package, workflow-ptc as its implementation, and tool-workflow and tool-ralph as consumers, and describes the service as “one engine per context, as in bash, with no named-provider registry”. That last clause matters for the seam reading: a single engine service with no registry of named providers is a narrower surface than a provider list, and in our reading a future move to multiple engines would itself be a change at this seam. The doc states the shape; the versioning consequence is our reading, and the operational effect is not measured here.
Model-coupled harness versions
The DeepSeek API changelog entry for 2026-10-17 says DeepSeek V4.1 Flash “has been upgraded to DeepSeek-V4.1-Flash-1017”, that the API calling method and pricing are unchanged, and that users should “simply use deepseek-flash to access the latest model”. It also advises upgrading to DeepSeek Harness 0.2.1-rc.1 or later for the best experience with the new model, and says the model was optimized for DeepSeek Harness, Tencent CodeBuddy, WorkBuddy, and other platforms. It is advice, not a hard requirement; in the text of that entry we found no mechanism that binds a model version to a harness version.
That still makes the model part of the compatibility picture: authors track the seams they attach to, the declared engines.dsh range they tolerate, and the model behind their API name, and a change in any of the three could plausibly cause a regression. For the enforcement side of this coupling, see our earlier post on harness governance and enforcement points.
Aliases behave like unpinned dependencies
The DeepSeek changelog entry for 2026-09-10 says the previous-generation V4 Flash models were retired and that, for compatibility, the model names deepseek-v4-flash and deepseek-v4-flash-vision-exp are temporarily routed to V4.1 Flash, and it links to a news entry for details. That news entry’s contents are not verified here. Even though the change was announced, a caller that keys on the name gets a different backing model without changing its own code — and “temporarily” means the stopgap itself can go away.
The 2026-10-17 upgrade is the same pattern: the name stayed the same while the model behind it changed. The changelog’s own guidance is to keep using deepseek-flash, and we did not find a dated callable identifier presented in the excerpts reviewed. So the practical advice is to log what you resolved to: record the changelog date, the model behind the alias, and the harness release you are running next to the integration, so the next change is diffable. Treat an unpinned alias as a dependency you have not versioned.
What this means if you are building or extending a harness
These recommendations are ours, derived from the documentation reviewed here — they are not measured results:
- Track seams and the declared range together. The
engines.dshrule from the rc.1 and alpha.4 notes is the check the project points to; in our reading, the service map is the attachment-side surface. - Prefer a script-backed map to a hand-written one. The doc’s mode is hybrid: discovery from Cordis declarations, role classification in a script with a completeness guard. Our reading is that the script-backed half is the part a build can re-check.
- Record plugin-facing breaking changes in release notes. The invariant removal in rc.1 and the
tools.resolve, Session-projection, andagent/requestchanges in v0.2.2-alpha.2 show the release notes doing that work here. - Log model names and harness releases together. The alias changes above are only diffable if someone recorded what they resolved to.
Our DeepSeek Harness plugin-everything runtime review covers the general runtime model, and this post focuses on what changes when the extension surface itself is versioned.
FAQ
What is a capability seam in an agent harness?
The capability-seams doc tags each service with one of four role values, and its intro describes one kind of service as “a swappable capability seam”; matching that phrase to the seam tag is our inference, since the doc does not tie the two together. Reading a seam as the point where extensions attach to the harness is our gloss as well, not a definition the doc states. Separately, the release notes say third-party plugin compatibility prioritizes engines.dsh when a plugin declares it, so the declared range is part of the compatibility picture alongside the service map.
Why did removing the ./invariant export break extensions?
The dsh-v0.2.1-rc.1 release notes record removal of runtime invariant plugins and each package’s ./invariant export, and state that developers who used those diagnostic entry points must adjust their extensions or custom profiles.
Does the DeepSeek model version affect which harness version I need?
The changelog for 2026-10-17 advises DeepSeek Harness 0.2.1-rc.1 or later for the best experience with the upgraded model, while the rc.2 notes list adding support for DeepSeek-V4.1-Flash-1017 — the notes do not say whether rc.1 alone suffices, so check the release you actually run. It is advice, not a requirement. On the separate question of plugin compatibility, engines.dsh is described in the release notes as the first check when a plugin declares it; we found no mechanism in the changelog entry that binds a model version to a harness version.
The Bottom Line
DeepSeek Harness gives extension authors two things to track: the service roles in its capability-seams doc, and the engines.dsh declaration its release notes prioritize when a plugin declares one. The ./invariant removal in dsh-v0.2.1-rc.1 shows a removed extension export surface, and the alias changes in the DeepSeek changelog are consistent with model names behaving as unpinned dependencies. In the material reviewed we found no versioning policy — none of this is measured runtime data, and the versioning lessons drawn from it are ours.
How This Guide Was Built
This review is based on official documentation and release notes: the DeepSeek Harness capability-seams doc and GitHub releases page, and the DeepSeek API changelog. We did not run DeepSeek Harness hands-on, so every claim here is a reading of published sources, and interpretation columns and advice sections are labeled as ours.
- Primary sources: the DeepSeek Harness releases page, the capability-seams doc, and the DeepSeek API changelog.
- Sources linked but not verified for this post: the DeepSeek news entry on the V4 Flash routing (linked from the changelog; not fetched for this review), the MCP tools specification, and the MCP security best practices. No factual claim in this post rests on these.
- Limits: we did not verify a stable public API version, deprecation window, semver policy, what the completeness guard checks, or any hands-on behavior for DeepSeek Harness, so none is described here. No benchmark figures are used.
📖 Related Reads
- ToolBrain — tool reviews, LLM comparisons, and AI workflow guides
Cross-links automatically generated from CodeIntel Log.




