Skip to content

Transactional ProfileController: literal commands, scheduler-safe commit, and runtime ownership #2643

Description

@acoliver

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureArchitectural refactor / clean designpackages/coreIssues related to packages/core componenttype: task

    Type

    Projects

    Status
    Todo

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions