The localized catalog exposed one count.total and one count.running string for every cardinality. The English dictionary therefore rendered both the visible trigger and its accessibility label as 1 subagents, and the assembled Web golden had begun preserving that grammar error.
Split both count families into explicit one and other keys, following the existing client locale convention. SubagentCatalogAction selects the pair from the effective descendant count; English uses subagent for one and subagents otherwise, while Chinese keeps its unchanged classifier text under the same key domain.
Add a component regression proving a single running descendant selects both singular keys. Update the real Web E2E locator and keyless assembled aria golden from 1 subagents to 1 subagent. Both ui-subagent test files pass all 28 tests and the package TypeScript project builds cleanly.
The ui-subagent catalog and read-only composer copy moved from hardcoded
Chinese to the locale-aware `subagent` namespace, so an en-US headless
browser now renders English. The e2e's selectors and goldens still
asserted the old hardcoded Chinese strings, leaving the scenario unable
to find the catalog trigger.
Convert the selectors to the default (en-US) render and re-record the
catalog goldens (ui, tree, nested) in English. The locale-aware parts of
the remaining goldens were already English (recorded under the en-US
default), so sidebar and fork are untouched.
The opt-in `core-web.cordis.yml` profile promises "exactly persistent
`bash` plus `str_replace_editor`" (its header comment and `apps/cli/
README.md`), but the base registration of `tool-subagent-list-agents`
(added with the durable child catalog) was not disabled by the overlay,
so the profile actually exposed `bash`, `str_replace_editor`, and
`list_agents`. The assembled snapshot was updated to accept the third
tool, which ratified the contract break instead of fixing it.
Disable `tool-subagent-list-agents` in the overlay and restore the
snapshot's expected tool registry to the documented two tools.
- Wire the control service and send_message tool into every shipped
composition with a resumable provider and background enabled
(headless-agent, tui-agent, and the SDK helper's subagent feature
base resources); jsonrpc-agent disables background and is unchanged.
- Resolve the send_message availability check in the CALLER's tool
scope so a restriction that removes the follow-up tool from one
agent also blocks that agent's continuable start.
- Control-service disposal now cancels live activations and awaits
producer settlement instead of stranding them: TaskService keeps
producer Tasks across a reload, so the disposing service aborts each
activation-owned controller, resolves its terminal gate (the
effect-scoped onTaskDone listener is already gone), and awaits done.
A new test kills a mid-start activation through HMR disposal.
The shipped-roster change made @deepseek-ai/dsh-tool-session-query a
default row of the shared base.cordis.yml, so the TUI and Web surfaces
put the five session-search tools in front of the model. That
contradicts the recorded opt-in stance for the model-facing session
query consumer; the ACP example remains the mounted reference.
Remove the row from the shared base, the now-dangling disabled patch in
the opt-in core-web profile, and the workspace dependency. The
ctx.sessionQuery index stays: the TUI's /resume and the Web content
search consume it directly. Both shipped-composition tests now pin the
20-tool catalog.
ds-review-bot round 1 on the DSH-home integration:
- generated wrappers now inject the services their manifest needs (skills/
tools beside loader), and loadPreparedRepository rejects a wrapper fiber
that settles anything but ACTIVE — a composition missing a required
service fails the repository transaction instead of committing an ACTIVE
row over a silently PENDING child (critical finding)
- the github: source ref segment excludes '#', so 'a#b' refs fail at the
config parser with the promised syntax instead of inside pnpm
- watchPersonalPatches re-reads the include's non-patch options per refresh
instead of a registration-time snapshot
- the TUI smoke's cache-seeded wrapper is produced by the real
prepareDshPlugin (cache LAYOUT stays a deliberate external pin)
- new Loader integration test drives a live repositories update through
entry.update: generation swap, old skills removed, failed candidate
rolled back to the previous generation
PR #1100 recorded the golden with the session-lineage navigation still in
the header; PR #1099 removed it. Master's snapshots job was skipped on the
combining merge, so the conflict first surfaced on the next PR's CI.