Files
vscode/test/scenario/src
Sandeep SomavarapuandCopilot 44f3c89801 sessions: Add experimental chat-scoped layout modes (#340047)
* sessions: Add shared chat layout ownership contract

Freeze the experimental presentation setting for each window and invalidate queued owner snapshots across focus and phone-presentation transitions. Expose exact confirmed chat deletion identities and provider-neutral graduation mapping for layout and terminal consumers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add captureSidePaneComposition/restoreSidePaneComposition API to Workbench

Adds a narrow public API on IAgentWorkbenchLayoutService and Workbench
for capturing and restoring a per-chat Editor/Details side pane
composition (ISidePaneState) without forcing visibility during
capture and without a controller needing direct access to private
cache/storage. restoreSidePaneComposition reuses the existing
setEditorHidden/_setAuxiliaryBarHidden primitives (editor-before-
auxiliaryBar ordering, suppressEditorPartAutoVisibility wrapping,
reveal-event gating matching toggleSidePane), so shared grid geometry,
maximize/transient state, and all legacy callers are unaffected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Scope terminals and tasks to chat ownership

Capture immutable terminal origins before asynchronous work, persist backend-qualified ownership, scope terminal/task reuse and cleanup to exact chat pairs, and preserve presentation, focus, reconnect, and runtime protections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* terminal: Initialize BasePty ownership properties

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: chat-owned desktop layout composition (R5/R8/R13)

Adds per-chat (owner-key) Editor/Details side-pane composition tracking
to the desktop layout controller, on top of the chat-layout-ownership
contract and captureSidePaneComposition/restoreSidePaneComposition APIs:

- chatLayoutOwnerKeys.ts: computes/compares the stable owner key for a
  session's active chat (main chat maps to the session resource
  unchanged; peer chat maps to the chat resource), including
  replacement-safe remapping.
- desktop/desktopOwnerCompositionStore.ts: per-owner last-open
  editor/auxiliaryBar composition store (ResourceMap-backed, storage
  persisted, versioned by workspace/machine).
- desktopExistingSessionStrategy.ts: resolves/applies/captures the
  active owner's composition instead of always the single shared
  profile; restores composition on same-session peer-chat switches;
  reconciles on owner changes, including a phone-suspension entry or
  exit (owner key flips to/from undefined). While chat-owned layout is
  in effect, captures are written only to the active owner, leaving the
  shared legacy "Existing" profile untouched so it still reflects the
  last composition seen outside chat ownership (used by the disabled
  baseline and while phone-suspended).
- baseSessionLayoutController.ts: chatLayoutActive(reader) reads the
  live, phone-aware ChatLayoutContext presentation instead of the
  frozen startup flag, so phone transitions reactively suspend/resume
  chat ownership; owner-key resolution threads an optional reader.
- desktopLayoutController.ts / desktopLayoutStrategy.ts: wires
  chatLayoutActive(reader)/ownerKeyFor(reader)/compositionStore through
  IDesktopLayoutContext; compositionStore field made protected for test
  subclassing.
- desktopDockedTabsCoordinator.ts: scopes tab-reconciliation intents by
  owner key instead of only by session.

New test/browser/chatLayoutOwnership.test.ts covers: R1 disabled
baseline (same-session chat switch never touches the shared
composition), R5 same-session A/B/A distinct compositions, all four
Editor/Details compositions round-tripping per owner, R8 confirmed
peer-chat deletion clearing only that owner's composition, R8 draft
promotion carrying a peer chat's composition to its new owner key, and
R13 a phone transition suspending chat-owned composition and resuming
the focused chat's own composition on exit.

150/150 layout tests passing (144 existing + 6 new), native browser
typecheck clean, valid-layers-check clean, eslint clean on all changed
files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Harden chat-owned layout: legacy seeding, stale-owner guard, same-key remap no-op

- [R-seed] DesktopLayoutController seeds its chat-layout key from the
  disabled-mode key once (never removing the legacy snapshot), so
  enabling chat layout for the first time inherits existing per-session
  state instead of regressing to defaults.
- [R4] BaseLayoutController captures the chat-layout owner snapshot
  before a working-set apply is queued, and checks it after every
  await inside the apply, so a superseded apply can no longer publish
  editor-part reveal/hide once the owner has moved on while it was in
  flight (the queued apply itself still always runs to completion).
