dsh-death-forensics
In-process death black box for a DeepSeek Harness (dsh) host. A Cordis plugin (bundle format) that records what happened before the host died — heartbeat windows, crash stacks, and an end-kind self-check at the next boot.
Why
dsh web processes can die without a trace (external kills, frozen event loops, crashes). An external launcher can record how the process died (exit code / stderr / uptime), but only something inside the process can record what happened before: when the last heartbeat was, what the crash stack was, and whether the previous boot ended gracefully.
This plugin is the in-process half. Pair it with an external launcher (see DESIGN.md) for a complete picture.
Features
| Feature | Mechanism |
|---|---|
| Heartbeat | append JSONL to <DSH_HOME>/death-forensics/heartbeat.log every heartbeatIntervalMs (default 15s, bounded file) |
| End-kind self-check | SIGTERM/SIGINT record graceful; exit event records neutral exit; crash/kill leaves running → next boot detects a non-graceful end and appends a record to crash.log |
| Crash stacks | uncaughtException (incl. unhandled rejections via Node's default throw chain) records the full stack, then reprints it and exits(1) — host behavior is byte-identical to the no-plugin case |
| Report tool | death_forensics_report — current boot, previous end kind, death window (last heartbeat → next boot), crash log tail, external launcher log tail (if present) |
Data files (<DSH_HOME>/death-forensics/)
state.json— current boot identity + last end kind (single source of truth)heartbeat.log— append-only JSONL, truncated atmaxHeartbeatLinescrash.log— append-only JSONL records (crashes + detected non-graceful ends)
Safety contract
- Zero child processes — never spawns anything; only file writes.
- Hot paths are synchronous writes with try/catch degrade — failures disable the black box, never the host.
- Hooks are additive listeners only, cleaned up on plugin dispose.
- No monkey-patching of host services.
Install
Add to a dsh profile (e.g. profile/profiles/web/package.json):
"dependencies": {
"dsh-death-forensics": "link:/path/to/dsh-death-forensics"
},
"dsh": {
"profile": {
"bundles": [ ..., "dsh-death-forensics" ]
}
}
Then restart dsh. The bundle patch inserts entry id death-forensics.
Alternatively, via CLI: dsh plugin --profile web add /path/to/dsh-death-forensics.
Build
Requires a dsh checkout or profile install carrying @deepseek-ai/* packages
(resolved via $DSH_CHECKOUT, or $HOME/dsh-harness, $HOME/dsh,
$HOME/.dsh/dsh-harness), plus typescript:
# install devDependency offline (from any pnpm store)
node <pnpm.mjs> install --store-dir=<pnpm-store-dir> --prefer-offline \
--config.node-linker=hoisted --config.auto-install-peers=false
# compile src/ → lib/
bash scripts/build.sh # Git Bash on Windows; node must be on PATH
node lib/selftest.js # 17 pure-logic assertions
The published lib/ is committed so the plugin works from a plain clone.
Configuration
| Key | Default | Description |
|---|---|---|
heartbeatIntervalMs |
15000 | heartbeat interval (min 5000) |
maxHeartbeatLines |
20000 | heartbeat file line cap |
reportTailLines |
40 | tails shown by the report tool |
dataDir |
<DSH_HOME>/death-forensics |
data directory override |
Docs
DESIGN.md— full design (Chinese): state machine, hook semantics, acceptance criteria.- Death-window interpretation:
[last heartbeat of previous boot, this boot's start].
License
MIT — see LICENSE.
No comments yet. Be the first to write one.