feat(web): subagent Agent cards, completion turns, and the child transcript dialog - #304
Merged
Merged
Conversation
Rustam Sadykov (SBOne-Kenobi)
requested review from
Olga Lavrichenko (OLavrik),
danyaberezun and
Rinat S (rsolmano)
as code owners
August 26, 2026 12:58
🌐 Vibecoding website preview
This comment updates in place on every push that touches the vibecoding website or shared build inputs. |
🌐 Website previewPreview retired when this pull request closed. |
This was referenced Aug 26, 2026
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 26, 2026
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
Rustam Sadykov (SBOne-Kenobi)
force-pushed
the
subagents-web
branch
from
August 26, 2026 13:49
25ae090 to
569bce5
Compare
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 26, 2026
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 26, 2026
…arrowing - SubagentCompletionCard: three-state icon — green check only for completed, red X for error, warning triangle for aborted; a turn-capped run no longer reads as success (#304 review finding). - readRunDetails narrows through contracts' isDelegationRunDetails — the same strictness the completion-message guard gained in layer 2 (an open status string or empty usage no longer passes). Pinned.
Rustam Sadykov (SBOne-Kenobi)
force-pushed
the
subagents-web
branch
from
August 26, 2026 14:41
569bce5 to
c7d93ea
Compare
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 26, 2026
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 26, 2026
…arrowing - SubagentCompletionCard: three-state icon — green check only for completed, red X for error, warning triangle for aborted; a turn-capped run no longer reads as success (#304 review finding). - readRunDetails narrows through contracts' isDelegationRunDetails — the same strictness the completion-message guard gained in layer 2 (an open status string or empty usage no longer passes). Pinned.
Rustam Sadykov (SBOne-Kenobi)
force-pushed
the
subagents-web
branch
from
August 26, 2026 15:43
c7d93ea to
a6c9a81
Compare
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 27, 2026
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
Rustam Sadykov (SBOne-Kenobi)
added a commit
that referenced
this pull request
Aug 27, 2026
…arrowing - SubagentCompletionCard: three-state icon — green check only for completed, red X for error, warning triangle for aborted; a turn-capped run no longer reads as success (#304 review finding). - readRunDetails narrows through contracts' isDelegationRunDetails — the same strictness the completion-message guard gained in layer 2 (an open status string or empty usage no longer passes). Pinned.
Rinat S (rsolmano)
approved these changes
Aug 28, 2026
stack merge was automatically disabled
August 28, 2026 21:33
Pull Request is not mergeable
stack merge was automatically disabled
August 28, 2026 21:34
Pull Request is not mergeable
Rinat S (rsolmano)
pushed a commit
that referenced
this pull request
Aug 28, 2026
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
Rinat S (rsolmano)
pushed a commit
that referenced
this pull request
Aug 28, 2026
…arrowing - SubagentCompletionCard: three-state icon — green check only for completed, red X for error, warning triangle for aborted; a turn-capped run no longer reads as success (#304 review finding). - readRunDetails narrows through contracts' isDelegationRunDetails — the same strictness the completion-message guard gained in layer 2 (an open status string or empty usage no longer passes). Pinned.
Rinat S (rsolmano)
force-pushed
the
subagents-web
branch
from
August 28, 2026 21:36
b3ee8c9 to
221ccd3
Compare
Rinat S (rsolmano)
disabled the stack merge
August 28, 2026 21:43
Rinat S (rsolmano)
added a commit
that referenced
this pull request
Aug 28, 2026
…ent layer (#302) * feat(packages): pi-delegation + pi-subagents — portable pure-pi subagent layer pi-delegation: delegation core — child AgentSessions spawned from a parent session (hidden children, per-scope store, concurrency semaphore, run registry). pi-subagents: the Agent tool extension over it (foreground await + background completion injection, per-call definition discovery, built-in roles). Architecture decision #14 records the layering; AGENTS.md lists the packages. Squashed from subagent-research-planning (layer 1/3). * fix(packages): review fixes — per-run outcome deltas, live runtime binding, error results keep details Review findings on the subagents stack (#302/#303/#304): - pi-delegation: a run's finalText/usage derive from a baseline captured before prompt() (per-run deltas), never the child session's cumulative totals — a reusable child no longer reports stale text or double-counted usage on sequential runs. - pi-delegation: modelRuntime accepts a live provider function resolved per createChild, so an embedder with generational runtimes (Central connect/disconnect) never pins children to the generation the service was created under. - pi-subagents: an error outcome's thrown tool result keeps the run's final details — stashed by toolCallId, re-injected via a tool_result override — so a failed run's transcript stays openable. All three pinned by regression tests verified to fail on the unfixed code. * fix(packages): review round 2 — fallback shutdown dispose, result lineage, parent-retained runtime, stash sweep Review findings on #302/#303 plus same-class hardening: - pi-subagents: the zero-config fallback service disposes its parent's children on session_shutdown (a vanilla-pi background child no longer outlives its session); embedder-injected services stay untouched. - pi-subagents: get_subagent_result enforces lineage — another parent's child on the shared service takes the unknown-id path (pinned, bites). - pi-delegation: ParentContext optionally carries the parent's retained ModelRuntime; createChild prefers it over the service binding, so an embedder with per-session runtime generations gives children their parent's generation (pinned, bites). Host half lands in layer 2. - pi-subagents: the errored-details stash is swept on turn_end and session_shutdown so an aborted finalization cannot strand entries. * fix(packages): review round 3 — suppress background completion delivery at session shutdown A detached run's continuation no longer sends its completion (triggerTurn) into a session that received session_shutdown — a wasted provider turn racing teardown. Parent-turn aborts still deliver. Pinned by emitting session_shutdown through the public extension runner; harness resolveParent now projects any registered live session so a dedicated session can spawn the child. * fix(packages): review round 3 — mark all children disposed before awaiting any abort in disposeChildrenOf Aborting a running child frees its semaphore slot; with the sequential mark-and-abort loop suspended on a later abort, a still-unmarked queued sibling won the slot and issued a provider request mid-cascade. Marking the captured set first lands it on the existing disposed-before-start guard. Pinned with two running + one queued child (limit 2) — the loop must suspend on a second abort for the release to beat the marks. * todo: Specify and implement opaque provider mirroring for fallback children ThinkRail-Todo: 01a047b5-14db-7a7e-8538-09b72f147467/t_5fdc507c7af6 * todo: Add synthetic dynamic-provider regression coverage ThinkRail-Todo: 01a047b5-14db-7a7e-8538-09b72f147467/t_083134006835 * fix(packages): align running status updates * fix(packages): isolate fallback runtimes by parent * fix(packages): cancel queued runs through ChildHandle.abort * fix(packages): settle active runs before child disposal * fix(packages): share teardown across concurrent disposal * fix(packages): rebuild mirrored provider registrations --------- Co-authored-by: rsolmano <rinat.suleimanov@jetbrains.com>
Rinat S (rsolmano)
pushed a commit
that referenced
this pull request
Aug 28, 2026
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
Rinat S (rsolmano)
pushed a commit
that referenced
this pull request
Aug 28, 2026
…arrowing - SubagentCompletionCard: three-state icon — green check only for completed, red X for error, warning triangle for aborted; a turn-capped run no longer reads as success (#304 review finding). - readRunDetails narrows through contracts' isDelegationRunDetails — the same strictness the completion-message guard gained in layer 2 (an open status string or empty usage no longer passes). Pinned.
Rinat S (rsolmano)
force-pushed
the
subagents-web
branch
from
August 28, 2026 21:44
221ccd3 to
e4d4017
Compare
…script dialog Live Agent tool cards with REPLACE-semantics run details, the background subagent-completion custom message rendered as its own chat turn, and the child transcript dialog polling subagent.getTranscript while the registry still knows the run. e2e: @agent live spec (foreground fan-out + background completion) with a seeded echo-agent fixture; scripts: pure-pi subagents smoke (bun run smoke:subagents). Squashed from subagent-research-planning (layer 3/3).
…tion Review finding on #304 (fix lands in pi-subagents, layer 1): an error tool result now carries the run's final details, so the failed card's transcript action survives reload. Pinned at the hydration seam; subagent tools SPEC records the failed-run guarantee.
…arrowing - SubagentCompletionCard: three-state icon — green check only for completed, red X for error, warning triangle for aborted; a turn-capped run no longer reads as success (#304 review finding). - readRunDetails narrows through contracts' isDelegationRunDetails — the same strictness the completion-message guard gained in layer 2 (an open status string or empty usage no longer passes). Pinned.
ThinkRail-Todo: 01a04907-28ba-7ea9-b3d9-deee11fbe0ab/t_2d400f0bf6eb
Rinat S (rsolmano)
force-pushed
the
subagents-web
branch
from
August 28, 2026 21:58
ce9833a to
f79ce52
Compare
Iaroslav (Rick) Postovalov (CommanderTvis)
added a commit
to CommanderTvis/thinkrail
that referenced
this pull request
Aug 31, 2026
The engine stops being pi-in-process and becomes any ACP agent the host launches as a child and speaks JSON-RPC to over stdio. A fatal agent or provider fault now kills one supervised child, not the host. packages/acp — the ACP client, and the only client-side package allowed to name an ACP type. connection/ spawns and negotiates (tolerating an agent that writes a banner before its first message), client/ implements what we offer agents (fs, terminals, permissions, elicitation, MCP over the ACP channel), translate/ is the single seam where protocol shapes become ThinkRail shapes, registry/ resolves the published agent registry, and testing/ validates a committed frame corpus against the SDK's own schema so an SDK bump fails here rather than in production. packages/contracts — chatProtocol.ts replaces piProtocol.ts: ThinkRail's own transcript model, a delta event union with three write modes, and a ChatCapabilities record carrying one field per UI-visible affordance, so panels read a negotiated record instead of probing the agent. The package now imports nothing at all. packages/pi-agent — the bundled first-party agent wrapping pi, launched as `thinkrail acp-pi`. It is the only package permitted to import pi, and it carries the four signals ACP has no words for (retry, compaction, queue, steering) in a namespaced _meta. packages/server — the host: an ACP session manager over its own append-only transcript store, so history, search, jump-to-message and reopen work with every agent rather than only those implementing ACP's optional session/load. Credentials belong to the agent now; auth is the policy layer over the six ACP credential operations plus the Central lifecycle the host must own. apps/web — renders the ThinkRail transcript model, never an ACP shape, and gates every control on the negotiated capability record. scripts/check-architecture.ts makes the module boundaries a gate rather than a convention: the ACP SDK stops at five sub-modules of packages/acp plus packages/pi-agent, and pi stops at packages/pi-agent. Rebased onto main. Carried through unchanged: the bottom workbench panel, terminal reservations, Pino host logging, browser history navigation, the subprocess budget, the Remix icon pack, the numeric spacing scale, the gh-CLI Open PR module and the Cloudflare website. Re-landed on the ACP wire, where the shapes differ: - Mid-stream queue editing. The host owns the steering queue, so session.clearQueue and session.removeQueued need none of the drain-and-re-queue emulation pi's all-or-nothing clearQueue forced. queue_changed carries the queued texts beside the depths, and session.abort restores them; SessionQueueContent holds PromptContent so an image-bearing queue restores losslessly. - The native /compact command moves to the agent side. ACP already carries a command list, so packages/pi-agent advertises compact and intercepts it in session/prompt — no session.compact wire method, and any agent that advertises its own compact command gets the same affordance for free. - Plan review (reviewer + reflector sessions, the verdict gate, the auto-fix cycle) runs on AgentSessionManager: sessions are created through it and configured by config-option value, sends are synchronous so the rollback keys off a throw rather than an acceptance window, settlement is observed as turn_settled, and notices land as durable notice markers. The reviewer policy is agent-neutral on the wire — reviewModel/reviewEffort are opaque config-option values, not a pi Model. - Extensions get a real theme (JetBrains#316): plainTextTheme moves into packages/pi-agent beside the bridge it serves, replacing an empty object cast, and an extension failure is named to the client before the session registers. Rebased again onto the Electrobun desktop packaging (JetBrains#317). The desktop app drives the same host, so `createServer` now answers `{ port, stop, shutdown }` with the ACP teardown behind `shutdown()`, `bootHost` runs under upstream's host-ownership lease, and `apps/cli` takes the shared build-support and artifact-probe modules. `artifactProbes.ts` is ported to the ACP wire — the model catalog is read from a session's config options, Central status from `agent.providers`, the trash probe seeds a host transcript, and the retired `provider.loginStart` OAuth leg becomes an `agent.authMethods` probe that the CLI smoke runs beside its own `acp-pi` initialize legs. Upstream's `check:boundaries` table learns the ACP layout (`packages/acp`, `packages/pi-agent`, and the server/cli edges into them); it runs alongside `check:arch`, which keeps policing the pi and ACP-SDK import invariants. Rebased again onto the subagent layer (JetBrains#302/JetBrains#303/JetBrains#304), frontend-local workbench layouts (JetBrains#338), newest-first chat order (JetBrains#327) and Try-again recovery (JetBrains#345). - pi-delegation and pi-subagents are pi packages, so the delegation host moves from packages/server into packages/pi-agent and scopes child sessions by an encoding of the worktree cwd — the agent has no workspace ids. The Agent card registers through the existing tool-renderer seam unchanged; the pi-only subagent-completion custom message drops, because under ACP the child's result already arrives on the Agent tool call. - subagent.getTranscript becomes the first ThinkRail _ext round-trip: the host asks the agent over dev.thinkrail.v1/subagent/transcript and the agent answers with ChatMessages, so the child transcript reaches the UI without the host owning sessions it never created. - Layouts leave the wire with upstream: layout.get/layout.replace, the layout module and the layout.changed channel are gone, and the workbench frame is the web's own state. - The desktop's generated entry registers only the trash helpers now; the bundled pi runtime belongs to the agent process, which registers its own. - Try-again attaches to an error notice, since notices replace the pi-era error turn. Deliberately not carried: the reviewer model/effort pickers in Settings (ACP has no session-less config read to source the options from — the auto-fix toggle stays), and useTranscriptSync's revision fence (this transcript model is one fold over one event log, so a reloaded transcript is the live object graph by construction). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFWLfHUiKpPbiAHxiD75BJ
Iaroslav (Rick) Postovalov (CommanderTvis)
added a commit
to CommanderTvis/thinkrail
that referenced
this pull request
Aug 31, 2026
The engine stops being pi-in-process and becomes any ACP agent the host launches as a child and speaks JSON-RPC to over stdio. A fatal agent or provider fault now kills one supervised child, not the host. packages/acp — the ACP client, and the only client-side package allowed to name an ACP type. connection/ spawns and negotiates (tolerating an agent that writes a banner before its first message), client/ implements what we offer agents (fs, terminals, permissions, elicitation, MCP over the ACP channel), translate/ is the single seam where protocol shapes become ThinkRail shapes, registry/ resolves the published agent registry, and testing/ validates a committed frame corpus against the SDK's own schema so an SDK bump fails here rather than in production. packages/contracts — chatProtocol.ts replaces piProtocol.ts: ThinkRail's own transcript model, a delta event union with three write modes, and a ChatCapabilities record carrying one field per UI-visible affordance, so panels read a negotiated record instead of probing the agent. The package now imports nothing at all. packages/pi-agent — the bundled first-party agent wrapping pi, launched as `thinkrail acp-pi`. It is the only package permitted to import pi, and it carries the four signals ACP has no words for (retry, compaction, queue, steering) in a namespaced _meta. packages/server — the host: an ACP session manager over its own append-only transcript store, so history, search, jump-to-message and reopen work with every agent rather than only those implementing ACP's optional session/load. Credentials belong to the agent now; auth is the policy layer over the six ACP credential operations plus the Central lifecycle the host must own. apps/web — renders the ThinkRail transcript model, never an ACP shape, and gates every control on the negotiated capability record. scripts/check-architecture.ts makes the module boundaries a gate rather than a convention: the ACP SDK stops at five sub-modules of packages/acp plus packages/pi-agent, and pi stops at packages/pi-agent. Rebased onto main. Carried through unchanged: the bottom workbench panel, terminal reservations, Pino host logging, browser history navigation, the subprocess budget, the Remix icon pack, the numeric spacing scale, the gh-CLI Open PR module and the Cloudflare website. Re-landed on the ACP wire, where the shapes differ: - Mid-stream queue editing. The host owns the steering queue, so session.clearQueue and session.removeQueued need none of the drain-and-re-queue emulation pi's all-or-nothing clearQueue forced. queue_changed carries the queued texts beside the depths, and session.abort restores them; SessionQueueContent holds PromptContent so an image-bearing queue restores losslessly. - The native /compact command moves to the agent side. ACP already carries a command list, so packages/pi-agent advertises compact and intercepts it in session/prompt — no session.compact wire method, and any agent that advertises its own compact command gets the same affordance for free. - Plan review (reviewer + reflector sessions, the verdict gate, the auto-fix cycle) runs on AgentSessionManager: sessions are created through it and configured by config-option value, sends are synchronous so the rollback keys off a throw rather than an acceptance window, settlement is observed as turn_settled, and notices land as durable notice markers. The reviewer policy is agent-neutral on the wire — reviewModel/reviewEffort are opaque config-option values, not a pi Model. - Extensions get a real theme (JetBrains#316): plainTextTheme moves into packages/pi-agent beside the bridge it serves, replacing an empty object cast, and an extension failure is named to the client before the session registers. Rebased again onto the Electrobun desktop packaging (JetBrains#317). The desktop app drives the same host, so `createServer` now answers `{ port, stop, shutdown }` with the ACP teardown behind `shutdown()`, `bootHost` runs under upstream's host-ownership lease, and `apps/cli` takes the shared build-support and artifact-probe modules. `artifactProbes.ts` is ported to the ACP wire — the model catalog is read from a session's config options, Central status from `agent.providers`, the trash probe seeds a host transcript, and the retired `provider.loginStart` OAuth leg becomes an `agent.authMethods` probe that the CLI smoke runs beside its own `acp-pi` initialize legs. Upstream's `check:boundaries` table learns the ACP layout (`packages/acp`, `packages/pi-agent`, and the server/cli edges into them); it runs alongside `check:arch`, which keeps policing the pi and ACP-SDK import invariants. Rebased again onto the subagent layer (JetBrains#302/JetBrains#303/JetBrains#304), frontend-local workbench layouts (JetBrains#338), newest-first chat order (JetBrains#327) and Try-again recovery (JetBrains#345). - pi-delegation and pi-subagents are pi packages, so the delegation host moves from packages/server into packages/pi-agent and scopes child sessions by an encoding of the worktree cwd — the agent has no workspace ids. The Agent card registers through the existing tool-renderer seam unchanged; the pi-only subagent-completion custom message drops, because under ACP the child's result already arrives on the Agent tool call. - subagent.getTranscript becomes the first ThinkRail _ext round-trip: the host asks the agent over dev.thinkrail.v1/subagent/transcript and the agent answers with ChatMessages, so the child transcript reaches the UI without the host owning sessions it never created. - Layouts leave the wire with upstream: layout.get/layout.replace, the layout module and the layout.changed channel are gone, and the workbench frame is the web's own state. - The desktop's generated entry registers only the trash helpers now; the bundled pi runtime belongs to the agent process, which registers its own. - Try-again attaches to an error notice, since notices replace the pi-era error turn. Rebased again onto the off-the-event-loop git reads (JetBrains#265). The review and todo read paths are async now, so the host's review send, todo fix request and review snapshot await them; the plan-fix flow keeps upstream's per-item latch (claim on entry, release in a finally) around our synchronous ACP send, and firstOpenWorkspace follows listWorkspaces into a promise. Deliberately not carried: the reviewer model/effort pickers in Settings (ACP has no session-less config read to source the options from — the auto-fix toggle stays), and useTranscriptSync's revision fence (this transcript model is one fold over one event log, so a reloaded transcript is the live object graph by construction). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFWLfHUiKpPbiAHxiD75BJ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Layer 3/3 of the subagents stack: the web UI for subagent runs — live
Agenttool cards, background-completion turns, and the child transcript dialog — plus the@agente2e coverage and the pure-pi smoke script.Squashed from
subagent-research-planning(the remote archive branch of the original history). This layer's tree is byte-identical to the verified squash-merge of the feature branch onto main.Stack: #302 (packages) ← #303 (host) ← #304 (this).
Changes
apps/web/src/chat/tools/subagent— theAgenttool renderer: live run card fed bypartialResult.details(REPLACE semantics), report fold on completion,runDetailsreaders/formatters. Registered via the tool registry (capability and presentation joined by tool name). Spec:apps/web/src/chat/tools/subagent/SPEC.md.apps/web/src/chat—subagent-completioncustom messages become their ownsubagentCompletionturn (a background run's tool card freezes at its ack — the completion turn is the terminal signal), on both the live reducer and hydration paths;SubagentTranscriptDialog(an integration file, likeChatView) reads the child transcript viasubagent.getTranscriptand polls only while the host still reports a registrystatus. Reached throughChatActions.openSubagentTranscript— the cards stay presentational.e2e—subagents.live.spec.ts(@agent): foreground parallel fan-out (live cards → report fold → transcript dialog) and a background run's completion card arriving live;fixtures/agents.tsseeds an echo-agent definition.scripts+ rootpackage.json—bun run smoke:subagents: the pure-pi smoke proving the packages work under vanilla pi, no ThinkRail.Testing
bun run test— full suite green (14 turbo tasks).bun run e2e— all 8 shards passed (122s).bun run e2e:agent -- e2e/subagents.live.spec.ts— 2 passed against a real provider.bun run e2e:binary— 273 passed on this tree;build:binary+smoke:binarygreen.bun run smoke:subagents— OK against a real provider (child transcript persisted).check:deps,check:seams,lint,typecheck— all green.Screenshots
All captured on this stack's final tree (post theme/spacing overhaul), driven by the seeded echo agent against a real provider.
Before (this layer's UI stripped — the host's
Agenttool renders through the generic fallbacks):After: