Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 55 additions & 4 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@
// re-proposing, every week, the exact bump this project has already decided
// against - and to make the reason travel with the proposal when there is one.
//
// This file does nothing on its own. Renovate only acts once the Renovate
// GitHub App is enabled for the repository (https://github.com/apps/renovate).
// Validated with `renovate-config-validator` before landing.
// The Renovate GitHub App was enabled on 2026-07-30 with "Automated PRs",
// "Require config file" and "Create onboarding PRs". Two consequences worth
// knowing: "Require config file" means Renovate does NOTHING, silently, if this
// file is absent or unparseable from the DEFAULT branch - so validate edits, and
// never let a broken config read as "no updates available". And onboarding PRs
// are moot while this file exists, since onboarding only fires with no config.
// Validate any edit with `renovate-config-validator` (run it from OUTSIDE the
// project root - a bare `npx` here fails with `EBADDEVENGINES`).
//
// `dependencyDashboardApproval` is deliberately NOT set. It would require ticking
// a box per update before a PR appears, which re-imposes scan-only behaviour at
// the config layer and would quietly defeat the app's "Automated PRs" setting.
// PRs are wanted; what is not wanted is anything MERGING unread - see `automerge`.
//
// THE pnpm INTERACTION, which is the subtle part.
// This workspace relies on pnpm 11's built-in release-age cooldown - there is no
Expand Down Expand Up @@ -44,9 +54,50 @@

dependencyDashboard: true,

// One weekly batch instead of a trickle. Times are UTC (no `timezone` set).
// Seattle. Without this the schedule below is UTC, i.e. "before 6am Monday"
// fires around midnight Sunday local - which reads as a bot that runs at
// random times.
timezone: "America/Los_Angeles",

// One weekly batch instead of a trickle. To pull a run forward without editing
// this, tick the "Check this box to trigger a request for Renovate to run
// again" checkbox on the dependency dashboard issue.
schedule: ["before 6am on monday"],

// Now that PRs actually arrive unattended, cap the burst. The first run after
// enabling the app sees every pending update at once; without a limit that is
// a dozen PRs in one morning, each triggering a ~4 minute CI run.
prConcurrentLimit: 3,
prHourlyLimit: 2,

// Renovate's `lockFileMaintenance` is automated `pnpm up` for the lockfile, and
// that is the one dependency operation this repo has measured as harmful:
// re-resolving the ~22 surrounding transitive packages triggered
// `TS2321: Excessive stack depth comparing types ... 'UserConfig'` in
// vite.config.ts, while installing the SAME target versions directly did not.
// CLAUDE.md's "prefer targeted `pnpm add` over `pnpm up`" is exactly this.
// Off by default; pinned off explicitly so it cannot get switched on as tidying.
lockFileMaintenance: { enabled: false },

// Security fixes must not wait for the weekly window. Without this block a CVE
// fix could sit ~10 days: up to 3 for the age floor, then up to 7 for Monday.
//
// NOTE THE AGE VALUE, which is not zero and must not be. pnpm 11 refuses
// anything younger than 24h without writing a `minimumReleaseAgeExclude:`
// bypass into pnpm-workspace.yaml, so a same-day security PR would reintroduce
// precisely the hazard the top-of-file comment exists to prevent. 25 hours
// clears pnpm's floor with an hour to spare and drops 3 days to ~1.
vulnerabilityAlerts: {
schedule: [],
minimumReleaseAge: "25 hours",
prBodyNotes: [
'Security update - this bypassed the weekly schedule deliberately. Still read it: `brace-expansion`\'s advisory carries a flat `<=5.0.7` range, so `pnpm audit` flags a version that already has the fix. "The audit is red" is not by itself a reason to take a bump here.',
],
},

// GitHub's own advisories miss ecosystem-only reports; OSV catches more.
osvVulnerabilityAlerts: true,

packageRules: [
{
// THE ONE THAT MATTERS MOST. Without it a bot proposes 6.0.3 -> 7.x every
Expand Down
24 changes: 21 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,27 @@ config, above pnpm's default, so Renovate can never propose a release pnpm would
want a bypass for. If `minimumReleaseAgeExclude:` appears in a bot PR's diff,
that PR is wrong; fix the age rule, don't commit the bypass.

Renovate is inert until the GitHub App is enabled on the repo. Validate any edit
with `renovate-config-validator` (run it from outside the project root - a bare
`npx` here fails with `EBADDEVENGINES`).
**The app is live as of 2026-07-30** - enabled with "Automated PRs", "Require
config file" and "Create onboarding PRs". So Renovate opens real PRs on its own
now; `automerge: false` is what keeps anything from _landing_ unread, and
`dependencyDashboardApproval` is deliberately unset because it would re-impose
scan-only behaviour at the config layer and defeat the app setting.

"Require config file" is the one with teeth: **a config that fails to parse makes
Renovate do nothing at all, silently**, which is indistinguishable from "no
updates available". Validate any edit with `renovate-config-validator` (run it
from outside the project root - a bare `npx` here fails with `EBADDEVENGINES`).

Two settings whose reasoning is not guessable from the outside:

- **`lockFileMaintenance` is pinned off.** It is automated `pnpm up` for the
lockfile - the one dependency operation measured as harmful here, since
transitive re-resolution is what triggered the `TS2321` pathology below.
- **`vulnerabilityAlerts.minimumReleaseAge` is `"25 hours"`, not `0`.** Security
fixes skip the weekly window, but they cannot skip pnpm's 24-hour floor: a
same-day PR would make pnpm write the `minimumReleaseAgeExclude:` bypass this
whole section exists to prevent. 25 hours clears pnpm and still drops the wait
from 3 days to ~1.

Branch protection on `main` is **not** configured. It is the natural follow-up
now that a check exists, but it is a repository setting rather than a file.
Expand Down