The trajectory host kept the composer as a fixed flex sibling, so the
ledger never reached the viewport bottom. Anchor the composer seat
absolutely over the ledger (reusing chat's fade treatment) and have the
internal scroll panes reserve the composer's live height plus a 16px gap
so end rows and detail bodies scroll clear of the overlay.
(cherry picked from commit 0058a1f4b6e8c2e23bfde7c827a84838cc5ebffc)
The parenthetical listed 14/16 and this branch added 20, but the set never
held to it: IconRightUpOutline14 defaults to 8, IconTreeCorner8x10 to 10,
and IconWarningOutline16 to 14. Drop the list rather than maintain one that
drifts, and retitle the icons test that carried the same generalization.
The session row menu's Archive action carried ic_ds_download_outline_16, a
download tray that reads as "save to disk" rather than "put away". Swap it
for the design's archive glyph — a lidded box with a label slot — added to
the ic_ds_* set as IconArchiveOutline20.
The glyph is native 20, the first of that size in the set, so the menu's
16px icon slot asks for it explicitly. The figma export's 0.11px stroke ring
around the box contour is dropped: it restates the same contour in the same
ink, which currentColor already carries.
The injected instruction persists as a durable user message, so an
unscoped 'Do not call any more tools.' stays in every later request's
history. Scope it: '...in this run; further work waits for the user's
next instruction.' A/B probes on deepseek-v4-pro show the scoped wording
is non-inferior in-turn (4/4 zero tool calls, closing quality unchanged)
and next-turn tool use is unaffected under both wordings; the scoped
form states the instruction's actual lifetime.
- fromRequest placeholder: the last two braces of a consecutive } run now
terminate the placeholder, so patterns may end with a brace quantifier
(bot warning; the truncated pattern could even silently mis-match since
an unclosed { is literal in JS regexes)
- document that derived JSONL entries pass through the same resolution
- widen ToolRunContext/deferContext seam docs beyond composite-only usage
(source JSDoc, README pair, core-data-structures type-equiv blocks)
- pin direct-human blocked as uninstructed, completing the
goal-round/direct-human x complete/blocked test quadrant
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.
A scripted sidecar cannot know values minted at run time, so terminal
goal updates (which must echo the random goal id) were previously
un-scriptable. Placeholders in scripted entries now resolve against the
request corpus at stream time: last match wins, capture group 1 or the
whole match substitutes, and unmatched/invalid/unterminated patterns
fail loud.
Correcting the cold-resume module contract added one JSDoc line above SubagentDescriptorData, but the generated persistence catalog still linked the durable subagent/descriptor event payload to descriptor.ts line 36. That left a dead source pointer and made the repository documentation gate fail even though the catalog content itself was otherwise current.
Regenerate docs/persistence-catalog.md so its source link follows the declaration to line 37. This is a generated-reference correction only: it does not change the durable event vocabulary, payload shape, or runtime behavior.
Validated with pnpm run verify-persistence-catalog and git diff --cached --check; the generator reports the catalog is up to date.
The subagent conversation scenario asserts English role names and compares English accessibility goldens, but it opened a raw Playwright page while the rest of the English Web scenarios use the shared bootstrap that writes dsh.locale before client initialization. Once the subagent surface became localized, the raw page left those assertions dependent on ambient browser or persisted locale selection.
Create the page through newEnglishPage so the product sees an explicit English preference before boot, while preserving the standard 1680 by 1000 viewport. Chinese-surface scenarios continue to bypass this helper and advertise their own locale explicitly.
A fresh library build and production Vite build completed successfully. The focused assembled subagent-conversation Web suite then passed all 8 keyless replay tests against the updated singular-copy golden, and the staged diff passes formatting, lint, and whitespace hooks.
The localized catalog spec introduced two package-local translation stubs: one manually looped over interpolation parameters and the other indexed the Chinese dictionary directly. That duplicates framework test plumbing and can drift from the shared lookup, fallback, and placeholder semantics used by the rest of the client suites.
Use makeTranslate from dsh-client-test-runtime as the single Chinese translator for both catalog and read-only composer assertions. Record the test-only workspace dependency in the ui-subagent manifest and lockfile; no production dependency or runtime bundle edge is added.
This removes twelve lines of local translation behavior while preserving the same Chinese assertions and exercising the shared interpolation path. Both ui-subagent test files pass with all 28 tests, the package TypeScript project checks cleanly, and the staged diff passes formatting, lint, and whitespace hooks.
The PR moved child scope-effect registration into the contribution-installation try/catch solely to cover a hypothetical throw, while documenting that Context.effect cannot reject for the live unpublished scope passed to apply. The change therefore added control-flow and rollback implications for a failure mode the API does not expose, without changing observable behavior.
Keep the rollback boundary focused on contribution installers, which are the operations that can actually fail and leave recorded installations to unwind. Register the child-scope cleanup effect immediately after that boundary, as before; its disposer still converges with contribution removal through the registry idempotence rules.
This is a behavior-preserving removal of unnecessary code. The focused activation-setup-registry suite passes all 11 tests, the subagent TypeScript project checks cleanly, and the staged diff passes whitespace validation.
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.
The descriptor module claimed that no parent exists during cold resume, using that as the reason maxTokens cannot be inherited. Continuable follow-up actually requires and authorizes the exact live direct parent before it loads the descriptor and materializes the child, so the stated lifecycle fact was false.
Keep the real persistence decision explicit: per-activation budgets are not durable descriptor composition. Cold resume reconstructs child options only from the curated durable fields, so it deliberately neither restores the establishing budget nor inherits the live parent current transient budget; the resumed provider and model route defaults apply.
This is a contract-only correction with no runtime change. The exported JSDoc gate remains clean.
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.
ACP waits for every owned Agent disposal and throws one AggregateError when any Session teardown fails. The aggregate message embedded each rejected value with String(failure) because the connection-close logger itself renders only the outer error message. String preserves only an Error name and message, so causes and AggregateError members disappeared from the operational warning.
Render each per-session rejection with the existing errorChain diagnostic helper before joining it into the outer message. The original rejected values remain in AggregateError.errors for programmatic inspection, while the message now carries cause chains and nested aggregate members through the String-based logger.
Exercise a disposal failure containing both AggregateError members and a nested cause, while retaining the existing barrier that proves the second Session finishes disposal before any warning is emitted. All 10 ACP disposal tests pass and the ACP TypeScript project builds cleanly.
refreshSubagents previously treated every overlapping caller as proof that the in-flight response was stale. Selection, menu opening, and reconnect paths can legitimately request the same catalog concurrently without any host mutation, so those reads were coalesced and then followed by an unnecessary second RPC.
Restore ordinary in-flight coalescing at the public refresh boundary. The debounced host/session-added path now owns the membership-specific stale mark: if its timer fires during an older pull, it queues one trailing request; otherwise it starts the refresh directly. Parent removal keeps its separate explicit invalidation and trailing-refresh path.
Add a regression proving two overlapping reads share one Promise and issue one RPC. Rework the membership test to start from a restored selected parent, so only the host membership frame can request the trailing pull instead of the test priming the stale bit with an unrelated duplicate read.
Validated with both focused catalog cases, all 40 SessionManager tests, and the client runtime TypeScript project build.
The earlier removal fix invalidated parentAvailable immediately and queued a trailing subagent.list request, but it still applied the already in-flight success verbatim. That stale success reopened the composer and became the trailing request baseline. If the trailing request failed, its error snapshot preserved parentAvailable:true indefinitely.
Record a false-only parent availability override on the exact in-flight catalog request when the owner removal frame arrives. Successful and failed responses now replay that request-local invalidation before publishing a snapshot, and addressed child Sessions receive the same effective value. The trailing request therefore starts from a false baseline and a later transport or business failure cannot resurrect the removed parent.
Strengthen the regression to assert the catalog and selected child remain read-only immediately after a stale parentAvailable:true success, then fail the trailing pull and assert the error snapshot remains unavailable. The complete SessionManager test file passes all 39 tests, and the client runtime TypeScript project builds cleanly.
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.