DSH Lifeboat
English | 简体中文
DSH Lifeboat is an out-of-process recovery console for DeepSeek Harness profiles. It can still start when a profile cannot: every probe runs against a temporary DSH_HOME, and the original profile manifest and patch files stay read-only until the user explicitly applies a recovery.

What is included
- A loopback-only Web UI at
127.0.0.1with live probe progress, evidence, verified recovery-plan selection, report download, and one-step undo. - A CLI mode that emits the same
dsh-lifeboat/v1JSON report without the UI. - Config probes using
dsh --profile <name> --dump-config. - Optional runtime probes that require the process to survive the full configurable startup window; any earlier exit, including exit code 0, fails the boot probe.
- One bounded configuration snapshot per diagnosis, cloned into a fresh temporary Home for every probe attempt; runtime results are confirmed twice by default and mixed evidence never enables recovery.
- Bounded upper-bound-first removal search over the complete Profile: delta debugging finds a small verified plan, then shallow exact enumeration proves whether any smaller plan exists.
- Separate checks for profile-level and Harness-home
cordis.patch.ymlfailures. - Full probe-input fingerprint checks before recovery, optimistic manifest hashing, timestamped backups, and atomic recovery writes.
- A bounded diagnosis queue, graceful process shutdown,
GET /api/health, browser-session reconnect, restart-safe report/undo recovery, and atomically persisted reports. - A small Harness plugin that writes
~/.dsh/lifeboat/last-healthy.jsononly after the Loader settles. The rescue server itself never runs inside the failing Harness process.
Run from this checkout
Node.js ^22.19.0 || >=24.0.0 is required. There are no runtime dependencies.
node ./src/cli.js serve
Open the printed http://127.0.0.1:<port>/ address. The default port is 4317; use --port 0 for a random free port.
Terminal reports are stored under $DSH_HOME/lifeboat/reports. The service keeps the newest 500 by default; use --max-reports N, or --max-reports 0 only when an external retention policy owns cleanup. See service operation for systemd and Windows Task Scheduler guidance.
Run without the UI:
node ./src/cli.js diagnose --profile web
node ./src/cli.js diagnose --profile web --json
node ./src/cli.js diagnose --profile web --mode boot --allow-runtime-code-execution
node ./src/cli.js diagnose --profile web --mode boot --boot-confirmations 3 --allow-runtime-code-execution
node ./src/cli.js diagnose --profile web --max-exact-removals 2 --max-recovery-probes 256
When dsh is run from a Harness source checkout, use safe executable-plus-argument fields instead of a shell command string:
node ./src/cli.js diagnose \
--command pnpm \
--command-arg --dir \
--command-arg /path/to/deepseek-harness \
--command-arg dsh \
--profile web
On PowerShell, quote any argument beginning with -- when necessary.
Install as a Harness bundle
Install the pinned v0.1.1 release directly through Harness:
dsh plugin --profile web add https://github.com/IoveCelestina/dsh-lifeboat/releases/download/v0.1.1/dsh-lifeboat-0.1.1.tgz
For a local checkout, run this from its parent directory instead:
dsh plugin --profile web add ./dsh-lifeboat
The package declares dsh.bundle through cordis.patch.yml. Installation adds the health marker to the selected profile. The rescue UI remains a standalone binary so a broken Loader cannot take it down:
pnpm --dir "$DSH_HOME/profiles/web" exec dsh-lifeboat serve
Release packages are distributed as GitHub Release assets, not through the npm registry. Validate the tarball installation command above against the current Harness CLI before relying on it for an incident.
How isolation works
- Lifeboat reads
$DSH_HOME/profiles/<name>/package.json, both user-patch layers, bounded safe Profile assets, and installed package-resolution identities into one diagnosis snapshot. - Installation-owned bundles stay fixed. Bundles also present in the profile's
dependenciesbecome candidates. - Every probe attempt receives a fresh clone of that configuration snapshot under a new direct child named
dsh-lifeboat-probe-*in the operating-system temp directory. - Credential-bearing files and symlinked assets are skipped. Package links use the absolute targets captured at snapshot time so pnpm's relative links remain valid and later link-target swaps cannot change the diagnosis midway.
- The full composition is probed. If it fails, Lifeboat distinguishes clean bundle failures from user-patch failures.
- For a community-bundle failure, bounded delta debugging first shrinks the known-recovering “remove all candidates” set. A completed result is 1-minimal: re-adding any one removed Bundle loses the observed recovery.
- Lifeboat then enumerates only removal cardinalities smaller than that upper bound, up to the configured exact depth. If all smaller cardinalities are exhausted, the upper bound is promoted to globally minimum
exact; otherwise the completed 1-minimal result remains explicitly non-global. A separate small residual budget looks for equal-size alternatives. - Every candidate plan is independently re-run in another fresh Home with the complete remaining Profile. Failed verification, unstable runtime evidence, an exhausted search budget, or live inputs that no longer match the snapshot suppresses automatic recovery.
- In runtime mode, inconsistent repeated attempts stop the diagnosis as
unstable-probewithout offering recovery. - Each temporary directory is removed after all owned links are unlinked, unless
--keep-artifactswas selected.
The search never performs an unbounded 2^n powerset walk. At most half of the logical-probe budget is used to obtain the initial upper bound; the unused budget plus the reserved proof share can test C(n,1) + ... + C(n,k) candidates only below that bound. Equal-size alternative discovery has its own sub-budget within the same total (normally 4–32 probes, capped by a smaller total) and the existing result-count cap. Defaults remain exact depth 2 and 256 total recovery probes in config mode or 64 in boot mode; the advanced UI and --max-exact-removals / --max-recovery-probes expose the main limits.
These are recovery plans, not moral blame. If A and B fail only when active together, Lifeboat can offer "disable A" and "disable B" as equal one-removal alternatives. If A and B fail independently, a verified plan must remove both. Reports distinguish exact from one-minimal and record whether all equal-size alternatives were enumerated.
Recovery behavior
“Apply recovery” is deliberately unavailable until the report contains an independently verified Bundle-removal plan. When confirmed, Lifeboat:
- lets the operator choose among verified alternatives;
- resolves that
planIdfrom the server-owned diagnosis report and rejects arbitrary Bundle lists; - acquires a per-Profile, cross-process mutation lock and rejects overlapping recovery operations;
- re-reads the original manifest and rejects the write if its hash changed;
- refuses linked Profile, manifest, lock, or backup-directory paths, then writes the exact original file under
.lifeboat-backups/with its full SHA-256 in the filename; - verifies the backup before atomically replacing
package.json, removing only the selected plan's Bundles fromdsh.profile.bundleswhile keeping dependencies installed; - persists the recovery receipt so “Undo this recovery” survives a local service restart, then verifies both the backup hash and manifest shape while preserving the post-recovery manifest as another restore guard.
Running a later dsh plugin package-manager command may reconcile an installed bundle back into the active list. Remove or update the actual faulty dependency after recovery.
Safety and current limitations
- The server binds only to
127.0.0.1, rejects non-loopback Host headers, sends a restrictive CSP, and requires a random per-process token for writes. - Config mode does not mount plugin rows. Runtime mode does execute installed plugin code with the current operating-system user permissions and therefore requires an explicit acknowledgement. The temporary Home isolates configuration and runtime data; it is not an operating-system sandbox for plugin source code.
- Probe processes receive a credential-scrubbed environment. A plugin that requires an API key may therefore fail for an environmental reason; the report preserves this distinction as far as the process result allows.
- Runtime survival is a health heuristic, not proof of full application correctness. Prefer config mode for deterministic loader/configuration failures.
- A boot success window must end at least 250 ms before the overall probe timeout. Invalid combinations are rejected instead of silently shortening the requested window.
- Relative profile assets are copied up to 32 MiB. Links are skipped and reported, so a profile built around linked local sources may require
--keep-artifactsand manual inspection. - On POSIX, probes run in their own process group and cleanup targets that complete group, including descendants that remain in it after the group leader exits. Windows uses
taskkill /Twhile the owned probe process is alive. - Package-resolution fingerprints include captured real targets and package manifests; installed package source trees are linked rather than fully copied. In-place source edits that leave
package.jsonunchanged are outside the immutable configuration snapshot and should be avoided during diagnosis. - The current candidate classifier follows the Harness profile contract: out-of-tree bundle names are active bundles also listed in
dependencies. Installation-owned bundles are never automatically disabled. - The current release targets the
dsh.profile.bundlesformat used by current pre-release Harness builds. It has not been validated against every historical release.
Relationship to dsh-guard
Lifeboat was implemented independently. The closest listed community project, dsh-guard, focuses on rolling snapshots and in-process rollback; its README explicitly notes that an in-process plugin cannot rescue a startup crash without an external launcher. Lifeboat focuses on an independent diagnostic service, fresh-home reproduction, verified bounded removal plans, and evidence-gated recovery. See the non-ranking comparison.
Development
npm test
npm run check
npm pack --dry-run --ignore-scripts
The project intentionally uses only Node.js built-ins so the rescue path does not acquire another dependency graph that can fail during an incident.
还没有评论,来写第一条。