Rewrite the agent-scope RFC with executable examples and an explicit security non-goal. Harden subagent scalar and depth validation, and pin live tool-filter semantics across code, tests, and generated docs.
Every packages/*/* README now carries a canonical '## Known Limitations and
Deferred Work' section: condensed, evidence-backed bullets for consumer-visible
gaps (unimplemented features, platform caveats, MVP cuts) and consciously
postponed work (TODO/FIXME/XXX markers, RFC deferrals still open). The ten
pre-existing ad-hoc variants ('What is NOT here (TODO)', 'Deferred',
'Limitations (MVP)', 'Known limitations (tracked TODOs)', ...) are normalized
into the canonical heading.
A new doc-sync gate, scripts/verify-readme-limitations.ts, enforces the shape:
exactly one limitations-like heading per package README, byte-equal to the
canonical h2, with at least one bullet; near-miss headings fail so variants
cannot creep back. Packages with genuinely nothing to declare (dsh-brand,
dsh-timeout, dsh-subagent-mock, dsh-app-boot) are whitelisted in the script and
must NOT carry the section; whitelist entries are validated against the scanned
package set so a rename fails loud.
Wired into the doc-sync chain (package.json) and the run-gates doc-sync leaf
set; the standing rule lands in packages/AGENTS.md and the adding-a-package
cookbook; decision record in
docs/rfc/implemented/process/2026-07-10-readme-known-limitations-gate.md
(RFC index regenerated).
Also fixes two stale '(deferred)' markers claiming dsh-compact-basic is
unimplemented (the dsh-compact seam README's package table and the seam's
module doc comment).
The exact-disposer fix (5fbac8be B1) repaired agents.register but left the
same wrapper (return () => void dispose()) at seven sibling sites:
tools.register, tools.restrict, systemPrompt.section/tools/variable,
agents.setFactory, and subagents.registerProvider. A wrapper makes correct
composite usage unrepresentable — the exact disposer cannot be recovered, so
a generator effect yielding it leaves the inner effect disposing as a
CONCURRENT SIBLING on owner unload, silently reproducing B1's ordering
corruption. The exact disposer serves both usages (composite-nestable AND
fire-and-forget callable); all seven now return it, typed
() => Promise<void> | void, with the convention pinned by a discriminating
test: an async-link composite probe that passes with the exact disposer and
observes the sibling unregistration firing mid-drain with a wrapper.
Re-auditing also surfaced that B1 itself SHIPPED a full-lint failure: it
changed register()'s return type without updating cross-file consumers
(agent.spec.ts dispose() statements, tool-bash's disposer list), which the
staged-scoped pre-commit lint never saw — pnpm run lint was red at HEAD.
Those three sites and this change's own fallout are fixed together: tests
now await disposers (stronger — they observe the full unwind), sync
paths void them, and the two annotation sites carry the honest union type.
agents.register's README line had drifted the same way (B1 updated the
JSDoc, not the README) — all seven README signatures now match; services
catalog regenerated.
Every subject-extractor row of the invariants carrier table is exercised
with a matching and a foreign-keyed carrier; the HMR re-apply seed path
(sessions of agents that predate the plugin are marked started) is pinned;
the scoped tool-provider disposal, plural restrict() validation, singular
scopeHost absentee, tool-subagent passthrough, stale-stage drop, and
disposing-parent spawn (INACTIVE_EFFECT, no orphan) each gain their test.
Two genuinely defensive branches carry justified v8-ignore markers.