Every time DSH ships a new release, existing plugins can stop working. This skill reads the vendor's official upgrade guide directly, scans your plugin code, and reports which breaking changes you hit together with the vendor's own fix instructions; it also scaffolds a runnable plugin from zero in one command and verifies it. Adapted through 0.2.2-rc.1, field-verified on 0.2.2-rc.2: rc.1 has no vendor guide entry yet, so its official Release Note is folded in as a virtual guide and coverage still reads complete; the rc.2 host — newer than every official npm channel at the time of testing — was verified live, where version resolution returned an honest
ahead-of-upstreamverdict and the export-surface diff across 391 core packages found zero removals. If a future version has neither a guide nor release notes, the ledger says outright that the scan cannot be called clean instead of pretending otherwise. Also features local environment anchoring, Release Note targeted extraction, and fleet multi-dimensional governance.
| Upstream ships a new release | Works immediately, zero changes (reads vendor sources and release notes, no hand-curated cards) |
| DSH Host Compatibility | Covers v0.1.7-rc.2 through 0.2.2-rc.1 (that version's official Release Note is converted into a virtual guide); host 0.2.2-rc.2 field-verified live while ahead of every official channel (391-package export-surface diff: zero removals). A newer version with no vendor source at all makes the coverage ledger say the scan cannot be called clean |
| Fleet Governance Board | One-click sweep across Web/APP installed plugins & workspace code with life-cycle matrix |
| Version Authority | Strictly anchors to the local installed host version by default (Plan B: 0 network requests) |
| Scan false positives | 12 → 0 (four noise-reduction layers + word boundary regex + virtual guide deduplication) |
| Verifying one change | 3,600 s real host cold start → millisecond-scale in-memory smoke test (with unbuilt check & host module fallback) |
| Ghost host | Warns when the disk has new code but the running process still executes the old one (compares process start time, not version strings) |
| Fake-green check | Warns when tsconfig paths point at a missing checkout, where TypeScript silently falls back to published types |
| Self-test | 270 assertions, runs offline |
| External dependencies | 0 (Node built-ins + the git/npm commands only) |
| Cross-platform | Native support for macOS, Linux standard paths, Termux Android, and containers (XDG-compliant) |
| Scaffolding | One command emits a runnable plugin in five forms, verified on creation, then a write gate issues the birth certificate |
DSH (DeepSeek Harness) is an AI runtime framework where everything is a plugin, and the trouble is that every new release can break existing plugins. The common workaround is hand-written upgrade cards: dozens of cards per version range, each recording what broke and how to fix it. That path has three problems it cannot get around:
- Cards go stale the moment they are written. A single upstream jump can touch thousands of files, and there are "corridor gaps" the cards never cover.
- A large knowledge base crowds out reasoning. In the paper's evaluation a weaker model (qwen3.8-27b) scored -3.07 pp worse with the full card library loaded (equal-weight difference over 56 tasks: 7 improved, 18 regressed, 31 flat).
- Verification is expensive. Every change needs a real host cold start (a 3,600-second timeout is on record), and stale packages left in the profiles overlay after a host upgrade break plugin loading.
This project takes a different approach: maintain the method of obtaining knowledge, not the knowledge itself. The authoritative description of breaking changes lives in the vendor harness repository at docs/upgrade-guide/<version>/<topic>/guide.md, updated with each release in a fixed format (## Change for what changed, ## Migration for how to fix it); version information lives in the npm registry's dist-tags. Both are vendor sources, so the skill catches up the moment upstream ships.
- Adapted through 0.2.2-rc.1, field-verified on 0.2.2-rc.2: reads the official
docs/upgrade-guide/and Release Notes directly. The guide stops at 0.2.2-alpha.3, so 0.2.2-rc.1 is covered by converting its official Release Note (27k+ characters, with a full breaking-changes section) into a virtual guide; that is why coverage still reads complete. The 0.2.2-rc.2 host — ahead of every official npm channel — was verified live on 2026-11-12: honestahead-of-upstreamresolution plus a zero-removal export-surface diff across 391 core packages. Also generates virtual guides and speeds up scans with a 3-tuple compatibility ledger - Local environment authority anchoring (zero network reliance): defaults to the locally installed DSH host version (Plan B, 0 external network requests), eliminating upstream network jitters and GitHub rate limits; uses
--check-upstreamfor explicit check - Fleet multi-dimensional governance board: introduces
fleet-sweep.mjsto inspect workspace code, installed Web plugins, APP desktop plugins, and active processes in a multi-stage life-cycle matrix, with--apply-compatbatch safe patching - Hard guards against false positives & unbuilt traps:
- Four noise-reduction layers + regex word boundaries (preventing
ABORTEDmatchingFS_ABORTED) - Virtual release note & official guide deduplication
- Unbuilt TypeScript plugin hard gate (blocks and guides
pnpm run buildwhen missinglib/index.js) - Bundle Resolution Shadow detection for host-bundled packages
- Exit code 143 (
SIGTERM) acknowledged as graceful shutdown, eliminating false crash alarms - Auto Schemastery
Config({})parsing and temporary hostnode_modulesfallback symlinking during smoke tests
- Four noise-reduction layers + regex word boundaries (preventing
- Cross-platform & container ready: eliminates hardcoded directory assumptions, supporting Linux standard paths (
/usr/lib/node_modules), Termux on Android ($PREFIX/lib/node_modules),npm_config_prefix,DSH_HOST_PATH/DSH_LOCATIONenv overrides, and XDG cache specs - Cheap verification: in-memory Cordis smoke test returns in milliseconds to seconds without a real host cold start;
--real-smokeprovides real-host isolated profile boot verification - Zero external dependencies: Node built-ins plus
git/npmcommands only - Reproducible: 270 assertions, runs offline; CI runs on ubuntu, macOS, and Windows
- More than adaptation:
scaffold.mjsemits a runnable plugin in five forms in one command, andwrite-gate.mjsissues a birth certificate - Silent failures have hard evidence:
ghostHostcompares process start time against disk change time;falseGreencatches TypeScript silent fallbacks - Honest about its limits: passing smoke test ≠ host compatibility, and the tool states this clearly in its output
The main entry only routes. Each lane owns one job, and the agent reads the matching document instead of loading all four:
SKILL.md main skill: pick a lane + one-shot pipeline + cross-lane discipline
sub-skills/adapt/SKILL.md upgrade adaptation: resolve version → fetch guide → scan hits → seams → smoke → audit
sub-skills/build/SKILL.md plugin authoring: scaffold five forms + write-gate birth certificate
sub-skills/diagnose/SKILL.md environment and boot failures: env-doctor + log-doctor + env-heal
sub-skills/review/SKILL.md code review and architecture audit: P0/P1/P2/P3 grading + sub-agent dispatch
scripts/ shared toolbox for all lanes, not split per lane
references/ noise rules, migration SOP, CI template
build, diagnose and review also ship optional top-level aliases so they can trigger on their own (they are not required — the main skill reads the lane document by intent):
ln -s <repo>/sub-skills/build ~/.agents/skills/dsh-plugin-build
ln -s <repo>/sub-skills/diagnose ~/.agents/skills/dsh-plugin-diagnose
ln -s <repo>/sub-skills/review ~/.agents/skills/dsh-plugin-reviewThe aliases exist so "author a plugin", "installed but not working" and "review this code" each get their own trigger surface instead of competing inside one description. Host loaders cap description at 1024 characters and drop the whole skill when it overflows (they do not truncate); the self-test now guards that limit.
With the skills CLI (recommended — one command installs to every supported agent):
npx skills add taxueseek/plugin-fast-adaptClaude Code marketplace:
/plugin marketplace add taxueseek/plugin-fast-adapt
/plugin install plugin-fast-adaptnpm (ships a plugin-fast-adapt command that forwards to the one-command pipeline):
npx plugin-fast-adapt <plugin-dir>Manual install:
git clone https://github.com/taxueseek/plugin-fast-adapt.git
# Point your agent at the repository root (where SKILL.md lives) as a skill directory
# Cursor users: cp -r plugin-fast-adapt/* .cursor/skills/plugin-fast-adapt/Run the whole chain with one command (recommended); every run writes a local log and updates the compatibility ledger:
node scripts/run.mjs <plugin-dir> # env → version → guide → scan → build-check → audit → smoke → typecheck
node scripts/run.mjs <plugin-dir> --check-upstream # explicitly check upstream npm registry and release tags
node scripts/run.mjs <plugin-dir> --real-smoke # plus one more tier: install & boot in a clean profile (bridges upstream verify-runtime)
node scripts/run.mjs <plugin-dir> --offline # skip fetching vendor sources (no npm read, no clone); local all-step pipeline
node scripts/run.mjs <plugin-dir> --no-clone # resolve the version but do not fetch the guide (use an existing local clone)
node scripts/run.mjs <plugin-dir> --strict # exit 2 when the scan did not run or the guide does not cover the target version (CI)
node scripts/run-log.mjs list # review past runs (tool version@commit included)
node scripts/run-log.mjs doctor # cross-check run logs × host startup logs (first stop for "plugin erroring")
node scripts/run-log.mjs sanitize --latest --out share.json # sanitise before sharing
npm run release-check # release preflight: version sync, tag, npm publish state, pack contents, self-testWhen upgrading DSH hosts or managing monorepos, sweep and categorize all plugins:
node scripts/fleet-sweep.mjs # full matrix board: running, workspace, web, app, disabled
node scripts/fleet-sweep.mjs --running # active plugins currently loaded in running host
node scripts/fleet-sweep.mjs --workspace # workspace source plugins only
node scripts/fleet-sweep.mjs --web # Web profile plugins only
node scripts/fleet-sweep.mjs --app # Desktop (APP) profile plugins only
node scripts/fleet-sweep.mjs --disabled # disabled/inactive plugins and reasons
node scripts/fleet-sweep.mjs --target 0.2.2-rc.1 --apply-compat # batch adapt zero-hit pluginsDetailed SOP and multi-platform practices are in references/user-guide.md.
You can also run each step on its own (the six-step spine remains; run.mjs just chains the steps below, and the optional ones are added as needed):
# 1. Inspect the local environment: installed version, stale overlay packages,
# installed plugins, activation readiness. Also two silent-failure judges:
# ghostHost (process still running old code) and falseGreen (tsconfig paths fake green)
node scripts/env-doctor.mjs <plugin-dir> --brief # omit raw patch lines, 80.5KB -> 4.5KB
# 2. Resolve the target version: what is upstream's latest, should this machine follow it
node scripts/guide-sync.mjs <local-version>
# 2b. Upstream watch (cron/agent friendly): exit 1 = new version out (guides prefetched),
# 0 = nothing to do, 2 = could not determine
node scripts/guide-sync.mjs --check
# 3. Fetch the guide for the scan window target (managed branch snapshot first;
# never leave --target empty and follow upstream's newest)
node scripts/guide-sync.mjs <local-version> --target <scan-target> --clone
# 4. Find which changes the plugin hits
node scripts/code-scan.mjs <plugin-dir> <upgrade-guide-dir> <local-version> <target-version>
# 4b. Seam query: dual-source verdict for a package/API symbol across the official
# guide anchors and the local host install ("removed" is only concluded when both agree)
node scripts/seams.mjs dsh-settingsHeal stale overlay packages first when any are reported (dry-run by default):
node scripts/env-heal.mjs # report only
node scripts/env-heal.mjs --apply # move to ~/.dsh/.trash/<date>/, never deleteTwo optional steps complete the "verify as you build, audit as you upgrade" loop:
# 5. Post-fix smoke verification: in-memory Cordis mock checks module loading,
# the apply contract and tool registration. Undeclared-inject host-service
# access is rejected with the same contract error the real host throws.
node scripts/quick-smoke.mjs <plugin-dir>
# 6. Four-dimension audit while you are at it: performance, resilience,
# context budget, lifecycle
node scripts/plugin-audit.mjs <plugin-dir>
node scripts/plugin-audit.mjs <plugin-dir> --guide <guide-root> <local-version> <target-version>
node scripts/plugin-audit.mjs <plugin-dir> --guide <guide-root> <local-version> <target-version> --peer-patch # print verified peer patches
# 7. One-command host-log diagnosis: StartupError / port-in-use /
# undeclared inject / dead client entry
node scripts/log-doctor.mjs --pattern '^startup-' --limit 5
# 8. Sync the skill surface to a downstream skill directory (--check = drift only)
node scripts/sync-skill.mjs --dest <downstream-skill-dir> --checkA naive first version reported 12 findings on a real plugin; on inspection all 12 were false positives. The current version applies four layers of noise reduction, and the same plugin reports 0:
- The scanner uses a state machine to skip comments and strings, so a name mentioned in a comment is not a hit
- Full member chains win; overly generic parent chains like
ctx.toolsare dropped - Generic words (
register,resolve,readFile) and short names never become anchors; "old → new" replacement pairs are recognized, so a plugin already using the new symbol is not reported - Constant anchors come only from the
Changesection; matching requires the object parts to be mutual suffixes, soengines.dshnever collides withresult.dsh - Package semantic gate: a package name becomes an anchor only when mentioned in a sentence with a removal/renaming verb — contextual mentions ("The mode fields of X accept only …", about field values) do not count. All 3 criticals reported on dsh-files were of this kind; the gate zeroed them
Each finding carries a severity (package=critical, member=high, code=medium — fix the front of the list first), an evidence line (the source line itself, so checking for false positives needs no file opening) and provenance anchors (guideFile/guideLine, pointing straight at the official guide's original location). The rules and the measurements behind them are in references/heuristics.md. Scan roots are the union of source roots (src plus sibling client/web/ui); build outputs (lib/dist) are not scanned twice. The smoke test discloses its mock fallbacks: the mockFallbacks list in the output names every property the plugin touched but the mock does not provide — the longer that list, the less the result can be trusted. A passing smoke test is not host compatibility, and the tool says so in its output, not just in the docs. The smoke test also rejects undeclared-inject host-service access at the inject_contract stage, matching the real Cordis contract, instead of letting load-time crashes pass silently. When you need real-host evidence, run.mjs --real-smoke bridges upstream plugin-upgrade's verify-runtime.mjs: install → boot → four-class attribution in a clean profile (honestly skipped with install guidance when the script is absent).
node scripts/scaffold.mjs <namespace>/<name> --form tool|hook|service|config|llm-adapter [--out <dir>] [--harness <version>]One command emits a runnable plugin in five forms: package.json (build-free pure-ESM invariants), a complete entry implementation per form, a cordis.patch.yml mounting row, and a dsh-plugin.naming.json with collision-resistant naming projections derived in full (the output passes upstream validate-names in --strict mode). Non-empty target directories and invalid coordinates are rejected before anything is written.
The entry ships a working starting capability (echo tool, observing hook, example service method, config with defaults, OpenAI-compatible adapter) — swap in your own; the full contract still follows the five form references of plugin-write.
Verification runs in two layers, and each layer reports when it is skipped: tool and hook use the dependency-free in-memory smoke test; all five forms run a real-base-class load check — when the host is installed, the entry is imported against the real @deepseek-ai/* base classes to prove the API is used correctly (Service inheritance and super(ctx, name), real Schema validation, LlmAdapter inheritance and route registration). When no host is installed it is honestly skipped, never faked. When the capability is written, gate it in one command:
node scripts/write-gate.mjs <plugin-dir> # birth certificate: hard gates auto-judged, soft metrics passed throughThere are only three hard gates (entry artifact exists, smoke passes, zero critical findings against the official guide); a failing one exits 1. Audit scores, high/medium findings, mockFallbacks and the not-yet-mounted fact all land in the discretion section labelled for human judgment — the tool never says "qualified" on your behalf. Guide discovery reuses the guide-sync cache (zero network); a new plugin is scanned against the full historical corridor; pass --skip-smoke right after scaffolding to skip the duplicate smoke run.
Zero external dependencies. Only Node built-ins (node:fs, node:path, node:os, node:child_process) plus the git and npm commands.
No TypeScript, no AST library, no HTTP client. Runs on Node 22.13+ (import.meta.dirname needs 20.11+, the optional type stripping needs 22.13+; type stripping is off by default).
Self-test:
npm test # node scripts/self-test.mjs, 270 assertionsContributors should enable the pre-commit gate (one time): git config core.hooksPath .githooks — every commit runs the self-test, so a forgotten downstream sync is caught at commit time.
Covers scanner false positives (names in comments and strings are not hits), false negatives, version heuristics, replacement-pair recognition, end-to-end findings (with guide file + line provenance anchors), dual-source seam-query verdicts (agree-removed / host-still-present disagreement / honest no-record), run-log × host-log cross-checks, the --real-smoke bridge tier (fail → exit 2 with a next-step pointer), the upstream-watch exit codes, the sync commit-command suggestion (adds only the synced path), SOP reference integrity, dist-tags cache states, smoke verification (including the undeclared-inject contract rejection), the four-dimension audit (including peer patches), activation diagnostics, ghost-host four states (stale/ok/unknown/no-running-host) with disk-time provenance, tsconfig paths fake green (extends chains, JSONC comments, wildcard prefixes, non-host aliases downgraded), the plugin scaffolder (all five forms, naming-projection grammar, smoke closure, patch-layer recognizability, invalid-input and non-empty-target rejection), the write gate (hard-gate interception, soft metrics never overrule, skip semantics, scaffold handoff), log diagnosis, downstream-sync drift checks plus a real-machine zero-drift gate, cache-root injection (the self-test never writes the real user cache), one-time run-log ledger migration (legacy ~/.cache root moves to ~/.local/state), a self-test size gate, a scanner performance gate, full incident-fixture regression (fixtures/ cross-checked against references/incident-ledger.md, with both sides of every tightened criterion pinned), a single-source state-vocabulary check (lib/run-states.mjs), and a doc-layering check (process reports are archived under docs-local/archive/ and never enter the skill surface). The self-test itself is zero-network and zero-dependency, and runs on any machine.
To gate your own plugin's repository at commit time (smoke/typecheck as hard gates, audit as a soft report), see references/ci-snippet.md.
| Script | Responsibility |
|---|---|
scripts/cli.mjs |
npm entry (npx plugin-fast-adapt), forwards to run.mjs |
scripts/run.mjs |
One-command orchestration of the full chain (env → version → guide → scan → audit → smoke → typecheck), unified report plus a local run log; --real-smoke bridges upstream verify-runtime for a real-cold-boot tier |
scripts/run-log.mjs |
Run-log viewing (list/show), cross-checking (doctor: run logs × host startup logs) and sanitised export (sanitize) |
scripts/seams.mjs |
Seam query: dual-source verdict for one package/API symbol across official guide anchors and the local host install |
scripts/scaffold.mjs |
Scaffold a plugin from zero: one command emits a runnable plugin in any of the five forms (package.json invariants + complete form entry + patch layer + naming projections), verified on creation |
scripts/write-gate.mjs |
Gate a finished plugin: orchestrates smoke + activation readiness + four-dimension audit + official-guide scan into a birth certificate; only three hard gates auto-judge, soft metrics pass through untouched |
scripts/env-doctor.mjs |
Probe the local DSH environment (version, overlay, plugins, processes, activation readiness, ghost host, tsconfig fake green) |
scripts/env-heal.mjs |
Heal stale overlay packages (dry-run by default) |
scripts/guide-sync.mjs |
Resolve the target version and fetch the official guide (managed default-branch snapshot, 1-hour TTL; release tags are an offline fallback marked frozen) |
scripts/release-check.mjs |
Release preflight: version sync, tag, npm publish state, npm pack contents, self-test and worktree; read-only, never tags or publishes |
scripts/code-scan.mjs |
Scan plugin code against official change anchors |
scripts/quick-smoke.mjs |
Post-fix smoke verification (in-memory Cordis mock, discloses fallbacks) |
scripts/plugin-audit.mjs |
Four-dimension performance & architecture audit, optional --guide cross-check; --peer-patch prints verified peer patches |
scripts/standards-scan.mjs |
Upstream standing-rule detection (7 mechanically-decidable rules with defensive-patterns provenance); --rules prints the table |
scripts/codemod.mjs |
Deterministic code/package-surface autofix (Loader entry exports, peer deps, top-level await); dry-run by default, --apply writes with a backup |
scripts/types-diff.mjs |
Host .d.ts and export-surface diff; synthesises virtual guides keyed by baseline version |
scripts/fix-peer-deps.mjs |
Batch-move host core packages from dependencies into peerDependencies; dry-run by default, --apply writes with a backup |
scripts/fleet-sweep.mjs |
Fleet-wide governance and inspection with a matrix board and JSON report; --apply-compat backs up before batch-writing ledgers |
scripts/log-doctor.mjs |
One-command diagnosis of ~/.dsh/logs/ (startup header / failed plugins / waiting services / signal summary) |
scripts/sync-skill.mjs |
Sync the skill surface to a downstream skill directory; --check reports drift |
scripts/self-test.mjs |
Self-test |
scripts/lib/scanner.mjs |
Lexical scanner and version comparison (zero-dependency) |
scripts/lib/guide-parser.mjs |
Official guide parsing and anchor extraction |
scripts/lib/runlog.mjs |
Run-log writing, indexing and sanitisation |
scripts/lib/host-modules.mjs |
Resolves the host @deepseek-ai/* base classes and runs the real-base-class load check |
scripts/lib/package-json.mjs |
Single source for reading package.json: strips UTF-8 BOM, lenient/strict modes, missing/corrupt/ok tri-state |
scripts/lib/cache-root.mjs |
Single source for the cache root (DSH_PFA_CACHE_DIR > DSH_CACHE_DIR > XDG_CACHE_HOME > ~/.cache); self-test can isolate it |
scripts/lib/backup.mjs |
Shared backup contract for the three autofix entry points: { backupDir, backupFiles, backupRel }, NO_BACKUP when nothing changed |
references/user-guide.md |
Comprehensive user guide (local anchoring, cross-platform adaptability, Web/APP fleet governance, guardrails) |
references/legacy-migration-sop.md |
Legacy migration SOP (for ranges the official guide does not cover) |
references/heuristics.md |
Scan noise-reduction rules and the measurements behind them |
references/incident-ledger.md |
Incident ledger: one line per real false positive/negative, each pointing at a minimal reproduction under fixtures/ |
references/ci-snippet.md |
CI gate template for plugin repositories (smoke/typecheck hard gates + audit soft report) |
env-doctor,code-scan,plugin-audit,log-doctor,seamsare strictly read-only;run-logis read-only except forsanitize --out <file>, which writes the sanitised result to the given pathenv-healis dry-run by default and moves rather than deletes when applied (into~/.dsh/.trash/<date>/)sync-skillwrites to a downstream skill directory explicitly, copying only the fixed skill surface (SKILL.md/README*/references/scripts/sub-skills);--check/--dry-runlet you inspect first- Never modifies DSH itself, nor config or profile declarations under
~/.dsh - Automatic plugin-code edits are limited to three mechanically-decidable classes, always with a backup first:
codemod(Loader entry exports, top-level await),fix-peer-deps(host core package peer relocation) andfleet-sweep --apply-compat(batchpackage.jsoncompatibility ledger and peer ranges). All report by default and write only with--apply/--apply-compat, backing up the original to<plugin>/.pfa-backup/<timestamp>/. Everything else reports findings and vendor fixes only;plugin-audit --peer-patchalso prints rather than applies .pfa-backup/is the local snapshot taken before an autofix; it is listed in the release gate'sFORBIDDEN_PACKand in the.gitignorethat scaffold generates, becausenpm packdoes include it (measured) and the backup holds the pre-editpackage.json- The cache root is injectable (
DSH_PFA_CACHE_DIR>DSH_CACHE_DIR>XDG_CACHE_HOME>~/.cache); the self-test points it at a temp directory on startup and never writes the real user cache - Network is used only for "fetching vendor sources": version resolution reads npm
dist-tags, guide fetching clones the official repo. Both have timeouts and report failures explicitly instead of silently skipping;dist-tagsis cached for 1 hour and degrades to the stale cache with astalemarker; guides reuse an existing local clone first, and--no-cloneskips the fetch
The official upgrade guide only goes back to dsh-v0.1.7-rc.2. For older plugins, follow the legacy migration SOP: use the upstream plugin-upgrade skill's hand-curated card corridor (from dsh-v0.1.0-rc.8 on) as the difference source and walk an eight-stage checklist (mode → read-only prep → ghost-host check → corridor assembly → seven touchpoint classes → plan & confirm → implementation → six-layer validation). The SOP references rather than copies the cards, so renamed cards are caught by the self-test's dead-link assertion.
- The official upgrade guide does not cover every breaking change (package retirement is one class that is not documented there); the
env-doctoroverlay inspection covers that case - Same-named symbols can still collide (a plugin's
path.resolve()versus the guide'sruntime.resolve()) and require human judgment of the surrounding code - Static matching only, no runtime-behaviour verification; the smoke mock covers the common host surface only
- The ghost-host check covers CLI host processes only: Windows has no
ps etime, and desktop Electron renderers are excluded; both cases reportunknownwith the reason instead of guessing
This project was split out of oh-my-dsh/dsh-plugin-upgrade-skill (a skill collection that teaches AI agents to upgrade DSH plugins, with an arXiv paper) via git subtree and has evolved independently since. As of 2026-10-26, the upstream project carries 198 upgrade cards, 12 skills and a 65-case auto-graded benchmark.
The two projects complement each other:
| Aspect | Upstream | This project |
|---|---|---|
| Difference source | Hand-maintained upgrade cards | Official docs/upgrade-guide/ + npm dist-tags, updates with upstream automatically |
| New release ships | Wait for cards, corridor gaps in between | Works immediately, zero changes needed |
| Verifying one change | Real host cold start, measured up to 3,600 s | In-memory Cordis smoke test, milliseconds to seconds |
| Stale overlay packages | Manual troubleshooting | env-doctor inspection + env-heal healing (dry-run by default) |
| Weaker models | Full card library in context, -3.07 pp | Six independent scripts, one small output each |
| Code-level scanning | None | Anchor matching + four noise-reduction layers |
| Fleet-wide sweep | plugin-fleet-sweep owns breadth |
The six-step pipeline owns depth |
A fleet-wide sweep after a host upgrade goes to upstream's plugin-fleet-sweep (breadth), and each flagged plugin comes back to this project's six-step pipeline for a deep pass (depth). For historical corridors the official guide does not cover (before v0.1.7-rc.2), this project's SOP references upstream's cards and scripts — segments with a guide use this project's code-scan, segments without use upstream's plan-migration.mjs and cards, and runtime verification uses upstream's verify-runtime.mjs (directly bridgeable via this project's run.mjs --real-smoke).