- Same-key remap in BaseLayoutController._remapOwnerKeyState and
  DesktopOwnerCompositionStore.remap is now a documented no-op,
  avoiding a self-delete hazard when old and new owner keys coincide.
- Documents the flat synthetic chat-layout-owner-key scheme's
  rationale for reusing the base controller's existing session-keyed
  maps instead of introducing a nested resource-pair map.

Tests: [R-seed] legacy-key inheritance/non-removal, [R4] stale-owner
race (verified to genuinely fail with the guard disabled), new
DesktopOwnerCompositionStore suite covering remap/forget including the
same-key no-op.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: suspend chat-owned layout ownership during phone presentation (R13)

Correct a bug where a desktop window crossing into a phone-sized
presentation silently collapsed per-chat layout ownership onto the
plain session resource instead of suspending it: capture/restore and
reconcile-intent lookups keyed on that collapsed resource, which is
also the main chat's own owner key, so a peer chat's working set,
side-pane composition, or panel state could read or overwrite the
main chat's stored state the moment the window narrowed, and panel
restore/intent-scoping autoruns could apply a stale default on the
suspend transition itself.

- _ownerKeyForChat/_ownerKeyFor (BaseLayoutController) and
  IDesktopLayoutContext.ownerKeyFor now return URI | undefined:
  undefined means the per-chat owner exists but must be treated as
  unavailable while suspended; callers that WRITE/CAPTURE/DELETE skip
  on undefined, callers that RESTORE/APPLY (panel visibility/view
  autoruns, the working-set derive, composition reapply, docked-tab
  intent scoping) explicitly check suspension so they freeze the
  dormant owner's state rather than falling back to a shared default.
- DesktopExistingSessionStrategy's ownerChanged no longer treats
  entering suspension (a real key becoming undefined) as an owner
  change, so suspend-entry leaves the on-screen composition
  undisturbed; resuming (undefined becoming a real key) still
  reapplies the then-focused chat's own composition.
- The working-set derive's suspend branch freezes the last resolved
  owner by reference, so neither the suspend transition nor a
  session/chat switch during suspension captures or restores a
  working set; resuming recomputes the key for whichever chat is then
  focused.

New tests (chatLayoutOwnership.test.ts, baseSessionLayoutController.test.ts)
prove composition, working-set, and panel-visibility state survive a
phone suspend/resume cycle undisturbed and that resuming applies the
then-focused chat's own state, not the one focused when suspension
began.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix phone-suspension state conversion and strip added comments

Follow-up to b056819bf02 (not amended, per coordinator instruction),
addressing coordinator rejection points:

- Genuine bug: entering phone presentation no longer collapses the
  chat-layout owner key to the plain session resource or re-resolves
  Existing-strategy composition against the session default. Phone
  suspension now freezes the owner key and composition snapshot in
  place instead of converting/restoring state, so dormant per-chat
  data is never overwritten and no legacy profile is applied while
  phone presentation is active.
- Removed all comments added in the prior (rejected) commit across
  production and test files; none remain.
- Added coverage for same-session A/B/A distinct editor working sets
  plus panel view, and for a peer chat not inheriting the legacy
  session-keyed working set on its first visit.

Validation this commit: full compile clean; targeted layout suite
162/162 passing (0 failing); native browser typecheck
(node build/npm/electronTypes.ts && node node_modules/@typescript/native/bin/tsc
--project build/checker/tsconfig.browser.json --pretty false) clean;
eslint clean on touched files; npm run valid-layers-check clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix cross-owner side-pane toggle-reopen staleness and strip added comments

Fixes a genuine bug exposed by driving the real toggleSidePane() API in a
test: closing the side pane on chat A, visiting chat B, then reopening the
side pane on A could restore B's stale global pre-hide cache instead of A's
own composition, because the native toggle's reopen fallback
(_sidePaneStateBeforeHide) is a single workbench-wide cache with no owner
awareness. Adds a per-owner, transient (non-persisted)
_preHideComposition map to DesktopExistingSessionStrategy, captured on
onWillToggleSidePane and used on onDidToggleSidePane to correct a reopen via
the existing restoreSidePaneComposition() API when it diverges from the
owner's own remembered pre-hide state. Wires remap/forget through
desktopLayoutController's owner-key lifecycle hooks alongside the existing
composition store.

Adds missing captureSidePaneComposition()/restoreSidePaneComposition() stubs
to the test harness's mock layout service (previously entirely absent).

