Frame-level scan diagnostics for session files (torn/corrupt/empty detection).
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:omdsh-dev/dsh-session-health
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
DSH session health check plugin — performs frame-level scan diagnostics on multi-frame zstd session files under $DSH_HOME/sessions (torn / corrupted / empty sessions / stray files), and outputs a health report with cleanup suggestions. Read-only: never modifies or deletes any file.
Repository: https://github.com/omdsh-dev/dsh-session-health (public)
Motivation
While investigating issue #376 on 8/7, we ran a full decode analysis over 39 session files and discovered a key fact in the process: DSH session files are a concatenation of multiple zstd frames (a 19MB session = 119,952 frames). Reading a multi-frame file with a single-frame decode API only reveals the header — which once caused a false "all sessions empty" judgment. This diagnostic logic deserves to be productized as a tool: the model can directly ask "is my session file healthy" instead of relying on hand-written scripts.
Complementary to dsh-session-repair-skill (which repairs corrupted sessions): this tool discovers via read-only diagnostics → the repair skill repairs.
Security Model
- Read-only guarantee: never modifies/deletes any file (covered by the "file byte counts unchanged after scanning" test, see the files.spec SH-06 case)
- Path fencing: session ids go through a strict directory-name whitelist (prevents
../traversal); both the absolute path and the final file passfs.realpathreal-path containment checks (prevents symlink/junction escape); enumeration uses lstat to reject symlinks - Zero business dependencies: the zstd frame scanner is an independent implementation (reads bytes with DataView, RFC 8878 structure, differential-consistent with the official
scanZstdFrames) - Deep analysis optional: with
deep: truethe official decoder is dynamically imported; on parse failure it explicitly degrades todeep: "unavailable", never silently - Fixed input scope (sessions directory), no network, no execution surface
Tool Declaration
Registers the session_health tool (@deepseek-ai/dsh-session-health, row id tool-session-health), uniformly outputting JSON text.
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | ✅ | scan / file / stats |
path |
string | Absolute file path (must be within the sessions root) or session id (required for file/stats) | |
deep |
boolean | Deep analysis (decoded event statistics), default false | |
detail |
boolean | List abnormal files (scan defaults to true); false returns only the summary |
Detection Items
| Category | Determination |
|---|---|
missing |
Session id resolves to no file |
empty |
0-byte file |
not-zstd |
First 4 bytes are not 28 b5 2f fd (plaintext .jsonl or corrupted) |
torn |
EOF interrupts a frame tail (interrupted write) |
reserved-header / reserved-block |
Invalid reserved bits in the frame header/block header (structural corruption) |
bad-header |
deep mode: the first frame is not a session header |
empty-session |
Only 1 frame (header) and not updated for over 1 minute |
oversized-single-frame |
Single frame > 1MB (normal multi-frame writes do not do this) |
interrupted |
deep mode: has turn/start but no turn/end (process killed/crashed) |
stray-file |
*.tmp / leftover files with non-standard names |
The report contains: root / scanned / errors / suspicious / totals(bytes·frame count·event-batch estimate) / detail / deep / suggestions (suggestions give cleanup/repair advice per the issue template, not executed automatically).
Examples
session_health { action: "scan" }
→ {"root":"C:\\Users\\admin\\.dsh\\sessions","scanned":39,"errors":{...},"suspicious":{...},"suggestions":[...]}
session_health { action: "file", path: "session-abc123", deep: true }
→ 单文件报告(含事件分布与中断检测)
DSH 0.1.5-rc.1 Compatibility (verified)
This plugin has been migrated to the DSH 0.1.5-rc.1 harness, and full end-to-end verification was completed in an isolated consumer of local harness 0.1.5-rc.1:
- Types/runtime:
@deepseek-ai/cordis@^4.0.1+@deepseek-ai/dsh-tools@>=0.0.1-rc.1 <0.2.0+@deepseek-ai/dsh-invariants@>=0.0.1-rc.1 <0.2.0(peer); no longer depends on unscopedcordis - Standalone build:
npm install(devDependencies self-contain typescript/vitest/@types/node) →npm run typecheck→npm test→npm run build→npm pack - Consumption verification: tarball loaded into an rc.8 consumer → the plugin's row appears in
dsh --profile compat --dump-config→ real tool registration and execution passed - Startup method:
npx -p @deepseek-ai/dsh@next dsh web(lib production mode; do notinstall -gglobally)
Known limitation: under DSH 0.1.5-rc.1, the
@deepseek-ai/dsh-session-persistence-jsonltarball that deep mode depends on still does not include src/, and its root entry still does not export the zstd API; deep degrades todecoder-unavailable; frame-level scanning is unaffected (reported to dsh-external/issues — that organization is org infrastructure and remains in place).
Installation
Under DSH 0.1.5-rc.1, plugins are installed via dsh plugin --profile <profile> add <source>; source is a GitHub repository or an npm pack tarball.
Install from GitHub (Recommended)
# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-session-health
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-session-health
Install from npm pack tarball
The npm pack artifact can be installed directly as source:
dsh plugin --profile web add dsh-session-health-*.tgz
The bundled dsh.bundle.patch automatically adds the plugin to the profile's layer stack after installation (row id: tool-session-health). The plugin's missing peer dependencies (@deepseek-ai/cordis, @deepseek-ai/dsh-tools) are provided by the profile's healed profiles/node_modules fallback installation.
⚠️ web and headless are different profiles: installing into web does not automatically cover headless;
dsh runuses the headless profile by default. Use forward slashes for Windows paths (C:/...).
Verifying the Installation
dsh --profile web --dump-config | grep tool-session-health
Runtime Verification
dsh run "使用 session_health 工具扫描会话目录健康状态"
Legacy Scenario: monorepo / Local-Path Installation
The monorepo approach is now a legacy scenario (local junction/symlink, manually editing the profile layer, legacy snapshots without GitHub/tarball source support):
dsh plugin --profile web add "C:/path/to/dsh-session-health"
Testing
node <monorepo>/node_modules/vitest/vitest.mjs run tests
zstd-scan.spec.ts: boundaries of frames generated by the official compressor / multi-frame / not-zstd / truncated / reserved bits + real-session differentials (large/medium/small files frame-by-frame identical to the officialscanZstdFrames; reads local sessions read-only, not committed to the repo)files.spec.ts: two-level directory enumeration, stray/jsonl identification, path fencing (traversal/symlink/out-of-bounds rejection), session id resolution, read-only guaranteereport.spec.ts: error/suspicious count bucketing, suggestions templates, empty results, deep degradation annotationregister.spec.ts: registration contract (AUDIT-CROSS-02 style)
Known Limitations
deepdepends on dynamically importing the official decoder: at runtime in a profile, if the package cannot be resolved, it explicitly degrades to frame-level scanning (the report is annotated withdeep: "unavailable")- Event-batch estimate = frame count - 1 (each batch has at least 1 frame; not an exact event count, the report notes it is an estimate)
License
MIT
Links
More in this category
yjh051108/dsh-routing-suite★ 7000
One repository, three parts: a runtime injector for DSH plugin packages (inject, hot-reload, unload, promote a dev staging tool to the front, route self-heal, plus a settings-page plugin manager that lists, unloads and drags folders in to internalize), a task-aware reasoning-mode router agent preset (router-standard / router-spec / router-react), and a graded two-level task protocol whose six tools (commit_star, lock_stage, revise_do, edit_plan, mark_task, redteam_verdict) pin task state to disk. The injector implementation ships in-tree, so the install carries its own behaviour rather than a dependency list.
strukto-ai/mirage#dsh★ 3663
Swaps the filesystem and bash providers for a mirage virtual workspace: file tools and shell commands run over mounted resources (RAM, S3, Redis, Slack, Gmail, Notion, Postgres) instead of the host disk, with per-mount read/write/exec modes, per-command sandbox routing (monty, pyodide, quickjs in process; docker, e2b, daytona remote), and installed CLIs (git, gh, slack, linear, ntn, gws, or one you register) as head words in the virtual terminal.
hust-open-atom-club/oh-dsh★ 325
Community distribution: TUI, desktop, and Web UI as one bundle with layered installation.
weijiafu14/pi2dsh★ 206
Pi Host ABI compatibility engine: after one install, unmodified Pi extensions from npm mount as native DSH plugins with `dsh plugin add <pi-package>`. Verified end to end on stock DSH with pi-mcp-adapter (full MCP manager: OAuth, resources, prompts, MCP Apps, elicitation, sampling), @tintinweb/pi-subagents, pi-code, pi-hermes-memory and pi-background-tasks; `pi2dsh inspect` reports a package's compatibility before installing.
lire1131/dsh-undo-savepoint★ 165
Undo/redo & rollback system for DSH: every config change is auto-snapshotted; undo/redo/restore to any version from the WebUI or the offline CLI/GUI tools (works even when DSH fails to boot).
Fishquito7/dsh-skill-mcp-panel★ 152
Manages DSH skills and MCP servers from the web settings: skill cards with hot enable/disable, workspace scopes, groups, batch migration and drag-and-drop import, plus stdio/HTTP MCP CRUD with connection tests, secret redaction and the unified dsh-panel CLI.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.