0:00AI coding agents generate pull requests faster than humans can review them, and the CI pipelines we built were designed for human pacing. 0:24Stack five single-purpose linters, a formatter and two scanners, and the pipeline becomes the bottleneck it was supposed to remove: minutes of execution, overlapping rule sets, and 0:41a wall of warnings that trains everyone to ignore the output โ or, worse, to disable the security checks so the build goes green.
The subject of this video is mokevnin/dev-quality-gates: not a tool, a curation โ an opinionated list of one recommended tool per job, chosen so each one can fail a build deterministically and hand the failure back in a form an agent can parse. The video walks it against a sample polyglot monorepo, the "OmniStack API".
tools.json file. Every tool it recommends is a live repository โ I checked each one named in the video.The velocity problem
0:11The argument's shape is worth stating plainly, because it inverts the usual "add more checks" advice. CI was built for a world where a human wrote the diff and a human read the report. 0:17When the diff is machine-written at machine speed, advisory tooling is worse than nothing: it produces volume without enforcement, and volume is exactly the resource that runs out first โ human attention.
0:44The failure the video describes is not "the linter missed a bug". It's that a build throwing hundreds of stylistic warnings next to one critical vulnerability gets ignored wholesale, and the team's response is to route around it โ disable checks, add ignores, force the merge. A gate that can be argued with is not a gate.
What a quality gate is, and the five rules
1:49The definition offered: a predefined, configurable checkpoint in the lifecycle that blocks a change from merging or deploying unless it meets measurable criteria. 2:02Around that the repo organises five principles, and all five are in the README as written โ this part of the video is accurate to the source:
| Principle | What it rules out |
|---|---|
| One tool per job | Two overlapping linters whose rule sets drift apart; several tools only when the jobs or environments genuinely differ |
| Enforcement over advice | Reports nobody reads: a tool must return a non-zero exit code on violation, or it doesn't count |
| Fast native toolchains first | A pile of single-purpose scripts where one Rust binary does lint + format + analysis |
| Agent-friendly | Interactive prompts and prose logs: output must be machine-readable, diagnostics clear, autofix where it's safe |
| Honest about gaps | Filling a category with an unverified or stale tool; an empty category is preferred |
2:16The "coverage over quantity" rule sits alongside them: a tool that replaces three narrow checks beats three narrow tools. 1:44And the video's own summary line is the thesis worth keeping: if you want to secure a supply chain at the speed of AI generation, abandon passive advice and build impassable deterministic constraints.
Agent-friendly output is the load-bearing idea
2:26Of the five principles, the one that is genuinely new relative to a 2019 CI article is the fourth. 2:43Human engineers read text logs; agents parse structured data. A diagnostic in JSON or SARIF, carrying a file, a line and a rule id, is a specification for the fix. Prose is not.
2:53That reframes what CI is for: not a dashboard for humans to consult, but a policy control interface that a machine calls and reacts to. The gate stops being a report and becomes a function whose return value the agent branches on.
TypeScript: Oxlint and oxfmt, and the exit-code trap
3:12For the TypeScript layer, the ESLint + Prettier pair collapses into Oxlint and oxfmt โ the Rust-native Oxc toolchain, 23,358โ , MIT, an ESLint-compatible linter plus a Prettier-compatible formatter in one binary. 3:28The video repeats the project's own performance claim (syntax analysis "often measured at 50 times faster" than the JavaScript equivalents) โ that is Oxc's benchmark of itself, not an independent measurement.
3:38Then comes the most practical minute in the video: by default Oxlint exits 0 on warnings, so a gate built naively around it lets non-compliant code straight through. 3:50The fix is a flag. I confirmed it in Oxc's CLI docs: --deny-warnings "ensure warnings produce a non-zero exit code", with --max-warnings=INT if you'd rather set a budget than a hard stop.
--deny-warnings, --strict, -D warnings, --check instead of --write. A quality gate is a property of your configuration, not of your tool list.One detail the video omits that matters for the machine-readability principle: Oxlint's --format accepts json, sarif, github, gitlab, junit and unix โ and also agent, a format aimed squarely at the audience this whole framework is written for.
Knip and the static-graph blind spot
3:54Next job: dependency bloat. Manifest scanners read package.json and stop there; Knip (12,621โ
, ISC) builds a full import graph across every workspace to find unused files, exports and dependencies.
4:29But a static graph only sees what it can resolve. A module reached through a string-built dynamic import(), an HTML template, or a string reference is invisible โ 4:41so Knip reports it as unused and fails your build on code that is very much alive. 4:50The remedy is explicit configuration: declare those dynamic entry points so the analyser knows to skip them.
5:00That yields the honest generalisation at the centre of the video: native static analysis gives speed and precision but no runtime context, and every blind spot must be paid for with an explicit configuration boundary โ otherwise the gate generates the exact developer friction it was meant to remove.
Python: Ruff, the type checker, and deptry
5:11The Python layer collapses Flake8, Black and isort into Ruff (50,715โ , MIT) โ linter and formatter, one Rust binary, one config. 5:36And then the boundary that trips people: Ruff "explicitly does not perform semantic static type checking", so a gate that stops at Ruff has no type safety at all.
5:44Here the video says a dedicated checker "such as Pyright or MyPy" is mandatory. The repository's own recommendation is narrower and more current: it lists ty (20,035โ
), Astral's Rust-native type checker โ not MyPy. Note that the repo is visibly still deciding: its curated README recommends ty while its own research note argues for Pyrefly and calls ty beta (0.0.91) and pyright "the more battle-tested alternative". A curated list that shows its own disagreement is more trustworthy than one that doesn't, but it also means the type-checker slot is not settled.
5:54Dependency hygiene goes to deptry (1,501โ
, MIT; the video's "dep-tree" is a mis-transcription of the name, and the project has migrated from fpgmaas/deptry to osprey-oss/deptry). 6:04The friction: libraries imported purely inside an if TYPE_CHECKING: block exist only for type hints, so deptry flags them as development dependencies used in production code. 6:21The fix is a per-rule exclusion in the project manifest โ again, an explicit configuration boundary.
6:32Which produces the video's most honest sentence: a 0% false-positive rate is impossible out of the box. Effective gates are built by teams who pre-emptively map their analysers' blind spots and configure around them โ not by teams who install more analysers.
The repository perimeter: Markdown and GitHub Actions
6:46A gate should cover the non-code parts of a repo too. 7:01Two entries: rumdl (1,630โ
, Rust, MIT โ a Markdown linter/formatter that reads markdownlint configuration, exits 1 on violations, and formats with rumdl fmt) and jactionlint (317โ
, MIT, Go, by jdx โ lints workflows, composite actions and dependabot.yml, with --fix and --online to pin tags to commit SHAs). The video's audio mangles both names ("rumdel MD", "jacksonlint"); the repos are the ones linked above.
7:14The principle this section demonstrates is the fifth one: honesty about gaps. Where an ecosystem has no mature native tool, the list keeps its established legacy tool rather than forcing a broken replacement โ Ruby, Java, .NET and Swift keep their standard toolchains, and the repo says so.
The remediation loop: what the gate is really for
7:30This is the payoff, and the reason the content belongs on an agents site rather than a linter blog. A passive toolchain leaves an agent in "limbo": it has to audit hallucinated dependencies, half-formatted imports and invented APIs by reading prose warnings. 7:48A gate that blocks the merge and returns a structured JSON payload turns that into a loop: non-zero exit โ parse โ locate file, line, rule โ rewrite โ push โ re-run.
8:02The agent never needs to ask a human what "warning: expected indentation" means; the deterministic exit code plus the machine-readable diagnostic is the instruction. 8:13Which redefines CI from "a test suite" into a self-correction engine โ and quietly reassigns the human: review stops being about formatting and becomes about whether the thing should exist at all.
8:32The video's impact claims here โ review time drops, defect density plummets, compute costs fall โ are stated without a number, a source or a measurement. Treat them as the framework's premise rather than as findings. 8:53What is true is the cost side of the same sentence: these gates are rigid and tunable, and the tuning is ongoing. 9:03A stale config is a gate that either blocks legitimate work or waves through what it was built to catch.
What the video leaves out โ and it's the best part
The video covers four ecosystems' worth of a list that contains 69 recommended entries, and skips the parts most useful to anyone actually adopting it:
- It's built to be applied by an agent. The README's own instruction is a prompt: "Apply https://github.com/mokevnin/dev-quality-gates to this repository. Read and follow docs/adopt.md. Show me the plan before you change anything." The agent inspects the project, picks only the entries that fit, wires hooks and CI, and proves each check can fail โ that last step is the one most "add linting" tasks skip.
- It lints your agent configuration. One entry, agnix, checks
CLAUDE.md,AGENTS.md,SKILL.md, hooks and MCP configs for Claude Code, Codex, Cursor, Copilot, OpenCode and Kiro, with--fixand--strict. If your agents are part of the pipeline, their instructions are part of the pipeline's input. - Cross-cutting categories the video never reaches: secrets (Betterleaks, Gitleaks-compatible rules, optional live credential validation), vulnerabilities (OSV-Scanner with call analysis), Dockerfiles (Hadolint), Terraform (TFLint), Kubernetes (Kubeconform), SQL migrations (squawk), policies in Rego (Conftest).
- The data is machine-readable too. The README is generated from
tools.json, which records each tool's review date, sources and limitations โ so an agent can read the list as data instead of scraping prose.
| Stack shown in the video | Gate | The flag that makes it a gate |
|---|---|---|
| TypeScript | Oxlint + oxfmt | --deny-warnings |
| TypeScript | tsc | tsc --noEmit with strict |
| TypeScript deps | Knip | fail on unused files/exports/deps |
| Python | Ruff | ruff check + ruff format --check |
| Python types | ty (repo) / Pyright-MyPy (video) | non-zero on any error |
| Python deps | deptry | per-rule exclusion for TYPE_CHECKING |
| Markdown | rumdl | rumdl check |
| GitHub Actions | jactionlint | exit 1 on workflow findings |
Use it or skip it
Use it as a map, exactly as the video suggests: one tool per job, chosen because it can fail a build and speak JSON, with explicit configuration for the blind spots you actually hit. The five principles are sound and apply whether or not you adopt a single entry from the list.
Don't treat it as an installation. The README says it outright: this is not a universal stack, do not install everything here. A new repo is 12 days old, the type-checker recommendation is visibly in flux, and every entry carries a "limits" note precisely because the authors know a gate you didn't configure is a gate that fires on the wrong thing.
And one thing worth copying whatever your stack: a gate is only real if you have watched it fail. That is the step the repo's adoption prompt forces and most CI migrations skip โ and it is the difference between a policy and a hope.
๐ฏ Key takeaways
- CI was built for human pacing. Machine-speed diffs make advisory linting worse than useless: volume without enforcement burns the one resource that runs out first.
- A gate is a non-zero exit code, not a report. Enforcement over advice is the repo's core rule, and it's a configuration property โ the tool list alone proves nothing.
- Oxlint exits 0 on warnings by default. Without
--deny-warnings(or--max-warnings) your TypeScript gate lets violations through; Oxc also offers a SARIF/JSON/agent output format. - One tool per job beats a stack of overlap. Oxc replaces ESLint + Prettier; Ruff replaces Flake8, Black and isort โ fewer configs, fewer contradictory rule sets.
- Static analysis has no runtime context. Knip misses string-built dynamic imports; deptry flags
TYPE_CHECKINGimports โ each blind spot costs an explicit exclusion until 0% false positives is unreachable out of the box. - Ruff is not a type checker. A Python gate needs a dedicated one, and the repo's pick is
ty(beta), not the Pyright/MyPy pair the video names. - Structured diagnostics close the agent loop. Non-zero exit + JSON/SARIF with file, line and rule turns CI into a self-correction engine and frees human review for architecture.
- The video covers a fraction of the list. 69 entries, including secrets (Betterleaks), vulnerabilities (OSV-Scanner), Dockerfile/Terraform/K8s checks, and agnix for
CLAUDE.md/AGENTS.md/SKILL.md. - The list is designed to be adopted by an agent. A prompt plus
docs/adopt.mdhas the agent pick what fits, wire CI and hooks, and prove each check can fail. - Curated means maintained, and maintained means in flux. CC0, 12 days old, README generated from
tools.jsonwith review dates โ read the review date before you trust an entry.
Claims checked
The repo is real. mokevnin/dev-quality-gates โ CC0-1.0, created 2026-10-23, pushed 2026-11-06, 317โ
, 18 forks, 2 open issues, 69 recommended entries, README generated from tools.json.
The five principles are the README's own. Opinionated (one tool per job), curated, coverage over quantity, fast native toolchains first, enforcement over advice, agent-friendly, honest about gaps.
Every tool named in the video exists. Oxc/Oxlint 23,358โ (MIT) ยท Knip 12,621โ (ISC) ยท Ruff 50,715โ (MIT) ยท deptry 1,501โ (MIT) ยท rumdl 1,630โ (Rust, MIT per its LICENSE file) ยท jactionlint 317โ (MIT, Go).
The exit-code flag. Oxc's CLI docs list --deny-warnings ("ensure warnings produce a non-zero exit code") and --max-warnings=INT, plus --format values including json, sarif and agent.
"Pyright or MyPy" is not the repo's pick. Its curated Python section recommends ty (Astral); its own research note prefers Pyrefly and describes ty as beta (0.0.91) with pyright as the conservative alternative. MyPy appears in neither as a recommendation.
The transcript's "Ox C" = Oxc (Oxlint + oxfmt); "dep-tree" = deptry; "rumdel MD" = rumdl; "jacksonlint" = jactionlint; "Seraph" = SARIF. The sample monorepo, "OmniStack API", is the video's own illustrative project, not part of the repo.
"50ร faster" and the impact claims. The speed figure is Oxc's own benchmark of itself. "Review time drops", "defect density plummets" and "compute costs fall" are stated in the video with no measurement, sample or source โ premise, not evidence.
๐ Sources & further reading
- mokevnin/dev-quality-gates โ the curated list (CC0-1.0)
- docs/adopt.md โ the agent adoption procedure ยท docs/patterns.md โ setup patterns
- oxc-project/oxc โ Oxlint and oxfmt ยท Oxlint CLI reference
- webpro-nl/knip โ unused files, exports, dependencies
- astral-sh/ruff ยท astral-sh/ty ยท osprey-oss/deptry
- rvben/rumdl ยท jdx/jactionlint
- agent-sh/agnix โ lints CLAUDE.md, AGENTS.md, SKILL.md and MCP configs
- Betterleaks ยท OSV-Scanner ยท Hadolint ยท TFLint ยท Kubeconform