toolPairingBalancedAfter previously answered by resolving a cached positional successor and reading its before-balance, with a null-successor depth fallback. Both queries are the same prefix property sampled at adjacent cuts, so the cache now holds one per-cut balance sequence (N nodes -> N+1 cuts) plus a seq->position index; before/after differ only by a cut offset. The successor map, the duplicate rebuild/extend fold loops, and the non-null assertion are gone, and the running counter is named inProgressToolCalls. Docs describing the successor mechanism are updated in place.
compact/ — compaction capability family
A three-package capability seam (see capability seams): an abstract compaction interface, a backend that summarizes, and the model-facing tool that consumes it. The interface and a first backend (compact-basic/) exist; the consumer tool is deferred. All product packages.
| Package | Role | ctx key |
|---|---|---|
compact/ |
Abstract compaction seam (interface + compact/* events + CompactionResult) |
ctx.compact |
compact-basic/ |
A backend: chars-per-token estimation (charsPerToken, default 4) + token-budget retention + llm.stream() summarization |
(registers ctx.compact) |
tool-compact/ (deferred) |
Model-facing /compact tool over ctx.compact |
(registers on ctx.tools) |
The interface lives at compact/compact/, the backend at compact/compact-basic/. Unlike the bash seam, it depends on dsh-session and dsh-llm — its verbs are defined over a Session and its output is the ContentBlock vocabulary, so the contract cannot be expressed without naming them. That deviation from the "interface depends only on cordis" guidance is intentional and recorded in the compaction capability-seam RFC. A tokenizer- or template-based backend would replace compact-basic without touching the interface or the tool.