今日已更新 156 条资讯 | 累计 29890 条内容
关于我们

今日精选

HOT

最新资讯

共 29890 篇
第 287/1495 页
AI 资讯 Dev.to

Two coding agents editing the same issue, no merge conflict. Here is how git refs make that work

Run two AI coding agents on the same repo and the first thing that breaks is not the code. It is coordination. Agent A starts refactoring auth. Agent B, running in parallel, has no idea and starts the same thing. Neither remembers what it did last session, because each one boots fresh with an empty context window. The usual fixes are worse than the problem: a state file in the repo pollutes every diff and conflicts on merge, and an external issue tracker means API tokens, rate limits, and a hard dependency on the network for something that should be local. So I built grite : an issue tracker that lives inside your git repository as an append-only event log, with deterministic CRDT merging so two writers never conflict. No server. No database. No merge conflicts. Just git. The core idea: issues are events, git refs are the log Grite does not store issues as files in your working tree. It stores them as an append-only write-ahead log inside a git ref, refs/grite/wal . Every action, a create, a comment, a label change, is one immutable CBOR-encoded event appended to that log. Your working tree stays completely clean. The only tracked file grite ever writes is AGENTS.md , and that is on purpose, so agents discover the tool automatically. Because the state lives in a git ref, it travels with your code. It branches when you branch. It merges when you merge. It syncs when you git push . If you can push to a remote, you can sync issues. There is no new account, no new infrastructure, no new protocol to learn. How it works Three layers, cleanly separated. The git WAL is the source of truth. Events are appended as CBOR chunks, each identified by a content-addressed EventId that is a BLAKE2b hash of the event body. Content addressing is what makes the log tamper-evident: change one byte of an event and its ID no longer matches, which breaks the chain. Signing is optional Ed25519 per event, so you can prove which actor created what. The materialized view is a sled embedded key-

Dipankar Sarkar 2026-07-25 23:24 8 原文
AI 资讯 Dev.to

The Two-Map Party Game Server: Building GameNight Without a Database

Every party game app I'd used before building this one wanted an account, a lobby website, or a subscription. I wanted the opposite: plug a laptop into the TV, run one command, and have everyone's phone connected in under thirty seconds — no internet required once the LAN is up. That constraint ends up dictating almost every architectural decision in GameNight : a Node/Express/Socket.io server that runs five real-time party games — a Mafia-style social deduction game I call Mongolpuri, UNO, a trivia quiz, Scribble, and Tic-Tac-Toe with tournament brackets — entirely from two in-memory Map s, no database, no auth, no build step on the frontend. Decision 1: A room is a plain object, not a schema const rooms = new Map (); // roomCode -> room const playerRooms = new Map (); // socketId -> roomCode const room = { code , gameType , host : socket . id , players : new Map ([[ socket . id , { id : socket . id , name , avatar }]]), status : ' lobby ' , gameState : null , timers : [], settings : defaultSettings ( gameType ), sessionStats : {}, }; Every game's state — the UNO deck, the Killer/Doctor night phase, the Scribble canvas buffer — lives in room.gameState , an untyped bag shaped differently per gameType . There's no ORM, no room class hierarchy, no GameEngine interface every game implements. Each game gets its own set of top-level functions ( startKD , kdResolveNight , startUno , unoPlayCard , …) that read and mutate room.gameState directly, dispatched through one handleAction switch: function handleAction ( room , socket , data ) { const gs = room . gameState ; if ( ! gs ) return ; switch ( room . gameType ) { case ' tictactoe ' : /* ... */ break ; case ' killerdoctor ' : kdAction ( room , socket , data ); break ; case ' scribble ' : scribbleAction ( room , socket , data ); break ; case ' uno ' : unoAction ( room , socket , data ); break ; case ' quiz ' : quizAction ( room , socket , data ); break ; } } For a five-game server built by one person, this is the right amo

Abhijat Chaturvedi 2026-07-25 23:21 6 原文
AI 资讯 Dev.to

No Backend, No Build Step: A Spaced-Repetition Chrome Extension That Runs on chrome.storage.sync Alone

