You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement Commit 5 — Integrate running table and all open paths from the approved remote-agent-session design.
Integrate persisted runtime hydration and local/remote acquisition into IRunningAgentChatTable and every fresh, restore, auto-resume, and non-GUI opening path. Local and remote chats must use the same common IAgentChat surface, all paths must enforce the same persisted-owner decision, and an already-running runtime must never be rehydrated.
Implementation mapping and hierarchy
Implementation commit: Commit 5 — Integrate running table and all open paths.
Approved design source: features commit 0c6578641befad31d5a38003baf6c0f0fe64748a.
all existing AgentSessionEntityFactory.CreateEntityData callers affected by the property-based factory request
Required behavior
Hydrate persisted runtime intent exactly once when a local session is first materialized.
Reuse an existing local or remote running entry without rehydrating it.
Attach/start remote sessions only through the strict authorized remote-session client/proxy path.
Publish a remote running row only after its first authoritative snapshot.
Single-flight concurrent acquisition by session, persisted owner, and ownership generation.
Leave no running row when acquisition is cancelled or fails before publication.
Use the same owner decision and acquisition pipeline for direct open, restore, fresh launch, auto-resume, and non-GUI acquisition.
Dispatch continue-in-background changes to the local owner registry or remote client as appropriate, and complete only after persistence and authoritative state publication.
Preserve ref-counted viewer leases. Releasing a lease is not explicit termination, although final release may trigger the owner’s default graceful-stop rule.
Keep local and remote behavior compatible through IAgentChat.
Relevant product decisions and background
The remote-agent protocol decides which host owns and runs AgentChat. Persisted executor bindings decide where components and tools execute. Effective trust plus MXC decide how a process is confined on its final launch host. These are orthogonal decisions.
Opening a session owned by the current profile starts or reuses the local owning runtime. Opening a session owned by another profile performs an authorized status query and offers:
Connect on owning profile — start there if absent, otherwise attach to the existing runtime.
Resume locally — perform ownership takeover before local acquisition.
The status shown before that choice is Running, Not running, or Unavailable. Unauthorized and missing sessions are both Unavailable and reveal no session metadata. Every opening and restore path applies the same rule.
The owning host constructs the real AgentChat, host services, persistence, tools, and current-session identity. A remote GUI receives an IAgentChat proxy backed by an authoritative snapshot and ordered deltas. It does not construct the owner runtime, execute remote tools locally, compile MXC, or install attachment identity as current-session identity.
ChatClientOverTransport remains the lower-level split-client mechanism; it is not the full-session proxy. No compiled policy, process handle, policy path, or other host-specific runtime state is persisted or sent over machine transport.
continue-in-background is an explicit persisted per-session preference. It defaults to false; a missing legacy value reads as false. Lease disposal releases one viewer. Explicit termination is a separate operation.
API shape convention
APIs carrying multiple independent values use a property-based *Request or *Options record plus an optional CancellationToken.
Semantically required properties are required init; optional properties have explicit defaults.
Requests/options and data values are constructed with named object initializers.
Constructors remain compact value objects or receive a small cohesive set of dependencies.
Protocol DTOs remain property-based records with their existing serializers, kebab-case wire names, strict unknown-member rejection, and fixed codec/concrete-type discriminators. A discriminator is not caller-selectable.
The complete approved design contains exactly 28 request/options types: 22 public and 6 internal. This includes the modified AcquireAgentChatRequest, command, UI, and entity-factory requests and the internal authorization/host/runtime requests; it excludes ProcessExecutionRequest owned by [mxc] - Streaming process executor backed by MXC #1474.
Detailed design
Persisted runtime intent and entity factory
AgentSessionRuntimeIntentData is a serialization-only DTO. Its init properties contain no runtime policy:
Every call site, including repeated persistence, must create CreateAgentSessionEntityDataRequest with a named initializer and call CreateEntityData(request):
JsonSchemas/agent-session.json retains host-profile-entity-id and executor-bindings and adds ownership-generation (integer, minimum zero, default zero), trust-profile-reference, expected-trust-profile-revision (integer, minimum zero), and continue-in-background (boolean, default false). Trust reference and revision are both present or both absent.
HostProfileEntityId is required for every new entity. The factory always writes owner, generation, executor bindings, and background preference. Only the reader accepts a missing owner for the documented legacy migration.
AgentSessionRuntimeContextFactory.Create is the shared hydration seam. It reads owner, generation, trust intent, existing executor bindings, and background preference; reconstructs ExecutorBindings; and returns the process-scoped transport registry. Missing bindings mean local. Malformed bindings or nonlocal bindings without a registry fail closed. It does not resolve GUI routes, fetch a remote runtime, compile MXC, or mutate caller services.
Exact common state contracts
Local and remote chats expose the same atomic state values. These exact property-based forms are required:
Unreported usage metrics are null; reported counts and cost are nonnegative. AgentInformation requires nonblank identity/display strings and a complete non-null AgentDefinition; CurrentModelId is null or nonblank. Publishers and codecs validate complete replacement values before one foreground assignment. UsageChanged and InformationChanged fire only after the atomic assignment. Record equality is intentional.
AgentChat remains sealed and implements IAgentChat; no transport branch is added to it. RemoteAgentChat also implements IAgentChat. Engine-only APIs remain on concrete AgentChat and are not added to the UI contract.
Named remote open contract
Remote open/status/attach uses the existing strict property DTO:
The added properties are ordinary init-only storage. They perform no I/O and do not clone, own, or dispose the transport. Local forbids OwningProfileTransport. Remote modes require the transport, persisted entity data, owner, and generation.
For a not-yet-running local session, AcquireAsync calls AgentSessionRuntimeContextFactory.Create exactly once and immutably merges the result into that session’s AgentServices. Existing running sessions retain their already-composed services.
For remote acquisition, the table creates RemoteAgentSessionClient/RemoteAgentChat through the internal attach path and registers the proxy only after the first authoritative snapshot. Concurrent requests single-flight by session, owner, and generation. Cancellation before publication leaves no row.
TerminateAsync returns false when absent. For a local runtime it disposes the owning runtime; for a remote proxy it sends explicit termination rather than detach.
SetContinueInBackgroundAsync rejects absent and subagent sessions. It dispatches a local owner update to the runtime registry or a remote update to RemoteAgentSessionClient, and completes only after persistence and authoritative publication.
RunningAgentChatLease.AgentChat returns the registered acquired instance. RunningAgentChat and RunningAgentChatWithEntityInfo continue to expose AcquireLeaseAsync; they do not add a borrowed Chat property. Lease disposal is idempotent and releases viewer/reference ownership exactly once.
RunningAgentChatWithEntityInfo metadata is an owner/client-authoritative snapshot. Changes raise the existing property-change path before RunningAgentBrainViewModel.Refresh updates a row.
Session services and current-session identity
AgentServices keeps its existing object-typed layering seams and adds:
Blank owner, negative generation, and an epoch without owner are rejected. The owning host creates one context per runtime. Attachment identity never replaces host identity.
AgentServicesComposition.ComposeSessionServicesAsync remains host-service composition and does not parse persisted executor/trust fields. RunningAgentChatTable applies AgentSessionRuntimeContextFactory.Create afterward through with, preventing GUI/auto-resume divergence and cross-session service leakage.
Unified open and UI helper requests
OpenAgentSessionShortcutHandler.Handle, TryCreateAgentSessionTabForRestoreAsync, TryCreateTabForRestoreAsync, and CreateAgentSessionTabAsync route through one internal persisted-session opening pipeline. ConnectOnOwner constructs remote acquisition; ResumeLocally completes takeover before local acquisition. The handler never parses executor bindings or compiles trust policy.
The inherited Handle and TryCreateTabForRestoreAsync overrides retain their framework signatures. Changed helper APIs use these exact property-based records:
Fresh launch, restore, and auto-resume pass the persisted entity into acquisition. Non-GUI acquisition uses the same table seam. All paths preserve slash-command composition through the common IAgentChat surface and cannot bypass runtime hydration or owner selection.
Ownership compare/exchange and deterministic takeover shutdown, which are implemented by the later takeover commit.
Host-local trust/MXC compilation or component-placement implementation.
Full remote modal/notification/control presentation beyond the common opening and authoritative running-row contracts required here.
Discovering unrelated remote sessions.
Migrating a live AgentChat, compiled policy, process handles, or host runtime state.
Tests
All prior tests remain required. The following committed-design tests are also part of this child where they define Commit 5, its entity-factory boundary, common acquisition surface, open DTO, UI helper requests, or authoritative running metadata.
Direct open, restore, fresh launch, auto-resume, and non-GUI acquisition all pass persisted entity data into AcquireAsync.
Each path applies the same local/connect-on-owner/resume-local decision.
Each path uses named request/options initialization.
Each path acquires the same single-flight runtime for the same session, owner, and generation.
Existing runtime reuse does not invoke hydration again.
Cancellation before ready publication leaves no tab or running row published as ready.
Common slash-command composition is present for both local and remote chats.
Acceptance criteria
Every affected creation/persistence call uses a named CreateAgentSessionEntityDataRequest variable and AgentSessionEntityFactory.CreateEntityData(request).
No superseded positional entity-factory or UI-helper signature remains.
Usage and AgentInformation exactly match the property contracts above.
Remote open and protocol records retain their serializer and fixed-discriminator behavior.
Part of #1483
Summary
Implement Commit 5 — Integrate running table and all open paths from the approved remote-agent-session design.
Integrate persisted runtime hydration and local/remote acquisition into
IRunningAgentChatTableand every fresh, restore, auto-resume, and non-GUI opening path. Local and remote chats must use the same commonIAgentChatsurface, all paths must enforce the same persisted-owner decision, and an already-running runtime must never be rehydrated.Implementation mapping and hierarchy
0c6578641befad31d5a38003baf6c0f0fe64748a.This child is self-contained for Commit 5. It consumes the contracts supplied by #1484-#1487; it does not recreate those implementations.
Scope
Files
Phantom.Workspaces.Services/AcquireAgentChatRequest.csPhantom.Workspaces.Services/IRunningAgentChatTable.csPhantom.Workspaces.Services/RunningAgentChatTable.csPhantom.Workspaces.Services/RunningAgentChatWithEntityInfo.csPhantom.Workspaces.Llm/RunningAgentChat.csPhantom.Workspaces.Llm/RunningAgentChatLease.csPhantom.Workspaces.Llm/AgentServices.csPhantom.Workspaces.Llm/CurrentSessionContext.csPhantom.Workspaces.Services/AgentServicesComposition.csPhantom.Workspaces/ViewModels/OpenAgentSessionShortcutHandler.csCreateAgentSessionTabForRestoreRequestCreateAgentSessionTabRequestComposeSessionAgentViewModelOptionsAgentViewModelOptionsAgentSessionEntityFactory.CreateEntityDatacallers affected by the property-based factory requestRequired behavior
continue-in-backgroundchanges to the local owner registry or remote client as appropriate, and complete only after persistence and authoritative state publication.IAgentChat.Relevant product decisions and background
The remote-agent protocol decides which host owns and runs
AgentChat. Persisted executor bindings decide where components and tools execute. Effective trust plus MXC decide how a process is confined on its final launch host. These are orthogonal decisions.Opening a session owned by the current profile starts or reuses the local owning runtime. Opening a session owned by another profile performs an authorized status query and offers:
The status shown before that choice is Running, Not running, or Unavailable. Unauthorized and missing sessions are both Unavailable and reveal no session metadata. Every opening and restore path applies the same rule.
The owning host constructs the real
AgentChat, host services, persistence, tools, and current-session identity. A remote GUI receives anIAgentChatproxy backed by an authoritative snapshot and ordered deltas. It does not construct the owner runtime, execute remote tools locally, compile MXC, or install attachment identity as current-session identity.ChatClientOverTransportremains the lower-level split-client mechanism; it is not the full-session proxy. No compiled policy, process handle, policy path, or other host-specific runtime state is persisted or sent over machine transport.continue-in-backgroundis an explicit persisted per-session preference. It defaults tofalse; a missing legacy value reads asfalse. Lease disposal releases one viewer. Explicit termination is a separate operation.API shape convention
*Requestor*Optionsrecord plus an optionalCancellationToken.required init; optional properties have explicit defaults.AcquireAgentChatRequest, command, UI, and entity-factory requests and the internal authorization/host/runtime requests; it excludesProcessExecutionRequestowned by [mxc] - Streaming process executor backed by MXC #1474.Detailed design
Persisted runtime intent and entity factory
AgentSessionRuntimeIntentDatais a serialization-only DTO. Its init properties contain no runtime policy:All new or repeated agent-session entity persistence uses this exact property-based request:
Every call site, including repeated persistence, must create
CreateAgentSessionEntityDataRequestwith a named initializer and callCreateEntityData(request):JsonSchemas/agent-session.jsonretainshost-profile-entity-idandexecutor-bindingsand addsownership-generation(integer, minimum zero, default zero),trust-profile-reference,expected-trust-profile-revision(integer, minimum zero), andcontinue-in-background(boolean, default false). Trust reference and revision are both present or both absent.HostProfileEntityIdis required for every new entity. The factory always writes owner, generation, executor bindings, and background preference. Only the reader accepts a missing owner for the documented legacy migration.AgentSessionRuntimeContextFactory.Createis the shared hydration seam. It reads owner, generation, trust intent, existing executor bindings, and background preference; reconstructsExecutorBindings; and returns the process-scoped transport registry. Missing bindings mean local. Malformed bindings or nonlocal bindings without a registry fail closed. It does not resolve GUI routes, fetch a remote runtime, compile MXC, or mutate caller services.Exact common state contracts
Local and remote chats expose the same atomic state values. These exact property-based forms are required:
Unreported usage metrics are null; reported counts and cost are nonnegative.
AgentInformationrequires nonblank identity/display strings and a complete non-nullAgentDefinition;CurrentModelIdis null or nonblank. Publishers and codecs validate complete replacement values before one foreground assignment.UsageChangedandInformationChangedfire only after the atomic assignment. Record equality is intentional.The common surface relevant to acquisition is:
AgentChatremains sealed and implementsIAgentChat; no transport branch is added to it.RemoteAgentChatalso implementsIAgentChat. Engine-only APIs remain on concreteAgentChatand are not added to the UI contract.Named remote open contract
Remote open/status/attach uses the existing strict property DTO:
The codec retains the
attach-agent-sessiondescriptor, version-1 kebab-case JSON, strict unknown-member rejection, fixed command/event discriminators, authorization-before-lookup, and owner/generation validation.Interrupt has this exact client API:
It emits the fixed
interruptcommand discriminator, is idempotent for the active turn, and does not terminate the runtime.AcquireAgentChatRequest, running table, and leasesAcquireAgentChatRequestremains the existing public property-based request and adds:Example:
The added properties are ordinary init-only storage. They perform no I/O and do not clone, own, or dispose the transport.
LocalforbidsOwningProfileTransport. Remote modes require the transport, persisted entity data, owner, and generation.For a not-yet-running local session,
AcquireAsynccallsAgentSessionRuntimeContextFactory.Createexactly once and immutably merges the result into that session’sAgentServices. Existing running sessions retain their already-composed services.For remote acquisition, the table creates
RemoteAgentSessionClient/RemoteAgentChatthrough the internal attach path and registers the proxy only after the first authoritative snapshot. Concurrent requests single-flight by session, owner, and generation. Cancellation before publication leaves no row.TerminateAsyncreturnsfalsewhen absent. For a local runtime it disposes the owning runtime; for a remote proxy it sends explicit termination rather than detach.SetContinueInBackgroundAsyncrejects absent and subagent sessions. It dispatches a local owner update to the runtime registry or a remote update toRemoteAgentSessionClient, and completes only after persistence and authoritative publication.RunningAgentChatLease.AgentChatreturns the registered acquired instance.RunningAgentChatandRunningAgentChatWithEntityInfocontinue to exposeAcquireLeaseAsync; they do not add a borrowedChatproperty. Lease disposal is idempotent and releases viewer/reference ownership exactly once.RunningAgentChatWithEntityInfometadata is an owner/client-authoritative snapshot. Changes raise the existing property-change path beforeRunningAgentBrainViewModel.Refreshupdates a row.Session services and current-session identity
AgentServiceskeeps its existing object-typed layering seams and adds:CurrentSessionContextadds:Blank owner, negative generation, and an epoch without owner are rejected. The owning host creates one context per runtime. Attachment identity never replaces host identity.
AgentServicesComposition.ComposeSessionServicesAsyncremains host-service composition and does not parse persisted executor/trust fields.RunningAgentChatTableappliesAgentSessionRuntimeContextFactory.Createafterward throughwith, preventing GUI/auto-resume divergence and cross-session service leakage.Unified open and UI helper requests
OpenAgentSessionShortcutHandler.Handle,TryCreateAgentSessionTabForRestoreAsync,TryCreateTabForRestoreAsync, andCreateAgentSessionTabAsyncroute through one internal persisted-session opening pipeline.ConnectOnOwnerconstructs remote acquisition;ResumeLocallycompletes takeover before local acquisition. The handler never parses executor bindings or compiles trust policy.The inherited
HandleandTryCreateTabForRestoreAsyncoverrides retain their framework signatures. Changed helper APIs use these exact property-based records:Named initializer examples:
Fresh launch, restore, and auto-resume pass the persisted entity into acquisition. Non-GUI acquisition uses the same table seam. All paths preserve slash-command composition through the common
IAgentChatsurface and cannot bypass runtime hydration or owner selection.Out of scope
AgentChat, compiled policy, process handles, or host runtime state.Tests
All prior tests remain required. The following committed-design tests are also part of this child where they define Commit 5, its entity-factory boundary, common acquisition surface, open DTO, UI helper requests, or authoritative running metadata.
AgentSessionRuntimeContextFactoryTests(Phantom.Workspaces.Tests)Constructor_NullRegistry_AllowsLocalOnlyHydration.AgentSessionRuntimeIntentData_InitProperties_PreserveOnlyPersistableIntent.CreateAgentSessionEntityDataRequest_RequiredInitProperties_AreMarkedRequired.CreateAgentSessionEntityDataRequest_OptionalProperties_UseDocumentedDefaults.CreateEntityData_NamedInitializer_PersistsMappedFields.PersistedAgentSessionRuntimeIntent_Init_InvalidOwnerOrGeneration_RejectsValue.AgentSessionRuntimeContext_Init_StoresIntentAndProcessRegistry.Create_PersistedSplitBindings_ReconstructsRuntimeContext.Create_NoPersistedBindings_UsesLocalDefaults.Create_LegacyHostProfile_UsesSessionExecutorFallback.Create_MalformedBinding_ReportsBindingKeyWithoutValue.Create_NonlocalBindingWithoutRegistry_ReportsConfigurationError.Create_TrustIntent_PreservesReferenceAndExpectedRevision.AgentSessionEntityFactory_CreateEntityData_DefaultBackground_PersistsFalse.AgentSessionEntityFactory_CreateEntityData_BackgroundEnabled_PersistsTrue.AgentSessionEntityFactory_CreateEntityData_DefaultOwner_ThrowsArgumentException.AgentSessionEntityFactory_CreateEntityData_RuntimeAuthority_PersistsOwnerGenerationBindingsAndTrust.Create_MissingContinueInBackground_UsesFalse.Create_ExplicitContinueInBackground_PreservesTrue.Create_CompiledPolicyProperty_RejectsEntity.RunningAgentChatTableTests(Phantom.Workspaces.Tests)AcquireAsync_NewLocalSession_HydratesServicesBeforeFactoryAcquisition.AcquireAsync_ExistingLease_DoesNotRehydrateRuntimeContext.AcquireAsync_RemoteMode_UsesInternalAttachPath.AcquireAsync_CancelledBeforePublication_AddsNoRunningRow.AcquireAsync_ValidRemoteSession_AddsProxyAfterSnapshot.AcquireAsync_RemoteMissingEntityOrTransport_ThrowsArgumentException.AcquireAsync_ConcurrentSameRemoteRuntime_ReturnsLeasesForOneProxy.AcquireAsync_RemoteAuthorizationDenied_AddsNoRunningRow.TerminateAsync_MissingSession_ReturnsFalse.TerminateAsync_LocalSession_DisposesOwningRuntime.TerminateAsync_RemoteSession_SendsTerminateNotDetach.SetContinueInBackgroundAsync_LocalOwner_PersistsAndPublishesPreference.SetContinueInBackgroundAsync_RemoteProxy_SendsCommandAndAwaitsEvent.SetContinueInBackgroundAsync_MissingOrSubagentSession_ThrowsArgumentException.SetContinueInBackgroundAsync_CancelledBeforeWrite_DoesNotPersistOrPublish.RunningSessions_RemoteAttach_MutatesOnForegroundScheduler.CurrentSessionContextTestsandAgentServicesTestsCurrentSessionContext_ValidOwnerGenerationEpoch_PreservesOwningHostIdentity.CurrentSessionContext_BlankOwner_RejectsInitialization.CurrentSessionContext_NegativeGeneration_RejectsInitialization.CurrentSessionContext_AttachmentPeer_DoesNotReplaceHostIdentity.AgentServices_AgentExecutionTrustContextSetter_WithExpressionPreservesOtherServices.AgentServices_RemoteRuntimeIntentSetter_WithExpressionPreservesOtherServices.AgentServices_GetService_NewObjectTypedSeams_DoesNotExposeConcreteTypes.AcquireAgentChatRequest_RemoteInitProperties_PreserveModeTransportAndCursor.AcquireAgentChatRequest_Defaults_SelectLocalModeWithoutTransportOrCursor.AcquireAgentChatRequest_InvalidModeCombination_AcquireRejectsRequest.AgentViewModel_AgentChatProperty_LocalAndRemote_ReturnsIAgentChat.RunningAgentChatLease_AgentChatProperty_LocalAndRemote_ReturnsIAgentChat.RunningAgentChatWithEntityInfo_RetentionMetadataChange_RaisesAuthoritativeUpdate.Common
Usage,AgentInformation, andIAgentChatcontract testsInformation_LocalChat_ReturnsAtomicAgentInformation.Usage_LocalChat_ReturnsAtomicUsage.InputQueues_LocalChat_ReturnsCommonQueueAggregate.GetToolSnapshot_MutationAfterRead_DoesNotChangeReturnedSnapshot.SetToolEnabledAsync_KnownTool_ChangesStateThenRaisesToolsChanged.SetToolEnabledAsync_UnknownTool_ThrowsArgumentException.SetToolEnabledAsync_Cancelled_DoesNotMutateOrRaiseEvent.RespondToModalAsync_CurrentModal_AcceptsExactlyOnce.RespondToModalAsync_UnknownModal_ThrowsArgumentException.EnqueueSystemNote_ValidText_AppendsSystemNote.EnqueueHelpNote_ValidText_AppendsHelpNote.EnqueueTransientDiagnostic_ValidText_AppendsNonPersistedDiagnostic.Interrupt_ActiveTurn_CancelsTurnWithoutDisposingChat.Interrupt_NoActiveTurn_IsIdempotent.Usage_EqualValues_CompareEqual.Usage_DefaultInitialization_AllOptionalMetricsAreNull.Usage_NamedInitializer_PreservesExactMetricTypes.Usage_RoundTrip_PreservesNullableCountsAndDoubleUsd.UsagePublisher_NegativeMetric_RejectsBeforePublication.UsageChanged_CompleteReplacement_StateVisibleBeforeSingleEvent.AgentInformation_EqualValues_CompareEqual.AgentInformation_RequiredInitProperties_AreMarkedRequired.AgentInformation_NamedInitializer_PreservesAllFields.AgentInformationPublisher_InvalidRequiredString_RejectsBeforePublication.AgentInformationPublisher_InvalidOptionalModel_RejectsBeforePublication.AgentInformation_AuthorizedPeer_RoundTripsCompleteDefinition.AgentInformationPublisher_NullDefinition_RejectsBeforePublication.SessionSnapshot_TwoAuthorizedViewers_ReceiveEquivalentFullDefinition.OpenAsync_UnauthorizedPeer_SerializesNoSessionMetadata.InformationChanged_SessionAndModelChange_StateVisibleBeforeSingleEvent.TurnCompleted_TurnPersists_EventRaisedAfterHistoryMutation.DisposeAsync_RepeatedCall_DisposesOnce.GetService_KnownService_ReturnsExistingService.Remote open/client contract tests relevant to acquisition
ClientRequestTypes_RequiredInitProperties_AreMarkedRequired.ClientRequestTypes_NamedInitializers_PreserveStatusAndCommandPayloads.GetStatusAsync_AuthorizedRunningOrStopped_ReturnsAuthoritativeStatusOnly.GetStatusAsync_UnauthorizedOrMissing_ReturnsUnavailableWithoutMetadata.ConnectAsync_FirstCall_OpensAttachAgentSessionChannel.ConnectAsync_SecondCall_ThrowsInvalidOperationException.ConnectAsync_CancelledBeforeOpen_LeavesClientDisconnected.ConnectAsync_SnapshotThenDelta_UpdatesCursorAndRaisesFramesInOrder.ConnectAsync_SequenceGap_ClosesWithProtocolException.ConnectAsync_UnknownDiscriminator_ClosesWithProtocolException.ReconnectAsync_UnexpectedLoss_ForcesAttachWithTokenAndLastAppliedCursor.ReconnectAsync_ConnectedDetachedTerminalOrExpired_ThrowsInvalidOperationException.ReconnectAsync_CancelledAttempt_AllowsRetryBeforeDeadline.InterruptAsync_Connected_SerializesInterruptAndAwaitsCorrelation.SetContinueInBackgroundAsync_Connected_AwaitsPersistedAuthoritativeEvent.SetContinueInBackgroundAsync_Rejected_LeavesProjectionUnchanged.CommandMethod_EmptyCommandId_ThrowsArgumentException.CommandMethod_CancelledAfterWrite_DoesNotRetractCommand.CommandMethod_NotConnected_ThrowsInvalidOperationException.FrameReceived_ValidFrame_CursorAdvancesBeforeSubscriberRuns.LastAppliedCursor_NoFrames_IsNull.RuntimeEpoch_EmptyValue_RejectsInitialization.ReplayCursor_NegativeSequence_RejectsInitialization.AgentSessionOpenRequest_InvalidVersionOrGeneration_RejectsInitialization.ProtocolDtos_RequiredInitProperties_AreMarkedRequired.ProtocolDtos_OptionalProperties_UseDocumentedDefaults.ProtocolDtos_NamedInitializers_PreserveFixedDiscriminators.Serialize_AllOpenIntents_UsesVersionOneDiscriminators.AgentViewModelTestsConstructor_RemoteChat_UsesCommonSurfaceWithoutConcreteCast.AgentViewModelOptions_NamedInitializer_PreservesRequiredValuesAndParentDefault.Constructor_WrongForegroundContext_Throws.RespondToModalAsync_CurrentModal_SendsResponseAndKeepsInputGatedUntilDismissed.RespondToModalAsync_UnknownModal_ThrowsArgumentException.RespondToModalAsync_Cancelled_DoesNotDismissModal.ModalEvent_DescendantModal_UpdatesRootAggregateOnly.DisposeAsync_RemoteChat_UnsubscribesBeforeDetaching.InterruptCommand_RemoteChat_InvokesCommonInterrupt.ConfigureSlashCommands_RemoteChat_RegistersOnlyCommonHandlers.SlashCommandContextTestsAgentChatSetter_LocalOrRemote_PreservesCommonChat.AgentChatSetter_Null_RejectsInitialization.OpenAgentSessionShortcutHandlerTestsHandle_OwnerIsCurrentProfile_AcquiresLocalRuntime.Handle_OwnerIsRemoteConnectChoice_AttachesOnOwner.Handle_OwnerIsRemoteResumeChoice_CompletesTakeoverBeforeLocalAcquire.TryCreateAgentSessionTabForRestoreAsync_RemoteOwner_UsesSameChoicePipeline.TryCreateTabForRestoreAsync_RemoteOwner_UsesSameChoicePipeline.Handle_RemoteOwnerPrompt_ShowsAuthorizedRunningStatus.Handle_RemoteOwnerPrompt_ShowsAuthorizedNotRunningStatus.Handle_RemoteOwnerPrompt_UnauthorizedOrMissingShowsUnavailable.CreateAgentSessionTabAsync_PersistedSession_PassesEntityToAcquisition.ComposeSessionAgentViewModel_RemoteChat_ConfiguresCommonSlashCommandSurface.SessionUiRequestOptions_NamedInitializers_PreserveRequiredValuesAndOptionalDefaults.DisposeAsync_InitializationInFlight_CancelsWithoutPublishingReadyTab.Fresh, restore, auto-resume, and non-GUI parity
AcquireAsync.Acceptance criteria
CreateAgentSessionEntityDataRequestvariable andAgentSessionEntityFactory.CreateEntityData(request).UsageandAgentInformationexactly match the property contracts above.InterruptAsync(Guid commandId, CancellationToken ct = default).