- Status: accepted · Date: 2026-08-25 · Deciders: Davor Runje
- Amended 2026-08-25: the decision as originally recorded rested on two
false premises about Dependabot’s capabilities — that it has no
pre-commitecosystem, and thatcooldownis unsupported forgithub-actions. Both were corrected the same day, against GitHub’sdependabot-options-referencedocs; see Decision and Rejected alternatives below.
Context
Dependency maintenance was manual: PR #78 bumped six tool pins and 21 locked versions by hand. The repo carries three independent version surfaces — the package’sdev/lint pins plus uv.lock, the action refs in
.github/workflows/**, and the remote hook rev: pins in
.pre-commit-config.yaml — and each drifts on its own schedule. The
codespell hook rev had already drifted from the lint group’s pin; PR #78
reconciled that specific drift by hand, but nothing stops it recurring, since
the == pin and the rev: pin are still bumped by two independent
automations (tracked as issue #79).
The package is a library installed beside a consumer’s own environment, so
[project.dependencies] are deliberately wide floors (typer>=0.12,
requests>=2.31, pyyaml>=6.0, pooch>=1.8). Raising them would narrow what
consumers can co-install for no benefit.
Decision drivers
- Automate the mechanical part without surrendering the review decision.
- Never narrow the runtime floors.
- Batch enough to stay reviewable on a solo-maintained repo; isolate the bumps that actually break things.
- Don’t review a release the same day it ships — yanked and compromised releases are usually caught within days.
- One pattern for Action-created PRs, not two (
bump-version.ymlalready established it).
Considered options
- Dependabot scoped to development dependencies, minors/patches grouped with
ruff+mypysplit out, majors ungrouped, a 7-day cooldown on all three ecosystems (uv,github-actions,pre-commit). No auto-merge. - Dependabot with
versioning-strategy: increaseacross all dependencies, floors included. - Ungrouped Dependabot — one PR per dependency.
- Patch-level auto-merge once CI is green.
- No Dependabot: a scheduled
uv lock --upgradeworkflow that opens a PR. - Dependabot for
uvandgithub-actionsonly, plus a scheduledpre-commit autoupdateGitHub Actions workflow to bump hook revs. This was the decision as originally recorded on 2026-08-25; it rested on the false premise that Dependabot lacks apre-commitecosystem, and was superseded the same day.
Decision
Option 1.- Scope:
allow: dependency-type: "development"on theuventry, so only thedev/lint==pins anduv.lockmove. The runtime floors are never rewritten. - Grouping: minors and patches are grouped;
ruffandmypyform their own group ahead of the catch-all. Plain semver misplaces the risk for this toolchain —ruffis 0.x andmypymajors move fast, so a minor bump (ruff 0.15.21 → 0.16.4) is the one that rewrites files or surfaces new errors repo-wide. Majors are excluded from every group and therefore arrive one PR at a time. - Cadence: weekly, Mondays 07:00 UTC, with
cooldown: default-days: 7on all three entries —uv,github-actions, andpre-commit.default-daysis supported forgithub-actions; only the semver-major/minor/patch-days sub-options are not, because those need a version-based ecosystem to classify a release as major/minor/patch, whichgithub-actionsrefs don’t have. - Hook revs: a third
.github/dependabot.ymlentry withpackage-ecosystem: "pre-commit"bumps therev:pins in.pre-commit-config.yamldirectly, on the same weekly cadence and cooldown as the other two ecosystems. No bespoke workflow is needed. - No auto-merge, of any update type.
mainis protected, merging is the maintainer’s action, and the agency principle says the human signs material decisions — a green tool bump is still a decision.
Consequences
- At most three or four dependency PRs a week, each reviewable as a unit, each through the full green gate.
- A formatter or type-checker change is never buried in a batch with type stubs.
- The runtime install surface stays as wide as authored; Dependabot cannot narrow it.
- A CVE fix published on a Tuesday waits up to a week on the version-update path. Security alerts are unaffected — this is a version-update policy.
codespellanddetect-secretsremain pinned in two places, now bumped by two independent Dependabot ecosystems (uvfor the==pin,pre-commitfor therev:); the durable fix (making thelintpins the single source) is tracked as issue #79.- Dependabot PRs deviate from the house
<area>/<slug>branch and commit-attribution conventions. Accepted: those govern human PRs.
Rejected alternatives
- Option 2 (floors included) — would rewrite
typer>=0.12to the latest release, narrowing consumer co-installation for no gain, and would need reverting on most PRs. - Option 3 (ungrouped) — maximum bisectability at roughly 6–10 PRs per cycle, each demanding the full gate. Too much review load for a solo-maintained repo.
- Option 4 (patch auto-merge) — even with a 100% coverage gate and strict
mypy, a green tool bump can change formatting or lint semantics. Landing it
in
mainunseen contradicts the agency principle for a saving measured in seconds. - Option 5 (
uv lock --upgradeworkflow) — hand-rolls what Dependabot’suvsupport already does and gives up per-dependency changelogs, compatibility scores, and security-update PRs. - Option 6 (scheduled
pre-commit autoupdateworkflow) — its one genuine advantage was real: because it ranpre-commit autoupdateand then the updated hooks,pyupgrade/whitespace autofixes landed in the same PR as the rev bump, which thepre-commitecosystem cannot do (Dependabot rewritesrev:pins; it does not run the hooks). It lost anyway — it duplicated a capability Dependabot already ships natively, requiredcontents: write(a broader permission than thepre-commitecosystem needs) to push commits forpeter-evans/create-pull-request@v7, and its pipedrunsteps were missingshell: bash, sopipefailwas never enabled: a hook failure exited 0 and the failure-honesty branch written to catch it was unreachable dead code. Superseded by thepre-commitecosystem entry the same day it shipped.
Links
.github/dependabot.yml (the grouping, scope, and cooldown policy this ADR
records, including the pre-commit ecosystem entry that bumps hook revs);
docs/superpowers/specs/2026-08-25-dependabot-design.md (the design this ADR
records); PR #78 (the manual dependency bump that motivated automating this);
issue #79 (the durable fix for the two-place codespell/detect-secrets
pin, tracked as a follow-up).