minimumReleaseAge on a package rule was declared on PackageRule, resolved into ResolvedEffects, validated by config-validation, and converted from Renovate's prose durations by the migration.
Nothing ever read the resolved value. Both age gates consulted the global setting alone:
src/buddy.ts:1927 this.config.packages?.minimumReleaseAge ?? 0
src/registry/registry-client.ts:1725 this.config?.packages?.minimumReleaseAge ?? 0So this, straight out of docs/advanced/scheduling.md:67, did nothing at all:
{
// Framework upgrades wait a week after publication.
matchPackages: ['react', 'react-dom', 'next'],
minimumReleaseAge: 10080,
}Two things kept it inert
- The filter returned early whenever the global age was zero — so a rule-only hold never reached a check.
meetsMinimumReleaseAgetook no override — so even reaching it would have measured against the global.
The filter now resolves effects per update and passes the required age down, returning early only when neither the global nor any rule asks for a hold. Overriding downward works too: a repo holding everything for a week can still let its own packages through with minimumReleaseAge: 0.
The shape worth naming
A rule pairing a hold with autoMerge:
{ matchPackages: ['react'], minimumReleaseAge: 10080, autoMerge: true }Only the auto-merge half was ever read. "Hold this for a week, then merge it without review" was proposing and auto-merging versions published minutes earlier — a supply-chain cooling-off control that reported itself as configured, validated cleanly, and was reported as migrated by the Renovate importer.
There's a test for exactly that pairing.
Why it survived
The ordering made it doubly dead: the age filter runs at buddy.ts:233, applyPackageRules at :246. No amount of rule resolution downstream could have reached it.
Existing tests covered the global filter and the Renovate conversion — neither asserted application.
Tests
2072 → 2080. No docs change needed: scheduling.md already described this behaviour correctly. It just never happened.
Lint ✓ · typecheck ✓ · check:docs ✓ · 2080 pass / 0 fail
🤖 Generated with Claude Code