Add ucode apply: publish the authored managed config - #271
Open
tt-le wants to merge 1 commit into
Open
Conversation
tt-le
force-pushed
the
tien/managed-apply-clients
branch
from
August 5, 2026 17:53
d3ee7c2 to
13c66f0
Compare
tt-le
force-pushed
the
tien/managed-apply
branch
2 times, most recently
from
August 5, 2026 19:29
c16711b to
8287258
Compare
tt-le
force-pushed
the
tien/managed-apply-clients
branch
from
August 5, 2026 19:58
b0ba733 to
7e2ec09
Compare
tt-le
force-pushed
the
tien/managed-apply
branch
from
August 5, 2026 19:58
8287258 to
be99eed
Compare
tt-le
force-pushed
the
tien/managed-apply-clients
branch
from
August 5, 2026 20:49
7e2ec09 to
88f43af
Compare
tt-le
force-pushed
the
tien/managed-apply
branch
from
August 5, 2026 20:49
be99eed to
d4fcec4
Compare
tt-le
force-pushed
the
tien/managed-apply-clients
branch
from
August 5, 2026 21:03
88f43af to
b8dff9e
Compare
tt-le
force-pushed
the
tien/managed-apply
branch
from
August 5, 2026 21:03
d4fcec4 to
1dd8c7e
Compare
tt-le
force-pushed
the
tien/managed-apply-clients
branch
from
August 5, 2026 21:12
b8dff9e to
03a3f13
Compare
tt-le
force-pushed
the
tien/managed-apply
branch
from
August 5, 2026 21:12
1dd8c7e to
56a5e69
Compare
The publish step for the manifest `ucode setup` authors. Validates, shows what would change, confirms, then writes it to the workspace via the clients added in the parent commit. Updates in place rather than replacing. When the workspace already has a config, `apply` PATCHes it using its resource name (read back from the existing-config GET, which `normalize_managed_config` preserves). Delete-then-create was the original plan — v0's Create returns ALREADY_EXISTS — but it has a window where the workspace has *no* managed config, and if the create failed there every developer would silently fall back to their own settings until someone re-ran the command. The server applies the update mask inside a single entity-store update, so a failed PATCH leaves the current config intact. It is still a whole-manifest write: every path ucode owns is sent, so a field the admin dropped on a re-run is cleared rather than left behind. Refuses to publish when it cannot tell whether a config already exists. A failed existence check used to be the one case where "just try the create" would either duplicate or silently overwrite an admin's work, so an unreadable check is a hard error naming the reason rather than a warning. `_explain_publish_failure` maps the failures an admin will actually hit. FEATURE_DISABLED is the likely first experience — the CRUD flag is off by default — so it names `codingAgentConfigCrudEnabled` instead of printing an HTTP 400. INVALID_PARAMETER_VALUE is passed through verbatim: the server names the offending field, which beats any paraphrase. `--yes` skips the confirmation for CI; `--dry-run` validates and previews without writing. The admin gate and validation both run before anything is sent, so an invalid manifest or a non-admin costs no round trip. README documents the publish step and drops the "no partial update yet" caveat, which the PATCH path makes untrue. Verified against eng-ml-inference.staging: `apply --dry-run` authenticated, verified admin, rendered the summary, detected the existing config, and chose the update path without writing. Tests: 19 cases. Mutation-verified three ways — always-create instead of PATCH, publishing despite an unreadable existence check, and publishing an invalid manifest each fail a specific test. Also covers that `typer.Exit(0)` isn't caught by the command's own RuntimeError handler, the same trap `setup` hit. Co-authored-by: Isaac
tt-le
force-pushed
the
tien/managed-apply-clients
branch
from
August 5, 2026 21:21
03a3f13 to
32205ad
Compare
tt-le
force-pushed
the
tien/managed-apply
branch
from
August 5, 2026 21:21
56a5e69 to
dc06d66
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.
Changes
The publish step for the manifest
ucode setupauthors. Validates, shows what would change, confirms, then writes it to the workspace using the clients from #270. This completes the admin path: author (ucode setup) → review (ucode setup show) → publish (ucode apply).It updates in place rather than replacing
When the workspace already has a config,
applyPATCHes it using its resource name, read back from the existing-config GET (normalize_managed_configpreservesname).Delete-then-create was the original plan, since v0's Create returns
ALREADY_EXISTS. But that has a window where the workspace has no managed config — and if the create failed there, every developer would silently fall back to their own settings until someone re-ran the command. The server applies the update mask inside a single entity-store update, so a failed PATCH leaves the current config intact.It is still a whole-manifest write: every path ucode owns is sent, so a field the admin dropped on a re-run is cleared rather than left behind.
It refuses to publish when it can't tell whether a config exists
A failed existence check is the one case where "just try the create" either duplicates or silently overwrites an admin's work. So an unreadable check is a hard error naming the reason, not a warning that proceeds.
Error mapping
_explain_publish_failurecovers the failures an admin will actually hit:FEATURE_DISABLEDcodingAgentConfigCrudEnabledand who to ask — this is the likely first experience, since the CRUD flag is off by defaultPERMISSION_DENIEDINVALID_PARAMETER_VALUEALREADY_EXISTSThe admin gate and validation both run before anything is sent, so an invalid manifest or a non-admin costs no round trip.
Testing
uv run pytest— 1372 passed, 6 skipped. 19 new cases.Mutation-verified three ways: always-create instead of PATCH, publishing despite an unreadable existence check, and publishing an invalid manifest each fail a specific test. Also covers that
typer.Exit(0)isn't swallowed by the command's ownRuntimeErrorhandler — the same trapsetuphit, where a successful run printedERROR 0.Verified against a staging workspace:
That exercised auth, the admin check, the summary, and the existing-config detection choosing the update path — without writing.
README
Documents the publish step and drops the "no partial update yet" caveat, which the PATCH path makes untrue.
Not included
A pre-publish validation probe (launching each agent to confirm its model actually answers) is deliberately out of scope — it needs its own retry UX and would roughly double this PR. Better as a follow-up or a
--probeflag.This pull request and its description were written by Isaac.