Skip to main content
Never ship a stale version. Never auto-merge a stranger’s major release. Minor and patch updates auto-merge for any package, ecosystem, or publisher once they clear a 3-day stabilization window and pass CI. Trust tiers no longer gate minor and patch updates. They only decide how reviewers handle a major update and how often Renovate opens PRs.
Every dryvist and JacobPEvans repo inherits one Renovate policy from dryvist/.github → renovate-presets.json. This master preset extends nothing external. The model uses a single global weekly schedule (the untrusted cadence) with per-tier overrides layered on top. SECURITY.md carries the same table from the security angle.

Trust tiers gate majors and cadence

Minor and patch updates auto-merge the same way in every scope in the preceding table. Any package or ecosystem qualifies, once it clears the scope’s minimum age and passes CI. Trust tier no longer decides whether minor or patch updates auto-merge. It only decides how reviewers handle a major update and how often Renovate creates PRs.

Why these tiers

Freshness first. The default is to move, not to freeze. Stale dependencies build their own risk: unpatched CVEs, drifting APIs, and harder upgrades later. Every scope auto-merges minor and patch updates the same way. The tier only decides how fast a PR opens and how reviewers handle a major update. A compatible-looking version is not always a compatible API for majors. Semver promises non-breaking minor and patch releases, and Renovate trusts that promise regardless of publisher. So minor and patch updates clear a 3-day soak plus green CI everywhere. A major update is a deliberate break, regardless of who published it. First-party majors auto-merge immediately because dryvist controls both ends of the API. A trusted-org major still opens a dep:review PR for a human. Every other major waits 30 days before a review PR opens. Trust buys review speed on majors, never a pass on breaking changes. The 3-day buffer is a supply chain tripwire. minimumReleaseAge: 3 days is the compromise-detection window. It applies to every external minor and patch auto-merge and to the trusted-org major review clock alike. The xz backdoor was caught within about 3 days of the malicious release. npm allows unpublish under 72 hours. Waiting three days lets Renovate skip a poisoned release before it lands. Under twice-weekly batching, the wait costs nothing extra. First-party and CVE fixes skip it (0 days). First-party code needs no soak, and a known-exploited CVE is more dangerous than an unvetted release.

First-party propagates immediately

Inside the org, release-please cuts and auto-merges every release in the source repo the moment its checks pass. Consumers pick it up with zero delay. Either the first-party tier (0-day, auto-merge all update types) bumps the pinned version. Or the consumer rides an @main reference and gets the change on its next run. No human sits in the propagation path for first-party code.

AI review is advisory, not the merge gate

Supply chain safety for the publisher-agnostic minor/patch lane comes from a deterministic gate, not an AI judgment call. actions/dependency-review-action runs inside the Merge Gate, a required, non-AI check on every public repo. It fails closed on vulnerable or disallowed transitive dependencies before anything merges. dryvist/ai-workflows → cc-dep-review.yml runs separately, under its own AI Merge Gate, on every Renovate/Dependabot PR. This is the inverse of the usual “skip dependency bots” rule. It is advisory only:
  • Claude reviews the diff and changelog with an injection-resistant prompt. The review is read-only and uses no secrets. Claude applies a low, medium, or high risk label.
  • The label informs human reviewers on majors and review PRs. It does not decide whether the minor/patch lane auto-merges, and it cannot override the deterministic Merge Gate.
  • The Merge Gate and the AI Merge Gate are always two distinct required checks on public repos. The AI signal never substitutes for the deterministic one.

Grouping and scheduling

Related updates batch into ecosystem groups (Terraform, AWS SDK, HuggingFace, OpenTelemetry, pytest, ESLint/TypeScript) plus a .nix version-pins group. One review then covers a coherent set instead of a PR per package. All trusted updates land in the same Monday/Thursday window, the same day and time across every repo. Renovate coordinates schedules, not cross-repo transactions. It cannot emit one PR spanning multiple repos, so each repo still gets its own PR in that shared window.

Nix flake locks are outside Renovate

flake.lock is the one file Renovate does not touch. Its nix manager is turned off org-wide. Each nix repo instead calls a shared workflow that runs a bare nix flake update. Every input in the lock moves together, onto one branch, as one pull request. Triggers are a weekly schedule, a repository_dispatch event when an upstream repo releases, and manual dispatch. All three amend the same pull request rather than opening a second. The reason is structural, not a preference. Renovate advances an input when the input’s reference changes. Nix repos pin nixpkgs to a moving channel branch, and that branch’s reference never changes; new commits simply land on the same branch. So Renovate has nothing to diff, and the locked revision would freeze permanently. Advancing it needs nix flake update, which in Renovate terms is lockFileMaintenance. That setting stays on for every other ecosystem. On nix it resolves to absolute-latest, ignores minimumReleaseAge, and once looped roughly 60 pull requests a week. Staleness here is expensive, not cosmetic. A pin that drifts off the Hydra-evaluated channel head loses binary-cache coverage and forces builds from source. The workflow reports that drift by comparing the locked revision against the published channel revision. The workflow withholds auto-merge on those pull requests whenever a nixpkgs* input moved, since a channel jump rebuilds the world on a machine configuration. A release bump of any other input still merges hands-off on green CI.

Version pinning

A uses: pin resolves its version tag automatically for Renovate and for anyone reading the diff. A non-uses: pin (a container digest, a downloaded binary, anything Renovate can’t infer the source of) needs an explicit hint comment instead: # renovate: datasource=... depName=... versioning=.... platformAutomerge stays false. GitHub’s merge queue has a known bug where a PR passes every check but the merge never executes, stalling for days. Renovate merges via its own API path with retry instead. The per-scanner rationale for the @main self-reference allowance lives in CI/CD policy → scanner posture.

Where to go next

CI/CD policy

Marketplace actions, release-please conventions, the scanner posture for @main self-references, the runner-label catalog.

ai-workflows

The reusable workflows behind the AI dependency reviewer and the App-token signing they use.