Removes residual added code comments left over from prior commits in this
task (mandatory copyright headers retained).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix multi-visible focused-owner restore and add resume-same-owner-key regression test

- desktopExistingSessionStrategy.ts: the multi-visible branch of the
  side-pane visibility autorun used _reveal() (show-only) instead of
  _apply() (show+hide) whenever an owner key was present, so focusing
  a second owner while both sessions stayed visible never hid what the
  previously focused owner had shown.
- chatLayoutOwnership.test.ts: add dedicated multi-visible-session
  tests for composition, editor working set, and panel
  visibility/view round-trips, plus a resume test proving that
  returning from a phone-layout suspension re-applies the focused
  owner's own composition even when the owner key is unchanged across
  the suspension.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: fix Draft strategy multi-visible capture suppression; prove fresh-restart composition restore

- Remove DesktopDraftSessionStrategy's unconditional multipleSessionsVisibleObs
  block in _captureOwnerCompositionIfApplicable(), which silently dropped
  composition capture for a focused draft owner whenever any other session was
  simultaneously visible. The existing _activeOwnerKey() gate (chatLayoutActive
  + isCreated + isQuickChat) already correctly no-ops in disabled/no-owner
  cases, so the redundant multi-visible block only ever suppressed valid
  enabled-mode, multi-visible captures, mirroring the already-fixed
  DesktopExistingSessionStrategy pattern.
- Add a regression test proving a focused draft owner's composition changes
  are captured while another session is simultaneously visible.
- Add a fresh-controller-restart test proving a newly constructed
  DesktopLayoutController restores a session's side-pane composition, editor
  working set, and panel view together from storage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: prove preHideComposition lifecycle, Quick Chat precedence, and strip a leftover divider comment

- Add 3 regression-proved tests covering the normal-toggle
  last-open composition cache lifecycle: deletion forgets it,
  draft promotion remaps it to the new owner key, and phone
  suspension neither writes a stale entry nor loses the one
  captured before suspension.
- Add a Quick Chat test proving a saved working set keeps its
  recorded shared side-pane profile instead of being forced
  through the reload editorless-hide default (the Quick Chat
  analog of the existing New Session entry-default precedence
  tests; Quick Chat is not part of the new per-owner composition
  catalog and continues to use the pre-existing shared profile
  store, confirmed by code inspection across all owning files).
- Remove a leftover '--- Owner composition ---' divider comment
  found during a cumulative git diff b095329b3e1..HEAD comment
  sweep; no other added comments beyond copyright headers remain.

All 184 tests across the 7 layout test files pass. ESLint, the
native browser typecheck, and the layers check are clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: persist normal-toggle last-open side pane composition across reload

The side pane's normal-toggle last-open composition (captured on toggle
close so a later toggle open reopens the same editor/auxiliary-bar state)
was tracked only in an in-memory map on the owning strategy. A fresh
controller (e.g. after a workbench reload) lost that cache and fell back
to the owner's current/default composition instead of its own last-open
one, violating R5/R7 (no geometry, but reopen preference must persist).

Route pre-hide composition reads/writes through a second persisted slot
on DesktopOwnerCompositionStore (storage key
sessions.chatLayout.sidePanePreHideComposition), alongside the existing
current-composition slot, and remove the strategy's private in-memory
map in favor of the store.

Added a regression test proving a freshly constructed controller
restores owner A's own last-open composition after a real toggle close,
not owner B's, and that B's own last-open composition also survives the
same recreation unaffected.

Validation:
- npm run transpile-client
- scripts/test.sh --run src/vs/sessions/contrib/layout/test/browser/{baseSessionLayoutController,chatLayoutOwnership,desktopLayoutController,desktopOwnerCompositionStore,desktopStrategies,mobileSessionLayoutController,sessions.layout.contribution}.test.ts
  -> 179 passing
- npx eslint on touched files -> clean
- node build/npm/electronTypes.ts && node node_modules/@typescript/native/bin/tsc --project build/checker/tsconfig.browser.json --pretty false -> clean
- npm run valid-layers-check -> clean

This is a bounded follow-up slice (R5 reload-persistence), not a claim
of full task completion; other outstanding items reported separately
remain to be addressed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Quick Chat own-composition precedence; genuine independent-storage reload proofs

