- permission-presets: register the permissions unit synchronously before the
existing-session sweep, so a remount reads folded knob state instead of
treating every session as fresh; add a regression test for that path
- sandbox-policy/terminal-bash: mount the projection registry in the 5 pwsh
terminal tests, the sdk-minimal bundle, and the e2b fixture composition;
declare the new package dependency in both manifests
- plan-mode: restore .strict() on the plan unit state schema and drop the
deleted foldPlanMode from the bilingual READMEs
- session-title/session-projection: sync bilingual READMEs to the mandatory
projection seam and re-record translation pairing
- docs: turnBoundary reader contract, subagent schema comment, token-meter
import comment, sandbox-policy module docstring
A running turn disables the composer by flipping contenteditable to
false on the same element. fill() throws there immediately — a disabled
textarea used to hold it back through actionability — and isEnabled()
reports true for a div regardless, so the permission-policy scenario's
post-settle wait never waited and its next gesture raced the re-enable
render. The window is a few frames wide; #3083's Remote-routed subagent
control stretches settle enough to hit it on CI.
writeComposerDraft now waits for contenteditable="true" before acting,
and the permission-policy scenario drives all four sends through it with
the settle wait pinned to the attribute.
Discovery proved only that a composition parsed, so a preset naming a
package a later rename took away kept a healthy card and its place in
every picker until a person switched to it. It now resolves each row it
can prove will start, reading the package off disk and falling back to
the resolver only for names that look absent — the resolver costs a
synchronous hooks-thread round-trip under the source launch's tsx hook,
which the walk avoids for every row it clears.
The mount diagnostic followed `AggregateError.errors` but never a cause,
so a group that failed on two rows named neither. It now follows a cause
that carries more than its own message.
A refused switch left the chip's label snapping back with no account of
why, which is the only account there can be for a preset that resolves
and then refuses. It announces through the shared Toast, which gained a
caller-set hold for a cause that names packages and rows.