Something worse than semver

Issue #507.July 28, 2026.2 Minute read.
Bytes

Today’s issue: The cure for male pattern baldness, compiling away React’s bad parts, and going ring shopping at gunpoint.

Welcome to #507.


Eyeballs logo

The Main Thing

A confused man reading a sheet of paper

GPT 5.6 Sol Ultra Fast

Something worse than semver

I am a little ashamed to admit that, for a long time, semver, my arch-nemesis, has been a helpful tool for deciding what to write about. But this week, when Anthropic released Opus 5 and Elon said Grok will release 4.6 and 4.7 in the next month, I realized that AI naming conventions are basically just vibes.

The way semver is supposed to work is that it follows the convention of MAJOR.MINOR.PATCH, where patches are backward-compatible bug fixes, minors are backward-compatible feature additions, and majors are reserved for breaking changes. But in the world of AI, none of this is particularly helpful. So I have decided to do an insane thing and try to make this all make sense. Wish me luck.

Version Number: Major versions usually represent significant changes to a model’s architecture, training data, and training strategies, with the goal of adding new capabilities. Minor versions represent optimizations to the base model, usually via post-training, that make the model perform better on benchmarks or improve its efficiency.

Product Name: Both Anthropic and OpenAI have product names (Fable | Opus | Sonnet | Haiku vs. Sol | Terra | Luna) within each version of a model. These products essentially represent a “tier” of model that relates roughly to how large and precise the model is. Roughly speaking, the larger and more precise the model, the slower and more expensive it will be. If you’ve noticed companies talking more and more about routers, it’s because they are trying to smooth over this nonsense by using an LLM to assess a query and send it to the most relevant model.

Effort Level: If this current set of conventions wasn’t dumb enough, there is also an effort level option that model providers offer. The effort level is an indication of how many reasoning steps a model should take before returning an answer. How do you know how much the model is going to reason? Lol you don’t. In my experience, it’s a great way to light tokens on fire, burn through all your credits, and never get a result.

Bottom Line: AI companies creating a system that is worse than semver is truly an accomplishment, but hopefully the next time you feel the urge to fire up Fable 5 on max reasoning for your CRUD app, you’ll think of this and reconsider your life choices.


CodeRabbit logo

Our Friends
(With Benefits)

A man giving a skeptical sideways glance

Reviewing AI-generated code before we had CodeRabbit

Understand the real change behind your code

Reviewing AI-generated code shouldn’t mean just going through files in alphabetical order.

CodeRabbit Change Stack reorganizes any pull request from a flat file list into a structured, layer-by-layer walkthrough. And you can try it out for free right now during early access.

Here’s a sneak peek:

  • PR Overviews: Get a PR summary, walkthrough, actionable blockers with one-click fixes, and all PR reviews and comments in one place.

  • Timeline View: See a full history and explanation of how the PR got where it is. Semantic Diff shows you the real changes behind your code, and you can ask the agent questions about your implementation, right where you’re working.

Review your next PR with CodeRabbit Change Stack – try it free today.


Spot the Bug logo

Spot the Bug

Sponsored by Clerk

Clerk now supports self-serve SSO. Now your customers’ IT admins can configure and manage their own enterprise SSO connections from a new Security tab in <OrganizationProfile />.

const items = [
  { id: 1, name: 'Apple', price: 0.5 },
  { id: 2, name: 'Banana', price: 0.3 },
  { id: 3, name: 'Orange', price: 0.6 }
];

function applyDiscount(items, discount) {
  for (let i = 0; i < items.length; i++) {
    items[i].price -= items[i].price * discount;
    items[i].price = items[i].price.toFixed(2);
  }
  return items;
}

const discountedItems = applyDiscount(items, 0.1);
const totalPrice = discountedItems.reduce((sum, item) => sum + item.price, 0);

Cool Bits logo

Cool Bits

  1. Claude has a new guide for context engineering for its version 5 models.

  2. I’m not saying it was personal, but Tanner wrote two new libraries@tanstack/markdown and @tanstack/highlight — just to get rid of RSC on tanstack.com.

  3. Archestra built an open-source AI platform that bundles a private MCP registry, orchestrator, cost controls, and observability into a secure environment that won’t leak private data to the internet. [sponsored]

  4. The Promise.allKeyed proposal, which lets you return a dictionary of promises, reached Stage 3. “Dictionary of promises” and “proposal” are things your girlfriend says when you’re being escorted to Tiffany’s at gunpoint.

  5. Vercel Labs released scriptc, a compiler that turns TypeScript into native code. Why? Faster cold starts, I guess.

  6. Ethan Smith wrote about reward functions for image models and why it’s so hard to make something everyone likes. If you know what a Gaussian distribution is, continue reading.

  7. Jay Henry and Sergiy Dybskiy are hosting a free workshop on How Etsy keeps their app crash-free during traffic spikes with Sentry. [sponsored]

  8. Dominic Gannaway just launched a new project called Octane that compiles away all of React’s bad parts.

  9. Kimi K3 released its weights on Hugging Face. Dario is furious.

  10. Wispr Flow is the smart, voice-to-text tool that *actually works* across any app. Just speak naturally when you want to write an AI prompt, PR description, or Slack message, and Wispr Flow turns it into clean, formatted text that’s ready to send. [sponsored]

  11. NVIDIA just gave Ilya Sutskever’s company SSI a bunch of compute. Step 1: AGI. Step 2: use AGI to fix male pattern baldness.

  12. Poolside made a desktop app for Mac to use their models locally. PC users will have to vibe code their own.


Spot the Bug logo

Spot the Bug: Solution

Sponsored by Clerk

After applying the discount, we use toFixed(2) to round the price to two decimal places. However, toFixed() returns a string, not a number. That means that when we calculate the total with reduce(), we perform string concatenation instead of number addition.

There are a few ways to fix it. The simplest, if you’re confident in your data, is to convert the result back to a number:

function applyDiscount(items, discount) {
  return items.map(item => ({
    ...item,
    price: Number((item.price * (1 - discount)).toFixed(2))
  }));
}