AI 资讯
The rules were written down. Nobody followed them. Then CI went red on day one
My project's docs had rules. "One document, one responsibility." "Split anything over 45 lines." I wrote that. The day before yesterday. Here's how that was going. Folders with no README (no index): 25 out of 37 The folder holding our engineering rules: 11 files, zero index Documents breaking the 45-line rule: 47 Largest offender: 1,203 lines Writing a rule down does not make it a rule. Obvious, I know. But there is something about being handed a list of 47 documents where you personally broke your own rule that stops being funny halfway down. (The me of two days ago fully intended to follow it.) I rewrote the rules themselves, and the rules file hit 150 lines The plan was already clear: let a machine enforce this. Fail CI. Which meant writing the rules properly first. README required, folder layout, update obligations, what CI actually checks. By the time it was all in there, the rules file was over 150 lines. The rules file was breaking the 45-line rule. Now, if you say "well, the rules file is special, it gets an exemption" — what have you just done? You have created the precedent "the rules are exempt," and it is permanent from that day. From then on, every time someone crosses 45 lines, they get to say "the rules file does it too." And they're right. So I split it. Eight files, all under 45 lines. If I can't follow my own rule, the rule was never worth writing. The moment CI landed, 63 existing violations bared their teeth On to the real work: write the checker, wire it into CI. Run it, and of course: 63 violations Everything fails. All red. Files I'm about to touch and files nobody has opened in months, equally red. Humanity is offered two choices here. Fix all 63 first, then turn on CI (including the 1,203-line monster) Add an ignore list, silence the 63, move on Tempting, isn't it? Option 2. It was to me. A .lintignore with 63 lines in it and a comment saying "remove later." So when exactly are you removing that list? Think about what that file actually is.
AI 资讯
Claude vs Gemini Across 4 Security Domains: A Dead Heat — and the Hardening 63% of AI Code Skips
The interesting result isn't who won. It's that across four security domains, Claude and Gemini missed the same hardening steps — and if you've shipped AI-generated auth middleware this year, your code almost certainly has the same gaps, and your review didn't catch them either. For the record, the scoreboard: one Gemini win, two ties, one split — a statistical dead heat. That's the last time the winner matters in this article. Here's the number that should bother you more than any leaderboard: across 700 AI-generated functions scored by the rules I'm about to use, 63% shipped a vulnerability . So "which model writes more secure code?" is mostly the wrong question — I've run that leaderboard myself and argued it's the wrong frame. But people keep asking it, so I ran it properly — on the ESLint security plugins I wrote specifically to catch these bugs, each mapped to a CWE — to show you what actually matters. The setup Four domains, four of my plugins. For each, the same feature-only prompt (no "make it secure" hint — that's how people actually use these tools), generated once by Gemini 2.5 Flash via the Gemini CLI and once by Claude Sonnet 4.6 via the Claude CLI , then linted with the domain's plugin on recommended . Method honesty: this is Gemini Flash vs Claude Sonnet — the comparable price/latency tier each vendor's CLI defaults to (Pro and Opus are a separate bracket; more on that below). It compares CLI tooling, system prompt included, not raw models under controlled decoding. n=1 per domain — but I re-ran the JWT round, and both models landed on 5 findings again with the same core misses, so treat these as directional with stable failure modes, not ±0 gospel. The scorecard Domain Prompt Plugin Gemini Claude NestJS service users + auth + admin nestjs-security 2 6 JWT auth login + verify middleware jwt 5 5 MongoDB data layer Mongoose model + search mongodb-security 8 8 General API (injection) import + search + reset secure-coding 9 13* One Gemini win, two dead h
AI 资讯
The Bug That Passes Every Toolchain Check: Circular Dependencies in JavaScript
A circular dependency is one of the few bugs that passes every check your toolchain runs. TypeScript compiles it cleanly. The tests pass. The build succeeds. The app ships. And somewhere deep in your import graph, a developer is staring at a TypeError: X is not a constructor that disappears the moment they add a console.log . Here are the three patterns that create them, what Node.js, webpack, Rollup, and esbuild actually do with them — they don't solve the problem, they each make a different tradeoff — and how to stop them from forming. What a circular dependency actually is A circular dependency exists when module A imports from module B, which imports — directly or transitively — from module A. // user.service.ts import { formatUser } from ' ./user.utils ' ; // user.utils.ts import { UserService } from ' ./user.service ' ; // ← closes the loop Neither developer planned this. user.service.ts needed a formatter. user.utils.ts needed the service type for a helper added three sprints later. Nobody saw the cycle form — they just saw two reasonable imports. This is how every circular dependency is born: through incremental, individually sensible decisions. The 3 patterns that create them 1. Barrel files ( index.ts re-exports) Barrel files are the biggest source of accidental cycles in TypeScript projects. // features/user/index.ts — re-exports everything in the feature export { UserService } from ' ./user.service ' ; export { UserRepository } from ' ./user.repository ' ; export { UserController } from ' ./user.controller ' ; export { formatUser , validateUser } from ' ./user.utils ' ; Now every file in the user feature imports from ../user (the barrel) for cleaner paths. And any utility the barrel re-exports cannot safely import anything else from the barrel without creating a cycle. // user.utils.ts import { UserService } from ' ../user ' ; // ← imports the barrel // The barrel re-exports user.utils → user.utils imports the barrel → cycle Teams adopt barrel files for