Most "save this for later" tools I've used eventually want a server: an account system, a database for your notes, a sync service with its own outage history. I wanted something narrower — capture text or a whole page while browsing, turn it into a spaced-repetition flashcard, and have it show up on my other machine — without running any infrastructure at all. MindStack is a Manifest V3 Chrome extension that does exactly that: capture, spaced-repetition scheduling, a full dashboard, and cross-device sync, built entirely on chrome.storage.sync and chrome.identity . No backend, no bundler, no npm install before you can load it unpacked. Here's what that constraint forces you to get right. Decision 1: The scheduler is SM-2-shaped, not SM-2 Spaced repetition apps usually reach for a full SuperMemo SM-2 implementation — ease factors computed from response quality on a 0–5 scale, per-review interval history. MindStack's actual scheduler is a compressed version that captures the two properties that matter for a lightweight capture tool and drops the rest: const scoreReview = async ( score ) => { const memory = state . memories . find (( item ) => item . id === activeReviewId ); const interval = { forgot : 1 , hard : Math . max ( 1 , Math . round (( memory . reviewCount || 1 ) * 1.5 )), good : Math . max ( 2 , Math . round (( memory . reviewCount || 1 ) * ( memory . ease || 2.5 ))), easy : Math . max ( 4 , Math . round (( memory . reviewCount || 1 ) * (( memory . ease || 2.5 ) + 1 ))) }[ score ]; const updated = { ... memory , reviewCount : ( memory . reviewCount || 0 ) + 1 , successCount : ( memory . successCount || 0 ) + ( score === " forgot " ? 0 : 1 ), ease : Math . min ( 3.4 , Math . max ( 1.3 , ( memory . ease || 2.5 ) + ({ forgot : - 0.35 , hard : - 0.12 , good : 0.05 , easy : 0.16 }[ score ]) )), nextReviewAt : addDays ( interval ), }; Two properties, deliberately preserved from SM-2: intervals grow multiplicatively with review count (so a card you keep getting righ

Abhijat Chaturvedi 2026-07-25 23:21 7 原文
AI 资讯 Dev.to

Every EnvCastError Tells You How to Fix It: Designing Error Messages as a Feature

int(os.environ.get("PORT", "8080")) fails constantly in ways that waste your time: ValueError: invalid literal for int() with base 10: 'abc' . No variable name. No hint about what a valid value looks like. You grep the codebase for PORT to even find where the read happened. specenv is a zero-runtime-dependency Python library for typed environment variable loading — casting, validation, schema grouping, prefix namespacing. All of that is useful, but none of it is the actual design decision worth writing about. The decision that shaped everything else was: every error must name the variable and say how to fix it, unconditionally, with no opt-out. Decision 1: The error message is generated at the failure site, not templated afterward It would be easy to build one generic EnvCastError(var_name, raw_value, target_type) and format a message from those three fields in __str__ . specenv doesn't do that — each cast failure builds its own message inline, at the point where the specific failure is known: if cast_type is int : try : return int ( raw ) except ValueError : raise EnvCastError ( f ' Cannot cast { name } = { raw !r} to int. \n ' f ' → Set { name } to a valid integer (e.g. { name } =8080) ' ) from None if cast_type is bool : ... raise EnvCastError ( f ' Cannot cast { name } = { raw !r} to bool. \n ' f ' → Set { name } to one of: 1/0, true/false, yes/no, on/off ' ) The generic version would produce "Cannot cast PORT='abc' to int" and stop there. The inline version gets to add (e.g. PORT=8080) for ints, 1/0, true/false, yes/no, on/off for bools, a namespaced hint for prefixed variables — because at the point of failure, you know exactly what a correct value looks like for that type, and a generic formatter three calls up the stack doesn't. The cost is a few lines of duplication across _caster.py 's type branches. That's a fair trade for every single error message being genuinely actionable instead of generically accurate. Decision 2: Missing-and-required collapses to t

Abhijat Chaturvedi 2026-07-25 23:20 6 原文
AI 资讯 Dev.to

Building a Timing Utility That Can't Corrupt Its Own Stats — Even When Your Code Throws

