Repository navigation
[Bug] Pre-install guard invents an entry file for skill-only bundles: valid plugins are blocked on the git channel and reported to their authors #183
Description
DeepSeek Harness version
0.2.0-rc.2 (dsh --version)
Plugin Hub version
1.6.6 (source at main @ f9a5a20)
Node.js version
v24.13.1
Profile
web, clean DSH_HOME
Affected plugin
QingYunA/answer-me-with-html — and every plugin whose manifest declares dsh.bundle.patch and no main / exports
Steps to reproduce
- In the market, install
qingyuna/answer-me-with-html. It has no npm package (npm search repository:qingyuna/answer-me-with-htmlfinds none), so the install falls back to the git channel. /installanswers 400 before installing:
[packaging] github:QingYunA/answer-me-with-html: plugin distribution is incomplete —
the entry file index.js declared in package.json is not present in the git distribution
(build output not committed). Report to the author.
- The failure dialog files that on the author's repository: [dsh-plugin.org | dsh-plugin-hub] plugin distribution incomplete: qingyuna/answer-me-with-html QingYunA/answer-me-with-html#209.
Expected behavior
The install proceeds and the plugin's skill mounts. The package is complete: it is a skill-only bundle, and the file the guard asks for is one its manifest never declares.
Actual behavior
A valid distribution is blocked, with a report filed on the author's repo. Ran the guard's own steps (resolvePackageEntry + rootPackageEntryOfTarList) on the real codeload tarball of 90c8d49d (the live path cannot run from my network — git ls-remote hits PREFLIGHT_TIMEOUT_MS, and that path returns ok: true by design):
| what the guard checks | result |
|---|---|
resolvePackageEntry(manifest) for { dsh: { bundle: { patch: './cordis.patch.yml' } } } (no main, no exports) |
index.js |
root index.js in that tarball |
absent |
the cordis.patch.yml the manifest declares |
present |
The same happens to wjvalue/dsh-answer-me-with-html, which has the same manifest shape.
Why the guard, not the package
- dsh loads a bundle from its manifest and the patch that manifest names, and never imports the package:
bundleManifestin@deepseek-ai/dsh-plugin-manageris documented as "Read bundle metadata without loading its JavaScript", andbundlePatchPaths(...)is what gets applied to the profile. - The npm channel never runs this check (the registry is trusted), so the same shape installs there and is blocked here — the two channels disagree about one package.
- End to end on DSH 0.2.0-rc.2, clean
DSH_HOME, pnpm 10.34.7:
$ dsh plugin --profile web add github:QingYunA/answer-me-with-html
+ answer-me-with-html github:QingYunA/answer-me-with-html Packages: +5 Done in 20.3s
$ ls $DSH_HOME/profiles/web/node_modules/answer-me-with-html
bin cordis.patch.yml docs examples locale package.json README.md README.zh-CN.md skills src
(no index.js — as the manifest says)
$ dsh --profile web --dump-config | grep -A8 'answer-me-with-html'
# == answer-me-with-html
- id: answer-me-with-html-skill
name: '@deepseek-ai/dsh-skill-filesystem'
config:
providerName: answer-me-with-html
includeDefaultRoots: false
bundledSkillDir: !!js >-
process.getBuiltinModule('node:path').join(…, 'skills')
exit 0, no stderr: the bundle is registered in dsh.profile.bundles, its patch composes into the plugin tree, and nothing imports the package.
Fix
#182 — a manifest that declares no entry is no longer treated as missing one; a distribution is judged on what its manifest declares (the entry, when there is one, plus the dsh.bundle.patch files it names), and that the declared patch is present is now checked too. Both channels use the same rule. Open, CI awaiting approval.
Until it lands, affected users can install with dsh plugin --profile <profile> add github:<owner>/<repo>, which the plugin's README documents.
Checklist
- I have searched existing issues and this is not a duplicate.
Activity
SU-AN-coder commentedon Oct 13, 2026
Scope check, so this can be judged against how far the bug reaches. I walked the catalogue (
api.dsh-plugin.org/plugins.zh.json, 13,810 entries) and audited the top 80 by stars. 32 of those have a readable rootpackage.json(the rest are monorepos or carry no root manifest, where the pre-flight has nothing to inspect at all); of the 32:dsh.bundle.patch— bundles are the norm, not a corner.QingYunA/answer-me-with-html,mnemon-dev/mnemon,thebiggavin/marketingdashboard,zuorn/tydora. None of them resolves to an npm package whose metadata points back to its repository — three of the names are not on npm at all (answer-me-with-html,@mnemon-dev/dsh-mnemon,tydora→404from the registry), and the market only uses the npm channel when that reverse check passes. So for those four the git channel is the only channel, and the pre-install guard blocks all four today.yjh051108/dsh-routing-suite→injector/lib/index.js,sandbaseai/sandbase-harness→dist/index.js,hust-open-atom-club/oh-dsh→dist/plugin.js,toolclub/dsh-agent-team-gui→lib/index.js. These are the guard's true positives, and every one of them is built by aprepare/build script that a git install cannot run.oh-dshis also a live case for the second half of the rule: it declaresdsh.bundle.patch: ./dist/cordis.patch.yml, and the repository has nodist/.- insert: - name: <package>pattern the packaging guide shows), which is why the fix keeps the entry requirement for that shape and drops it only for the bundles that mount a provider instead.The audit is a small script (catalogue → root manifest → declared files → patch row names → npm reverse lookup); say the word and I will paste it here or turn it into a fixture.