- DesktopDraftSessionStrategy now includes Quick Chat sessions in its
  owner-composition gate (previously excluded entirely), restoring a
  Quick Chat's own recorded composition on re-entry and on reload
  before falling back to the shared visibility profile default.
- Fixed a feedback-loop bug where applying an owner's own composition
  did not suppress the shared-profile capture listener, causing an
  incidental overwrite of the shared profile.
- Strengthened the R5 normal-toggle reload test and the R-seed peer
  working-set/panel-view restore test to reconstruct storage through a
  brand-new, independently seeded TestStorageService instance (keyed
  off raw serialized strings) instead of reusing the same live storage
  object across controller instances.
- Added a regression test proving Quick Chat re-entry restores its own
  recorded composition rather than the shared profile default.

All changes regression-proved via targeted sabotage/restore cycles.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: persist per-chat bottomVisible (panel visibility) across reload

- Add panelVisible to ISessionLayoutEntry and a new _isPanelVisibilityPersisted
  getter (base: false, Desktop: chatLayoutEnabled) so the existing per-session
  _panelVisibilityBySession runtime map is also written to and restored from
  the typed per-chat storage key when chat layout is enabled, independent of
  panelView restoration.
- Add matching delete/remap handling for _panelVisibilityBySession alongside
  the existing per-session maps (session delete/archive, draft promotion,
  owner key remap, peer chat forget).
- Update the R-seed fresh-controller test to assert the peer's persisted
  bottomVisible is now genuinely restored (and its panel view immediately
  re-opened) rather than asserting the prior unpersisted gap.
- Add an [R7] test proving a fresh controller restores a saved peer chat's
  own bottomVisible independently of the main chat and of its panel view,
  using an independently reconstructed storage service.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Version owner composition storage and prove hidden-bottom view retention

- DesktopOwnerCompositionStore now persists both the current and
  preHide/last-open composition slots in an explicit versioned
  {version, entries} schema instead of a bare array, and logs via
  ILogService (matching the repository's catch (error) {
  logService.error(error) } pattern) before discarding storage on a
  malformed or unsupported-version payload, rather than silently
  removing it.
- Add round-trip, unsupported-version, and pre-versioned-bare-array
  tests for the new schema.
- Update the two pre-existing tests that seeded the old bare-array
  format directly so they match the new schema.
- Add an [R7] test proving a fresh controller keeps a saved peer's
  hidden bottom hidden (without opening its remembered view) across
  reconstruction, and restores that exact remembered view once the
  bottom is shown.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: revert Quick Chat durable owner-composition routing

Quick Chat sessions must never receive a durable owner-composition
key; restore the original exclusion in _activeOwnerKey() and drop the
now-dead stored-composition branches in _registerQuickChatVisibility()
that only existed to serve that routing. The _changingVisibility guard
added alongside that change is unrelated to Quick Chat scope and is
kept, since it still guards the legitimate Draft-session composition
capture/apply pipeline.

Remove the regression test that asserted the now-reverted behaviour.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Version the chat layout state storage schema and prove peer editor resources survive restart

Adds a versioned {version, entries} schema, a runtime type guard, and
ILogService-based corruption diagnostics to the experimental-only
chat layout storage key (DESKTOP_CHAT_LAYOUT_STATE_KEY), leaving the
disabled/legacy raw-array serialization untouched. panelVisible is
now validated as a boolean rather than accepted as any non-undefined
value.

Also strengthens the test harness's saveWorkingSet/applyWorkingSet
fakes to round-trip the active group's real editor resources and
active tab (previously an opaque id/name spy only), and extends the
fresh-controller peer restoration test to assert on those genuine
editor resources and active tab, not just working-set object equality.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Prove and fix working-set/panel-map lifetime through deletion and promotion

Add R8 tests proving a confirmed chat deletion forgets a peer's
captured editor working set and panel visibility/view (not only its
composition), and that a draft promotion carries those same maps to
the replacement session's owner key while forgetting the stale draft
key. The promotion test exposed a real gap: the switch-away listener
that eagerly saves the outgoing chat's working set recomputes its
owner key from the live session object, so it could resave the
working set under a draft's now-remapped key after onDidReplaceSession
already moved its state to the committed session's key, leaking a
stale, permanently unreachable owner-key entry. Track replaced session
resources and skip the eager save for them.

