ImageBlock had no production producer and every consumer dropped it: the deepseek serializer skipped it, the pi-ai converter skipped it as unrepresentable, the ACP bridge neither advertises image prompt capability nor forwards image blocks, and compact-basic charged a flat 85-token estimate and rendered an [image] placeholder. A block constructed today would silently vanish from the wire — the vocabulary advertised a capability no path honors, the silent-data-loss shape the defensive patterns warn against. The only constructors were tests pinning the skip/estimate branches. Remove ImageBlock and its ContentBlockMap entry (its cache?: CacheHint field leaves with it; CacheHint itself and the other two cache? fields are out of scope). compact-basic loses its explicit image estimate and placeholder arms (the merge-extensible default arms absorb the case); the deepseek serializer, pi-ai converter, and ACP codec already handled image in their default arms, so only their image-naming comments change. The codec's inbound rejection of ACP-protocol image prompt content stays — that guards wire content a client can send regardless of our vocabulary. Tests that constructed harness image blocks to pin the removed branches are dropped (the 85-token estimate pin) or retargeted onto plugin-added block types / other non-text blocks, which the surviving default arms own. Docs, the type-equiv pastes, and the content-block vocabulary RFC's block list and multimodal-home consequence are updated in the same change; the RFC moves to implemented/ and the index is regenerated. A real multimodal feature reintroduces image via declaration merging together with the adapter mapping, ACP advertisement, and compaction pricing that honor it.
ui/ — editor/client integration surfaces
Integrations that expose the agent to an external editor or client. These are product packages: a real surface a user drives the harness through.
| Package | Role | ctx key |
|---|---|---|
acp/ |
Agent Client Protocol bridge: serves the agent to an ACP editor (Zed) over JSON-RPC stdio | (drives ctx.agents/ctx.sessions) |
stdio-agent/ |
Terminal stdio chat APP: the agent-core spine + console logger + readline UI + a pre-created main agent, with a bin |
(composition + bin) |
acp-agent/ |
ACP server APP: the agent-core spine + JSONL persistence + the acp bridge (no stdout logger), with a bin |
(composition + bin) |
A UI integration is a client-driver plugin, not a loop change and not a capability seam: it consumes the existing agent/* event taxonomy and the dsh-agent factory. The readline ui-stdio plugin is the unstructured analogue but lives in support/ because it exists chiefly for the examples and the coverage gate — ui/ is reserved for surfaces shipped as product.
stdio-agent and acp-agent are the two app packages: each composes the core/agent-core spine with its coupled front-door cluster (and owns the boot bin), so a leaf cordis.yml is the swappable backends plus one app entry plus any optional product tools. They live in ui/ because each IS a user-facing front door; the stdout-purity coupling (logger vs. no logger) becomes a property of the artifact rather than a leaf convention.