Install
Inside DeepSeek Harness, with dsh-market
dsh plugin --profile web add dshmarket
Or from the command line
dsh plugin --profile web add dsh-startup-guard
Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.
README
Boot-time guard for DeepSeek Harness — repairs session logs, preflights the plugin composition, smoke-tests host
apply(), and quarantines crash sources before boot, so a broken plugin or corrupt log can never brick startup.
Overview
DSH is assembled from many third-party plugins: a missing package, a malformed patch, an unbuilt client artifact, or even a runtime exception thrown from a host apply() can crash the whole app at startup. dsh-startup-guard runs seven checks early in boot and can auto-repair / roll back / quarantine the source of the problem — it is a four-layer defense: parse → compose → execute → crash-containment, not just a set of file checks.
Zero configuration needed; typical overhead < 0.5s per boot.
Core capabilities
| # | Check | Behavior |
|---|---|---|
| 1 | Session log repair | Fixes session.jsonl[.zstd] seq corruption (drop duplicate row or truncate to the last committed row); frame-level detection and truncation of permanent zstd torn tails; prunes stale cache entries for deleted sessions. Originals are backed up to repair-backups/ |
| 2 | Manifest snapshot + fingerprints | Snapshots each profile's package.json / cordis.patch.yml / pnpm manifests plus link: plugin sources into plugin-snapshots/, recording per-bundle host/client/patch content fingerprints (keeps the latest N) |
| 3 | Bundle preflight + rollback | Verifies third-party bundle dirs resolve; rolls back to the newest fully-resolvable snapshot when missing (24h grace against rollback loops); broken manifests kept as package.json.broken |
| 4 | Composition preflight + repair | Detects duplicate entry ids, unresolvable name: rows, and fatal YAML shapes; rows whose name: no longer resolves are auto-disabled (with backup); fatal shapes write a block marker in strict mode that the launcher refuses to boot past |
| 5 | Client bundle validity | Verifies exports["./client"] exists, registers via __ModuleLoader__.load, and actually executes at load time in a vm sandbox; detects duplicate client ids across bundles; broken artifacts are auto-disabled |
| 6 | Host apply() smoke |
Runs every third-party plugin's apply() in a throwaway child process against a mock Cordis context, catching "crashes at startup" runtime errors (e.g. ReferenceError); results cached by content fingerprint |
| 7 | Crash quarantine | The launcher / desktop app writes a crash marker on an observed crash, and the host plugin also maintains its own boot marker (dsh-boot-state.json: written at apply, cleared on clean shutdown, left behind by abnormal exits). Either piece of evidence forces a full smoke sweep on the next boot and auto-disables failing plugins — closing the "crash → auto-disable → boot recovers" loop. Works for a bare dsh web with no launcher/shell too |
Quick start
dsh plugin --profile web add dsh-startup-guard # npm (prebuilt, skips build approval)
# or from source:
dsh plugin --profile web add github:aokamoaki/dsh-startup-guard
Published on npm:
dsh-startup-guard@1.0.0(npm page).
Restart dsh web. On first boot it scans/repairs sessions, snapshots the plugin manifests, smokes every third-party host entry, and writes the summary to ~/.dsh/dsh-preflight-report.json.
Modes & configuration
File: ~/.dsh/dsh-startup-guard.json (defaults when absent).
| Mode | Behavior |
|---|---|
report |
Detect and report only; never modifies anything |
fix (default) |
Auto-repair / auto-disable / auto-rollback |
strict |
fix + fatal composition shapes write a block marker; the launcher refuses to start and shows a dialog |
{
"mode": "fix",
"smoke": true,
"smokeTimeoutMs": 15000,
"clientVmCheck": true,
"clientFactorySmoke": false,
"quarantineOnCrash": true,
"autoRepairComposition": true,
"tornTailGraceMs": 300000,
"keepSnapshots": 10,
"exclude": ["some-bundle-i-trust"]
}
| Option | Default | Description |
|---|---|---|
mode |
fix |
report / fix / strict |
smoke |
true |
Run the host apply() smoke |
smokeTimeoutMs |
15000 |
Per-bundle child timeout |
clientVmCheck |
true |
Execute client artifacts in a vm at load time |
clientFactorySmoke |
false |
Also invoke the client factory (stub require) |
quarantineOnCrash |
true |
Crash marker forces a full smoke sweep |
autoRepairComposition |
true |
Auto-disable patch rows whose name: no longer resolves |
tornTailGraceMs |
300000 |
"Permanent torn tail" write-idle threshold |
keepSnapshots |
10 |
Number of snapshots kept |
exclude |
[] |
Bundles the guard never touches |
Auto-disable safety policy
Smoke runs in a mock environment: a failure may be a real bug or an environment gap (the plugin needs real DSH services). Therefore:
- A smoke failure alone never auto-disables (only reported +
fixNeeded); - the previous boot actually crashed (crash marker present) → failing plugins are auto-disabled;
- a plugin explicitly declares
"dsh": { "smoke": true }→ auto-disabled on smoke failure; - a plugin declares
"dsh": { "smoke": false }or is inexclude→ smoke skipped; - broken client artifacts (parse-class checks) → auto-disabled as before.
Wrongly disabled? Remove the matching - id: "xxx" / disabled: true entry from the profile's cordis.patch.yml (the original patch is backed up in repair-backups/).
Data locations
~/.dsh/
├── dsh-preflight.log # run log (rotated past threshold to .old)
├── dsh-preflight-state.json # scan state + smoke fingerprint cache
├── dsh-preflight-report.json # machine-readable summary of every run
├── dsh-crash-state.json # crash marker (written by launcher/desktop, consumed by guard)
├── dsh-boot-state.json # boot marker (written by host plugin, cleared on clean shutdown; abnormal exit = crash evidence)
├── dsh-preflight-block.json # strict-mode block marker (read by launcher)
├── dsh-startup-guard.json # config (optional)
├── repair-backups/ # original files before repair/disable
└── plugin-snapshots/ # manifests + link sources + fingerprints
Integration
Three entry points, so every crash scenario has a fallback — and a bare dsh web with no shell still gets crash quarantine via the host plugin's boot marker:
- Desktop client (dsh-desktop-app): runs
guard-runner.mjsas a child process before spawning the server; writes a crash marker on server crash, clears the boot marker on clean quit - Web launcher (dsh-launcher.ps1): calls
guard-sessions.mjsin the boot loop; writes a crash marker on crash; refuses to start if a strict block marker exists; clears the boot marker on normal stop - Host plugin: runs asynchronously early in the dsh web boot; writes/clears the boot marker and triggers quarantine from it
CLI:
node guard-sessions.mjs # fix mode
node guard-sessions.mjs --dry-run # report only, change nothing
node guard-sessions.mjs --mode report # same as dry-run
node guard-sessions.mjs --mode strict # fix + strict block
Core API:
import { runGuard } from 'dsh-startup-guard/lib/guard-core.mjs';
const r = await runGuard(home, { dryRun: true });
// r: { repaired, rolledBack, autoDisabled, broken, hostBroken,
// smokeUnresolved, issues, fixNeeded, blocked, crash, lines, ... }
Development
dsh-startup-guard/
├── lib/
│ ├── index.js # host entry (fire-and-forget, dynamic import)
│ └── guard-core.mjs # core: runGuard + all checks
├── test/guard-core.test.mjs # 73 tests (node:test, mock home, zero deps)
├── cordis.patch.yml # bundle registration
└── package.json
npm run check # node --check lib/*
npm test # node --test (73 tests)
npm run pack:check # npm pack --dry-run
node guard-sessions.mjs --dry-run # safe dry-run against a real home
Design principles:
- fire-and-forget: guard failures are logged, never thrown into the boot sequence;
- atomic writes: every file modification goes through tmp+rename;
- graceful degradation: if the session decoder is missing, only session scanning is skipped;
- single-instance lock:
dsh-preflight.lockserializes the multiple entry points.
License
Independent community plugin for DeepSeek Harness. Not affiliated with DeepSeek.