Also correct a stale assertion message in the desktop reload test that
claimed panel visibility is runtime-only, not itself persisted - true
before persisted panelVisible existed, but no longer accurate since
that reload scenario specifically exercises the legacy-migrated
layoutState entry, which has no panelVisible field of its own.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix remaining Quick Chat durable-catalog leak and composition-store partial-apply corruption

- desktopExistingSessionStrategy: exclude Quick Chat sessions from
  _activeOwnerKey() so toggling the side pane while a Quick Chat is
  active no longer writes/reads its composition into the durable
  per-owner composition/preHide catalog (a second, independent
  instance of the Quick Chat exclusion bug, unrelated to the one
  already fixed in the Draft strategy).
- desktopOwnerCompositionStore: validate every persisted entry into a
  staging map before publishing to the live owner map, so a malformed
  entry can no longer leave earlier valid entries half-applied in
  memory while the backing storage record is removed. Entry shape is
  now checked strictly (tuple length, URI string, exact booleans)
  before any destructuring. Error messages for both the composition
  store and the base layout controller's session layout state no
  longer dump the full persisted payload, reporting only the storage
  key and version instead.
- Add regression tests for both fixes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Validate layout entries atomically and fix same-resource promotion blacklist leak

- isValidSessionLayoutEntry now validates editorWorkingSet, viewState, and
  sessionResource URI scheme; _parseVersionedSessionLayoutEntries rejects the
  whole record (logged once, index-only message) on any single malformed
  entry instead of silently filtering it out, matching the already-accepted
  desktopOwnerCompositionStore staged-validation precedent.
- _replacedSessionResources no longer blacklists a session resource
  indefinitely: the switch-away guard now consumes the entry with delete()
  instead of has(), and _onSessionReplaced only adds an entry for
  cross-resource promotions (a same-resource promotion never triggers the
  switch-away race the blacklist exists to guard against), so a committed
  session's next outgoing working-set save is no longer silently suppressed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Consume replacement blacklist marker outside the Untitled short-circuit

The switch-away listener's save-suppression check combined the
Untitled/isRestoringSessionLayout gates with the one-shot
_replacedSessionResources.delete() call using &&, so delete() only ran
when both gates were false. A cross-resource promotion while the draft
is Untitled (the common case) left its blacklist marker unconsumed
on the draft's own switch-away, so it could persist indefinitely and
incorrectly suppress a later, unrelated session's outgoing save if
that session ever reused the same resource.

Hoist the delete() into an unconditionally evaluated variable so the
marker is always consumed on the very next switch-away for that
resource, regardless of the Untitled/isRestoringSessionLayout gates.
No feature-gating is needed: _replacedSessionResources and this
switch-away guard are not scoped to chat-layout-enabled mode already,
so the fix applies uniformly to both the disabled/legacy and enabled
paths, matching the existing same-resource regression test.

Add a regression test proving a cross-resource promotion's blacklist
marker is consumed even when the draft is Untitled, so a later session
reusing that resource still gets its own outgoing working-set save.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add real working-set handle lifetime and delayed-hydration proofs

Extend the test harness to track real deleteWorkingSet calls and to
make workspace-folder readiness mutable/firable instead of a frozen
closure, then use that to add two genuine production-path proofs:

- a confirmed peer-chat deletion now asserts, via the real
  IEditorGroupsService.deleteWorkingSet call list, that only the
  deleted peer's own working-set handle is deleted, leaving the main
  chat's working-set handle untouched and still applicable when
  switching back to it.
- the workspace-gated working-set apply, previously only proven to
  hold back while a session's workspace folder is unregistered, is
  now also proven to fire correctly for the still-current session's
  own previously-saved working set once that folder later arrives,
  rather than staying stuck or applying a stale/empty one.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix main-chat deletion from destroying shared working-set handle; prove delayed peer catalog hydration

- onDidDeleteChat no longer treats deletion of a session's own main-chat
  entity as session-level cleanup; it now early-returns, leaving the
  shared/legacy working-set handle intact. Genuine session removal/archive
  continues to delete it via the existing onDidChangeSessions path.
- Add a test proving the fix (handle survives main-chat-only deletion,
  still deleted on session removal) and a test proving promotion that
  collapses a peer key onto an already-used owner key never calls the
  destructive deleteWorkingSet API.
