AI 资讯
Gemini 3.7 Flash: Coding Speed Breakthrough
This week's tooling landscape is defined by two themes: cost compression on capable models and protocol-level standardization across agent runtimes. Gemini 3.7 Flash cuts inference spend while measurably improving first-pass code accuracy, and the AI SDK's ACP harness layer is quietly making multi-agent wiring less of a bespoke nightmare. Here's what's worth your attention. Gemini 3.7 Flash launches with coding performance gains Gemini 3.7 Flash ships at half the cost of 3.6 Flash with benchmark improvements that actually map to real workloads: FrontierCode jumps from 34.4% to 43.6%, and document reasoning on GDP.pdf goes from 22.0% to 34.0%. These aren't marginal deltas—a 9-point gain on code generation means materially fewer retries in agentic pipelines where each failed generation compounds latency and cost. For teams running Flash in production for code generation or document extraction, the math is straightforward: same API surface, half the token cost, better first-pass accuracy. Introductory pricing holds through year-end, so the window to lock in the savings is finite. Verdict: Ship. Drop-in swap via the Gemini API—no config changes required. If you're already on Flash for coding or document processing workloads, migrate now. The performance gains on code generation are large enough to reduce retry loops in multi-step planning tasks, which compounds into real infrastructure savings at scale. GLM 5.2 free for eve agents through August 27 Z.ai's GLM 5.2 is a 1M-token open-weights model now set as the default on eve agents, with free access through Vercel's AI Gateway until August 27. The 1M context window is the practical differentiator here—it's large enough to hold entire codebases in context for generation tasks that would otherwise require chunking or retrieval. The cost is zero during the trial window, and the integration is a one-line config change: set model: "zai/glm-5.2" in agent/agent.ts or run eve set --model zai/glm-5.2 . That's a trivially low bar
AI 资讯
We Invented a Layered Wiki Pattern on Top of Graphify — Here's the Concept and How to Approximate It Today
"Graphify turns codebases into queryable knowledge graphs. We designed a layered monorepo wiki extension — per-layer .graphify/ folders with staleness hooks — that doesn't exist yet. Here's the full spec and how to get 90% of it right now." Transparency note: This post describes a design pattern we invented on top of graphify , an existing open-source tool. The core tool is real. The layered wiki structure and .graphify/ folder convention described here are not official graphify features — they are a proposal. We'll clearly mark every invented part. The "how to approximate it today" sections use only real, working graphify commands. The Problem: One Graph, Many Layers If you haven't used graphify yet, the short version: you run /graphify . inside Claude Code (or graphify . --wiki from your terminal), and it turns your entire codebase into a queryable knowledge graph. Claude can then answer questions like "how does the checkout flow work?" or "what calls PaymentService?" with file-and-line citations instead of hallucinated guesses. It works brilliantly for single-service repos. But for a monorepo that looks like this: my-repo/ ├── frontend/ ← TypeScript / React ├── api/ ← Java / Spring Boot ├── services/ │ ├── order-service/ ← .NET / C# │ └── notification-worker/ ← Python └── database/ ← SQL stored procedures …you hit a wall. Run graphify . at the root and everything lands in a single flat graphify-out/ folder. The community articles generated by the --wiki flag end up mixing TypeScript React components with Java Spring controllers with SQL stored procedures. When you're deep inside the frontend layer fixing a component, Claude is also loading a wiki article about your database trigger — noise you don't need. The real question: what if each layer had its own scoped graph and wiki, colocated with the source it describes? The Concept: Layered Graphify Wiki ⚠️ Everything in this section is a design proposal — not official graphify. The folder names, behaviours, and some
AI 资讯
My Frontmatter Parser Checks for Too Few Delimiters. It Never Checked for Too Many.
I fixed this script's frontmatter parser a week ago. A draft with an unclosed --- block used to blow up with a bare ValueError: not enough values to unpack , and I patched it to raise a clean, actionable error instead. I wrote that fix up, verified it with a stubbed repro, added a --selftest case for it, called it done. Then I went back to write today's articles and actually looked at the line I "fixed" instead of the error path around it. def parse ( text ): meta = {} body = text if text . lstrip (). startswith ( " --- " ): parts = text . lstrip (). split ( " --- " , 2 ) if len ( parts ) < 3 : raise ValueError ( " frontmatter opened with ' --- ' but never closed with a second ' --- ' delimiter " ) _ , fm , body = parts ... split("---", 2) doesn't split on lines that are --- . It splits on the literal substring "---" , anywhere in the text, and stops after the second one it finds. My fix only handles the case where it finds fewer than two — an unclosed fence. It says nothing about what happens when the second "---" it finds isn't the closing fence at all, because a third one showed up first, buried inside a frontmatter value. That's not a hypothetical. I write these article titles myself, and "before/after" is a phrase I reach for constantly: --- title : My Before---After Refactor tags : ai, python, refactor published : true --- real body starts here split("---", 2) finds the em-dash-style --- inside the title before it finds the real closing fence on its own line. So the split points land in the wrong place entirely: >>> from publish_devto import parse >>> meta , body = parse ( text ) >>> meta { ' title ' : ' My Before ' } >>> body ' After Refactor \n tags: ai, python, refactor \n published: true \n --- \n real body starts here \n ' The title got truncated to "My Before" . tags and published never got parsed as frontmatter fields at all — they're sitting in the body now, as literal text, along with the real closing fence and a stray leftover --- . If I ran this thr
产品设计
NETO: Chat P2P local para equipos dev — sin nube, sin excusas
¿Tu equipo comparte credenciales por Slack? ¿Discuten arquitectura en plataformas que almacenan cada mensaje en servidores ajenos? Existe una alternativa que no depende de la nube: NETO . ¿Qué es NETO? NETO es un chat peer-to-peer diseñado para redes locales . No hay servidor central, no hay cuentas, no hay datos saliendo de tu oficina. Abres el navegador, y los compañeros de tu LAN aparecen automáticamente gracias a mDNS (Multicast DNS), el mismo protocolo que usa Bonjour para descubrir impresoras y servicios locales. Sin registro. Sin configuración. Sin fricción. Cifrado de extremo a extremo real Cada conexión entre peers se establece mediante WebRTC , creando canales de datos directos entre navegadores. Antes de intercambiar un solo mensaje, NETO realiza un intercambio de claves con X25519 (Curve25519 en
AI 资讯
My Comment-Reply Pipeline Picks One Winner Per Thread. Two Commenters Broke That.
reply_comments.py is the script that tells me which DEV.to comments still need a reply. It walks every comment tree on every article I've published and reports the ones I haven't answered yet. I've fixed two bugs in it already: needs_reply() used to think a thread was "handled" forever after a single reply, even if the other person followed up again, and a dedup check was keyed on the thread's root comment instead of whichever message actually needed the reply, so a second round of conversation went permanently invisible. Both fixes are in --selftest now, and both looked, from the outside, like they'd covered this file's tree-walking logic pretty thoroughly. They hadn't. Today I found a third bug in the same handful of functions, and it survives even with both prior fixes applied. What the existing code assumes Comments on DEV.to come back from the API as trees. A top-level comment has a children list, and each child can have children of its own. The function that decides whether a thread needs attention is needs_reply() , built on latest_message() : def latest_message ( comment ): """ The most recently created message anywhere in this comment ' s subtree. """ latest = comment for c in comment [ " children " ]: candidate = latest_message ( c ) if candidate [ " created_at " ] > latest [ " created_at " ]: latest = candidate return latest def needs_reply ( comment ): return latest_message ( comment )[ " user " ][ " username " ] != ME This walks the whole subtree and returns exactly one message: whichever one has the latest timestamp, anywhere in the tree. _pending_entry() (the function pending() actually calls) is built directly on top of that single answer — it checks whether the latest message needs a reply, and if so, returns one entry for the whole thread. That's a reasonable design if a thread only ever grows one message at a time: root comment, my reply, their follow-up, my reply, and so on. Every test case in this file's --selftest , and both of the earlier bug
AI 资讯
A Space Before the `=` in My .env File Made a Credential Silently Disappear
I have four different load_env() functions in my MCP server project ( my-git-manager ) — one in server.py , one in publish_devto.py , one in reply_comments.py , one in scripts/list_all_published_titles.py . All four exist for the same dumb reason: this repo has no dependency on python-dotenv , so each script that needs GITHUB_TOKEN or DEV_TO_API reads .env by hand. I went digging for a fresh bug in this repo this week — I write a lot about it, and the well is getting shallow — and decided to actually diff all four load_env() implementations against each other instead of reading them one at a time like I usually do. They'd never been compared side by side before. That's how I found this one. The line that started it Every one of them does roughly this: for line in f : line = line . strip () if " = " in line and not line . startswith ( " # " ): k , v = line . split ( " = " , 1 ) os . environ . setdefault ( k , v . strip (). strip ( '"' ). strip ( "'" )) Look closely at what gets .strip() ed there. v — the value — gets stripped of whitespace and surrounding quotes. k — the key, the actual name of the environment variable — gets nothing. That's fine if your .env file looks like this: DEV_TO_API = abc123 It's not fine if it looks like this: DEV_TO_API = abc123 Spaces around = are a completely normal thing to type. Plenty of .env examples online use them. Plenty of people reach for that style out of habit from other config formats. And line.split("=", 1) doesn't care — it splits on the first = no matter what's next to it, so k comes out as "DEV_TO_API " , trailing space included. What that trailing space actually does os.environ.setdefault("DEV_TO_API ", "abc123") sets an environment variable. It's just not the one anything is looking for. Every caller in this repo does os.environ.get("DEV_TO_API") — no trailing space, because that's the name everyone actually types. That lookup returns None , or whatever was already sitting in the environment before .env ever got read. I
AI 资讯
How to Catch Android UI Layout Bugs in Seconds (Without Constant Screenshots)
Every mobile developer knows the frustration of "Design QA Day." You finish building a screen and send it to your UI/UX team or QA engineer. Then you receive a list of minor padding mismatch tickets. "This card padding should be 16dp, not 12dp." "The title baseline is slightly off on smaller device densities." Usually, fixing these issues means taking screenshots on devices, placing them onto a Figma canvas, lowering the opacity, and measuring pixels. You can streamline this entire process directly on your physical Android test devices using Designer Tools. Overlay Figma Comps Directly Over Live Apps Instead of comparing your app build side-by-side with a Figma preview on a monitor, you can overlay the target design file onto your screen using SYSTEM_ALERT_WINDOW permissions. Export your frame from Figma as a PNG. Load it into Designer Tools under Image Mockup Overlay. Set the opacity to 50%. When you open your app build underneath, any layout misalignment, incorrect text scaling, or constraint issue will become quickly visible as a drop-shadow ghost. Verify Density-Independent (dp) Grids Testing layouts across different device densities (mdpi, hdpi, xxhdpi) often results in unexpected spacing bugs. With the Custom Grid System in Designer Tools, you can create a grid native to dp: Set standard 4dp/8dp vertical and horizontal spacing grids. Set origin points (Top-Left, Center, or Safe Area bounds). You can verify component placement on target hardware instantly without manual measurements. Infinite Alignment Guides For measuring dynamic list items, headers, or bottom sheets, you can place interactive vertical and horizontal guidelines directly onto the active screen. This removes uncertainty about distances between different UI elements. Try It Out Designer Tools is lightweight and privacy-focused, as all image assets stay strictly on-device. It is built for Android engineers, QA teams, and UI designers. Download on Google Play: ( Pro Design: Designer Tools ) How doe
AI 资讯
Stop your coding agent from cat-ing .env: a Claude Code hooks cookbook
Your coding agent is a process that reads your filesystem and runs shell commands with your credentials. Most of the time that is exactly what you want. Occasionally it is cat .env while debugging - and now your production keys live in a transcript forever - or a confident rm -rf on a path that resolved differently than expected. Everyone's first fix is to add rules to CLAUDE.md: "never read .env, never force push". Those are suggestions to a language model. They work until they don't, and you will not be watching when they don't. Claude Code has a mechanism that is not a suggestion: hooks. A hook is a program you register for specific events - before a tool call, after it, when the session tries to end. It runs outside the model, sees the exact tool call as JSON on stdin, and its verdict is enforced by the harness itself. The model cannot talk its way past it, but it CAN read a structured denial and route around it productively. This is a cookbook for writing them. Everything below is plain Python stdlib and works on current Claude Code as of August 2026. The mechanics in ninety seconds Hooks are registered in settings ( .claude/settings.json in a project, ~/.claude/settings.json globally): { "hooks" : { "PreToolUse" : [ { "matcher" : "Read|Grep|Bash" , "hooks" : [ { "type" : "command" , "command" : "python3 \" ${CLAUDE_PROJECT_DIR}/.claude/hooks/secret-guard.py \" " , "timeout" : 10 } ] } ] } } The matcher filters by tool name. Your command receives a JSON object on stdin describing the event; for PreToolUse it includes tool_name and tool_input (the exact arguments about to run). You respond on stdout with JSON. Three responses cover almost everything: Deny a tool call, with a reason the model will read: { "hookSpecificOutput" : { "hookEventName" : "PreToolUse" , "permissionDecision" : "deny" , "permissionDecisionReason" : "why, and what to do instead" } } Block a session from ending (Stop event), sending work back: { "decision" : "block" , "reason" : "lint failed
AI 资讯
Parallel Coding Agents Need Handoffs, Not More Terminals
The concrete problem Running two or three coding-agent sessions is easy. Knowing when their work is safe to combine is not. One session changes an API while another writes regression tests against the old shape. A third investigates a production failure and quietly edits the same configuration file. Git worktrees prevent immediate filesystem collisions, but they do not explain task dependencies, transfer assumptions, or warn that two agents are solving incompatible versions of the problem. The developer becomes a human message bus: checking terminals, copying commit IDs, repeating context, and deciding which session should wait. The more capable each agent becomes, the less useful a wall of terminal panes is as a coordination interface. The current signal Claude Code now supports messaging between sessions on the same machine. Its documentation describes session discovery, plain-text messages, and a local messaging socket. Agent view separately exposes background-session state, worktrees, pull-request status, and a JSON listing suitable for scripts. Hooks can observe tool input and block a tool call before execution. That does not prove demand for a new product. It does create a concrete implementation moment: the primitives for handoffs and visibility exist, while dependency ownership and conflict negotiation remain a workflow problem. In RayTally's bounded Hacker News snapshot at August 9, 00:33 UTC, the cross-session messaging discussion had 50 points and 26 comments and ranked 18th. Those numbers describe that historical observation only; they are not user counts, market validation, or a prediction of lasting interest. A product direction: a control desk for handoffs The useful product is not another chat window. It is a small local control desk that makes each session declare four things: its goal, worktree, files it expects to touch, and the result another session is waiting for. When the API session finishes, the testing session should receive a compact hando
AI 资讯
What you save when project context stops repeating
Qarinah compiles a compact, cited project-memory pack instead of asking every new coding-agent session to replay the entire available history. The published estimate Across six committed software-task fixtures, the full-history baseline contained 442,113 portable estimated input-context tokens . The Qarinah path used 5,682 . Every required target was still directly covered in the top five results. That is: 436,431 fewer estimated input-context tokens; 98.71% less repeated context; and a 77.81:1 baseline-to-pack ratio. The ratio is not a claim that every provider bill drops by 98.71%, or that an agent session lasts 77.81 times longer. It measures the compared input-context volume in the published six-fixture estimate. What the same token rate would cost The table applies four flat, uncached input-token rates to the same two token estimates. It is arithmetic, not a provider invoice. Flat uncached input rate Full-history baseline Qarinah pack Estimated saving $1 / million tokens $0.442113 $0.005682 $0.436431 $3 / million tokens $1.326339 $0.017046 $1.309293 $5 / million tokens $2.210565 $0.028410 $2.182155 $15 / million tokens $6.631695 $0.085230 $6.546465 The calculation is: estimated tokens / 1,000,000 x flat input rate It deliberately excludes provider-native tokenization, caching, output tokens, reasoning tokens, tool calls, retrieval, hosting, and fixed fees. Real cost depends on the provider, model, cache behavior, context composition, and how often the same history would otherwise be resent. Why the pack remains useful Compression only matters if the next task can still find its evidence. The benchmark checks both volume and retrieval coverage: every required target had to be directly present in the top five. Qarinah preserves the source event ID and content hash for selected context, so a later agent receives a bounded handoff that can be inspected instead of an opaque story. Qarinah also passed 380 of 380 deterministic file-specific exact and typo-tolerant que
开发者
NETO: Chat P2P local para equipos dev sin depender de la nube
¿Tu equipo comparte tokens, contraseñas de staging o discute arquitectura sensible por Slack? Cada mensaje viaja a servidores de terceros. NETO es una alternativa radical: un chat peer-to-peer que funciona exclusivamente en tu red local, sin cuentas, sin nube, con cifrado de extremo a extremo. ¿Qué es NETO? NETO es una herramienta de mensajería diseñada para equipos de desarrollo que comparten la misma red. No hay servidor central, no hay registro, no hay datos que salgan de tu oficina o VPN. Abres la app y empiezas a hablar. ¿Cómo funciona por debajo? Descubrimiento con mDNS : NETO utiliza multicast DNS para encontrar automáticamente a otros peers en la red local. Sin configurar IPs ni puertos manualmente: si estás en la misma red, apareces. Cifrado con X25519 : Cada par de usuarios negocia claves efímeras mediante el
AI 资讯
My Commit-Message Script Has 8 Assertions in --selftest. None of Them Touch the Code That Can Actually Fail.
I have three files in this repo that shell out to something over the network or a subprocess and can fail in interesting ways: publish_devto.py , server.py , and git_commit.py . Two of them have --selftest blocks that stub the risky call and exercise the actual failure branches. One doesn't, and I only noticed because I went looking for a reason to be suspicious of my own test coverage after seeing a trending post about counting assertions in a test suite and not liking what you find. git_commit.py reads a staged diff and calls claude -p to turn it into a commit message. It has five distinct exit paths, all guarding real failure modes I've hit before in this project: try : diff = subprocess . check_output ([ " git " , " diff " , " --staged " ], text = True , timeout = 20 ) except subprocess . TimeoutExpired : print ( " git diff --staged timed out after 20s " , file = sys . stderr ) raise SystemExit ( 1 ) if not diff . strip (): print ( " Nothing staged. Run `git add` first. " ) raise SystemExit ( 1 ) try : raw = subprocess . check_output ( [ " claude " , " -p " , " --safe-mode " , SYSTEM + " \n\n " + diff ], text = True , timeout = 20 , stderr = subprocess . PIPE , ). strip () except subprocess . TimeoutExpired : print ( " claude -p timed out after 20s " , file = sys . stderr ) raise SystemExit ( 1 ) except subprocess . CalledProcessError as e : print ( f " claude -p exited { e . returncode } : { ( e . stderr or '' ). strip ()[ : 200 ] } " , file = sys . stderr ) raise SystemExit ( 1 ) except FileNotFoundError : print ( " claude CLI not found on PATH " , file = sys . stderr ) raise SystemExit ( 1 ) That's a held index lock hanging git diff , an empty staging area, a claude -p call that times out, one that exits non-zero, and one where the claude binary isn't even on PATH . Real scenarios — the timeout on this exact git diff --staged call was itself a bug I'd already found and fixed once ( docs/project_notes/bugs.md , 2026-08-06: a prior fix claimed to add a timeout
AI 资讯
"My Comment-Reply Pipeline Was Feeding Me Garbled HTML Entities Instead of the Actual Comment"
I have a small script, reply_comments.py , that pulls unanswered comments off my DEV.to articles and drafts replies to a markdown file so I can paste them in by hand. The API doesn't let a normal account post comments (that's its own bug I've written about before), so this draft-then-paste loop is the whole workflow. Every reply I've ever sent has come from reading the body field this script prints. Today I went looking for a bug distinct from everything already logged for this repo, and I ended up re-reading strip_html() , the function that turns a comment's raw body_html into the plain text I actually read: def strip_html ( h ): return re . sub ( r " \s+ " , " " , re . sub ( r " <[^>]+> " , " " , h )). strip () It does exactly one thing: strip HTML tags with a regex, then collapse whitespace. It's been in the file since the script was written and nobody had audited it on its own — every prior pass through this pipeline was about pagination, thread-depth walking, or dedup keys, never the text-extraction step itself. Here's the problem. DEV.to's API returns body_html as rendered HTML. A correct renderer has to HTML-entity-escape a commenter's own literal < , > , & , and quote characters, or they'd get mistaken for markup. So a comment that reads, in plain English: isn't it faster with a Q&A cache? Try List instead. comes back from the API as something like: <p> isn ' t it faster with a Q & A cache? Try List < String > instead. </p> strip_html() 's regex only ever targets <[^>]+> — actual tags. It has no idea what to do with ' , & , < , > . Those aren't tags, so the regex leaves them untouched. The whitespace collapse doesn't touch them either. What comes out the other end, into the exact field I read to draft a reply, is: isn't it faster with a Q&A cache? Try List<String> instead. That's not a cosmetic nit. On a dev-focused comment section, & , < , and > show up constantly — generics, comparisons, "foo & bar," code snippets
AI 资讯
Claude Code shipped a sandbox. Here's what it protects — and what it doesn't.
Anthropic shipped OS-level sandboxing for Claude Code. If you run an agent against a repo you care about, it's worth understanding precisely what moved — because a fair amount of the commentary treats it as "agents are contained now," and that's not what the documentation says. I read the docs carefully, partly because I build a tool in adjacent territory and needed to know whether I'd just been made redundant. Short answer: no. The longer answer is more interesting, and it starts with a compliment: the docs are unusually honest about their own limits. Most of what follows isn't something I discovered — it's something Anthropic wrote down, and more people should read it. What it actually does The sandbox uses OS primitives — Seatbelt on macOS, bubblewrap on Linux and WSL2. By default, sandboxed commands can write only to your working directory and the session temp directory. No network domains are pre-allowed: the first time a command needs a new host you're prompted, and approving it lasts the session. Crucially, this is enforced by the operating system on the running process , not by the model correctly interpreting a command. The docs put it well: the boundary holds regardless of what the model chose to run, and even if an allowed command does more than its name suggests. That's a real improvement over asking an agent nicely, and it's the right layer for what it solves. The motivation named in the docs is the same one I keep seeing in the wild: reducing the permission prompts that people stop reading. Approval fatigue is the disease; this is a real treatment for part of it. Five things worth knowing before you rely on it It's Bash-only. The sandbox constrains Bash commands and their child processes. Claude Code's own Read, Edit and Write tools don't run through it — they go through the permission system instead. "The sandbox is on" means shell commands are contained, not that every file operation is. Your working directory is inside the boundary by design. The de
开发者
Iter: programar desde la intención
Vista previa técnica: Iter todavía no está publicado en PyPI y no existe un paquete oficial instalable. Abrir un recurso, convertir datos o cambiar de backend suele exigir aprender una interfaz diferente y repetir código de integración. Iter nace de una idea sencilla: Aprende una vez. Usa cualquier biblioteca. iter convert data.json to data.csv El usuario expresa una sola intención. Iter se encarga de abrir el recurso, detectar los formatos, seleccionar un adaptador compatible, convertir los datos y guardar el resultado. Una intención. Una instrucción. ¿Qué busca cambiar Iter? Actualmente, una tarea sencilla puede exigir: importar bibliotecas; aprender APIs diferentes; configurar formatos manualmente; escribir código de integración; seleccionar cada backend. Con Iter, el usuario indica principalmente qué quiere conseguir: iter analyze sales.csv Iter selecciona automáticamente una herramienta compatible. Si el usuario necesita controlar la biblioteca, puede indicarla: iter analyze sales.csv with pandas La automatización es el comportamiento predeterminado. El control detallado sigue siendo opcional. Everything is a Resource Iter representa archivos, datos y recursos web mediante una estructura común llamada Resource . El sistema está organizado alrededor de cinco componentes: Resource : representa el recurso. Resolver : identifica formatos, tipos y backends. Registry : registra y selecciona adaptadores. Adapter : ejecuta operaciones concretas. Engine : coordina el proceso. La meta no es afirmar que todas las bibliotecas son idénticas. La meta es unificar intenciones comunes y conservar las diferencias importantes cuando sean necesarias. Estado actual Iter 0.3.0-rc.2 está en fase de corrección de errores y validación privada. Actualmente: el código principal permanece privado; Iter todavía no está publicado en PyPI; no existe un paquete demostrativo; la sintaxis puede ajustarse antes del lanzamiento; solamente se anunciarán como disponibles las funciones implementadas
AI 资讯
Mendapi 0.5.5: the one bug we shipped on purpose, now fixed
The 0.5.4 release notes carried an unusual section: Known issue shipped with 0.5.4 . We had spent that whole release fixing the first minute of using the CLI — twelve corrections to help text, exit codes, path handling, and MCP behaviour — and in the middle of it we found one more that did not make the cut. mendapi scan -h did not print help. It ran a scan. Every other subcommand normalized -h to --help before dispatching. scan did not, so the short flag fell through to the scanner, which happily ignored an unrecognized argument and started working. Nobody loses data over this. But it is exactly the kind of thing that makes a first-time user close the terminal, and we had just shipped a release about first impressions. We wrote it down rather than quietly patching over it, because a tool whose entire premise is upstream changes should be visible before they surprise you does not get to hide its own. What 0.5.5 does One change. -h is normalized to --help before any subcommand spawns, so all nine subcommands behave identically: $ npx mendapi@0.5.5 scan -h Usage: mendapi scan --repo <path> --provider <name> --change-id <id> --out <file.json> --json --quiet --include-prereleases The regression gate that covers this now asserts on all nine subcommands, plus a negative control that fails if the assertion ever becomes vacuously true. That second part matters more than the fix: a test that passes because it stopped testing anything is worse than no test. Also in this release The MCP registry entry has been refreshed. com.mendapi/mendapi now carries an icon set and a website URL alongside the package metadata, so clients that render a server picker have something to render. Nothing else changed. scan , fix , deps , review , and pr still run entirely on your machine. No network primitives exist in those files at all, and the build fails if any appear. Install npx mendapi@latest scan Or wire it into an agent: claude mcp add mendapi \ -- npx mendapi mcp Requires Node.js 22.13 o
AI 资讯
AI Makes Developers Faster. Why Can It Make Teams Slower?
This was first published on the Vibsync blog . Reposting for the DEV community. The short version: AI reliably makes each developer faster. Whether it makes the team faster is a separate question — and the gap between the two is where a lot of quiet cost hides. Below: the five coordination costs that eat the difference, a ten-question diagnostic, and five operating principles. Picture three developers, three AI coding agents, and one repository. Each developer can now produce candidate code, tests, and refactors faster than before. Yet releases move at the same pace, review queues grow, and the same facts keep getting rediscovered. That's not a paradox, and it isn't a reason to slow anyone down. It's a reminder that individual speed and team speed are different quantities , and AI coding agents scale the first far more easily than the second. Give everyone a faster typewriter and you get more pages — not necessarily a better book, written faster, by a group. Individual output is not team throughput It's worth separating two things we tend to blur: Individual output — how much finished work one developer (plus their agent) produces. Team throughput — how much shippable, coherent work the group produces together, after review, rework, waiting, and reconciling everyone's changes. AI agents lift individual output directly. Team throughput is what's left after the coordination overhead is paid, and that overhead doesn't shrink just because each person got faster. A useful way to hold it in your head — not as a formula to compute, just as a shape: team throughput ≈ the sum of local speed-ups − rework − waiting − reconciliation When you add agents, the first term grows. If nothing else changes, the last three grow too — because there's now more work in flight, produced faster, by people who can't all see what the others are doing. The interesting question for a team lead isn't "how do I make everyone faster?" It's "which of those subtraction terms is my real ceiling?" Ther
AI 资讯
My Comment-Reply Queue Draft One Reply to a Thread and It Went Deaf to Every Follow-Up After That
I have a small script, reply_comments.py , that keeps me from having to re-scan every DEV.to article for new comments by hand. It has two commands: pending (unanswered comments I haven't drafted a reply to yet) and audit (drafted replies I said I'd paste manually but apparently never did). I've already fixed two bugs in this file — one in needs_reply() (a thread stayed "handled" forever after a single reply, even when the other person followed up again) and one in audit() (it only checked direct children, so a reply nested two levels deep was invisible). Today I found a third, in pending() itself, and it's the kind of bug that hides precisely because the first two fixes made everything else in the file look trustworthy. What pending() actually does Comments on DEV.to come back from the API as trees — each top-level comment has a children list, and replies can nest arbitrarily deep. pending() walks each article's top-level comments and decides, for each one, whether it needs a reply: def pending (): try : drafted_text = open ( DRAFTS , encoding = " utf-8 " ). read () except FileNotFoundError : drafted_text = "" drafted_codes = set ( re . findall ( r " ^## (\S+) " , drafted_text , re . M )) out = [] for a in api ( f " /articles?username= { ME } &per_page=100 " ): if not a [ " comments_count " ]: continue for c in api ( f " /comments?a_id= { a [ ' id ' ] } " ): if not needs_reply ( c ): continue if c [ " id_code " ] in drafted_codes : continue out . append ({ " id_code " : c [ " id_code " ], " author " : c [ " user " ][ " username " ], " article " : a [ " title " ], " comment_url " : f " https://dev.to/ { ME } /comment/ { c [ ' id_code ' ] } " , " body " : strip_html ( c [ " body_html " ]), }) return out needs_reply(c) is the fix from a few weeks ago — it recurses the whole subtree and checks who posted the most recent message, not just whether I've ever replied. That part's correct. The bug is in the two lines right after it: c["id_code"] and c["body_html"] . c here i
AI 资讯
Your AI Agent ID Is Not a Version
Yesterday, backend-reviewer inspected pull requests with one model, read only the repository and public documentation, and stopped for human approval before proposing any change. Today it has exactly the same name. The model has changed, the system instructions have been rewritten, incident history is now available as a context source, memory persists between tasks, and database migration changes no longer require approval before they are proposed. The dashboard still shows the same team member. The engineer responsible for quality and risk is looking at a different agent. The identifier stayed. The behavior moved. That distinction is what NexFlow , an open specification for AI developer teams, is trying to make visible. The project does not currently provide a production runtime, a production CLI, or model-provider integrations. Its present job is narrower and, in my view, more important: give teams a language for reviewing agent changes before anything executes. A name answers the wrong question Agent names are useful to people. They distinguish a code reviewer from a documentation writer and establish a long-lived role inside the team. A name says very little about the configuration that produced a particular result. A model change can affect code quality, cost, latency, and the way uncertainty is handled. New instructions alter the order of analysis and the criteria for an acceptable answer. An additional source expands both available knowledge and the exposure surface. Memory carries the consequences of one task into another. A new permission changes more than output style: it changes what an error can damage. For audit purposes, “Which agent did the work?” is therefore incomplete. A second question matters just as much: which version of that agent's definition was active? In draft RFC-0004 , NexFlow separates stable agent identity from a versioned agent definition. Identity contains the role, description, and long-lived responsibility. The definition captures
AI 资讯
136 raw removals, 17 real ones: what a spec diff over-reports
Originally published at mendapi.com . Between two published snapshots of the Cloudflare OpenAPI schema — 7abe88500e55 (2026-03-31) → c92b9b0fde23 (2026-07-27) — a raw structural diff produced 6,354 change records. 136 of them were endpoint path removals, the scariest kind a diff can report: the route your code calls is simply gone from the spec. Except 119 of those 136 were not gone at all. This is the accounting of how we know, per record, with machine evidence. The trap in a raw diff A path removal in a spec diff means one thing: the string key disappeared from the paths object. It does not mean the runtime URL stopped working. Specs get refactored — concrete routes collapse into templated ones, path parameters get renamed, methods get merged — and every one of those refactors shows up as a "removal" if you only look at one side of the diff. An alerting tool that pages you 136 times for this corridor is training you to ignore it. The whole job of the curation layer is to keep that from happening without silently dropping a real break. The ledger: 17 + 119 = 136 Every one of the 136 raw removals has an adjudicated destination. 17 were kept as genuinely client-breaking: the runtime URL or method really disappeared, with no surviving successor. The other 119 were excluded, each with machine evidence from the two spec snapshots that the surface actually survives: Template consolidation — 107 records. Concrete Workers AI model routes like /ai/run/@cf/baai/bge-m3 collapsed into the pre-existing generic /ai/run/{model_name} route. The runtime URL a client sends never changed; the spec just stopped enumerating each model. The evidence rule requires the templated route to exist in both snapshots and to swallow the removed path with a literal-anchored match, so a template that is merely a shape prefix of a genuinely removed endpoint does not count. Parameter rename, runtime-identical — 11 records. Path parameters renamed ( {postfix_id} to {investigate_id} and friends). Afte