2.5 KiB
ADR-2026-08-12-empty-utility-bindings-inherit-default: Empty Built-in Utility Bindings Inherit the Default
Status: accepted Date: 2026-08-12 Area: backend, frontend
Context
Older profile migration code persisted built-in utility actions with an empty profile ID and an
unconfigured binding. The previous default-inheritance decision preserved that state because it
did not distinguish a deleted explicit binding from a failed legacy migration. In practice, this
leaves every built-in action unavailable when the user has selected a valid global default. The
settings repair flow can also send an invalid explicit binding when the user chooses Default.
Decision
A built-in utility action with an empty profile ID always means that no concrete override is
recoverable. The backend normalizes an empty unconfigured built-in binding to inherit, and the
action resolves through the user's saved global default profile. This normalization is idempotent
and persists the inherited state so the database does not continue to expose the action as
unavailable.
The Utility Agents picker treats its fallback callback value, the empty string, as an inherited
selection. Saving Default sends an empty agent_profile_id with profile_binding_state: "inherit".
It never sends an empty explicit binding.
A non-empty stale profile ID still represents a recoverable explicit choice. Such a binding remains
unconfigured and fails closed until the user selects Default or another eligible profile. Custom
utility agents still require a concrete eligible profile.
Consequences
- Existing installations with empty unavailable built-in actions recover on the next binding migration and use the selected global default.
- Selecting Default repairs the action through the normal Settings save flow.
- The system no longer preserves hypothetical explicit intent when no profile identity remains.
- Concrete stale overrides remain diagnosable and do not silently change model, permissions, credentials, or launch policy.
Alternatives Considered
- Keep every empty
unconfiguredrow fail-closed. Rejected because no concrete identity can be repaired or audited, while the product contract already gives every built-in action a default. - Copy the current default profile ID into every repaired row. Rejected because built-in actions then stop following later changes to the global default.
- Convert every stale binding to
inherit. Rejected because a non-empty stale ID preserves a real explicit user choice and its security-relevant launch configuration.