Skip to content

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

Merged
asujithan merged 4 commits into
databricks:mainfrom
asujithan:managed-apply
Aug 5, 2026
Merged

Resolve managed coding-agent config over local state at launch#265
asujithan merged 4 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.

First command: with env var set uses managed config and launches with opus-4-8 as specified by admin
Second command: fallback path uses my user settings not managed config so claude launched with opus-5 when env var unset

Screen.Recording.2026-08-05.at.9.09.25.AM.mov

Note: Clearer warning messages for when fallback path is being used and edits to ucode configure command will be added in followup pr

@AarushiShah-db AarushiShah-db left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to gate this whole change behind an env var for now? I don't want to release the new functionality to users until we've properly bug bashed it

Im thinking we have a env var for now like ENABLE_MANAGED_AGENT_CONFIG and if it is set then only do we pull the config on launch

Comment thread src/ucode/cli.py Outdated
Comment thread src/ucode/managed_resolve.py
Comment thread src/ucode/managed_config.py Outdated
Comment thread src/ucode/managed_config.py Outdated
Comment thread src/ucode/cli.py
@asujithan
asujithan enabled auto-merge (squash) August 5, 2026 16:50
@asujithan
asujithan merged commit 578fc78 into databricks:main Aug 5, 2026
2 checks passed
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.

2 participants