Skip to content

[AIGTWY-4758] Reconcile managed-config skills at ug configure - #691

Merged
david-siqi-liu merged 3 commits into
mainfrom
david/ug-configure-skills
Sep 18, 2026
Merged

david-siqi-liu merged 3 commits into
mainfrom
david/ug-configure-skills

Conversation

@david-siqi-liu

@david-siqi-liu david-siqi-liu commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Problem

Managed coding-agent config can declare a skills selector ({names | unity_catalog_location}), but ug never consumed it. cli read skills.names as if they were <catalog>.<schema> locations and ignored unity_catalog_location, so both valid selector shapes downloaded nothing: a silent no-op, exactly like the managed mcp_servers no-op that #669 fixed.

Change

Mirror how managed mcp_servers are handled: at ug configure (alongside MCP registration, off the launch hot path), resolve the NamesOrLocation selector correctly and reconcile the workspace's skills to disk.

  • skills_download.py: _resolve_managed_skills resolves the selector into the refs to download plus the desired FQN set (a unity_catalog_location lists every finalized skill under that <catalog>.<schema>; names are 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.
  • Managed attribution: managed installs are recorded 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 a managed skill via ug skills add transfers it back to the developer.
  • cli.py: _configure_managed_skills mirrors _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/skills and .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_time compare, so it is deferred.

Testing

Set up
image

Claude

image image

Codex

image image

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 and ug skills remove exclusion, configure wiring and order, and launch making no skill calls.

E2E: the managed_fixture integration suite (tests/integration/test_ug_configure_managed_skills.py) injects an admin config via UCODE_MANAGED_CONFIG_STUB, runs ug configure, and launches the real agent. Two cases assert the downloaded skill appears in the agent's /skills view for Claude (via the names selector) and Codex (via the unity_catalog_location selector).

A third case, test_managed_skills_reconcile_lifecycle, exercises the managed-vs-personal behavior end to end across four ug configure runs: (1) no skills configured downloads nothing; (2) a unity_catalog_location config 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 remove refusing to drop a managed skill, and reconcile keeping a developer's own scope="user" install.

uv run ruff check . / ruff format --check clean; focused unit suites pass locally; the new suite collects.

Part of epic AIGTWY-4329.

This pull request and its description were written by Isaac.

@david-siqi-liu
david-siqi-liu marked this pull request as ready for review September 16, 2026 21:30
@david-siqi-liu david-siqi-liu added the quicktree-assisted PR created with quicktree-assisted workflow label Sep 16, 2026
@david-siqi-liu
david-siqi-liu force-pushed the david/ug-configure-skills branch from 9cc4fc8 to 6c27edb Compare September 16, 2026 21:36
@david-siqi-liu david-siqi-liu changed the title [AIGTWY-4329] Download managed-config skills at ug configure [AIGTWY-4758] Download managed-config skills at ug configure Sep 16, 2026
@david-siqi-liu
david-siqi-liu force-pushed the david/ug-configure-skills branch 2 times, most recently from 04f27f4 to b560103 Compare September 17, 2026 16:48
Comment thread src/ucode/skills_download.py
Comment thread src/ucode/skills_download.py Outdated
@david-siqi-liu david-siqi-liu changed the title [AIGTWY-4758] Download managed-config skills at ug configure [AIGTWY-4758] Reconcile managed-config skills at ug configure Sep 18, 2026
@david-siqi-liu
david-siqi-liu force-pushed the david/ug-configure-skills branch 4 times, most recently from 1c6c73e to 1eef287 Compare September 18, 2026 03:49
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>
…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
david-siqi-liu force-pushed the david/ug-configure-skills branch from 1eef287 to 2538875 Compare September 18, 2026 04:55
@david-siqi-liu
david-siqi-liu enabled auto-merge (squash) September 18, 2026 05:09
@david-siqi-liu
david-siqi-liu merged commit bbf9c40 into main Sep 18, 2026
20 checks passed
@david-siqi-liu
david-siqi-liu deleted the david/ug-configure-skills branch September 18, 2026 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

quicktree-assisted PR created with quicktree-assisted workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants