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 adep: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.