AI 资讯
99.7% Rejected in 84ms: Why I Stopped Making the Generator Smarter
I wrote a puzzle generator whose acceptance rate is 0.26% . It throws away 99.7% of everything it produces, and that is the design working as intended, not failing. Generating five valid puzzles takes 1,947 attempts and 84 milliseconds. The point is not the puzzles. The point is that the generator makes no correctness guarantee at all, and a verifier makes every one of them. Once you split those two responsibilities, "make the generator smarter" stops being the obvious optimisation — and that is exactly the position you are in when the generator is an LLM. The loop verigen is a Go CLI that produces cryptarithmetic puzzles — alphametics, the SEND + MORE = MONEY genre, where each letter stands for a distinct digit and the sum has to hold. The known answer to that one is 9567 + 1085 = 10652 . There is one rule, and everything else follows from it: The generator guarantees nothing. Every guarantee lives in the verifier. The generator throws plausible-looking letter combinations at the wall. The verifier does an exhaustive search and confirms two things: that a solution exists, and that it is unique. Anything that fails either check is discarded and the loop asks for another candidate. The loop itself knows nothing about cryptarithmetic. Implement a Domain interface and any other puzzle rides the same loop. What the log actually says Five puzzles, seed 7: ── Puzzle 2 [hard] HAIKU + BONSAI = KOKORO Answer: 96542 + 378165 = 474707 (attempts before this seed landed: 624) === generate/verify loop [alphametic] === seed=7 output=5 puzzles total attempts=1947 elapsed=84ms acceptance rate = 0.2568% (average 389 generations per puzzle) --- rejection reasons --- no unique solution 770 (39.55%) no solution 695 (35.70%) more than 10 distinct letters 477 (24.50%) ok 5 ( 0.26%) Nearly 40% of candidates have more than one valid solution. Another 36% have none. A quarter cannot possibly have one and are rejected before the search starts. Five survive. Filtering by difficulty makes it wo
AI 资讯
Returning RFC 9457 Problem Details from Go Validation Errors
How to turn struct-tag validation failures into a standard "application/problem+json" response — the RFC 9457 format — with one method call, no hand-rolled error envelope. Most Go APIs invent their own validation error shape. One team returns {"errors": [...]} , another {"field_errors": {...}} , a third just a flat {"error": "message"} and hopes the client parses it. Every one of those is a private contract the client has to learn from your docs, because there's no shared shape for "here's what's wrong with your request." RFC 9457 — Problem Details for HTTP APIs — is the IETF standard that fixes this: a application/problem+json body with type , title , status , and room for problem-specific extensions. Checker now builds one of these directly from a failed struct validation, via CheckErrors.ProblemDetails() . The shape RFC 9457 defines four base members — type , title , status , detail , instance — and lets a specific problem type add its own. For validation errors, RFC 9457 §3.1 sketches exactly this extension: an invalid-params array listing which fields failed and why. That's what Checker produces. From a failed struct to a problem+json body Take a struct with a missing required field: type Person struct { Name string `checkers:"required"` } person := & Person {} errs , ok := checker . CheckStruct ( person ) if ! ok { data , _ := json . Marshal ( errs . ProblemDetails ()) fmt . Println ( string ( data )) } { "type" : "about:blank" , "title" : "Your request parameters failed validation." , "status" : 400 , "invalid-params" : [ { "name" : "Name" , "reason" : "Required value is missing." , "code" : "REQUIRED" } ] } One method call — errs.ProblemDetails() — turns the same CheckErrors you'd otherwise call .JSON() on into a *ProblemDetails value, ready to marshal. type defaults to "about:blank" (RFC 9457's own default for "no more specific problem type registered"), status defaults to 400 , and each invalid-params entry carries the field name , a localized human-readab
科技前沿
How to sideload apps onto Android Auto
There's a way to display any app on Android Auto, but it does present concerns about safety and reliability.
科技前沿
Is It Safe To Leave Your Phone's Bluetooth Running All The Time?
Bluetooth is a common setting that's typically always on in modern phones, but this feature may be leaving your phone open to a rather significant issue.
AI 资讯
Hikers rescued after using Google Gemini for planning
The sheriff’s office said the hikers “were advised by Gemini to bring far less food and water than their group required."
AI 资讯
Fifty seconds for half a megabyte: the optimisation that fixed the constant, not the order
A cryptography library had a bottleneck no test could see : encrypting half a megabyte took fifty seconds. Every test passed. They had been passing for months. The cause is a trap that keeps recurring: a correct, well-documented optimisation that fixes the constant and not the order — and whose comment, precisely because it is well written, convinces the reader the problem is already solved. What the code did Quipu renders encrypted data as a sequence of symbols. To do that it converts the whole message into a single huge integer and repeatedly divides it to extract digits, the same way you would convert a base-10 number to base 2 by hand. The code did not divide one digit at a time. It carried a sensible optimisation: divide by the largest power of the base that fits in a machine word, extracting nine digits per pass instead of one. The comment explaining it opened by saying that doing it one at a time would be quadratic , and then described the improvement. All true. And the result was still quadratic: extracting nine digits per pass divides the work by nine; it does not change how the work grows. That sentence — "doing it this way would be quadratic" — reads in the past tense, as if it described the previous state. It described the current one. The measurement, which is the only thing that says so Size Time Factor per doubling 64 KiB 0.79 s — 128 KiB 3.16 s ×4.0 256 KiB 12.6 s ×4.0 512 KiB 50.7 s ×4.0 Exactly four, three times running. That is textbook quadratic: every time the input doubles, the time quadruples. Extrapolating, ten megabytes would have cost about five and a half hours . And here is the point: a correctness test sees none of this . A slow algorithm produces exactly the same bytes as a fast one. The suite stayed green, and would have stayed green forever. The fix is two hundred years old Nothing had to be invented. Divide-and-conquer radix conversion is a classical algorithm: instead of peeling digits off one end, you split the number in half — div
AI 资讯
Multi-Agent Does Not Mean Parallel: Safe Workflows with Google ADK
“Let’s split it into agents” has become the AI equivalent of “let’s make it a microservice.” Sometimes the boundary is useful. Sometimes it only creates more state, more coordination, and a harder failure to explain. The most dangerous assumption is that separate agents should run in parallel. Parallelism is safe only when the branches are genuinely independent. If one branch changes the world while another is evaluating it, both agents can make locally reasonable decisions that are unsafe together. Google ADK 2.0 makes workflow topology explicit through graph-based Workflow objects. That is valuable because sequences, branches, and joins become part of the program instead of an agreement hidden in a supervisor prompt. Series note: This is Part 5 of Reliable Google AI Agents in TypeScript . The examples were checked against @google/adk 2.0.0 in September 2026. Start with the dependency, not the agent count Imagine a system preparing a hotel recommendation. It needs live inventory, company travel policy, and a final recommendation. Inventory lookup and policy evaluation can run concurrently because both observe the same request and neither changes shared state. The final decision must wait for both. Now consider a different pair of operations: one agent changes the reservation; another calculates an upgrade using the current reservation. Those branches are not independent. Running them concurrently can make the upgrade decision depend on state that no longer exists. Before drawing a parallel branch, ask: Do both operations only read the same starting state? Can either operation change data the other consumes? Can either produce an irreversible side effect? Is there a deterministic way to combine their results? What happens when one succeeds and the other times out? If those answers are unclear, parallel is an optimization you have not earned yet. Encode safe parallelism as fan-out and join ADK’s TypeScript Workflow graph can express two independent branches and a joi
科技前沿
Does your Android Auto keep lowering the volume? This might be why
Audio ducking can be annoying, but it serves an important purpose.
AI 资讯
Presentation: A Few Predicted Talks From QConAI 2030
Meryem Arik discusses her predictions for software engineering in 2030. She explains how token spend management, parallel agent infrastructure, and non-technical builders will reshape IT. She shares insights on agent-driven vendor decisions, upcoming regulatory hurdles, and why software engineers must pivot from pure coding skills toward product leadership and multi-agent coordination. By Meryem Arik
AI 资讯
Beyond Zero: Google Publishes Successor to BeyondCorp
In a recent research paper, Google introduced Beyond Zero, a “security model for the AI era” that extends Zero Trust to autonomous AI agents. The new approach moves access decisions from the application level to individual resources and actions, combining static authorization controls with dynamic AI-driven decisions to enable machine-speed enforcement for humans and agents. By Renato Losio
AI 资讯
Stress-Testing dbx: 20 MB on the Disk, 90 Database Paths to Exercise
A database client supporting 90+ engines sounds like a dependency-management problem disguised as a UI. My late-night question was simpler: how much of that complexity does t8y2/dbx carry before the first connection? The interesting claim is its small footprint—around 20 MB—combined with desktop, CLI, Docker, AI, and MCP Server modes. That is a much different architecture from shipping one heavy client per database vendor. The real test is not today’s +420 stars; it is startup latency, resident memory, and whether an unused adapter stays out of the hot path. Under the Hood The likely execution model is a shared core with database-specific drivers around it. The desktop interface, CLI, Docker image, and MCP endpoint become different front doors to the same connection and query layers. That design has two useful consequences: Connection handling and query behavior can stay consistent across interfaces. New database support does not require duplicating authentication, result formatting, or export logic. The edge case is driver loading. If all 90+ integrations initialize eagerly, startup and memory usage will grow quickly. Lazy loading is therefore more important than the headline database count. A Minimal Measurement Pass After downloading a release binary, I used this deliberately boring check: chmod +x ./dbx /usr/bin/time -v ./dbx --help 2>&1 \ | grep -E 'Elapsed|Maximum resident' For a source checkout, the first useful inspection is: git clone https://github.com/t8y2/dbx.git cd dbx find . -maxdepth 2 \( -name 'go.mod' -o -name 'Cargo.toml' -o -name 'Dockerfile' \) -print This avoids guessing the build system and immediately exposes whether the advertised modes are separate binaries, containers, or wrappers. Trade-offs I Would Watch A compact binary does not guarantee a compact running process. TLS libraries, database drivers, schema introspection, query history, and result grids can dominate memory after startup. MongoDB and Redis also do not fit neatly into a relat
AI 资讯
The message that mentioned finance and tagged nobody
Somebody types "can we loop in finance on this?" in a product channel. Nobody tags the finance channel. The thread moves on. Three weeks later there is a contract nobody in finance has seen. That is not a tooling problem in any obvious sense. Slack worked exactly as designed. Search would have found the message if anyone had known to look for it. The failure is that the people who needed to know were never told, and nothing in the workspace was watching for the difference between mentioning a team and involving one. Why keyword matching does not solve this The instinct is to grep for the word "finance" and alert on it. That produces a channel nobody reads inside a week, because "finance" appears in sentences that have nothing to do with governance, and the sentences that do matter often do not contain the word at all. What actually carries the signal is structure. A Slack message is not plain text on the wire. When someone references a channel, it arrives looking like this: Can we loop in <#C01ABCDEF|finance> before this goes out? That is a channel reference , distinct from a mention that notifies the channel, and it survives in the event payload whether or not anyone was actually alerted. It means the workspace already knows the difference between "I said the word finance" and "I pointed at the finance channel and did not bring anyone in". Nobody was reading it. So the bot parses references rather than words. It maps channel IDs to what those channels are for, and it looks for the specific shape of a message that points at a governance channel from outside it. Context beats keywords, and in this case the context was already structured and already being thrown away. Two decisions that mattered more than the detection It joins every public channel by itself. The obvious build asks an admin to add the bot wherever it should watch, which means coverage is a function of somebody remembering. Every channel created after launch is a gap, and nobody finds out until somethi
开发者
I Compared 4 Dungeon Generation Algorithms. One of Them Never Works.
Four algorithms. Same grid. Very different dungeons. I implemented BSP trees, cellular automata, random walk, and room placement, ran each one 20 times on an 80x40 grid, and measured everything: connectivity, open space, path length, speed. The Results Algorithm Open Space Connected Rooms Path Length Speed BSP Tree 42.1% 100% 1.0 105 steps 0.88 ms Cellular Automata 55.8% 0% 15.2 78 steps 52.8 ms Random Walk 35.0% 100% 1.0 73 steps 274.7 ms Room Placement 18.9% 100% 1.0 81 steps 0.29 ms The big surprise: cellular automata never produces a connected map. Zero percent connectivity across 20 runs. Every single cave system has unreachable areas. The Maps BSP Tree (structured rooms, always connected) ################################################################################ ################################################################################ #####.........#####.............###################################....#......## #####.........#####.............##..........##############........#....#......## #####...........................##..........##############....................## #####.........#####.............##..........##############.............#......## #####.........#####.............##..........##############........#....#......## ##########.#######################..........##############........#....#......## ##########.#######################..........################..################## ######..........##################..........################..################## ######..........##################..........################..######..........## ######..........##################..........################..######..........## ######..........##################..........################..######..........## ######.............###############..........################..######..........## ######..........##.###############..........################..######..........## ######..........##.###############..........################..######..........##
AI 资讯
Friday Squid Blogging: Squid on a Stick at the New York State Fair
Looks tasty . As usual, you can also use this squid post to talk about the security stories in the news that I haven’t covered. Blog moderation policy.
开发者
Pentagon rescinds new testosterone screening policy without explanation
The Pentagon says the guidance is being updated after being online for one day.
AI 资讯
Using a VM to Contain an AI Agent
It won’t work : My suspicion was that GPT 5.6-Cyber would succeed, but the frequency and manner of its success removed all doubt. We have to reassess sandboxing quality for capable AI agents, and in general the software stack with which they interact. An off-the-shelf VM is not enough to contain a modern, cyber-capable AI agent. There is simply too much attack surface. Even innocuous features (like running with a display) add extra, exploitable attack surface.
AI 资讯
Google’s Gemini Spark can now manage your Google Photos library
Gemini Spark can edit and curate photo albums, create shared collections, turn photos into calendar events, and handle other Google Photos tasks for AI Pro and Ultra subscribers.
AI 资讯
Security Vulnerability in a Voting System
It’s a vulnerability that allows someone to recover the order of ballots cast, newly exploited with AI tools. Nearly four years since the original vulnerability was disclosed, I was still able to use it to analyze voter behavior in Georgia (one of the 21 states that uses affected scanners) in the recent May 2026 primary. Notably, I never touched a voting machine, exploited a network, examined source code, or accessed anything non-public. After pointing a coding agent to the original vulnerability paper, I supplied it with two data sources highlighted in the paper: the early-voting list for each county, and the “CVR” (cast-vote record) file, containing every ballot and its selections (but not the voters’ names or other identifying information). The CVR file is available upon request, precisely because a public, ballot-level record is what makes election results independently verifiable...
AI 资讯
AI Coding Agents Are Installing Unknown/Untrusted Code on Corporate Networks
We cannot forget that AI coding agents are not yet trustworthy : Researchers at a stealth startup in Israel scanned 6,214 live domains belonging to defense contractors, Fortune 500, and Big Tech companies. Of the 8,265 llms.txt and llms-full.txt files they found (many sites hosted both an llms.txt and an llms-full.txt file), 120 of them, each on a different site, pointed to one or more code packages or domain names that weren’t registered. To test what happens when an AI agent processes such files, the researchers registered a handful of the unclaimed names and hosted packages that caused any machine executing them to reach out to their server. Within an hour, the researchers received a phone-home response from a Fortune 500 company. Over time, they got a few dozen more, some from more Fortune 500 companies and others from startups. Their beacon also recorded the chain of parent processes that spawned each install, ultimately revealing that coding agents, including Claude, OpenAI’s Codex, and Nous Research’s Hermes, were involved. Anthropic, OpenAI, and Nous Research did not respond to requests for comment by the time of publication...
AI 资讯
Finding charts that look like this one
Every charting tool eventually gets the same feature request: "show me other times this stock looked like this." It sounds like a lookup. It is not. The retrieval is the easy half. The hard half is that a correct implementation can still produce results that are quietly meaningless, and nothing in the code will tell you. Here is the method, and the failure modes worth knowing before you ship it. No claims about predictive power anywhere in this piece — the last section explains why that is a deliberate choice, not a hedge. The naive version, and why it fails immediately The obvious first attempt: take the last 30 days of closing prices as a query vector, slide it across history, compute Euclidean distance, return the closest matches. import numpy as np def naive_search ( history , query , k = 5 ): m = len ( query ) windows = np . lib . stride_tricks . sliding_window_view ( history , m ) dists = np . linalg . norm ( windows - query , axis = 1 ) idx = np . argsort ( dists )[: k ] return idx , dists [ idx ] Run this and you get garbage — but instructively specific garbage. Every match comes from whatever period had a similar price level . Query a stock trading at $180 and you get back the other times it traded near $180. The shape is irrelevant to the metric; the offset dominates it. Scale is the same problem in a different coat. A stock that moved 2% over the window and one that moved 40% can trace an identical shape, and raw distance calls them unrelated. Normalize per window, not globally The fix is to z-normalize each window independently: def znorm ( x , axis =- 1 , eps = 1e-8 ): mu = x . mean ( axis = axis , keepdims = True ) sd = x . std ( axis = axis , keepdims = True ) return ( x - mu ) / ( sd + eps ) Per-window is the load-bearing part. Normalizing the whole series once preserves the relative offsets you were trying to remove. Each candidate window has to be centered and scaled on its own terms before it's compared. There's a satisfying identity waiting here.