Uh oh!
There was an error while loading. Please reload this page.
fix(resources): a same-ceiling resources set must not require --yes (cli#546) - #547
Conversation
… (cli#546) Bugbot MEDIUM on the develop->staging promotion mirror (#540), against #539 (backend#2220). #539 made any non-`user` RESOURCE_PROVENANCE stale, so an unchanged ceiling stopped returning early and instead fell through to the apply in order to re-stamp the marker as `user`. Correct intent, wrong landing site: the fall-through lands in the confirmation gate, and off a terminal that gate does not ask -- it returns exit 1. So tracebloc resources set --cores 4 --memory 16 # the CURRENT ceiling went from the exit-0 no-op the command's own --help documents ("0 applied (or nothing to change)"), and that docs/cli-navigation.md draws as an edge going straight to exit 0 bypassing CONF, to a hard failure. Nearly every installed edge still reads `installer` or `unknown`, so the blast radius was the installed base rather than an edge case, and the callers that restate a size are scripts -- the bootstrap, the end-to-end journey -- none of which pass --yes for what the docs promise is a no-op. The fix is one clause on the gate, not a revert: the gate guards the CEILING, and an unchanged ceiling has nothing to ask about ("Let each training run use up to 4 CPU / 16 GiB?" when the answer is already that is a question with one honest answer). The re-stamp #539 added still happens. The phantom-GPU fall-through (#241) had the same shape and is fixed by the same clause: both are bookkeeping writes, already announced by their own Infof lines, not budget changes an operator needs to sanction. Tests: TestSet_SameCeilingNeedsNoYes. Every same-ceiling case already in the file passed `yes: true` -- the flag under dispute -- which is why nothing was red. The new cases assert exit 0 AND that the apply still happens, because either alone is satisfiable by the wrong fix; they read RESOURCE_PROVENANCE=user off the values file helm was actually handed (the existing assertions go through --dry-run, which skips the very gate at issue); they cover the phantom-GPU sibling and a declining prompter on a terminal; and one sub-case bounds the fix by proving a real CHANGE off a terminal still exits 1 and mutates nothing. Five of the six sub-cases fail without the one-clause change. docs/cli-navigation.md: the `no change` node now says it may still re-stamp provenance or clear a phantom GPU, and never asks to confirm -- true of #539's behaviour too, which shipped without updating the map. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
saadqbal
commented
Aug 21, 2026
@LukasWodka — could you approve this one too if it looks right? Blocked on review. It's the Fix is one clause (the gate guards the ceiling; an unchanged ceiling has nothing to ask about) and #539's provenance re-stamp still happens. It also fixes the docs #539 made false — Six new sub-cases; reverting just the fix line reddens five of them. |
LukasWodka
left a comment
There was a problem hiding this comment.
Approving. I verified the claims locally rather than reading them approvingly, including the one that decides whether this fix is safe.
The mutation claim holds exactly. Reverting just the clause (anchor match asserted, so I know the mutation landed and isn't inert):
--- FAIL: TestSet_SameCeilingNeedsNoYes/installer-sized_edge
--- FAIL: TestSet_SameCeilingNeedsNoYes/pre-marker_edge
--- FAIL: TestSet_SameCeilingNeedsNoYes/junk_marker
--- FAIL: TestSet_SameCeilingNeedsNoYes/phantom_GPU_cleanup_needs_no_--yes
--- FAIL: TestSet_SameCeilingNeedsNoYes/not_even_asked_on_a_terminal
Five sub-cases, and a_real_change_still_needs_--yes passes both ways — precisely as you described it, the guard rather than the proof. Restored → green. go vet ./... clean, go test ./... all packages ok.
The thing I actually went looking for, since it's what makes this a one-line change instead of a revert: adding && !ceilingUnchanged means any case where ceilingUnchanged is wrongly true becomes a silent confirmation bypass on a real ceiling change. So the fix is only as exact as sameCeiling. It compares CPU/Mem via Cmp (quantity-aware, so unit spellings normalise), HasGPU, and GPUName+GPU when a GPU is present. Against resources.Training it omits two fields:
Provenance— correctly, and deliberately: it "never affects the numbers", and treating a provenance difference as a ceiling change is exactly the bug #539 created. It's handled separately bystaleProvenance.HasCPUMem— not compared. The only way that could matter isHasCPUMem=truewithCPU=0, Mem=0comparing equal to an unset current, which the floors validation should make unreachable.
Neither is introduced here — sameCeiling is untouched by this PR (0 lines in the diff), and it already gates the more consequential no-op early return above, where imprecision would skip the apply entirely rather than just a prompt. So the blast radius of any residual imprecision is strictly smaller on your new path than on the existing one. Not a blocker; noting it because "one clause" changes what sameCeiling is load-bearing for, and that's worth someone having checked once.
Two things in the tests I'd have asked for if they weren't there:
- Asserting exit 0 AND that the apply still happened. You're right that either alone is satisfiable by a wrong fix, and that's the distinction between fixing this and reverting #539.
- Reading
RESOURCE_PROVENANCEoff the values file helm was actually handed, via the newfakeHelmValueshelper, because the existing provenance assertions all run through--dry-run— which skips the very gate in dispute. A test that cannot reach the path it names is the failure mode this whole class keeps hitting; good that you built the helper rather than reusing an assertion that looked adjacent.
Docs: the no change edge in docs/cli-navigation.md now says it may re-stamp provenance or clear a phantom GPU and never asks to confirm — which was already true of #539's shipped behaviour, so this corrects a map that was silently stale rather than documenting the new clause. And the --help table's 0 applied (or nothing to change) becomes true again rather than needing an edit, which is the right direction: the code moved back to the contract, not the contract to the code.
Noted your untracked-worktree aside on make check's fmt-check — scoping the gate to git ls-files is the right call and CI agrees. Gate: 10 checks pass (Bugbot included), 3 skipping, MERGEABLE, zero unresolved threads.
LukasWodka
commented
Aug 22, 2026
/fr-pass |
Fixes#546. Bugbot MEDIUM on the develop→staging promotion mirror #540, against #539 (backend#2220). Fixed on
develop, per the promotion-findings rule — nothing was pushed to #540.The regression
#539 made any non-
userRESOURCE_PROVENANCEstale, so an unchanged ceiling stopped returning early and fell through to the apply in order to re-stamp the marker asuser. Right intent, wrong landing site: the fall-through lands in the confirmation gate, and off a terminal that gate does not ask — it returns exit 1.That is a breaking change for scripted callers. The command's own
--helpdocuments0 applied (or nothing to change), anddocs/cli-navigation.mddraws theno changeedge going straight to exit 0, bypassing CONF entirely. Both became false. Nearly every installed edge still readsinstallerorunknown, so the blast radius is the installed base, not an edge case — and the callers that restate a size are scripts (the bootstrap, the end-to-end journey), none of which pass--yesfor what the docs promise is a no-op.The fix
One clause on the gate, not a revert:
The gate guards the ceiling. An unchanged ceiling has nothing to ask about — "Let each training run use up to 4 CPU · 16 GiB?" when the answer is already 4 CPU · 16 GiB is a question with one honest answer. #539's re-stamp still happens; the marker still flips to
user.The phantom-GPU fall-through (#241) has the same shape and is fixed by the same clause. Both are bookkeeping writes, already announced by their own
Infoflines above the gate, not budget changes an operator needs to sanction.Tests
TestSet_SameCeilingNeedsNoYes. The finding's sharpest point was that the regression is untested: every same-ceiling case already in the file passesyes: true— the flag under dispute — which is why nothing was red.resources setas a human choice (backend#2220) #539 as merged gives the re-stamp only to callers who pass--yes.RESOURCE_PROVENANCE=useroff the values file helm was actually handed (newfakeHelmValueshelper). The existing provenance assertions all go through--dry-run, and--dry-runskips the very gate at issue — so they cannot prove this path.cleanCanceland shell no helm).Five of the six sub-cases fail without the one-clause change — verified by reverting just that line:
The sixth ("a real change still needs
--yes") passes both ways by design — it is the guard, not the proof.Docs
docs/cli-navigation.md: theno changenode now says it may still re-stamp provenance or clear a phantom GPU, and never asks to confirm. That was already true of #539's behaviour, which shipped without updating the map. The--helpexit-code table needed no change —0 applied (or nothing to change)becomes true again.docs/troubleshooting.mddoes not listresources setunder exit 1, so it stays correct.Verification
go vet ./...clean ·gofmt -s -l+goimports -lclean over tracked files ·go test ./...all packages ok ·make lint(errcheck, ineffassign, misspell, staticcheck) clean ·make lint-full→0 issues.·make file-budget/make check-style/make check-tool-pinsok.Note for the reviewer:
make check'sfmt-checkstep flags three files under an untracked, stale nested git worktree (.claude/worktrees/practical-maxwell-4338c6/) left by an earlier local session. It is unrelated to this change and invisible to CI; I ran the fmt gate scoped togit ls-filesinstead, which is clean.🤖 Generated with Claude Code
Note
Medium Risk
Touches the
resources setconfirmation gate and helm apply path used by scripts. The change is a narrow skip for unchanged ceilings; actual budget changes still require confirmation.Overview
Restores the documented exit-0 path for
resources setwhen the per-run ceiling is unchanged. After #539, restating the current size (to re-stampRESOURCE_PROVENANCE=useror clear a phantom GPU) fell through into the confirmation gate and failed off a TTY without--yes, breaking scripted callers.The gate now also requires
!ceilingUnchanged. Bookkeeping helm applies still run; a real size change still refuses without--yesor a terminal.Tests cover installer/unknown/junk markers, phantom-GPU cleanup, a declining TTY prompter, and the guard that a real change still exits 1. The navigation map notes that the no-change path may re-stamp or clear GPU and never asks to confirm.
Reviewed by Cursor Bugbot for commit 24447b2. Bugbot is set up for automated code reviews on this repo. Configure here.