Skip to content

Resolve managed coding-agent config over local state at launch - #265

Open
asujithan wants to merge 2 commits into
databricks:mainfrom
asujithan:managed-apply
Open

Resolve managed coding-agent config over local state at launch#265
asujithan wants to merge 2 commits into
databricks:mainfrom
asujithan:managed-apply

Conversation

@asujithan

@asujithan asujithan commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Changes

Applies the admin-published managed coding-agent config at launch, taking precedence over the developer's own ucode settings.

On every ucode launch, the workspace's managed config is re-read and persisted to ~/.ucode/managed-state.json, then resolved against ~/.ucode/state.json per key — the manifest wins, the developer's state fills any gaps. The resolved view renders the agent settings file (e.g. ~/.claude/ucode-settings.json); the two state files are never merged on disk, so state.json keeps recording what the developer configured for themselves.

— managed_resolve.py — pure precedence logic. Claude resolves per model family (a family the admin didn't pin keeps the developer's choice); flat-list agents take the manifest's list wholesale.
— managed_config.py — adds the per-launch refresh. A failed read falls back to the last persisted config rather than blocking the launch; a successful "no config" read clears the persisted copy so a removed policy can't reappear after an outage.
— state.py — save_state swaps managed values back for the developer's own before writing, so precedence never overwrites state.json.
— cli.py — wires this into _launch_tool. An explicit --provider that conflicts with the admin's is a hard error; a managed provider that can't be used names the managed config in the error.

Followups:

  • models and provider services, MCPs/skills, custom_headers, budget_policy/recommendModels, and sudo ownership of managed-state.json are follow-up PR
  • ucode configure / first-run auto-configure still pull agent settings from local state in this PR; follow-up PR will gate configure when a managed config exists ("deprecated, run ucode" message + path)

Test plan

uv run pytest — 1173 passed, 6 skipped. ruff check . and ruff format --check . clean.
tests/test_managed_resolve.py
— TestClaudeModels (5) — proto slots → families; manifest wins per family; unpinned family keeps developer's value; falls back to local; None when neither side has models
— TestListModels (3) — manifest list replaces local; local stands when manifest silent; blank entries dropped
— TestManagedProviderService (3) — manifest-only read, no fallback to local state
— TestResolveState (4) — input state not mutated; managed values layered onto the copy; unrelated keys preserved; other tools' providers untouched
— TestStateFileIsNotRewritten (8) — the core contract, run against a real temp state.json with save_state unstubbed: developer's model survives; settings file still gets the managed model; overlay bookkeeping never on disk; repeated saves stay idempotent (the relayed-proxy path saves twice); provider_services preserved; a developer with no prior value isn't given one; codex + gemini parametrized

tests/test_managed_config.py
— TestRefreshManagedConfig (9) — persists and returns the manifest; no-config returns None; no-config clears the persisted copy; read failure and auth failure each fall back to persisted, or to local settings when there is none; empty persisted marker isn't treated as a fallback; no workspace is a no-op
— TestManagedLaunchState (2) — layers managed models when a config exists; hands state back untouched when none
— TestPersistence — empty config overwrites a previous one

Ran e2e tests locally against eng-ml-inference-us-east-1 workspace and all tests pass except tests/test_e2e.py::TestCodexLaunch::test_launch_codex_per_model which is expected due to codex model list fix not yet being rolled out to prod.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant