Moving the agent plane behind presets left two readers on the wrong side of the host/agent line. `dsh-token-meter` was disabled on the host and mounted inside each preset's `compaction` realm, but its three projection units register into the process-wide `sessionProjections` table. A unit registered from one preset answers for every session, so whether a `minimal` session showed a context meter depended on whether some other session had mounted `standard` since boot, and a process that only ever ran `minimal` showed none. The meter takes no configuration, keys every fold by Session, and registers no tool or prompt section, so it returns to the host composition and leaves the presets' `isolate` map; the realm and `compact-basic` stay, because what a preset chooses is whether its agent compacts, not whether its tokens are counted. Nothing named an agent that joined no preset. The join is a scope-parent link, and without it the tools, prompt-section, and skill views resolve the empty global layer: the agent publishes, the turn runs, and the model receives nothing. `AgentPresets` now logs one warning per such agent while a roster is configured, and the invariant companion fails outright — at `system-prompt/assemble` rather than at publication, because an unjoined agent is legal until it addresses a model and `recompose` binds exactly such an agent. The warning stays advisory: a synchronous `agent/created` throw vetoes publication, and the ACP bridge, SDK server, and headless bundle all create an unjoined agent today. Three limits are recorded rather than fixed: projection key presence is not a per-session capability signal, a superseded standing generation is never reclaimed, and a `cordis_mount` temporary plugin belongs to the composition rather than the session that mounted it. Fixes #2203
@deepseek-ai/dsh-headless
English | 中文
The dsh one-shot bundle. cordis.patch.yml rides directly over dsh-base: it supplies the coding persona and tool mode, disables HMR, mounts Code Mode's worker as a core execution capability, and inserts this package's headless-runner plugin (config {task}). It mounts no Host, HTTP server, Web runtime, or browser plugin.
After the Loader settles, the runner reads the shared ctx.agentDefaultModel, creates one fresh persisted Agent through ctx.agents, submits the task as an ordinary user message, and waits for quiescence. It flushes the Session before folding the owned durable event interval, writes the last non-empty assistant text to stdout, and requests exit through the launcher-provided ctx.headlessIo host hook (final turn/end completed → 0, otherwise 1). A terminal error reason also writes its code and message to stderr; successful runs keep stderr empty. The process opens no listening port. The launcher patches the task text in (dsh run "task") and fails loud when the selected profile lacks this row.
Model Experience
None, as the runner submits the task as an ordinary user message; prompts and tools belong to the base and headless bundle rows.
KV Cache effect
None; the runner adds nothing to the request prefix.
Known Limitations and Deferred Work
- One submitted task only — the runner has no interactive follow-up surface; it waits through any work the Agent completes before returning to idle and prints the last non-empty assistant message in that interval.
ctx.headlessIois launcher-owned — booting the headless profile outside thedshlauncher fails loud at activation until the host provides the hook.