Most ad-hoc timing code in Python looks like this: start = time . perf_counter () result = do_work () elapsed = time . perf_counter () - start stats [ name ]. append ( elapsed ) It works, until do_work() raises. Then the line that records the timing never runs, the exception propagates, and the one call that was probably slowest — the one that failed — is silently missing from your stats. If you're using timing data to find what's expensive, the failing case is exactly the one you can least afford to lose. timerx is a small, dependency-free Python timing library — a decorator, a context manager, and named stopwatches, all backed by one stats store. The one rule that shapes the whole implementation: a timing gets recorded whether or not the timed code raised. Decision 1: finally , everywhere, no exceptions to the rule @functools.wraps ( target ) def wrapper ( * args : Any , ** kwargs : Any ) -> Any : started = self . _clock () try : return target ( * args , ** kwargs ) finally : elapsed = self . _clock () - started with self . _lock : self . _record ( label , elapsed ) return wrapper The async wrapper is the identical shape with await added. The context manager ( _Lap ) does the same thing structurally, just split across __enter__ / __exit__ instead of try / finally : def __exit__ ( self , * exc_info : object ) -> bool : if self . _started is None : raise RuntimeError ( " timerx lap exited before it was entered " ) elapsed = self . _timer . _clock () - self . _started with self . _timer . _lock : self . _timer . _record ( self . _name , elapsed ) return False Note the return False — __exit__ deliberately never swallows the exception. It records the timing and lets the exception continue propagating unchanged, because a timing library has exactly one job here: observe, not intervene. A version that suppressed exceptions to "clean up" would be actively dangerous to drop into someone else's codebase. Three entry points — decorator, context manager, stopwatch — and all t

Abhijat Chaturvedi 2026-07-25 23:20 6 原文
AI 资讯 Dev.to

12 things to check before you ship your vibe-coded app

Getting an app to work has stopped being the hard part. You describe what you want, Lovable or Bolt or v0 builds it, and forty minutes later there's something on a real URL that real people can click. The hard part moved. It's now everything between "it works" and "it survives contact with the internet." That gap isn't a vibe. It's measurable. Symbiotic Security crawled 65,643 URLs and fully scanned 1,072 Supabase-backed vibe-coded apps in June 2026: 98% had at least one security issue, 16% had something critical. A separate academic study by Deng et al. found that vibe-coded apps show recurring vulnerability patterns that differ from the ones traditional codebases produce — meaning these aren't random mistakes, they're structural. And an Xint.io analysis reported by SecurityWeek turned up 434 exploitable flaws concentrated in secrets exposure, broken authorization and denial of service. Same handful of failure modes, over and over. Which is good news, because it means you can check for them in about fifteen minutes. Below is the list I actually walk through. Everything here you can run against your own domain with curl and browser devtools. No tooling required. 1. Is your .env reachable over HTTP? The single most common catastrophic finding. It happens when the build output directory and the project root end up being the same thing. curl -sI https://yourapp.com/.env | head -1 curl -sI https://yourapp.com/.env.local | head -1 curl -sI https://yourapp.com/.env.production | head -1 Anything other than 404 is an emergency. Rotate every key in that file before you do anything else — assume it's already been scraped, because bots hit these paths constantly. 2. Is your .git directory exposed? Worse than .env , because it hands over your entire history including keys you thought you'd removed. curl -sI https://yourapp.com/.git/HEAD | head -1 curl -s https://yourapp.com/.git/config If HEAD returns 200, the whole repository is reconstructable by a stranger. 3. Which keys are

Janni Hares 2026-07-25 23:16 5 原文
开发者 The Verge AI

Synth historian Oli Freke will spend big on a good bicycle

Oli Freke is a musician and journalist whose works have appeared in Sound on Sound, The Quietus, and Mixmag. This has included using math to explore the melodic potential of the Western 12-tone scale and deep dives on effects plug-ins. He's even written a book tracing the evolution of the synthesizer from 1963 through 1995, […]

Terrence O’Brien 2026-07-25 23:15 12 原文
产品设计 The Verge AI

Teenage Engineering’s unique music machines are 30 percent off

With elements from synthesizers, loopers, and effects pedals, Teenage Engineering’s devices lie somewhere between musical instrument and modern art. These grooveboxes, as they’re often called, are capable of helping you produce songs in real time from a single unit, with an eye-catching design language. A wide swath of the brand’s offerings are 30 percent off […]

Brad Bourque 2026-07-25 23:00 10 原文