Repository navigation
Hold back what the package manager's minimum release age holds back - #14
Merged
Merged
Conversation
…ing else The plan is to ask pnpm and yarn for their minimum release age the way update.mjs runs them, so managerCommand moves into scripts/manager.mjs for both to import. The structural tests failed any relative import and any script SKILL.md doesn't name. A script another script imports now counts as reachable, and ./manager.mjs is the one relative import allowed, so the scripts still need no install and no dependencies. On a copy with the move made, the old tests failed and these pass, and a stray script or another relative import still fails them.
…n share The plan is about to ask pnpm and yarn for their minimum release age the way ng update asks them, so it has to find them the way update.mjs does: through npm_execpath, Corepack, or a shim read without a shell. managerCommand moves to scripts/manager.mjs unchanged, and update.mjs imports it.
…g update does From Angular CLI 22.1, ng update skips a release younger than the package manager's minimum release age without a word, and in M7's run the plan called Angular 22 reachable with the team's 22.0.0 minutes old. The plan now asks pnpm and yarn the way ng update asks them, reads npm's before and min-release-age and bun's bunfig.toml, and reports the answer as releaseAge, or under Could not check when the manager can't be asked. It asks with pnpm_config_pm_on_fail=ignore and Corepack offline, since pnpm 12.16.1's --version wrote the lockfile of a project that pins pnpm, and drops the person's own spelling of those names, which on Windows would win. The pnpm workspace test that runs the plan directly gets the fake manager, so no real pnpm runs.
…r, and name the younger one Every manager's install and, from Angular CLI 22.1, ng update treat a release younger than the minimum release age as not out yet, so a pick that ignored the age printed a command that failed. Libraries, siblings, followers, tooling that follows Angular's major and Angular itself now come from releases old enough; a younger one passed over is named with when it's old enough, and a release with no publish time counts as old enough, as ng update and pnpm count it. The installed release is never held back, since the lockfile has it. Below CLI 22.1, where ng update takes Angular's newest whatever its age, the command names the newest core and CLI old enough.
…il a time, with how to go sooner In M7 the plan called Angular 22 reachable while the team's 22.0.0 was minutes old, and ng update skipped it, so the Run: line failed. When nothing old enough fits, the plan now works the major out as it will stand once the first fitting release is old enough, gives it every check a runnable major gets, and puts it in plan.waiting with a too-young blocker per release, exit 2 and no Run: line, since plan.hops means runnable. It gives the time, which npm's before doesn't have, and the command for going sooner once the person approves an exemption: --install-first where ng update skips young releases itself, the command as it is where only the install does, and none when Angular itself or a library with migrations is young. A library held back only by age is upgraded already, so it gets no note to upgrade it first. On a --next hop the CLI's prerelease can be the young one, so core and the CLI are each held on their own times.
On a --next hop the CLI's prerelease can come out hours after core's, as CLI 22.1.0 did after core 22.1.0. Holding the hop on core's times there gave a wait that had already ended, so the test checks the waiting major names the CLI and when it's old enough.
…d name the younger one Already on the target major, the plan offered the newest patch however young, and the package manager's install then refused it, or on pnpm under its default age let it in by writing an exemption nobody approved. It now offers the newest patch old enough for the manager and names a younger one with when it's old enough, or lists it alone under patchesHeld when nothing newer is old enough yet.
…releases it passes over An agent acts on the printed plan, and a waiting major printed as a blocked one with no time reads as something to fix or force. The result now says until when the project stays where it is, or that npm's before has to move, and the waiting major prints after the runnable ones with a From line for that time and a Sooner or No sooner way line in place of Run:. Each line that passes over a younger release, Angular's own in a hop's header, a library's and a patch's, says which and until when, for pnpm or yarn and for ng update too where it skips young releases itself.
…g on young releases In M7 the plan called Angular 22 reachable with the team's 22.0.0 minutes old, and ng update from CLI 22.1 skipped it without a word. The plan now prints such a major as waiting until a time, with no Run: line, and a Sooner command for once the person approves an exemption. Going early relaxes a guard against a compromised release, so the skill goes as far as the major before and asks, even for the team's own library, and blocked.md gives each manager's exemption setting. An exemption already committed that covers the releases counts as that approval given before.
… back by its age The section only covered pnpm and yarn, and told the agent to run a Run: line that a waiting major no longer has. npm's min-release-age or before stops its install with ETARGET, and ng update, which reads only before, then fails at Installing packages with node_modules deleted. bun's minimumReleaseAge stops it with blocked by minimum-release-age. pnpm 12.16.1 refuses with ERR_PNPM_NO_MATURE_MATCHING_VERSION once the team sets the age itself, which makes it strict, so step 4e now says pnpm add writes the exemption only under the default age, and an install into an empty node_modules fails with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION when the lockfile holds a young release nothing exempts. ng update never says it skipped a release, and exits 0 when the old release's peers raise no error, so the section says to check package.json.
Its name said yarn 4.15 and newer hold a release back and yarn before 4.10 doesn't, cut-offs nobody checked here. The test runs yarn 4.18.1, which printed 1440 with nothing set, and 4.9.4, which doesn't know npmMinimalAgeGate, so the name says that.
…g a hop pnpm 12.16.1 reads pm-on-fail only under the pnpm_config_ name, so update.mjs's npm_config_pm_on_fail=error never reached it. In a project that pins pnpm, with no record of that pin in pnpm-lock.yaml, ng update's own pnpm list and the installs wrote packageManagerDependencies into the lockfile. With a devEngines pin, ng update then stopped every hop at its own clean check, and the retry was refused as not clean.
…while its new major is too young Whether angular-eslint declares Angular peers was read from the releases old enough. With the new major's releases young, that fell back to the whole history, found the @angular/cli peer older releases had, and sent the package down the library path, where a peerless young release judged as no support. So the major read as blocked by angular-eslint, with the text troubleshooting.md calls a planner error, instead of noting the release is too young until a time. Those packages' X.0.0 came out 3 to 9 days after Angular's.
… core Only core's publish time could hold Angular back on a stable hop, and the CLI comes out after core: 30 minutes later at 22.0.0, 3 hours 41 at 22.2.0. So once a new major's core was old enough the plan called the hop ready and printed a Run: line, while ng update gave the young CLI no target and failed on @angular/build's peers, and a waiting major's time was core's, early by that gap. With an age set, the plan now reads the CLI's full document, about 3.4 MB, and holds the CLI on every hop the way it did on --next.
"No sooner way: Angular N itself is too young until then" took then from the From line, which a later library's release can set. Angular itself is old enough sooner, and from then a library can be exempted and installed first, so the line was wrong in between.
"Nothing to upgrade until" took the latest of the held patches' times. Each patch is an upgrade on its own, and the CLI comes out after core, by 3 hours 41 at 22.2.0, so the headline could overstate the wait by hours.
…bling's move passes over Only a library's first pick named a newer release too young to take, and when it's old enough. Tooling that follows Angular's major, a follower moving with its peer, and a library a sibling made move took the newest release old enough and said nothing, though ng update would take the newer one once it's old enough. The sibling pass now names it against its own pick, and keeps nothing when that pick is itself too young.
… on as a before, as a wait with a time Those npms turn min-release-age into a before that many days back as they load, and 11.10 to 11.13 list it in min-release-age's place. So the plan said the major waits on npm's before, with no time, until that setting moves, for a setting the project never set and that moves by itself. Node 24.14.1 to 24.17.0 bundle npm 11.11 to 11.13. ng update reads that before too, so the plan now says it skips the release as well.
…ude, and exempt a package on npm and bun npm 11.10 to 11.16 apply min-release-age, and npm 10 applies before, but only npm 11.17 added min-release-age-exclude. On those, the plan offered a Sooner command after an exemption npm only warns about as an unknown setting, so the command still failed at install. Node 24.18 bundles npm 11.16. The line also named a release, while npm's and bun's exclusions take a package and let every release of it through, which is what the person approves.
…ain once dependencies are installed The reason was cut at 80 characters, mid-URL for Corepack's offline error, and quoted update.mjs's advice to run the printed command when pnpm wasn't found. The entry sits under a header that says to check things in the running app, which can't check an age, and nothing sent the agent back to plan after step 3's install fetched the pnpm the project pins, so the first plan's Run: line could fail on a young release.
… its place, so it proves the keep Since the major's wait went in, later() picks a young installed release straight back from the whole document, so the test passed with the keep in aged() removed. An installed release that came out after a higher one, as a backport does, now fails without the keep and passes with it.
A review reverted the new release-age code one piece at a time, and these passed every test: the wait taking the first held time instead of the last, the blocker's ng update clause, an answer that isn't a version, yarn's units, a failed question counting as could-not-check, and the Corepack controls. In M7 ui-forms came out 0.6 s after ui-core, and the fixture now does too, so the first and last times differ.
…hen release age went unchecked The skill's waiting-major bullet matched only waiting until, and said a No sooner way line meant only waiting gets past it, which is wrong under npm's before, where only moving that setting does. It also called the From line what the plan will print as Run: then, though a newer release can be old enough by then. When the plan couldn't ask pnpm or yarn, as before step 3's install fetches the pinned one, nothing sent the agent back to plan, so a major it called reachable could fail on a young release. blocked.md now gives every reason the plan prints for no sooner way.
…e, and quote ng update's npm failure pnpm 12.16.1 failed with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION with node_modules present too, frozen or not, so the narrower wording let an agent think a local install was fine. On npm, ng update with min-release-age alone prints Installing packages [FAILED: Unable to install packages] and Restored package.json to its original state., not npm's ETARGET, which is what an agent will search for. npm 11.10 to 11.14 hand min-release-age to ng update as a before.
…me from The plan asks the project's own pnpm or yarn for its age now, which its header didn't say. The age rules copy Angular CLI's parser, so the comment names the CLI they were read from, 22.2.6, and the first pnpm and yarn majors whose unset age is a day sit in one place instead of two.
… stands in for npm 11.16 The shortcut said 2 minutes 39 with no unit for the last number. The npm 11.17 test sets npm-version in the project's .npmrc, which its comment didn't explain, while the test before it does.
…npm test can't override it The two tests that stand in for npm 11.13 and 11.16 set npm-version in the project's .npmrc. npm sets npm_config_npm_version for the scripts it runs, so under npm test the running npm's own version beat the .npmrc and both tests failed, though they passed under node --test. The environment beats the .npmrc on npm 11.19.0 and 10.9.10.
…s and runs nothing from the repo A security review of 0fd0ae5 found the plan ran pnpm or yarn in the project to ask for the minimum release age, and a yarn repo's yarnPath release or plugin is code the repo commits. The plan now reads those settings from pnpm-workspace.yaml, .yarnrc.yml, their global files and the environment, and asks an installed pnpm or yarn only for its version, from an empty temporary folder, when nothing pins it.
…nd runs nothing from the repo The plan no longer starts pnpm or yarn in the project, since a yarn repo's yarnPath release or plugin is code the repo commits. A pinned manager's version now comes from the pin, so step 3 no longer says the install fetches the pinned one: only a pnpm or yarn whose version the plan couldn't learn leaves release age unchecked. What ng update asks the manager stays as it was.
…s' minutes-old release The plan now reads pnpm's minimum release age from pnpm-workspace.yaml and takes pnpm's version from the portal's packageManager pin, so it no longer calls Angular 22 clear while the libraries' 22.0.0 is minutes old. The agent runs the plan's command that installs them first. The start-over note now says only their peer ranges stop blocking, since a run within a day of the last one is still waiting.
…plan's own, and Node's compile cache off
…, which npm 11 refuses without --force
…un, not a pin, and a packageManager above it first, as Corepack does
…'s log and cache go
…epack does when nothing sets packageManager
…age.json pin, so a stray one above the home folder can't choose its version
…and what to do, instead of waiting for pnpm or yarn to be installed
…aming where it's set, instead of crashing the plan
…refuses or passes over, as the probes printed them
… from pnpm 12, since 11.28.11 matched it as written
…in a file indented as a whole, and leave a line the plan can't read unknown, not refused
… sets any key twice, not only minimumReleaseAge
… no XDG_CONFIG_HOME, which no test reached
…* and **, as pnpm 12.16.1 did
…he person's own, outside the repo, not only that the repo's never ran
…he plan can't read
…, since the relative-PATH test's PATH has no dirname on Linux and macOS
…g.yaml with a Set, since comparing each key with every other stalled the plan for 33 s over 100,000 keys
…with spaces or tabs only, since a run of blank lines before another line stalled the plan for 24 s
…olders have on disk, as fs.realpath.native gives them, whatever the spelling the plan was run with
… one, or "" with a value below it, which every pnpm and yarn command failed on, instead of reading the age
…ull and NULL, compare 2^64 - 1 as a BigInt, and leave 1_440 or an escape in double quotes unknown
…dn't be asked, and ask the person when the reason names a file, a value, the home folder or a manager in the repo
…in a too-long age, and read a quoted key while leaving two lines below a key and an ignorePath the plan can't read unknown
…e registry dates one so late that the age ends past the year 9999, instead of crashing or printing a garbled time
…stry gives as a list stopped the plan with a TypeError
…what the reviews left
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.
Summary
In M7 the plan called Angular 22 reachable while the team's libraries' 22.0.0 was minutes old, and
ng updaterefused them. The plan now reads the package manager's minimum release age and holds back what it holds back. It reads pnpm's and yarn's settings from their files and the environment, and runs nothing from the repo.minimumReleaseAge, yarn'snpmMinimalAgeGate, npm'sbeforeandmin-release-age, and bun'sminimumReleaseAge. It picks the newest release that's old enough, for Angular's own packages too, and names a younger one it passed over. A major that only waits getswaiting untila time and noRun:line, with aSoonercommand for the person to approve, or the reason there's no sooner way.packageManager, an exactdevEnginesversion or theyarnPathfile's name, and adevEnginesrange only limits which version may answer, as Corepack 0.35.0 reads it. Only a manager nothing pins is asked, only for--version, from an empty folder the plan makes in the home folder and removes, with Corepack reading no pin and using no network. A pnpm, yarn or npm found inside the repo never runs. Folders are compared by identity, so a junction or a short name doesn't get past that.--force, since npm 11 refusesconfigandviewin a project whosedevEnginesnames another manager.update.mjsruns every command withpnpm_config_pm_on_fail=ignore. pnpm 12.16.1 reads that setting only under that name, and in a pinned projectng update's ownpnpm listand the installs wrotepackageManagerDependenciesinto the lockfile, which then stopped every hop atng update's clean check.bunfig.tomland pnpm 10.npmrcreaders no longer slow down on long runs of blank lines or many keys. An older.npmrcpattern that still does is in M8.SKILL.md,blocked.md,troubleshooting.md,libraries.md,SECURITY.mdand the enterprise example say what the plan reads and runs, and where, what to do with a waiting major, and when to plan again or ask the person.min-release-age.Checked
npm teston Windows (Node 24.20.0, npm 11.19.0): 356 tests, 347 pass, 9 skipped (the 8 evals-login tests and the POSIX-only pnpm 12 updater test).plan.test.mjsalone: 213 of 213.plan.test.mjson Linux, in Dockernode:22.23.4-bookwormwith no network, at 6fbb751, before the last one-line fix: 209 pass, 4 skipped (the 3 Windows-only tests, and npm'smin-release-agetest, since npm 10.9.9 doesn't have it).plan.mjsthat the new test caught.dirname, would have failed the Linux and macOS test jobs.test/smoke.test.mjs("the server is stopped afterwards"), which this branch doesn't touch, and passed on the rerun.