Repository navigation
fix(direct-upgrade): a declaration that admits the fix gets the in-range refresh, not a bump (E8 follow-up) - #993
Merged
Merged
Conversation
…nge refresh, not a bump (E8 follow-up) Live 2026-10-18 (navcal): sharp, next and vite were told to `npm install "x@^v"` though their `^` range already admitted the fix target. When the declared range admits the target, the minimal correct advice is the tool's in-range lockfile refresh, which leaves the manifest as it is. Each form was run on 2026-10-18 against a project declaring `ms ^2.1.1` locked at 2.1.1; each moved the lock to 2.1.3 with package.json unchanged: - npm 10.9.2: `npm update ms` - pnpm 10.34.6: `pnpm update ms --no-save` (plain `pnpm update ms` rewrote the range to `^2.1.3`); also inside a workspace member, where only that member's importer moved - yarn 1.22.22: `yarn upgrade ms`; yarn 4.9.1: `yarn up -R ms` - cargo 1.97: `cargo update -p itoa --precise 1.0.11` on `itoa = "1.0.5"`, Cargo.toml unchanged DirectFix gains Refresh. The plan reads "Fixable now with a lockfile refresh (the declared range already admits the fix)" when every fix is one; in a mixed row a refresh says what it is. The Brief reads "bump x to >= v: within its declared range, run `npm update x`". Any readable range qualifies (a `>=` range carries no operator but admits the target). Yarn workspace members, Cargo workspace/git/path/registry entries keep their existing declines. Vectors: fc-054..fc-059 (refresh: true). fc-029..035 and fc-037..041 had in-range targets; they move outside the declared range (sources say so) to keep pinning the operator-keeping install. fc-036 keeps its decline purpose with `1.x` -> 2.0.0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KSXWNneouUjTiVV3Rc3FH
…efresh (fc-060) pr-001: express is declared ^4.13.4, which already admits 4.22.3, so the lever's command is `npm update express` (fc-054's rule), not an install that rewrites the declaration. fc-060: an npm workspace member's in-range refresh runs in the member's directory; npm 10.9.2 moved the member's copy both hoisted and nested, declaration unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KSXWNneouUjTiVV3Rc3FH
… in-range refresh lever_command and the decide-mode vector helper matched only DirectFix::Command (the helper with a `_ => None` wildcard), so the new DirectFix::Refresh dropped out and pr-001's lever named nothing. Both are now exhaustive: a lever declared ^4.13.4 moving to 4.22.3 names `npm update express`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KSXWNneouUjTiVV3Rc3FH
…ases; refresh only a bounded range; refresh wording only when every direct site refreshes - B1: fc-029..035 and fc-037..041 had been moved to releases that do not exist (minimist 2.0.1, ms 2.2.0, serde 2.0.0, ...). They now use REAL targets, with the declaration chosen so the target is out of range, and each command was re-run against the real tool on 2026-10-18; each vector's source is that run (npm 10.9.2 --package-lock-only, pnpm 10.34.6, yarn 1.22.22, yarn 4.9.1, cargo 1.97). npm wrote ^8.0.7 for `npm install "@babel/traverse@^8.0.0"` (the resolved release), so fc-031 says so. fc-036 is `0.2.x` -> 1.2.8 (a rule, no run). fc-058 cites the exact command text it ran. - S3: only a range bounded below the next major (`^`, `~`, or a Cargo requirement) is refreshed: a refresh installs the NEWEST release in range, so `>=` / `||` / `*` / x-ranges could jump a major or land on a withdrawn or held release. fc-059 (`>=1.2.0`) names nothing. - S2: the refresh wording applies only when every direct site of the row got a refresh; a site whose fix could not be named keeps "bump". - S4: the Brief/plan parity test covers the exact pin (install) and the tilde (refresh) again. - S5: the npm and Cargo arms are their own functions. S6: the module doc says which ranges refresh. - fc-061: the pnpm workspace-member refresh (run 2026-10-18). The twin plan test's skip message names itself. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015KSXWNneouUjTiVV3Rc3FH
runyourempire
force-pushed
the
fix/c2-direct-refresh
branch
from
October 18, 2026 14:18
8bfc43a to
cf314dc
Compare
runyourempire
enabled auto-merge
October 18, 2026 14:19
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.
What
This answers recovery-lead's live-check finding (2) on the rebuilt operator app. In navcal, the direct rows for sharp, next and vite told the user to
npm install "pkg@^x", although each declared^range already admitted the fix target.When the declared range admits the target, the minimal correct advice is the tool's in-range lockfile refresh, which leaves the manifest as it is. An install command is kept only when the range excludes the target.
Every form was run against the real tool (2026-10-18)
The project declared
ms ^2.1.1with the lock at 2.1.1. Each command moved the lock to 2.1.3, and package.json was unchanged:npm update mspnpm update ms --no-savepnpm update msrewrote^2.1.1to^2.1.3. Also inside a workspace member, where only that member's importer movedyarn upgrade msyarn up -R mscargo update -p itoa@1.0.5 --precise 1.0.11itoa = "1.0.5"; Cargo.toml unchangedHow
DirectFixgains aRefresh(String)variant.direct_fixchecks that the declaration admits the installed copy, as before. If it also admits the target, it returns the refresh. Any readable range qualifies: a>=range carries no operator, but it admits the target.workspace = true, git, path and registry entries.npm update sharp" when every fix is a refresh. In a mixed row, the refresh is labelled "(a lockfile refresh: the declared range already admits it)".npm update sharp" (DirectFix::brief_clause).lever_commandand the decide-mode vector helper both coverRefresh, and both matches are now exhaustive (the helper had a_ => Nonethat silently dropped it). A lever declared^4.13.4moving to 4.22.3 namesnpm update express.Vectors
refresh: true:fix_commandfc-054 to fc-058: npm, pnpm, yarn 1, yarn berry and cargo, one line each;>=range;1.x→ 2.0.0.parent_releasepr-001: now expectsnpm update express. The rule text says why. pr-002..004 declare exact versions and keep their installs.Checks
cargo clippy --locked -- -D warnings: clean.osv::,brief,evidence::,morning_andpreemption: 914 passed, including the vector gate, rebased on main d63fd7c.>=range;~1.2.5, which names the refresh;🤖 Generated with Claude Code
https://claude.ai/code/session_015KSXWNneouUjTiVV3Rc3FH