[AIGTWY-4758] Reconcile managed-config skills at ug configure - #691
Merged
Merged
Conversation
david-siqi-liu
marked this pull request as ready for review
September 16, 2026 21:30
david-siqi-liu
force-pushed
the
david/ug-configure-skills
branch
from
September 16, 2026 21:36
9cc4fc8 to
6c27edb
Compare
ug configureug configure
david-siqi-liu
force-pushed
the
david/ug-configure-skills
branch
2 times, most recently
from
September 17, 2026 16:48
04f27f4 to
b560103
Compare
xsh310
reviewed
Sep 18, 2026
xsh310
reviewed
Sep 18, 2026
ug configureug configure
david-siqi-liu
force-pushed
the
david/ug-configure-skills
branch
4 times, most recently
from
September 18, 2026 03:49
1c6c73e to
1eef287
Compare
Managed coding-agent config can declare a `skills` selector, but ug never consumed it: cli read `skills.names` as `<catalog>.<schema>` locations and ignored `unity_catalog_location`, so both valid selector shapes downloaded nothing -- a silent no-op, like the managed mcp_servers no-op that #669 fixed. Resolve the `NamesOrLocation` selector correctly (names as full `<catalog>.<schema>.<name>` FQNs, unity_catalog_location as a schema; malformed entries skipped with a warning) and download the skills at `ug configure`, alongside managed MCP-server registration and off the launch hot path. The bundles land in both `.claude/skills` and `.agents/skills`, so Claude Code and Codex both pick them up. Add a managed_fixture integration suite (test_ug_configure_managed_skills.py) mirroring the mcp/models suites: inject a config naming a real skill, configure, and assert the agent's /skills view lists it, for both Claude and Codex. Co-authored-by: Isaac <no-reply@databricks.com>
xsh310
approved these changes
Sep 18, 2026
…bution Builds on the download-at-configure base: `ug configure` now reconciles the workspace's skills rather than only adding them, mirroring `reconcile_managed_mcp_servers`. `_configure_managed_skills` runs alongside `_configure_managed_mcp_servers` (managed branch and the no-managed cleanup path) and calls `reconcile_managed_skills(managed)`, which loads state itself, downloads desired skills not on disk, and removes managed skills the config no longer lists. Managed installs are tagged `scope="managed"` in `~/.ucode/skills.json`, so `ug skills remove` never drops an admin skill and a developer's own downloads stay distinct; re-downloading one via `ug skills add` transfers it back to the developer. Removal is skipped when the desired set can't be determined (a listing failure), so a transient error never deletes a skill. Adds a disk-based reconcile lifecycle integration test alongside the /skills TUI tests. In-place version refresh (uc_update_time) is left as a follow-up. Co-authored-by: Isaac <no-reply@databricks.com>
david-siqi-liu
force-pushed
the
david/ug-configure-skills
branch
from
September 18, 2026 04:55
1eef287 to
2538875
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Managed coding-agent config can declare a
skillsselector ({names | unity_catalog_location}), butugnever consumed it.clireadskills.namesas if they were<catalog>.<schema>locations and ignoredunity_catalog_location, so both valid selector shapes downloaded nothing: a silent no-op, exactly like the managedmcp_serversno-op that #669 fixed.Change
Mirror how managed
mcp_serversare handled: atug configure(alongside MCP registration, off the launch hot path), resolve theNamesOrLocationselector correctly and reconcile the workspace's skills to disk.skills_download.py:_resolve_managed_skillsresolves the selector into the refs to download plus the desired FQN set (aunity_catalog_locationlists every finalized skill under that<catalog>.<schema>;namesare full<catalog>.<schema>.<name>FQNs; malformed entries are skipped with a warning).reconcile_managed_skills(managed)downloads desired skills not already on disk and removes managed skills the config no longer lists. Removal is skipped when the desired set can't be determined (a listing failure), so a transient error never deletes a skill.scope="managed"in~/.ucode/skills.json, soug skills removenever drops an admin skill and a developer's own downloads stay distinct. Re-downloading a managed skill viaug skills addtransfers it back to the developer.cli.py:_configure_managed_skillsmirrors_configure_managed_mcp_servers, running on both the managed branch and the no-managed cleanup path (so switching to a workspace with fewer or no skills reconciles the old ones away). Skills land in both.claude/skillsand.agents/skills, so Claude Code and Codex both pick them up.Follow-ups
In-place version refresh: a republished skill already on disk is not re-fetched yet. Doing it correctly needs bundle-replacement semantics (the writer adds files but does not delete ones a newer version drops), not just a
uc_update_timecompare, so it is deferred.Testing
Set up

Claude
Codex
Unit: selector resolution (names / location / precedence / malformed / unresolvable / failures / empty / duplicate-FQN dedup), reconcile removal (dropped skill removed, empty selector clears all, listing failure never removes, configured-but-unfetchable kept),
scope="managed"attribution andug skills removeexclusion, configure wiring and order, and launch making no skill calls.E2E: the
managed_fixtureintegration suite (tests/integration/test_ug_configure_managed_skills.py) injects an admin config viaUCODE_MANAGED_CONFIG_STUB, runsug configure, and launches the real agent. Two cases assert the downloaded skill appears in the agent's/skillsview for Claude (via thenamesselector) and Codex (via theunity_catalog_locationselector).A third case,
test_managed_skills_reconcile_lifecycle, exercises the managed-vs-personal behavior end to end across fourug configureruns: (1) no skills configured downloads nothing; (2) aunity_catalog_locationconfig downloads the workspace's skills to disk; (3) a developer's own hand-authored skill (no attribution record) sits alongside them; (4) switching back to a no-skills config removes only the managed skills and leaves the developer's own untouched. That proves the reconcile is attribution-driven: it removes the admin skills the config drops while never deleting a skill ug did not download. Runs in the existing non-blocking managed lanes.Managed-vs-personal ownership is also covered at the unit level:
scope="managed"attribution,ug skills removerefusing to drop a managed skill, and reconcile keeping a developer's ownscope="user"install.uv run ruff check ./ruff format --checkclean; focused unit suites pass locally; the new suite collects.Part of epic AIGTWY-4329.
This pull request and its description were written by Isaac.