DeepSeek Harness shared package contract regressions
None of these five problems is a misused API; in each case a shared package behaves differently from the contract it declares, so upgrading will not make them disappear. A user reviewed them one by one in read-only mode on 687f282e86 and concluded that 5 out of 5 are real defects. The patches and regression tests live on a fork branch and have not been merged upstream (Discussion #10065).
DeepSeek Harness shared package defects: what each one gets wrong
The common thread is that validation or comparison is narrower than the documentation, and each case can be triggered with a minimal input. Item by item:
deepEqualJsoninvaluescompares records withinplus member reads. Expected check:{"__proto__":{},"b":2}compares equal to{"a":1,"b":2}because an inherited member satisfies the left-handa. The fix compares own properties only.marketVersioninplugin-market-indexuses only a SemVer syntax regex. Expected check: an overlong version passes validation, but sorting the list withsemver.rcomparethrows a bareTypeErrorinstead ofMarketIndexError.PartialArguments#invalidinvaluesreads the value without going throughremember. Expected check: an invalid state discovered after the read does not triggerrefresh(), unlike the behavior ofcomplete().normalizeLlmFailureinllmrenders non-Errorthrows. Expected check: throwing{message, code}turns the error message into[object Object]and loses the original message.boundContextSummaryinllmtruncates by code unit. Expected check: when the cut lands inside a surrogate pair, the summary keeps a lone high surrogate and the message carries it into the persistence log.
The patch branch also corrects two pieces of documentation: the code-language JSDoc claims hcl maps to tf, while the actual table still maps hcl to hcl; and the plugin-market-index README claims no runtime dependencies, while the validator depends on semver and a package-manifest package. According to the thread, the reviewer considers the second description to count one more package than the code does.
The five defects have very different trigger surfaces, so triaging by input is safer than changing all five at once. Four steps:
- Check whether your JSON input can contain keys such as
__proto__orconstructor. Expected: only such input hitsdeepEqualJson; ordinary object comparison is unaffected. - Check whether the market index contains overlong or edge-case version strings. Expected: normal SemVer never triggers the
marketVersionsorting exception. - Check whether you depend on a callback after
PartialArguments#invalidchanges. Expected: callers that never read the field cannot reach the third defect at all. - Search logs for
[object Object]and replacement characters. Expected: the former points to a non-Errorthrow, while the latter points to summary truncation.
The value of triage is that most applications hit only one or two of these, and changing all five widens the regression surface for no benefit.
DSH plugin path 1: merge the patch branch
This suits people who can modify host source and want all five fixed in one pass. How to do it:
- Fetch the fork branch
fix/shared-contract-regressions-20261017. Expected: five separate commits, one for each defect above. - Read the commit messages and cherry-pick only what you need onto your baseline. Expected: each commit touches one package, so conflicts stay contained.
- Run the tests for the package and for affected consumers. Expected: the new regression cases fail on the unfixed source and pass after the fix.
- Record your baseline commit and the cherry-pick order. Expected: on the next host upgrade you can tell whether upstream absorbed these patches.
The five commits are fc74097e0e (deepEqualJson), 038c710d33 (marketVersion), b49f975945 (invalid observation), d451d26f9b (non-Error throws), and 61ee3f668e (surrogate truncation). According to the thread, all of them include regression tests.
DeepSeek Harness path 2: patch individual packages locally
This suits people who do not want to replace the host and only need to fix the one or two packages they actually hit. Steps:
- Decide which package really affects your feature; do not change all five. Expected: a list of one or two package names and the scenario that triggers them.
- Override that package's build output with your existing patch mechanism, touching only the comparison or validation logic. Expected: the package version is unchanged and behavior changes as intended.
- Add a minimal case for each change, using the JSON or version string from the checks above. Expected: the case fails without the patch and passes with it.
- Re-apply the patch and re-run the cases after a host upgrade. Expected: the patch still applies, or upstream fixed it and you can delete the patch.
The cost of local patches is rechecking offsets on every upgrade, especially line numbers inside minified output. Assert on behavior rather than line positions and you avoid much of that rework.
DeepSeek Harness path 3: add defenses at the call site
This suits people who cannot change dependencies at all and only need their own plugin to stop misbehaving; before publishing a plugin on DSH Plugin Hub, confirm these package behaviors cannot break it. Three common defenses:
- Normalize to own properties before comparing JSON, for example by taking only what
Object.keysenumerates. Expected: members on the prototype chain no longer affect equality. - Before using the return value of
marketVersion, runsemver.validyourself and enforce a length limit. Expected: overlong versions are rejected before sorting and the bareTypeErrornever happens. - When catching a non-
Errorthrow, check for an own stringmessagebefore falling back toString(value). Expected:[object Object]no longer appears in logs.
Call-site defenses do not fix the shared packages, and other callers still hit the defects. Their value is containing the failure at your boundary while you wait for an upstream merge.
DeepSeek Harness: use regression tests to prove the patch works
A code diff is not enough; each of the five needs a minimal input that can fail on its own. Build the tests in order:
- Write an equality assertion for
deepEqualJsonwith a__proto__key. Expected: on unfixed code the assertion passes (wrongly equal); after the fix it fails (correctly unequal). - Write an overlong version case for
marketVersionthat asserts aMarketIndexError. Expected: unfixed code raisesTypeError. - Write a case that reads
invalid, changes the content, and countsrefreshcalls. Expected: unfixed code does not refresh. - Write one string assertion each for non-
Errorthrows and surrogate truncation. Expected: the first no longer contains[object Object], and the second no longer contains a lone surrogate.
These cases must fail against the current source; otherwise they protect nothing.
DeepSeek Harness: notes for handling contract defects
Separate "the documentation is wrong" from "the implementation is wrong", because the fixes differ. Four points:
- When documentation is stronger than code, whether to fix docs or code depends on whether callers already rely on the documented semantics. If someone writes calls against the docs, fix the code.
- Fixing a shared package requires running consumer tests too; the change surface in
valuesandllmis larger than it looks. - When external PRs are not accepted, a fork branch plus a discussion thread is the viable submission route for now. Do not leave the patch only on your machine.
- After a host upgrade, recheck whether these commits were absorbed, so the same logic is not changed twice.
According to the thread, none of the five has entered an official release; the state is "patch available, merge pending". Writing them into your compatibility notes as known boundaries is more practical than waiting for an uncertain fix date.
The three paths differ as follows:
- Merge the patch branch: changes five packages at once, needs conflict resolution on upgrade, and suits people who can modify host source.
- Patch individual packages: changes only the one or two you hit, at the cost of rechecking build output offsets on every upgrade.
- Defend at the call site: touches no dependencies, but you maintain the defense yourself and other callers still hit the defects.
They are not mutually exclusive. A common order is to stop the bleeding with call-site defenses, then cherry-pick the commits you need. If you maintain several host branches, keep a per-branch list of merged commits so upgrades do not reopen settled patches.
Source: Discussion #10065, fix/shared-contract-regressions-20261017. For more plugin-side checks, see DSH troubleshooting.
FAQ
DeepSeek Harness compared records with in checks plus member reads, so members inherited from Object.prototype also satisfy a key on the left side. As a result {"__proto__":{},"b":2} compares equal to {"a":1,"b":2}. The fix is to compare own properties only; the commit on the patch branch is fc74097e0e.
DeepSeek Harness accepts overlong version numbers and lets sorting throw a bare TypeError instead of the documented MarketIndexError. The regex checks syntax only, while the actual sort uses semver.rcompare, which also limits total length and each numeric identifier. The patch validates with node-semver instead.
DeepSeek Harness normalizeLlmFailure renders the thrown {message, code} as a plain object string. The patch reads an own, data-backed message field without triggering accessors and keeps code as UNKNOWN, because third-party error codes are outside the harness classification.
DeepSeek Harness writes a summary to the persistence log with a lone high surrogate, shown as a replacement character or garbled text, and later code that walks by code point can become misaligned. The fix drops the unpaired half when the cut lands inside a surrogate pair.
Related Terms
- deepEqualJson
- deepEqualJson is the values package function that compares two values with JSON semantics. A correct implementation compares own properties only and must not let members from the prototype chain affect equality.— https://github.com/deepseek-ai/deepseek-harness/discussions/10065
- marketVersion
- marketVersion is the plugin-market-index function that validates the market index version. It must satisfy both SemVer syntax and the range the sorting implementation accepts.— https://github.com/deepseek-ai/deepseek-harness/discussions/10065
- PartialArguments#invalid
- PartialArguments#invalid is the read-only answer in the values package that says whether streaming arguments are already invalid. Reading it should register an observation like complete(), or later invalid changes do not trigger a refresh.— https://github.com/deepseek-ai/deepseek-harness/discussions/10065
- surrogate pair
- A surrogate pair is the UTF-16 encoding of one supplementary-plane character as two 16-bit code units. Truncation by code-unit index must never keep only one half.— https://github.com/deepseek-ai/deepseek-harness/discussions/10065
Sources
- deepseek-harness Discussion #10065: five verified shared-package fixes on a fork branch· deepseek-ai (GitHub Discussions)
- Patch branch atharvaHJoshi/deepseek-harness @ fix/shared-contract-regressions-20261017· GitHub (atharvaHJoshi)