Master's transactional loader made the invalid-provider PTY case regress:
the HMR main watcher's initial scan refreshed the include mid-initial-apply,
the concurrent group updates stranded the include fiber, and once serialized
the failing apply's rollback deadlocked on HMR's refresh drain — dsh exited
13 with no diagnostic and the terminal stranded, the exact symptom this
branch fixes. Serialize every include child-tree mutation through one queue
and pass ignoreInitial to the HMR main watcher; the failing boot now settles
through boot()'s labelled rejection with the tree disposed and exit 1. The
PTY case asserts the settled diagnostic; the fail-loud release remains the
guard for rejections boot cannot see.
Conflicts: apps/cli/src/tui.ts (keep the release install over master's comment
rewording), packages/ui/app-boot/README* (master's new installFailLoud row
wording plus this branch's release and timeout rows).
The hover affordance framed only the strip right of the crumbs. The bar itself
now carries the outline and the padding in both modes, so hovering previews
exactly the field the click produces and nothing resizes when the two swap.
One keystroke moved the view twice: deleting a separator first narrowed the
pane the draft had just walked away from, then replaced it with its landing.
The tail now filters only the LAST pane — the one whose level the path names —
so a pane on its way out holds still until its landing arrives.
Also from the review round: the walk waits both legs out instead of taking the
submitted-navigation bound (a speculative scan has nothing waiting on it, and
a tail keystroke aborting a slow parent leg would otherwise strand the
two-pane view); a level keeps answering the directory text that produced it,
so `..` segments and Windows forward slashes filter and stop rescanning; the
release-on-miss rule counts displayable rows, so it survives `hidden` ever
meaning more than dot-prefixed; and the editor's 250ms rest joins the other
two constants on the remote-recalibration list.
Skipping the draft-following scan whenever ANY pane happened to list the
directory was the cheaper rule and the wrong one: erasing a segment left the
level being typed on the LEFT, with its own child pane still standing to its
right, so the two panes stopped reading as "where I am, and where I came
from".
The pane arity is now the invariant the editor maintains — the last pane lists
the level the path names, its parent sits beside it, and only a display root
lists alone. Only that last pane's own tail costs no scan; every other
directory part re-lands.
The draft-following scan replaced the panes with one wide level, so typing a
path collapsed the dialog's Miller view — the thing the dialog is. It now
lands through the same selection-anchored landing every navigation uses:
target and parent legs as one frame, the target re-selected in its parent
level, its children on the right. Typing a path moves the Miller view exactly
as a crumb jump does.
One landing shape, two callers: `land(path, {closeEditor, announce})` is what
`navigate` and the draft-following scan share. A submitted path closes the
editor and announces failures; the speculative scan keeps both to itself and
re-parks the focus its swap dropped.
A level a pane already lists still needs no scan at all — the filter alone
answers the draft — so erasing back into the parent's own path keeps both
panes and only moves the filter.
ds-review-bot round one. Keying the debounce on the directory part the draft
named left two states with no recovery until the operator crossed a separator:
a keystroke that superseded an in-flight scan never re-armed one, and an edit
after a rejected submission released the hold with no timer left to release.
The wait is now keyed on the draft itself and decides its target when it
fires, reading the panes through a ref so a landing cannot re-arm it (a host
answering with a differently spelled path would otherwise scan forever).
A landed scan that unmounts the row a keyboard operator Tabbed onto re-parks
focus on the still-open editor; the Modal has no focus trap. That a walked-to
level survives closing the editor is now stated in the README, the Agent Note,
and the module contract. The new e2e stages its own beta directory so running
it alone sees the tree its assertions describe.
The Select Workspace Directory dialog hid its one route into typing a path
behind an invisible click target, and once the editor opened the panes stayed
on whatever level was listed when it opened — so the typed text and the list
under it disagreed for the whole edit.
The edit zone now carries a pencil glyph at the bar's right edge and lights in
the editor's own footprint on hover/focus (the bar keeps one height across the
swap). While editing, the panes follow the draft: a directory part no pane
lists is scanned after a 250ms rest and lands in place, so typing deeper
descends and erasing segments steps back up without leaving the editor, and a
final segment nobody matches releases the prefix filter instead of emptying
the pane it is being spelled into. The draft-following scan is speculative and
silent on failure; Enter still owns the view from submission until landing and
remains the only path that surfaces an error.
The review caught the pwshCoverageExclusions comment claiming the inverse of
the code's behavior: a bare-PATH probe FAILING grants the exemption, so a
win32 host where only install-location pwsh (or 5.1) resolves kept the
exemption while its suites ran - over-exempting, never tightening.
resolvePwshPath/candidatePwshPaths move to the dependency-free
pwsh-local/src/resolve.ts (index.ts re-exports; public API unchanged) and
vitest.config.ts probes with that shared definition, so the exemption is
active exactly when the suites skip. The two spec headers stop saying
'on PATH' for a probe that is deliberately not PATH-only, and the parity
note records the abort backport as the one both-ways parity change (both
languages, pairing re-recorded); catalogs regenerated for the line shift.
A goal round reporting complete or blocked used to conclude the turn at
the tool result, so the model never spoke after the call and sessions
ended on a bare update_goal card. The terminal update now defers one
plugin-sourced <goal_complete>/<goal_blocked> instruction onto its
result asking for a grounded closing message without further tool
calls; the turn then ends through the ordinary no-tool-calls stop.
Direct-human mutations stay uninstructed. Wording chosen by A/B
sampling on deepseek-v4-pro; one extra request per goal lifecycle.
New keyless ACP snapshot goal-wrapup drives the shipped app through
create -> round one -> autonomous complete and pins the injection, the
same-turn closing message, and the completed turn end.
The PR appended a superseded warning to one obsolete durability clause while leaving the same active decision record with mutually incompatible claims about Task-backed continuations, provider resume dispatch, and persistence guarantees. Because implemented Agent Notes are current authority rather than a review-history log, readers could still derive an API and ownership model that no longer exists.
Rewrite the affected decision, alternatives, and consequences in place around the activation-based implementation: ordinary starts remain holder-owned one-shot runs; continuable starts return durable child and accepted message identities; the manager owns materialization, follow-up/report routing, cold resume, and teardown; providers only contribute detached first-create data through prepareContinuable; and flush participation is observable but is not proof that a persistence backend stored state.
Keep the English and Chinese records equivalent, move the Chinese dispose glossary to its new first use, and refresh the pairing sidecar. This commit changes documentation authority only; it does not change runtime behavior.
Validated with the scoped translation-pairing writer and checker, verify-md-wrap, verify-agent-note-format, verify-agent-note-classification, and git diff --cached --check.
Agent setup may await while a mutable contribution registry changes. The previous subagent path validated and committed its provisioning batch inside the setup callback. A revocation queued after that callback returned therefore treated the installation as resident and released it, even though AgentLoop had not published the child yet. AgentLoop could then admit and announce a child whose required capability had already disappeared.
Introduce AgentSetupCommit as the optional synchronous result of create and resume setup. AgentLoop now awaits setup, invokes that commit with no intervening asynchronous boundary, and only then enters the Session and Agent registries. A commit failure follows the existing private-transaction rollback, so neither identity is published and the caller can reuse the id.
Keep continuable-subagent installations provisional until this publication commit. Contribution removal still releases every installation immediately, but now marks an unpublished batch invalid so its commit rejects with ACTIVATION_SETUP_REVOKED. Once the commit succeeds, later removal remains ordinary live revocation.
Cover create and resume ordering, resume commit rejection and identity reuse, and an assembled microtask revocation that leaves only the parent Agent and Session. Update the public JSDoc, architecture flow, package contracts, current Agent Notes, Chinese counterparts, pairing records, and generated Cordis API to describe the new boundary.
Validated with the four focused Agent/subagent test files (91 tests), the isolated assembled regression, targeted TypeScript project builds, generated Cordis API freshness, export JSDoc verification, scoped translation pairing, Markdown wrapping, and Mermaid parsing.