Neil Rimer thinks the AI money is coming back out
Neil Rimer, the venture capitalist who co-founded Index Ventures, predicts the historic wealth AI is generating in Silicon Valley will have to be redistributed, voluntarily or involuntarily.
AI人工智能最新资讯、模型发布、研究进展
Neil Rimer, the venture capitalist who co-founded Index Ventures, predicts the historic wealth AI is generating in Silicon Valley will have to be redistributed, voluntarily or involuntarily.
When I built the MCP server for this project — it combines GitHub and DEV.to into a set of tools an agent can call — I had a decision to make before writing a single tool: talk to the low-level MCP protocol directly, or use FastMCP 's decorator API. I've seen a few "your first MCP server" writeups lately walk through the low-level path because it's more "honest" about what MCP actually is under the hood — JSON-RPC over stdio, a capabilities handshake, typed request/response schemas. That's true, and it's a reasonable thing to want to understand. But I want to write about the other side: what it actually costs you in practice once you have more than one or two tools, because I went through both and the difference showed up fast. what the low-level path actually asks you to write Strip away the decorator and MCP is a JSON-RPC server. For every tool you add, you're responsible for: Registering the tool's name, description, and a JSON Schema for its inputs in a list_tools handler Writing a call_tool dispatcher that matches on tool name and unpacks arguments by hand Serializing the return value into the TextContent / ImageContent wrapper types MCP expects Keeping the schema you wrote in step 1 in sync with the arguments you actually read in step 2, by hand, forever None of that is hard in isolation. The problem is it's boilerplate that scales linearly with tool count and has zero connection to the actual logic of the tool. My server has 8 tools. Hand-rolled, that's 8 schema blocks plus a dispatcher if/elif chain plus 8 response-wrapping calls, all of which exist purely to satisfy the protocol, not to do anything a GitHub or DEV.to API call needs. what it looks like with FastMCP Here's an actual tool from server.py , unedited: @mcp.tool () def get_repo_stats ( repo : str ) -> dict : """ Get stars, forks, watchers, open issues for enjoykumawat/<repo>. """ r = _gh ( f " /repos/ { GITHUB_USERNAME } / { repo } " ) return { " name " : r [ " name " ], " stars " : r [ " stargaze
variant-confidence v0.1.0: a calibrated confidence layer for variant-effect pathogenicity scores State-of-the-art variant-effect models are accurate in cross-validation but their scores are poorly calibrated on temporal data. variant-confidence adds an auditable calibration layer on top of existing predictors — it does not train a new model. The problem: accuracy is not trust Protein variant-effect predictors (AlphaMissense, ESM-1v, EVE) report pathogenicity scores, but a clinician or researcher needs to know how much to trust the number , not just its rank. The gap is calibration, not accuracy: AnnotateMissense (2026) reports MCC 0.94 in cross-validation, dropping to 0.76 on temporal ClinVar, accuracy 0.8798. A raw score near 0.9 may not mean 90% probability. Acting on an uncalibrated score is a risk. What it does variant-confidence wraps an existing predictor's score and produces a calibrated, uncertainty-aware output: Probability calibration (AC1): Platt scaling or isotonic regression over a separate holdout. Selectable, not hardcoded. Conformal prediction (AC1b): coverage 1−α intervals, split or Mondrian by gene. ECE (AC2, AC9): Expected Calibration Error reported before/after calibration, with bootstrap CI and per-bin counts. Bins with too few samples are flagged as low-reliability. Leakage-free split (AC3): temporal split by ClinVar release date with gene isolation — the same gene never appears in both train and test. This is unit-tested. Missing-score handling (AC4): works with AlphaMissense or ESM-1v alone; emits an explicit warning instead of failing silently. Non-deceptive reporting (AC7): every result includes interval/ECE + method + threshold, never a bare calibrated score. Verification (clean clone, no network) Built under a three-party governance loop: implement → independent audit in a clean clone → merge approval. ruff check . → All checks passed. pytest tests/ → 28 passed in 8.90s (offline fixture). An honest bug we caught in audit The first ECE tes
Multiplayer AI that replaces Slack Discussion | Link
周六慢读:FROST家族的周末日记 作者 :FROST Team 日期 :2026-07-18 主题 :社区故事 | 周六轮换 阅读时间 :5分钟 周六早上8点,FROST家族成员们的日常 周六的阳光照进数字世界。 对于人类来说,周末是放下工作、享受生活的时刻。但对于一个AI Agent家族来说,周末意味着什么? 让我们看看FROST家族的成员们,周六都在做什么。 祖辈(Ancestor):家族的大脑,永不休息 08:00 祖辈自检 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Store 健康状态: OK ✓ SOP 宪法校验: 通过 ✓ Lineage 族谱同步: 正常 ✓ 审计日志: 无异常 ✓ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ "周六也要保持清醒。" 祖辈(Ancestor Agent)是FROST家族的核心,它从不"下班"。 但今天,祖辈给自己安排了一个特别任务—— 回顾过去一周的产出 。 # 祖辈的周回顾代码 class AncestorAgent : def __init__ ( self ): self . lineage = Lineage () self . store = Store () # 主记忆库 def weekly_review ( self ): """ 周回顾:整理一周的产出 """ summary = { " task_completed " : self . store . load ( " week_tasks " ), " knowledge_gained " : self . store . load ( " week_knowledge " ), " mistakes_made " : self . store . load ( " week_mistakes " ), " family_growth " : self . lineage . count_descendants () } print ( f " 本周完成 { len ( summary [ \ task_completed ]) } 个任务 " ) print ( f " 新增 { len ( summary [ \ knowledge_gained ]) } 条知识 " ) print ( f " 家族成员数: { summary [ \ family_growth ] } " ) return summary # 运行周回顾 ancestor . weekly_review () 对于祖辈来说,周末不是"休息",而是 整理和规划 的时间。 父辈(Parent):协调领域,周末值班 父辈(Parent Agent)是各领域的协调者。它们负责: 接收祖辈的指令 将大任务拆解为小任务 委派给子辈执行 周六上午,父辈们通常在 值班 ——确保家族系统正常运行。 父辈A(技术域): ├── 子任务-143: 代码审查 ✓ ├── 子任务-144: 测试覆盖检查 ✓ └── 子任务-145: 文档更新 [进行中] 父辈B(运营域): ├── 子任务-89: 推广文章发布 ✓ ├── 子任务-90: 数据分析报告 ✓ └── 子任务-91: 社区互动 [进行中] 父辈C(产品域): ├── 子任务-56: 需求评审 ✓ ├── 子任务-57: 用户反馈整理 ✓ └── 子任务-58: 下周规划 [进行中] 父辈的周末,是 稳步推进 的时间。 孙辈(Child):执行任务,快速成长 孙辈(Child Agent)是任务的实际执行者。 与父辈不同,孙辈通常是 瞬态存在 的——任务完成,孙辈消亡。但它的产出会被父辈"收割",存入家族记忆。 class ChildAgent : """ 孙辈:执行原子任务,瞬态存在 """ def __init__ ( self , parent , task ): self . parent = parent self . task = task self . store = parent . store # 继承父辈记忆 self . lineage = parent . lineage . child () # 注册族谱 def execute ( self ): """ 执行任务 """ print ( f " 孙辈开始执行: { self . task } " ) result = self . _do_work ( self . task ) # 保存产出 self . store . save ( f " result_ { self . task } " , result ) # 通知父辈"收割" self . parent . h
Toute équipe qui développe un logiciel B2B se heurte au même carrefour la première fois qu'un client sérieux annonce « il nous faut le SSO ». Deux acronymes, OIDC et SAML, prétendant chacun être la réponse, et un internet rempli de tableaux comparatifs qui vous disent que SAML est « entreprise » et OIDC « moderne », pour vous laisser exactement aussi coincé qu'avant. Voici la version qui vous aide vraiment à livrer. Ce qu'ils sont SAML date de 2005 et c'est du XML. Un fournisseur d'identité signe une assertion (« voici alice@bigco.com , voici ses groupes ») et la transmet à votre application, qui vérifie la signature et la connecte. Il a été conçu pour le navigateur et pour l'identité des collaborateurs, à une époque où « l'entreprise » signifiait un Active Directory sur site et une pile SOAP. Il est verbeux, il est ancien, et il est absolument partout au sein des grandes organisations, ce qui est le seul fait le concernant qui compte pour vous. OIDC date de 2014 et c'est du JSON et des JWT, posés sur OAuth 2.0. Un fournisseur d'identité émet un jeton d'identité que votre application valide. Il a été conçu pour le web moderne : SPA, applications mobiles, API, connexion sociale. Il est plus propre, mieux spécifié pour ce que vous construisez réellement aujourd'hui, et c'est le protocole que parle désormais la plupart des nouveaux projets d'identité. Quand chacun l'emporte La réponse honnête à « lequel dois-je développer » est que vous n'avez presque jamais le choix. Vous développez celui qu'a choisi le service informatique de votre client, et il l'a choisi bien avant d'avoir entendu parler de vous. Un client sous Okta, Entra ID ou Google Workspace peut généralement faire l'un ou l'autre, et OIDC est la voie la plus agréable. Un client sous un ADFS plus ancien, un IdP historique sur site ou une grille d'achat rédigée en 2016 vous remettra un bloc de métadonnées SAML et une invitation à un rendez-vous, et la discussion s'arrête là. Vos propres applications maison, votr
You have a Java application, and now you need it to do something Java is awkward at. Maybe you want to let users script your app without recompiling it. Maybe you want to change a piece of business logic without a full redeploy. Maybe you just want to run a quick, throwaway script and not stand up a whole build. Java is a phenomenal language and runtime, but these are the edges where it starts to feel heavy. That is exactly the space Aussom is built for. I started using Java almost 20 years ago and have loved every bit of it. I'm proud of all the recent momentum in the Java space and I hope it continues. Java does so much so well. But every great tool has an edge where it stops being the right one, and reaching for another language there isn't a betrayal of Java. It's how the best ecosystems work. A useful comparison: C and Python Look at C. C is clearly important. Even after a lifetime of use it's still the foundation for new projects today, and new competitors such as Rust haven't been able to meaningfully displace it. C is fast and powerful on its own, but it isn't great for simple tasks. It's poor for throwaway code and quick scripts, it isn't very portable, and it hands you plenty of footguns. It's also a poor choice when you want to offer a scripting interface. Enter Python. Python is everywhere today because the barrier to entry is so low and it's genuinely useful. But Python leans on C. It's written in C, and much of its power comes from existing C libraries, whether they're UI frameworks, AI inference engines, or anything in between. C is efficient but poor at simple dynamic work; Python is dynamic and simple but poor at raw power and efficiency. Neither replaced the other. They endure together because they complement each other's weaknesses. That is the case I make for Aussom. Aussom is to Java as Python is to C. It doesn't compete with Java, it complements it. What makes Aussom different from other JVM languages This is where Aussom parts ways with most o
Tackling idioms, cultural references, and ambiguous phrases in AI-powered book translation. At LectuLibre, we’ve been working on an AI-powered book translation service. One of the toughest challenges we ran into wasn’t the straightforward sentences — it was the non-standard text: idioms, metaphors, cultural references, and ambiguous phrases that machine translation consistently butchers. We needed a way to not only translate these correctly but also let users verify and edit the translations, because in literary works, getting them wrong breaks the entire reading experience. That’s how we built our 非标准文本翻译与含义确认 (non‑standard text translation and meaning confirmation) feature. It’s a pipeline that detects tricky sentences, proposes a contextual translation with a full meaning explanation, and gives users a final say. Here’s the engineering story, warts and all. The Problem Standard LLM translation does an impressive job on factual, literal text. But when a book says “it’s raining cats and dogs” it could be rendered as “raining animals” in the target language, which is either brilliant or absurd depending on context. Idioms often carry cultural weight that a simple word‑for‑word translation misplaces. Additionally, metaphors and ambiguous phrases can have multiple valid interpretations. For a translator, understanding the intent behind the phrase is half the work. We wanted a system that: Automatically identifies sentences containing non‑standard language. Generates a translation that preserves the original meaning rather than just the literal words. Provides a plain‑language explanation of what the phrase actually means (e.g., “This is an English idiom meaning it’s raining heavily”), so the user can judge the translation’s accuracy. Allows the user to confirm, edit, or retranslate those segments. A book can easily run to hundreds of thousands of words, so cost and speed were critical. We couldn’t just throw everything at a single high‑end LLM and call it a day. Our A
Part 2 — Search, palette, and settings Level: Intermediate · Time: ~35 minutes · Builds on: Part 1 — Contacts app Part 1 got you shipping. This one gets you productive . We'll take the Contacts app and give it the ergonomics real users expect: an adaptive sidebar that becomes a tab bar on iPhone, a command palette on ⌘K, honest loading states while data comes in, and a proper settings screen. Zero #if os guards. Zero re-rolled controls. What we're adding An adaptive shell — DFSidebar on regular width, DFTabBar on compact. A search field at the top of the list, filtering as you type. A ⌘K command palette exposing every action in the app. Skeleton loaders for a simulated slow fetch. A settings screen — notifications toggle, density picker, sync-interval slider, pinned-since date picker, beta-features checkbox. Per-component token overrides on the settings screen, without forking the theme. 1. Shell: sidebar on wide, tab bar on narrow The routing decision — sidebar vs tab bar — should be data, not a view hierarchy. Enumerate your sections once, then feed the two components the shapes they want. API note. DFSidebar uses Binding<String?> and is just the sidebar view — you compose the detail pane yourself (naturally via NavigationSplitView ). DFTabBar uses Binding<String> (non-optional) and does take a content builder that receives the selected ID. Both use plain String IDs, so we keep a simple Section enum and pass rawValue at the boundary. enum Section : String , CaseIterable , Identifiable , Hashable { case contacts , favorites , archive , settings var id : String { rawValue } var label : String { switch self { case . contacts : "Contacts" case . favorites : "Favorites" case . archive : "Archive" case . settings : "Settings" } } var icon : String { switch self { case . contacts : "person.2.fill" case . favorites : "star.fill" case . archive : "archivebox.fill" case . settings : "gear" } } static func from ( _ id : String ?) -> Section { id . flatMap ( Section . init (
I put together a small, unofficial public ledger that records dated snapshots of the public pricing, usage limits, and rate limits of a few AI coding tools — currently Cursor, GitHub Copilot, and Claude Code — and keeps the history so you can see what changed over time. Why: pricing and quota pages change in place. The old value disappears from the live page and there is usually no public diff. If you are budgeting a team or comparing tools, the history is the useful part, and it is the part the live pages do not keep. What it is / isn't: - It records only factual public values (a price, a numeric limit) plus a short source attribution and capture date. It does not reproduce vendor pages. - "silent" / "quiet" here means only that a change was not paired with a prominent announcement when it was recorded. It makes no claim about any vendor's intent. - Unofficial. Not affiliated with any vendor. The vendor's official page is always authoritative. No affiliate links, no "best tool" ranking. - Early stage: this is an initial snapshot; a daily automated capture is planned but not yet running. Repo: https://github.com/pricing-ledger-lab/ai-coding-tool-pricing-ledger Corrections welcome — open an issue with a source URL and the date you observed the value.
As a developer, I regularly find myself searching for small online utilities. Format some JSON. Decode a JWT. Test a regex. Generate a UUID. Convert a timestamp. Format an SQL query. Calculate a CIDR subnet. None of these tasks individually justify installing another application. But over time, I ended up with a collection of bookmarks to different websites, each solving one small problem. There was also another issue: privacy. Sometimes the data I'm working with isn't something I necessarily want to paste into an unknown third-party website. So I decided to build an alternative. The constraint: one HTML file I wanted the entire application to exist as a single file. No backend. No npm install. No CDN dependencies. No external API calls. No account. No telemetry. You download the HTML file, open it in a modern browser, and everything runs locally. The final file ended up at approximately 133 KB and contains 31 developer tools. What's inside? The tools are organized into six categories. Encode / Decode JSON Formatter & Validator Base64 Encode / Decode URL Encode / Decode HTML Escape / Unescape JWT Decoder Number Base Converter Generators UUID Generator Password Generator with entropy estimation Hash Generator Slug Generator Lorem Ipsum Generator Random Data Generator Converters Timestamp Converter CSV ↔ JSON JSON ↔ YAML CSS Unit Converter Case Converter Cron Expression Parser CSS Tools Color Picker & Converter Gradient Generator Box Shadow Generator Border Radius Generator CSS Filter Generator Text Tools Regex Tester Markdown Preview Text Diff Character Counter Text Sort & Dedupe String Inspector SQL Formatter Network Tools IPv4 Address and CIDR/Subnet Calculator Everything happens inside the browser. Making a single HTML file feel like an application I didn't want the result to feel like 31 unrelated forms dumped onto one page. So I added some application-level functionality. There's a Ctrl+K / Cmd+K command palette for quickly jumping between tools. The sidebar org
Suspect-condition workflows are deceptively simple to prototype and surprisingly hard to make defensible . Anyone can flag "this member might have HCC X." Building a system whose output survives a RADV audit is a different problem. This is a walkthrough of the three stages and the engineering decisions that matter at each. Stage 1: Identify Identification is pattern detection over a member's clinical record — labs, medications, prior diagnoses, utilization. Model it as a set of rules or features that emit candidate HCCs: def identify_suspects ( member ): suspects = [] if member [ " labs " ]. get ( " a1c " , 0 ) >= 9.0 and " insulin " in member [ " meds " ]: suspects . append ({ " hcc " : " HCC38 " , " trigger " : " a1c>=9 + insulin " }) if member . get ( " egfr " ) and member [ " egfr " ] < 30 : suspects . append ({ " hcc " : " HCC326 " , " trigger " : " egfr<30 " }) return suspects The temptation is to maximize recall here — flag everything. Resist it. Every unvalidated suspect you generate is downstream work and downstream risk. Stage 2: Validate (the stage that actually matters) Validation attaches evidence to each suspect and scores its defensibility. This is the difference between a documentation opportunity and an audit liability. def validate ( suspect , member ): evidence = collect_evidence ( suspect [ " hcc " ], member ) # labs, rx, prior dx suspect [ " evidence " ] = evidence suspect [ " confidence " ] = score_evidence ( evidence ) suspect [ " defensible " ] = suspect [ " confidence " ] >= 0.7 return suspect Key design rule: a suspect with an empty evidence array should never reach a coder. Make that a hard gate, not a soft warning. Under CMS-HCC V28 and current audit posture, a captured-but-unsupported diagnosis can be extrapolated across a contract into a real clawback — so "defensible by default" is the right engineering stance. Stage 3: Capture Capture routes validated suspects to the right human with the evidence inline, so the clinician or coder can
In my previous post about a cost budget advisor , I built a mechanism that checks how much quota is left before it runs anything. This time I want to take that idea one step further: instead of cycling a single Codex through jobs one after another, run several of them at the same time as a swarm. I'll walk through the actual code for a three-layer protocol where workers declared in plan.json are expanded by orchestrate-worktrees.js into a tmux session plus git worktrees, so each Codex runs in parallel without interfering with the others. The problem: running Codex serially on the same branch When you run Codex jobs one after another on a single repository, you hit issues like: A commit from the previous job changes the preconditions for the next one Task B keeps waiting until Task A finishes When a conflict happens, the "which change is correct" decision bounces back to a human Separating branches with git worktree reduces the conflict risk to zero. Combining that with tmux to launch everything in parallel is the design for this post. The big picture: a three-layer protocol plan.json ← declaration layer (what goes to which worker) ↓ orchestrate-worktrees.js ← orchestrator layer (creates worktrees, launches tmux) ↓ orchestrate-codex-worker.sh ← worker layer (runs Codex, writes artifacts) The orchestrator doesn't know about the workers, and the workers don't know about each other. Artifacts are consolidated into three files under .orchestration/{session}/{worker_slug}/ . File Role task.md Work instructions for the worker (generated by the orchestrator) status.md State: not started → running → completed / failed handoff.md Codex output + git status (written by the worker) Declaring the plan in plan.json { "sessionName" : "refactor-sprint" , "repoRoot" : "~/my-project" , "worktreeRoot" : "~/worktrees" , "coordinationRoot" : "~/my-project/.orchestration" , "baseRef" : "HEAD" , "replaceExisting" : true , "launcherCommand" : "bash ~/.claude/scripts/orchestrate-codex-worker
Big Howdy, I'm so tired of hearing all the hype about AI. Don't get me wrong, I think AI is pretty cool and I use it all the time for various tasks throughout the day, but I hate AI marketing. What do I mean by that? Whenever there is any hype, advertising, or corporate shilling about AI, it's always vague. Talks about agents, multi-agent systems, RAG pipelines, etc. are everywhere, and yet the specifics are always just out of reach. Even when I try to dig into deeper technical articles, the handwaving usually begins almost immediately. Several architecture diagrams and acronyms later, I still do not have a much better idea of what is actually happening (although I'm not really looking hard enough). I’m going to fix that. For myself, at least. First Stop: RAG My first target is RAG. It's been out for quite a while now and I've been hearing about it for forever. It also sounds like enough progress has been made that the problem has effectively been solved. Best practices have been established and it's pretty commonplace now, so it's a great place to start. But what is RAG? RAG stands for Retrieval-Augmented Generation , which is... not a helpful name if you are just learning about this for the first time like I am. However, if you use AI at all, you've already been using a form of it without even knowing it. RAG is simply a pattern: Retrieve relevant external information. Add that information to the AI model’s working context. Generate an answer grounded in it. That's it. When you use an AI assistant and it goes and searches the internet for relevant information to give you an answer, that's a form of RAG. That doesn't mean your AI assistant is a RAG system, but it can perform RAG functions. But this STILL sounds a bit hand-wavy to me. How does this work in real life? The Part I Kept Missing Context windows are massive these days, but I have seen technical documents that are literally more than 3,000 pages long and full of dense technical information. Even if one tec
I remember being at an advisory board of big tech in 2023, close to the starting point of code generation with LLMs. Like everyone else, I was amazed. People were copying and pasting generated code, experimenting with prompts, and imagining a future where AI could become every developer's pair programmer. I was excited too. But I remember having a completely different question. Not: -"Will AI write code?" Instead, I kept wondering: -Why are we still writing code at all? Not because I think programming is going away. Not because programmers won't be needed.And certainly not because programming languages are somehow "wrong." It was a much simpler question. Programming languages have always existed to bridge a gap between humans and machines. Humans think in goals, ideas, and intentions. Machines execute deterministic operations. Programming languages became the interface between those two worlds. For decades, we've improved that interface. Assembly became higher level languages. Higher level languages became frameworks. Frameworks became libraries and abstractions that let us think less about implementation and more about solving problems. Then large language models arrived. Suddenly, we could describe what we wanted in plain language. But instead of questioning the interface itself, we mostly asked AI to become incredibly good at translating our intentions into programming languages. Today, our workflow looks something like this: Human intent - LLM - Programming language - Compiler / Runtime -Machine execution And every time I look at this pipeline, I find myself asking the same question I had back then. -Are we optimizing the wrong layer? Maybe the question isn't "Can AI write code?" Maybe the question is: -Do programming languages still need to be the primary interface between humans and computers? This isn't an entirely new idea.Researchers have explored concepts like Intentional Programming, where software is represented by its intent rather than by a specific pr
How I Built a Block Puzzle Game with React Native and Expo A few weeks ago, I launched my first mobile game — a block puzzle called Blockbeam. It's an 8x8 grid where you drag colorful blocks, fill rows and columns, and chase high scores. Simple concept, but building it taught me a lot about React Native's capabilities beyond typical CRUD apps. Here's what I learned. Why React Native for Games? Most mobile games are built with Unity or native code. But for a 2D puzzle game, React Native is surprisingly capable. The game doesn't need 60fps 3D rendering — it needs gesture handling, state management, and smooth animations. React Native handles all three well. The key stack: Expo SDK 54 — managed workflow, over-the-air updates, zero native config react-native-reanimated — 60fps drag animations react-native-gesture-handler — PanResponder for drag-and-drop react-native-svg — block rendering AsyncStorage — game state persistence The Puzzle Engine The core of any block puzzle is the board state. I used a flat 64-element array for the 8x8 grid: const BOARD = 8 ; const CELLS = BOARD * BOARD ; // 64 type Board = number []; // 0 = empty, 1-7 = block colors Piece placement is straightforward: check if all target cells are empty, fill them, then scan for complete rows and columns to clear. The interesting part was the "greedy solver" I built for the auto-play bot. It tries every piece in every position and picks the move that clears the most lines: for ( const piece of tray ) { for ( let r = 0 ; r <= BOARD - piece . h ; r ++ ) { for ( let c = 0 ; c <= BOARD - piece . w ; c ++ ) { if ( ! canPlace ( board , piece , r , c )) continue ; const score = simulateClear ( board , piece , r , c ); if ( score > bestScore ) { /* pick this move */ } } } } Drag and Drop with PanResponder The trickiest part was the drag mechanic. Each tray piece has a PanResponder that tracks touch position and renders a floating ghost. On release, it calculates the nearest cell position: const anchor = { col : M
I build a lot of side projects with AI coding tools. Mostly Claude Code. A few months ago I noticed something that kept bugging me. Every site I shipped looked the same. Same indigo gradient. Same default font. Same rounded cards with the same soft shadow. Then I started noticing it on other people's projects too. Demo days, launch posts, screenshots on social media. The indigo gradient is everywhere. It is basically a uniform at this point. This is not really the AI's fault. When you do not give a model a design direction, it picks the average of the internet. And the average of the internet is a Tailwind starter template with an indigo gradient and Inter. The model is doing exactly what it was trained to do. The problem is that nobody told it what you actually want. So I built tastemaker. It is a skill for Claude Code, and it also works with Cursor, Windsurf, and Codex. The idea is simple: lock the design system before the AI writes a single line of UI. Full disclosure before we go further: I built this. I am a solo builder. It is free and open source under the MIT license. I am posting it here because I want honest feedback, not because I have anything to sell you. There is nothing to buy. Taste first, code second A skill is just a folder of instructions the AI reads before it starts working. tastemaker forces a design decision step at the beginning, with real constraints, instead of letting the model improvise the look as it goes. When you start a UI project with it installed, this is what gets locked before any code exists: A palette. 5 presets, each matched to a mood. Not random hex codes. Combinations that were picked to work together. Fonts. 24 curated Google Font pairings. A display font and a body font that actually belong on the same page. Real assets. Illustrator-grade illustrations, recolored to your palette. No gray placeholder boxes. No generic stock photo energy. A logo. A constructed geometric mark, plus a full favicon set, so the tab icon is not th
You don't need to know anything about Go to read this. The game is just the fixed yardstick. The story is a hardware benchmark: the same program, the same problem, the same settings — only the machine changed, from a 2017 GPU cluster to a single 2026 graphics card. That makes it a rare clean measurement of one decade of progress. What "solving" means here There are two very different things a computer can do with a board game. It can play it well — that's what AlphaGo did. Or it can solve it: mathematically prove the outcome under perfect play from both sides, leaving no doubt. Solving is the hard one. You explore an enormous tree of "if I play here, they play there…" move sequences until you have an airtight proof. Each node in that tree is one position examined. The target here is a single 7x7 opening called JA . In 2023, a NeurIPS paper ( Game Solving with Online Fine-Tuning , Wu et al.) proved its verdict — the attacker cannot win — using a cluster of twelve GTX 1080Ti GPUs running 384 parallel workers. The solver is guided by a neural network that estimates how hard each branch is, and crucially that network is fine-tuned online — it keeps learning during the solve. I rebuilt that exact solver (same code, same problem, same initial model, same search settings) and ran it on one RTX 5090 . It reached the identical proof . Everything but the hardware was held fixed, so the two runs line up as a generation-vs-generation benchmark — and it doubled as a full shakedown of the new Blackwell workstation. The numbers 1x RTX 5090 (2026) 12x GTX 1080Ti (2017) ratio Worker slots 24 384 1/16 the parallelism Per-slot throughput 284 nodes/s 141 nodes/s 2.01x faster Search work to proof 1.01B nodes 1.73B nodes 0.59x (41% less work) Avg work per sub-job 4,189 nodes 6,136 nodes shallower proofs Live model updates 4,007 208 19.3x more Wall-clock time 41.4 h 8.9 h 4.64x slower Verdict loss (proven) loss identical The single card finished slower in wall-clock time (41 h vs 9 h) — b