`dsh` shipped two config trees that were 43 rows the same: apps/cli/cordis.yml
composed web as 74 flat rows, while the TUI booted examples/tui-agent/cordis.yml
whose single `@deepseek-ai/dsh-tui-demo` row mounted twelve plugins behind a
twenty-key pass-through Config. Neither file was what its location claimed —
apps/cli hardcoded the "example" as the product default and the "demo" bundle
was the application — and every capability change had to be made twice.
- apps/cli/base.cordis.yml holds the 43 shared rows; tui.cordis.yml and
web.cordis.yml are patch lists stating only what differs per surface
- overlays apply as SIBLING patch lists at one include level, because include
patches never cross an include boundary. Precedence: base < surface <
(--config | personal ~/.dsh/config.yaml) < launcher flag/profile patches
- `--config` now applies an overlay INSTEAD OF the personal one, so a demo or
test tree never inherits the user's route; new `--config-replace` boots a file
as the entire tree (the old `--config` behaviour). Both survive /resume
- vendor/include: index each `insert`ed row as it is added so a later patch can
configure or disable it. Upstream built the id index once before the patch
loop, leaving every surface-only row — the whole TUI front door — silently
unpatchable from user config. Logged as local modification 8
- session identity moves to dsh-agent-loop's CONFIGURED_AGENT_IDENTITIES_KEY;
dsh-tui's MAIN_SESSION_ID_KEY is deleted (only the bundle read it)
- delete examples/tui-agent, examples/cordis-agent, packages/examples/tui-demo;
TUI tests → apps/cli/tests, cordis e2e → packages/cordis/tool-cordis/tests,
examples/code-mode survives as an overlay leaf
- `dsh web` gains --config, threaded into AppCLIEntry as an extra overlay
Three latent defects surfaced and are fixed here: the TUI captured the optional
sessionQuery service once at construction and could permanently disable /resume
when it won the mount race; the session-store root silently reverted to a
project-local ./.sessions; --config-replace was dropped by the resume handoff.
Verified by booting each tree through the real Loader (TUI 55 entries, web 75,
zero unsettled) rather than reading YAML. All eight terminal snapshots replay
byte-identically; 14/14 PTY smoke, 112/112 snapshots, 25/25 doc-sync, hygiene
and lint clean.
Shared-surface conflicts resolve as unions: the fixture serves all five
projection keys (title/todos/permissions/plan/goal) with the /permission
and /plan command mirrors side by side, the connection specs assert the
five-key baseline and the shifted approval/question replay indices, and
the cli roster/deps, tsconfig aggregate, and README allowlist carry both
lines' rows. Plan-side content lands verbatim from master.
One end-state consolidation both branches half-did: with questions
(ui-question) and approvals (ApprovalPanel) each owning a composer
takeover, PendingCard retires outright — ChatView renders no pending
placeholder, the card component and its specs go, and both README halves
state the takeover-only contract.
Union resolutions throughout — the fixture serves both the goal and plan
projection units (catalog gains /goal beside /plan; the retired
goal-fixture sample command yields to the real goal mirror), the mux
baseline spec expects all four unit frames, and the tsconfig paths /
Model Experience allowlist carry both domains' outlets.
Shared-surface conflicts resolve as unions: the fixture serves all four
projection keys (title/todos/permissions/goal) with both the /permission
and /goal command mirrors (the goal-fixture placeholder retires with
master), apps/cli carries both lines' dependency additions, and the README
Model Experience allowlist keeps both entries. The connection specs assert
the four-key baseline and the shifted approval/question replay indices;
the module graph regenerates over the merged dependency set.
Three ui-conversation spec conflicts resolve to master's SlotTestRuntime
rewrites. Adaptation to the new outward session face: ISession gains the
command verb (the composer chip and the /permission picker submit through
it), FixtureSession grows the matching fail-loud stub plus the
waitingApproval summary default, and the picker reads the projection
through projections.faceOf (the ProjectionsFace shape) instead of the
retired store getter.
The TUI keyless smoke exposed the wrong idle signal: /plan submitted while
the driver is between turns still saw status running (checkpointing), so
the selection queued and the immediate copy never appeared. The commit
gate is now the log's own open-turn fold — plan/mode commits at once
whenever no turn is open, and queues only inside one. Specs drive the
distinction through explicit turn/start / turn/end events instead of a
fake status; the keyless smoke pins the new idle copy on both /plan and
/plan off; regenerated cordis/service catalogs ride along.
gen-cordis-catalog/api, config/persistence catalogs, module graph, and doc
graphs pick up the ui-permission package, the permissions projection key,
and the /permission command; KnobState and PermissionSelect join the
type-link exemptions (owned by the permission package's own docs), and
ui-permission joins the sentence Model Experience allowlist (indirect via
the host command). The ui-conversation and dsh-permission READMEs gain
their zh halves for the approval/chip and projection/command paragraphs;
all three touched pairs re-record.
- Regenerate the cordis/config catalogs, doc graphs, and module graph for
the four newly mounted plugins and the goal projection key.
- ui-goal README pair (Model Experience indirect + Known Limitations) with
its i18n record; sentence-allowlist entry for the indirect form.
- knip workspace entry for ui-goal (tsx test pattern).
- type-equiv manifest follows the seven host-coupled goal symbols to
domain.ts.
- The web-slash-command-dispatch note documents the dropped prompt
interception and leaves with it; the goal-bar note's code paths follow the
component into ui-goal (pairing re-recorded).
gen-cordis-catalog/api, config and persistence catalogs, and doc graphs
regenerated over the new sessionProjectionCache service and the registry's
checkpoint faces. Classifications: ProjectionCheckpoint joins the type-link
exemptions (owned by the projection package source), Partial joins the
foundation names, the cache service gets its capability-seam role row, and
the package takes the one-sentence Model Experience contract (host-side
read-model accelerator, no model surface).
Add @deepseek-ai/dsh-tmux-context: an opt-in per-turn context plugin that
reads which tmux session/window/pane this agent process runs in (plus the
window layout tree) via the ctx.bash seam, and injects it as one durable,
source-attributed user/message when the location changes.
- Pull on the first step of each turn; no tmux hook or background process.
- Detect a real pane by tty, not $TMUX_PANE alone: a terminal launched from
a tmux shell inherits $TMUX/$TMUX_PANE from that ancestor, so the command
also matches the pane's #{pane_tty} against this process's controlling
terminal and emits fields only on a match.
- No-op outside a real pane, without a bash executor, or on a malformed
reading.
- Own location and layout only: no pane sizes, no sibling-pane scraping.
- Unit tests at 100% per-file coverage, plus a keyless Loader e2e with a
mock bash provider so it replays without tmux.
- Agent Note: 2026-07-27-tmux-location-context.
gen-cordis-catalog type-link rows for the ProjectionDefinition surface and
CommandExecution; a sessionProjections service-role row for gen-doc-graphs;
regenerated module graph, persistence/config/cordis catalogs and api-catalog;
packages/README rows condensed back under the word ceiling; the RFC's sketch
fences marked ignore-check on both language sides (pairing re-recorded).
The group's convention is package suffix == provider default
(subagent-acp/'acp', subagent-spawn/'spawn', subagent-fork/'fork'), and the
provider default became dsh-sdk in the last review round — so the package
follows: @deepseek-ai/dsh-subagent-dsh-sdk at
packages/subagent/subagent-dsh-sdk, plugin name subagent-dsh-sdk,
diagnostics prefixed subagent-dsh-sdk:. The dsh echo has precedent
(dsh-llm-deepseek). Directory, fixture path, knip/tsconfig/examples
registrations, catalogs, READMEs (en+zh), and the Agent Note follow; the
sdk-client dispose ladder moves to its own module (src/dispose.ts) with the
deterministic FakeChild tier tests restored alongside it.
Resolutions: regenerate the conflicted generated docs (cordis services
catalog, event-producer-consumer, module-graph); take master's
packages/README pair and re-insert the telemetry row on both sides;
re-record the README and session-doc translation pairs.
Regenerate event-producer-consumer.md after the queued-frame steering removal;
re-record the bilingual consistency records the master merge left stale; and
restore the eight archived notes the agent-loop rename had swept up (archived
notes are frozen — their archival-time path references stand).