- Add a test proving a persisted peer-chat owner record (working set,
  panel view, panel visibility, composition) survives controller startup
  before the peer chat is observed in the session's chat catalog, and is
  correctly applied once the peer is added and focused.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Implement reference-counted working-set handle lifetime; restore R8 main-chat deletion clearing

Replace the unconditional destructive deleteWorkingSet call in
_deleteWorkingSet with reference-counted release semantics: a working-set
handle id carried forward from the frozen legacy (disabled-mode) storage
key, or still tracked under another live owner key, is never destroyed;
only a genuinely unreferenced handle is. Apply the same release logic to
_remapOwnerKeyState's promotion-collision overwrite so an orphaned
pre-existing destination handle is correctly freed instead of leaked.

Revert the previous commit's main-chat deletion no-op exemption in
onDidDeleteChat back to always computing and forgetting the owner key
(matching R8: deletion clears the exact owner's refs, with no main-chat
exemption); this is now safe because the underlying delete is
reference-counted.

Replace the two stale tests from the prior commit with three that prove
the corrected behaviour: a legacy-referenced handle survives an ordinary
outgoing overwrite while its fresh replacement is still freed once
unreferenced; deleting a session's main chat entity now clears its own
tracked working set per R8 while leaving a legacy-referenced handle
untouched; and a promotion collision frees the orphaned pre-existing
destination handle exactly once while never destroying the incoming
handle, with the surviving handle still cleaned up exactly once later.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Collect legacy-referenced working-set ids unconditionally on load

Previously _legacyReferencedWorkingSetIds was only populated inside the
legacy-fallback branch of _loadState(), which is skipped whenever the
versioned chat-layout key already has its own entries and returns
early. On a reload where both the frozen legacy key and the versioned
key reference the same working-set handle, the handle would lose its
legacy-referenced protection and could be destroyed on the next
outgoing overwrite or delete.

_collectLegacyReferencedWorkingSetIds() now performs a read-only scan
of the legacy storage key, independent of which _loadState() branch
subsequently loads or returns, and is invoked unconditionally as the
first step of _loadState().

Also removes the two JSDoc comments previously added to
_legacyReferencedWorkingSetIds and _isWorkingSetStillReferenced.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove extra blank line at EOF in chatLayoutOwnership.test.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document chat-specific layout ownership and persistence contracts

Define focused-chat layout and terminal ownership, startup presentation and phone suspension, legacy compatibility, versioned persistence, and confirmed-delete/remap lifecycles. Preserve shared geometry and transient Quick Chat behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make experimental chat-specific layout window scoped

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove chat-specific layout reload notification

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Implement shared and per-chat layout modes

Freeze the unreleased window setting as disabled, shared, or per-chat until manual reload. Keep editor working sets, selected panel views, and terminal ownership per chat while sharing existing-workspace pane composition and bottom visibility in shared mode, with independent mode persistence.

Capture outgoing ordinary editors on same-session chat switches and prove lifecycle, managed-tab, reload isolation, suspension, and terminal/task ownership paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document shared and per-chat layout modes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Rename chat layout setting to sessions.layout.mode

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify experimental session layout scope setting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Align chat-scoped layout with session behavior

Reuse session visibility defaults and lifecycle transitions with chat owner keys; preserve saved owner state and shared visibility mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Restore original terminals and fix scoped layout restoration

Keep terminal and task behavior unchanged across layout scopes. Preserve pinned editors when queued Details-only collapse becomes stale, and support isolated recorded layout validation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Preserve chat layout state through owner lifecycle changes

Retain collapsed editors per chat, transfer main owner state on promotion, and register persisted peer keys independently of catalog hydration. Cover regressions and both hydration visibility states.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Make workspace hydration pane-state assertions explicit

Verify default managed tabs after restoring an empty editor group with Details visible, with and without Editor content. Preserve the existing empty-group and Details-only rules.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Clarify shared-visibility layout mode names

Rename the unchanged default to session-shared alongside chat-shared and chat. Keep all layout policies and persistence unchanged; update enum descriptions, tests and documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Hide the bottom panel when no chat owns the layout

Preserve saved visibility when the active session clears, and align first-visit documentation with Existing defaults. Add regressions for both chat modes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: Isolate layout schema tests from registry resets

Capture registered configuration before other suites clear the shared registry, following existing Sessions schema-test patterns. Reproduces and fixes Linux Electron and macOS WebKit CI failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-06 15:48:49 +00:00
..
…
…