Sandeep Somavarapu
90d · built 2026-09-30
Performance
What Sandeep Somavarapu shipped in the selected window, measured in ETV, and how it compares with the 90 days before it.
Effective capacity
+9.1engineers
delivers like 10.1 (10.1x pre-AI)
Output (ETV)
194.5ETV
+130.0% vs 84.6 prior
Features share
28.8%
−20.8 pp vs prior window
Fixes share
10.6%
+0.1 pp vs prior window
Work mix
28.8% Features14% Maintenance43.6% Tests3.1% Docs10.6% Fixes
322 commits over 90 days, ending 2026-09-30.
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 11 %
- By Features share
- Top 33 %
Daily performance
Daily ETV, stacked by Features, Maintenance, Tests, Docs and Fixes.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 10 by ETV in the last 90 days.
- 17.5ETVagentHost: make the orchestrator own session enumeration and chat lifecycle (#329633) * agentHost: relocate Session ownership into the orchestrator (T2/T4) Make the orchestrator (AgentService + AgentHostStateManager) own the Session concept - identity, lifecycle, and grouping - so the agent harness talks only in chats. Session provisioning stays agent-specific but is now invoked through the chat surface instead of a Session-typed method, honoring "represent, don't orchestrate". - Create: `_provisionSessionViaDefaultChat` allocates the session URI and drives `chats.createChat(defaultChatUri, { provisionSession })`; the agent's provisioning runs inside creating the default chat and returns `IAgentCreateChatResult.provision`. - Dispose: routes to `chats.disposeChat(defaultChatUri)`. - Enumerate: `_enumerateProviderSessions` groups `listConversations()` into sessions via the default-chat URI convention. Gated per harness by `IAgent.orchestratorOwnsSession` (Codex, Claude, Copilot all opt in). Storage-preserving: session URIs and the derived `sdkSessionId == session raw id` (I3) are unchanged, agents read/write the same SDK stores, and providerData / PEER_CHATS_METADATA_KEY / protocol types are untouched. The legacy createSession/disposeSession/listSessions remain as the delegated fallback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: drop orchestratorOwnsSession opt-in; chat surface is the single path Address review feedback: the agent should not declare an orchestration policy, and the interface should not carry an optional flag that splits behavior. The opt-in was transitional scaffolding for a per-agent rollout; all harnesses have migrated, so remove it and make the orchestrator drive the chat surface unconditionally. - Remove `IAgent.orchestratorOwnsSession`; make `listConversations` required. - `AgentService` always provisions (non-fork/import) / disposes / enumerates through the chat surface; no per-agent branch. - Drop the flag from Claude/Copilot/Codex. - Make both test mocks first-class chat-surface agents (provisionSession bridge, default-chat disposeChat, listConversations) so their existing createSession/ disposeSession assertions still hold via the bridge. - Update the routing test to assert session create/dispose now also flow through the chat surface; refresh the architecture doc. Storage-preserving; no protocol/data change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: trim verbose comments on the T2/T4 session-ownership code Shorten the JSDoc/inline comments added for the session-ownership relocation to 1-2 sentences per the coding guidelines; drop obvious per-field comments. No behavior change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: drop redundant session-typed methods from IAgent (Category C) Remove `listSessions` and `getSessionMessages` from the IAgent contract - they are superseded by `listConversations` and `chats.getMessages`. Reroute the one remaining internal caller (the restore metadata catalog fallback) to `_enumerateProviderSessions` (which uses `listConversations`). The harnesses keep those methods privately as the implementation their chat/conversation bridges delegate to. `createSession`/`disposeSession` stay on IAgent as the session-lifecycle provisioning primitives the chat-surface bridge delegates to; `createSession` is also still used directly for fork/import, whose session id is minted server-side (sessions.fork) and so cannot fit the orchestrator-allocates-URI seam - left as a documented follow-up. No behavior change; storage-preserving. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: rename IAgent.getSessionMetadata to getConversationMetadata Align the single-item metadata lookup with the chat-addressed conversation surface: the method is now keyed by a chat URI and returns IAgentConversationMetadata, mirroring listConversations. All five implementers (Copilot, Claude, Codex, and both test mocks) derive the session from the chat URI and return chat-keyed metadata; the orchestrator maps the default-chat URI back to a session when hydrating restore metadata. Also reframe the fork/import createSession path in MULTI_CHAT_ARCHITECTURE.md from a deferred follow-up into a permanent, by-design exception (the fork id is minted server-side by the SDK, so the orchestrator cannot pre-allocate the URI). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: clarify IAgentConversationMetadata._meta is session-generic by design Document why the field keeps the SessionMeta alias rather than a conversation-specific type: _meta is the protocol's open property bag on SessionState / SessionSummary, carried through verbatim. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: clarify Claude disposeSession takes the agent's own SDK session URI Document that the session parameter is the provider's own SDK session (the SDK's terminology), NOT the AH-level Session grouping - that grouping lives in the orchestrator and the agent only ever deals in chats. The URI backs the default chat (invariant I3), so chats.disposeChat routes here when a default chat is disposed; peer chats go to _disposeChat. Teardown disposes that SDK session plus the peer-chat backings the agent parents under it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: document the AH-session vs SDK-session terminology convention Add a 'session is overloaded' convention table to the Mental Model section: in the protocol/orchestrator 'session' means the AH grouping; inside an agent harness it means the provider's own SDK session (Codex: thread); at the IAgent seam the session URI is a shared identity (AH-minted, SDK-session-id raw id per I3). Explains why we do not rename the provider-internal 'session' symbols. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: make IAgent enumeration session-keyed (orchestrator owns session->chat) Revert the chat-keyed enumeration surface (listConversations / getConversationMetadata) back to session-keyed listSessions / getSessionMetadata on IAgent. Chat-keyed enumeration forced every harness to derive default-chat URIs via buildDefaultChatUri for cold (SDK-discovered) sessions it never created in-process - re-deriving the session<->default-chat encoding that belongs to the orchestrator/protocol. Now each agent returns its own SDK-session identity (AgentSession.uri: provider scheme + SDK id, no protocol-chat knowledge) and the orchestrator owns the session->chat mapping. Drops the orchestrator's _conversationToSessionMetadata bridge (the enumeration/restore round-trip) and deletes the now-unused IAgentConversationMetadata type. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: stop agents synthesizing default-chat URIs at runtime Agents no longer call buildDefaultChatUri. Outbound events, default-vs-peer comparisons, and session-or-chat normalizers now reuse the chat URI the agent was already given - read back from the session entry's stored defaultChatKey (new getter on AgentSessionEntry) or the live session's stored chat channel, or tested with isDefaultChatUri - instead of re-deriving it from the session URI. The one irreducible conversion (a session URI first born inside the agent: a freshly forked SDK-assigned id, or a cold-restore/create seed) is centralized in a single node-layer helper, defaultChatUriForSession, in agentPeerChats.ts. This is creation-time only; no runtime routing/event path derives chat URIs anymore. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agents: reuse orchestrator default-chat URI on the provision path The provision (create) path already hands the agent the orchestrator-allocated default-chat URI via createChat(defaultChatUri, { provisionSession }). Claude and Codex decoded it to a session and then re-derived the identical URI inside createSession. Thread the supplied chat URI straight through (createSession's new optional defaultChat argument) so the agent seeds its entry with the URI it was handed instead of re-deriving the session-to-default-chat mapping itself. Copilot has no synchronous create seed (it stores a provisional session and seeds the default-chat key at materialize/resume), so it has no provision round-trip to thread; its derivations are the restart-lazy category. The remaining defaultChatUriForSession callers are the restart-lazy paths (cold resume, peer-send provisional default, fork/restore materialize) where the orchestrator supplies no chat URI in-call; documented as the single sanctioned, irreducible conversion. Behavior is unchanged (the mapping is deterministic); two Claude tests that deep-equal the emitted URI object are aligned with the file's toString-based convention since keying now populates the URI's cache. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: flatten provider chat bindings Make Agent Host own chat membership and pass contextual data only for individual operations. Providers route exact chats to their SDK conversations without deriving default or peer roles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: make chat lifecycle exact and retry-safe Post-merge repairs and review follow-ups for the AH-owned multi-chat architecture, keeping providers on exact chat-to-SDK bindings: - Make `IAgentChats.releaseChat` mandatory so AgentService has one exact-chat release path with no optional legacy fallback; Claude, Copilot, Codex, and the test agents implement it explicitly. - Copilot chat disposal now propagates SDK deletion failures (preserving routing/state for retry) but tolerates an already-deleted session via an O(1) `getSessionMetadata` recheck, keeping a partially-completed multi-chat teardown retry-safe. - Claude: gate materialization on post-await cancellation, abort every live session's controller on dispose, and restore session-addressed resume without inferring chat membership from the URI. - Rename `IAgentCreateChatOptions.provisionSession` to `newSession` to state intent (this createChat creates the owning session). Verified typecheck, transpile, AgentService/Claude/Copilot/Codex unit suites, valid-layers, and hygiene. * agentHost: restore subagent transcripts via the chat-surface getMessages Copilot's `chats.getMessages` routes to `_getChatMessages`, which lacked the subagent-session-URI branch that only lived in the now-orphaned `getSessionMessages`. On the persisted replay/restore path the orchestrator loads a subagent's turns through the chat surface, so reopening a session rebuilt an empty subagent transcript — failing the "reopening a session keeps sub-agent messages out of the parent transcript (replay path)" E2E test on all platforms. Extract a shared `_getSubagentMessages` helper and route subagent URIs through it from both `_getChatMessages` and `getSessionMessages` (matching Claude, which already shares one path). Also address PR review feedback: - `AgentService._releaseSession` releases every catalog chat even if one rejects, then propagates the first error (idle eviction has already dropped the session state, so a skipped leaf would stay resident indefinitely). - `CopilotAgentSession` stores the host-supplied `IAgentChatContext.resource` as its persistence scope instead of re-deriving it from the mutable chat channel via `isDefaultChatUri`, so an explicitly chosen resource survives a later `bindChatChannel`. - MULTI_CHAT_ARCHITECTURE.md: correct the flat `IClaudeChatBinding` shape (`{ sdkSessionId, model? }`, no retained session/storageUri). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: orchestrator owns session provisioning; agents only create chats Removes the `newSession` seam so an agent no longer distinguishes "a chat for a new session" from "a chat for an existing session". Session provisioning now always goes through the agent's dedicated `createSession` + `chats.bindSessionChat` (the same path fork/import already used), and `chats.createChat` has exactly one meaning: add an additional chat to an already-provisioned session. Contract: - Delete `IAgentProvisionSession`, `IAgentCreateChatOptions.newSession`, `IAgentProvisionResult`, and `IAgentCreateChatResult.provision`. - Add `IAgentCreateChatOptions.inheritedContext` ({ workingDirectory, config }): the orchestrator supplies the owning session's resolved context when creating an additional chat, so the agent never reads it back from the parent session. Orchestrator: - `_createProviderSession` always provisions via `createSession` + `bindSessionChat`; delete `_provisionSessionViaDefaultChat`. - `_buildInheritedChatContext` resolves the AH-owned worktree/folder + session config values and passes them to `chats.createChat`/`fork`. Agents (Claude, Copilot, Codex): - Drop the `if (options.newSession)` branch and the `_provisionChat` method; the chat surface handles additional chats only. - Claude/Copilot consume `inheritedContext` for the additional-chat working directory (and Claude for its permission mode) instead of resolving the parent session; remove the now-dead `_createSession(target)` plumbing where the provision path was its only caller. Tests/docs: - Rewrite the AgentService routing test to assert provisioning via createSession + bindSessionChat. - Update MULTI_CHAT_ARCHITECTURE.md §2/§7 to the new seam. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: enable multi-chat for Codex (base for I3-removal branch) Adds Codex multi-chat support (parity with Claude/Copilot): the `multipleChats: { fork: true }` capability, `chats.createChat`/`chats.fork` minting a fresh backing Codex thread per chat, `materializeChat` restore, and a providerData codec. This is committed as the base of the dedicated I3-removal branch (it is intentionally not on the PR branch). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: add orchestrator-owned session registry (I3 removal stage 1) Introduce AgentSessionRegistry, a durable, orchestrator-owned index of the sessions that exist, keyed by session URI and persisted as a JSON blob in a reserved session database with serialized read-modify-write. Wire it into AgentService: register on every createSession success and on restoreSession, unregister on true delete (disposeSession). Add a Stage 1 validation surface (getRegisteredSessions) plus component and parity unit tests. This is additive and does NOT yet drive enumeration; listSessions still uses the provider-derived path. It is the foundation for switching enumeration off invariant I3 in stage 2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: enumerate sessions from the registry, not providers (I3 removal stage 2) Switch AgentService.listSessions to iterate the orchestrator-owned session registry instead of unioning each provider's listSessions(). Per-session metadata still comes from the agent's direct getSessionMetadata lookup (I3 keeps the default chat's SDK id == session id, so it resolves), then flows through the existing DB and state-manager overlays unchanged. This decouples AH enumeration from the agents' SDK stores: peer-chat backings and subagent sessions never enter the registry (so they cannot leak as top-level entries), and a provider that transiently drops a session from its own snapshot no longer evicts it. Idle provisional sessions are suppressed explicitly via a new state-manager predicate (isIdleProvisionalSession), preserving #321269 now that the registry — not the provider snapshot — is the session source. A one-time, marker-gated backfill seeds the registry from the legacy provider enumeration so hosts created before the registry keep their on-disk sessions. I3 is unchanged; agents are untouched. Adds backfill and transient-drop tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: clarify Codex is already I3-decoupled (I3 removal stage 3a) Codex's default chat does not actively satisfy I3: a fresh session's raw id is an AH-minted provisional UUID while its backing thread id is app-server-assigned, with the real mapping persisted in the per-session metadata overlay. The residual sessionId == threadId uses (_readSession's ?? sessionId fallback and listSessions' thread->URI mapping) are legacy-compat shims for pre-existing sessions whose persisted identity is the thread id; they cannot be removed without a data migration (disallowed), so Codex is treated as already I3-satisfied. Comment/doc-only: clarifies the two shim sites and adds a per-agent nuance note to the I3 invariant in MULTI_CHAT_ARCHITECTURE.md. No behavior change. The active I3 removal targets are Claude and Copilot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: collapse fresh-session provisioning into chats.createSessionChat (I3 removal stage 4, step 1) Add an optional chat-surface entry, chats.createSessionChat, that provisions a session AND binds its session-backed (default) chat in one call — the replacement for the IAgent.createSession + bindSessionChat provisioning pair. The agent reuses the session id as its SDK id (id-reuse kept; no storage change, no I7 for the default chat). The orchestrator mints the session URI, derives the default-chat URI, and calls createSessionChat; agents that don't implement it fall back to the create-then-bind pair. Claude implements it via its existing { kind: 'chat' } provisioning path (also used by truncate), so routing state is identical to create-then-bind. Only fresh sessions collapse: fork and import mint a fresh SDK-assigned session id inside the agent, so the orchestrator can't know the default-chat URI up front and keeps them on the create-then-bind pair. bindSessionChat is now documented as the restore-time counterpart. Additive and always-green: Copilot/Codex still use createSession. Validated typecheck, layers, eslint, hygiene; Claude units 206, AgentService 140, Claude E2E replay 8. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: implement chats.createSessionChat in Copilot and Codex (I3 removal stage 4, step 2) Both agents now provision a fresh session and bind its session-backed (default) chat through the collapsed chats.createSessionChat entry, delegating to their existing _createSession and then binding the default chat (id-reuse; no storage change, no I7 for the default chat). The orchestrator already prefers this path for fresh sessions across all providers; fork/import still use createSession. Validated typecheck, layers, eslint, hygiene; Copilot 347, Codex 47, AgentService 140 units; E2E replay Copilot 15 / Codex 6 / Claude 8. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: enable Codex multi-chat capability Advertise Codex multiple-chat and fork support now that the exact chat binding, model-provider forwarding, and registry-owned enumeration paths are complete. Keep provider-owned side chats disabled for Codex. Add replay-only parity gating for Codex model-backed peer/fork tests. Host-only capability checks and conformance catalog/lifecycle coverage remain enabled; recording mode still runs the gated tests once the documented live Codex recording defect is fixed. No capture files are fabricated or hand-edited. Validated typecheck, layers, ESLint, Agent Host unit suites, and Claude/Copilot/Codex strict replay. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: allow recording gated multi-chat E2E tests Keep Codex model-backed peer/fork tests skipped in strict replay while permitting both focused recording modes to execute them and generate fixtures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden session registry and chat lifecycle Make registry load/write mutations durable and retryable, require successful provider enumeration before marking backfill complete, and unregister before irreversible deletion. Dispose every peer and always run provider-level session finalization before surfacing the first error. Harden Codex workspace-less peer/fork managed-directory ownership across create, release, restore, and disposal; refresh an empty model catalog before validating restored provider-qualified models. Remove unsupported multi-chat capability from ScriptedMockAgent and add regression coverage for every reported failure/retry path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: remove Claude default-chat URI inference Use exact chat state routing and retain only the legacy bare-session compatibility path.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: make chat backings session-neutral Give every provider an exact default-chat backing, keep Agent Host authoritative for membership and lifecycle, and isolate provider enumeration to legacy discovery.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: dispose legacy Claude sessions Retain exact default-chat disposal while falling back to an unbound same-ID SDK conversation for direct legacy provider callers.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: route peer session events to owners Normalize session-scoped progress from exact chat resources, keep Codex peer lifecycle off backing session URIs, and resolve peer configuration through the owning AH session.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: restore Codex peer chat history Resume cold Codex peer threads before reading their turns and honor the persisted replacement thread ID. Share concurrent resume work with the first send and suppress idle usage notifications emitted during restore.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: update AgentService worktree deletion stub Use the current prepare/remove worktree deletion contract so durable registry retry coverage reaches the expected cleanup path.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: fork the exact Copilot source chat Pass the orchestrator-owned default chat channel through session forks so Copilot resolves independent SDK backings. Preserve refork support when imported protocol turn IDs already match provider event IDs.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: clarify btw command input Document that selecting the slash command consumes the command token, so the remaining input must contain only the side question.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore persisted subagent chats Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Store orchestrator state separately Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Attach restored peer rejection eagerly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Cancel session cleanup before revival Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Enforce Agent Host routing channels Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use plural session working directories Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Apply provider feedback consistently Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify provider chat backing terminology Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Stop inferring chat role from resource Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify provider chat resolution Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Require exact source chat for forks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Let providers observe session config Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore subagent transcripts lazily Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Complete chat-only provider ownership Route provider provisioning, restore, lifecycle, configuration, and active-client behavior through exact chat-addressed seams. Preserve additive legacy default-chat migration across Claude, Copilot, and Codex and remove obsolete session compatibility paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix chat test field initialization Avoid directly reading the overridden chat surface from subclass field initializers so define-class-fields compilation remains safe. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Keep session chat roles in Agent Host Move legacy backing selection and session-versus-peer materialization filtering into Agent Host. Providers now recover or materialize exact opaque chat backings without retaining session/peer classifications. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Make provider chat creation uniform Remove provider-visible chat role classification and collapse runtime initialization and additional chat creation into one createChat operation. Document and test the registry backfill's idempotent, coalesced migration behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Flatten provider chat creation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove session ownership from agent chats Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address active clients by chat Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Make agent provider seams chat-only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Organize agent provider contract Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Group legacy chat recovery APIs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Document agent capability optionality Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Separate agent provider model Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix cold peer-chat fork to read source chat's own persistence resource Cold peer-chat fork previously read the shared configurationResource overlay instead of the source chat's own persistence resource, so inherited model/agent/permissionMode came from the wrong scope for any non-default source chat. _chatConfigScopes now records both the configurationResource and the exact resource (IChatScopeBinding) for each chat, and _bindInheritedConversation reads the source overlay by the source's own resource. Also adds a backing-model fallback for a source that was created but never materialized. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add regression tests for cold peer-chat fork scope inheritance Covers two scenarios for the claudeAgent.ts fix (commit aabdead86d7): - a peer chat materialized before a cold restart forks with its own model/agent/permissionMode/workingDirectories, not the session-wide decoy overlay - a peer chat never materialized before a cold restart still recovers its model via the _chatBackings fallback Also adds a per-resource-aware ISessionDataService test double, since the shared sessionTestHelpers.ts fake ignores the resource argument and returns one flat database for all resources, which would otherwise mask the session-vs-peer overlay bug. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Complete Agent Host chat ownership migration Make session registry migration durable, preserve exact chat backings across provider restore and lifecycle paths, and harden deletion and rollback behavior. Rename the architecture spec and add regression coverage across providers, migration, concurrency, and protocol restore. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore Agent Host checkpoint lifecycle * Fix Agent Host CI test portability --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 150119bd · 2026-08-12
- 11.3ETVagentHost: scope changesets to chat working folders (#337263) * agentHost: scope changesets to chats Publish independent changeset catalogues for each chat and route changes, Git state, repository operations, and review state through the owning chat workspace while preserving session-wide checkpoints, summaries, and mutation safety. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden chat changeset ownership Refresh chat and aggregate Git state concurrently, prevent session Git fallback for chats, evict removed-chat Git state, and preserve the legacy session catalogue fallback when chat catalogues are unavailable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: scope focused changes to active chat Read focused changes, changesets, operations, review state, and status pills from the owning chat without falling back to aggregate session state. Preserve session-wide catalogues for lists, lifecycle reporting, telemetry, and draft-session repository preparation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: move selectable changesets to chats Make each chat the sole catalogue owner from draft creation onward while sessions retain only aggregate change summaries. Route chat-rooted subscriptions and operations through the containing session without duplicating selectable state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: restore session changes alongside chat changes Publish cumulative session changes separately from chat-owned changesets, scope picker visibility and ordering to the active chat, and keep last-turn changes accurate across peer chat databases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: clarify changeset catalogue ownership Document the final split between session-wide and chat-owned selectable changesets. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: fix changeset test fixtures Align session test doubles and catalogue expectations with the restored session-owned Session Changes entry.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: update changeset catalogue snapshots Record the expected chat changeset catalogue notification in provider AHP traffic after restoring session-owned changesets.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: scope changesets to working folders Share Branch Changes across chats that use the same folder while retaining checkpoint-based active-chat changes. Route Git operations, blob reads, reviews, summaries, and monitoring through the owning folder and preserve the Sessions changes UI behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden folder-scoped changesets Restore non-Git chat changes, folder-owned operation refreshes, stable summaries and catalogues, and multi-root review-ref lifecycle behavior. Keep changes pills and session workflow operations aligned with the active chat scope. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden changeset recomputation Keep coalesced full recomputes from inheriting incremental turn state, and distinguish non-Git scopes from transient Git failures so incomplete worktree summaries are not persisted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: restore chat changes across host versions Resolve restored peer state before computing chat changes and preserve compatibility with legacy session-owned changeset catalogues. Avoid duplicate operation refreshes and remove the obsolete Branch computation path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: restore session changes across chats Keep Session Changes session-owned and project it into every chat while preserving chat-scoped repository and turn changesets. Remove the obsolete host-side Chat Changes production path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Merge origin/main into sessions chat changeset ownership Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: address changeset review and CI failures Remove the unused session-level changeset publication and obsolete Chat Changes identity so every chat consumes the provider-projected Session Changes catalogue. Harden the affected cross-platform and asynchronous CI tests by using platform-native paths and waiting for the observable completion conditions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: update fixtures for chat-owned changes Component fixtures still mocked the removed session-level changes and changesets. Provide main-chat changes to session list fixtures and implement getChatChanges on agent feedback service mocks so the fixtures render again. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · a8c1541d · 2026-09-23
- 10.7ETVagentHost: centralize session and chat catalog metadata (#332410) * agentHost: centralize session list metadata Add a backward-compatible sessions_v2 catalog, legacy-first synchronization receipts, reconciliation, shadow validation, central fallback reads, and durable chat metadata while retaining open-only content in per-session databases.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: migrate sessions directly to v2 Make sessions_v2 an independent current registry, import directly from current, legacy, and provider sources, mirror runtime identities for downgrade compatibility, and reconcile cross-version changes with durable exclusions and versioned markers.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: extract session catalog helpers Move catalog source resolution and downgrade-compatible peer chat persistence out of AgentService into focused helpers without changing migration or runtime behavior.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: simplify session catalog persistence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: remove live compatibility test harness Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: make catalog payload rebuildable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: centralize session chat membership Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: address catalog review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: bridge session catalog migration collision Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: migrate catalog after first listing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: preserve titles during catalog migration Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: bound catalog summaries Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: address catalog persistence feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: reuse keyed catalog sequencer Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden central catalog synchronization Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: persist unloaded session flags centrally Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden peer chat catalog lifecycle Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: preserve peer backing during recovery Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden catalog reconciliation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: avoid claiming unopened legacy sessions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: preserve catalog fallback metadata Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: fence catalog sync during deletion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: avoid title metadata reads on restore Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * build: raise class fields checker heap limit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: stabilize passive metadata restart test Ensure the test performs an actual read-state transition and waits for the corresponding fresh summary notification before restarting. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: avoid redundant peer metadata writes Only rewrite chat-local compatibility metadata for added or changed peers on normal mutations, while retaining full repair for legacy imports and stale mirrors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: preserve pre-release session database schemas Recreate the released turn-delegation table alongside the catalog snapshot so databases produced by the earlier catalog-only v10 migration converge after updating. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: avoid claiming untitled legacy sessions Keep unadopted legacy sessions out of Agent Host title generation so list-only migration cannot create local session storage and prematurely transfer provider ownership. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: coalesce background catalog writes Keep one active synchronization and one merged trailing projection per session so summary bursts do not build an unbounded SQLite write backlog. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: fix catalog ESLint warnings Use type-safe property access in the payload decoder and the database sequencing test so full-repository ESLint passes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: bound catalog reconciliation work Publish passive metadata without awaiting full catalog synchronization, batch discovery timestamp and dirty-marker updates, and rotate persisted bounded verification samples instead of rescanning every catalog row on each startup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: bulk insert central chat catalogs Batch parameterized chat inserts within the existing revision-checked transaction. Cover bounded SQLite statement counts and atomic rollback after a later batch fails. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: keep legacy runtime discovery central-only Avoid creating local session storage for adoptable legacy chats discovered after migration is enabled. Directory creation makes the legacy provider hide sessions before explicit adoption. Preserve existing compatibility synchronization for locally stored sessions and non-legacy discovery. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: skip catalog sync for transient summary changes Compare summary status deltas against the notifier's previous snapshot and only queue catalog persistence when persisted fields change. Activity-only and transient status updates avoid database work while read/archive changes and explicit field clears remain synchronized. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: drain catalog writes before shutdown Stop reconciliation scheduling and drain accepted dispatches and catalog synchronization before shutting down providers and closing the central database. This preserves read/archive updates already published to clients across an immediate host restart without blocking normal passive notifications on catalog work. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: finish Copilot tool results before idle Wait for asynchronous tool completions before normal SDK idle clears the active turn. Preserve immediate abort handling and original tool-result attribution when a replacement turn starts while file-edit persistence is pending. Add deterministic delayed-completion, abort, and replacement-turn regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: resolve provisional sessions before subscribing input pills Do not subscribe to untitled UI identities when Back returns to the new-chat input. Wait for the existing provisional-session service to publish a backend and follow its mapping changes, releasing obsolete subscriptions. Cover Back, provisioning, replacement, retirement, and return to a started session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: defer automatic catalog repair until startup settles Gate automatic reconciliation scheduling and discovery-driven verification until host startup and the first listing complete, then start deferred periodic maintenance. Preserve explicit refreshes and immediate durable mutations. Cover zero pre-startup maintenance I/O and replacement-turn completion independent of an aborted edit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: settle startup before title reconciliation test Establish host startup and the first listing before waiting for background catalog repair in the persisted-title test, matching the startup-gated maintenance contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: skip local storage for unresolvable catalog sources Check provider availability before taking the per-session exclusive open, so periodic reconciliation of sessions whose provider is not registered no longer opens their local database on every pass. Retry semantics are unchanged. Also un-nest the startup-gating test, which was defined inside another test and therefore never ran. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: add session catalog rollback switch Add chat.agentSessions.sessionCatalog.enabled, defaulting to true and frozen at its first read so the store backing the session list cannot change while the host runs. When disabled the host skips catalog import and background repair and lists from provider metadata and per-session storage, while registry identity and compatibility writes continue unchanged. Clear the verification marker while disabled so the next enabled start re-verifies every cached payload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: report comparable listing metrics in both catalog modes Emit the catalog mode, the catalog-served and provider-fallback row counts, and the resolve phase duration on every listing, so a run with the session catalog enabled can be compared directly against one with it disabled. Catalog-served rows cost no provider or session-database read; fallback rows cost both. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: release a settled session listing instead of pinning it `listSessions()` attaches a trailing refresh to an in-flight listing so that concurrent callers share the hand-off instead of each starting their own recomputation, and `clear()` keeps the entry reachable while that hand-off is attached. Nothing released the entry once the hand-off itself settled, so it stayed in `_inFlightListSessions` as a permanently settled result: every later listing was served from it and the host never recomputed again. A later epoch bump does not free it either -- `listSessions()` takes the `if (!inFlight.trailing)` = false path and returns the settled trailing verbatim -- so the only escape is a host restart. Release the entry once the trailing hand-off settles, which is the point after which no caller can join it. `clear()` and `_startSessionListComputation` are untouched, so the starvation fix from #333646 still holds, and `startTrailing()` replaces the map entry with its own computation, so the identity check leaves that fresh entry alone. This regression was introduced by this pull request, in e1bc2e30576 ("agentHost: harden catalog reconciliation"), which added an epoch short-circuit to the trailing hand-off: - inFlight.trailing = inFlight.promise.then(startTrailing, startTrailing); + inFlight.trailing = inFlight.promise.then( + result => inFlight.epoch === epoch ? result : startTrailing(), + startTrailing, + ); Before that change `startTrailing` ran on every settle, and because `_startSessionListComputation` replaces the map entry, the pinned entry was always displaced by a fresh one whose `trailing` is unset -- so `clear()` could always collect it. With the short-circuit an unchanged epoch resolves to `result` and never calls `startTrailing()`, so nothing replaces the entry and it stays pinned forever. The retention in `clear()` came in earlier with 9e596330004 ("[cherry-pick] Avoid Agent Host session listing starvation (#333646)") and is benign on its own, because that commit always replaced the entry. origin/main is therefore NOT affected and needs no separate fix; e1bc2e30576 exists only on this branch. The cached-entry logic is mode-independent by construction -- `listSessions` and `_startSessionListComputation` never consult the session-catalog gate, and `_isSessionCatalogEnabled()` is only read inside `_computeSessions` for data sourcing -- so the fix applies in both catalog modes. The regression test reproduces the defect deterministically with the catalog disabled only, where the provider metadata round-trip gives a reliable point at which to hold a listing open; with the catalog enabled the same sequence races against projection writes that bump the epoch again. Observed in the field as an agent host that stopped recomputing listings entirely: six `listSessions` requests served in ~1ms with no computation at all after the host wedged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: rename the session catalog setting and mark it advanced Move `chat.agentSessions.sessionCatalog.enabled` to `chat.agentHost.sessionCatalog.enabled`. The setting governs how the agent host serves its session list, not the agent sessions UI, so it belongs in the existing `chat.agentHost.*` namespace alongside the other host-level settings. Tag it `advanced` as well as `experimental` so it surfaces under the advanced filter: it is a rollback lever for the catalog read path rather than a tuning option. Register a configuration migration so an existing value carries over instead of silently reverting to the default. The migration clears the old key and writes the new one only when the new key is unset, so a value already set under the new name is not clobbered -- the same shape as the existing `chat.experimental.autoApprovals.enabled` migration. The agent host root key `sessionCatalogEnabled` is unchanged: forwarding is driven by the registration's `agentHost: { key }` through the configuration registry rather than by the workbench setting id, so nothing on the host side needs to move. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: migrate the session catalog setting from application scope `chat.agentHost.sessionCatalog.enabled` is APPLICATION-scoped, so an existing value can live in the application settings file. The migration inspected only the user target, silently dropping such a value and resetting the user to the default. Follows the `unifiedWorkspacePicker` precedent. Also restate the wedge regression test's comment: the trailing refresh pins a settled entry because its success handler observes a matching epoch and returns the settled result rather than starting a replacement computation. That is an epoch-timing bug, not a catalog-mode one, which is why the catalog-enabled variant cannot fail -- projection writes bump the epoch again and heal the map before a test can observe it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: track per-session storage access counts Opening a session database is the dominant cost of any listing that cannot be served from the catalog, and it is the one figure that compares across machines: per-file costs differ by an order of magnitude between platforms (virus scanning, filesystem), so a duration measured on one machine says little about another. Expose cumulative open and stat counts from `SessionDataService` so diagnostics can report them. The member is optional because it is diagnostics only -- an implementation that owns no real files has nothing to report, and requiring it would force every test double to implement it for no benefit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: resolve legacy changeset aggregate when importing sessions The `sessions_v2` importer built each catalog payload from provider metadata, which never carries file-change counts -- those live only in the session's own database. Imported rows were therefore written with no `changes` aggregate, and because they were written clean and verified, reconciliation never revisited them. The host then reported no counts at all for those sessions. The workbench treats an absent `changes` as "keep what you had" (`session.changes ?? cached`) and persists that value per workspace, so a silent omission surfaced as a stale, inflated edit count in the session list that only corrected itself once the session was opened and its diffs were recomputed. Resolve the aggregate during the import, reusing the resolver the reconciliation path already uses; the session database is open at that point, so this costs no extra open. Bump the catalog verification version so profiles migrated by an earlier build re-verify once and pick up the aggregate they are missing. Read the small persisted summary before the diff blobs. The blobs run to hundreds of kilobytes and occasionally megabytes, while the modern aggregate is a few dozen bytes and is returned verbatim when present, so the common already-migrated session no longer loads and parses a blob it does not need. This also removes that cost from every reconciliation pass, including the one the version bump triggers. Finally, report duration and storage-access counts on the import and session-list log lines. The import runs at most once per provider per payload version, so a report that arrives afterwards can never reproduce it; both lines are emitted at info level for the same reason. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 8ec3108c · 2026-09-16
- 5.6ETVConvert workspace-less sessions to workspace sessions (#334250) * agentHost: support setting workspace on existing sessions Allow an agent to attach a workspace-less session to a folder or managed worktree without replacing the session or losing conversation history. Propagate the new project, working directory, continuation, and activity state through Agent Host and Sessions UI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent Host changes for sandy081/agents/workspace-less-to-workspace-conversion * Keep workspace conversion progress continuous Reserve a visible host-authored turn while workspace setup completes, then route that same turn through normal provider admission. Keep project updates catalog-only, durably quarantine disposed provider sessions, atomically persist Copilot workspace metadata, and wire conversion without lazy service lookup.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Show workspace conversion outcome in transcript Use a stable visible continuation request and add synchronized Workspace Set or Workspace Setup Failed notifications to the same turn.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove stale workspace conversion imports Clean up imports left behind while adapting the workspace conversion changes to the current Agent Host composition. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Adapt workspace conversion to chat queue diagnostics Pass operation names through the updated Copilot chat queue API for working-directory mutations and their sequencing tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix workspace conversion tests on Windows Create in-memory customization directories before writing fixtures and derive expected paths from URI.fsPath so assertions follow the host platform.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Avoid concurrent in-memory folder creation Serialize creation of customization fixture directories because the in-memory filesystem's recursive mkdir path is not safe when sibling operations race.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix remaining workspace conversion CI failures Use the real disk provider for native Windows customization paths, prevent late aborted-idle events from cancelling replacement turns, and give the full property initialization checker enough heap for the expanded Agent Host sources.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · a9864c02 · 2026-09-04
- 5.1ETVsessions: single-pane layout as a sibling controller with composed strategies (#324657) * sessions: fix base-controller single-pane leak via Template Method hooks (R1) Move the single-pane branches out of BaseLayoutController into SinglePaneDesktopSessionLayoutController via three protected hooks (_suppressEditorVisibilityDuringRestore, _shouldRevealEditorPartOnApply, _shouldRevealEditorPartForEmptyWorkingSet). The base controller no longer reads isSinglePaneLayoutEnabled. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: segregate docked-editor layout concerns into IDockedEditorLayout (R3) Extract handleDockedEditorPartLayout and isEditorRevealedExplicitly into a focused IDockedEditorLayout interface that IAgentWorkbenchLayoutService extends, keeping the cross-cutting isSinglePaneLayoutEnabled and suppressEditorPartAutoVisibility on the main contract. Fix stale typo comment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: extract side-pane presentation Strategy from workbench (R2/R4) Replace the 26 scattered _dockDetailPanel branches in workbench.ts with an ISidePaneLayoutStrategy (GridSidePaneStrategy + DockedSidePaneStrategy), selected once at initLayout. DockedSidePaneStrategy owns the docked width, the DockedAuxiliaryBarController lifecycle, the reveal-sync, and a DockedEditorSizeMemento for the docked size bookkeeping (R4). Workbench implements ISidePaneLayoutHost and delegates geometry, grid-descriptor, visibility-mutator, and reveal-sync work to the strategy. Behaviour is unchanged in both layouts; the only remaining _dockDetailPanel reference is the strategy selection point. Rewrites workbench.test.ts to drive the real strategy through a host harness. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: replace side-pane Strategy with Workbench subclass (R5) Convert the composition-based ISidePaneLayoutStrategy into inheritance, matching the layout-controller Template Method pattern. The base Workbench now carries the classic (grid) layout as protected _-prefixed hooks; SinglePaneWorkbench overrides them for the docked detail-panel layout and owns the docked width, DockedAuxiliaryBarController, reveal-sync, and DockedEditorSizeMemento. A createSessionsWorkbench factory picks the subclass from the setting at construction; web.main.ts and sessions.main.ts use it. Removes sidePaneLayoutStrategy.ts and the ISidePaneLayoutHost callback interface. No behaviour change in either layout. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: single-pane editor part owns the auxiliary bar (R6) Make editor + auxiliary bar a single unit in the single-pane (new) layout by having the editor part create and own the auxiliary bar instead of the workbench/pane-composite service: - New SinglePaneMainEditorPart extends MainEditorPart; lazily creates the SinglePaneAuxiliaryBarPart via a getter and owns the DockedAuxiliaryBarController (created in create(), calling setContentRightInset directly). - EditorParts.createMainEditorPart() returns SinglePaneMainEditorPart when the shared shouldUseSinglePaneLayout(config) predicate is true. - AgenticPaneCompositePartService retrieves the same aux bar instance from the editor part in single-pane; classic/mobile create it as before. - SinglePaneWorkbench drops DockedAuxiliaryBarController ownership; keeps the docked width (exposed via getDockedAuxiliaryBarWidth/setDockedAuxiliaryBarWidth on IDockedEditorLayout) and reveal-sync, delegating layout to the editor part. - workbenchFactory, EditorParts, and the pane-composite service all select via the single shouldUseSinglePaneLayout predicate so the workbench, editor part, and aux bar are always chosen together (fixes a phone-viewport + setting-on mismatch that would pair SinglePaneWorkbench with a plain MainEditorPart). Classic (default) and mobile layouts are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: make isSinglePaneLayoutEnabled class-based, not a config read Address review feedback: since the workbench subclass is selected at construction (Workbench vs SinglePaneWorkbench), isSinglePaneLayoutEnabled is now a class-level constant — false in the base, overridden to true in SinglePaneWorkbench — instead of reading DOCK_DETAIL_PANEL_SETTING at runtime. Removes the _configurationServiceForLayout field. This also aligns the flag with the phone-aware workbench selection, so it no longer reports single-pane on a phone viewport where the classic workbench is used. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: single-pane editor-group header menus, docked aux bar, and header styling - Make the full-width Changes header a group-level editor concept: the editor part configures header menu ids via IEditorGroupViewOptions.headerMenuIds and the editor opts in via IEditorPane.getHeaderActions(); EditorGroupView renders the menus (no concrete menu points leak into core). - Docked aux bar: top border connecting to the sash, and hide editor/aux when their sash collapses them. - Changes pill and file-diff open reveal the editor explicitly (revealEditorPartExplicitly), and close the Files tab when a real file opens. - Header styling: re-scope diff-stats/picker CSS via marker classes, restore inter-action spacing, and shrink the right toolbar buttons to 24px. - Fix setHeaderContent wiping freshly-rendered content on re-render; tie per-group header listeners to group removal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: reparent single-pane layout to a sibling controller with composed strategies Make `SinglePaneLayoutController` a sibling of the classic desktop `LayoutController` (both extend `BaseLayoutController`) instead of extending it, so the desktop controller can be deprecated/deleted without affecting single-pane. Its behaviour is composed from focused strategy objects under `contrib/layout/browser/singlePane/`: - Detail (aux bar) ownership split in two — `SinglePaneDetailVisibilityStrategy` owns per-session shown/hidden memory (D1-D4); `SinglePaneDetailPanelStrategy` owns container selection (Changes/Files), maximize, browser-hide, and the nothing-to-show hide. Removed the overlapping `EmptyAuxCleanup` (D10) strategy and desktop's redundant saved-container machinery. - `SinglePaneManagedTabsStrategy` + `SinglePaneEditorAreaCollapseStrategy` share a `SinglePaneDockedTabsCoordinator`; plus `SinglePaneResponsiveSidebarStrategy` (Toggle Details), `SinglePaneNewSessionRulesStrategy` (R1), and `SinglePaneQuickChatEditorHideStrategy`. - Strategies coordinate through the controller via `ISinglePaneLayoutContext`. - Fresh per-session storage keys (`sessions.singlePane.*`) so single-pane never shares state with the classic controller. Fix a chain of new-session-submit / Detail-only bugs (all verified in-app): - New-session submit no longer reveals the docked editor or hides the just-opened detail. `onDidReplaceSession` fires before the controller's later-registered listener, so submit is detected intrinsically from the reactive transition (`!previousIsCreated && isCreated`); D3c leaves the detail as-is when a session has no saved state; the empty-editor-group hide is skipped during a layout restore. - Detail-only sessions no longer flicker the editor open on switch or reload: the editor-part grid view (which hosts the docked aux bar) no longer maps its visibility to `setEditorHidden`, the width-based reveal-sync bails while editor-part auto-visibility is suppressed, and the persisted editor width uses the node's real visibility so a reload restores the collapsed node width. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix component fixture screenshot CI Add the missing workbench layout service mock needed by the changes view fixtures and update blocks-ci screenshot hashes to the expected CI output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: fix cramped Changes actions bar in the single-pane editor header The `ChangesActionsBar` marker (`.changes-actions-bar`) only carried a height rule in the single-pane editor-group header; the classic `.session-changes-editor-header-right` normalization does not reach that header, so the primary split-button and the trailing secondary icon actions rendered cramped together with no spacing or button chrome. Add the container flex/gap layout and the secondary icon-button chrome (padding, corner radius, secondary background/border + hover) keyed off `.changes-actions-bar`, using design tokens, so it applies in the single-pane editor-group header while staying idempotent for the classic internal changes-editor header (whose element also carries `.session-changes-editor-header-right` with the same values). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: match classic Changes actions bar chrome in single-pane editor header The single-pane editor-group header renders the Changes actions bar (`.changes-actions-bar`) inside `.editor-group-header-secondary`, where the high-specificity `editorgroupview.css` rules stretched the primary split-button but gave the trailing secondary icon actions (Mark as Done, Run Code Review) no inter-button gap and no button chrome, so they rendered flat and cramped against the dropdown chevron. Add, at matching specificity in `editorgroupview.css`, the container flex/gap and the secondary icon-button chrome (padding, corner radius, secondary background/border + hover) mirroring the classic `.chat-editing-session-actions` actions bar. Drop the equivalent low-specificity rules from `sessionChangesEditor.css`, which lost the cascade to the editor-group-header selectors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: fix single-pane Changes actions bar and move its styles out of core In the single-pane editor-group header the Changes actions bar renders as a toolbar action item inside a `.monaco-action-bar`, where the generic rule `.monaco-action-bar .action-item .codicon { width: 16px; height: 16px }` clamped every codicon — including the button elements themselves (which carry the `codicon` class), squashing the secondary icon buttons and detaching the split-button chevron. - Un-clamp the codicons and lay out the bar (primary split-button grows, trailing secondary icons stay natural size) scoped to `.monaco-action-bar .action-item.changes-actions-bar`, so the classic internal changes-editor header and the aux-bar Changes view are left untouched. - Move all `.changes-actions-bar`-specific rules OUT of core `editorgroupview.css` into the contributing component's `sessionChangesEditor.css`; core keeps only the generic header/toolbar layout. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: draw the single-pane header divider under the editor header/tab bar Move the single-pane detail-panel separator from the auxiliary bar's top border to a bottom divider on the editor header (spanning the editor content and docked detail), so the line runs the full header width. When the active editor has no header toolbars (e.g. Files), the divider is drawn under the tab bar instead so a separator is always present below the header row. The docked auxiliary bar is absolutely positioned over the right of the editor part with a solid background, so it would overlay the divider. Rather than fight it with z-index, start the aux bar one divider-thickness below the header/tab bar (new `DockedAuxiliaryBarController.DIVIDER` offset applied to the aux top/height and the resize sash), so its background sits just beneath the line. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: update docked aux geometry tests for the header-divider offset The docked auxiliary bar now starts one divider-thickness below the header/tab bar (`DockedAuxiliaryBarController.DIVIDER`), so its top and height shift by 1px (top 34->35, height 566->565). Update the two workbench geometry snapshot tests to the new expected values. Fixes the CI unit-test failures on the PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · e656eb8d · 2026-07-07
- 4.4ETVagentHost: fix chat-folder separation review findings (#337608) * agentHost: fix per-folder changeset review issues Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: fix chat lifecycle review findings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: scope chat UI actions to folders Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: keep create_session descriptions unchanged for quick chats The runtime error already tells the model how to proceed from a quick chat, so the model-facing descriptions stay as they were. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: scope Agent Merge by host folder keys Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: publish working directory keys Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: fork only a scoped chat's folders Forks copied the source chat's effective folders, including inherited ones, which failed for providers without per-chat folders (Codex, Copilot E2E). A fork now copies only the folders the source chat is scoped to, and only when the provider supports per-chat folders. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: address #337608 review feedback - Agent Merge changes are advertised only on the chat that owns a shared folder's Agent Merge, using the same owning-chat resolution as the host controller. - A folder key the host published is authoritative: GitHub and Agent Merge state no longer fall back to another folder that differs only in case. - Input banner feedback is read and marked under the session and sent to the chat showing the pull request. - A chat row sized while offscreen reserves its folder row once rendered. - Terminals match by the backend they run on: the cwd fallback no longer adopts another Agent Host's terminal, and local task or manual terminals of a local Agent Host session stay visible. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 97182611 · 2026-09-24
- 4.2ETVsessions: run Agent Merge per chat folder and present multi-folder sessions (#337594) * agentHost: run Agent Merge per folder Each folder a chat works in can run its own Agent Merge. State moves to per-folder session config (`agentMerge.folders`, host-owned `agentMerge.controller.folders`), with the earlier session-level entries read as the session folder's state and cleared on its first write. The session-wide elevated configuration lives in `agentMerge.injectedConfiguration`: applied while any folder runs and restored when the last one stops. The controller keeps one runtime per folder, bound to that folder's pull request and checkout. Repair turns and notices go to the folder's owning chat (the chat that turned Agent Merge on, else the first chat working in that folder) and wait only for that chat to be idle; a turn ending in an error also completes the repair. Tools, Create PR with Agent Merge, and Mark Ready with Agent Merge resolve the invoking chat's or changeset's folder. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: follow the active chat's folder for Agent Merge Agent Merge actions, context keys and the chat input's pull request pill now read and write the Agent Merge settings of the folder the active chat works in. The provider writes a peer chat's folder into agentMerge.folders, recording the chat that turned it on, and keeps the legacy agentMerge key for the session folder until the host migrates it. Session-wide surfaces keep using the session folder. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: harden per-folder Agent Merge Addresses review findings on the per-folder Agent Merge implementation: - Lifecycle updates re-read the folder and write only host-owned state, so an evaluation never reverts settings the user changed meanwhile. - Clients write only the folder they change, by working directory; the host merges it into the other folders and derives the key, so stale client maps cannot undo host changes and keys match across platforms. - The owning chat must be a chat of the session; notices use it; a folder no chat works in waits instead of repairing from the session folder's checkout. - Repair turns are tracked per chat: only that chat may use the repair's tool authorization, and removing it ends the turn. - Turning a folder off clears its lifecycle state, and Create PR with Agent Merge binds afresh, so a new pull request is not judged by an old target. - The elevated configuration of earlier versions carries over when migrating. - Unrelated config changes no longer re-sync monitoring. - A peer chat whose folders are still loading cannot change the session folder. - Observable ref-counting and caches are per session. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: run Agent Merge tools for the invoking chat Agent Merge tools passed the session URI, so a peer chat's repair turn could not use its tools, a turn in another chat could use the default chat's repair authorization, and the enable tool always changed the session folder. They now pass the invoking chat. A folder that no chat of the session works in any more now turns Agent Merge off with a reason, instead of waiting and keeping the session resident, and the host drops client entries for folders that are not the session's. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: keep other folders' Agent Merge settings during client writes A client write of one folder is applied locally before the host merges it, so until then the local config held only that folder: other folders looked off, and a toggle there could turn them off. The provider now reads every folder it has seen, as the host never removes a folder's settings. Config replacement no longer sends the client's copy of the Agent Merge settings, which could undo a host self-disable or a demoted merge choice; the host carries them over when a replacement omits them. Notices waiting for a chat that is removed are posted to the default chat. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: restore per-folder Git state and present multi-folder sessions - The host persists the latest Git state of each chat's working-directory scope, so chats in other folders show their branch state right after a restore instead of the session folder's. - Multi-folder sessions: the session hover summarizes every workspace, its changes and pull requests, and a chat's hover shows its own folder, branch changes and pull requests. The sessions list shows chat rows accordingly. - The Changes view hides Session Changes in multi-folder sessions, and the input banners follow the active chat's folder and its Agent Merge settings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · a41ff3b2 · 2026-09-24
- 4.0ETVsessions: refine the single-pane detail-panel layout (#324348) * sessions: single-pane detail-panel layout for the Agents window Add an experimental `sessions.layout.singlePaneDetailPanel` setting (default off) that docks the detail panel (auxiliary bar) inside the editor part, so a single editor tab bar spans the editor content and the docked panel. Introduces a custom Changes (multi-diff) editor, Files/Browser tabs, and a "+" add-tab menu, with the Changes view and diff-stats split into standard vs single-pane subclasses chosen at startup. The redesign uses a mode-based architecture: all single-pane parts, editors, serializers, actions and views are registered/gated behind the setting via `IAgentWorkbenchLayoutService.isSinglePaneLayoutEnabled` (the single source of truth), so the standard Agents-window layout is unchanged when the setting is off. Core editor support: `EditorPart.setContentRightInset` (concrete class, not the public `IEditorPart` interface) insets only right-edge groups so the tab bar stays full-width; a generic `MenuId.EditorTabsBarAddTab` renders a core-owned "+" dropdown at the end of the tab strip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: address CCR feedback on single-pane layout - empty-file editor: register a touch Gesture target and handle Tap (iOS) in addition to click, and set `touch-action: manipulation` to avoid the tap delay. - docked detail panel border: use `var(--vscode-strokeThickness)` instead of a hardcoded 1px. - drop the internal `[Option A]` design-discussion marker from comments across workbench.ts / style.css / sessionConfig.ts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: fix use-before-init in DetailPanelController The _activeEditorObs / _auxBarVisibleObs field initializers referenced the constructor-injected _editorService / _layoutService, which run before the parameter properties are assigned (TS2729, caught by tsc in CI but not by the tsgo typechecker). Move their initialization into the constructor body. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: update blocks-ci screenshot hashes Refresh the committed blocks-ci-screenshots.md to the current CI-rendered image hashes (CodeEditor / InlineChatZoneWidget fixtures). These are bare editor-widget fixtures not affected by this PR's editor-tab changes; the drift is from the screenshot service re-render. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: make SessionChangesService resolvable without the workbench layout service SessionChangesService is a DI singleton also instantiated in component fixtures / unit tests, which do not register IAgentWorkbenchLayoutService. Read the single-pane setting via IConfigurationService (available everywhere) instead, so resolving ISessionChangesService no longer fails with 'depends on layoutService which is NOT registered'. The layout service remains the single source of truth for contributions that run only in the real Agents window. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: re-sync blocks-ci screenshot hashes Update the committed hashes to the current CI render (the 6 CodeEditor / InlineChatZoneWidget fixtures shifted with the merged upstream editor changes). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: fix single-pane layout bugs from layout audit Grid/sizing: persist the logical editor width (excluding the docked panel) so the Sessions Part no longer shrinks by the panel width on every reload; clamp the stored docked width to its minimum and yield to the editor's minimum in narrow windows; keep the editor grid leaf visible when only the docked aux bar toggles. Editor content inset: recompute on group maximize/restore so a maximized non-right group is not rendered under the docked panel, and re-layout the docked panel after the un-maximize resize. Controllers: DetailPanelController shows Changes while the editor is maximized (agreeing with the D5 rule) and classifies editor types (file/empty-file -> Files, Changes -> Changes, Browser -> hidden, other -> preserve); the LayoutController no longer auto-reveals the Changes view on editor open in single-pane, so existing sessions keep the 'never auto-open' rule. Docs: fix stale method references in LAYOUT.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: single-pane detail panel refinements and controller merge Merge the single-pane detail/tab controllers into the layout controller, add a dedicated Toggle Details command, refine R1 (transition-triggered editor hide), default a created session to the Changes editor with the detail closed, reveal the docked editor part for created sessions, and remove the docked reveal-sync suppression mechanism. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 5cfa7158 · 2026-07-05
- 3.3ETVsessions: single-pane detail-panel layout for the Agents window (#324257) * sessions: single-pane detail-panel layout for the Agents window Add an experimental `sessions.layout.singlePaneDetailPanel` setting (default off) that docks the detail panel (auxiliary bar) inside the editor part, so a single editor tab bar spans the editor content and the docked panel. Introduces a custom Changes (multi-diff) editor, Files/Browser tabs, and a "+" add-tab menu, with the Changes view and diff-stats split into standard vs single-pane subclasses chosen at startup. The redesign uses a mode-based architecture: all single-pane parts, editors, serializers, actions and views are registered/gated behind the setting via `IAgentWorkbenchLayoutService.isSinglePaneLayoutEnabled` (the single source of truth), so the standard Agents-window layout is unchanged when the setting is off. Core editor support: `EditorPart.setContentRightInset` (concrete class, not the public `IEditorPart` interface) insets only right-edge groups so the tab bar stays full-width; a generic `MenuId.EditorTabsBarAddTab` renders a core-owned "+" dropdown at the end of the tab strip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: address CCR feedback on single-pane layout - empty-file editor: register a touch Gesture target and handle Tap (iOS) in addition to click, and set `touch-action: manipulation` to avoid the tap delay. - docked detail panel border: use `var(--vscode-strokeThickness)` instead of a hardcoded 1px. - drop the internal `[Option A]` design-discussion marker from comments across workbench.ts / style.css / sessionConfig.ts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: fix use-before-init in DetailPanelController The _activeEditorObs / _auxBarVisibleObs field initializers referenced the constructor-injected _editorService / _layoutService, which run before the parameter properties are assigned (TS2729, caught by tsc in CI but not by the tsgo typechecker). Move their initialization into the constructor body. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: update blocks-ci screenshot hashes Refresh the committed blocks-ci-screenshots.md to the current CI-rendered image hashes (CodeEditor / InlineChatZoneWidget fixtures). These are bare editor-widget fixtures not affected by this PR's editor-tab changes; the drift is from the screenshot service re-render. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: make SessionChangesService resolvable without the workbench layout service SessionChangesService is a DI singleton also instantiated in component fixtures / unit tests, which do not register IAgentWorkbenchLayoutService. Read the single-pane setting via IConfigurationService (available everywhere) instead, so resolving ISessionChangesService no longer fails with 'depends on layoutService which is NOT registered'. The layout service remains the single source of truth for contributions that run only in the real Agents window. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: re-sync blocks-ci screenshot hashes Update the committed hashes to the current CI render (the 6 CodeEditor / InlineChatZoneWidget fixtures shifted with the merged upstream editor changes). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 7317e60f · 2026-07-04
- 3.1ETVsessions: Add grid layout for chats (#330848) * Grid layout for chats in a session Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Show tab strip when lone chat title diverges from session title Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Active chat shares the session background (no per-group dimming) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Persist and restore chat grid layout across reloads Persist each session's chat group partition (group assignments, grid structure + sizes, active group) to workspace storage keyed by sessionId. On reopen, deserialize the grid and route chats — including ones whose catalog loads asynchronously — back to their saved groups, collapsing empty groups only once restore settles. Driven entirely off observables. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix chat tab drag-to-split broken by chat-reference drag payload Dragging a chat tab to place chats side by side did nothing for agent-host sessions: the group-move payload and the chat-reference payload both used the global single-slot LocalSelectionTransfer, so fillChatReferenceDragData clobbered the DraggedChatIdentifier the grid drop target checks — its dragenter saw no chat drag and never showed the split zones. Carry the group-move payload {sessionId, resource} on the drag event's dataTransfer (SessionsDataTransfers.CHAT) instead, decoupled from the singleton which the chat-reference keeps to itself. The dataTransfer types are readable during dragover (to gate the overlay) and its value on drop. Verified end-to-end in a launched Agents window: dragging a chat tab now shows the split overlay and drops into a new chat group (1 -> 2 groups). Adds a regression test and documents the LocalSelectionTransfer single-slot pitfall. * Cap read-only banner to the centered band in single-group layout The read-only chat banner spanned the full leaf width instead of aligning with the tab strip. When the banner moved from SessionView's centered content container into the full-width ChatGroupView bar, the tab strip got a single-group centering rule but the banner did not, so on wide windows the banner ran edge-to-edge while the tabs stayed centered. Add the matching .single-group rule so the banner caps to the centered content band and centers (overriding only its horizontal margins, preserving the negative top offset). Multi-group keeps the banner full-leaf like the tab strip. Verified live: at a 1304-1578px leaf the banner now caps to 950px, centers (equal 177px margins), and pixel-aligns with the tab strip (same x, same width). * sessions: improve chat grid interactions Keep focused chat groups synchronized with session state, make side opening and restoration deterministic, and add accessible keyboard navigation and regression coverage.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: route child chats to adjacent groups Apply parent-aware placement to every chat activation path, preserve focus when removing groups, and dispose removed group resources promptly.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: preserve chat grid placement Keep manual child-chat assignments authoritative, retain the initiating group across asynchronous chat creation, and align logical group order with left and top splits.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: restore new session composer Keep the standalone composer for the no-session state, avoid restoring persisted grids into drafts, and update side-chat and visibility test harnesses for the grid dependencies.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · ed96883e · 2026-08-14