Conflict: apps/web/tests/workspace-flow.snapshot.ts was deleted on
master (#921 sinks assembled-app journeys to package-level benches)
and modified here (show-hidden/prefix-filter and crumb-back lanes).
Resolved by taking the deletion: the same behaviors are asserted at
package level in directory-picker-browse's directory-browser.spec.tsx
and client-flow.spec.tsx, which is the post-migration home for them.
ZiyaZhang approved 97a192d7b; the subsequent bot-review rounds (7-24)
landed after that approval and were not requested by a human reviewer.
This commit restores the approved tree verbatim as a forward commit
(pushed history stays intact). git diff 97a192d7b is empty.
The rename impl narrows on SessionTitleInvalidError: only an
empty-normalizing title maps to title-invalid (its message renders verbatim
in the rename dialog alert), while liveness/disposal races fall to internal;
the absent-service message trims to one presentable sentence. rpc-schemas
gains the title-invalid accept/missing-details lines; cosmetic ordering
(type-only import comment, tsconfig reference, schema import order) restored.
New unary method in RpcMethodMap with the title-invalid error code; the impl
resolves the agent (cold sessions resume first) and delegates to
ctx.sessionTitle.rename, returning the normalized title plus its event seq so
clients settle the title projection cell ahead of the push frame. session.fork
stays on the reserved-seam list.
Two races from the #572 review, still live in the ported registry:
An ask whose signal aborted between the service's own check and the
microtask-deferred waterfall dispatch would register its abort listener
AFTER the signal fired — never invoked, entry pending forever, zombie
frame on every mux replay. The answerer now settles 'cancelled'
synchronously before publishing anything.
The audit back-scan let a callId-less ask claim the newest unclaimed
asked record even when that record carried another call's id. Pairing is
now shape-symmetric: callId-bearing asks take exactly their call's
record, callId-less asks take only callId-less records — neither can
steal under parallel asks.
Disposability parity with the question provider: a gateway disposed while
approvals are pending settles every registry entry as 'cancelled' (the
service's fail-closed vocabulary), so no ctx.approval ask dangles past the
proxy's lifetime and mux subscribers see the withdrawal. Spec mounts the
proxy on its own fiber and drives dispose with a live ask.
Addresses the ds-review-bot suggestion on PR #851.
Selecting a preset from the hero pushed the session into the conversation
view: the /permission switch logs its command/run + command/done pair, the
pair folds into flow nodes, and the composerPhase predicate counted ANY
node as conversation — so the hero (composerPhase === 'blank') collapsed.
The host-side blank bit was already correct (sessionBlank = no turn/start;
knob events open no turn), but the client derives its phase from window
content, and command rows are log-only records, not conversation.
derivePhase's hasContent now excludes command nodes — the client mirror of
the host predicate. The knob events themselves never fold (not
surface-eligible), so the pair was the only leak. Covers /plan on the hero
identically (same lifecycle pair, same predicate).
Specs: the host blank spec pins the three knob events as standalone
events; a session spec drives the /permission pair through the live path
and asserts phase stays 'blank' while the command node renders.