Parent: #2635
Objective
Implement the core transactional per-agent profile state machine: immutable state/contracts, literal command reduction, candidate resolution/construction, scheduler-safe commit, resource lifecycle, and explicit Agent/Turn/ProviderCall/ToolInvocation routing.
This task establishes the single authoritative active-state owner. Entry-point cutovers are separate subissues.
Scope
Core contracts
Define implementation-neutral:
configured/unconfigured ProfileState and tagged saved/draft identity;
one ProfileCommand union with expected revision and unsaved-discard intent;
typed committed/no-op/queued/confirmation-required/cancelled/busy/stale/conflict/invalid/unverified/failed results;
redacted snapshots/diffs/errors/health and factual agent+command+revision events;
narrow AgentProfile query/transition capability and smaller role/read capabilities;
profile repository, runtime factory, credential resolver, provider/model catalog/capability, trust/tool environment, and scheduler-boundary ports;
immutable TurnContext, ProviderCallContext, and ToolInvocationContext contracts.
Core must not import settings/provider implementations or expose a generic runtime/service bag.
Literal command reduction
Implement pure reduction rules from one explicit source document:
/model: clone the concrete standard source, patch model only, no template reread; no-op on same model.
LB /model: clone the immutable captured active member source selected by its provider-specific model menu; no cross-provider inference.
/provider: blank reset from restricted template materialization; copy no active state even for same provider.
/profile load: exact repository document.
/setup: blank candidate.
profile /set: clone and patch; reject application-owned keys.
startup: one composite initial command; LB + model requires qualified member.
Preserve pin/unset semantics, saved/draft provenance, immutable menu source values, no-op detection, expected-revision checks, and unsaved-draft confirmation results.
Candidate resolution
With injected ports:
resolve defaults without mutating explicit document;
resolve reference graphs from captured documents/etags;
create discriminated credential bindings without copying resolved secrets;
validate provider/model extensions and known capability constraints;
return valid, invalid, or unverified;
capture active LB member source;
intersect profile agent policy with environment/trust, application/session, and role/delegation ceilings;
missing required tool invalidates, unavailable allowed tool warns/intersects, unknown disabled IDs remain portable;
status explains requested versus effective restrictions.
ProfileController and ActiveProfileRuntime lifecycle
One controller per agent/subagent, no active-state singleton.
Serialize commands; queued commands retain base revision and never silently rebase.
Pure reduction/validation and revision/etag capture before waiting.
Commit only at the real execution-coordinator safe boundary; parent turn awaiting subagent still blocks itself.
Recheck revision/etags, resolve credentials/build candidate locally, then perform a minimal non-failing ownership swap.
Candidate uses async-disposable ownership scope; failure/cancel cleans all candidate resources.
Listener/event errors are isolated.
Old-runtime disposal is bounded best effort after commit and cannot roll back.
Fresh logical provider/LB bindings for effective changes; only explicitly safe stores/transports/caches are borrowed/shared.
Tool registries remain stable; runtime exposes filtered declarations and immutable policy snapshots.
Lazy role runtimes are children of parent revision and capture referenced document+etag.
External repository edit/delete turns matching saved identity into draft, increments revision, preserves document/runtime, and never hot-reloads.
Runtime auth/network/quota degradation updates typed health only; no automatic rollback/dirtiness.
Coordination / non-overlap
Acceptance criteria
Two agents loading the same profile have independent controller/runtime/LB/policy state.
No command exposes half-applied state; failed/cancelled candidates leave prior state active and leak no resources.
Literal command semantics and no-op behavior match Transactional per-agent profiles: replace ambient provider/model state with declarative runtime ownership #2635 exactly, including same-provider reset and captured LB member fork.
Commands serialize, expected revisions/etags reject stale work, queued commands never rebase, and unsaved destructive operations require typed confirmation.
Interactive transition commit waits for the scheduler-safe boundary; in-flight model/tool/continuation work retains captured contexts/policy.
Profiles can narrow but never expand environment authority; requested/effective explanations are available without secrets.
Runtime health is separate from profile identity and operational failures never auto-rewrite or revert the document.
Public contracts expose no Config, SettingsService, ProviderManager, runtime registry ID, credentials, or generic runtime bag.
Behavioral tests cover cleanup races, listener failures, old-runtime disposal, parent/subagent boundaries, background tools, external repository changes, and simultaneous agents.
Full test/lint/typecheck/format/build verification passes for affected packages.
Parent: #2635
Objective
Implement the core transactional per-agent profile state machine: immutable state/contracts, literal command reduction, candidate resolution/construction, scheduler-safe commit, resource lifecycle, and explicit Agent/Turn/ProviderCall/ToolInvocation routing.
This task establishes the single authoritative active-state owner. Entry-point cutovers are separate subissues.
Scope
Core contracts
Define implementation-neutral:
ProfileStateand tagged saved/draft identity;ProfileCommandunion with expected revision and unsaved-discard intent;AgentProfilequery/transition capability and smaller role/read capabilities;TurnContext,ProviderCallContext, andToolInvocationContextcontracts.Core must not import settings/provider implementations or expose a generic runtime/service bag.
Literal command reduction
Implement pure reduction rules from one explicit source document:
/model: clone the concrete standard source, patch model only, no template reread; no-op on same model./model: clone the immutable captured active member source selected by its provider-specific model menu; no cross-provider inference./provider: blank reset from restricted template materialization; copy no active state even for same provider./profile load: exact repository document./setup: blank candidate./set: clone and patch; reject application-owned keys.Preserve pin/unset semantics, saved/draft provenance, immutable menu source values, no-op detection, expected-revision checks, and unsaved-draft confirmation results.
Candidate resolution
With injected ports:
ProfileController and ActiveProfileRuntime lifecycle
Coordination / non-overlap
Acceptance criteria