跳到正文
DEV Community· TECHDEV·· 2 小時前AI 評分53

TECHDEV 開發 diffgate CLI,以四項門檻檢查程式碼差異

My AI writes 400-line diffs in 30 seconds. I built a 2-second gate that reviews them.

AI 導讀

TECHDEV 開發 diffgate,一款零設定 CLI,針對程式碼差異設置四項檢查,並在 CI 回傳通過或失敗及原因。預設門檻包括複雜度 10、函數增量 +15、重複區塊 50 tokens,以及單檔增長 +500 lines;未修改的既有技術債不會觸發失敗。

正文

My AI pair programmer writes a 400-line diff in 30 seconds. I used to spend 20 minutes reviewing it: scroll, squint, guess whether that new function is "a bit complex" or "merge-blocking complex", wonder if the helper it added already exists somewhere else in the file. Tests pass. The diff looks plausible. Ship it.

A week later we find the duplicated retry logic in three places and a 14-branch function nobody remembers writing.

The bottleneck in AI-assisted coding is not writing code. It is reviewing diffs at the speed the model produces them. Eyeball review does not scale to model throughput, and "tests pass" says nothing about the shape of the code that was just added.

Gate the diff, not the repo

I built diffgate, a zero-config CLI that checks changed code only for complexity, duplication, and PR growth. It runs in CI in under a second and returns a verdict: pass or fail, with reasons.

Four gates, all scoped to the diff (v1):

Gate Default What it checks
complexity max 10 a touched function above the max fails
delta max +15 a function gaining more than this at once fails
dupe 50 tokens a normalized token block repeated in the diff fails
growth +500 lines a single file growing past this fails ("split this PR")

The point of scoping to the diff: pre-existing tech debt is context, never a failure. You do not get punished for the legacy function you did not touch. You get stopped when this PR makes things worse.

A real run

diffgate demo

A sample PR with three violations: a checkout function at complexity 13, a 106-token duplicated block in a Go file, and one JSON file growing by 622 lines. diffgate fails it with the exact locations. Fix the branch, re-run: PASS, all functions at complexity 5 or below. In CI it emits ::error annotations that land on the PR's Files tab:

diffgate check --base origin/main --format github
- run: npx -y diffgate-cli check --base ${{ github.event.pull_request.base.sha }} --format github

There is also a measure mode that prints numbers with no verdict, for the "measure first, gate later" crowd. A 500-file diff checks in about 0.7 seconds on a laptop. Zero runtime dependencies, Node 20+.

Method, stated honestly

Complexity is a token-based cyclomatic approximation: count branch keywords and operators (if, for, while, &&, ||, ??, ternaries, elif, except...) per function. Same class as lizard: fast and deterministic, not compiler-grade.

Duplication detection normalizes identifiers to id and literals to str/num, then finds repeated token windows with a rolling hash, so copy-paste with renamed variables still matches. Strings are blanked to a single str marker rather than nothing, which avoids mass false hits on fixtures full of string literals. I hand-computed complexity fixtures in JS, Python, and Go (all 5) and the tool agreed on all of them; the suite is 38 tests, all green.

What it is NOT

  • It does not prove correctness. Structural gates do not prove semantics.
  • It does not detect AI-generated code and makes no authorship claims. There is no snake-oil "AI detector" inside.
  • Complexity numbers are heuristic-class, not universal truths. Thresholds are team-tunable via flags or a diffgate.json in the repo root.

Where rivals beat us

Honest comparison, checked 2026-10-31:

  • unclebob/ub-mode wins on process depth: it guides the whole agent workflow (planning, review rounds, verification habits). diffgate is a 2-second CI check, not a workflow. Complementary, not competing.
  • SonarQube / SonarCloud wins on history: trend dashboards, leak-period tracking, and 30+ languages. diffgate sees one diff, three languages, no server.
  • lizard wins on language breadth (20+ languages) and editor integrations. It reports numbers; diffgate adds verdicts, PR gating, and annotations.
  • Semgrep wins on custom rules: you can encode your team's exact patterns. diffgate ships fixed gates with sane defaults, no rule authoring, no rule maintenance.

Install

git clone https://github.com/techdevfun/diffgate.git
cd diffgate
npm install && npm run build
npm link   # or run ./bin/diffgate directly

(The diffgate-cli npm package is being published; until the registry listing is live, install from source. The README will be updated the moment npm install -g diffgate-cli works.)

Then drop diffgate check into CI and let it argue with your pull requests. It is deterministic, local, and has no model, no account, and no network to phone home to.

Roadmap: new-lines-without-coverage when an lcov/cobertura file is supplied, more languages, and per-file growth budgets. Repo: github.com/techdevfun/diffgate. MIT licensed.

來源:DEV Community · dev.to