Browser acceptance of the activity panel surfaced the product problem: a background bash registers in both planes, so the header grew two near- identical popovers — "background jobs" with lifecycle and duration, "activities" with live output — listing the same work twice. The service planes stay orthogonal (jobs: model-visible control with a consuming read cursor; activities: transient non-consuming observation). The join happens per row in the UI projection instead: - dsh-client-ui-activity renders the single merged "tasks" list. Each jobsBySession row joins the activity carrying its correlation.jobId — the job supplies identity, lifecycle (stopping exists only there), duration, and the model-visible detail; the activity supplies the expandable live-output panel. Standalone activities (workflow runs) keep their own rows; without the activity registry, job rows still render and the control degrades to the old job list exactly. - dsh-client-ui-jobs is deleted (pre-release, no shim); the merged entry takes its slot order. The job locale namespace folds into activity. - User-facing copy says "task" (任务): N tasks running / N 个任务进行中. - Hierarchy: live rows first as two lines (label over kind badge and status, ticking duration), a Finished divider when both sections exist, settled rows compacted to one de-emphasized line, and the output panel hangs behind a spine under its row. Deliberately not joined: subagent rows stay bare (the subagent panel is their surface) and foreground commands stay in tool cards. Both web e2e scenarios now assert one Tasks list; the background-job scenario's row gained a live-output panel, proving the join end to end. Agent Note: 2026-08-25-unified-task-list.
bundle/ — profile plugin bundles
English | 中文
Profile bundles: npm packages whose manifest declares "dsh": { "bundle": { "patch": "./cordis.patch.yml" } }, making them installable patch layers for dsh --profile compositions (profile contract). A bundle's substance is its patch list; some also ship runtime glue plugins their patch mounts.
The manifest declaration, not this directory, defines Bundle identity. Domain packages can carry their own optional Profile layer; the Codex and Claude Code subagent packages are directly installable examples.
| Package | Role | ctx key |
|---|---|---|
base/ |
The shared dsh core applied first by base-backed profiles | — (patch only) |
acp-app/ |
Automation-only ACP stdio application over base | mounts the ACP bridge |
web-app/ |
Browser surface: web patch layer + runtime glue plugin | mounts rows |
headless/ |
Direct one-shot task mode over base, with no Host or Web layer | mounts headless-runner |
sdk-app/ |
SDK stdio JSON-RPC application over base | mounts the SDK server |
sdk-minimal/ |
Standalone minimal SDK application without base or Web | — (complete patch tree) |
In-box bundles resolve from the dsh installation; out-of-tree bundles install into a profile through dsh plugin --profile <name> add <package>.