Overview
dsh-lineage
README / EN
Package documentation
dsh-lineage
A visual conversation map plugin for DeepSeek Harness: sessions, follow-ups and forks of one workspace as a single navigable canvas.
DSH session logs remain the only source of truth. The plugin reads them on demand through ctx.sessionQuery and persists nothing but view metadata (lane drag offsets). It never touches prompts, tool schemas, provider routing, or KV-cache prefixes.
Features (v0.1.0)
- Lineage map (default): a tree rooted at a root session is ONE map — opening it from any member shows the WHOLE tree from the root: the ancestor chain, ancestors' other branches, and all descendants. Lineage follows
parentSessionIdwith no workspace separation inside the tree (a fork child stuck in a cwd bucket is still the same tree); a branch added on any lane appears in the same map immediately, and any ancestor ↔ any descendant pair is one click apart. - Workspace view (drill-up): one click expands to the flat session slice of a workspace bucket — the tier that mirrors how DSH itself lists sessions.
- Lane title, three-in-one: single click opens the conversation, double click renames it (stub lanes rename the branch), drag moves the lane.
- Ask card: every lane's card queue ends with a trailing ask card — the whole card is one input (Enter sends, Shift+Enter breaks a line, grows with content); message cards carry no follow-up button, and "asking about a middle turn" is expressed as a branch via the card's ">". A stub lane is just its ask card: the first send forks the real session and delivers the message.
- Card interactions: single click on the question jumps to that turn; double click on the card background opens expanded reading — the card rises to the foreground center over a dimmed backdrop (same markdown spec as the native page, via
src/client/markdown.ts), wheel scrolls the float only; the circular ">" on the card's right edge is "branch from this turn" — the fork edge leaves from that button and lands on the cut's card. - Context inheritance follows the map's edges: the branch cut is the branch turn's
turn/end— the child inherits the WHOLE turn (question + answer + tools) and the ask card's text lands as the next user message; materialized forks resolve the cut from the child log's inherited prefix length (inheritedEventCount). Both edge kinds leave from the cut card's ">" button, never the lane header. - Jump lifecycle: the row bridge takes a cancellation token — closing the map or starting a new jump cancels in-flight bridge walks (retries, scrolling, row clicks), so nothing fires late; failures dump full row-label evidence via
__dshmJumpDebug. - Lazy branches: ">" only records a stub (dashed ◇ lane; ✕ in the title bar deletes, double click renames). Stubs are pure view metadata under
$DSH_HOME/dsh-lineage/branches/and never touch any DSH session. - Read-only map: lane = session (title + running badge), card = one turn (question, answer snippet, tool chips, failure count, cancelled/error badges, pending-approval chips), SVG curves = fork lineage edges (from
SessionHeader.parentSession). - Layout persistence: drag lane headers; offsets are stored per workspace under
$DSH_HOME/dsh-lineage/layout/(view metadata only). - Subagent toggle, live running status, wheel zoom / shift-alt pan / drag pan / double-click-on-empty reset; panning never sweeps text selection and zoom stays vector-crisp.
Compatibility
- DeepSeek Harness 0.2.0-rc.2,
webprofile only (contract-verified against the installed release; seedocs/contract-notes.md). - Node.js >= 22.19.0.
Install / verify
dsh plugin --profile web add ./
dsh --profile web --dump-config
dsh --profile web
Open any session → the 「会话地图」 header button → the map overlay. Host API: GET /lineage/api/graph, GET /lineage/api/sessions/:id/turns, GET|PUT /lineage/api/layout/:workspaceId, GET /lineage/api/health.
Configuration (cordis.patch.yml)
| Field | Default | Meaning |
|---|---|---|
dataDir |
$DSH_HOME/dsh-lineage |
Lane-offset storage directory (view metadata only) |
trustedHosts |
[] |
Extra accepted Host names for proxied deployments (localhost always allowed) |
Disable / uninstall
dsh plugin --profile web remove dsh-lineage. Only $DSH_HOME/dsh-lineage/ (offset data) remains; session data is untouched.
Known limits
- Jump relies on the native sidebar's DOM structure (the row's title leaf, the chat anchor prefix
data-chat-anchor-key) — a version-sensitive bridge, centralized insrc/client/glue.ts. Matching runs in three passes (title-leaf exact → safe composed-strip → aggressive strip) and on failure dumps full evidence to the console as__dshmJumpDebugbefore degrading explicitly. - Branching from a turn that is still running has no
turn/endyet: the cut falls back to the turn's opening question (the unfinished answer is not inherited). - Not implemented: minimap, synapse data import, settings card (configuration stays in the patch file).
Release status
Prepared per the dsh.pub plugin development and catalog-admission guide: the repository root is an independently installable package with committed runtime artifacts, a declared safe dsh.bundle.patch, and CI covering build, tests, artifact-contract checks and a web-profile activation smoke. dsh.pub listing happens through its automated gates and a submission Pull Request — it implies no human review, security audit, compatibility certification, or official DeepSeek endorsement.
License
MIT — see LICENSE. Ideas inspired by dsh-synapse (MIT) © liangmianya; an independent implementation sharing no code.
LIMITATIONS
Known limitations
Submitted through a public pull request. Automated checks verified the public bundle contract and committed files, but did not inspect runtime capabilities. This is not a human review, security audit, publisher identity check, or official endorsement.
