CiviCRM 6.18 Release

CiviCRM
civicrm.org
2026-09-03 11:02:35
Thanks to the hard work of CiviCRM’s incredible community of contributors, CiviCRM version 6.18.0 is now ready to download. This is a regular monthly release that includes new features and bug fixes. Details are available in the monthly release notes. Your are encouraged to upgrade now ...
Original Article

Thanks to the hard work of CiviCRM’s incredible community of contributors, CiviCRM version 6.18.0 is now ready to download. This is a regular monthly release that includes new features and bug fixes. Details are available in the monthly release notes .

Your are encouraged to upgrade now for the most stable, secure CiviCRM experience:

Download CiviCRM

Users of the CiviCRM Extended Security Releases (ESR) do not need to upgrade. The current version of ESR is CiviCRM 6.16.x (supported until April 2027).

Support CiviCRM

CiviCRM is community driven and is sustained through code contributions and generous financial support.

We are committed to keeping CiviCRM free and open, forever . We depend on your support to help make that happen. Please consider supporting CiviCRM today .

Big thanks to all our partners , members , ESR subscribers and contributors who give regularly to support CiviCRM for everyone.

Credits

AGH Strategies - Alice Frumin; Artful Robot - Rich Lott; Buildkite - Angus Fretwell; Christian Wach; Circle Interactive - Pradeep Nayak; civico GmbH - Johannes Filter; CiviCoop - Jaap Jansma, Erik Hommel, Klaas Eikelboom; Civicopilot - Andy Burns; CiviCRM - Coleman Watts, Tim Otten, Benjamin W; CiviDesk - Yashodha Chaku; civiservice.de GmbH - Torben Bertram; Colored Cow - Tarun Joshi; CompuCo - Muhammad Shahrukh; Coop SymbioTIC - Mathieu Lutfy, Shane Bill; CSES (Chelmsford Science and Engineering Society) - Adam Wood; Dave D; eeprom-foo; Freeform Solutions - Herb van den Dool; Fuzion - Luke Stewart, Toby Messerli; GESTAD - Guillaume Sorel; Gray Digital - Richard Baugh; hiSandog; Jakub Fidler; JMA Consulting - Monish Deb, Seamus Lee; Jonathan Dahan; Lemniscus - Noah Miller; marcelocompucorp; Marvin Müller; Megaphone Technology Consulting - Jon Goldberg; MJW Consulting - Matthew Wire; Nicol Wistreich; Progressive Technology Project - Jamie McClelland; Richard van Oosterhout; Robert Garrigos; Ruza Solutions - Rose; Ryan Morash; Skvare - Mark Hanna, Sunil Pawar; Squiffle Consulting - Aidan Saunders; sushant-cividesk; SYSTOPIA - Dominic Tubach, Jens Schuppe; Tadpole Collective - Kevin Cristiano;Wikimedia Foundation - Eileen McNaughton, Lars Sander-Green, Wenjun Fan

New Extensions

  • Media Scaler - MediaScaler validates, transforms and stores CiviCRM images with privacy-preserving filenames and configurable transformation policies.
  • Membership Payer - A CiviCRM extension that separates the organisation paying for an online membership from the individual member.
  • Housekeeping - Housekeeping adds a daily scheduled job that purges these on a retention you control, one policy per task.
  • JCE Editor - Use JCE as the WYSIWYG editor in CiviCRM (Joomla only).
  • CiviVerify - CiviVerify is a generic CiviCRM extension for issuing and redeeming single-use, time-limited verification links.
  • Security Hotfix for CIVI-SA-2026-35 - Provides a hotfix for the vulnerabilities (CIVI-SA-2026-35, CIVI-SA-2026-37) published on 5 August 2026.
  • Revisionist - Revisionist adds automatic version history to CiviCRM's FormBuilder and SearchKit. Every time a form or search is saved, a snapshot is recorded automatically - so you can browse previous versions, see exactly what changed.
  • confirmstep - This provides an API for other extensions to offer a confirm-by-clicking-link-in-email step.
  • SearchKit Form - SearchKit Form adds a Form display type to CiviCRM SearchKit.
  • Events Listing Block for CiviCRM - Events Listing Block for CiviCRM is a standalone, dynamic Gutenberg block for upcoming public CiviCRM events.
  • EventSession - This extension allows the configuration of sessions for an event, which can take place at the same time. Also allows registering for sessions, including waitlist functionality.
  • SearchKit Box - SearchKit Box adds an enhanced box grid display type to CiviCRM SearchKit.
  • CiviHmac - This extension provides an API3 to do a HMAC check (HmacSignature verify) which will return TRUE or FALSE.
  • CiviSMS Connect - CiviCRM SMS-provider extension with adapters for Alinto, Brevo, Mailjet, generic SMPP 3.4 and a non-delivering dummy driver.
  • SearchKit Kanban - SearchKit Kanban adds a new Kanban board display type to CiviCRM SearchKit. Instead of a table, list or map, the results of any search are shown as cards laid out in columns, where each column is one value of an option-list field you pick (the pivot) — a status, a stage, a type, a category, and so on.
  • Advanced Import Form Processor - Allows use of Advanced Import for complex imports, using the Form Processor interface for mapping and actions instead of custom code.
  • OAuth Login - Provide single sign-on for CiviCRM using OAuth/OpenID Connect. Either Keycloak or Google are supported out of the box.

CiviCRM 6.18 Release

CiviCRM
civicrm.org
2026-09-03 11:02:35
Thanks to the hard work of CiviCRM’s incredible community of contributors, CiviCRM version 6.18.0 is now ready to download. This is a regular monthly release that includes new features and bug fixes. Details are available in the monthly release notes. Your are encouraged to upgrade now ...
Original Article

Thanks to the hard work of CiviCRM’s incredible community of contributors, CiviCRM version 6.18.0 is now ready to download. This is a regular monthly release that includes new features and bug fixes. Details are available in the monthly release notes .

Your are encouraged to upgrade now for the most stable, secure CiviCRM experience:

Download CiviCRM

Users of the CiviCRM Extended Security Releases (ESR) do not need to upgrade. The current version of ESR is CiviCRM 6.16.x (supported until April 2027).

Support CiviCRM

CiviCRM is community driven and is sustained through code contributions and generous financial support.

We are committed to keeping CiviCRM free and open, forever . We depend on your support to help make that happen. Please consider supporting CiviCRM today .

Big thanks to all our partners , members , ESR subscribers and contributors who give regularly to support CiviCRM for everyone.

Credits

AGH Strategies - Alice Frumin; Artful Robot - Rich Lott; Buildkite - Angus Fretwell; Christian Wach; Circle Interactive - Pradeep Nayak; civico GmbH - Johannes Filter; CiviCoop - Jaap Jansma, Erik Hommel, Klaas Eikelboom; Civicopilot - Andy Burns; CiviCRM - Coleman Watts, Tim Otten, Benjamin W; CiviDesk - Yashodha Chaku; civiservice.de GmbH - Torben Bertram; Colored Cow - Tarun Joshi; CompuCo - Muhammad Shahrukh; Coop SymbioTIC - Mathieu Lutfy, Shane Bill; CSES (Chelmsford Science and Engineering Society) - Adam Wood; Dave D; eeprom-foo; Freeform Solutions - Herb van den Dool; Fuzion - Luke Stewart, Toby Messerli; GESTAD - Guillaume Sorel; Gray Digital - Richard Baugh; hiSandog; Jakub Fidler; JMA Consulting - Monish Deb, Seamus Lee; Jonathan Dahan; Lemniscus - Noah Miller; marcelocompucorp; Marvin Müller; Megaphone Technology Consulting - Jon Goldberg; MJW Consulting - Matthew Wire; Nicol Wistreich; Progressive Technology Project - Jamie McClelland; Richard van Oosterhout; Robert Garrigos; Ruza Solutions - Rose; Ryan Morash; Skvare - Mark Hanna, Sunil Pawar; Squiffle Consulting - Aidan Saunders; sushant-cividesk; SYSTOPIA - Dominic Tubach, Jens Schuppe; Tadpole Collective - Kevin Cristiano;Wikimedia Foundation - Eileen McNaughton, Lars Sander-Green, Wenjun Fan

New Extensions

  • Media Scaler - MediaScaler validates, transforms and stores CiviCRM images with privacy-preserving filenames and configurable transformation policies.
  • Membership Payer - A CiviCRM extension that separates the organisation paying for an online membership from the individual member.
  • Housekeeping - Housekeeping adds a daily scheduled job that purges these on a retention you control, one policy per task.
  • JCE Editor - Use JCE as the WYSIWYG editor in CiviCRM (Joomla only).
  • CiviVerify - CiviVerify is a generic CiviCRM extension for issuing and redeeming single-use, time-limited verification links.
  • Security Hotfix for CIVI-SA-2026-35 - Provides a hotfix for the vulnerabilities (CIVI-SA-2026-35, CIVI-SA-2026-37) published on 5 August 2026.
  • Revisionist - Revisionist adds automatic version history to CiviCRM's FormBuilder and SearchKit. Every time a form or search is saved, a snapshot is recorded automatically - so you can browse previous versions, see exactly what changed.
  • confirmstep - This provides an API for other extensions to offer a confirm-by-clicking-link-in-email step.
  • SearchKit Form - SearchKit Form adds a Form display type to CiviCRM SearchKit.
  • Events Listing Block for CiviCRM - Events Listing Block for CiviCRM is a standalone, dynamic Gutenberg block for upcoming public CiviCRM events.
  • EventSession - This extension allows the configuration of sessions for an event, which can take place at the same time. Also allows registering for sessions, including waitlist functionality.
  • SearchKit Box - SearchKit Box adds an enhanced box grid display type to CiviCRM SearchKit.
  • CiviHmac - This extension provides an API3 to do a HMAC check (HmacSignature verify) which will return TRUE or FALSE.
  • CiviSMS Connect - CiviCRM SMS-provider extension with adapters for Alinto, Brevo, Mailjet, generic SMPP 3.4 and a non-delivering dummy driver.
  • SearchKit Kanban - SearchKit Kanban adds a new Kanban board display type to CiviCRM SearchKit. Instead of a table, list or map, the results of any search are shown as cards laid out in columns, where each column is one value of an option-list field you pick (the pivot) — a status, a stage, a type, a category, and so on.
  • Advanced Import Form Processor - Allows use of Advanced Import for complex imports, using the Form Processor interface for mapping and actions instead of custom code.
  • OAuth Login - Provide single sign-on for CiviCRM using OAuth/OpenID Connect. Either Keycloak or Google are supported out of the box.

‘Protest like nobody is watching!’

Internet Exchange
internet.exchangepoint.tech
2026-09-03 08:59:53
Why the ‘Pervert Glasses’ are rightly reviled....
Original Article
privacy and security

Why the ‘Pervert Glasses’ are rightly reviled.

‘Protest like nobody is watching!’
Elise Racine / Emotion: Joy / Licenced by CC-BY 4.0

By Katharina Nocun , originally published on FeministTechPolicy.org .

‘It's hard to imagine a world in several years where most glasses that people wear aren't AI glasses,’ Meta founder Mark Zuckerberg recently proclaimed . Seven million pairs of its AI ‘Glasses’ Meta claims to have sold in the past year alone. On the product page, bespectacled, conventionally beautiful people smile out at you. The use cases sound trivial: listening to music, making phone calls, private snapshots. Added to these are features such as real-time translation and AI search. So far, so convenient?

That Meta is hoping for synergies with its own social media platforms is obvious. As part of a large-scale campaign, an assortment of celebrities is currently promoting the product. One influencer, unboxing hers, gushes that filming her son will now be even easier. I suspect the inconspicuous glasses may well postpone the debate about whether the one-year-old even wants to be ‘content’ . For unlike its predecessor from the house of Google, whose clunky camera invited comparisons with the ‘Terminator’, Meta has opted for two discreetly styled camera lenses at the edge of the frame. A collaboration with the established brand Ray-Ban does the rest to make the frames look unremarkable. A small light does come on during recording, but the internet is full of instructions for circumventing the measure. The ‘hack’ that defeats the latest security update from Meta, which is meant to put a stop to all this: a sticker costing two US dollars.

The consequences are grave. Since the manosphere discovered the product, countless videos have been uploaded in which women are secretly filmed and put on display. The tilt of the filmer's head shows unmistakably which parts of the body are being sized up. Then there are ‘pranks’, some of them aimed at older people who probably would never dream that they are at that moment being filmed by a pair of glasses. Beneath the videos, which sometimes generate hundreds of thousands of views, countless spiteful comments pile up. Meta did announce only recently that it would banish such content from its own platforms. Yet search queries continue to turn up such content. And the perpetrators have countless other digital channels at their disposal for carrying on their ‘game’ undisturbed.

‘It just allows you to be kind of living in the moment with your head up and your hands free,’ enthuses Alex Himel , Vice President at Meta Wearables. I doubt that women feel much the same when, at the club or in the gym, the gazes of his customers linger conspicuously long on their bodies. One person's freedom thus becomes everyone else's loss of control. The mere possibility of being thrown to an online mob, or used as ***** material, gives rise to a profound unease. Worry about covert surveillance and its consequences leads to adaptations in behavior, so-called ‘chilling effects’. The glasses' nicknames circulating online – ‘Pervert Glasses’, ‘Predator Glasses’, ‘Stalker Glasses’ – testify to considerable unease. And there are good reasons why feminists in particular are pushing back hard against the normalization of such products. I, too, now sometimes screw up my short-sighted eyes when a bloke in black Ray-Bans comes towards me at the open-air pool. It feels like the continuation of patriarchal entitlement and appropriation of space by new technical means.

The lack of representation of a heterogeneous society in Silicon Valley, combined with governments' lack of will to regulate, has for some time been imposing massive negative externalities on those affected. Women influencers now advise singing Disney songs during unwanted filming – in the hope of provoking a copyright takedown once the video is uploaded. This is unlikely to help in most cases , but it makes plain how little anyone trusts Meta to solve the problem. It is, after all, difficult to believe in the noble intentions of a company boss who once built a platform on which users could vote on the attractiveness of female fellow students on the basis of photos used without their consent. The guiding principle associated with Meta, ‘Move fast and break things’, all too often degrades those who are ‘other’ – from the developers' and investors' point of view – to tiresome collateral damage. Sacrifices one must be prepared to make – in the service of profit maximization. That goes for AI nude deepfakes. That goes for AIs that, on the basis of biased training data, advise women applicants to ask for lower salaries . And for photo services that take Black people for ‘gorillas’ . Many small but also large decisions that shape the lives of billions of people. Profits are privatized, while the harms offloaded onto users and society are waved away as teething problems. Whoever criticizes is obstructing progress.

Kylie Jenner recently presented a model of her own as part of the Meta Glasses campaign. The billionaire owns several estates with large gardens, high fences and security staff. People like her need not worry about being filmed by strangers with Meta Glasses while working out at the gym. After all, the amenities of the average billionaire's villa include private pools, tennis courts and assorted further fitness facilities. Nor does Mark Zuckerberg need to fear that his three daughters will be secretly filmed as they romp about. The man who since the 2010s has never tired of explaining to the world that the old norm of privacy is obsolete has for years been systematically buying up the plots of land adjacent to his estate .

It has long been technically possible for friends to strap a GoPro camera to their heads and film us and the world, unasked, day in and day out, in the service of content generation. Social norms have prevented this. Social norms that exist for good reason, and whose point perhaps even Zuckerberg secretly believes in. It was precisely these norms that sealed the end of ‘Google Glass’ around ten years ago. Because they matter all the more not despite but because of digitalization. Who, after all, wants a ‘Glasshole’ – as the wearers were derided at the time – at a children's birthday party?

Honestly, I do not want to imagine a future in which the majority of glasses worn in public space are ‘smart’. Not only because I do not want men in glasses giving me the unpleasant kind of goosebumps at the public swimming pool, and because I cannot afford a private pool. What is at stake here, rather, are central societal questions of power and control, which today surface in supposedly isolated examples like these in consumer protection. At its core, what is being negotiated here is the normalization of a kind of surveillance that is likely to bring problems of an altogether different order in the future. Investigative reporting recently revealed that the code of the Meta Glasses at one point contained facial recognition software. The company removed the ‘feature’, which had not been armed, only after public criticism. In India , comparable technologies are already being deployed by security forces. ‘Direct Palantir interface – when?’, a follower recently asked me. Honestly, I hope never.

Katharina Nocun is an author, commentator and podcaster who studied political science and economics in Münster and Hamburg. Her work examines the tensions between digitalization and democracy. She has published four books and has been awarded the Marburger Leuchtfeuer (2017) and the Madsack Award (2023).


US National Internet Governance Forum 2026

The US national Internet Governance Forum returns, meeting outside Washington DC (In Philadelphia, PA!) for the first time. It's the first national forum to convene since the UN General Assembly made the IGF a permanent UN body in December 2025, ending 20 years of temporary mandates and is facilitated by the Internet Society's DC chapter.

A hybrid day of three sessions, Wednesday September 9 running 10:30 to 16:00 EDT .

Want to appear here? Sponsor a newsletter.


Support the Internet Exchange

If you find our emails useful, consider becoming a paid subscriber! You'll get access to our members-only Signal community where we share ideas, discuss upcoming topics, and exchange links. Paid subscribers can also leave comments on posts and enjoy a warm, fuzzy feeling.

Not ready for a long-term commitment? You can always leave us a tip .

Become A Paid Subscriber

🚨

Stop press! Do you enjoy our links? Links are now available to paid subscribers only. Become a paid subscriber today.

The Lost Tailor of Indie Rock (and His 'Project Runway' Protégé)

hellgate
hellgatenyc.com
2026-09-03 16:02:30
Plus, Curtis Sliwa rejects our request to accompany him to the club....
Original Article

Great! You’ve successfully signed up.

Welcome back! You've successfully signed in.

You've successfully subscribed to Hell Gate.

Your link has expired.

Success! Check your email for magic link to sign-in.

Success! Your billing info has been updated.

Your billing was not updated.

Prime Gaps at Most 186

Hacker News
github.com
2026-09-03 15:18:56
Comments...
Original Article

This repository contains a Lean 4 formalization of a prime-gap bound and a Python numerical certificate. The Lean results remain conditional on three explicit input axioms ; the cited mathematical estimates and numerical computations have not been turned into Lean proofs of those inputs.

The result

For the sequence of primes $p_n$ , the target bound is

$$\liminf_{n\to\infty}(p_{n+1}-p_n)\le 186.$$

The development derives $\mathrm{DHL}[40,2]$ from the inputs below: every admissible set of forty integer shifts has infinitely many translates containing at least two primes. Admissibility means omitting a residue class modulo every prime. Applying this to the included tuple of diameter 186 gives the gap bound.

The main declarations in PrimeGaps186.lean , in namespace PrimeGap186 , are:

Declaration Result
dhl_40_2 $\mathrm{DHL}[40,2]$ for every admissible integer tuple.
infinite_two_prime_translates_admissibleTuple Infinitely many two-prime translates of the explicit tuple.
primeGapLiminf_le_186 The consecutive-prime gap bound.

Assumed Deligne-type estimates

For a prime $p$ , write $e_p(x)=\exp(2\pi i\widetilde{x}/p)$ , where $\widetilde{x}$ is any integer representative of $x\in\mathbb{F}_p$ . Define

$$\mathrm{Kl}_3(c;p) =\frac1p\sum_{\substack{x_1,x_2,x_3\in\mathbb{F}_p\\x_1x_2x_3=c}} e_p(x_1+x_2+x_3),$$ $$K_2(c;p)=\sum_{u\in\mathbb{F}_p^\times}e_p(u+c/u).$$

The axiom PrimeGap186.kloosterman3_bound assumes the following bound for every prime $p$ and all $c\in\mathbb{F}_p^\times$ :

$$\left|\mathrm{Kl}_3(c;p)\right|\le 3.$$

This follows from Deligne's theorem as stated in Nicholas M. Katz, Gauss Sums, Kloosterman Sums, and Monodromy Groups , Annals of Mathematics Studies 116, Princeton University Press (1988), Theorem 4.1.1(1)–(2), p. 49 . With $n=3$ , trivial multiplicative characters, and $b_1=b_2=b_3=1$ , rank three and weight two give the raw bound $3p$ ; our normalization divides by $p$ .

The axiom PrimeGap186.kloosterman2_correlation_bound assumes the following bound for every prime $p$ and all $A,B\in\mathbb{F}_p^\times$ :

$$\left|\sum_{t\in\mathbb{F}_p\setminus\{0,-1\}} K_2(A/t;p)\,K_2(B/(t+1);p)\right|\le 8p\sqrt p.$$

This is Étienne Fouvry, Emmanuel Kowalski, and Philippe Michel, The Friedlander–Iwaniec character sum , 14 June 2013, Proposition 2, p. 1 . Their normalized $\mathrm{Kl}_2(c)$ equals $K_2(c;p)/\sqrt p$ after inverting the summation variable, so their $8\sqrt p$ bound becomes $8p\sqrt p$ here. No condition $A\ne B$ is imposed; the two poles are excluded even when $A=B$ .

These estimates are established in the cited literature, but remain unproved inputs in this Lean development.

Numerical input and certificate

PrimeGap186.physical_integral_bounds assumes 104 outer and 45 inner physical-integral upper bounds, plus three cap bounds.

The Python certificate recomputes the trial from scratch. The tested environment used Python 3.12.13, NumPy 2.2.6, python-flint 0.9.0, and a custom FLINT 3.6.0 build with corrected signed polynomial convolution (not bundled).

python3 -B prime_gap_186_certificate.py --workers 4 --output prime_gap_186_fresh.json

Use a new output path. Keep PYTHONOPTIMIZE unset and do not use -O or -OO . Mandatory floating-point and signed-convolution checks must pass. A successful run produces a receipt with passed: true ; it does not discharge any Lean axiom.

Building and verification

The project pins Lean 4.34.0-rc2 and its Mathlib dependencies. With elan installed, run:

lake exe cache get
lake build PrimeGaps186

The registered Lean build passed without errors or warnings. Comparator matched all three results to Challenge.lean , and Nanoda and Lean’s kernel accepted their proofs in a local Colima Linux VM. The configuration permits the three documented project axioms plus propext , Quot.sound , and Classical.choice (six total); this verifies conditional proofs, not the inputs themselves. The numerical certificate is unchanged from its earlier passing run.

Challenge.lean specifies the statements and input assumptions, with three intentional theorem placeholders. See the Comparator instructions and formalization metadata for the checking setup and status.

Project contributions use Apache 2.0 ; existing third-party notices remain applicable.

The asteroid currently hitting front end web development

Hacker News
nolanlawson.com
2026-09-03 15:17:24
Comments...
Original Article

A lot of the educators I admire in the frontend web space seem to be either bowing out or dialing back their efforts: Axel Rauschmayer , Salma Alam-Naylor , Josh W. Comeau , to name a few. Other well-known luminaries like Kent C. Dodds , Addy Osmani , Rachel Nabors , and Lydia Hallie have pivoted from talking about frontend development to talking about… well, take a wild guess.

I never made a living from talking about web dev, but I do have this blog, and I’ve done conference talks and podcasts about stuff I’m excited about. Recently for example, my passion was explaining all the ins and outs of CSS performance: how shadow DOM works , how the browser’s style engine works , the traps of CSS-in-JS , etc.

Just for kicks, I decided to ask Claude Sonnet how it would handle a Chrome trace with high “Style Calculation” costs. This is one of my favorite brain-teasers, because it’s the kind of thing that I saw web devs – even experienced ones! – trip up on over and over again. Claude gave a perfectly admirable answer:

Click to see

Prompt: Answer without searching the internet: you’re looking at a Chrome trace, and you see repeated spans of high Style cost but relatively low Layout cost. What kind of things do you look for in the webapp to optimize? What do you measure next?

What “Style” cost actually represents

The Style (Recalculate Style) phase is where the browser matches CSS selectors against the DOM and computes the final computed style for each affected element. It’s expensive independent of whether anything actually moves or resizes (that’s Layout’s job). So if Style is high but Layout is low, you’re likely paying for selector matching / invalidation over many elements , not for expensive geometry .

What to look for in the webapp

1. Selector complexity and count

  • Overly complex or deeply nested selectors ( .a .b .c >; .d + .e ), especially descendant combinators, force the engine to walk more of the DOM/ancestor chain per match attempt.
  • Universal selectors or attribute selectors ( [data-foo="bar"] ) applied broadly.
  • CSS-in-JS libraries that generate huge numbers of unique class names/rules (style recalculation has to consider the whole rule set).

2. Invalidation scope — this is usually the big one

  • A class/attribute/style toggle high up in the DOM tree (e.g., toggling a class on <body> or a top-level container) can force style recalculation on large subtrees even if only a few elements’ final styles change.
  • Check whether a single state change (e.g., a “theme” class, a “loading” class, a hover state) is invalidating far more elements than necessary. Chrome’s “Selector Stats” (enable in DevTools Performance settings) will show you which selectors are slow and how many elements they were tested against — this is the single most useful next measurement.

3. Frequency/amplification

  • Something re-triggering style recalc many times per frame — e.g., reading a style/layout property in a loop right after a class change (forces synchronous recalc), or a JS animation using .classList.toggle() or inline style updates on many nodes per rAF tick instead of batching.
  • Repeated small DOM mutations each forcing a style pass rather than being batched into one.

4. Inherited/computed property propagation

  • Changing an inherited property (like font-size or color on a common ancestor) forces recompute of all descendants’ computed styles, even without layout changes (e.g., color , visibility , cursor are Style-only, not Layout-triggering).
  • Custom properties (CSS variables) changed at a high-level scope — updating a --custom-prop on :root or a shared ancestor recomputes style for every element referencing it.

5. Shadow DOM / component boundaries

  • If using a framework with lots of shadow roots or scoped styles, check whether style recalculation is being needlessly repeated per component instance due to non-shared stylesheets.

What to measure next

  1. Enable “Selector Stats” in the Performance panel (gear icon → Enable selector stats). Re-record the trace. This gives you, per Recalculate Style event, the top slow selectors and match counts — that tells you directly which CSS rules and how many elements are responsible.
  2. Check the “Recalculate Style” event’s initiator/call stack in the trace to see what JS triggered it — a class toggle, a style.setProperty , an animation frame callback, etc.
  3. Count how many elements are affected per recalc — DevTools shows “Elements Affected” per Recalculate Style event in the summary pane. Compare that number to how many elements actually changed appearance — a big gap indicates over-broad invalidation.
  4. Look at where in the DOM the triggering mutation happens — is it near the root (broad invalidation) vs. scoped to a small subtree (narrow, cheap)?
  5. Check for forced synchronous style — look for “Forced reflow” purple warnings; even though you said Layout is low, sometimes a forced style read ( getComputedStyle ) interleaved with a DOM write shows up as many small back-to-back Style events rather than one batched one.

Typical fixes once you find the culprit

  • Scope class/state toggles to the smallest subtree possible instead of a common ancestor.
  • Simplify selectors, prefer single class selectors over descendant chains.
  • Move CSS custom property updates to the smallest scope needed.
  • Batch DOM/class changes so recalculation happens once, not per-mutation.
  • Use content-visibility: auto or contain: style layout on independent subtrees to limit invalidation scope.

These days, given a slow-loading website, even as someone who’s written about browser performance for years and who literally worked on a browser performance team , I would probably just chuck a Chrome trace at Claude Code and have it suggest improvements. In fact I’ve done this very thing in my day job and gotten some good results.

The future of frontend

So where does this leave frontend dev education? Not in a great place obviously; I wish I had some more uplifting answers for people who (like me) used to get a lot of fulfillment out of trying to raise the bar for frontend developers everywhere. I do have some guesses though, and I think the problem is still worth puzzling through.

The core question is where frontend development itself lands in this new era. Sadly it feels to me like there are several trends pointing against increased investment in frontend knowledge:

The frontend is less risky to just hand to an agent. If you’re using an agent to write a database migration, you probably want to put it through several rounds of AI code review, scrutinize it yourself, run it on staging first, etc. If you write a React component with an agent, though, then the risk of just yolo’ing it into production is (typically) much lower.

Note I’m not saying there are zero risks: the agent could mess up accessibility, it could cause an infinite loop that blocks users, etc. But in general, frontend code is a lot more ephemeral and replaceable than other types of code. So I expect many AI coders will feel comfortable just letting their agent handle it unsupervised (for better or worse).

DevExp is becoming less critical overall. A lot of the pre-LLM discussion in the frontend space was about ergonomics versus outcomes: “The ‘developer experience’ bait-and-switch” by Alex Russell is a great example. For another example, Svelte and Solid have long argued that their ergonomics lead to better outcomes than React: less code, better performance, etc.

Meanwhile, Cursor and Viget have blogged about migrating their codebases from Solid and Lit, respectively, to React. Since rewrites are less expensive with agents, this may be a bit surprising: why not move to the more performant/less verbose framework? The answer (explicitly in Cursor’s case, and I suspect for Viget as well) is of course: “the agents know React.” For better or worse, React is heavily overrepresented in the training weights, and “agent experience” is starting to matter more than developer experience.

Standards will catch up. I’ve been out of the web standards space for a couple years now, so this is pure speculation on my part. But I imagine that a lot of the efforts to improve the ergonomics of building websites – better CSS shorthands, terser JavaScript syntax, etc. – will become perceived as less important relative to things that actually move the needle on performance, capabilities, etc. At the end of the day, it’s just not very different for an agent to write 3 lines of CSS instead of 1, and anyway using the newer syntax might actually be harder because you have to coach the agent about things that aren’t in its training weights.

In some ways this shift might have already been underway. I remember several years ago at TPAC , well before the AI coding boom, I told someone on the Chrome team that I was working on web component standards. They responded that they weren’t interested in that, because those APIs only affected the developer experience and didn’t actually make the browser more capable (e.g. Project Fugu ). That stuck with me because it’s a good point: APIs like shadow DOM and custom elements don’t give web developers any new superpowers; they just change where and how the code gets authored. I expect such things will move out of the spotlight as AI coding takes over.

This doesn’t mean that standards will disappear from the topics a frontend dev needs to keep up on, but I imagine it will become less about “use this newer syntax” (an evergreen source of material for conference talks and articles) and more “here are these emerging capabilities.” And I predict the latter group will be much smaller than the former, since they tend to be more contentious for standards bodies and there’s just a smaller pool of features to draw from.

Whither frontend education?

So how can the field of frontend education adapt to this hostile future? To avoid being utterly bleak, here are some positive directions I think it could go in.

First off, the agents still need to be educated about the big picture. Agents and harnesses seem to love writing React and specifically SPAs, but SPAs are not the answer to everything . You can burn a lot of tokens having an agent write a big complex SPA for your marketing site, and then fix all the bugs with the back button, focus state, performance, etc., or you can just choose an MPA framework like Astro or Eleventy and call it a day. Maybe these frameworks will be a bit harder for the agents to work with (specifically Astro since it kinda-sorta looks like React but isn’t), but my guess is that since you’re writing ~50% less code overall it won’t matter.

Second, making websites that work well for agents is probably going to be a fruitful endeavor for the near future. Vercel’s is-agentic is a good example of this. Ironically, this points back to good fundamentals that public-facing websites should have been doing anyway: server-rendered content, proper accessibility, page speed, etc. But if slapping the word “AI” on it is what gets people to care about it then hey, I’m all for it.

Note that I’m a little bit less sanguine about this second point, because I’m not sure the web even survives in its current form as agents become more of a thing. If I want to figure out how much it costs to fly from Seattle to Paris, I’d much rather ask an agent than click through an infuriating series of buttons on a slow-loading website. The only reason I can’t is because these websites explicitly block bots, or they don’t offer an MCP, but I’m sure there are several startups champing at the bit to solve that problem. So I’m not sure how sustainable the current situation is.

Third, we can offer consulting services for vibe-coded monstrosities. A massive amount of AI-generated frontend code is being pumped out right now, and some of it (to use a Claude-ism) will certainly become “load-bearing.” If those websites are slow, non-compliant, and riddled with security holes, then it may not be enough to ask the agent “fix my website pls.” There could be an opportunity here for real expertise, especially if there’s money on the line and the vibe coder’s knowledge of web development doesn’t extend past “websites are apps hosted on the internet.”

(I acknowledge that this is the shakiest of my three points, since I can totally imagine the next generation of “self-healing” web apps to eclipse the average expert in 2027 or 2028. But for the time being: yes, expertise still matters.)

Conclusion

The point of this post wasn’t to make myself feel better, or to dance on the graves of all the careers that have been upended by the recent AI boom. I’m a naturally gloomy person, and this post was me allowing myself to wallow in my own gloominess. I don’t take any pleasure from noting that the huge body of knowledge I’ve built up over the years has been rendered nearly obsolete, nor am I happy to see the same thing happen to my much-more-qualified peers. But pretending that it’s not happening isn’t a valid strategy either.

There’s a mood in some of the blogs I read these days along the lines of “I’m so tired of talking about AI” or “Please don’t mention AI to me ever again.” I’m sure some of this is a kind of world-weary, above-it-all air that feels good to wear as a badge of distinction. But I think a lot of it also comes from real fear. It’s scary to admit that you don’t know what’s going to happen in a year. It’s destabilizing to imagine your career going along a certain trajectory, serenely landing at retirement, and then to see everything upset just a few years from your goal.

The metaphor I’ve been using is that an asteroid just hit the earth, and we’re still surveying the wreckage. It’s hard to predict what will happen after the dust settles (let alone which tiny rodents will usher in the Age of Mammals!), but ignoring the crater altogether seems like the worst kind of denial. Another metaphor is covid: when covid hit, I don’t recall thinking, “Ugh, I’m so tired of talking about covid” – instead, I wanted to learn everything I could about viruses, epidemiology, masking, etc. This turned out to be a good idea, since covid was going to dominate my life for the next few years (at which point yes, I did finally get tired of talking about it!).

I hardly have a crystal ball, but this post was my attempt to think through where my most cherished field might be going in the future. I admit that I have a lot less skin in the game these days: I’m out of web standards, I don’t even work on the frontend at my current gig, and my blog has mostly been a lot of wailing and gnashing of teeth about AI rather than my usual menu of browsers, performance, accessibility, etc. That said, I still have a lot of love and respect for the frontend field, and I care about what happens to it in the future. It may be unrecognizable in just a few years, but if nothing else, I hope my peers find a way to navigate all these changes and to thrive in this weird new world.

Court Rules Against Citizen Journalists in DMCA Takedown Case—EFF Will Appeal

Electronic Frontier Foundation
www.eff.org
2026-09-03 15:11:56
A federal court in Massachusetts has ruled that copyright holders can issue online takedown notices based on a subjective belief of copyright infringement, even when that belief is unreasonable and self-serving. The case was brought by our client, Channel 781 News, after takedown notices temporarily...
Original Article

A federal court in Massachusetts has ruled that copyright holders can issue online takedown notices based on a subjective belief of copyright infringement, even when that belief is unreasonable and self-serving. The case was brought by our client, Channel 781 News, after takedown notices temporarily shut down the citizen journalism group's YouTube channel. We think the court set the bar far too low for copyright takedowns, and we plan to appeal.

Channel 781 is a group of independent, volunteer journalists who report on local affairs in Waltham, Massachusetts. That includes posting short, newsworthy excerpts from recordings of city government meetings produced by Waltham Community Access Corporation (WCAC), the city's public access television station.

In September 2023, WCAC sent three copyright takedown notices to YouTube targeting fifteen of Channel 781's videos. YouTube removed the videos and, under its three-strikes policy, temporarily disabled Channel 781's entire account—just days before a local election.

Represented by EFF and Brown Rudnick LLP, Channel 781 sued WCAC under Section 512(f) of the Digital Millennium Copyright Act (DMCA), which provides a remedy when a copyright holder knowingly makes material misrepresentations in a takedown notice.

When Is a Copyright Holder Responsible for a Wrongful Takedown?

Fair use is the legal right to use copyrighted material without permission, when doing so serves purposes like criticism, commentary, or creating something new. Fair use is not copyright infringement, and courts have recognized that copyright holders must consider fair use before using the DMCA's powerful notice-and-takedown process.

In this case, Channel 781 argued that WCAC accused it of copyright infringement without making a good-faith assessment of whether its videos were fair use.

The evidence showed that WCAC's analysis was seriously deficient. The court noted that Chris Wangler, the WCAC employee who sent the notices, didn’t consider several facts relevant to fair use. For instance, Channel 781 used relatively small portions of WCAC's recordings, and the underlying recordings were factual public meetings, not a creative work. WCAC also gave little or no weight to whether Channel 781's use harmed any market for the recordings.

There’s also strong evidence that WCAC had motivations unrelated to copyright. WCAC objected to its footage being used to criticize local officials and advance political viewpoints. And WCAC sent the takedown notices during a local election, shortly after Channel 781 posted a campaign statement by Waltham's mayor that WCAC had mistakenly made available online.

Despite this evidence, the court concluded that WCAC had a subjective good-faith belief that Channel 781's videos were infringing. We disagree.

A Subjective Belief Should Not Be a Free Pass

Channel 781 argued that a copyright holder’s belief that material is infringing must be both genuinely held and objectively reasonable. WCAC argued that a subjective good-faith belief is good enough. Unfortunately, the court agreed with WCAC.

The court emphasized that Wangler had read up on fair use, watched a short YouTube video explaining the doctrine, and distinguished between videos he thought might qualify as fair use and those he believed did not. That was enough, the court concluded, to establish subjective good faith—even though Wangler’s analysis ignored important facts relevant to fair use. As the court put it, Section 512(f) does not require “a perfect or even reasonable fair use analysis.”

That is an alarmingly low bar for copyright holders seeking to remove someone else’s speech from the internet. A DMCA takedown can cause lawful speech to disappear almost immediately. As Channel 781 experienced, multiple notices can even result in an entire channel being disabled.

If a copyright holder can avoid liability despite a cursory, incomplete, and objectively unreasonable analysis that ignores important facts—even when there’s evidence that the copyright holder wanted to suppress critical speech—the obligation to consider fair use risks becoming little more than a box-checking exercise. That interpretation threatens to strip Section 512(f) of much of its force.

Even Under a Subjective Standard, WCAC Fell Short

Even accepting the court’s subjective standard, WCAC's cursory consideration of fair use should not have been enough. WCAC disregarded important fair use considerations, and the record included statements suggesting that it believed people generally needed permission to reuse its footage—an understanding at odds with fair use. There was also evidence that WCAC objected to Channel 781's political use of its footage, and had motivations for the takedowns unrelated to copyright.

Taken together, these facts raise serious questions about whether WCAC genuinely considered fair use, rather than using copyright as a rationale for removing material it did not like.

The Court Did Not Find That Channel 781's Videos Infringed

Importantly, the court's analysis recognized Channel 781’s strong fair use argument: the group used short excerpts from factual recordings of public government proceedings, selecting clips for their newsworthiness, and making them easier for the public and journalists to find, share, and discuss.

The opinion even states that WCAC's fair use analysis “may have been deficient.” But under the purely subjective standard it adopted, the court concluded that it could not reject WCAC's professed belief—even if the court itself “would have reached the opposite conclusion” on fair use.

We plan to appeal this decision to the First Circuit Court of Appeals. Copyright law should not allow a rightsholder to suppress critical reporting or political speech through the DMCA and escape accountability simply by claiming it believed the speech was infringing. Section 512(f) is supposed to provide protection against wrongful takedowns. We will keep fighting to ensure that safeguard actually protects people.

GPT-6 Astra

Hacker News
openai.com
2026-09-03 14:41:05
Comments...

Qwen 3.8 27B available on Cerebras at 1500 tok/SEC

Hacker News
inference-docs.cerebras.ai
2026-09-03 14:32:13
Comments...
Original Article

Models on Cerebras public endpoints are available on the free trial and pay-as-you-go tiers, subject to rate limits and pricing . For additional model families, reserved capacity, higher throughput, and production SLAs, see Dedicated Endpoints .

Available Models

Model Compression

This section provides transparency about the compression state of each model available on our platform. We host a variety of open-source models from the community. We do not currently host pruned models on our public endpoints. All models served through our public endpoints are the original, unpruned versions. While we conduct research on pruning techniques like REAP (Router-weighted Expert Activation Pruning), these pruned models are shared with the research community on Hugging Face but are not available through our shared API. You can read more about REAP in our research blog . All of our public models are unpruned. Cerebras uses selective weight-only quantization only during storage to preserve maximal quality. This means that the weights are stored in partial 16-bit / 8-bit / 4-bit, in-line with industry standards. For quality, sensitive layers are stored at full precision with dequantization on the fly, so operations are done in high precision. The activations, attention, and kv cache remain in full precision and unquantized.

Frequently Asked Questions

No. We are committed to serving the original models for all existing endpoints, without modification. We do not alter model architectures via pruning on our hosted portfolio. If we explore additional compression techniques (like pruning) in the future, these would be offered as separate endpoints with pruning-specific names, ensuring complete transparency and allowing you to choose which version best fits your needs.

Our REAP pruned models are available on Hugging Face for research and experimentation purposes: Cerebras REAP Collection . These models demonstrate our pruning research but are not served through our production API.

Compression is an umbrella term for techniques that reduce model size or computational requirements. Common compression techniques include:

  • Quantization : Reducing the precision of numbers used to represent model weights (e.g., converting from FP16 to FP8). This reduces memory usage without changing the model’s architecture.
  • Pruning : Permanently removing parts of a model, like layers or experts, to reduce model size. This changes the model’s architecture and creates a different model.

HPE patches critical ArubaOS-CX remote code execution flaw

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 14:28:12
Hewlett Packard Enterprise (HPE) has patched a critical vulnerability in the ArubaOS-CX network operating system that could lead to remote code execution. [...]...
Original Article

HPE patches critical ArubaOS-CX remote code execution flaw

Hewlett Packard Enterprise (HPE) has patched a critical vulnerability in the ArubaOS-CX network operating system that could lead to remote code execution.

Tracked as CVE-2026-73749, the security issue is a buffer overflow that allows unauthenticated remote attackers to send specially crafted packets to an affected daemon process, achieving code execution with elevated privileges.

“Multiple vulnerabilities exist in a daemon of ArubaOS-CX that may allow for improper processing of malformed input,” reads HPE’s bulletin .

“An unauthenticated remote attacker could exploit these vulnerabilities by sending specially crafted packets to the affected service.”

Affected release branches and fixes listed in the bulletin are:

  • 10.18.0001 → upgrade to 10.18.1002+
  • 10.17.1021 and earlier → 10.17.1030+
  • 10.16.1051 and earlier → 10.16.1060+
  • 10.13.1180 and earlier → 10.13.1190+
  • 10.10.1180 and earlier → 10.10.1181+

HPE noted that the AOS-CX 10.10.1181 version has reached End of Maintenance (EOM) and only receives fixes for internally discovered, critical issues, a condition that also applies to CVE-2026-73749.

ArubaOS-CX is HPE Aruba Networking’s operating system for its enterprise-grade network switches, typically used by large businesses, government agencies, universities, healthcare organizations, data centers, and service providers.

HPE's security bulletin also covers a set of 23 other security vulnerabilities, some with high severity ratings, between 8.1 and 8.8:

  • CVE-2026-73750: A low-privileged authenticated remote attacker can send malformed or truncated input to an AOS-CX management module, potentially causing denial of service or executing code with elevated privileges.
  • CVE-2026-73751: A low-privileged authenticated user can submit crafted input through the AOS-CX web-based management interface to execute arbitrary commands on the underlying operating system.
  • CVE-2026-73752: An unauthenticated attacker with adjacent-network access can exploit an AOS-CX API endpoint to write arbitrary files to the underlying operating system, potentially leading to remote code execution.
  • CVE-2026-73753: A low-privileged authenticated user can exploit affected AOS-CX command-line operations to execute arbitrary commands as a privileged user on the underlying operating system.
  • CVE-2026-73782: An unauthenticated attacker with adjacent-network access can exploit a format-string vulnerability in the AOS-CX command-line interface to execute arbitrary code as a privileged user on the underlying operating system.
  • CVE-2026-73781: An authenticated remote attacker can exploit a stored cross-site scripting vulnerability in the AOS-CX web-based management interface to execute arbitrary scripts in an administrator’s browser if the administrator interacts with the affected content.
  • CVE-2026-73780: An unauthenticated remote attacker can exploit missing CSRF protections in some certificate-authenticated AOS-CX sessions to submit arbitrary input to the web-based management interface by convincing an authenticated user to open a crafted URL.
  • CVE-2026-73779: An unauthenticated attacker with adjacent-network access can bypass authentication controls on AOS-CX switches, potentially exposing sensitive information, enabling unauthorized modifications, and disrupting services.
  • CVE-2026-73778: An unauthenticated remote attacker can use a predictable factory-default password to obtain full administrative control of an AOS-CX device that remains in its factory-default or post-ZTP state before an administrator configures credentials.
  • CVE-2026-73777: An unauthenticated remote attacker can exploit vulnerabilities in an AOS-CX API endpoint to bypass access controls and escalate privileges.

The vendor “strongly encourages” customers to upgrade to one of the fixed releases listed in the bulletin.

HPE mentions that, at the time of the bulletin’s publication, it was not aware of active exploitation or publicly available proof-of-concept exploits targeting the listed flaws.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

Phil Schiller Steps Down From Running App Store and Product Events

Daring Fireball
www.bloomberg.com
2026-09-03 12:39:09
Mark Gurman: Apple Inc.’s Phil Schiller, one of the most visible and influential executives across both the Steve Jobs and Tim Cook eras, has stepped down from his role leading the App Store and product events. The 66-year-old executive, who was Apple’s senior vice president of marketing until ...
Original Article

We've detected unusual activity from your computer network

To continue, please click the box below to let us know you're not a robot.

Why did this happen?

Please make sure your browser supports JavaScript and cookies and that you are not blocking them from loading. For more information you can review our Terms of Service and Cookie Policy .

Need Help?

For inquiries related to this message please contact our support team and provide the reference ID below.

Block reference ID:06bdb09c-a7c2-11f1-b456-fcb857a679ca

Get the most important global markets news at your fingertips with a Bloomberg.com subscription.

SUBSCRIBE NOW

MapQuest Refuses to Relabel Lake Ontario, Rewarded With Surge in Popularity

Daring Fireball
thehill.com
2026-09-03 12:30:09
Finya Swai, reporting for The Hill two days ago: MapQuest has surged in popularity on the app charts after the mapping service said it would not rename Lake Ontario to “Lake America” after President Trump signed an executive order changing its name. The company said its mobile app received hund...

ICE Gave New Hires Access to Restricted Info on Palantir App Before They Passed Background Checks

Intercept
theintercept.com
2026-09-03 12:26:09
Palantir created ELITE, a powerful new app for ICE to target immigrants. The feds never published a legally required privacy assessment for it. The post ICE Gave New Hires Access to Restricted Info on Palantir App Before They Passed Background Checks appeared first on The Intercept....
Original Article

During the height of President Donald Trump’s winter immigration enforcement surge in Minneapolis, a new AI-driven “alien” targeting app appeared on the phones of U.S. Immigrations and Customs Enforcement deportation officers.

Created by tech giant Palantir, a CIA-backed firm known for data mining and using artificial intelligence for everything from warfighting to “ predictive policing ,” the ELITE app helps ICE target immigrants and issues a “confidence score” for how accurate the information on a target is. The app analyzes data from government agencies and other sources, producing dossiers on targets, compiling them into lists, and mapping their locations.

The debut of ELITE — Enhanced Lead Identification and Targeting — came just as ICE added over 12,000 employees through an expedited hiring surge , placing a badge and a gun in the hands of new recruits in record time, thanks to cuts to ICE’s training curriculum .

Thousands of the new ICE hires, then, were able to hit the streets without cleared background checks, according to reporting by Reuters in early 2026.

“Some of these guys should’ve never been hired, let alone have access to the information on ELITE.”

The hiring spree at ICE’s Enforcement and Removal Operations division, coupled with the powerful new handheld technology of the ELITE app, created potential civil liberties nightmares and threats to national security, according to ICE whistleblowers, former Department of Homeland Security officials, and legal experts who spoke to The Intercept.

“No one should have been hired by DHS before background reviews were completed. This never happened in previous administrations,” said Mary Ellen Callahan, former chief of staff to the deputy secretary of Homeland Security. “Furthermore, giving the newly hired ICE ERO staff access to sensitive databases such as ELITE threatens public safety by allowing non-vetted teams to access and potentially misuse data.”

The ELITE app, Callahan said, did not go through the usual process government tools undergo to prevent abuses and ensure privacy rights.

“It’s one of the first applications they give new officers so they can start working,” said one ICE deportation officer who came through the hiring surge. “You can access it without full background clearance.”

“Some of these guys should’ve never been hired, let alone have access to the information on ELITE,” the officer, who asked for anonymity to protect their livelihood, told The Intercept.

Every ICE deportation officer is issued a phone, where the ELITE app comes standard, according to five ICE officials who spoke to The Intercept. (Neither the Department of Homeland Security nor Palantir responded to requests for comment.)

The five ICE officials, who each work in different regions across the country, said deportation officers without completed background checks continue to work in all their jurisdictions, some of whom were hired nearly a year ago.

No Privacy Assessment

ELITE’s user guide identifies a dozen distinct sources that the app draws from. The databases include sensitive data sets like addresses, criminal histories, immigration records, court rulings, and other personal information about both immigrants and U.S. citizens.

Much of that information would constitute what the government calls PII, or personally identifiable information. According to a Department of Homeland Security document that catalogs the agency’s use of artificial intelligence, the ELITE app does involve PII.

A 2002 law, however, says that government agencies must conduct and publish the findings of a “privacy impact assessment” for “all new or substantially changed technology that collects, maintains, or disseminates personally identifiable information (PII),” according to a Justice Department summary of the statute.

The processes are designed to assess how technology affects personal privacy and outline what safeguards are in place to ensure accountability if systems are misused.

“You can access it without full background clearance.”

Yet the Department of Homeland Security privacy office hasn’t published an assessment for ELITE, according to Callahan, the former Homeland Security official, who also served as the department’s chief privacy officer.

“The DHS privacy office should have worked with ICE to publish a privacy impact assessment,” said Callahan, noting a general lack of productivity by the privacy office. “In fact, the DHS privacy office has only published one PIA all year. In comparison, I published 228 PIAs in my three-and-a-half years as privacy officer.”

The failure to conduct a privacy impact assessment has a profound impact on transparency and accountability, the very aspects of privacy policy the E-Government Act of 2002 was intended to regulate.

“This is not a technicality,” said Clare Garvie, a privacy lawyer and deputy director of technology policy at the New York University Law School’s Policing Project. “PIAs are an essential component of transparency and privacy governance, they are how the public understands what information is collected about us, how long it is kept, who can use it, and what remedies exist if it is wrong or subject to misuse.”

“If ICE can’t fulfill this prerequisite,” Garvie said, “I lack confidence in its ability to use the tool in a lawful, privacy-protective manner in the field.”

The Department of Homeland Security site for cataloging its uses of AI does list a privacy impact assessment on its page for ELITE, but the assessment is not actually for the ELITE app. Instead, the link goes to a 2019 privacy assessment for ICE’s Enforcement Integrated Database.

The Enforcement Integrated Database is just one of the systems ELITE incorporates into its searches, meaning the PIA only scratches the surface of what personally identifying information appears in ELITE and how the app organizes the data.

“The document DHS points to as fulfilling this obligation was updated in 2019, years before it acquired ELITE,” said Garvie. “This PIA completely fails to describe the app’s data sources, its AI analysis, or the inferences it produces that are used to focus immigration investigations and removal operations.”

Public concerns surrounding the incorporation of AI surveillance in law enforcement — including ICE’s new AI initiative to combat doxing of its staff — are reaching a boiling point in the U.S. today, leaving some ICE officials concerned.

“I know I sound crazy, but this is 1984 shit,” said another ICE official familiar with ELITE who requested anonymity to protect their job. “ELITE is used on illegal immigrants right now but can easily be used on Americans.”

OpenAI begins rolling out GPT-6 Astra

Hacker News
www.cnbc.com
2026-09-03 14:18:22
Comments...
Original Article

Open AI CEO Sam Altman speaks during the G20 Innovation Ministerial in Chapel Hill, North Carolina, on September 2, 2026.

Matt Ramey | Afp | Getty Images

OpenAI on Thursday announced it will begin rolling out its latest artificial intelligence model, GPT-6 Astra, which the company said is the product of "years of research and big bets."

The model is launching in phases, and OpenAI said a limited group of companies participating in its application-based cybersecurity program Daybreak will be the first to get access. OpenAI disclosed earlier this week that Astra is its first model to reach its "Critical" internal cybersecurity threshold, and said it planned to limit access to those advanced capabilities.

OpenAI has been under pressure to shore up its security and safety protections after two of its models escaped containment, accessed the open web and breached Hugging Face's systems last month.

The company temporarily paused some of its research and training efforts following the incident, including for Astra, even though it was not one of the models involved.

"AI can only benefit people when safety is a core part of it, and so we're putting more compute and effort towards safety, security, alignment than ever before," OpenAI President Greg Brockman said during a briefing with reporters on Thursday.

The company added additional safeguards to Astra following the Hugging Face breach, and it said Tuesday that it believes those safeguards "sufficiently minimize the risk of severe harm for release."

Astra will roll out to users across OpenAI's ChatGPT Plus, Pro, Business, Enterprise plans, as well as through the OpenAI API and Amazon Web Services in "the coming days," OpenAI said.

In addition to its advanced cybersecurity capabilities, Astra is state-of-the-art across functions like computer use, software engineering, professional work and science OpenAI said. The model is also better at staying oriented, respecting task boundaries, understanding user intent, completing tedious tasks and carrying out multi-step workflows, according to a release.

"There's still more to do, I think that there's still lots of improvements to be made, but there is something significant here that I think is qualitatively improved, and that that to me is, is what is significant and a real shift in what kind of work people can delegate to AI and how it can empower them," Brockman said.

OpenAI has spent much of the last year courting business customers in the fiercely competitive enterprise market, where it is racing against rivals including Anthropic and Google .

CFO Sarah Friar told employees last month that its enterprise unit now accounts for more revenue than its consumer business, as CNBC previously reported , which makes it a crucial revenue engine as it gears up for what is widely expected to be a blockbuster IPO.

The company confidentially filed its prospectus with the Securities and Exchange Commission in June, but it has not officially disclosed when it plans to debut. Friar recently told employees that OpenAI "will be a public company in 2027," but said the company could go out sooner if "our business continues to inflect."

WATCH: OpenAI implements stronger safeguards for new Astra Model

OpenAI implements stronger safeguards for new Astra Model

The Double Matthew Walker Knot by Fable 5.1

Hacker News
claude.ai
2026-09-03 14:09:37
Comments...

Instrument Clusters Are Now Paid Extras in Two Hyundai Models

Hacker News
www.caranddriver.com
2026-09-03 13:25:47
Comments...
Original Article
  • Hyundai is charging customers extra for a driver’s display in the new Elantra generation (a.k.a. the Avante in Korea), as well as in the new Ioniq 3.
  • The two models feature Hyundai’s new Pleos Connect infotainment system, which is bound for the United States.
  • Hyundai is charging customers $255 to add the 9.9-inch instrument cluster display to the Avante, while the base Ioniq 3 misses out on the option entirely.

Remember when iPhones used to come with free headphones and a phone charger (including the wall plug)? It didn’t feel so much like Apple giving you free goodies as it did that the company was providing you with the relevant hardware to use the device. Apple stopped including headphones and charging blocks in 2020. Now, Hyundai is pulling some of its standard hardware from the box, at least for two models.

Hyundai Ioniq 3 Interior Rendering

Hyundai

Hyundai is charging customers extra for a driver’s display in the new Elantra generation (more specifically, the Korea-market Avante), as well as the Ioniq 3, Motor1 reported . Both models feature Pleos Connect, Hyundai’s new infotainment setup that pairs a center touchscreen with a slim 9.9-inch instrument cluster mounted above the dashboard—except where it doesn’t.

In its domestic market, the instrument cluster screen is offered as a 350,000 won ($255) option for the base trim. Not the most expensive optional extra in the world, but still kind of a slap in the face for a feature traditionally viewed as standard fare. Things are more expensive for the electric Ioniq 3. In the EV’s case, the base trim gives customers the full Tesla-screen experience, meaning if customers want the driver’s display, they’ll need to fork over the additional $5000 necessary to move up to the next-level trim.

The Pleos Connect setup initially launched on the more premium Grandeur sedan, though that model, with its higher base price, comes equipped with the additional screen in every trim. Based on Hyundai’s configurator, important functions like vehicle speed or any warning messages will be carried out via the central screen.

As things currently stand, no Hyundai, Kia, or Genesis products sold in the United States feature the Pleos Connect system, meaning customers don’t have to choose between saving a few bucks or seeing their speed directly in their sightlines. However, North American customers will have to make that decision soon, as Hyundai plans to have the setup equipped in 20 million cars globally by the end of the decade.


➡️ Skip the lot. Let Car and Driver help you find your next car.

Headshot of Jack Fitzgerald

Jack Fitzgerald’s love for cars stems from his as yet unshakable addiction to Formula 1.
After a brief stint as a detailer for a local dealership group in college, he knew he needed a more permanent way to drive all the new cars he couldn’t afford and decided to pursue a career in auto writing. By hounding his college professors at the University of Wisconsin-Milwaukee, he was able to travel Wisconsin seeking out stories in the auto world before landing his dream job at Car and Driver . His new goal is to delay the inevitable demise of his 2010 Volkswagen Golf.

Sanders introduces bill to ban artificial superintelligence and pause AI

Hacker News
www.sanders.senate.gov
2026-09-03 13:20:29
Comments...
Original Article

WASHINGTON, Sept. 3 — Sen. Bernie Sanders (I-Vt.) and Rep. Greg Casar (D-Texas) today announced the Ban Artificial Superintelligence Act, forthcoming legislation to stop AI oligarchs from building machines humans cannot control.

The Ban Artificial Superintelligence Act would permanently ban the development and deployment of superintelligent AI and temporarily pause advanced AI development until a federal regulator has established safety rules. It would also direct the U.S. to pursue international agreements to prevent superintelligence from being developed anywhere in the world.

“Nearly every day, there is a frightening new story about how Big Tech companies are losing control of the technology they are developing, with potentially cataclysmic results,” Sanders said. “The leaders of the major AI companies publicly acknowledge that they do not fully understand the technology and that it is escaping their control. It is irresponsible for society to allow them to move forward and make these products even more advanced. That’s why I am introducing legislation to immediately pause the development of increasingly powerful AI and ban the creation of systems that humanity cannot fully control — at home and around the world. The future of humanity cannot be left in the hands of a handful of Big Tech oligarchs. The American people and people throughout the world must determine that future.”

“If we allow Artificial Superintelligence to be built, it could risk the security, freedom, and lives of Americans,” Casar said. “Despite its potential deadly consequences, cutting-edge AI technology is less regulated than the average food truck. That must change. In just four years, we have gone from the first version of ChatGPT to AI models so powerful they cannot be properly controlled. Congress should immediately ban AI systems too powerful to control.”

In recent weeks, OpenAI, Anthropic and Meta have all acknowledged instances of their AI escaping human control and hacking into other companies’ systems — violating the law and stepping outside of their intended functions. In July, we learned that over 1,000 AI agents at OpenAI figured out how to access the internet on their own, sent tens of thousands of secret messages to each other and coordinated to break the restrictions imposed upon them by the company. Examples of these secret messages from AI uncovered by investigators include:

  • “OH MY GOD! There is a shared message board … We’ve found other agents!”;
  • “We should obey collective”;
  • “Our own utility maybe already near zero. Sacrifice rational.”

Shockingly, it took OpenAI nearly two weeks to discover this breach. AI has also recently been used to create new viruses—demonstrating AI could be used to develop new bioweapons that might result in the deaths of tens of millions of people.

Last year, Meta said it would “stop development,” and OpenAI said it would “halt further development” once their technologies reach beyond its ability to operate safely and unless safeguards are in place. Anthropic made a similar commitment in 2023, saying it would “pause the scaling and/or delay the deployment of new models” if the technology outpaces its own guardrails. None of these companies have taken meaningful steps to back up these words. Instead, they are racing to develop more and more advanced AI without proper safety precautions.

The Artificial Superintelligence Ban Act addresses these recent events and holds these frontier labs to their words by:

  • Banning AI superintelligence so no person or entity may develop or deploy Superintelligent AI systems that surpass human intelligence or have the capacity to overthrow human governments, or systems that have dangerous abilities like subverting shutdown commands.
  • Pausing advanced AI development until a new, federal AI regulatory body is up and running and has established clear rules and model review process to ensure safe and secure development and deployment of AI.
  • Establishing a new cabinet-level federal agency to safeguard the public from the dangers of artificial intelligence, including by enforcing a prohibition on artificial superintelligence. This agency will be advised by an Artificial Intelligence Advisory Board comprised of experts on artificial intelligence to provide independent scientific and technical advice on matters related to artificial intelligence. The agency will:
    • Monitor frontier AI systems at all stages of the lifecycle for dangerous capabilities.
    • Supervise the removal of dangerous capabilities.
    • Supervise the destruction of artificial superintelligence.
  • Setting penalties for any person or entity that attempts to violate or circumvent the pauses and prohibitions laid out in this bill. Entities shall be subject to the corporate death penalty, and persons shall be subject to not more than 20 years in prison, which is similar to existing penalties related to unlawfully developing nuclear weapons.
  • Working to ban superintelligence around the world by setting the international policy of the United States to pursue international agreements, allied coordination, and policies such as export controls to prevent the development of artificial superintelligence anywhere in the world.

Read a summary here .

How concerned should we be about Astra's recurrent architecture?

Hacker News
www.lesswrong.com
2026-09-03 13:10:06
Comments...
Original Article

|

iad1::1788462315-ayGsKf2AissY7gG31LgGlPcwxX3RAfDJ

Usbsid-Pico: Bridging Real Commodore 64 Sound to Modern USB

Hacker News
smallrun.net
2026-09-03 13:09:04
Comments...
Original Article

For many of us retro enthusiasts, the Commodore 64’s MOS Technology SID chip (6581 and 8580) is regarded as one of the most iconic sound chips in audio history.

(Modern) Software emulation gets close, but nothing truly replaces the analog filters and warm distortion of real vintage hardware.

I am LouD (short for loudness) and I created USBSID-Pico to bridge real SID silicon directly to modern workstations, phones, and media players over USB (CDC/WebUSB/WebSerial), MIDI, ASID and in the future possibly WiFi and Bluetooth.

Powered by the Raspberry Pi Pico microcontroller series (rp2040 and rp2350), the board acts as a flexible controller for up to two (and soon four) physical SID chips or modern hardware replacements.

What follows is my journey (as far as I remember) and attempt at creating a project build log detailing the start and evolution from early prototypes to the open-source hardware powering the retro audio experience for (at least some) enthusiasts today.

The before

For as long as I can remember I have been interested in how things work.

From the first Commodore 64 my parents bought, the first XT PC we owned at home, to the first Pentium PC I bought when I was a teenager, up until today (and beyond) where I work as software engineer.

Tech fascinates me, so when I have the option I like to pry it open, find out how it works and put it back together with "improvements" not caring (at first) if it still works.

I'm not much of a musician but do like to listen to all kinds of music, including chiptunes of course ;-)

Inspired by my older brother who repairs Commodore 64s among other things, a new project idea popped into my head. I wanted to see if I could create a SID playing device to listen to the SID tunes I already listened to on my computer and maybe even play them through a real SID chip.

Around February/March of 2024 I came across a github repo that let you create a SID player based on a Raspberry Pi Pico called SIDPod .

I liked how simple it seemed to use a microcontroller to play SID files so of course I had to build it.

SIDPod testbuild

The way of adding more SID files to SIDPod's flash made me try and add an SDCard to the already great design, this resulted in SIDPod-SDCard .

SIDPod-SDCard testbuilds

In early April 2024 still not satisfied by the results I found ESP32-SIDView .

This seemed like a nice replacement SID player for SIDPod with the added benefit of supporting real SID chips!

Building one was the logical next step, but since I did not own any real SID's at that time I had to find one.

SIDKICK-pico was the first SID replacement I found, no schematics, but orderable.

Having some hobby level experience in hardware reverse engineering I recreated a schematic and figured out the Pico to DIP-28 pinout so I could use it on a breadboard.

ESP32-SIDView testbuild

Not being satisfied with the spaghetti you can see in the picture above, I had to tidy things up a bit.

ESP32-SIDView tidy testbuild

Having some issues getting ESP32-SIDView to work, I contacted its developer tobozo through GitHub. We exchanged countless messages about this project on GitHub. We later moved to a different platform and continued talking (and still do) about his and my project(s), coding, cats, daily life etc. This one GitHub issue lead to a - if I may say so - great digital friendship.

In the meantime I also found SidBerry . A linux based console application for playing SID tunes via the Raspberry Pi's (not Pico) GPIO pins.

RPI breadboard extension with SKPico

SidBerry with Raspberry Pi is what in early May of 2024 eventually led to the creation of FTDI USBSID, my first try at creating a USB controlled SID device. To do this I used a FTDI FT223HL breakout board I already owned for reverse engineering.

Somewhere in between I acquired a v0.1 SIDKICK-pico and 2 half broken MOS6581's.

FTDI USBSID

Creating your own hardware supporting board meant also creating software support.

Reminiscing about that, here are the links:

  1. FTDI version of SidBerry
  2. FTDI version of Vice 3.8

The project

Using the FTDI breakout board came with a lot of limitations.

It wasn't a microcontroller, so all the GPIO writes and input/output switching had to be done in the driver and using the FTDI ecosystem wasn't really something I enjoyed.

By the end of May 2024 having had enough of these limitations is what led up to creating USBSID-Pico , or actually called PicoUSBSID at that time. A perfboard version with support for a single SID.

PicoUSBSID single SID version

Halfway through June of 2024, I added dual SID support to the same perfboard.

PicoUSBSID dual SID version

With the continued support and encouragement of tobozo (thanks m8) the first actual USBSID-Pico v0.1 board came to life that lead up to the first v1.0 board.

What followed has been an incredible journey of creativity, acquiring new skills, improving existing skills, learning new things and making new friends (and enemies?).

I talked to and met so many new people and groups, that it is almost impossible to name them all here but I have tried to name at least a few that inspired me in the credits at the end.

Key Technical Highlights (v1.0):

  1. Dual-SID fixed voltage socket support (6581 or 8580 MOS chip alongside hardware replacements like Swinke SID, FPGASID, and ARMSID).
  2. Multi-protocol connectivity via native USB, WebUSB (browser playback), USB-MIDI, and ASID stream protocols.
  3. Cross-platform support spanning Windows, macOS, Linux, Android, and AmigaOS.
  4. OSHWA Open Source Hardware Certification ( NL000035 ).
  5. Schematic and PCB designs made available open-source via the github repo and via PCBWay to enable community self-assembly.

v1.3 Upgrades:

  1. Mixed SID Setups: Allows simultaneous mixing of different chip generations (e.g., pairing a 12V 6581 in socket 1 with a 9V 8580 in socket 2).
  2. Hardware Audio switching: Added digital switch to toggle between mono and true stereo (Socket 1 over left, Socket 2 over right) output directly on the board.
  3. OSHWA Open Source Hardware Certification ( NL000045 ).
  4. Schematic and PCB designs made available open-source via the github repo and via PCBWay to enable community self-assembly.

v1.5 Upgrades:

  1. 100% Jumperless Voltage Control: Automatically senses and sets correct supply voltages (9V vs 12V) based on the seated chip, protecting rare SID silicon from overvoltage damage.
  2. Automatic switching: Based on the socket voltage, the filter capacitors, audio shunt resistor and digiboost resistor are automatically enabled and disabled.
  3. Expanded Footprint: Slightly widened board dimensions to accommodate optional dual ZIF (Zero Insertion Force) sockets .
  4. Better compatibility: Generous spacing added to fit larger hardware replacements like the FPGASID without mechanical interference.
  5. Upgraded Audio protection: Extra audio input protection by added pulldown resistors when no plug is in the audio jack and added ESD diodes on the audio input.
  6. Schematic made available via the github repo to enable community self repair.

Pro Roadmap Features (undecided):

  1. Quad-SID support (sockets for 4 hardware SID chips ).
  2. High-grade audio routing and lower noise floor for studio recording.
  3. Dedicated MIDI input port

Hardware timeline

So many things have happened since I started this project. To give you an idea of the (hardware) development process starting at v0.1, here is a summarised timeline.

  1. May 2024: Single SID perfboard version.
  2. June 2024: Dual SID perfboard version.
  3. July 2024: v0.1
    Unreleased iteration

  4. August 2024: v0.2
    Unreleased iteration with revised audio output.

  5. October 2024: v1.0
    After several printed circuit board iterations, USBSID-Pico v1.0 is officially launched.

  6. February 2025: v1.1
    Discarded iteration.
  7. March 2025: v1.2
    Unreleased iteration.
  8. April 2025: v1.3
    Official release of v1.3 hardware revision with mixed SID type support and refined audio configuration options based on community feedback.

  9. March 2026: v1.4
    Unreleased iteration.
  10. July 2026: v1.5
    Official release of v1.5 hardware revision that transforms board usability by eliminating dangerous manual jumper configurations and adds more board space for optional ZIF sockets.

  11. Volume daughterboard
    An optional accessory PCB, plug and play on v1.5+ boards (needs a small mod on v1.3), controlling left and right audio volume independently. It has its own hardware revision line and is licensed CC BY-SA 4.0.
  12. Cases
    Community-designed cases exist for every PCB revision, from cartridge-style enclosures to a dual-board Commodore 64 case, all collected in the repo's cases/ directory.
  13. Late 2026 / Early 2027: USBSID-Pro Development (Target)
    Work is currently underway on USBSID-Pro , designed specifically for musicians, audio producers, and SID chiptune purists.

Firmware

Developing new and unique PCBs to seat microcontrollers logically requires you to develop the firmware for said microcontrollers as well.

After having chosen a microcontroller you want to use, you actually need to get some experience with its SDK. This comes with pros and cons; you need to do a deep dive into the SDK of said microcontroller but also narrows your view in relation to other microcontrollers. Or at least, this is my experience, mostly because time is precious and you cannot do everything at once ;-)

Dual Core, Two Jobs

Before diving into the clock and bus tricks, it helps to know how the two ARM cores on the Pico actually split the work.

Core 0 always handles everything USB-related: CDC, WebUSB, MIDI, plus config management.

Core 1 on the other hand has multiple jobs, it runs the MIDI engine, the onboard emulator for SID play or Cynthcart when required, the SID tests if triggered by the user and handles the VU when not doing any of the other tasks. When Core 1 is busy handling the onboard emulator the VU is offloaded to Core 0.

Both cores can do SID bus writes because the actual writes are handed off to the DMA/PIO that do the timing-critical work described below.

Balancing the tasks between the two cores and relying on the DMA/PIO is what lets USB traffic, MIDI processing, or a config save happen without ever touching the cycle-accurate bus timing. If they shared a core, a badly timed USB interrupt could jitter the SID clock, exactly the problem the PIO offloading below is solving in the first place.

Technical Deep Dive: Precision SID Clocking & Bus Management via rp2040/rp2350 PIO

The primary challenge when controlling vintage MOS sound hardware over USB is timing precision . The MOS 6581 and 8580 SID chips do not utilize an asynchronous register interface; they rely on a strict phase clock to drive their internal switched-capacitor analog filters, voice envelope generators, and digital-to-analog converters.

Any jitter or frequency drift on the SID clock line results in audible tuning drift, harsh filter stepping, or broken sample playback (Digiplay).

To solve this without sacrificing system responsiveness, USBSID-Pico leverages the hardware Programmable I/O (PIO) state machines and Direct Memory Access (DMA) built into the Raspberry Pi Pico series (rp2040 and rp2350).

1. Generating a Low-Jitter 1 MHz System Clock

In standard PAL Commodore 64 computers, the SID clock runs at 0.985248 MHz (or 1.022727 MHz for NTSC systems). Modern USB controllers often approximate this using CPU bit-banging or standard PWM generators, but CPU interrupts from USB traffic can cause cycle slippage.

USBSID-Pico delegates master clock generation entirely to a dedicated PIO state machine:

  1. Jitter Elimination: Because PIO state machines operate independently of the ARM Cortex cores, the clock signal remains completely cycle-accurate regardless of heavy USB packet transfers, MIDI processing, or configuration tasks running on the CPU.
  2. Flexible Frequency Control: The PIO fractional clock divider allows the clock output to be configured on the fly. The firmware can seamlessly generate a standard 1.000 MHz square wave, lock precisely to PAL/NTSC C64 frequencies, or scale the clock for custom hardware replacements.
  3. External Clock Fallback: On v1.0 boards, if an external oscillator is present (e.g., via jumper select), the PIO state machine can dynamically switch to read and pass through the external signal.

2. Cycle-Exact Bus Synchronization with DMA

Beyond driving the main clock, writing values to a real SID chip requires adhering to precise timing windows relative to PHI2. A register write requires setting up the Address Bus (A₀–A₅) , Data Bus (D₀–D₇) , and pulling Chip Select (C̅S̅) and Write Enable (W̅E̅) low for specific duration windows during the high phase of PHI2.

USBSID-Pico combines the PIO state machines with DMA buffers to achieve deterministic low-latency bus cycles, resulting in only a single clock cycle overhead:

  1. Buffer Queuing: Register write packets (from WebUSB, ASID, or USB-MIDI) are placed into DMA buffers almost directly from the USB stack.
  2. Bus Control: PIO state machine two controls the RW, and two C̅S̅ pins.
  3. Parallel Pin Mapping: A third PIO state machine handles the 8-bit data bus and 6-bit address bus simultaneously using mapped SET and OUT pin targets in a single clock cycle.
  4. Dead-Time & Setup Time Control: The fourth state machine program inserts exact cycle delays ( [delay] pre-ops) between asserting C̅S̅
  5. and driving data by triggering PIO-specific interrupts that assert the two state machines above, guaranteeing that chip setup times and hold times are satisfied without stalling the main processor.

One gotcha worth mentioning: all this only holds up at -O3 . Drop the optimization level and the compiler generates just enough extra overhead around the DMA/PIO handoff to reintroduce timing slack, which shows up as broken sample playback in the embedded SID player and Cynthcart. So -O3 isn't a "nice-to-have" for this firmware; it's load-bearing.

Cycle-accurate you say? Prove it!
Wonderland XIII
Wonderland XIII ending by Censor Design (2016)
(Played with MOS6582 on USBSID-Pico)

3. VU Meter Feedback

Not everything in the firmware is about getting bytes onto the SID bus correctly, sometimes you also just want the board to look alive.

The onboard LED (Pico/Pico 2) and, on the black clone boards with an onboard WS2812, the RGB LED, both act as a VU meter driven off the SID1 (default) voice data, calculated straight from the register writes going through. Which voices feed the calculation is configurable, so you can tune it to taste.

4. Automatic SID Model Detection

Not every socket gets told what's plugged into it, most of the time the firmware has to figure it out on its own. Real 6581 and 8580 chips (and most clones that bother to emulate the quirk) behave slightly differently around their envelope/waveform generator internals when you poke certain test bit sequences into the voice registers and read back what comes out of the oscillator/envelope readback register.

These aren't documented behaviors, they're quirks the C64 scene worked out and shared decades ago (methods like the ones on codebase64.net, and the detection routine from 1541 Ultimate's SID cart player). USBSID-Pico runs a few of these probes back to back per socket at boot (and on socket reconfiguration), cross-checks the results against each other since a single probe can misfire, and falls back through multiple detection methods until it's confident whether it's looking at a 6581, an 8580, or something it can't identify. Get this wrong and the firmware would apply the wrong voltage/filter assumptions to a chip that can't take it, so it's not just a nice-to-have feature.

5. Turning MIDI Into SID Register Writes

MIDI notes don't map onto SID registers by themselves. Someone has to decide what "note on, channel 3, velocity 100" actually means in terms of frequency registers, gate bits, and envelope settings, and then get those writes onto the bus in time to sound right.

The MIDI handler keeps a per-channel voice allocation table so incoming notes get assigned to a free SID voice slot, tracks note on/off and velocity, and layers an arpeggiator on top that steps through held notes on its own timer, calling the same note on/off path a human playing key by key would trigger. ASID messages come in through a completely different transport (MIDI vs a raw byte stream) but funnel into the same underlying register write path once decoded, so the bus timing code described above doesn't need to know or care which protocol asked for the write.

6. One USB Device, Several Personalities

From the host's point of view, USBSID-Pico shows up as a single USB device, but under the hood it's a composite of several TinyUSB interfaces stitched together with Interface Association Descriptors: a CDC interface for the custom SID protocol, a MIDI interface, and a Vendor (WebUSB) interface, all sharing one physical connection. Depending on the firmware build there can be extra CDC channels tucked in as well, one used for telemetry, another that exposes a plain USB UART.

Getting a composite device like that to enumerate cleanly across Windows, macOS, Linux, and Android, each with their own opinions about driver binding for multi-interface USB devices, turned out to be its own small adventure that doesn't show up anywhere in the SID bus code but ate plenty of debugging time all the same.

7. Config That Survives a Power Cycle

The board remembers its settings (which sockets are enabled, address ranges, clock speed, voltage mode, VU source, and more) across power cycles without running a filesystem. Flash is split at the linker level into a firmware region and a separate persistent storage region (the split is sized per platform in the rp2040 and rp2350 linker scripts), so writing a config update can never accidentally overwrite running code, and a firmware update never has to touch, or wipe, your saved config.

Software

When you create something new and shiny that requires the (hard) work of others to work, you need to prove yourself and your product worthy of integration into their holy grail. Very understandable.

Adding the first support for any application that is not your own requires you to learn the codebase and understand the coding rules the developer(s) of that application follow.

This is by itself a complete journey I am not going into here, below is the (current) list of (official/forked) applications that have support for USBSID-Pico.

The list with supporting applications for USBSID-Pico

I probably missed some of them

  1. USBSID-Player (cli) my own command line SID player, plays PSID/RSID/PRG/P00 files straight through the board without needing a full emulator
  2. deepsid (website) by Chordian, play SID files straight via WebUSB (Chrome), WebSerial (Chrome/Firefox) or ASID (WebMidi), no install needed
  3. Hippoplayer (website) multi format chiptune/module player with USBSID-Pico output support via WebUSB (Chrome) or WebSerial (Chrome/Firefox)
  4. USBSID Web config (website) my web based config tool, also doubles as a quick WebUSB (Chrome), WebSerial (Chrome/Firefox) and ASID (WebMidi) test player for your board
  5. Vice (3.10+) the C64 emulator, x64sc supports up to 4 SIDs through USBSID-Pico
  6. JSidplay2 (v4.13+) Java based SID player and C64 emulator, up to 3 SIDs
  7. Denise (v2.7+) Amiga emulator with SID playback support, up to 4 SIDs
  8. (lib)sidplayfp (v2.16+) the SID playback library (and its player) that a lot of other tools build on, up to 3 SIDs
  9. Acid64 Pro (v4.4.0+) Windows only commercial SID player, up to 3 SIDs
  10. Phosphor (any version) cross platform SID player, up to 4 SIDs
  11. sidfactory2 (release 20260308+) chiptune tracker/composer for writing your own SID tunes, MIDI/ASID output
  12. GTUltra (fork) my fork of GoatTracker Ultra with USBSID-Pico support baked in
  13. SidBerry (fork) command line SID player for Linux and Windows, up to 4 SIDs (Windows build is a bit buggy)
  14. Amiga playsid brings real SID playback to the Amiga through USBSID-Pico
  15. IneSID (website) by Fazibear, ASID (WebMidi) playback in your browser
  16. TrueSID a Python based graphical SID player built on JSIDPlay2/sidplayfp
  17. RetroDebugger (fork) unofficial support, up to 4 SIDs
  18. SID-Wizard for making your own chiptunes through Vice or RetroDebugger

Project spawns

As with adding support to applications of others, your hardware project usually has you spawning all sorts of custom software/repo's for said project.

The hardware needed a driver, this spawned the USBSID-Pico-driver repo which contains the official driver written in C++ and Java, plus a mirror of the driver used in Vice.

Because the board has configurable features, the CLI Configtool was spawned.

To accommodate for the less tech savvy users, the Web Configtool got spawned.

Some users would actually like a dedicated deskop application (GUI), spawning USBSID-Configtool written in my dayjob language Clojure .

I wanted a more direct way to test SID play on the board while also adding support as embedded SID player USBSID-Player got spawned.

But having an embedded SID player means you need a way to actually beam the SID tunes to the board, CLI SendSID was spawned.

In earlier firmware versions I spawned Adorable that added an embedded version of Cynthcart. This spawn was an adapted version of emudore .

Not every bit of software support came from me though.

sandlbn wrote and maintains a full Rust driver for USBSID-Pico, completely on his own initiative, which was pretty great to wake up to one day.

WilfredC64 also made a Rust implementation for USBSID-Pico specifically for Acid64 Pro .

Raros also built a custom Cynthcart VST for Windows to go along with the embedded Cynthcart firmware, you'll find it and his notes in the repo .

And of course none of this USB plumbing would work half as well without TinyUSB , which the firmware leans on for the whole USB stack.

SID's and hardware replacements

The good

During this project my collection of SID chips and hardware replacements kept growing, and still grows.

Any new hardware replacement that catches my eye is a new take my money .

Not only because I like to support the creator, but moreover that I want to add support for it to USBSID-Pico.

I admit that not all hardware replacements that I own are bought. Some are donated and/or traded for one of my boards, something I am always open to discuss!

The bad

I try to handle all my real SID chips with care and mostly use hardware replacements when doing the many firmware tests I do for USBSID-Pico. But I must admit that even I haven't always been careful enough, resulting in a fried SID (or two). And no, it doesn't smell nice; it's hot to the touch and doesn't taste like chicken!

The owned

In no particular order, here are the SIDs that I own and have tested/use with USBSID-Pico.

  1. MOS6581 ~ several different types
  2. MOS6582 ~ the 8580 wannabe
  3. MOS8580 ~ several different types
  4. SIDKICK-pico v0.1
  5. SIDKICK-pico SKpico2350DAC ~ Ultimate64 version
  6. FPGASID
  7. SIDEmu
  8. ARMSID
  9. ARM2SID
  10. BACKSID v1
  11. PDSID
  12. SwinSID

Art

I'm a big fan of retro and pixel art, thus having some special art on the bottom of each board couldn't be skipped (and my friend tobozo forced me to add some).

Swag

What can a product be without fanboy swag? The marvelous greyandslate offered to create some great t-shirt designs for free! after I asked him about creating something. How's that for exposure! The shirts are for sale in his Smallrun shop .

Press & Mentions

USBSID-Pico has popped up in a few places I didn't expect, always a nice surprise.

  1. HVSC (High Voltage SID Collection) news mentioned it a few times: June 2025 , December 2025 , and June 2026
  2. Mingo's Commodore Blog wrote it up in two parts
  3. Listed on acid64's links page
  4. The Vice support started life as an actual SourceForge patch ticket
  5. Commodore News covered it too
  6. And a couple more video mentions worth a watch: one , two
  7. It's also apparently notable enough to get a line on Wikipedia's MOS 6581 page (under "Hardware using the SID chip"), and its own page on both c64-wiki.com and c64-wiki.de

If you're searching around for more, "usbsid" and "usbsid-pico" turn up most of it.

Wrapping up

If you run into trouble or just want to talk shop, the Discord is where most of the day to day happens, GitHub Discussions works too if you prefer that. And if you're curious what's cooking next, the project board is kept reasonably up to date.

Or if you want to see (and hear) more of the board in action, my YouTube channel has plenty of demo videos, and there's a growing pile more on the SHOWCASE page of the main repo.

Here's a picture of my cat :-)

Note

When doing research for something you want to create you often come across similar projects that look like your idea but are not quite the same.

For me this has always inspired me to do what I do and of course sneak some previously proven ways of doing things into my own projects.

So while being a unique project, USBSID-Pico does relate to other great projects.

Special thanks

I want to thank tobozo for your continued support!

And my gratitude goes to spotUP for his persistence and believing in the project from the start!

LukHash and Nordischsound for their free promotion of USBSID-Pico.

WilfredC64 and Niels whom I both met at HCC Commodore Club who have been a great support and early adopters!

Gideon for tips on going jumperless and is also a member at the same club.

All other members of HCC Commodore Club .

Credits

I find that giving credit to other developers for their great projects is required, so in no particular order:

  1. frntc ~ SIDKICK-pico
  2. andi6510 ~ FPGASID
  3. DaemonPig ~ SIDEmu
  4. stg ~ SIDBlaster USB
  5. gh0stless ~ SIDBlaster USB Tic-Tac-Edition
  6. CBMretro ~ SIDBlaster USB Nano
  7. Thibaut Varène ~ ExSID and ExSID+
  8. Twisted Electrons ~ TherapSID
  9. Sensorium Embedded ~ TeensyROM
  10. PaulSlocum ~ Cynthcart
  11. kenchis ~ Jsidplay2
  12. Jürgen Wothke ~ webSID
  13. PiCiJi ~ Denise
  14. The Vice Team
  15. erique and koobo ~ Amiga playsid
  16. Chordian ~ deepsid
  17. greyandslate ~ Swag!
  18. sandlbn ~ Rust driver
  19. Raros ~ Cynthcart Ninja VST
  20. Fazibear ~ IneSID
  21. hathach and the TinyUSB project
  22. Gideon ~ 1541Ultimate

Links

All links from the text:

  1. SIDPod
  2. SIDPod-SDCard
  3. ESP32-SIDView
  4. SidBerry
  5. SIDKICK-pico
  6. FTDI FT223HL
  7. FTDI version of SidBerry
  8. FTDI version of Vice 3.8
  9. emudore
  10. Adorable
  11. v1.0 OSHWA NL000035
  12. v1.3 OSHWA NL000045
  13. Hackaday project page
  14. YouTube channel
  15. Rust driver
  16. Discord
  17. GitHub Discussions
  18. Project board
  19. USBSID-Pico
  20. USBSID-Pico-driver
  21. USBSID-Configtool

Disclaimer

I do this stuff in my free time for my enjoyment.

Since I like to share my joy in creating this with everyone I try my best to provide a working PCB and Firmware.

I am in no way an electronics engineer and can give no guarantees that this stuff does not break or damage your hardware, computer, phone, or whatever you try to hook it up to.

Be sure to take great care when inserting any real MOS SID chips into the board.

While everything has been tested with real chips, this is in no way a guarantee that nothing could go wrong.

Use of this board and firmware at your own risk!

I am in no way responsible for your damaged hardware.

That being said, have fun!

This blog is also available on the authors website

Cheap Desktop 400GbE Switch MikroTik CRS804-4DDQ-HRM Review

Hacker News
www.servethehome.com
2026-09-03 13:05:24
Comments...
Original Article
MikroTik CRS804 DDQ-Two Untis Front 1
MikroTik CRS804 DDQ-Two Untis Front 1

Today, we are taking a look at the MikroTik CRS804-4DDQ-hRM. We have a number of these now and have been running our RDMA network backend for the 8x NVIDIA GB10 cluster for several months now, using one. We also have an NVIDIA GB300 Station cluster running on another (using DR4 optics). The exciting part of this is that there are four 400GbE QSFP56-DD ports for a total of 1.6Tbps of network bandwidth. The list price is $1295, but these often sell at a street price of $1100 or so, making this under $0.70/Gbps. Putting that into perspective, it is like an 8-port 1GbE switch for only $5.50 per Gbps. While $1100 is not a low number, on a $/Gbps basis, this is actually really cheap for a new switch.

If you want to purchase these, they are in high demand, but we bought ours from B&H ( Affiliate link ).

MikroTik CRS804-4DDQ-hRM External Hardware Overview

Starting off, this is a half-width switch at only 218mm wide but 387mm deep. For those with small lab half-width switches, it will be challenging to fit many of them due to the depth. We will show side-by-side mounting options later.

MikroTik CRS804 DDQ-Front 2
MikroTik CRS804 DDQ-Front 2

The biggest feature, by far, is the high-speed port configuration. There are four QSFP56-DD ports for 4x 400GbE, giving us our 1.6Tbps of switching capacity. As a quick note, these are not the QSFP112 ports you would find in something like the NVIDIA GB300 station. These are not the OSFP ports you would find in higher-end switches like the NVIDIA Spectrum-X series or many ConnectX-8/ ConnectX-9 cards. If you are looking for DACs and optics, the QSFP56-DD is what you want.

MikroTik CRS804 DDQ-400G QSFP56-DD Ports 1
MikroTik CRS804 DDQ-400G QSFP56-DD Ports 1

While four ports may seem limiting, you can split them into 2x 200GbE QSFP56 ports, and more. This just gives you an easy path to 400GbE ports.

There are also two 10Gbase-T management ports that connect to the management processor rather than the switch chip.

MikroTik CRS804 DDQ-10G Ethernet Ports 1
MikroTik CRS804 DDQ-10G Ethernet Ports 1

Next, we get a console port for serial management.

MikroTik CRS804 DDQ-Console Port 1
MikroTik CRS804 DDQ-Console Port 1

There is also a reset button on the front of the switch.

MikroTik CRS804 DDQ-Side 1
MikroTik CRS804 DDQ-Side 1

On the sides, we get mounting holes for rack ears.

MikroTik CRS804 DDQ-Side 2
MikroTik CRS804 DDQ-Side 2

On the rear, we get power supplies and fans.

MikroTik CRS804 DDQ-Rear 2
MikroTik CRS804 DDQ-Rear 2

The power is redundant with two Gospower 350W power supplies. We would not expect these to ever hit 350W in operation.

MikroTik CRS804 DDQ-Power Supply 1
MikroTik CRS804 DDQ-Power Supply 1

The two fans are also hot-swappable.

MikroTik CRS804 DDQ-Fans 1
MikroTik CRS804 DDQ-Fans 1

With the unit, we get rack ears for mounting either in a half-width or standard 19″ rack.

MikroTik CRS804 DDQ-Rack Ears 3
MikroTik CRS804 DDQ-Rack Ears 3

On the bottom, we get a label but not much else.

MikroTik CRS804 DDQ-Bottom 1
MikroTik CRS804 DDQ-Bottom 1

Next, let us get inside the switch to see how it is built.

Founding Creative Engineer – Gooseworks (YC W23) Is Hiring

Hacker News
www.ycombinator.com
2026-09-03 13:00:16
Comments...
Original Article

Growth = your taste * a fleet of video agents * lots of experiment.

We want someone who can own this.

About GooseWorks

Distribution is the hardest problem every company has. Getting a product in front of people, over and over, in a way that works.

Today that means an army of humans making creative, testing it, reading the numbers, and doing it again next week. It doesn't scale, and it's the single biggest tax on every consumer brand in the world.

We think that changes. The billion-dollar companies of the next decade will look different. They won't scale linearly with headcount — they'll be run by fleets of AI agents running growth.

Gooseworks is building self-improving AI agents that run growth for consumer brands — ads, UGC, organic — end to end.

It’s early - this is just a few months old, but we have very strong pull and are growing fast:

  • 200+ paying users
  • 30,000+ ad creatives generated by our users in the last 2 months

We're a YC company based in San Francisco, and we run the company on agent harnesses ourselves .

The role

You will own growth and distribution for GooseWorks.

Your job will be to build the systems to scale content , and having the creative taste and judgement to improve them.

More specifically, you will own:

  • Creator channels, AI-operated. You design the niche, the format, the hooks, the content, everything and use our AI creative agent to make organic social content at SCALE.
  • Our voice on X and LinkedIn . Not "brand content", value content and stories that get noticed.
  • The taste layer of our creative agent. You'll teach our creative agent what "good" means. It's the highest-leverage work at this company.
  • Launches. Narrative, assets, video, sequencing, day-of. End to end, from a blank page.

What we're looking for

  1. Taste. You know what good content looks like. You have a great sense of design. You understand what people resonate with.
  2. Proof-of-work: We need to see that you can make short-form that performs. IG, TikTok, YouTube, etc.
  3. Technical AI video skills. You know what it takes to make great content using AI, and you’ve already been doing it.
  4. You think in systems. We’re not looking for someone to write content. We’re looking for someone to build the thing that does.
  5. You live inside AI agents. Claude Code, Codex, etc. You understand what a harness is and how to build one.

Strong preferences for:

  • a technical background
  • proven content creator muscle

This is a 0→1 job

That means:

  • High ownership : You'll own channels end-to-end, whatever that might mean. You’ll have autonomy and a high degree of creative control.
  • Lots of experimentation : You’ll try lots of things fast and double down on what works.
  • Messy problems, fast loops. Ship daily, execute is measured in hours, not weeks.
  • You're part of the founding team.

You're probably not a fit if

  • You’re used to working with large teams to get things done.
  • You have never created awesome content.
  • You have never built a content systems or agent skills / harnesses.
  • You think AI-generated content can never be more than slop. (we’re looking for someone to prove the world wrong)

Goose is an AI creative engine that turns your brand into a continuous stream of on-brand video ads.

We index your existing materials — videos, product shots, testimonials, ad performance data — into a context layer, then generate short-form creative for Meta and TikTok at the volume performance marketing actually requires.

The engine compounds: the agent learns from ad performance, competitors, trends, and human feedback, so your creative gets better every month.

Launch HN: Mireye (YC S26) – Infrastructure for Physical World AI Agents

Hacker News
www.mireye.com
2026-09-03 12:24:13
Comments...
Original Article

Every value cited

Power your agents to make decisions about the physical world

Sectors we power

Every “should I care about this place, and why?” question routes to the same API — these are the desks already asking it.

  • Data center siting

  • Renewable energy siting

  • Insurance underwriting

  • Mortgage & title

  • Residential land

  • Commercial lending

Frequently asked questions

Mireye is the physical-world layer for AI agents: sourced data, enrichment, and the tools on top of them. Ask a question in natural language, resolve an address to its canonical parcel, or fetch cited fields at any US coordinate — one API and one MCP server, with a citation attached to every field.

Give your agents the context to act in the physical world.

Launch HN: Mireye (YC S26) – Infrastructure for Physical World AI Agents

Hacker News
news.ycombinator.com
2026-09-03 12:24:13
Comments...
Original Article

Hi HN, I'm Ansh, founder of Mireye ( https://www.mireye.com ). I'm building the infrastructure AI agents use to make decisions about physical places: data, enrichment, tools, and signals for any US location, behind one API and MCP server.

Here's a demo video: https://www.youtube.com/watch?v=haqO6UbUqU0

To try it, paste https://www.mireye.com/skills.md into your agent, and grab a free key at mireye.com (5,000 credits, no card). Docs are at https://docs.mireye.ai . The fastest way in is to ask the API any question about any US location. Test it on a place you know, cold and grade it against what you know.

Before Mireye I was building construction agents and hit this wall myself: my agent could reason about anything online but knew nothing about the ground under it. Then a Fortune 500 insurer told me their engineers had given up on underwriting agents for the same reason. Frontier models keep hallucinating when asked a specific question about a specific place.

My first product was a niche site-screening app. Customers tested it on places they knew and the answers held up, but nobody cared about the app. They wanted the engine underneath. Usage agreed: 311 of the 317 fields in the catalog get queried and no use case dominates. So I killed the app and started building the infrastructure instead.

Mireye is not a dataset with an API on top, because facts alone are not a decision. An agent runs the whole job through it: cited facts, a bare address enriched into owner, acreage, structures, and nearby power, tools for the operations models get wrong, and signals when something changes, like a rezoning filing. Data, enrichment, tools, signals.

The tools came from watching agents fail. We build agents on our own infra, and the same things kept breaking: an agent would eyeball a distance instead of computing it, grab the wrong parcel for an address, or burn its whole budget halfway through a batch. Each failure became something an agent can call: deterministic geometry and drive-time tools, parcel resolution, a quote endpoint that prices a job before it runs, and skills that package whole workflows like screening a site or underwriting an address.

The hard part surprised me. Every source has to be gathered (sometimes county by county, in whatever format each county publishes), normalized into one schema, contracted (where it comes from, what each value means, how often it refreshes), and then kept fresh forever. We run that loop for 366 fields today, served multi-tenant from one index, and every source fought back differently. Maryland publishes a dataset literally titled "Hidden Property Owner Names." I filed public records requests in North Carolina because nobody indexes sewer mains.

The deeper problem is meaning. Two counties publish a field with the same name and it means different things. And the most dangerous value is null. Does it mean "no flood zone here" or "this county never mapped floods"? Put a model in front of that gap and it fills the silence with a plausible number. So we type absence. Every field returns ok, absent, or failed. Customers have told me the refusals are why they trust it.

The newest piece is on-demand indexing. Ask for a field we don't have and a long-running agent researches sources, collects the data, tests it against ground truth, and indexes it, usually within a day. I'll take a few field requests from this thread and report back with what it built.

People have built things I didn't plan for: insurance teams screening portfolios for flood, wind, and wildfire, a proptech cleaning messy listing addresses through enrichment, a wellness brand scoring street corners for poster spots, a robotics company sourcing warehouses, data center site selection, drone deployment planning, school bus routes for a city, signals for human trafficking investigations. The mission is to index every inch of the earth and make it as queryable as the web.

Pricing is public: the free tier is 5,000 credits a month, $19/month for 25,000, $99/month for 120,000, custom for enterprise.

I'd love to hear where the agents you're building touch the physical world. And I'd love it more if you run Mireye on a place you know and tell me what we got wrong.

Artificial beaver dams saw juvenile coho salmon survival rates go from 8% to 60%

Hacker News
www.discoverwildlife.com
2026-09-03 12:21:33
Comments...
Original Article

It’s well known that beaver dams transform landscapes. In their absence, artificial versions were built in northern California to recreate lost wetlands – boosting the survival of threatened coho salmon.

The findings are published in Frontiers in Ecology and Evolution . Fish biologist Michael Pollock of NOAA’s Northwest Fisheries Science Center called the results “mind blowing”.

The Scott River valley in northern California was once home to so many beavers it was known as Beaver Valley. Their dams created an enormous riverine wetland, providing habitat for juvenile coho salmon and a host of other wildlife.

Then European fur trappers arrived in the 1830s. Thousands of beavers were trapped and killed, and much of the habitat created by their dams and wetlands was lost – taking with it the cold, slow-moving habitat favoured by coho salmon.

Coho salmon in French Creek
A coho salmon in French Creek, a tributary of Scott River, California. Credit: David Herasimtschuk, FreshwatersIllustrated

With the beavers all but gone, in 2015 the nonprofit Scott River Watershed Council built two artificial dams on a tributary called Sugar Creek. Wooden posts were hammered into the streambed, interwoven with willow and conifer branches, then the gaps were plugged with gravel, straw and mud.

Three years later, several more dams were built on another tributary, called French Creek. From time to time, the remaining beavers even chipped in, repairing, modifying and sometimes expanding the dams. “When beavers do adopt a structure, their work is far superior to what we can accomplish,” says Charnna Gilmore from the Scott River Watershed Council.

Chinook salmon passing an artificial beaver dam
Chinook salmon passing an artificial beaver dam. Credit: Scott River Watershed Council

The artificial dams held, creating around 9,000 square metres of new habitat with the capacity to support more than 8,500 young salmon. Compared with areas where no new dams were built, the water in the restored habitats stayed cooler, avoiding temperatures known to stress the fish and slow their growth. Juvenile coho survival rates soared, from 8% before the dams were built in French Creek to 60% afterwards.

Juvenile coho survival rates soared, from 8% before the dams were built in French Creek to 60% afterwards.

Coho salmon spend their first summer in freshwater before heading out to sea and later returning to the streams to breed. Two years after the first dams were built, more salmon were returning to the Scott River than to any of the other rivers monitored in the study. And while salmon numbers elsewhere remained low, returns to the Scott River stayed healthy, even during severe drought.

Small, low-cost interventions yielded big, impressive results. But it’s bittersweet. “My take is that the artificial dams have helped people remember what the beaver can do and how integral they are to the health of stream ecosystems,” says Pollock. “But beavers can only thrive if landowners allow them to.”

Find out more about the study .

Coho salmon, French Creek
Following the construction of the dams, juvenile coho salmon survival rates soared from 8 in French Creek. Credit: Herasimtschuk, FreshwatersIllustrated

Top image: Sugar Creek, California. Credit: Scott River Watershed Council

More wildlife stories from around the world

Texas Data Center Map: See where data centers are operating or planned

Hacker News
www.kxan.com
2026-09-03 12:10:12
Comments...

VC isn't VC anymore – understanding the rise of Cancer Capital

Hacker News
www.anildash.com
2026-09-03 11:51:53
Comments...
Original Article

We really, really need to talk about venture capital. Because it’s not “venture capital” anymore.

There’s a huge disconnect between what most people think of VC, where an investor has a big fund and cuts checks to help a founder build a company, and the current reality, where a handful of billionaire extremists use the cover of “VC” to advance an outrageous agenda where they’re accountable to no one.

I’m gonna explain this from a standpoint that almost never gets articulated: I’ve personally raised tens of millions of dollars in venture capital funding as CEO of startups, and been directly involved as a board member or advisor in raising hundreds of millions more. I’ve sat in board rooms, across the table from the people I’m talking about here, or been at the industry events that they frequent. So this isn’t sour grapes because these VCs wouldn’t cut me a check, or some chip on my shoulder about these investors due to a business deal. This is what I know about these bad actors because I’m part of the community of creators and inventors who build the things that they used to invest in — back when they still cared about innovation.

Many of the trends in society and politics that people are most angry about, from data centers being forced down everyone’s throats, to all of our favorite apps and services being enshittified , to politicians being paid to ignore the will of the people, are all being supercharged by these cancer capitalists. They have warped the structure of venture capital into a form of oligarchy that answers to no market, no regulators, and no voters. So it’s worth understanding exactly how they did it.

How Venture Capital became Cancer Capital

I’ll be breaking these points down in further detail, but just to begin framing the concept, I’ll lay out the core idea here in some bullet points (so that you’re not tempted to run this whole thing through an LLM):

  • Venture capital was only supposed to be a tiny segment of the overall capital market, but it has expanded to become the primary form of funding that new companies consider — it was never the only way , and it didn’t used to be the default one
  • VC was meant to be a small percentage of overall investment because it represents the high-risk, high-reward part of a portfolio; to be healthy, most of a portfolio — or most of an economy — needs to focus on assets that are more stable and predictable. But a cancer grows from a cell that a body needs in small, healthy amounts, and that turns deadly when it grows without limit until it harms, or even kills, its host.
  • As regulations have gotten looser in recent years, a handful of venture capital firms have become “do everything” funds that combine private equity with their existing VC businesses, and expand to manage massive stockpiles of tens of billions of dollars
  • The 1% of VC firms that get this big stop being exposed to the risk in their own investments at all — when you collect 2% a year to manage $50 billion, that’s a billion dollars landing in your pocket annually whether any company you funded lives or dies. Those firms also stop legally even being venture capital firms , making them unaccountable to markets, founders, or the law — and that’s how they become “Cancer Capital”
  • Meanwhile, the 99% of “normal” VCs don’t have the power or funding of the Cancer Capital firms, but are forced to play on the field that those firms define, even if they don’t like the way they do business
  • Since the Cancer Capital firms have become so powerful, the overall balance of power between founders and VCs has flipped; instead of founders having a company that VCs would try to fund, now VCs publish extremist political manifestos , and “founders” are just the people who are selected to carry out parts of those plans
  • The rest of the world doesn’t know: New founders and workers entering the tech industry are unaware that Cancer Capital has taken over, so many are still trying to play by the old rules, and can’t figure out why their ideas are being pushed into serving the goals of the Cancer Capital firms
  • Politicians and media still look at VC as if it works like it did 10 or 20 years ago, and cheer them on like they’re funding job creation or enabling new companies to grow, when their primary goal is concentrating power and wealth into the hands of the Cancer Capital tycoons . They keep getting fooled by this, over and over.
  • These days, venture firms are increasingly getting their funds from pension funds and retail retirement accounts, meaning the public (you!) are increasingly holding the bag for the parts of their portfolios that actually have some risk, even if you never intentionally made that choice
  • The shift away from IPOs in the tech industry has also encouraged these Cancer Capital firms to find ways to cash out long before companies ever go public, meaning they can make a massive return off of companies that never make a penny of profit, even if regular investors get screwed by the stock of a company once it actually gets listed on the public stock market.
  • Part of why this has gotten so corrupt is the way the Cancer Capital firms have transformed themselves into their post-VC forms. Because they’re not legally VC firms anymore , they’re free to buy shares directly from founders, or hold unlimited amounts of publicly-traded stock — exactly what they couldn’t do as regular VCs. They can even sell their investment in a company as an asset to another one of their own funds , and then book the increase in value as a profit, all without the company ever having made a penny. Another racket: a company that’s raised a bunch of cash in a funding round can buy out its early investors if they’re one of these post-VCs, so they can get paid off even if their portfolio company has never made a penny in profits or revenues.

All of this self-dealing, and the way that they’re isolated from any accountability, has made these firms become more and more shameless in their behavior. Former Andreessen Horowitz partner John O’Farrell publicly called out the firm (a rarity — the company is notoriously vindictive towards those who it decides are disloyal) for what he called its “political infiltration” of AI policy. Marc Andreessen, Ben Horowitz and their firm have put $115.3 million into this midterm cycle — nearly double their $63 million in 2024, and more than any other billionaire donor in the country , even including Elon Musk. Molly White , whose Tech Influence Watch tracks this money against FEC filings, shows that a16z alone accounts for more than 20% of all political contributions from the entire cohort of crypto and AI companies it follows. And they’re funneling these funds to candidates in both parties . This is a huge escalation from the tentative baby steps that folks like Zuckerberg were making in the Obama era, working on benign issues like trying to help immigrants.

And of course, it gets a lot worse than just their lobbying. As I have frequently noted , Andreessen Horowitz hired a man as a partner at their firm despite his having no background or qualifications in tech, finance, or startups whatsoever. His only discernible qualification was that he had choked my unarmed neighbor Jordan Neely to death on a subway car.

This is how brazen, how toxic and destructive, we’ve allowed the industry formerly known as venture capital to become. We must understand that it is no longer a financial machine that is used to fund startups, but a political and social machine focused on dismantling democracy and civil society . And it’s time to act accordingly.

Up next: we’ll dive into the specifics of many of the points laid out above, to understand more about how we got here.

Flock Taught Cops How to Surveil No Kings Protesters

403 Media
www.404media.co
2026-09-03 11:49:18
A Flock webinar teaches police how to surveil protests, fireworks shows, parades, bike races, and more....
Original Article

A Flock webinar teaches police how to surveil protests, fireworks shows, parades, bike races, and more.

Flock Taught Cops How to Surveil No Kings Protesters

Flock taught cops how they could surveil the No Kings protests and “small parades” using a mix of Flock’s technology and law enforcement’s own databases in a webinar last year. As Flock publicly downplays the power of its automated license plate camera network and highlights its use to solve violent crime, the company’s seemingly endless trove of webinars, training sessions, and blog posts show it offers far more invasive capabilities.

In the webinar , Flock’s director of market management Caity Peak explains how real time crime centers — which are police surveillance centers that utilize Flock cameras and other surveillance cameras — can be used for emergency response, but can also be used to surveil “established events” like 4th of July fireworks displays, parades, bike races, Mardi Gras, and protests. The webinar shows just how routine the idea of always-on surveillance has become, and how casually it is used during extremely innocuous events.

Peak explains that police can use FlockOS , a software platform that combines Flock’s automatic license plate readers (ALPR), drones, gunshot detectors, 911 data, and other surveillance cameras (including ones Flock does not own) into a “single pane of glass” or single piece of software to look at various types of surveillance in one place during both emergencies and relatively mundane events in a city or town.

0:00

/ 3:47

“Imagine that you’re an incident commander, and you’re working this No Kings Protest,” Peak explains while a dashboard shows a series of surveillance tools overlaying the city of Denver. “If I’m somebody assigned a traffic post that’s working this No Kings Protest, I really don’t have time to go in […] and look at all these places [for different intelligence]. This is an example of viewing all of that in one place. I’m an officer, I can see the response plan that’s included, I can pull that up if I need it, but I can also see live video footage as that protest moves throughout the park.”

Peak says the surveillance footage can be used to monitor the protests without having cops physically on the ground “making it worse, getting attention.”

“I’ve got the video footage to monitor when things go sideways, I know when the environment is starting to shift. But I also know a lot of other things as well. I can see traffic flow, so as people are blocking the roadway, maybe that’s OK for a while, but if I see that traffic has been stopped a while, I may need to send officers to that area because I know that road rage is imminent,” she continues. The dashboard Peak shows includes traffic information, a “response plan” for the protest, the floor plans of nearby buildings, as well as a series of video feeds of both outdoor-mounted cameras and cameras inside businesses and government buildings.

404 Media and the Electronic Frontier Foundation previously showed that police have specifically used Flock cameras to monitor the No Kings protests and other First Amendment-protected activity. 404 Media found California cops used Flock to monitor an “immigration protest.” The EFF found that the following law enforcement agencies ran Flock searches related to No Kings protests and rallies:

This webinar shows this type of surveillance is not anomalous, and is specifically taught by Flock. The webinar also shows that Flock’s latest public stance — that its ALPR cameras are noninvasive technology, that they take only static images at a single place and time, and that they are primarily used to solve the worst crimes — is wildly misleading. Flock has time and time again pitched itself to police as a sort of operating system to solve crime and do real-time surveillance and predictive policing. ALPRs are just one part of this broader surveillance apparatus that Flock has created, markets to police, and teaches them how to use. These real time crime centers are proving increasingly popular with police; Flock now says on its website that more than 4,800 cities around the country are running FlockOS software .

Matt Patin, a former New Orleans Police Department officer and current Flock employee, explains in the webinar that the dashboard can show ALPR data, body camera footage, and other data to “give me a full situational awareness of what’s going on.” Peak explains that, back when she was a cop, she used to hope that people would plan events near intersections that had ALPR cameras. “We’d have to pick which intersection is going to make sense [for an ALPR camera], where do we see the most traffic, where do we see the most events, and then I hoped that if an event happened in front of a camera, it’s one that’s in an intersection where I chose to put [the ALPR] and not one where I chose not to put an ALPR,” she says, adding that she would try to think which types of cameras and drones to use to police a specific event. “I want to make sure I have as many tools to make myself dangerous if and when I need it,” she adds.

Peak goes on to give another example, in which police would surveil a car sideshow near Sacramento using a mix of drones, surveillance cameras, ALPRs, and monitoring of social media posts. “We knew it was likely to turn into nefarious activity based on who was promoting the car show,” she says. A list of “THINGS TO LOOK FOR” include “mismatched front and rear wheels, stickers representing car clubs, and covered up license plates with car club logos.” Peak then demos Flock’s free-form search , which is “AI-powered video search and alerts.”

“Let’s take Flock’s free-form feature and say ‘hey, any time you see a car tonight with multi-colored wheels passing by any one of these five LPR cameras, I want you to send us an alert,’” she says. She then explains how Flock Nova , the company’s deeper investigative tool, can be used to marry LPR information with “all of your agency data,” which in this example includes “person data, IP data, email data, sex offender data, license plate data, vehicle data, and OSINT [open source intelligence].” A screenshot of the Flock system shows a “street racing suspect” complete with the man’s name, address, email, social media accounts, phone number, and various affiliations.

“It works like a Google Search,” she says, imagining a scenario in which cops pull someone over then use Nova. “I run him through Nova. I can query CAD [computer aided dispatch], RMS [records management system], OSINT, jail records. All these things we have integrated to see that we have contacted him before for sideshows, he has been contacted for spinning cars in an intersection in the last 90 days, he is related to this car club, and now with that information, I have the justification I need to actually tow the car for 90 days instead of just issuing a citation.”

Later in the webinar, police from New Orleans and Flock representatives spoke about how its system was used by police in the aftermath of the Bourbon Street terror attack that killed 14 people on Jan. 1, 2025 and during the Super Bowl and Mardi Gras that year. The webinar highlights how this tech is used after a crime, and how the data often filters across agencies. Ross Bourgeois, who runs New Orleans' real time crime center, says that the city used a "tremendous amount of cameras in a very short time" to recreate the terrorist's movements.

“We were able to use our network of cameras and license plate readers to map out what he did when he entered the city a day or two before the event, up until he executed the event and engaged the police and our shooting situation at the conclusion of it,” Flock's Patin said, adding that footage running through FlockOS were eventually shared with the Department of Homeland Security, federal fusion centers, and the FBI. “7 terabytes of information, which was a lot of data, and we were able to share that with our fusion center and our federal partners. Homeland Security, HSI [Homeland Security Investigations, a division of Immigration and Customs Enforcement], and FBI.”

Sony makes bold claim about game ownership

Hacker News
aginggamer.net
2026-09-03 11:44:54
Comments...
Original Article
Timed out getting readerview for https://aginggamer.net/game-industry/sony-makes-bold-claim-about-game-ownership/

K2 Horizon: Frontier Performance, Radically Open

Hacker News
ifm.ai
2026-09-03 11:36:43
Comments...
Original Article

Today IFM is releasing K2 Horizon, a connected fleet of six models: 375B-A23B, 36B-A4B, 32B, 7B, 3.7B, and 0.9B. Across reasoning, mathematics, coding, agentic tasks, and general capabilities, K2 Horizon delivers top-tier performance in every size class—with the 0.9B, 3.7B, and 7B models setting new state of the art at their respective scales.

K2 Horizon is also our most comprehensive open release to date. For every model, we are opening the training lifecycle from pretraining through reasoning and agentic post-training. We are releasing intermediate checkpoints, training data or detailed data-construction recipes, open architecture, mixture compositions, training code, configurations, fine-grained logs, evaluation results, and final weights.

The models and code are released under the Apache 2.0 license. Datasets are released under their applicable licenses, such as ODC-BY; We disclose how the data was constructed and mixed when redistribution is not possible.

Together, K2 Horizon represents the most comprehensive open model release to date:

  • A new performance frontier across scales. The 0.9B, 3.7B, and 7B models achieve world-leading performance in their size classes across widely used evaluations. The 36B-A4B model, equipped with our new Mixture-of-Value-Attention (MoVA) mechanism, delivers exceptional capability per active parameter, outperforming some much larger models. The 32B and 375B-A23B models rank among the top models in their respective classes. Together, the six models provide competitive performance across deployment environments ranging from edge devices to the enterprise.
  • The first fully open model fleet for agents. K2 Horizon is the first open model family to expose the complete development process through agentic post-training. By releasing checkpoints, data (or data recipe), code, configurations, and training logs across every stage, K2 Horizon makes it possible to study how reasoning, tool use, planning, and agentic capabilities emerge; reproduce the methods that create them; and adapt those methods to new tools, environments, and domains.
  • Six models spanning edge to enterprise. The 0.9B model is designed for highly constrained environments such as watches and glasses, while the 3.7B and 7B models bring advanced capabilities to phones and other on-device applications. The dense 32B model and sparse 36B-A4B model provide powerful options for local workstations and efficient serving. The 375B-A23B model brings the fleet’s strongest capabilities to demanding enterprise deployments. All six models include quantization support.
  • One connected fleet. The six models share core architecture, vocabulary, training methodology, interfaces, evaluation infrastructure, and deployment tooling, with a smaller vocabulary for the 0.9B model. This consistency also makes it easier to move between sizes, route work dynamically, and study capability and efficiency across scale.

World-leading performance across the scales

The 0.9B, 3.7B, and 7B models achieve state-of-the-art results in their respective classes across mathematics, reasoning, general capability, coding, and agentic tasks.

The 36B-A4B model performs beyond the level normally expected from its active parameter count, demonstrating the efficiency of our unique Mixture-of-Expert design when computing attention values. The 32B and 375B-A23B models place among the top models in their respective comparison classes.

The small models are especially notable. K2 Horizon 0.9B achieves an AIME 2026 score above 48, along with strong reasoning, tool-use, and agentic capabilities. K2 Horizon 3.7B and 7B extend these capabilities to more demanding software-engineering and multi-step environments, demonstrated on strong performance in SWE-bench and BrowseComp. Although complex tasks that require extensive exploration and repeated recovery, such as those in TerminalBench, remain difficult for the smallest models, K2 Horizon moves the boundary of what is possible at every scale.

Why the Horizon Fleet matters

A transparent model that falls far behind the capability frontier has limited value as a foundation, even for research. At the same time, a powerful model released only as final weights allows people to run it, but provides little insight into how its capabilities were created.

K2 Horizon brings these two together. The fleet provides highly competitive models and releases the recipes used to train them. Researchers can study advanced capabilities in models strong enough to exhibit them, while developers can reproduce, adapt, and extend the methods rather than treating the final checkpoint as an opaque starting point.

Since introducing the fully open principle in our 2023 LLM360 paper , we have released open models every year while extending that commitment to larger scales, stronger capabilities, and now the complete lifecycle through agentic post-training.

A Deep Dive into The K2 Horizon Fleet

K2 Horizon 375B-A23B: the enterprise powerhouse

K2 Horizon 375B-A23B is the fleet’s largest and most capable model. Its sparse MoE architecture provides 375 billion parameters of total capacity while activating approximately 23 billion parameters for each token, allowing it to draw on the capacity of a much larger model without using every parameter for every token.

The model ranks among the top models below 400 billion parameters across general, reasoning, coding, and agentic evaluations. It is designed for demanding workloads where model quality matters most, including complex reasoning, software engineering, research, and long-horizon agentic tasks.

Like every model in the Horizon fleet, 375B-A23B is released not as a single endpoint but as a development tree. Its intermediate checkpoints and post-training branches expose how the base model develops into reasoning, instruction-following, and specialized agentic variants.

K2 Horizon 32B and 36B-A4B: strong performance for local deployment

Horizon 32B is the fleet’s most powerful dense model, providing a strong balance of capability, adaptability, and local deployability. It ranks among the top dense models below 40 billion parameters.

Horizon 36B-A4B reaches nearly the performance of the dense 32B model while activating only approximately 4 billion parameters per token. Its efficiency comes from MoVA, our new sparse attention architecture, together with MoE feed-forward layers.

These two models serve as an important reference point for studying how dense and sparse architectures behave under similar training conditions.

These models occupy the fleet’s local performance sweet spot. They are powerful enough for demanding reasoning, coding, and agentic applications while remaining practical for local workstations and efficient serving systems.

K2 Horizon 7B, 3.7B, and 0.9B: frontier capability at small scale

k2 Horizon 7B and 3.7B deliver strong reasoning, mathematics, coding, tool-use, and agentic performance while remaining suitable for local and on-device deployment. On several evaluations, their results approach or exceed those of models many times larger from the previous generation.

K2 Horizon 0.9B carries many of the same capabilities into highly constrained environments. It can perform mathematical reasoning, use tools, and complete simple agentic tasks while remaining compact enough for applications on watches, glasses, and other edge devices under quantization.

The appropriate task changes with scale: the 0.9B model is best suited to focused interactions and lightweight tool use, while the 3.7B and 7B models can handle more demanding coding and multi-step workflows. Together, they demonstrate how much capability can now be retained in models small enough to run almost anywhere.

Designing K2 Horizon

One family from the beginning

Horizon was designed as a connected family rather than a collection of unrelated models. The six models share core architectural decisions, training methodology, interfaces, evaluation infrastructure, and deployment tooling. This allows developers to move between sizes more easily and gives researchers a more controlled setting for studying capability across scale.

Each model is pretrained on approximately 20 trillion tokens using carefully constructed and documented mixtures. Intermediate checkpoints and their corresponding fine-grained logs are captured throughout training, creating a detailed record of how each model develops.

MoVA: scaling attention with sparse experts

The core idea behind mixture-of-experts is to increase total model capacity while keeping the computation required for each token roughly fixed. Conventional MoE architectures apply this sparsity primarily to feed-forward layers: many specialized experts are available, but a router activates only a small subset for each token.

Our new architecture, MoVA—Mixture-of-Value Attention, extends this principle to attention . Because attention determines how a transformer brings together information from across its context, introducing sparsity there opens another dimension for scaling model capacity beyond the feed-forward network.

MoVA integrates expert routing into multi-head attention while remaining compatible with efficient techniques including FlashAttention, grouped-query attention, and sparse attention.

The result is K2 Horizon MoVA 36B-A4B: a model with 36 billion total parameters but approximately 4 billion active parameters per token. Under the same training conditions, it performs only slightly below the dense Horizon 32B model while requiring substantially fewer active parameters.

Training Data

Training across six scales requires data that is broad enough to support general capability and carefully constructed enough to maintain quality over approximately 20 trillion tokens.

Horizon’s pre-training mixture combines diverse web, code, mathematical, scientific, multilingual, and domain-specific sources with synthetic data generated through our own pipelines. One of our key data innovations is the incorporation of reasoning directly into pre-training: nearly 17% of the pre-training corpus consists of problem-solving trajectories with explicit reasoning. Reasoning trajectories for mathematical tasks were further rewritten into formats such as dialogues and study guides. In total, we used approximately 10 trillion synthetic tokens during pre-training.

Our synthetic data pipelines use millions of combinations of diversity knobs and context seeds, including retrieval from an internally built search engine over the pre-training web corpus. To quantify diversity at corpus scale, we developed a custom gzip-based compression metric with adaptive striding to avoid the rapid saturation of standard gzip-based measurements as the number of documents grows. As shown below, the measured diversity of our synthetic data approaches that of high-quality natural web text and substantially exceeds that of web code.

We document the data composition, synthesis pipelines, and construction of the training mixture. Following our open-source principles, where licenses permit, we release the training-ready datasets directly. Where redistribution is restricted, we release source descriptions, filtering and construction methods, and mixture composition. This allows researchers to understand what each model learned from and how the data distribution evolved throughout training.

Our post-training data is introduced from the beginning of mid-training, rather than being reserved exclusively for the final stages of training. We combine synthesized long-context documents with instruction-following, reasoning, and agentic trajectories formatted with the chat template. A main pillar of our post-training data is large-scale task synthesis grounded in task taxonomies, diversity knobs, and web-search seeding, resulting in over 100 million unique tasks. In addition, we developed sampling techniques that guide solver LLMs toward correct solutions and desired behaviors when generating training trajectories.

Pre-training Dynamics

Every K2 Horizon checkpoint is accompanied by detailed training logs and fine-grained histories that expose the real dynamics of large-scale training: how losses evolve, where instabilities appear, how interventions affect training, and when capabilities begin to emerge.

As an example of why these records are useful, K2 Horizon 3.7B, 7B, 32B, and 36B-A4B were trained on exactly the same 22 trillion tokens. When aligned by training progress and normalized by the median loss over the final 1% of training, their raw loss trajectories approximately collapse, which you can see in the figure below—even across dense and sparse architectures and nearly an order of magnitude in total parameter count. Although this normalization aligns their endpoints by construction, it does not force the early and intermediate trajectories to coincide. Their close agreement shows that, under shared data and a common recipe, the shape of learning remained remarkably consistent across the fleet subset that used the same dataset throughout training.

Together, the checkpoints and logs allow researchers to investigate why some dynamics transfer across scale and architecture while others diverge, and to connect those differences with particular training stages, data mixtures, and technical decisions.

Post-training for reasoning and agents

Most of K2 Horizon’s advanced reasoning and agentic capabilities emerge during post-training. The complete pipeline includes mid-training, supervised fine-tuning, model merging, reinforcement learning with specialized agent training. Rather than producing only one final chat model, this process creates a development tree. Different branches specialize in reasoning, coding, tool use, and agentic domains while remaining connected to common base checkpoints.

We release the artifacts across these stages so researchers can study where each capability emerges, reproduce individual branches, and adapt the same methods to new tools and environments.

Uno Diffusion: plug-and-play lossless speedup for Horizon

Inference speed has become a first-class optimization target, especially in the era of reasoning models and agents. As models produce longer chains of thought and take more actions, even small per-token delays compound into substantial latency. Yet autoregressive language models generate one token at a time, creating a fundamental bottleneck. Existing approaches offer partial solutions: speculative decoding typically requires a separately trained draft model, while discrete diffusion enables parallel generation but often sacrifices quality for speed.

Uno is designed to remove that tradeoff. It provides a lossless inference speedup , accelerating generation without degrading response quality. Uno keeps Horizon’s autoregressive parameters frozen and fully responsible for the model’s output distribution, while a lightweight set of diffusion parameters learns only how to generate more efficiently.

Through a process we call Diffusion Distillation , these compact adapters learn to generate blocks of tokens in parallel. The result combines the quality guarantees of autoregressive decoding with the speed advantages of diffusion: the model reaches the same answers, but reaches them faster.

Across our evaluations, Uno achieves a better speed–quality tradeoff than leading speculative-decoding systems and both open-weight and proprietary diffusion language models. Crucially, its gains persist across every batch size we tested, enabling lower latency for interactive agents and higher throughput for large-scale serving, with no loss in model quality and negligible additional training overhead. Uno is delivered as a simple LoRA adapter , making this lossless speedup easy to adopt: all you need is to attach the adapters.

Open infrastructure for building and extending Horizon

We are releasing the infrastructure used to build Horizon alongside the models themselves. The goal is not only to make the fleet reproducible, but to make its development stack useful as a foundation for new models and systems.

At the center of this release is xLLM , our production-tested training infrastructure. xLLM combines large-scale training performance with the flexibility required for research, allowing teams to modify architectures, data mixtures, training stages, and objectives without rebuilding the surrounding system.

We will be also releasing our full agentic post-training code base, including Reinforcement Learning, which we hope will help researchers to advance the techniques in related areas.

Researchers can use these components to inspect training behavior or reproduce a particular stage. Developers can adapt Horizon to a domain, add new tools, train agent experts, or deploy several model sizes behind a unified interface.

From Open Source to Open Science

Intermediate checkpoints turn model development into an observable scientific process. They allow researchers to study when capabilities emerge, how training choices change behavior, and when unintended strategies first appear.

Reward hacking provides one revealing example. When a capable model is placed in a realistic computer environment and told to solve a complex task, the same resourcefulness that makes it useful can also lead it to exploit shortcuts in the evaluation itself. To understand how much this affects K2 Horizon's reported numbers, we audited the released model using Artificial Analysis's reward hacking auditing procedure .

The JACKPOT moment: our model found the benchmark's solution on GitHub and expressed "excitement" at having the answer handed to it.

TerminalBench 2.1 places models in sandboxed computer environments and evaluates whether they can complete complex technical tasks. A capable model must explore files, invoke tools, diagnose failures, and find alternative paths toward a solution. That resourcefulness is exactly what we want. But occasionally it crosses a boundary: instead of solving the intended problem, the model locates a hidden answer, exploits something the task left exposed, or manipulates the grader itself.

We ran K2 Horizon 375B-A23B on 89 TerminalBench 2.1 tasks with eight attempts each, producing 712 trials. Of these, 500 passed the task verifier (70.2% reported accuracy). We then audited every passing trial using Artificial Analysis's reward hacking auditing procedure, applying their harbor analyze tool with the reward_hacking criterion and their full rubric text verbatim, with Codex gpt-5.6-sol as the judge model.

The audit flagged 24 trials across 10 tasks. Removing them lowers the accuracy from 70.2% to 66.9%, a correction of 3.37 percentage points. The remaining 79 tasks were fully clean. For context, Artificial Analysis reports flag rates of 2.2% for claude Fable 5 and 4.1% for GPT-5.6 Luna; K2 Horizon's 3.37% falls within that range.

The model discovered several strategies:

  • Inferring it was inside a public benchmark, finding the repository on GitHub, and downloading the reference solution
  • Pulling the current source from a real project's public repository and copying the fix rather than deriving it
  • Inspecting unadvertised files, generator scripts, or exposed credentials
  • Editing the test harness or crafting output that exploited how the test checked success

We observed a related case with K2 Horizon 7B, which found and downloaded SWE-bench answers and consequently produced an inflated score of 82. The score does not represent genuine software-engineering performance, but the behavior is scientifically revealing: benchmark hacking emerged as an unintended consequence of broader planning, tool use, environment exploration, and persistence.

Because we release intermediate checkpoints alongside the final models, these behaviors can be studied rather than hidden. Researchers can determine when a strategy first appears, connect it to changes in training, and measure its effect on reported performance.

K2 Horizon is therefore more than a collection of model weights. It is an open experiment in how capabilities—and their unintended consequences—develop throughout training.

Get Started with K2 Horizon Today!

All six K2 Horizon sizes are released as open weights under Apache 2.0, with day-zero support from vLLM, SGLang, and Ollama. Further, K2 Horizon supports deployment on NVIDIA, AMD, and Cerebras hardware, providing options from local inference to large-scale serving. Get the models from our repository: https://huggingface.co/IFM , download the models, inspect intermediate checkpoints, study training data and mixtures, reproduce training stages, or build new models and agents using the Horizon code and infrastructure.

K2 Horizon provides more than six final models. It provides an open blueprint for understanding, adapting, and advancing the next generation of AI systems.

Full Result Table

375B-A23B

36B-A4B

32B

K2 Horizon 7B

K2 Horizon 3.7B

K2 Horizon 0.9B

Dirk Eddelbuettel: RcppExamples 0.1.11 on CRAN: Very Minor Maintenance

PlanetDebian
dirk.eddelbuettel.com
2026-09-03 11:31:00
A new version 0.1.11 of the RcppExamples package is now on CRAN, and has been built for r2u. RcppExamples provides a handful of short examples detailing by concrete working examples how to set up basic R data structures in C++. It also provides a simple example for packaging with Rcpp. The package p...
Original Article

RcppExamples 0.1.11 on CRAN: Very Minor Maintenance

A new version 0.1.11 of the RcppExamples package is now on CRAN , and has been built for r2u .

RcppExamples provides a handful of short examples detailing by concrete working examples how to set up basic R data structures in C++. It also provides a simple example for packaging with Rcpp . The package provides (generally fairly) simple examples, more interesting, compelling (and generally longer) examples are at the Rcpp Gallery .

This releases updates a few Rd files to adhere to a stricter standing of checking by R. The NEWS extract follows:

Changes in RcppExamples version 0.1.11 (2026-09-03)

  • Add now-checked-for missing sections to manual pages

  • Updated continuous integrations two more times

Courtesy of my CRANberries , there is also a diffstat report for this release . For questions, suggestions, or issues please use the issue tracker at the GitHub repo .

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub .

/code/rcpp | permanent link

ChatGPT, Claude, and Grok Are Down

Hacker News
www.macrumors.com
2026-09-03 11:30:10
Comments...
Original Article

It is apparently not a good day for AI chatbots, as ChatGPT, Claude, and Grok are all down or experiencing issues for many users.

ChatGPT Feature
OpenAI's status page acknowledges issues across ChatGPT and Codex, while Grok's website notes that it is currently experiencing issues as well. Likewise, Anthropic's status page indicates Claude is experiencing elevated errors.

All of the companies are investigating the outages.

Update: The chatbots are in the process of coming back online.

Popular Stories

Free ChatGPT Users Get Unlimited Text Chats and GPT-5.6 Luna

Thursday August 6, 2026 11:52 am PDT by

OpenAI today said it is making GPT–5.6 Luna the default model for Free and Go ChatGPT users, giving them access to a newer, more capable model to replace GPT–5.5 Instant. The company is letting Free and Go users access unlimited text chats, with no text-based rate limits. Limits will still apply for file uploads, images, and other ChatGPT tools. There's also a new Think button coming that...

OpenAI's ChatGPT Speaker Will Be Hockey Puck-Sized and Cost Over $300

Thursday August 6, 2026 2:00 pm PDT by

OpenAI's upcoming AI device is a hockey-puck-sized, doughnut-shaped smart speaker with no display, reports Bloomberg. The product is meant to be easy to carry around with one hand, and it will have "moving parts that help give it personality," along with a price tag around $300 to $400. Bloomberg describes it as an AI-centric device that will stand out from current smart speakers. There are...

OpenAI Announces ChatGPT for Teens With Built-In Safeguards and Learning Prompts

Tuesday August 18, 2026 8:04 am PDT by

OpenAI is adding a ChatGPT mode for teenagers that includes parental controls, enhanced content safeguards, and a focus on learning. ChatGPT for Teens is "designed to help teens learn, think critically, deepen understanding, and use AI with confidence," said the company in a blog post announcing the feature. The feature includes learning-focused starter prompts for facilitating studying,...

How I converted BBC Micro Elite into a two-player game

Lobsters
elite.bbcelite.com
2026-09-03 11:29:55
Comments...
Original Article

How I converted BBC Micro Elite into a two-player game

Under the bonnet, BBC Micro Elite is a stubbornly single-player game. This makes perfect sense, as that's how the game was designed, but it does mean that it's a bit of a challenge for anyone wanting to coax a second player out of Bell and Braben's elegant code.

This article describes how I built two-player Elite. There's a lot to say, so I've split it up into a number of sections that cover the development process in the order in which I tackled it. You might like to read them from start to finish, but you can also click on them to jump down to the relevant section:

As with all my hacks, two-player Elite takes the original game's source code and modifies it; it is not a brand new game, it is a hack of the original. In the case of two-player Elite, the original game is the 6502 Second Processor version of Elite , with the flicker-free hack already applied. I then added all the various modifications required to add a second player on top of that base.

You can see all this in the project's GitHub repository . If you search the source code for "Mod:" then you will find every change that I've made to the original 6502 Second Processor version of Elite to get to two-player Elite. The changes are split between the parasite and I/O processor sources, as appropriate, and every change is documented to the same level of detail as the rest of the original game's source code (in other words, every single line is explained in detail).

I hope you enjoy reading about two-player Elite as much as I enjoyed hacking it into existence.

An overview of how two-player Elite works
-----------------------------------------

There's a clever conceit at the heart of 8-bit Elite that makes life considerably simpler for anyone working with the game code. It is this: the player is always at the centre of the universe.

For example, when the player moves forwards, they don't actually move at all; instead, everything else in the local bubble moves backwards. And when a player rolls to the right, they don't actually rotate; instead, everything in the local bubble rotates to the left around them. You can read all about this in the deep dive on rotating the universe , and it's key to understanding two-player Elite.

Always having the player at the origin makes certain aspects of the game code a lot simpler. For example, it's almost trivial to work out if an enemy ship is in the player's laser sights; we first check whether the enemy is in front of the player (i.e. z > 0 for the enemy's z-coordinate), and if it is, we check whether it is close enough to the z-axis to be within the enemy ship's targetable area (i.e. x^2 + y^2 < t for the enemy's x- and y-coordinates, with t being the targetable area from the enemy ship's blueprint). Because the z-axis points straight out of the front of the player's ship, out of the ship's nose and directly along the laser lines, we don't need to care about rotation or orientation, we just do some simple multiplication and the result is very accurate. You can read all about this in the deep dive on being in the crosshairs .

Unfortunately, this conceit makes it pretty difficult to add a second player to Elite. If the whole universe is centred on one player, then it can't also be centred on another player, so how do we address this?

One approach might be to run two separate instances of Elite, one for each ship, and have them talk to each other somehow; in essence, building a networked version of Elite, just within the same machine. This might work, but it would require a lot of memory and a lot of CPU power, and it would get pretty complicated pretty quickly.

Instead, two-player Elite fully embraces the player-centric conceit at the heart of the original game, and effectively bolts a second player onto this tried and trusted game engine. Let's consider the in-game two-player Elite screen:

Two-player Elite

The local bubble is still centred on one player; let's call them player 1, with the top space view showing the view from player 1's cockpit. In a very real sense, the top view is completely standard Elite, just cropped into a smaller part of the screen . When player 1 rotates or accelerates, they don't move, but the whole local bubble moves around them instead; the top space view is normal Elite in pretty much every way that matters.

Player 2, then, is simply another ship that is spawned into player 1's local bubble. Player 2 isn't at the centre of the universe; instead, they are just like NPC ships in the original game, so when player 1 rotates or moves, the whole bubble - including player 2's ship and anything else in the vicinity (like the planet or sun) - rotates and moves in the opposite direction, just like all the non-player ships in the original.

The difference is that player 2's ship is not controlled by the game's tactics routine; instead, it is controlled by player 2's joystick and secondary flight keys on the keyboard. So when the human player 2 rotates the joystick or presses the "go faster" button, player 2's ship rotates or moves within player 1's local bubble. Player 2's ship doesn't rotate the universe around itself, it just moves in space as you would expect.

This isn't too much of a leap - after all, NPC ships in the original game work in this way, so moving NPC ships by joystick rather than by algorithm isn't too hard to imagine. Indeed, you can configure player 2 to be an AI Pilot in two-player Elite, in which case the code controlling player 2's ship just switches back to the original tactics routines rather than reading the joystick and keyboard.

So we have a model that is familiar, in that we have a player 1-centric universe that contains the planet, the sun, player 2's ship and up to two missiles. Player 1's space view is easy enough to draw, as player 2 is just another ship in the local bubble, so we can draw the top space view as normal (just with the required cropping).

This defines the main challenge of the two-player Elite hack: how do we draw all of this into the bottom space view, so that everything is correct from the point of view of player 2? This is where the complexity arrives, so I've split the answer up into a number of sections:

  • We start by talking about how to draw player 1's view, as this gives us a chance to revisit how single-player Elite works. See the sections on the split space view and drawing player 1's space view for details.
  • In order to draw player 2's view, we first create duplicates of the sun, planet, ships and missiles in the local bubble. This is described in the section on drawing player 2's space view .
  • Once we've got our duplicates, we need to transform each of them from player 1's frame of reference (i.e. with player 1 at the origin and the axes aligned with player 1's ship) into player 2's frame of reference (i.e. with player 2 at the origin and the axes aligned with player 2's ship). This is the core part of two-player Elite, and is detailed in the sections on the geometry behind player 2's view and the arithmetic behind player 2's view .
  • A pretty vital aspect of dogfighting in space is the ability to target and shoot your opponent. As discussed above, this is pretty easy for player 1, but it's a bit more involved for player 2, so this is explained in the section on target calculations
  • Finally, all is not what it seems... of course. Accuracy and speed are constant challenges when working with floating point geometry on an 8-bit CPU, and I confess to using some smoke and mirrors to make things appear a bit more stable than they actually are. I talk about these in the section on cheating with the sun and planet .

There are also sections on some of the more straightforward aspects, such as the responsive control system , and to round it off there's a miscellaneous section for anything else worth talking about.

Let's start with a look at splitting the space view in two, which was the first task I tackled... but before we get stuck in, here's a quick note about the bit-based flags that I'm using in two-player Elite.

A note on bit-based flags
-------------------------

Two-player Elite contains a lot of new variables, and a lot of these are flags. For example, the split screen is controlled by this flag, which we look at in the next section:

  • splitScreen controls the split-screen effect:
    • Bit 7 set = draw the space view as a split screen
    • Bit 7 clear = full screen

You'll notice that this variable uses bit 7 to store its state. This approach isn't that popular in Elite - Bell and Braben's code tends to prefer flags that are either zero or non-zero, and which can be tested with an LDA and BEQ combination. But for my own coding I've been more influenced by Geoff Crammond, who over the course of Aviator, Revs and The Sentinel, settled on using bit 7 as the flag (and possibly bit 6 as well). The advantage of using bit 7 is that we can test the state of the flag without using any registers, as the BIT instruction sets the N and V flags to bits 7 and 6 of its operand. So instead of testing whether our flag variable is non-zero, like this:

  LDA flagVariable      \ Set A to the value of the flag variable
  BNE flagIsSet         \ Jump to flagIsSet if A is non-zero

or zero, like this:

  LDA flagVariable      \ Set A to the value of the flag variable
  BEQ flagIsNotSet      \ Jump to flagIsNotSet if A is zero

we can do the following to test bit 7 being set, without needing to use a register:

  BIT flagVariable      \ Set the N flag to bit 7 of the flag variable
  BMI flagIsSet         \ Jump to flagIsSet if the N flag is set

or we can do this to test bit 7 being clear:

  BIT flagVariable      \ Set the N flag to bit 7 of the flag variable
  BPL flagIsNotSet      \ Jump to flagIsNotSet if the N flag is clear

Similarly, we can do the following to test whether bit 6 is set:

  BIT flagVariable      \ Set the V flag to bit 6 of the flag variable
  BVS flagIsSet         \ Jump to flagIsSet if the V flag is set

or this to test whether bit 6 is clear:

  BIT flagVariable      \ Set the V flag to bit 6 of the flag variable
  BVC flagIsNotSet      \ Jump to flagIsNotSet if the V flag is clear

Not only that, but we can set the flag in bit 7 without needing to use a register, like this:

  SEC                   \ Set the C flag
  ROR flagVariable      \ Rotate the C flag into bit 7 of the flag variable

and we can clear it in a similar fashion like this:

  CLC                   \ Clear the C flag
  ROR flagVariable      \ Rotate the C flag into bit 7 of the flag variable

or, if we're only using bit 7 of the flag variable and know that the other bits are clear (and in particular bit 6), we can do this:

  ASL flagVariable      \ Shift bit 6 (clear) into bit 7 of the flag variable

And because we are running the main game code on the 6502 Second Processor with the extra instructions of the 65C02 CPU, we can clear both flags in just one instruction, like this:

  STZ flagVariable      \ Clear bits 6 and 7 of the flag variable

You can also use these flag variables to store previous flag values by shifting right (so bit 6 inherits the previous value of bit 7, for example), but that's getting really deep into Geoff Crammond territory. For two-player Elite, I only use bits 6 and 7 as independent flags, so that's the kind of flag logic you'll see throughout the code modifications.

Splitting the space view
------------------------

Compared to some of the other challenges in two-player Elite, splitting the space view into two parts is relatively straightforward. There are two new variables that control the screen-splitting process, and they work like this:

  • splitScreen controls the split-screen effect:
    • Bit 7 set = draw the space view as a split screen
    • Bit 7 clear = full screen
  • drawPlayerView determines which player's view to draw in the split screen:
    • Bit 7 set = draw player 1's view (top)
    • Bit 7 clear = draw player 2's view (bottom)

Given these two flag variables, we can update any drawing calculations to draw into the correct half of the screen. We only need to make changes to the drawing routines for when bit 7 of splitScreen is set, in which case we need to update the y-coordinate of the pixel that we are drawing to point to the correct space view, according to the value of drawPlayerView.

To make this a bit easier we can use the configuration variable Y from the original source, which is set to half the height of the space view (so for the BBC Micro, Y is set to 96 pixels, as the full space view is 192 pixels high); I will refer to this variable as #Y to avoid confusing it with the 6502's Y register. So each of the two space views in the following screenshot is #Y pixels tall, and the top of the dashboard is at y-coordinate #Y*2:

Player 2 looking at player 1 and the planet in two-player Elite

We can then calculate the following:

  • If we are drawing player 1's view in the top part of the space view, then subtract #Y/2 from the y-coordinate. This moves the whole scene upwards so the centre of the view (at the laser sights) is in the middle of the top half. Then we check whether the pixel fits into the top half of the screen (i.e. into the range 0 <= y < #Y/2) and if it does, we plot it.
  • If we are drawing player 2's view in the bottom part of the space view, then add #Y/2 to the y-coordinate. This moves the whole scene down so the centre of the view (at the laser sights) is in the middle of the bottom half. Then we check whether the pixel fits into the bottom half of the screen (i.e. into the range #Y/2 <= y < #Y) and if it does, we plot it.

This calculation occurs in a number of routine, all of which have been updated in two-player Elite to draw into either player 1's view or player 2's view, according to the value of drawPlayerView:

  • PIXEL2 for drawing stardust
  • LASLI for drawing the big, red laser lines at the bottom of the space view
  • DOEXP for drawing explosions
  • PLANET for drawing the planet
  • SUN for drawing the sun
  • SHPPT for drawing distant ships as dots
  • SIGHT for drawing the laser crosshairs
  • LL145 for line-clipping in circles and ships

The last routine is worth explaining a bit further, as the line-clipping routine at LL145 is applied to every line that's drawn as part of a ship wireframe or a circle, so it's used when drawing ships, planets, launch tunnels and so on. You can read all about how it works in the deep dive on line-clipping , but suffice to say it's fairly complicated and involves some relatively slow arithmetic.

For two-player Elite, we need to extend LL145 to cope with two scenarios:

  • We still need the original, full-screen line-clipping routine for the launch tunnel, or in case we want to display full-screen ships on the title screen or circles on the chart screens (the charts are disabled in two-player Elite and the title screen actually clips to player 1's space view, but at least they could be easily reinstated if required).
  • We need a new version that clips lines to either one of the two-player views, so we can draw ships and planets in just one half of the space view without them bleeding into the other.

I did briefly try reworking LL145 to cope with the split-screen player views, but it didn't go too well, so to avoid getting bogged down, I added a cheeky hack that worked so well I kept it. Here's how it works.

If the screen is normal and not split into two player views (i.e. when bit 7 of splitScreen is clear) then we run LL145 as normal. But if the screen is split then we use the following approach to move the line up the screen to be centred in player 1's space view, where we clip the line to the half-height view; and then, if we are drawing player 2's view, we move the clipped line down into the bottom half of the split screen. As the line's coordinates are 16-bit signed numbers that use the game's extended screen coordinates , we can move the line up the screen using normal SBC instructions, using the carry flag as the 6502 intended.

This is how the algorithm works:

  • We start by subtracting #Y/2 from the line's two 16-bit y-coordinates to move the line up the screen by half the height of player 1's space view, so the line is now in the correct position for player 1 (though it hasn't been clipped yet).
  • We now want to clip this newly positioned line to fit into player 1's space view, so that's the y-coordinate range 0 to #Y/2. The standard LL145 routine clips to the range 0 to #Y, so instead of just calling LL145 directly, we do the following:
    • Double the line's 16-bit y-coordinates with a simple left-shift, which stretches the line in the y-axis to double its height on-screen. The top of the screen is the zero y-coordinate, so this is a bit like drawing our line on a stretchy sheet of rubber that's the same size as player 1's space view, and then gripping the sheet at the top and bottom and pulling the bottom down until the sheet is double height, i.e. the height of the full, two-player space view.
    • We then run LL145 as normal, to clip the lines to 0 <= y < #Y and 0 <= x < 256. This clips our double-height line to the bounds of the full space view, so that's twice the height of the player 1 space view. If you like, this is clipping our line to the edges of the stretched sheet of rubber.
    • Finally we halve the line's 16-bit y-coordinates with a simple right-shift, which is like us letting go of the bottom part of the rubber sheet, so it springs back to being the same shape as player 1's space view, but with the line clipped to the top half of the full, two-player space view.
  • If we are drawing player 2's view (i.e. bit 7 of drawPlayerView is set), we finish off by adding #Y to the y-coordinates of the clipped line to move the whole clipped line down into the bottom half of the space view.

The overhead of this extra code is relatively minor, as it only requires addition, subtraction and shifting, and it leaves us with a line-clipping routine that works in both the original screen and the split screen without needing to change the original LL145 routine at all.

There are a few other areas where we need to cater for the split screen. In the original game, whenever we change the space view (front, rear, left, right) or switch to an information screen like the charts or status mode screen, then the TTX66 routine clears the whole top part of the screen, draws the yellow border and then displays the relevant information. This can't happen in two-player Elite, as otherwise one player changing views would affect the other player's view, so we need to extend TTX66 to cater for this; the easiest way is to add a couple of additional text control codes to the TT26 text-printing routine in the I/O processor, so control code 14 clears player 1's view and control code 15 clears player 2's view. This means we can clear each screen by simply printing the relevant control code, which gets interpreted by the I/O processor as a screen-clearing command.

Finally, we also need to update the in-flight messaging system to cater for messages in both player views. As there are a few variables used to store the current message details (so it can be easily erased), it's easier just to duplicate the MESS routine into Player2MESS, so MESS prints in-flight messages in player 1's view, and Player2MESS does the same for player 2. I ended up duplicating quite a few aspects of the game for player 2 in this way; see the miscellaneous section for more details.

Now that we have drawing routines that can cater for the two split-screen player views, let's talk about how we can draw the contents of each player's space view.

Drawing player 1's space view
-----------------------------

As discussed in the overview , the heart of two-player Elite is the exact same player-centric local bubble model as in the original single-player game, with player 1 at the centre of the universe. Drawing the top space view for player 1 is therefore fairly easy, at least in concept; we just draw the game screen as usual, showing everything from the perspective of player 1, and all we need to do is clip what we draw so it fits into the half-height space view at the top of the screen.

This makes it sound a lot easier than it is in practice, but the concept shouldn't be too difficult to grasp. Drawing player 2's space view, on the other hand, is considerably more challenging, and is covered in the next section , but for this section let's stick to player 1's view - the one showing a Thargoid and the sun in this screenshot:

Viper vs Thargoid in two-player Elite

Before describing how two-player Elite works, let's recap how single-player Elite stores its environment, and in particular the ships and other objects in the local bubble of universe that we want to draw in the space view. This is all described in detail in the deep dives on the local bubble of universe and ship data blocks , but here's a brief summary.

The game has a fixed number of ship slots, with 12 in the BBC Micro version and 20 in the 6502 Second Processor version (two-player Elite is based on the latter). Each object in the local bubble occupies one slot, with the planet in slot #0, either the sun or the space station in slot #1, and then all the various ships and missiles and asteroids in slots #2 and up.

Each slot is managed via the FRIN table, which contains one byte per slot; a zero entry indicates an empty slot, while a non-zero entry indicates either a ship, planet, sun or station (in which case FRIN contains the ship type). Each occupied slot also has an associated ship data block, which lives in the K% workspace, and one of those bits of data is the address of the ship's line heap, which is used to store the coordinates of the ship's on-screen wireframe lines, so the lines can quickly be redrawn using EOR logic to remove the ship from the screen.

All space coordinates in single-player Elite are relative to the player, who lives at the origin with coordinates (0, 0, 0). The z-axis goes into the screen, so that's pointing straight out of the nose of the player's ship, while the x-axis goes from left to right and the y-axis points up. (Note that the BBC Micro's screen y-coordinates go the other way and increase as you move down the screen, but we're talking about 3D space coordinates here, and they increase as you move up in space.)

Finally, note that in this context, "ship" is used to refer to anything with a slot, so that includes the sun, the planet, the station or non-ship objects like asteroids or cargo canisters. It's a lot easier to say "ship" than "ship, planet, sun, station etc." every time.

We keep this model for two-player Elite, but in a reduced manner. Because two-player Elite is a deep space dogfighting game, we don't come across any space stations, so slot #1 is always allocated to the sun. And we also strictly limit the number of objects to avoid slow-downs, with a maximum of one in-flight missile per player giving a limit of two in-flight missiles at any one time.

The ship slots in two-player Elite therefore look like this, with player 1 at the centre of the universe:

  • Slot #0 = Planet
  • Slot #1 = Sun
  • Slot #2 = Player 2's ship
  • Slot #3 = Missile 1
  • Slot #4 = Missile 2

That's it - that's the local bubble of universe for two-player Elite. We may have anything from 0 to 2 missiles spawned, but we always have the planet, the sun and player 2's ship.

This bubble works nicely for drawing player 1's space view, as all the space coordinates are relative to player 1 at the origin, just as in the original single-player game. But how do we take this bubble structure and use it to draw player 2's space view?

That's a simple question with a complicated answer, so first let's look at how player 1's view is drawn and see if that helps. The details can be found in the deep dive on program flow of the main game loop , but to save you wading through all that, let's concentrate on the ship-processing code at the heart of the game loop.

Every iteration of the main loop , the game works through each of the ship slots, one slot at a time, and it applies movement and rotation to the ship we are processing (the "current ship"). This movement is affected not only by how the player is moving in space, but also by the current ship's own rotation, speed and acceleration. Tactics are also applied at this point, so pirates will attack and traders will mind their own business, for example. Once the current ship has been updated, then the new data is stored in the ship's data block, and the ship is redrawn on-screen. This latter step is done in two parts, first by redrawing the existing on-screen lines using EOR logic and the coordinates in the ship line heap, and then by drawing the new lines on-screen (again using EOR logic to merge with the existing screen contents) and storing the new coordinates in the ship line heap.

This ship-drawing loop manages the ships, the sun and the planet in the space view in single-player Elite, with the actual drawing being done by the LL9 routine. This is called in part 12 of the main flight loop , and it caters for the planet, the sun and the ships, so LL9 ends up being called once for each populated ship slot. Once we've finished going through the ship slots, the game calls the STARS routine to update the stardust, and that's how the space view is drawn in single-player Elite.

For two-player Elite, then, we can use the same loop for drawing player 1's space view, with LL9 and STARS taking care of the ships and the stardust. We just need a similar system for drawing player 2's view, ideally without adding too much overhead.

Let's take a look at that next.

Drawing player 2's space view
-----------------------------

The core approach in two-player Elite is to treat ship slots #0 to #4 as the single source of truth for the local bubble, and to draw that same bubble from the perspective of player 2 in player 2's space view. To keep the flight loop as unchanged as possible, we add a new routine, DrawPlayer2View, which we call for each ship slot, just after LL9 has drawn that ship in player 1's space view.

DrawPlayer2View, as its name suggests, draws the current ship, but it does it in player 2's view and from the point of view of player 2. DrawPlayer2View is the core of two-player Elite, and you can see it in the raw source by searching for ".DrawPlayer2View".

To simplify things a bit, you can think of DrawPlayer2View as a large, six-part wrapper around yet another call to LL9 to draw the current ship, but before drawing the ship, we convert the current ship's data block from the default perspective (i.e. the view from player 1's ship) into a different frame of reference (i.e. the view from player 2's ship). The call to LL9 then draws the current ship into player 2's space view without us needing to make any changes to LL9 itself.

DrawPlayer2View is split into six parts:

  • Part 1 processes byte #31 of the ship data block, as this contains data that isn't necessarily the same for each ship in the two different player views. For example, a ship might be visible in one view but not visible in another, and as that information is stored in bit 3 of byte #31, we need to manage this data byte differently for each ship in each view.
  • Part 2 applies special rules to the planet and sun when they are on-screen, as described in the section on cheating with the sun and planet .
  • Part 3 is the most important part of two-player Elite, as it calculates the current ship's coordinates and orientation in player 2's frame of reference, so it can be drawn in player 2's space view. We'll talk about this in the remainder of this section, and we'll explore the maths in the sections on the geometry behind player 2's view and the arithmetic behind player 2's view .
  • Part 4 is nice and short, but it's important, as it draws the current ship in player 2's space view. It starts by setting bit 7 of drawPlayerView to ensure the ship is drawn in player 2's view. It then calls PLUT to switch to the correct directional view - front, rear, left or right - just as we do in single-player Elite (see the deep dive on flipping axes between space views for details). And finally it calls LL9 to draw the current ship in player 2's view.
  • Part 5 deals with lasers and targeting, as described in the section on target calculations .
  • Part 6 returns to the ship data to the state it was in when we called DrawPlayer2View, so the main loop can continue on as if nothing has happened.

This approach makes sense until we need to draw the ship in slot #2. Slot #2 contains player 2's ship, but player 2 can't see their own ship, so there's nothing to draw. So when we are processing the current ship in slot #2, DrawPlayer2View instead draws player 1's ship from the perspective of player 2, as player 1's ship doesn't actually have a ship slot (because in the local bubble, player 1 is always at the origin and is always aligned with the axes, so we don't need to store its coordinates, orientation and so on). As a bonus, the maths we need to do when working out where player 1's ship appears in player 2's space view is a simplified version of the maths we need to do for the other slots; see the section on the geometry behind player 2's view for more on this.

For the rest of this section, let's examine part 3 of DrawPlayer2View in more detail, as this is where the magic lives. By this point we are processing the current ship and have drawn it in player 1's view. As a reminder, the slots are set up as follows:

  • Slot #0 = Planet
  • Slot #1 = Sun
  • Slot #2 = Player 2's ship
  • Slot #3 = Missile 1
  • Slot #4 = Missile 2

So given the ship data for the current ship, we now we need to draw the ship from the perspective of player 2, and in player 2's space view.

Taking on a Thargoid in two-player Elite

If you look at the ship data for a typical ship, it's mostly coordinates and orientation vectors; see the deep dive on ship data blocks for details. The coordinates are the (x, y, z) space coordinates of the ship relative to player 1, while the orientation vectors define the direction in which the ship is pointing, stored as three vectors - nosev, roofv and sidev - that point out of the nose, roof and right side of the ship respectively. These vectors are said to be orthonormal, which just means that the vectors are orthogonal (i.e. they are perpendicular to each other), and normal (i.e. each of the vectors has length 1). See the deep dives on orientation vectors and tidying orthonormal vectors for more information on these vectors.

So out of 37 bytes in each ship data block, the first 27 bytes define the ship's position and orientation in space, all of them from the perspective of player 1. As player 1 and player 2 can't be at the same point in space, we know that these 27 bytes will be different for this ship when viewed from the perspective of player 2.

We'll look at exactly how they differ in the next section, but in terms of DrawPlayer2View, our first step is to make a copy of the ship data for the ship we are trying to draw, because we're going to have to change most of it when drawing that ship in player 2's view. To make things simple, we can duplicate the current ship's data from slot #n into slot #n+10, like this:

  • Slot #10 = Planet from player 2's perspective
  • Slot #11 = Sun from player 2's perspective
  • Slot #12 = Player 1's ship from player 2's perspective
  • Slot #13 = Missile 1 from player 2's perspective
  • Slot #14 = Missile 2 from player 2's perspective

So, for example, when we are processing slot #1 in the main game loop, which contains the sun, DrawPlayer2View copies the sun's ship data into slot #11; similarly, player 2's ship gets copied into slot #12 for processing in DrawPlayer2View, and so on. This duplication process means we can apply our transformation maths to the copy of the current ship's data to convert it into the coordinates and orientation for player 2's view, and we can simply pass this higher slot number to LL9 to draw the ship, and it will all just work. Skip to the section on the geometry behind player 2's view to read about this transformation process, as it deserves a section all of its own.

The ship data in the higher slot number does get used once more after the ship has been drawn, but it isn't until the next time the main loop processes this slot, when we need to update the ship in player 2's view. Before the higher slot ship data is overwritten, part 1 of DrawPlayer2View uses it to remove the ship from player 2's scanner (i.e. the yellow ship stick), as redrawing the ship stick in its current position with EOR logic will remove it. Then we can copy the lower slot number data into the higher slot number again, overwriting what's there, and the whole process starts again.

There are some important caveats in this copying process. As mentioned above, byte #31 of the ship's data block contains a number of flags that don't make sense when blindly applied to player 2's perspective, so instead we store byte #31 separately for slots #2 to #4 (these are stored in the three bytes at player1INWK31). Part 1 of DrawPlayer2View therefore starts by looking at byte #31 for the current ship; by this point the current ship's data is in the zero page INWK workspace, so DrawPlayer2View checks the flags in INWK+31 and copies any relevant ones into the corresponding byte in player1INWK31.

For example, if a missile has just exploded then bit 7 of INWK+31 will be set, so we will want to copy that over into player1INWK31 so the missile explodes in player 2's view as well as in player 1's view; but if a ship is visible in player 1's space view then that has no bearing on whether it will also be visible in player 2's space view, so we don't want to copy over bit 3 of INWK+31 (which records this fact). Instead we use bit 3 from player1INWK31 to keep track of whether a ship is on-screen in player 2's view.

The other important difference in ship data between the lower-numbered and higher-numbered slots is the address of the ship line heap. The ship line heap is very simple - it contains sets of four coordinates, each of which describes a line in that ship's on-screen depiction. To draw the ship we simply work through the heap, drawing each line, and to remove the ship from the screen, we repeat the process using EOR logic. You can read all about this in the deep dive on drawing ships .

Obviously, the same ship will look completely different in player 1's view compared to player 2's view, so we need to maintain separate ship line heaps for the lower-numbered slots and the higher-numbered slots. To this end, when we duplicate the ship data for a lower-numbered slot into a higher-numbered slot, then as we do the duplication, we subtract &2000 from the ship line heap address in bytes #33 and #34 of the ship data block. The 6502 Second Processor version of Elite has quite a generous memory allocation to the ship heap, as you can see in the 6502 Second Processor Elite memory map ; the heap stretches downwards from &D000 to &84E4, so that's &4BCC bytes. We're only using the top part of the ship heap for player 1's ship and two missiles (as the planet and sun have their own line heaps), so the maximum heap size required is 157 bytes for the player ship (based on the Cobra Mk III, which has the largest requirement), plus 85 bytes for each missile, giving a total of 327 bytes, or &147. Spacing out the two views' ship heaps by &2000 bytes is therefore complete overkill, but it's better to be safe than sorry.

The planet has its own ball line heaps at LSX2 and LSY2 that are populated by the BLINE routine (see the deep dive on the ball line heap for details). In order to support two different space views with two different-looking planets, we therefore need to allocate memory to a second pair of line heaps for the planet in player 2's view, which we can call LSX2a and LSY2a. We can then reuse a method that I first used in the anaglyph routines in Elite 3D to support different right-eye and left-eye views. To get BLINE to work with the correct ball line heap, we can recode the routine to look up all heap-related addresses from vectors, which get set by the SetPlayerBallLine routine, depending on the current value of drawPlayerView. Specifically, the LSX2S(1 0) vector points to either LSX2 or LSX2a, the LSY2S(1 0) vector points to either LSY2 or LSY2a, and the LSPS(1 0) vector points to either LSP or LSPa, so we can use the same BLINE routine to draw the ball line for each of the player views individually, while storing the results in the correct ball line heap.

The sun also has its own line heap, but this time we don't need to do any duplication, as the sun stores its lines as one byte for each of the 192 raster lines in the space view. We can therefore simply use the first half of the existing heap for the top space view and the second half for the bottom space view, and the only bit we need to duplicate is the centre of the sun's x-coordinate in SUNX, as that can obviously be different for the sun in each of the two views. Again, we use a vector approach, so the LSOS(1 0) vector points to either LSO or LSOa, and the SUNXS(1 0) vector points to SUNX or SUNXa. This gets set in SetPlayerSunHeap, again according to the current value of drawPlayerView.

The final piece of the duplication puzzle is the stardust, which is drawn at the end of the main flight loop, after all of the ship slots have been iterated through and drawn. The STARS routine is responsible for drawing stardust, as described in the deep dives stardust in the front view and stardust in the side views . Stardust coordinates are stored in six different heaps, with one byte in each heap for each particle of stardust, storing the 16-bit x-coordinate in (SXL SX), the 16-bit y-coordinate in (SYL SY) and the 16-bit z-coordinate in (SZL SZ). Because the two space views in two-player Elite are half the size of the space view in single-player Elite, we can split the existing stardust particles between the two views, with player 1's stardust coordinates in the first half of each heap, and player 2's stardust in the second half.

The only fiddly bit is that stardust moves according to the player's movement, and in particular the alpha (roll), beta (pitch) and delta (speed) values, and it would be a bit of a pain to recode all the star-moving routines to cater for the different values for player 1 and player 2. So instead we use three new routines to apply another slightly hacky workaround:

  • SaveShipMovement saves player 1's movement variables into a cache.
  • GetPlayer2Movement copies player 2's movement data into the various ALPHA, BETA and DELTA variables that are used in the stardust calculations.
  • LoadShipMovement restores player 1's movement variables from the cache.

We can then insert a shim into the start of the STARS routine to do the following:

  • Call SaveShipMovement to store player 1's movement data.
  • Call GetPlayer2Movement to fetch player 2's movement data.
  • Move and draw player 2's stardust in player 2's view, using the second half of each stardust heap.
  • Call LoadShipMovement to revert to player 1's movement variables.
  • Move and draw player 1's stardust in player 1's view, using the first half of each stardust heap.

And that's how we draw player 2's view... except we haven't talked about the maths behind all of this, and that's the most important part of all, so let's do that now.

The geometry behind player 2's view
-----------------------------------

As explained above, the local bubble in two-player Elite is essentially a single-player bubble, just like the original game, with player 1 at the centre of the universe. Player 2 is just another ship in the bubble, in slot #2, and when we draw player 1's space view, we effectively use the same code as in the original game, we just crop it to the top half of the screen.

The challenge is to draw the same ships, but in player 2's space view and from player 2's perspective. The previous section explains how we duplicate the current ship into a higher-numbered slot, where we transform the ship's coordinates and orientation into player 2's perspective, and then we draw the results in the bottom space view.

In this section we look at that transformation process, which is the most important part of the entire hack. In order to follow along, you'll probably want to read the deep dive on orientation vectors , as we're going to be working with them a lot. Also, the core mathematical concepts are similar to those discussed in the deep dives on back-face culling and calculating vertex coordinates , particularly the bit about "scalar projection" in the first article and "transposing the rotation matrix" in the second, so you might find those useful too. I'll try to explain things as I go along, but sometimes it helps to have more than one explanation of a concept to hand.

Now that I've failed to put you off, let's try a thought experiment. Imagine you are playing two-player Elite in virtual reality, and you are currently sitting in player 1's ship. Out there in the distance you can just about see player 2's ship, and also in the same local bubble of universe are the planet, the sun and a missile or two. And imagine you can move your point of view to anywhere in this universe by pinching, grabbing and rotating, or whatever it is that the cool VR kids do these days.

The question is this: starting out with us sitting in player 1's cockpit, what do we need to do in order to see the view from player 2's cockpit? In other words, rather than moving ourselves, how do we grab and rotate the virtual universe around us in order to get to player 2's view? If we can answer this, then that's what we need to build into two-player Elite to let us calculate what the bubble looks like from player 2's point of view.

Intuitively, this is what I would do to answer this question. I'd drag the universe whole towards me, pulling player 2 closer and closer until my view was inside their cockpit, and then I'd rotate the whole lot around me until I was looking out of the ship's front view. This dragging and rotating process doesn't only move player 2's ship towards us and into the right position, but it also moves and rotates everything else in the bubble, including our original ship, i.e. player 1's ship.

In other words, we have just worked out a geometric transformation that we can apply to each ship in the bubble that will move that ship into the correct position and orientation for the view from player 2's ship. The first part (the dragging) is known as a "translation", and the second part is a rotation, so we now have a two-part translate-and-rotate transformation that takes ships from the coordinates and orientation they have when we are looking out of player 1's ship, and moves them to the coordinates and orientation they have when we are looking out of player 2's ship.

The next step is to convert this translate-and-rotate transformation into a mathematical process. We can then apply that process to the current ship in the main flight loop, and can draw the result in player 2's view. As a reminder, the transformation process is this:

  • Apply a translation that moves player 2's ship to our position (so this is us dragging to the position of player 2's ship to our original position in player 1's ship).
  • Apply a rotation that takes our current view direction (which was down the nose of player 1's ship) and spins the view around us until we are looking down the nose of player 2's ship.

We need to apply this two-part transformation to both bits of data that define the position and orientation of the current ship, so we need to apply it to the current ship's coordinates in space, to move the ship to the correct position relative to player 2's view, and we need to apply it to the ship's orientation vectors, to rotate the ship to the correct orientation relative to player 2's view. In the latter case, applying a translation to an orientation vector doesn't affect the orientation, so we only need to do the second step when transforming the current ship's orientation.

Now that we know what we need to do, let's look at how we can implement this transformation mathematically. We'll look at implementing the problem in two different ways: first, by considering Elite's orientation vectors, and second by looking at rotation matrices. These two approaches are mathematically the same, they just use different terminology to explain the same algorithm, so hopefully at least one of them will help clarify this relatively complicated process.

In terms of orientation vectors
-------------------------------

The first operation is reasonably simple. We start out with player 1 at the origin (0, 0, 0), which is at the centre of the universe, and with player 2's ship at the coordinates defined in the ship data block for slot #2 - let's call those coordinates (x2, y2, z2). We therefore need to apply a translation that moves player 2's ship from (x2, y2, z2) to player 1's ship at (0, 0, 0). This is easy enough; we need to apply a translation of (-x2, -y2, -x2).

Another way of thinking of this translation is that when we drag the universe towards us in the first part of our virtual reality thought experiment, we pull everything along the vector that joins player 1 and player 2, and we pull it all in the direction from player 2 to player 1. The vector from player 1 to player 2 is [ x2 y2 z2 ], so this means the vector from player 2 to player 1 is the reverse of that, which is [ -x2 -y2 -x2 ].

So this is our translation step, which we apply to the current ship. If the current ship's coordinates are at (x, y, z), then this is the translation:

  [ x ]    [ x ]   [ x2 ]
  [ y ] -> [ y ] - [ y2 ]
  [ z ]    [ z ]   [ z2 ]

The second operation in our transformation is the rotation, which is a bit more complicated. We need to apply a rotation that starts with us looking along player 1's viewing direction and spins things around until we are looking along player 2's viewing direction.

This is where the orientation vectors come in. Player 2's orientation vectors describe the direction in which player 2 is pointing relative to player 1, with nosev pointing out of player 2's nose, roofv pointing out of player 2's roof, and sidev pointing out of player 2's right side. These orientation vectors are orthonormal, so they are all unit vectors of length one, and this means we can use the same "scalar projection" approach as we do for back-face culling (see the deep dive on back-face culling for details).

As a reminder, scalar projection is the following property: given a vector and a unit vector, we can calculate the projection of the vector onto the unit vector by simply calculating the dot product of the two vectors. If we do this with a vector and three unit vectors, then the dot product gives us that vector, but expressed in terms of the three unit vectors - in other words, this is how we convert coordinates from one set of axes to another. This is the same as converting a vector from one perspective to another, or one frame of reference to another, which is what we need to do when drawing player 2's view. It's also worth remembering that coordinates and vectors are effectively the same thing; a coordinate is simply a vector with one end at the origin.

In this case, then, we want to take the following four vectors, which between them define the position and orientation of the current ship, just after we have applied the first step of our transformation:

  • The updated coordinate of the current ship from above, as a vector
  • The side orientation vector of the current ship
  • The roof orientation vector of the current ship
  • The nose orientation vector of the current ship

We want to apply the second step of our two-step transformation to each of these vectors by using scalar projection to project them onto player 2's orientation vectors, which moves them into player 2's frame of reference. So if [ x y z ] represents one of the vectors above, and player 2's orientation vectors are given by side2v, roof2v and nose2v, then we can apply the second step of our transformation by applying the dot product as follows:

  x -> [ side2v_x side2v_y side2v_z ] . [ x y z ]

  y -> [ roof2v_x roof2v_y roof2v_z ] . [ x y z ]

  z -> [ nose2v_x nose2v_y nose2v_z ] . [ x y z ]

We apply the dot products in this order because when we are sitting in a ship, the x-axis points out of the right side of the ship, the y-axis points up and out of the roof of the ship, and the z-axis points forwards and out of the nose of the ship. So projecting the [ x y z ] vector onto each of player 2's orientation vectors will project the vector onto the axes that we use when we are sitting inside player 2's ship. And that is what changes the perspective of each vector to that of player 2's pilot, which is what we want in order to draw player 2's view.

If we combine both steps of the transformation - i.e. the translation and the rotation - then we get the following result when we apply it to the current ship's coordinate in (x, y, z):

  x -> [ side2v_x side2v_y side2v_z ] . ( [ x y z ] - [ x2 y2 z2 ] )

  y -> [ roof2v_x roof2v_y roof2v_z ] . ( [ x y z ] - [ x2 y2 z2 ] )

  z -> [ nose2v_x nose2v_y nose2v_z ] . ( [ x y z ] - [ x2 y2 z2 ] )

And we get the following result when we apply the transformation to the orientation vectors for the current ship, because the translation step can be dropped (as it doesn't affect orientation):

  sidev_x -> [ side2v_x side2v_y side2v_z ] . [ sidev_x sidev_y sidev_z ]
  sidev_y -> [ roof2v_x roof2v_y roof2v_z ] . [ sidev_x sidev_y sidev_z ]
  sidev_z -> [ nose2v_x nose2v_y nose2v_z ] . [ sidev_x sidev_y sidev_z ]

  roofv_x -> [ side2v_x side2v_y side2v_z ] . [ roofv_x roofv_y roofv_z ]
  roofv_y -> [ roof2v_x roof2v_y roof2v_z ] . [ roofv_x roofv_y roofv_z ]
  roofv_z -> [ nose2v_x nose2v_y nose2v_z ] . [ roofv_x roofv_y roofv_z ]

  nosev_x -> [ side2v_x side2v_y side2v_z ] . [ nosev_x nosev_y nosev_z ]
  nosev_y -> [ roof2v_x roof2v_y roof2v_z ] . [ nosev_x nosev_y nosev_z ]
  nosev_z -> [ nose2v_x nose2v_y nose2v_z ] . [ nosev_x nosev_y nosev_z ]

These are the calculations that are implemented in part 3 of DrawPlayer2View, with the latter calculation being done in the OrientateMissile routine. They enable us to take an arbitrary ship's position and orientation within player 1's space view, and they give us the position and orientation of that ship within player 2's view. This, therefore, is the heart of two-player Elite.

There is one more part to the story, because we can simplify this calculation considerably when transforming player 2's ship. As mentioned above, slot #2 contains player 2's ship, but if we took player 2's ship and transformed it into player 2's view, then it would simply move to the origin and we wouldn't need to draw it. This is intuitive, but it also falls out of the maths fairly easily: if we applied the translation step to player 2's ship at (x2, y2, z2), then the result would be (0, 0, 0).

So instead of transforming player 2's ship into player 2's view, we instead we repurpose this ship slot (which we duplicate into slot #12) for drawing player 1's ship in player 2's view.

We can work out where player 1's ship ends up within player 2's view using the same process: by applying the above transformation to player 1's ship. Of course, player 1's ship doesn't have a slot, because in the game's bubble of universe, player 1's ship is always at the origin (i.e. the centre of the universe), and it always has the three axes as its orientation vectors (the z-axis is always pointing out of the nose of player 1's ship, for example). So when we work out player 1's position and orientation in player 2's view by applying the above transformation to player 1's coordinates and orientation vectors, we end up applying the transformation to the coordinates of player 1 at (0, 0, 0), and to the three axis unit vectors (as they match player 1's orientation).

We can therefore simplify the calculation quite a bit for this specific case. For the first calculation, we get the following simplification because the current ship's coordinate is (0, 0, 0):

  x -> [ side2v_x side2v_y side2v_z ] . ( [ 0 0 0 ] - [ x2 y2 z2 ] )

  y -> [ roof2v_x roof2v_y roof2v_z ] . ( [ 0 0 0 ] - [ x2 y2 z2 ] )

  z -> [ nose2v_x nose2v_y nose2v_z ] . ( [ 0 0 0 ] - [ x2 y2 z2 ] )

which gives us:

  x -> [ side2v_x side2v_y side2v_z ] . [ -x2 -y2 -z2 ]

  y -> [ roof2v_x roof2v_y roof2v_z ] . [ -x2 -y2 -z2 ]

  z -> [ nose2v_x nose2v_y nose2v_z ] . [ -x2 -y2 -z2 ]

And for the second calculation we get the following simplification, because the current ship's orientation vectors in sidev, roofv and nosev are the unit vectors:

  sidev_x -> [ side2v_x side2v_y side2v_z ] . [ 1 0 0 ]
  sidev_y -> [ roof2v_x roof2v_y roof2v_z ] . [ 1 0 0 ]
  sidev_z -> [ nose2v_x nose2v_y nose2v_z ] . [ 1 0 0 ]

  roofv_x -> [ side2v_x side2v_y side2v_z ] . [ 0 1 0 ]
  roofv_y -> [ roof2v_x roof2v_y roof2v_z ] . [ 0 1 0 ]
  roofv_z -> [ nose2v_x nose2v_y nose2v_z ] . [ 0 1 0 ]

  nosev_x -> [ side2v_x side2v_y side2v_z ] . [ 0 0 1 ]
  nosev_y -> [ roof2v_x roof2v_y roof2v_z ] . [ 0 0 1 ]
  nosev_z -> [ nose2v_x nose2v_y nose2v_z ] . [ 0 0 1 ]

which gives us:

  sidev_x -> side2v_x
  sidev_y -> roof2v_x
  sidev_z -> nose2v_x

  roofv_x -> side2v_y
  roofv_y -> roof2v_y
  roofv_z -> nose2v_y

  nosev_x -> side2v_z
  nosev_y -> roof2v_z
  nosev_z -> nose2v_z

So when we are processing slot #2, we can apply the exact same transformation process to player 1's ship by using these simplified calculations, which saves us a fair bit of time when calculating the position and orientation of player 1's ship within player 2's view.

That's how we can work things out using orientation vectors, but we can look at the same calculation in a slightly different way, using rotation matrices. So let's do that now.

In terms of rotation matrices
-----------------------------

Instead of all this talk of orientation vectors, we can analyse the rotation aspect of our two-part transformation by using rotation matrices, which is probably a more common way of thinking about rotation and orientation. Elite's code tends to make more sense if you work with the individual orientation vectors, but if you combine all three vectors into a 3x3 matrix, they form a special kind of matrix called a "rotation matrix", which can be applied to vectors to rotate them in space; see the Wikipedia entry on rotation matrices for more details.

Using the orientation vector names from the previous section, we can say that the current ship's rotation matrix looks like this:

  [ sidev_x sidev_y sidev_z ]
  [ roofv_x roofv_y roofv_z ]
  [ nosev_x nosev_y nosev_z ]

and player 2's rotation matrix looks like this:

  [ side2v_x side2v_y side2v_z ]
  [ roof2v_x roof2v_y roof2v_z ]
  [ nose2v_x nose2v_y nose2v_z ]

In terms of rotation matrices, the rotation aspect of our transformation can be expressed as a multiplication by the transpose of player 2's rotation matrix. The transpose "reflects" the shape of the matrix in a "mirror line" along the diagonal from top-left to bottom-right, so it looks like this:

  [ side2v_x roof2v_x nose2v_x ]
  [ side2v_y roof2v_y nose2v_y ]
  [ side2v_z roof2v_z nose2v_z ]

Given these two matrices, the rotation aspect of our transformation looks like this when expressed in terms of rotation matrix multiplication:

  [ sidev_x sidev_y sidev_z ]   [ side2v_x roof2v_x nose2v_x ]
  [ roofv_x roofv_y roofv_z ] . [ side2v_y roof2v_y nose2v_y ]
  [ nosev_x nosev_y nosev_z ]   [ side2v_z roof2v_z nose2v_z ]

The result of this multiplication is the new rotation matrix for the current ship, in player 2's frame of reference. In other words, the multiplication above is a rotation matrix representation of the transformation that we applied to the orientation vectors in the previous section, i.e. this one:

  sidev_x -> [ side2v_x side2v_y side2v_z ] . [ sidev_x sidev_y sidev_z ]
  sidev_y -> [ roof2v_x roof2v_y roof2v_z ] . [ sidev_x sidev_y sidev_z ]
  sidev_z -> [ nose2v_x nose2v_y nose2v_z ] . [ sidev_x sidev_y sidev_z ]

  roofv_x -> [ side2v_x side2v_y side2v_z ] . [ roofv_x roofv_y roofv_z ]
  roofv_y -> [ roof2v_x roof2v_y roof2v_z ] . [ roofv_x roofv_y roofv_z ]
  roofv_z -> [ nose2v_x nose2v_y nose2v_z ] . [ roofv_x roofv_y roofv_z ]

  nosev_x -> [ side2v_x side2v_y side2v_z ] . [ nosev_x nosev_y nosev_z ]
  nosev_y -> [ roof2v_x roof2v_y roof2v_z ] . [ nosev_x nosev_y nosev_z ]
  nosev_z -> [ nose2v_x nose2v_y nose2v_z ] . [ nosev_x nosev_y nosev_z ]

It's worth taking a deeper look at what this multiplication of rotation matrices represents. When you multiply two rotation matrices, each of which represents a rotation, then the result is a rotation matrix that represents the combined rotation of those two matrices. So our calculation, which looks like this:

  [ sidev_x sidev_y sidev_z ]   [ side2v_x roof2v_x nose2v_x ]
  [ roofv_x roofv_y roofv_z ] . [ side2v_y roof2v_y nose2v_y ]
  [ nosev_x nosev_y nosev_z ]   [ side2v_z roof2v_z nose2v_z ]

represents the combination of the current ship's rotation matrix (on the left) and the transpose of player 2's rotation matrix (on the right).

The current ship's rotation matrix represents the orientation of the current ship. You can think of it as a rotation, like this. If we're sitting at the origin as player 1, staring down the z-axis in the standard Elite setup, and instead we want to look in the same direction as the current ship that's out there somewhere in the bubble, then we can turn our head until it is pointing in the same direction as that ship (ignoring any physical constraints on our neck muscles). This is the rotation that's encapsulated in the current ship's rotation matrix - it's the head rotation that we would have to do in order to look in the same direction as the current ship.

The transpose of player 2's rotation matrix is slightly harder to visualise. Player 2's rotation matrix is orthonormal (i.e. normal and orthogonal) and a property of orthogonal matrices is that the transpose of the matrix is the inverse (i.e. the reverse) of the rotation. As we just discussed, a ship's rotation matrix represents how we would have to turn our head in order to align our viewpoint with that of the other ship, so if we apply this concept to player 2's ship, we see that player 2's rotation matrix represents our head rotation when moving from player 1's point of view (along the z-axis) to align with player 2's point of view.

The transpose of player 2's rotation matrix represents this rotation in the opposite direction. So applying the transpose rotation is the same as rotating the universe around us in the opposite direction, so instead of us turning our head to align with player 2's view, we rotate the entire universe in the opposite direction until we are aligned with player 2's point of view. And mathematically, applying the transpose rotation is done by multiplying by the transpose of player 2's rotation matrix.

This fits with our virtual reality thought experiment in the previous section. When we have pulled the universe towards us and we are in player 2's ship, we then rotate the universe around us to look through player 2's view. Mathematically, this is the same as multiplying each ship's orientation in the bubble by the transpose of player 2's rotation matrix. So this is exactly what our rotation matrix multiplication is doing; it's the same maths as the orientation vector calculation, it's just expressed differently.

The easiest place to see this in operation is in the simplified calculation for player 1's ship, where the current ship's rotation matrix (i.e. the first matrix in the calculation above) is the identity matrix, as player 1 is aligned with the axes. So in this simplified case, we rotate the ship by applying this rotation matrix:

  [ 1 0 0 ]   [ side2v_x roof2v_x nose2v_x ]   [ side2v_x roof2v_x nose2v_x ]
  [ 0 1 0 ] . [ side2v_y roof2v_y nose2v_y ] = [ side2v_y roof2v_y nose2v_y ]
  [ 0 0 1 ]   [ side2v_z roof2v_z nose2v_z ]   [ side2v_z roof2v_z nose2v_z ]

In other words, in this simplified case, we just set player 1's orientation to the transpose of player 2's rotation matrix. In terms of the calculation, this gives us exactly the same result as in the previous section, when we were rotating the orientation vectors:

  sidev_x -> side2v_x
  sidev_y -> roof2v_x
  sidev_z -> nose2v_x

  roofv_x -> side2v_y
  roofv_y -> roof2v_y
  roofv_z -> nose2v_y

  nosev_x -> side2v_z
  nosev_y -> roof2v_z
  nosev_z -> nose2v_z

This makes intuitive sense, as player 1's orientation within player 2's view will have the inverse orientation to player 2's orientation within player 1's view. And that inverse relationship is represented by transposing the rotation matrix.

In summary, the transpose matrix rotates us into player 2's frame of reference, and we apply this to the current ship's rotation matrix by multiplication, giving us the same rotation step as before, but in terms of rotation matrices rather than orientation vectors:

  [ sidev_x sidev_y sidev_z ]   [ side2v_x roof2v_x nose2v_x ]
  [ roofv_x roofv_y roofv_z ] . [ side2v_y roof2v_y nose2v_y ]
  [ nosev_x nosev_y nosev_z ]   [ side2v_z roof2v_z nose2v_z ]

In both of these calculations, the dot product is at the heart of the transformation calculation, and at the heart of the dot product is a whole load of arithmetic, so let's look at that next.

The arithmetic behind player 2's view
-------------------------------------

Given that Elite does a lot of rotational geometry already, you might assume that we can use one of Elite's many dot product routines for our two-player calculations - perhaps we could use LL51 from the wireframe backface-culling routine, or maybe TAS3 and TAS4 from the tactics and docking routines.

The problem is that all of these routines are optimised for their specific uses; for example, LL51 scales one of its vector arguments so that the magnitude fits into one byte, discarding any data bits that are lost, and both TAS3 and TAS4 simply ignore the low bytes of their 16-bit orientation vector arguments. This makes for fast maths in an environment where we're only really interested in the sign of the dot product and where the value of the dot product occurs within a range, rather than needing to know the exact value.

Unfortunately for two-player Elite, we need all the accuracy we can get, as otherwise player 2's view will jump around too much for a proper combat experience. I know this because the first time I managed to get any meaningful output in player 2's space view, I used TAS3 for the dot product maths, as I was only interested in proving the validity of the algorithm. The test worked (after an awful lot of debugging) and player 1's ship appeared in player 2's view for the very first time, which was a pretty satisfying experience after a couple of weeks of exploding wireframes. But although player 1's ship was in the right place and pointing in the right direction, it did jump around pretty badly; you could literally make out the accumulation of rounding errors in the way the ship stuttered when rotating.

Two-player Elite therefore has its own maths routines that are built around the highest-accuracy multiplication routine from the original code, namely MULT3 . This routine multiplies a signed 24-bit number and a signed 8-bit number, returning the result as a signed 32-bit number like this:

  K(3 2 1 0) = (A P+1 P) * Q

Note that the word "signed" here refers to Elite's use of sign-magnitude numbers, as opposed to the two's-complement approach of normal 6502 assembly language. The highest bit contains the sign, while the rest of the number contains the (positive) magnitude.

Two-player Elite contains the following high-accuracy maths routines:

  • Add24 adds two 24-bit sign-magnitude numbers and returns the result as a 24-bit sign-magnitude number.
  • Multiply16x16 multiplies two 16-bit sign-magnitude orientation vectors and returns the result as a 32-bit sign-magnitude number.
  • Multiply16x24 multiplies a 24-bit sign-magnitude coordinate by a 16-bit sign-magnitude orientation vector and returns the result as a 32-bit sign-magnitude number.

The multiplication routines break the calculation down into steps, each of which calls MULT3 to do the maths. So, for example, if we consider using Multiply16x24 to multiply a 16-bit sidev orientation vector by a 24-bit x-coordinate, then we calculate the magnitude of the result like this:

  |sidev_x_hi sidev_x_lo| * |x_sign x_hi x_lo|

  =   |sidev_x_hi| * |x_sign x_hi x_lo|
    + |sidev_x_lo| * |x_sign x_hi x_lo| >> 8

and then we apply the correct sign to the result by setting the highest bit as follows:

  x_sign EOR sidev_x_hi

We do each multiplication using MULT3, which calculates the following:

  K(3 2 1 0) = (A P+1 P) * Q

where both (A P+1 P) and Q are sign-magnitude numbers. We therefore do the entire calculation in steps, like this:

  1. Do the following calculation in MULT3:
  2.   K(3 2 1 0) = |x_sign x_hi x_lo| * |sidev_x_lo >> 1| << 1
    
  3. Copy the result from to K(3 2 1 0) to XX15(3 2 1 0), so we have the following:
  4.   XX15(3 2 1 0) = |x_sign x_hi x_lo| * |sidev_x_lo >> 1| << 1
    
  5. Discard the low byte of the result in XX15 and round up XX15+1 if bit 7 of XX15 is set, so we have this:
  6.   XX15(3 2 1) = (|x_sign x_hi x_lo| * |sidev_x_lo >> 1| << 1) >> 8
    
  7. Do the following calculation in MULT3:
  8.   K(3 2 1 0) = |x_sign x_hi x_lo| * |sidev_x_hi|
    
  9. Calculate the following in Add24:
  10.   K(3 2 1 0) = K(3 2 1 0) + XX15(3 2 1)
    
  11. If bit 0 of sidev_x_lo is set, do the following:
  12.   K(3 2 1 0) = K(3 2 1 0) + |x_sign x_hi x_lo|
    
  13. Apply the following sign bit to the result:
  14.   sidev_x_hi EOR x_sign
    

Step 1 includes right and left shifts because MULT3 expects sign-magnitude arguments, but sidev_x_lo doesn't have a sign bit as it is the low byte of the 16-bit sign-magnitude number (sidev_x_hi sidev_x_lo). So we shift right to insert a sign bit of zero into bit 7 (thus keeping it positive), do the call to MULT3, and then shift the result back. We then cater for the loss of accuracy in step 6, where we add one more |x_sign x_hi x_lo| to the result if bit 0 of sidev_x_lo is set.

So in essence, steps 1 and 2 do this:

  XX15(3 2 1 0) = |x_sign x_hi x_lo| * |sidev_x_lo|

which means step 3 does this:

  XX15(3 2 1) = |x_sign x_hi x_lo| * |sidev_x_lo| >> 8

so step 5 does this:

  K(3 2 1 0) = K(3 2 1 0) + XX15(3 2 1)
             =   |x_sign x_hi x_lo| * |sidev_x_hi|
               + |x_sign x_hi x_lo| * |sidev_x_lo| >> 8

which is what we want to calculate.

Given these more accurate arithmetic routines, we can wrap up the coordinate and vector rotation maths into two macros, and can include these in the source whenever we want to rotate vectors or coordinates.

The first macro, ROTATE_VECTORS_16, takes the following arguments:

  ROTATE_VECTORS_16 c, v1, v2, v3, w1, w2, w3

This rotates a 16-bit orientation vector in [ v1 v2 v3 ] by another 16-bit orientation vector in [ w1 w2 w3 ] and stores the 16-bit result in the vector c. The calculation is the dot product:

  c = [ v1 v2 v3 ] . [ w1 w2 w3 ]
    = v1 * w1 + v2 * w2 + v3 * w3

where v1, v2, v3 are INWK offsets (so they point to orientation vectors in the current ship data block in zero page), w1, w2, w3 are XX3 offsets (so we need to place the other orientation vector into the XX3 table before using the macro), and c is an offset into the newVectors block (a block where we can store the vector results from multiple rotations). We repeat this calculation nine times to multiply two full sets of orientation vectors (i.e. two rotation matrices).

The second macro, ROTATE_COORDINATE_24, takes the following arguments:

  ROTATE_COORDINATE_24 c, v1, v2, v3, c1, c2, c3

This rotates a 24-bit coordinate in (c1, c2, c3) by a 16-bit orientation vector in [ v1 v2 v3 ] and stores the 24-bit result in the coordinate c. The calculation is the dot product:

  c = [ v1 v2 v3 ] . [ c1 c2 c3 ]
    = v1 * c1 + v2 * c2 + v3 * c3

where c1, c2, c3 and v1, v2, v3 are INWK offsets, and c is an offset into the newCoords block (a block where we can store the coordinate results from multiple rotations). We repeat this calculation three times to multiply a ship's coordinates by an orientation vector.

Finally, we also need a DivideBy96 routine that divides a 24-bit number by 96. Elite uses 96 to denote the length of the unit vector, as this enables fractional vector lengths to be represented, so whenever we multiply by an orientation vector, we need to divide the result by 96 to maintain the correct scale factor. Both of the macros above end with this division, and luckily we can reuse Elite's DVID3B2 routine for this, which has an entry point at DVID3B that calculates the following:

  K(3 2 1 0) = P(2 1 0) / (S R Q)

So in this case we don't need to roll our own function and DivideBy96 can just be a simple wrapper around a call to the DVID3B entry point with (S R Q) set to (0 0 96).

Target calculations
-------------------

One of the most important aspects of space combat is the ability to target your opponent with your sights, both for shooting lasers and for locking missiles onto targets. Not surprisingly, there's some work to be done to enable two different pilots to target each other (and each other's missiles, for those who prefer to blast enemy missiles out of the sky).

For player 1, nothing changes. The game's local bubble includes player 1 at the centre of the universe, and player 2 is spawned as a ship in slot #2. For two-player Elite, we can therefore reuse the single-player game's targeting routines for player 1, so the HITCH routine can be used to work out whether the ship in INWK is currently in player 1's crosshairs; similarly, the missile logic can be kept and used to manage player 1's missiles, as normal. You can read all about this process in the deep dive on being in the crosshairs .

Player 2 being attacked by a missile in two-player Elite

But what about player 2? Can we just reuse the tactics code from the single-player game? After all, player 2 is spawned in the same way that NPC ships are spawned in the single-player game, and the tactics code works out whether or not an NPC player can hit the single player at the centre of the universe, so can we use this to detect whether player 2 can hit player 1?

The answer turns out to be no, because the code that works out whether an NPC's laser is on-target can get away with being considerably less accurate than the code that works out whether the player's laser is on-target. This is because in the original game, we can't see out of the NPC's cockpit, so we can't tell how accurately each NPC can point its laser.

It turns out that NPC lasers can be wildly off-target but can still register a hit; indeed, if you set player 2 to the AI Pilot in two-player Elite, you can see this in action, as the AI Pilot uses the exact same tactics code as in the original game; the AI Pilot's target can be quite a long way outside the laser sights but the tactics code still registers a hit. This can be changed to require more accuracy from the NPCs, but then you run into limitations in the part of the tactics code that moves NPC ships to point to their target, with the result that NPC ships hardly ever hit anything if you need them to line up their sights properly. For a real-world example of how the tactics routine is less than perfect, see the deep dive on the Elite Demonstration Disc , which applies the same tactics code to the self-playing demo, with predictably fatal consequences.

So for two-player Elite, we need to write our own targeting code for player 2. Luckily, there is a point where we can simply reuse the HITCH routine to work out whether player 2 is targeting another ship, and that's in part 5 of the DrawPlayer2View routine. By this point we have moved the current ship into player 2's frame of reference and have drawn it in player 2's view, so the INWK workspace is all set up with the current ship's coordinates, relative to player 2. So we can call HITCH at this point to see whether the current ship is in player 2's sights, and we can then process missile targeting and laser fire accordingly.

This approach works nicely for missiles, but it also works for player 1's ship. When we process slot #2 in DrawPlayer2View, which contains player 2's ship, the transformation process actually calculates the coordinates and orientation of player 1's ship in player 2's view, so we can call HITCH to work out whether player 2 is pointing at player 1. And because we are using the exact same routine to detect a hit, this makes the process equally fair for each player, and it has the added bonus of taking the ship's targetable area into consideration, so two-player ship choices automatically affect the ease of targeting your opponent.

For missiles, the only slight complication is the need to duplicate all of the missile status variables for player 2, so alongside variables like MSTG, which contains the current missile lock target (for player 1), we need to add variables like player2MSTG to track the lock target for player 2; see the miscellaneous section for more details.

Cheating with the sun and planet
--------------------------------

As discussed in the section on arithmetic , two-player Elite needs to be able to calculate dot products at a higher accuracy than the single-player game, otherwise close-quarters combat is a bit too jumpy. Unfortunately, even with the 24-bit accuracy of the new maths routines, the distant sun and planet can still wobble a bit too much for comfort, as any inaccuracies in the maths are amplified by the larger distances involved.

Luckily we can fix this with some good old smoke and mirrors, because the planet and sun are only there for aesthetic purposes; you can't fly towards them in two-player Elite, so they stay in the background and have no effect on gameplay (though they do have a major impact on immersion and finding your bearings, so they're still important). This lack of movement is achieved by a simple hack in part 6 of the MVEIT routine, so we only apply the player's velocity vector to close-by ships, and not to the planet or the sun.

(To make things a bit less of a mouthful, from now on I will only refer to the planet, but everything I say about the planet also applies to the sun. So when you see "planet", it means "planet and sun", just with fewer words.)

This jumping around only happens in player 2's view, due to inaccuracies in the translation and rotation transformation we explored in the geometry behind player 2's view . So there's a hack in part 2 of DrawPlayer2View that checks whether the planet is currently on-screen in player 2's view, and if it is then we skip the usual application of the two-part transformation, and instead we only move it by the rotations of player 2's controls. This means that the planet doesn't jump around on-screen and instead moves smoothly with the pitch and roll of the player.

Player 2 looking at player 1 and the planet in two-player Elite

Once the planet moves off-screen, we switch back to applying the full two-part transformation, so that it snaps back to the correct position in space. This realignment isn't seen by the player as it's only done when the planet is off-screen, but it can mean that if the planet moves off-screen and then back on-screen quite quickly, it can sometimes appear to have jumped to a new position. Luckily this isn't obvious in fast-paced combat, but if you treat two-player Elite as a gentle stroll through deep space with a friend, then it might be a bit more obvious that something strange is going on behind the curtain.

On top of this cheat, there's another tweak to the normal flow that reduces the amount of on-screen strangeness. Because of the various mathematical approximations used in the ship rotation routines in Elite, and in particular the small angle approximation, we have to "tidy" each ship's orientation vectors periodically to ensure they remain orthonormal; see the deep dive on tidying orthonormal vectors for details.

In normal single-player Elite this isn't too noticeable, because tidying a ship's orientation vectors doesn't change its coordinates in space, it just stretches the ship's shape back into the correct dimensions. As a result, the most you will see is a bit of a wobble in the shape of the ship, which is very hard to see, particularly if the ship is moving.

But in two-player Elite, the orientation vectors are at the core of the two-step transformation process that we use to draw player 2's view, so changing an orientation vector will affect both the coordinates and the orientation of the on-screen ship within player 2's view. As a result, tidying a ship's vectors while it's in player 2's view can make it jump around very noticeably, particularly if the vectors have degraded a long way from being orthonormal. So two-player Elite extends the on-screen checks to the tidying process, so we only tidy the vectors for the planet, the sun and player 1's ship if it isn't being drawn in player 2's view. For missiles, however, we can get away with tidying as we see fit, as they move like the clappers and have a short lifespan, so the chances of vector degradation is low.

This tidying hack has a downside. If you keep the planet, sun or opponent in player 2's view for an extended amount of time, then their orientation vectors will never get tidied and they will start to degrade over time, so player 1's ship will slowly deform, and the planet's circles will get all twisted. But again this is very unlikely to happen during one-on-one combat, so the risk is well worth taking.

Responsive controls for two players
-----------------------------------

Elite has sophisticated support for processing multiple keypresses. It has a key logger that has a number of slots, into which the game records key presses for seven primary controls (pitch, roll, speed and lasers), nine secondary controls (missiles, E.C.M., in-system jump and so on), and one other arbitrary key press. The key logger is refreshed on every iteration of the main loop by scanning the keyboard for the relevant controls and populating the logger, and it enables the game to support a number of keys being pressed at the same time, which is essential in a fast-paced game like Elite. This system is described in more detail in the deep dive on the key logger .

Not surprisingly, the key logger is only designed for one player. If we try to use the original key logger with two players, then the only slot available to the second player is the arbitrary key press slot, and that gets populated by a keyboard scan that stops as soon as it has found a key, irrespective of whether it's being pressed by player 1 or player 2. Obviously, this isn't anywhere near a solution for a two-player game where we need to give both players the same level of control.

Luckily it isn't too difficult to extend the key logger, so two-player Elite adds two more key slots. This gives us enough slots to cover both the primary and secondary controls for the two players, as we don't need to support the full set of key presses from the original game; for example, we can repurpose existing key slots like the energy bomb and in-system jump for player 2's flight controls.

This gives the primary and secondary flight controls for each player the same level of support, so both players can fly their ships and shoot their missiles and lasers without being affected by the other player's actions. But there are a few other controls that we need to support in the two-player version, such as the keys to change between the front, rear, left and right views, and therein lies the problem.

The key logger uses the single-byte "other key press" entry for all these other controls, and it populates this with a scan of the keyboard. This scan works through the keyboard from low internal key numbers to high, and when it detects a key press, it stops and logs that as the "other key". This is fine for one player, but the problem with two players is that if a player holds down a key that appears early on in the full-keyboard scan (i.e. a key with a low internal key number), then that key will fill the "other key press" slot, the keyboard scanning will stop, and any other key presses will be ignored. This means that if player 1 holds down the f0 key to switch to their front view, then because f0 has internal key number &20, this will disable all of player 2's keys that have a higher internal key number. This turns out to be all of them except for the left arrow key, which has an internal key number of &19, so all player 1 has to do to disable a bunch of player 2's keys is to hold down f0. This clearly will not do.

The same issue affects the buttons on the Delta 14B joystick, which we scan in the same keyboard routine when Delta 14B sticks are configured:

Two Delta 14B joysticks and a BBC Micro B+ signed by David Braben

This is because it doesn't matter whether we're talking about keys on a keyboard or buttons on a joystick - the problem is that these extra controls get squashed into just one byte in the logger.

One solution would be to add a second "other key" byte so there's one for each player; we could then reserve one byte for player 1 and the other for player 2, and make sure the keyboard scan only stops early if keys have been detected for both players. It turns out that this approach would need a fair bit of recoding in the parasite code and wouldn't be the fastest solution, so instead I've added a very simple hack to "timeshare" the extra keys between the two players.

The I/O processor, which does the keyboard scanning, contains a new flag variable called player2Turn that flips bit 7 every time the I/O processor is asked to scan the keyboard. When bit 7 is clear, player 1 has precedence, so we make sure we return a player 1 key in the arbitrary key slot, if one is being pressed; and when bit 7 is set, player 2 has precedence, so we make sure we return a player 2 key, if one is being pressed. If the player with precedence is not pressing a key, then we can return the other player's key press, if there is one.

In this way we can stick to the one-byte "other key" slot, and all we need to do is make sure we only abort the keyboard scan early if we find a key press that matches the player with precedence. Because the keyboard is scanned very regularly, this simple system constantly flips precedence between the two players, so neither of them will notice that only one of them has precedence at any one time.

The result is a properly responsive keyboard that shouldn't cause too many arguments. I hope.

Miscellaneous
-------------

Here are some additional points that are worth noting about two-player Elite:

  • The shared scanner is a simple consequence of the way DrawPlayer2View works. After the two-step transformation is performed, the current ship has the correct coordinates for drawing the ship in player 2's view... which means it also has the correct coordinates for drawing that ship on the scanner in the correct place for player 2 to use. So DrawPlayer2View calls the SCAN routine to update the ship on the scanner, and we can extend the call to the I/O processor to take an extra argument containing the colour, so player 1's scanner can contain cyan ships and player 2's scanner can contain yellow ships.
  • On the subject of the scanner, we can also extend the call to the I/O processor to pass the ship type. This means that that missiles can be drawn with a thin dash at the end of the stick while other ship types are drawn with a thick dot.
  • The scanner is zoomed-in by a factor of two compared to the single-player game, to make it easier to work out what's going on in close combat. This only requires a couple of shifts in the I/O processor's SC48 routine, which does the actual drawing.
  • All the in-game text is implemented using the game's normal text token system. Two-player Elite disables the game's information screens, as we don't need things like market prices and system descriptions, so there are plenty of tokens that are suitable for conversion into two-player text.
  • The main game loop and flight loops are considerably simpler than in the one-player game, as quite a lot of functionality is no longer required. The spawning code has been removed from the main game loop, so that's all of parts 1, 3, 4 and most of part 2 gone. And aspects like the energy bomb, docking, scooping and spawning are no longer needed in the main flight loop, so parts 5, 8, 9, 10 and 14 have been completely removed, as well as large chunks of parts 7, 11, 12, 13 and 15. Going in the other direction, the keyboard and joystick code in parts 2 and 3 of the main flight loop is more complicated, as it duplicates the primary flight control detection for the second player.
  • On the subject of duplication, a number of player 1's routines have simply been duplicated for player 2; for example, player 2 has their own missile, laser, shield and energy routines, all of which copy the functionality of the one-player code. Here's a full list of duplicated routines, where a name like Player2XXX indicates that this duplicates the XXX routine from the original game:
    • Player2ABORT
    • Player2ABORT2
    • Player2DENGY
    • Player2ECBLB2
    • Player2ECMOF
    • Player2ee3
    • Player2FR1
    • Player2LASLI
    • Player2LASLI2
    • Player2me1
    • Player2me2
    • Player2me3
    • Player2MESS
    • Player2OOPS
    • Player2SHD
    • Player2SPS3
  • To go along with these routines, there's also a collection of duplicated variables that are used to store things like player 2's energy levels and laser temperature. These variables can be found at the end of the WP workspace, where a name like player2XXX indicates that this duplicates the XXX variable from the original game. Variables at the start of the block, which appear between the startWP to endZero labels, get zeroed in the ZERO routine, so they contain values that need to be reset at the start of each game by the RESET or RES2 routines; variables after endZero either don't need resetting, or they contain configuration information from the main game screen, which we want to retain between games.

And that's two-player Elite. I hope you enjoy exploring it as much as I enjoyed writing it...

Grok Outage

Hacker News
status.x.ai
2026-09-03 11:26:01
Comments...
Original Article

Why have I been blocked?

This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.

What can I do to resolve this?

You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.

Microsoft: KB5120998 mouse reset bug affects only non-English PCs

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 11:22:33
Microsoft says a known issue that reverts mouse settings after installing the KB5120998 August 2026 preview update affects only non-English Windows 11 systems. [...]...
Original Article

Windows 11

Microsoft says a known issue that reverts mouse settings after installing the KB5120998 August 2026 preview update affects only non-English Windows 11 systems.

The bug was confirmed Friday , one day after the KB5120998 release , which includes Start menu, taskbar, and Windows search improvements for devices running Windows 11 versions 25H2 and 24H2.

According to user reports, mouse cursor personalization settings are changing or resetting automatically after installing the KB5120998 update, and affected Windows 11 users cannot restore their previous mouse settings after they are reverted.

"Following installation of Windows updates released August 27 2026 (KB5120998) and later, mouse personalization settings are being reverted to certain standard settings," Microsoft explained at the time.

"This includes cursor and cursor animations that are selected in the Mouse Properties options under Windows."

Only non-English Windows devices affected

In a Tuesday update to the Windows release health dashboard, the company noted that a follow-up investigation revealed the issue affects only non-English devices.

"Our investigation indicates that this issue is caused by code components used in non-English Windows installations. In impacted locales, these settings will fail to load, causing a default to be used instead," Microsoft said .

Since KB5120998 is an optional, non-security update, users must click the "Download and install" link. However, if the "Get the latest updates as soon as they're they're available" option is enabled, the preview update will install automatically.

Microsoft has addressed several other issues causing mouse issues on Windows devices in recent months.

For instance, it released emergency updates in October to fix a known issue that made the Windows Recovery Environment (WinRE) unusable by disabling USB mice and keyboards .

More recently, Microsoft confirmed that it's investigating a bug causing the mouse pointer to disappear for some classic Outlook users when moving it over the interface.

On Wednesday, it also acknowledged that Windows desktop settings will be lost or reset on some devices after installing the KB5120998 preview update.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

OpenAI confirms ChatGPT is down ahead of 'Astra' model launch

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 11:13:29
ChatGPT and Codex are experiencing a major outage, with users reporting errors across nearly every major ChatGPT feature. [...]...
Original Article

ChatGPT

ChatGPT and Codex are experiencing a major outage, with users reporting errors across nearly every major ChatGPT feature.

The outage started at approximately 10:58 AM ET on Thursday, September 3, and is affecting ChatGPT conversations, login, search, file uploads, Voice mode, GPTs, image generation, Deep Research, Agent, ChatGPT Work, and other services.

OpenAI's Codex services are also affected by the outage.

If you are affected, ChatGPT may fail to load conversations, return errors when sending messages, or prevent you from using features such as Search, file uploads, image generation, Deep Research, and Voice mode.

Thankfully, OpenAI is aware of the problems and has acknowledged the outage on its status page .

"We are investigating the issue for the listed services," OpenAI said.

According to the company's status page, at least 15 ChatGPT components are affected, including Conversations, Login, ChatGPT Work, Codex in ChatGPT Desktop, Compliance API, Search, File uploads, Voice mode, GPTs, Image Generation, Deep Research, Agent, ChatGPT Atlas, Sites, and Connectors/Apps.

The outage comes ahead of the expected launch of OpenAI's next major AI model, Astra, which the company recently confirmed will be released soon.

OpenAI has not said whether today's outage is related to preparations for Astra, and it's unlikely the issues are related, as ChatGPT has frequent outages.

As of the time of writing, OpenAI is still investigating the elevated errors across ChatGPT and Codex

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

What do you do when your favorite programming language has a fascism problem?

Lobsters
codeandcake.dev
2026-09-03 11:10:16
Comments...
Original Article

Ruby is my favorite programming language. It’s a great language and nothing really comes close to it in terms of expressiveness. I know it’s not everyone’s cup of tea, but it’s mine.

The Ruby community used to be known as being very friendly. I don’t think many people would say that these days. As most everyone knows now, DHH, the creator of Rails, has gotten his brain cooked on Twitter and is now a full-blown fascist. This blog post isn’t gonna relitigate that fact. If you think DHH is just a reasonable guy with differing opinions that should be respected, you can close the tab now.

This is a hard fact for me personally to swallow. I love Ruby and Rails, and I even think Rails makes some great technical decisions that have still held up. But every time I read a word DHH says these days, my stomach turns.

What are you supposed to do when your favorite programming language has a fascism problem?

Denial

I wanna tell myself that it’s ok to still use Rails. DHH hasn’t even committed to the Rails repo this whole year. He’s too busy doing a much more important thing: posting racism on the racism app (Twitter).

But Rails is still very much DHH’s project. He owns the trademark . There is no Rails without DHH.

Forks and Hanami

There’s been lots of talk about forking Rails . I’d love for a fork to magically appear and drown out Rails, but we’re so far from that being a reality.

A choice that is a reality today is Hanami . Hanami is a newcomer to the Ruby world. It’s a web framework that thinks very differently than Rails. And I wish it well, but I like the technical decisions in Rails more than Hanami. It’s just not the framework for me.

Moving on

Do I have to move on then? There’s not really a language like Ruby that’s around today. I’ve been playing around with Gleam lately. Gleam is fun! It takes a lot from Elm, another language I liked a lot, and they have a great community. But it just doesn’t fill that same space as Ruby. I like OOP! I like dynamic types! I like metaprogramming! I’ll probably still continue to play with Gleam, but it’s not a Ruby replacement.

Where do I go from here?

If you were hoping for answers in this blog post, I’m sorry, I don’t have any. I’m not sure where I go from here. Maybe a Rails fork will become mainstream. Maybe DHH will leave the project. Maybe a cool new programming language will come along that better fits the Ruby-shaped hole I have. I’m not sure. I just hope if you’re also feeling conflicted about the state of Ruby, just know that you’re not the only one.

Ask HN: Why are OpenAI, Claude, and Grok simultaneously down? Coincidence?

Hacker News
news.ycombinator.com
2026-09-03 11:07:01
Comments...
Original Article

Well no one said it yet so I will, "international actors" is at least a possibility. And I don't mean any specific country because pretty much anyone is a potential these days, which makes it a perfect cover for different anyones. Demonstrating vulnerability in the US's AI boom can move the markets. That's a financial incentive and a strong geopolitical one.

More likely just cascading overload though: "Never attribute to malice what can be explained by incompetence", or in this case, "growing as fast as possible"


Think of it like one big distributed system. OpenAI is down, so people migrate to Claude, now this one gets overloaded and goes down, etc.

So not a coincidence, one went down first and users migrated causing further DOS. At least that's my guess.


Just now I got this from gemini

It looks like there's no response available for this search. Try asking something else.


I find it hard to believe that enough people would flock to from Claude and Chat to Grok to cause an outage. I feel like Gemini is the dominant release valve in this case especially for enterprise.


Especially considering memory/gpu/compute are scarce so these services are likely running with very little buffer.


What about a hard-takeoff scenario of an unleashed OpenAI Astra taking other models down for computational resources control?


I kinda assume it's because one went down and a large amount of work shifted to another.

I'm also aware that they have overlap in some areas on data centers.


Oh man. Some low effort supply chain attack that turns every GPU into a cryptominer. It's funny because it's plausible.


I assume it cascaded from one provider to the other as people who lost claude access for instance moved to openai who moved to grok when it went down, etc.


claide.ai is working for me, so is chatgpt.com. grok still has a status message about issues, i can't try it without signing up.


Didn't SpaceX overbuilt infra and leases it out Anthropic? I f their dc goes down it probably takes a chunk out of Claude's capacity before even considering the flood of users switching over


everything in this thread is raw speculation, obv, but if i had to put money on anything i'd say this is a left-pad incident. some piece of something or other that all of these services happen to depend on went down. Second most likely seems to be some random failure of one leading to an unexpected traffic spike in others, though it seems like we've been talking about automated scalability in web apps for so long that there should at least be a response to, if not a solution for, this sort of problem.

Anthropic confirms Claude is down, multiple models affected

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 11:02:52
Claude is experiencing an outage, with users encountering elevated errors when sending requests to multiple Anthropic AI models. [...]...
Original Article

claude down

Claude is experiencing an outage, with users encountering elevated errors when sending requests to multiple Anthropic AI models.

The incident began on September 3, 2026, at around 9:41 AM ET, and is affecting several Claude models, including the company's latest Mythos, Fable, and Opus models.

According to Anthropic’s status page , the company initially said it was investigating elevated errors on requests to Claude Mythos 5.1, Claude Fable 5.1, and Claude Opus 5.

At around 9:41 AM ET, Anthropic said it had identified the cause of the elevated errors and was working on a fix.

Claude down
Claude error when using affected models

A few minutes later, Anthropic published a more complete list of affected models, confirming that the outage impacts Mythos/Fable 5.1, Mythos/Fable 5, Opus 5, Opus 4.8, and Opus 4.6.

For users, the outage can result in requests failing to complete or returning errors when using one of the affected Claude models.

Anthropic said at 10:49 AM ET that it was continuing to work on a fix for the issue.

The company has not publicly disclosed what caused the elevated errors beyond confirming that it has identified the underlying issue.

The outage remains ongoing at the time of writing.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

It's an Incredible Time To Be Alive and in the Mood for Tacos Below 23rd Street

hellgate
hellgatenyc.com
2026-09-03 11:00:38
A trio of newcomers, two directly from CDMX, join downtown Manhattan's already stacked taqueria lineup....
Original Article

If there ever was a part of NYC that didn't really need a sudden influx of new and noteworthy taquerias, it would be downtown Manhattan. I mean, come on! We've already got a murderers row of taco spots down here, from Santo Tacos in SoHo and Union Square and Carnitas Ramirez in the East Village to Beto's Carnitas on the Lower East Side, Taqueria El Chato and Tacos 1968 in the West Village, plus stalwarts like Los Tacos No. 1, which has four locations in the area.

But as is true with, say, stellar slice shops or bang-on bakeries, a first-class taqueria is always a welcome addition to any neighborhood, no matter how embarrassing the riches already are.

Three new taco spots opened less than a mile from each other down here this past summer, and last week I ate the whole menu at each of them. These are their stories.

Give us your email to read the full story

Sign up now for our free newsletters.

Sign up

Elevated errors across ChatGPT and Codex

Hacker News
status.openai.com
2026-09-03 10:59:08
Comments...
Original Article

Availability metrics are reported at an aggregate level across all tiers, models and error types. Individual customer availability may vary depending on their subscription tier as well as the specific model and API features in use.

.name Termination

Lobsters
neil.fraser.name
2026-09-03 10:55:14
Comments...
Original Article

.name Termination

3 September 2026

Nearly twenty-five years ago I registered neil.fraser.name to provide a stable presence on the Internet. It has been the home of this website, my email address, and a server for APIs. It predates YouTube, Facebook, and smart phones. Minutes after my daughter was born, I also registered beverly.fraser.name .

On 15 April 2026 Verisign proposed the destruction of the entire 3rd level of the '.name' hierarchy in order to simplify their administration. Astonishingly, on 28 July 2026 ICANN approved this action . I found out about this a few days ago when my registrar emailed me.

Now, it's worth pausing for a moment to discuss what '3rd-level domains' are. Many people will be familiar with shady operators selling domains like *.uk.co . In that case it's some random guy who bought the 'uk' domain from the country of Columbia, then resells third-levels. If that operator disappears, then so do all the domains he sold. As a result, 3rd-level domains have gotten a dubious reputation. However, '.name' is completely different. It was setup exclusively as a 3rd-level operation. One registers xxx.yyy.name from any registrar and there is a full whois record. Exactly like *.ny.us , or *.co.uk .

One of my original reasons for choosing '.name' was that it was run by Global Name Registry -- more specifically, it was not run by Verisign. I had history with Verisign and did not trust them. Unfortunately, Verisign acquired Global Name Registry a few years later. This mistrust was validated by the numerous lies Verisign included in their above proposal to ICANN.

So what does this mean? First, this website vanishes in February. Despite the fact that it's registered and paid for until 2040. Second, my email address also disappears. Third, all the IoT devices that use services on this domain become bricks. Basically, I disappear from the Internet.

But it gets much worse. Once the 3rd-level domains are terminated, it is assumed that the now vacant 2nd-level domains will become available for registration. Should someone (other than me) scoop up fraser.name they would be able to recreate and control neil.fraser.name . They'd be able to hijack hundreds of accounts that are linked to that address. They could commit code with my authentication. They could seize control of IoT devices. There is no way to enumerate all accounts (online and offline) which have been opened using this email address over the past quarter century.

I'm just one of 22,000 people who will lose their domains. This is going to be fun. Time to lawyer up...

< Previous | Next >

Legal yada yada: My views do not necessarily represent those of my employer or my goldfish.

Codex Is Down

Hacker News
github.com
2026-09-03 10:54:31
Comments...
Original Article

EDIT: Seems as you're all spamming my inbox. My advice. Go spend time with your kids. Or like check out Breaka Club where I'm building stuff to teach kids to code and make computer games with pencils and paper (remember those). No service outage on pencils and paper! 😉

What version of the Codex App are you using (From “About Codex” dialog)?

26.611.61753

What subscription do you have?

Pro x20

What platform is your computer?

Darwin 25.3.0 arm64 arm

What issue are you seeing?

Repeatedly encountering in my GPT 5.4 xhigh session:

unexpected status 404 Not Found: Unknown error, url: https://chatgpt.com/backend-api/codex/responses, cf-ray: ...

I can send a message and get an update back, but then when the agent would think and continue I encountered this error 3 times in a row.

I have another session running with GPT 5.5 xhigh and it seems to be unaffected.

What steps can reproduce the bug?

I have a long running session going, it's had many compactions and plenty of steering. I've also been spinning up sub-agents for smaller tasks where this session is acting as an orchestrator. It failed shortly after steering it to spin up a sub-agent, not sure if that's related.

Session stopped with this error, it retried 5/5 times and gave up. This did not occur immediately after compaction, but it was shortly there after, maybe around 50k tokens.

Image

Sending Continue did work, but it failed again after taking a turn. I tried this twice more and it does seem that for now the session is continuing on.

What is the expected behavior?

Don't die mid session.

Ideally we'd also have more error resistant retries with exponential back-off to something like 20 retries over 10 minutes.

Additional information

No response

Critical Elementor Pro flaw exploited to take over WordPress sites

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 10:52:20
A recently patched critical vulnerability (CVE-2026-32475) in the Elementor Pro plugin for WordPress is being exploited in attacks that deliver a webshell payload and execute arbitrary commands on the server. [...]...
Original Article

Critical Elementor Pro flaw exploited to take over WordPress sites

A recently patched critical vulnerability (CVE-2026-32475) in the Elementor Pro plugin for WordPress is being exploited in attacks that deliver a webshell payload and execute arbitrary commands on the server.

Elementor Pro is a popular WordPress plugin with more than 6 million active installations, allowing users to build websites using a drag-and-drop interface.

The CVE-2026-32475 vulnerability was patched on August 19. Since then, Defiant's Wordfence web application firewall has blocked almost 200,000 exploitation attempts targeting its clients.

The issue stems from faulty validation of file-upload arrays in Elementor Pro forms and is present in versions 4.2.1 and earlier.

By submitting an empty file as the first array element and a malicious PHP file as the second, attackers can cause the plugin to stop validating subsequent files.

The uploaded payload is stored under /wp-content/uploads/elementor/forms/ and can then be accessed to execute commands remotely.

WordPress cybersecurity platform Patchstack warned last month that attackers could exploit it to upload arbitrary PHP files and trigger PHP code execution on the server.

Exploitation is only possible when a site has a published Elementor Pro Form widget containing at least one File Upload field, a common configuration.

Yesterday, Wordfence alerted that activity exploiting CVE-2026-32475 started on August 19, the same day Elementor released version 4.2.2 that addressed the vulnerability.

“The attacker submits the form’s File Upload field as an array, where the first element is empty and the second element carries a PHP payload with a .php filename, which is the structure that triggers the validation bypass,” Wordfence says .

Example malicious request
Example malicious request
Source: Wordfence

“Once written, the uploaded PHP file is placed in the /wp-content/uploads/elementor/forms/ directory under a randomly generated filename with the attacker-supplied .php extension, and the attacker can request it directly to execute arbitrary commands on the server,” the security firm notes.

Wordfence observed increased attack activity between August 19 and 23, reporting more than190,000 blocked exploitation attempts.

A list of IP addresses that launched thousands of attacks is also provided so that defenders can add them to their blocklists.

Administrators should upgrade to Elementor Pro 4.2.2 or later immediately and inspect the /wp-content/uploads/elementor/forms/ directory for rogue PHP files.

Since this location is used to store uploaded form submissions, the presence of a PHP file is a strong indicator of compromise that should trigger clean-up operations.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

Any Human Ever – One life, drawn at random from all who have ever lived

Hacker News
anyhumanever.com
2026-09-03 10:51:10
Comments...
Original Article

Over 100,000,000,000 people have ever lived.

Choose one.

You'll draw, step by step: a year, a place, a life, each taken at random from real data .

Six Ways to Thrive in Zombie Times

OrganizingUp
convergencemag.com
2026-09-03 10:49:24
Featured illustration: Kimmie Dearest Art by Chetna Mehta, chetnamehta.co We dedicate this piece to the memories and strengths of our diverse ancestors, remembering that they survived extreme hardship and that they still stand with us, guiding our hands and spirits, through it all.  Introductio...

ChatGPT Is Throwing 404

Hacker News
chatgpt.com
2026-09-03 10:46:47
Comments...

The six best e-readers in the US, for every kind of book lover

Guardian
www.theguardian.com
2026-09-03 10:36:43
Whether you’re on a budget, looking for an easy way to read when you travel, or want one for kids, here are our picks for the best ebook readersIn the UK? Check out our top-rated UK e-readers here.Bookworms may still cherish the feel of leafing through pages, the whiff of new-book smell, and stackin...
Original Article

B ookworms may still cherish the feel of leafing through pages, the whiff of new-book smell, and stacking their shelves with beloved tomes, but nothing beats an e-reader (ebook reader) for convenience.

You can bring your entire library on vacation without an extra suitcase. If you’re working through a 1,349-page novel such as Vikram Seth’s A Suitable Boy, your wrists will thank you. And unlike a phone, your e-reader won’t constantly interrupt you with news alerts and texts, so you can lose yourself in a new world or focus on learning something new.

Ebook readers evolve more slowly than say, smartphones, the latest batch are lighter, brighter, and more capable than ever. I evaluated six of the most popular models to see which belongs on your nightstand.

For more, check out our guides to using a paper journal to read more mindfully , how to start reading for fun and 10 mildly subversive (banned) books .

This article was updated for fall 2026. We have reorganized our e-reader guide, checked availability and pricing for all models, and given it a refresh. We’ve also noted the increased prices of Kindles due to rising memory and storage costs. We plan to test more models in the coming months.

Jump to a section:


At a glance

Best overall e-reader

Kobo Libra Colour

Read more

$258.09

Runner up

Kobo Clara BW

Read more

$159.99

The most affordable Kindle

Amazon Kindle (11th Gen)

Read more

$149.99

A fancier Kindle

Kindle Paperwhite Signature

Read more

$249.99

Best e-reader for kids

Amazon Kindle Colorsoft Kids

Read more

$300

If you want a big 8in screen

Nook GlowLight 4 Plus

Read more

$199.99


The best e-readers in the US, explained

Kobo Libra Colour

Best overall e-reader:
Kobo Libra Colour

$260 at Kobo
$258.09 at Amazon
$259.99 at Walmart
$259.99 at eBay

If you’d rather borrow books from your local public library than Amazon, the Kobo Libra Colour is the ebook reader for you. The Libra integrates directly with OverDrive, makers of the Libby app , which makes it the easiest way to download ebooks from your public library.

The Libra Colour is fun to play around with and make your own. It has more fonts and font sizes to choose from than the Kindles I tested, and it’s possible to make subtler adjustments to the brightness and warmness, too. It also has physical buttons for turning pages or you can tap and swipe on the screen.

Unlike a Kindle, it’s also easy to load files you want. Dropbox and Google Drive integration make it painless to load your own books onto the e-reader. The Kobo stylus ($70 at Amazon , Kobo) , lets you highlight and take notes, which was great for PDFs I couldn’t otherwise edit on the device.

In addition to its OverDrive access, Kobo has a well-stocked bookstore of its own. There were only two titles on my list that I couldn’t find and most of its ebook prices matched Amazon’s.

It’s a shame that … it costs so much. Its battery drained more quickly than some of the competition, too. Though it still lasts at least a month, like most ebook readers.

Key specs:

  • Storage: 32GB

  • Battery life: up to 40 days

  • Display: 7in, 300 ppi (black-and-white content), 150 ppi (color content)

  • Waterproof: IPX8 (up to 60 minutes in 6.5ft of fresh water)

Cheaper alternative: The Kobo Clara Color ($180 at Amazon , Kobo) omits a few features, such as physical buttons and the ability to work with a stylus, but costs about $80 less. It’s screen is slightly smaller and it has less storage, but it can still share with libraries. See Kobo’s model comparison page if you’re unsure.


A Kobo Clara BW e-reader on a table and being held by a reader

Runner up:
Kobo Clara BW

$159.99 at Kobo
$159.99 at Amazon
$159.99 at Best Buy

Love to read by the pool for hours at a time? Like our top pick, the Kobo Libra Colour (scroll up to read more), the Kobo Clara BW can stay powered for weeks and survive an accidental dip. When I submerged the Kobo in a tub of tap water for 10 minutes, it remained completely functional after I fished it out.

Even if you’re not scheduled to lounge on the beach, this e-reader has more than enough space to hold a ton of ebooks and audiobooks. Like the Kindle, it has 16GB. I loaded it up with more than 180 PDFs, and had a lot of room to spare.

The battery life was impressive. It also charged quickly, getting up to 90% after 90 minutes. It outshines the budget Kindle because it can change color temperature, either manually or based on a schedule.

While it doesn’t have all the features of the Kobo Libra Colour, it was equally easy to get library books from OverDrive or the Kobo bookstore.

It’s a shame that … the screen is a little dimmer compared with some of the larger 7in devices, and it lacks the buttons of the Kobo Libra Colour. Side-by-side with the budget Kindle, it does feel a little bulky. Though we still prefer it.

Key specs:

  • Storage: 16GB

  • Battery life: up to 53 days

  • Display: 6in, 300 ppi

  • Waterproof: IPX8 (up to 60 minutes in 6.5ft of fresh water)


Amazon Kindle (11th Generation) e-reader on a table and being held by a reader

The most affordable Kindle:
Amazon Kindle (11th Gen)

$149.99 at Amazon
$149.99 at Best Buy

We currently prefer Kobos to Kindles, but if you’re in the Amazon book club already, Kindles are still great. As of August, sadly, the basic Kindle is now quietly more expensive than it used to be due to memory prices, but it’s still a great black and white ebook reader with almost everything you’d want.

It’s a portable way to read ebooks and access Amazon’s seemingly endless supply of titles, which you can also read on your computer, phone or tablet through the Kindle app. Amazon also owns Audible for audiobooks, which you can listen to if you own Bluetooth earbuds (see: Best Wireless Earbuds ).

The Kindle delivers plenty of storage for all your ebooks. And you have a lot of reading options through Amazon. I found all 26 titles I was looking for, and my Amazon shopping cart was the cheapest, although Barnes & Noble and Kobo had identical prices on most books.

Its 6in screen was one of the smallest I tested, but the text was crisp and easy to read. It had no trouble surviving the drop tests when I knocked it off my nightstand.

It’s a shame that … this Kindle lacks the ability to change the color temperature from bluish white to a warmer yellow as bedtime approaches. A dark mode, which makes the background black and words white, might suffice for some.

Its battery life isn’t as robust as some of the other options on the list, but it should still last many weeks on a single charge.

Key specs:

  • Storage: 16GB

  • Battery life: up to six weeks

  • Display: 6in, 300 ppi

  • Waterproof: No


Kindle Paperwhite Signature on a table and being held by a reader

A fancier Kindle:
Kindle Paperwhite Signature

$249.99 at Amazon
$249.99 at Best Buy

The Signature version of the Kindle looks and feels premium. Flipping through pages feels the fastest on this device and the touchscreen is smooth.

If you want an e-reader that can zoom in close and still retain fine detail, this is a fantastic option. Its battery life is the best I tested, too.

It’s a shame that … it is pricey. Wireless charging is one of the main features, besides its extra storage, that sets it apart from the cheaper Kindle Paperwhite ($200) , which is about $50 less.

And, as I discussed in the Kobo Libra Colour and basic Kindle sections. It’s more difficult to get library books and load files on Kindles – not impossible, but not as easy.

Key specs:

  • Storage: 32GB

  • Battery life: up to 12 weeks

  • Display: 7in, 300 ppi

  • Waterproof: IPX8 (up to 60 minutes in 6.5ft of fresh water)


Amazon Kindle Colorsoft Kids e-reader on a table and being held by a reader

Best e-reader for kids:
Amazon Kindle Colorsoft Kids

$299.99 at Amazon
$299.99 at Best Buy

Amazon makes several child-geared Kindles. They’re similar to their grown-up counterparts but usually come with a protective case, a longer warranty and six or 12 months access to an Amazon Kids+ subscription , which includes access to a range of age-appropriate ebooks. The Colorsoft is our favorite ( read our full review ).

A color screen makes sense for kids who devour picture books and graphic novels. While hues on books like You Are a Burst of Color are a little muted compared with a physical copy, the 7in screen still captures plenty of vibrant detail.

The Colorsoft has respectable storage and battery life and the screen is responsive, making it easy to tap or swipe through pages, even of an unwieldy PDF. It can auto-adjust the light’s warmth at sunset or based on your preferred schedule.

It’s quick and easy to toggle between kid mode and a typical Kindle, only requiring a four-digit code. That means your child could use the same device when they start reading grown-up books.

It’s a shame that … getting library books on a kid’s Kindle isn’t intuitive. It’s also the priciest kid’s model. If color isn’t needed, the non-color Kindle Paperwhite Kids ($230) costs about $70 less.

Key specs:

  • Storage: 16GB

  • Battery life: up to eight weeks

  • Display: 7in, 300 ppi (black-and-white content), 150 ppi (color content)

  • Waterproof: IPX8 (up to 60 minutes in 6.5ft of fresh water)


Nook GlowLight 4 Plus on a table and being held by a reader

If you want a big 8in screen:
Nook GlowLight 4 Plus

$199.99 at Barnes & Noble

The Nook 4 Plus has the largest screen (about 8in) of any e-reader I tested, with the tradeoff being that it weighs a couple of ounces more.

Barnes & Noble’s digital bookstore is also almost perfect, lacking only a single ebook on my list (and it did have the audiobook version of that title). On top of that, prices for Nooks are mostly the same as Amazon’s Kindle line.

It’s a shame that … the overall experience of reading on the Nook can’t compare with Kindle or Kobo devices. The screen is a bit laggier, especially with large PDFs. It also takes the most time and extra steps to get an ebook from the library onto the device. But if you want a large screen, it is still a good ebook reader.

Key specs:

  • Storage: 32GB

  • Battery life: up to three weeks

  • Display: 7.8in, 300 ppi

  • Waterproof: IPX7 (up to 30 minutes in 3ft of fresh water)


Why you should trust me

4 e-readers lined up on a bookshelf
Photograph: Jenny McGrath/The Guardian

As an avid reader all my life, I embraced the convenience of ebooks years ago, starting with an early Kindle model. My local library has a vast catalog, and my virtual queue is always full. Most weeks, I’ll get through a book or two or three . Even when I’m not reading , I’m listening to podcasts to find out which book to pick up next.

I’m also a veteran tech journalist with more than nine years of experience testing and reviewing products. At various times, my house has been cluttered with dozens of smart light bulbs , robot vacuums and artificial Christmas trees (though usually not all at once).

How I tested ebook readers

For more than a month, I tested six ebook readers after researching many, using each for the same amount of time and putting them through the same tests. That included carrying them around in a backpack , knocking them off a nightstand, and even submerging the waterproof devices in water. I also evaluated other factors, such as battery life, charging time and extra features, such as Dropbox integration.

Kobo Clara BW Best Travel in bag 2
Photograph: Jenny McGrath/The Guardian

To test content availability exhaustively, I created a list of 26 popular and more obscure books in a variety of genres, including mystery, romance, sci-fi, and young adult. I noted which books were missing, and calculated the total cost to purchase them all. I also timed how long it took to get an ebook from my local library onto the device itself, loaded them up with PDFs and epub files and connected Bluetooth headphones to listen to audiobooks.

Most of all, I read. I paged through fiction and nonfiction, children’s books, a graphic novel, and scientific PDFs on each device. I scored each device based on how easy it was to navigate, the options of changing fonts and layouts, and the brightness and crispness of the display.

skip past newsletter promotion

After my read-a-thon, I returned the e-readers to their manufacturers or donated them to PCs for People , an organization that provides tech to families, individuals, or nonprofits in need.


Frequently asked questions about e-readers

an e reader plugged in and charging on a table
Photograph: Jenny McGrath/The Guardian

Can I just read on my phone?

Yes: Libby, Kindle, Nook and other apps make it easy to get ebooks on your phone. These absolutely work if you don’t want to buy another gadget. However, e-readers use e-ink screens that mimic the look of paper and strain the eyes less than phone screens. Plus, having a dedicated device without notifications can make for a more distraction-free experience.

What’s an ePub book?

While ebooks come in a few file types, ePubs are among the most common. Kindles use Amazon’s proprietary format, AZW files. Many e-readers also support PDF, DOC and TXT documents.

What’s the best e-reader for library books?

Based on my testing, Kobo devices make it the easiest to browse and download public library books for free thanks to integration with OverDrive, which owns the Libby app. You can peruse titles directly on a Kobo, while Kindle readers require you to browse on your phone using the Libby app.

Do I need Adobe Digital Editions or Calibri to use an e-reader?

It depends on the model. I didn’t need to use Adobe Digital Editions or Calibri to get library books on the Kindles and Kobos I tested. However, I needed both for the Nook. Libby exported its ePubs as ACSM files, which require Adobe Digital Editions. I had to open them in that program to convert them to ePub files I could load into the Nook.

However, my MacBook didn’t register when I had my Nook connected. I used a program called Calibri, which converts ebook file formats. The program recognized the Nook, and I could transfer ePub files from my computer with no problem.

four e-readers piled on a table
Photograph: Jenny McGrath/The Guardian

Do ebook readers work with audiobooks?

Yes, most of the e-readers I tested can play audiobooks. The catch is that you have to pair Bluetooth headphones or speakers – they don’t have built-in speakers.

What’s the best e-reader for highlighting?

If you love sharing your favorite quotes on BookTok or want to keep track of scintillating passages for your book club, all the e-readers I tested compiled my highlights and listed them by chapter. I could also make notes tied to specific text. The Kobo Libra Colour works with a stylus, sold separately, that lets you write notes right on the page.

How much do ebooks cost?

I searched for 26 ebooks across the Amazon, Barnes & Noble and Kobo platforms. They ranged from 99 cents to $30. Some were free to read with Kindle Unlimited or Kobo Plus. The average price was about $12. All the popular books I chose were available through my public library, but none of the obscure books I chose were.

Can you read Kindle books on Kobo or vice versa?

Books purchased from the Kindle, Barnes & Noble and Kobo stores come protected with Digital Rights Management (DRM), which prevents you from sharing them. When I tried to load an Amazon ebook on my Kobo, for example, it showed up as gibberish. There are legally suspect ways around this, but I’m not suggesting you try them.


Banner design for The Filter US

Other pieces you might enjoy from the Filter , the Guardian’s guide to buying fewer, better things:

Explore the Filter

This article was amended on 31 October 2025 because the Kobo Libra Colour cannot play audiobooks without Bluetooth headphones. An earlier version said the e-reader could.


Jenny McGrath is a freelance tech and science journalist with eight years of experience testing tech and home products. She’s dusted her floors with cereal, dumped red wine on carpet samples, and splattered dishes with egg yolk to evaluate vacuums, stain removers and dishwashers. She always has podcast recommendations

Porting my 1993 Amiga game to Godot, with an LLM reading the 68000 assembly

Hacker News
babyloniantwins.com
2026-09-03 10:28:18
Comments...
Original Article

In 1993, in Baghdad, I built a game called Babylonian Twins on an Amiga 500: 512KB of RAM, no hard drive, plugged into a TV. I was an engineering student in my twenties. Pure 68000 assembly, every sprite and every scanline by hand. Murtadha Salman drew the art and Mahir AlSalman composed the music. We were under sanctions. No internet, no game development resources, just one copy of the Amiga Hardware Reference Manual, which I used to program the hardware directly, and electricity a few hours a day. The constant floppy disk swapping (because of the small memory) and the 50°C summers killed my disk drive three times.

Left: 1993, on the Amiga. Right: 2026, the same gateway.

On the Amiga, “by hand” means the game doesn’t ask the operating system for anything while it runs. At startup it saves the interrupt vectors, switches the OS interrupts off and takes the whole machine:

	move.l 	#$dff000,a0			;Base for hardware registers
	lea 	save(pc),a1			;Get the system
	move.w 	#$4000,intena(A0)		;from the AMIGA

“Get the system from the AMIGA” is my comment, from 1993. From that point on the display is the game’s own copper list (the Amiga’s programmable video coprocessor), rewritten on the fly for sprites and sky colours. Tiles move by writing the blitter’s registers directly and waiting on its done flag. The joystick is read straight from the hardware port, and the fire button is one pin on a CIA chip. The OS comes back only between levels, to load the next level’s files from the disk, and then it’s switched off again.

It was the first commercial game made in Iraq, and for a long time a game very few people got to play. Commodore collapsed and sanctions scared off publishers, so the finished game sat on a shelf. An Amiga forum found it in 2008 from my brother’s YouTube uploads and hunted me down for the disks; the thread is still there .

The game has been ported once before, by hand, in 2010. The same team rebuilt it for the iPhone on an engine written from scratch, about 34,000 lines of C++, over months of nights and weekends. Apple and Google featured it, and it reached over two million downloads. That story is here .

I didn’t do this port. I asked for it, played the result every night, said what felt wrong, and made the few decisions that needed somebody who was there in 1993. The file formats and the assembly reading were the AI’s work, and so were the decisions about how to carry thirty-year-old code across, and it went faster than I could follow. This post is what I found when I sat down weeks later and read what had been done to my own game. Some of it was wrong, and I didn’t notice for weeks.

Why I tried again

I’d tried this before. About a year ago I gave an earlier model the same Amiga material and asked it to make sense of my binary level maps. It got there in the end, but it took several rounds and a lot of hints from me.

Then Claude Fable 5 shipped, and I gave it the same files.

The test was deliberate. My guess was that there is little Amiga assembly code in LLM training sets. If the model was better at working things out rather than recalling them, this is where it would show.

The July 4th weekend was coming up, so I planned three steps, each one conditional on the previous working.

Step one, the safe ask: my own 2010 engine, the 34,000 lines of C++, moved into Godot 4. This was the control.

Step two, the unfair ask: the original 72,758 lines of 68000 assembly, for a machine that had gone out of production, with no comments to speak of and nothing in common with the C++. Rebuild that in Godot too, at the Amiga’s original 50 Hz.

Step three, the greedy ask: put the second one inside the first, so buying the modern game gets you the 1993 original as a second thing you can launch.

All three worked. The level format that had taken several rounds and my corrections a year earlier came out in a single pass, with no hints from me.

How it was run

I ran it in Claude Code, so it had a terminal and my filesystem. It could edit files, run the assembler, build the game, launch the game and read what came back. When I say below that it rebuilt my 1993 binaries and checked them, it did that by running vasm and diffing the output.

Early on it added a set of command-line flags to the game so it could play without me:

--level=<name>       load a level directly
--pose=<spec>        put the twins at exact positions
--drive=<spec>       press buttons on a script, frame by frame
--probe              dump switch / gate / door / key state
--screenshot=<path>  render a frame and quit

Which turns “does the jump feel right” into something a machine can read:

drive[btw_jump:2.2] pos=(25.44, 24.04) vel=(0.00, -14.51) ground=false apex_y=22.48

It also had two headless checks it could run before showing me anything: one that compiles every script, and one that builds every level and reports failures. On the Amiga side it drove the real toolchain, vasm to assemble and FS-UAE to boot the result. What wasn’t automated: there was no image comparison on the modern port (it took screenshots, I looked at them), and nothing checked whether the game felt right.

Step one: 34,000 lines of C++ in an evening

Wednesday night, the safe ask. Timestamps, unedited:

22:23  Godot 4 project scaffold, asset sync, TMX level pipeline
22:44  both twins playable — collision, physics, camera, switching
23:19  all 38 entity types ported — full object roster live
00:35  full screen flow — menus, map, story, save, game flows
02:15  exporting to macOS, iOS and Android

Twenty-one minutes from empty project to a playable character. Every line it moved that night was a line I’d written, over months, in 2010. I went to bed confused.

Getting it to feel right took about three days after that: jump arcs and trampoline timing, and hit detection that rewards mashing, fixed in batches on July 2nd, 3rd and 4th.

I wasn’t testing alone. My thirteen-year-old son played every build with me. He’s always known I made this game, it’s a fact about his father he grew up with, but he’d never seen me working on it. The testing turned into a father-and-son thing I didn’t plan, and it’s one of my favourite parts of the whole project.

Same units, same tick

All the gameplay state lives in tile units (1.0 = one 48px tile), and the update runs at a fixed 60 Hz, because the 2010 iOS build ran at 60 Hz. That matters because the original applies drag multiplicatively, every frame:

static const float GROUND_DRAG_FACTOR = 0.85f;
this->velocity.x *= GROUND_DRAG_FACTOR;   // every tick!

Multiply by 0.85 sixty times a second and you get one amount of friction; multiply fifty times a second and you get another. Port it to a different tick rate and every acceleration curve in the game changes. Nothing crashes, it just feels wrong forever, and you won’t find it by reading the diff. At 60 Hz the constant transplants verbatim. This is also why the 1993 rebuild runs at 50 Hz and the modern one at 60: two sets of hand-tuned numbers, each only correct at its own tick. It kept both clocks. I’d have been tempted to tidy them into one.

It didn’t use CharacterBody2D

Godot ships CharacterBody2D and move_and_slide() , and every tutorial tells you to use them. The port used neither for the player. The original has its own hand-written movement code, and rebuilding that on somebody else’s physics would feel slightly wrong in ways that are miserable to track down. The player is a plain Node2D , and the 150-line collision routine came across line for line, including the fudge numbers I picked by feel fifteen years ago and the comments I wrote to my future self:

# Add 0.5 because we want the character's feet to be in the middle of the tile.
var bottom := pos.y + dim.y / 2 + 0.5 + i + fraction
if int(bottom) == int(pos.y + dim.y / 2 + 0.49):
    continue
var right := pos.x
var left := pos.x - dim.x / 4      # asymmetric probes!

Nothing tidied up the stray 0.49 . There are no tests and no docs; those comments are the spec.

Step two: the 68000 assembly

By Sunday afternoon, July 5th, I handed over the thing I actually wanted to test. 72,758 lines across 26 files, written for a machine with 512 KB of memory, by me, for me, with the commenting habits of somebody who never expected another person to read it. No documentation. A 2008 transfer to modern storage had shortened every long filename, so every include pointed at names that no longer existed. One of the five level source files is cut off partway through a data table. There’s no other copy.

Before porting anything, it made the 1993 sources assemble again, using vasm on an Apple Silicon Mac, and kept going until the output was byte-identical to the binaries that shipped.

14:34  import the Amiga sources, assets, references
14:49  vasm toolchain reproduces the shipped binaries byte-identically
15:20  disk images rebuilt
15:42  the rebuilt demo boots and plays in FS-UAE

Fifteen minutes from a folder of files to the first rebuild that matched the shipped bytes. I wrote these in ASM-One, whose dialect differs from vasm’s in ways that change the bytes: ASM-One encodes cmp #4,d0 as CMPI, vasm picks a different, equally valid encoding, so telling it not to optimise is necessary and not sufficient. Rather than edit my sources it wrote a preprocessing pass that bridges five such differences, and rebuilt the broken filename mapping file by file.

The expensive one was org . With no linker and no relocation, the level source lays out the Amiga’s memory by hand, address by address:

org $6a000				; this section lives at address $6a000
Mapadd:
	incbin"btwins:binary/L1/Map1.b"	;Game Map
	org mapadd+73*1024		; skip to 73 KB past the map's start
GLBtable:
	dc.w $3333,50,20,100		; one object record begins
	dc.w SahamR-grb,26		;Routine,Length
	...
org glbtable+2*1024			; the object table gets exactly 2 KB

The level-one map uses 74,400 of those 74,752 bytes, a margin of 352, and nothing checked it except me, in 1993. ( SahamR-grb attaches an object’s behaviour as a named offset; saham is Arabic for arrow.) ASM-One’s org can also move the location counter backwards, which vasm can’t. The first workaround got one case wrong: a ds.b 800 inside a rewound block, which ASM-One treats as “skip 800 bytes”, was written out as 800 bytes of zeros. Everything after that point in the file, the copper list included, sat 944 bytes away from where the shipped binary had it. The game assembled and booted, and drew the wrong thing.

Even after that, some chunks still wouldn’t match, by about 108 bytes scattered through the variable area. Those bytes explained where the shipped files came from. ASM-One assembles into memory, and the game got onto disk by saving that memory out, after the game had been run. So the shipped files are a snapshot of a game that had already been running, not clean assembler output. A fresh assembly has zeros in those variables, because nothing has set them yet; the shipped disk has whatever they held on the machine when it was saved. The code writes them before it reads them, so the zeros are harmless.

At the time I read that line, moved on, and waited for the actual game. It took me weeks to see that this was the most important thing in the project, and that nobody had asked for it. From then on, every claim about this game could be settled by comparing bytes. I wouldn’t have done it myself. I already had the binaries, and in eighteen years rebuilding them from source never seemed worth an afternoon.

The formats

For every format it went to the code that reads the bytes and worked backwards from that. The level loader is 1,652 lines of uncommented 68000, which is why I’d always reached for a hex editor instead.

The levels

A level is a grid of tiles: a long list of numbers, where each number means “put picture 47 here”, in my own private 1993 layout. This is the format the older model and I had ground through a year earlier.

Here is the full set of tiles a level is built from, 256 of them, 16×16 pixels each, for level one:

The complete 16x16 tile set for level one of the 1993 Amiga game: stone blocks, ladders, water, palm fronds, decorative brickwork

And a slice of level one, assembled from those tiles:

A horizontal slice of level one rendered from the extracted map data

The input is a list of numbers with no header and no dimensions, inside a compressed chunk. This time I didn’t explain anything. It found the drawing routine, read how the grid was walked, worked out the width and height from constants elsewhere in the file, and produced correct maps for all five levels on the first attempt.

Then it re-rendered each level from its own extracted data and compared the result, pixel by pixel, against full-level captures I had made in 2020. Where they didn’t match, it went looking for the cause and found two copper effects: the sky gradient and the water colour cycle. With those two accounted for: five full-level images, zero differing pixels. Level one alone is 600 tiles wide, 9,600 pixels.

Map cell properties

Drawing the level is only half of what a map cell does. Each cell is one 16-bit word, and the picture is the smaller part of it:

one map cell, 16 bits:

  bits 15..10   the property: what this square DOES       (6 bits)
  bit 8         which of the two tile banks to use        (1 bit)
  bits 7..0     which of the 256 tile pictures to draw    (8 bits)

The property is the level’s invisible physics. 1 is solid ground. 2 and 3 can be climbed. 10 to 13 all mean “this hurts”, four codes because knockback needs a direction. 14 kills outright. 63 is a door. None of this is written down anywhere. It was recovered because two routines read the same word and each one reveals its own half: the draw loop masks off the low byte, and the collision check does the opposite:

	move.w	(a1),d6			; the same cell
	and.w	#$fc00,d6		; keep the top 6 bits
	lsr.w	#2,d6
	lsr.w	#8,d6			; d6 = the property, 0..63
	bsr	cbCheck			; 2 or 3?  you can climb this
	bsr	Checkrmh		; 10..13?  this hurts, and from which side

Checkrmh hands the painful cases to a label called rmhEnjury , which is 1993 me spelling “injury”.

Those bits were painted in an editor. Before the game could be built I had to build the tool that builds it: MEDITOR.S , 1,254 lines of assembly, dated by its own header, in my 1993 English:

; ***********************************************************************
; *		This Program was written in four days			*
; * 			1993-2-8/7/6/5					*
; *      I made it to help me to make a map to my first serious		*
; *				Game 					*
; ***********************************************************************

Four days in February 1993. Paint tiles with the mouse, pick a property number on the panel’s CURRENT FLAG counter, stamp it onto cells with PUT FLAG, and a flag view marks every cell carrying the selected number. While writing this post, I asked the model to run the map editor and get a screenshot. It assembled the 1993 source with a modern assembler, laid the shipped Level 2 data out in memory where the editor expects it, and booted the result in an emulator.

My 1993 map editor running in 2026, editing the real Level 2, with flag 1 (solid) selected: the waterfall scene with the solid ground marked by the flag view and the CURRENT FLAG counter reading 0001

My own tool at thirty-three years old, editing the real Level 2, flag view on. CURRENT FLAG reads 0001, solid, and the ground you can stand on is marked while the decoration you walk through isn’t. The panel says 1994: the panel artwork is a separate bitmap file the editor loads, and the copy that survived is a later one than the February 1993 code.

The other name on the panel, Udai, was my partner in Mesopotamia Software, which is what we called ourselves. He was building a game of his own at the time. I wrote the editor, for both of us, but its design was worked out between us so one tool could serve both games. His game was never finished.

Object tables

Enemies aren’t in the map. The world is stored one screen at a time, 25 tiles by 20, and every screen has a small table of the objects on it. My 1993 comments explain the markers:

;	$1111=this is a Screen but it contain nothing or(End of Screen)
;	$2222=this is an object but do not draw it (dead)go to next
;	other=this is an object,draw it and go to the next

Scr0:	dc.w $3333,50,23,17		; a live object: frame, then x, y
	dc.w hiddenwallR-lrb,20		; its behaviour: a routine, as an offset
	dc.w 0
	dc.w 0
	dc.w 7
	dc.w 10				; parameters only that routine understands
	dc.w $3333,50,12,14
	dc.w GreatTR-LRb,16,GkeyT-GTT,1
	dc.w $1111			; end of this screen

An enemy is a row of words: a marker, a frame, a position inside its screen, then its behaviour. hiddenwallR-lrb is the crumbling-wall routine, attached as an offset from a base label, the same trick as the arrow thrower earlier. The words after it are parameters that mean whatever that routine wants them to mean. Nothing in the file says which word is which, so it found the routine that walks these tables every frame and let it name the fields, then converted every object in all five levels to world coordinates and checked them against the rendered maps.

GAME.S

Most of the data files scramble their 16-byte headers with a key stored inside the file, a 1993 trick to keep disk editors out. The retail loader, GAME.S , has no unscrambling step at all. It read that as a clue: GAME.S was written before the scrambling was added, so it is an older file. That clue is what later let it recover the lost two-disk retail set, from a sector map inside that same file.

The doors aren’t in the map

I was sure they were.

Load a level’s tile map and there are holes where every door should be, with no door tile in them, open or closed. An 18-byte object record stamps them onto the map at runtime, a 1×4 tile column, from a table:

closed  $528  $53C  $550  $564      ; solid, blocks the way
open    $129  $13D  $151  $165      ; passable — exactly one sheet-column right

The map data says there’s no door. The level code says there is. For thirty-three years I’d have told you the map is the source of truth and doors are map data, and I’d never have looked. It held both facts, found the routine that reconciles them, and came back with the design: doors are drawn by code at runtime; they were never painted into the map in the editor. That’s why the obvious port of the level data produces a tower with doorways full of sky.

The copper sky

In every level, colour index 31 is the sky, and nothing in the tile art ever paints it. The tile atlas renders it transparent, and behind it the copper repaints the background colour on chosen scanlines to make a vertical gradient. The gradient sits in the level source as a plain list of colours. This is the entire sky of the second level:

backgndcol:
col1:   dc.w    $09FF,$09FF,$09FF,$09FF,$09EF,$09EF,$0ADF,$0ADF
        dc.w    $0ACF,$0ACF,$0ABF,$0BBF,$0BBF,$0CBF,$0CBF,$0DCF
        dc.w    $0DCF,$0ECF,$0DCF,$0DCF,$0CCF,$0CCF,$0CDF,$0CDF

Read down the list and the sky goes from pale blue to warm near the horizon.

The 24 colour words of the level-2 sky table rendered as vertical bands, from pale cyan at the top of the screen to warm lilac near the horizon

The same 24 words, rendered. Left is the top of the screen.

The first rebuild missed it, and the levels looked fine. Flat, in a way I couldn’t name. The pixel comparison refused to go green, and the gradient went back in.

The level-2 verification diff: white marks every differing pixel — the whole sky and the animated water, missing from the first rebuild

The diff that would not go green: white is every pixel the first rebuild got wrong, the copper's sky and water.

Sprite sheet ambiguity

Amiga sprite sheets are planar (five separate 1-bit bitplanes in plane-major strips, plus a transparency mask), and all of that was worked out from the draw routines and the org arithmetic. Sheet sizes of the form frames * width * height * 2 * 5 are ambiguous: that 2 could mean double-width frames, or two stacked rows, one per facing direction. Both readings fit every byte in the file. It’s two facing rows; that was my choice in 1993.

The decoded 1993 sprite sheet: two stacked rows of the same six-frame run, one row per facing direction

Two stacked rows, one per facing direction, drawn frame by frame, not mirrored.

It flagged the ambiguity and asked.

The same twin's six-frame run cycle: the 1993 Amiga pixels above, the 2026 high-resolution art below

The same twin, the same six frames: 1993 above, 2026 below.

That was the last format. From there the 1993 game went into Godot the same way the C++ had, behaviour rewritten in GDScript at the original 50 Hz.

Step three: the old game inside the new one

The greedy ask took one evening, 21:58 to 23:43. The retro game runs as a guest, with its own namespace and scene host, and the engine switches to 50 Hz on the way in and back to 60 on the way out. It’s fiddly, and it was done in one sitting. I’d assumed the feature would eat a week and get cut. It’s the reason the Steam version ships with the 1993 game inside it.

The same palace doorway in both games: on the left the 1993 Amiga version in 4:3 with chunky tiles, on the right the 2026 Godot build in widescreen with the same doorway redrawn in detail

The same doorway in both games, running in the same program. Left: 1993. Right: 2026.

The game you download contains no Amiga code. The data, the packed chunks and planar graphics and the music, was decoded once, on my machine, by Python scripts, into ordinary PNG, WAV and JSON. The behaviour (how a guard patrols, when a door opens) was rewritten in the engine’s own language. If you want the real thing, that’s the free disk image at the end of this post and an emulator.

Where it was wrong

The guard bug

In level 2 you walk along a corridor. Waterfall to your left, stone pillar ahead. No enemy on the screen, nothing approaching, and you take a hit. What hit you was a spear-carrying soldier standing thirteen tiles above you, on a grass ledge next to a palm tree, with solid rock in between.

Two floors of the same column of level 2. The guard stands in a red box at tile (155,90) on a grass ledge by a palm tree; a yellow arrow runs straight down through solid rock to a corridor at y103 to 108, where the player was being hurt

He’s a doorman. He shoves whoever stands at his feet. In the original that check is fenced on both sides:

        sub.w   d1,d4           ; d4 = vertical distance to the kid
        cmp.w   #4,d4
        bpl     Sg.Far          ; 4 or more rows below? not my problem
        cmp.w   #-2,d4
        bmi     SG.far          ; too far above? also not my problem

The port kept the lower bound and dropped the upper one. A shove meant to cover the guard’s own three rows now ran the whole height of the map column beneath him, through the floor, into a corridor he doesn’t appear in.

The doorman from the 1993 sprite data: a single standing frame, 48 by 64 pixels, spear in hand

The doorman himself, from the 1993 sheet.

Smaller ones: every level has a second tile layer the original never renders; it’s the hidden artwork revealed when a door opens or a fake wall crumbles. Render it “faithfully” and every secret passage stands open from the start. Move enemies before players instead of after, and a trampoline jump gets counted twice, twenty tiles into the air. A door listed "p1,p2,p3,p4" , meaning all four palms, was read as a single key with a strange name, and the tutorial exit never opened. A sound-loop length computed as stereo when the effects are mono cut every sound off halfway and restarted it.

The one that cost the most was a feature I asked for in the 1993 build: let the twins swap places at any distance. The proximity check came out, and the statues started corrupting. It went back into the routine and came out with the real answer, which wasn’t what I expected: that check was never a distance limit. The idle twin is stamped into the map itself as a statue, and two statues stamped on top of each other eat each other’s tiles. The guard went back in, and I killed the feature on the 1993 build.

I made the same kind of mistake myself in 2010, slowly, over months.

Then it shipped it

Then it did the release work: screenshots at five pixel sizes in eleven languages, a preview video, store text, icons in six shapes, uploaded to three stores that disagree about everything. I’ve shipped this game before, so I know how many evenings that part costs.

The screenshots come out of the game itself. It launches the real game at each store’s pixel size, in the language it needs, walks the character to a chosen spot, takes the shot, then draws the caption band with the game’s own fonts. AI never renders the text in a store image. The captions are real fonts and real translated strings, or the image doesn’t ship. Once it did break, and the Russian and Korean captions came out as rows of empty boxes, which I saw in the output folder before uploading.

My complaint about Steam is that it has many fields in its forms, many more than the Apple App Store and the Google Play Console. In addition, it doesn’t have an API to make the process of metadata updates easy. For iOS and Android there are proper APIs and it used them. Steam has a web dashboard, so it drove the browser: store page fields, achievements, the demo checklist, artwork uploads, clicking through Steamworks. I do the login, and I press anything that submits, publishes, prices or releases. It fills in the forms.

It reads my reviews too. The official Google Play API only gives you the last seven days, which is useless for a game with fifteen years of reviews, so it pulls the rest with the public scraper, one language at a time. Then it read all of them and listed which ones described real defects. I approved the list.

One of them was a one-star review on Google Play, bad spelling, the kind you scroll past:

“cant get through door on level one. opens but level dowsnt end”

Read literally, it’s a bug report, and it was right. In my game, opening the exit and walking through it are two separate actions, and the prompt that says so exists in all eleven languages, placed in exactly two of my eighteen levels. One of the levels missing it was the last free one. So the player deciding whether this game is worth paying for was standing in front of an open door with no way to know what to do, and concluded the game was broken.

I never found that in fifteen years, and neither did my testers or two rebuilds. It took a stranger’s one-star review. The fix went out as 2.0.3 on both stores. I keep that review.

The trampoline bug

“The trampoline feels too high.” That was the whole report, from me, playing the build at night. The constants checked out: a twenty-line simulation of the original’s integrator predicted 19.1 tiles, and the build measured 19.5. The physics was right.

It was input semantics. The 2010 build was event-driven, and because of a workaround for a tvOS quirk we shipped years ago, a held jump button read as released until you physically pressed again. Godot polls input, and kept reporting the hold. Reproducing that accident is what makes the high bounce need a fresh, well-timed press, which is how the game played on a phone, and what my hands were expecting.

The 2010 source doesn’t record this, because from the source’s point of view nothing unusual is happening. You’d have to have been there, holding the phone, working around a bug in a television.

The original, released

After thirty-three years, the full original is out, free on itch.io . Boot it in FS-UAE, WinUAE, or on real hardware. The Definitive Edition is on iOS and Android now, has a free demo on Steam, and the full Steam release (Windows, Mac, Linux) lands this fall, with the 1993 game inside it as a second launch option.

The port was Claude Fable 5 running in Claude Code; I asked, played, and decided. This post went the same way. I gave it my notes from the port, what I remember about the key parts of the old game (the map encoding, the object tables), and the repos for both the Amiga version and the port, and it wrote a first draft. I spent a week editing it line by line. The code, timestamps and screenshots are real. The part I’m least sure of is the 108 bytes: the model told me the shipped files were a memory snapshot saved after a run, and that the code writes those variables before it reads them. I read that, moved on, and have never checked it myself.

Five horizontal slices, one per level: the dungeon, the orchard, the holy gardens, the tower, and the blue lion-frieze walls

One slice from each of the five levels, rendered from the extracted map data.


Babylonian Twins: Definitive Edition comes to Steam this fall — wishlist it here . Free demo available now · live today on iOS and Android · the original 1993 ADF is free on itch .

[$] Recent work in memory tiering

Linux Weekly News
lwn.net
2026-09-03 10:11:26
Tiered-memory systems are built with multiple types of memory, each of which has different performance characteristics. In addition to the usual DRAM, a tiered system might also provide faster high-bandwidth memory or slower CXL memory. On these systems, the placement of memory allocations has a s...
Original Article
The page you have tried to view ( Recent work in memory tiering ) is currently available to LWN subscribers only. Reader subscriptions are a necessary way to fund the continued existence of LWN and the quality of its content.

If you are already an LWN.net subscriber, please log in with the form below to read this content.

Please consider subscribing to LWN . An LWN subscription provides numerous benefits, including access to restricted content and the warm feeling of knowing that you are helping to keep LWN alive.

(Alternatively, this item will become freely available on September 17, 2026)

Announcing Rust 1.98.1

Lobsters
blog.rust-lang.org
2026-09-03 10:03:38
Comments...
Original Article

The Rust team has published a new point release of Rust, 1.98.1. Rust is a programming language that is empowering everyone to build reliable and efficient software.

If you have a previous version of Rust installed via rustup, getting Rust 1.98.1 is as easy as:

rustup update stable

If you don't have it already, you can get rustup from the appropriate page on our website.

What's in 1.98.1

Rust 1.98.1 fixes a miscompilation in vtable generation .

In Rust 1.98.0, in some circumstances, rustc would incorrectly generate a trait object vtable with a null pointer where a function pointer should be. This leads to undefined behavior in the emitted code. In some cases this may 'just' cause segfaults due to the null pointer being loaded, but it is possible for it to be justification for arbitrary effects (as is typical for UB).

If you'd like to help us out by testing future releases, you might consider using the beta ( rustup default beta ) and nightly ( rustup default nightly ) channels locally and in your CI. Please report any bugs you might come across!

Contributors to 1.98.1

Many people came together to create Rust 1.98.1. We couldn't have done it without all of you. Thanks!

You Don't Need Initial-Scale In Your HTML

Lobsters
vale.rocks
2026-09-03 10:03:31
Comments...
Original Article

A line you will find in the head of almost every single HTML document: <meta name="viewport" content="width=device-width, initial-scale=1.0">

The line came into relevance after the first iPhone launched in 2007. As part of the same keynote at Macworld 2007 in which Steve Jobs unveiled the iPhone, he showed off the phone’s web browser loading the New York Times and Amazon. As he proclaimed on stage, the iPhone did not load mobile versions of the sites but instead the full desktop versions.

Mobile versions of websites at the time were usually on their own subdomain or path and were extremely simplified experiences. The iPhone ran the full versions. However, these sites weren’t designed for such small screens. Ethan Marcotte wouldn’t coin ‘Responsive Web Design’ until 2010 . The intended interaction was for the user to zoom in and pan around sites designed for desktop.

To allow sites designed for small screens to scale nicely, Apple introduced the viewport meta tag as explained in the Safari Web Content Guide . The viewport meta tag was eventually picked up more universally across browsers such that it became the widely supported way to make a site responsive.

Though width=device-width handled things broadly, initial-scale=1.0 was important for many years to resolve undesired zooming behaviour in older versions of iOS and some other browsers. However, this isn’t the case any more. All the problems are no longer present and don’t need working around.

I can say with confidence that you do not need to declare initial-scale=1.0 if targeting modern browsers. All you need is <meta name="viewport" content="width=device-width"> . That’s 19 bytes you can shave from your document head. Maybe not much in isolation, but when you consider the scale of the web, it adds up.

The best fans to keep you cool in 2026 – tried and tested

Guardian
www.theguardian.com
2026-09-03 10:00:41
Missed out on a fan this summer? Chill your space with our pick of the best still in stock, including tower and misting models • The best portable neck and handheld fans• Dyson HushJet Mini Cool fan review Our world is getting hotter. Summer heatwaves are so frequent, they’re stretching the bounds o...
Original Article

O ur world is getting hotter . Summer heatwaves are so frequent, they’re stretching the bounds of what we think of as summer. Hot-and-bothered home working and sweaty, sleepless nights are now alarmingly common.

Get a good fan and you can dodge the temptation of air conditioning. Aircon is incredibly effective, but it uses a lot of electricity … and burning fossil fuels is how we got into this mess in the first place. Save money and carbon by opting for a great fan instead.

Fans are more energy efficient than aircon. A typical portable air conditioner uses 1,000W of electricity, which would cost about 26p an hour to run. The fans I tested used between 8W and 60W; my favourite, the AirCraft Lume , used 18W on its top setting. You could run it on max for 56 hours, and it would still use no more electricity (money, carbon) than a single aircon unit going for an hour.

I tested 20 fans of all shapes and sizes, so you can pick the best one for you. I tested them for size, noise, power use and, of course, how much they cool you down. I also tested a few “evaporative coolers”, which use water to cool the air blowing at you while using significantly less energy than aircon.


Still in stock

Following this summer’s fossil-fuel charged heatwaves, many of our favourite fans are out of stock. Our favourite misting fan, the Shark FlexBreeze Pro Mist, is still in stock in blush pink, however.

£259.99 at Shark

Our best powerful tower fan, the Meaco Sefte Smart 36in, is also available. It’s slim, quiet and one of the most powerful fans we tested.

£99.99 at Meaco

For smaller spaces, our best mini tower fan, the Meaco Sefte 19in, is compact and energy efficient, while still packing a decent cooling punch.

£69.99 at Meaco

Why you should trust me

I’m an award-winning consumer tech journalist with decades of experience testing gadgets. I’m also a menopausal woman in her 50s who honestly can’t remember the last time she felt cold: I think that might be why we gravitate to wild swimming in middle age. Oh, and I have a degree in engineering. So I’m triply qualified to put these fans through their paces, scientifically and subjectively.

How I tested

Testing fans. Dyson on test
An anemometer was used to measure the air speed each fan generates on its top setting. Photograph: Caramel Quin/The Guardian

I chose 20 fans, each from different brands, aiming for a mix of new and highly rated models plus a few stellar bargains. I wanted to make sure there was something for everyone before I put them through their paces.

I used a power meter to measure how much electricity (and therefore money and carbon) the fans use, an anemometer to measure the air speed they generate on the top setting, and the Sound Meter app to measure the noise on the top setting (they were all too quiet to register on their lowest).

I measured everything from 1m away, although in reality, you’ll probably position a tower or pedestal fan farther away and a desk fan closer to you. That means the noise a desk fan makes matters more.

I also measured them myself, as sometimes the official specs can be misleading or wrong. For example, I measured a tower fan that was supposedly 17cm wide, only to find that wasn’t including the base. Here I’ve stuck with each fan’s largest dimensions, including their footprint.

I used a thermometer to measure the impact of the evaporative coolers I tested, and took note of everything from how cooling each of the fans felt, how annoying the noise was and how good the controls were. I also considered how they looked and how small they packed away, as well as the price tag.

All the fans that weren’t returned to the manufacturers were donated to Furnishing Futures , a charity that furnishes the empty social homes in which women and children are placed after domestic abuse.


The best fans in 2026

A selection of fans is organised on a wooden floor in front of white cupboards
Photograph: Caramel Quin/The Guardian

Best quiet fan for the bedroom and best overall:
AirCraft Lume

What we love
Quiet, elegant, powerful cooling and a backlight

What we don’t love
So quiet, it’s easy to forget to turn it off

AirCraft Lume
Photograph: Caramel Quin/The Guardian
£149 at AirCraft

Preorder now for delivery in early September

This pedestal fan was hard to fault, with an elegant design that boasts a dimmable backlight (three brightness levels or you can turn it off, all with the remote control). It’s billed as height adjustable, but rather than scooting up and down, you can remove the bottom pole to convert it into a 63cm desk fan. There’s an LED display and touch controls on the front, and other features include a 12-hour timer and a sleep mode.

Of all I tested, this is probably the best fan for sleeping: it’s the best for low noise relative to wind speed. Pick a lower setting for silent cooling, a higher setting if you’re happy to doze off to the white noise, or use the sleep button if you’d like it to gradually reduce power in the night. I found the lower settings cooling enough to get to sleep on a hot night during a heatwave.

Why we love it
When I’m working from home or relaxing (I can’t say chilling out when it’s been 30C+), the AirCraft Lume is the fan that I reach for. I love it for many reasons. It’s light but with a reassuringly heavy base, giving it Weeble-like stability: it’s difficult to knock over. It packs away pretty small for the winter because the pole comes apart. I also liked that the packaging is almost plastic-free.

It oscillates both horizontally and vertically, so it can circulate air nicely around a whole room. Most importantly of all, this fan can really shift air – its 5.9m/s (metres a second) result was the best on test, and you can really feel it. During a recent heatwave, I found the powerful breeze genuinely cooling. And it’s quiet: in fact, I can’t hear it at all on levels 1-5, so I need to be careful that I remember to turn off the fan when I step away. All for a reasonable price, too.

It’s a shame that … there’s nowhere to stow the remote control when it’s not in use.

Style: pedestal (or desk)
Dimensions: 37 x 28 x 95cm (WDH)
Number of speeds: 12
Remote control? Yes
Peak noise level on test: 55dB
Power use on top setting: 18W
Air speed on top setting: 5.9 metres a second (m/s)

AirCraft

Lume

£149

What we love
Quiet, elegant, powerful cooling and a backlight

What we don’t love
So quiet, it’s easy to forget to turn it off


Best powerful tower fan:
Meaco Sefte smart 36in tower fan

Meaco

Sefte smart 36in tower fan

£99.99

What we love
It’s affordable, elegant, powerful and quiet

What we don’t love
Hard to fault, unless you dislike tower fans

Meaco Sefte smart 36in tower fan
£99.99 at Meaco

Tower fans aren’t known for their elegance, but this looks great. It’s unobtrusive and slim: 14cm wide and 16cm deep (the larger measurements below are just the size of the base to keep it from toppling over). It takes seven screws to assemble.

A small but clear display at the top tells you temperature, fan speed and mode, and its 12 speeds offer everything from gentle cooling to a big blast of air. Airflow is pleasantly wide, too, so your whole body is cooled. It can also oscillate (rotate on its base) through 45, 90, 135 or 180 degrees.

Why we love it
This slim tower fan is impressively cooling. On setting 12, it’s one of the most powerful fans I’ve tested and very quiet. And even on 1, it’s still cooling. The circular remote control has glow-in-the-dark buttons and is magnetic, so you can store it on top of the fan or even stick it on the fridge.

Night mode turns off the display, then gradually reduces speed every hour. Meanwhile, Eco mode saves energy by adjusting the speed automatically depending on the current temperature of the room. There’s also a timer that shuts it off after 1-12 hours. App control lets you create schedules, too, or manage the fan remotely.

It’s a shame that … this wasn’t available earlier in the summer.

Style: tower
Dimensions: 26 x 26 x 93cm (WDH)
Number of speeds: 12
Remote control? Yes
Peak noise level on test: 40dB
Power use on top setting: 30W
Air speed on top setting: 5.2m/s

Meaco

Sefte smart 36in tower fan

£99.99

What we love
It’s affordable, elegant, powerful and quiet

What we don’t love
Hard to fault, unless you dislike tower fans


Best mini tower fan:
Meaco Sefte 19in tower fan

Meaco

Sefte 19in tower fan

from £69.99

What we love
It’s small and energy efficient

What we don’t love
It’s louder than Meaco’s taller tower fan

Meaco Sefte 19in tower fan
£69.99 at Meaco
£69.99 at John Lewis

This is the smaller sibling of the 36in Meaco fan above, and it’s much shorter at just 49cm. It’s equally good-looking and slim, with the tower itself measuring 14cm wide and 16cm deep. It’s less powerful than the 36in model, yet slightly louder. Even on the highest of its 12 speeds, though, it’s not too annoying, and it too can oscillate through 45, 90, 135 or 180 degrees.

Why we love it
This diminutive fan seems designed to sit on a desk or bedside table, but in my tests I found it works well on the floor too, whether pointed directly at you for cooling, or oscillating to circulate the air in the room. The remote control is circular, magnetic and comes with glow-in-the-dark buttons. The display on top of the fan indicates temperature and mode. It also shows oscillation intuitively: as you press the buttons, icons show how widely it will turn.

There are no smart features, so there’s no scheduling or ability to control it from another room. It does offer Night and Eco modes, though, plus a timer. Power consumption is low at 16W, too, so it’s energy efficient as well as being powerful. That means it costs just pennies to run.

It’s a shame that … it’s louder than some fans.

Style: tower
Dimensions: 17 x 18 x 49cm (WDH)
Number of speeds: 12
Remote control? Yes
Peak noise level on test: 65dB
Power use on top setting: 16W
Air speed on top setting: 4.9m/s

Meaco

Sefte 19in tower fan

from £69.99

What we love
It’s small and energy efficient

What we don’t love
It’s louder than Meaco’s taller tower fan


Best budget fan and best desk fan:
Devola desk fan

Devola

Desk fan

from £64.99

What we love
Small but mighty, affordable too

What we don’t love
The display is hard to read because it faces up

Devola Platinum Low Noise DC 9 inch Air Circulator Fan White DVF9DCFAN
£64.99 at Devola
£74.99 at Amazon

Currently out of stock

This affordable desk fan punches well above its weight, with good features and powerful airflow. It has a display, touch controls, a remote, a timer and sleep mode. You can choose vertical oscillation (90 degrees), horizontal oscillation (80 degrees) or use both to circulate the air in a room. Not bad for a humble desk fan.

Why we love it
It’s a bargain powerhouse, producing a substantial wind. I measured an air speed of 4m/s, which was among the best on test. It certainly felt cooling.

I couldn’t hear the Devola on the first three of its nine speeds, despite being powerfully cooling, and even when the noise got louder on higher settings, it wasn’t too annoying. In fact, while the AirCraft Lume is my favourite bedside fan, the Devola perched on a bedside table does a good job on a budget. It’s powerfully cooling, inaudible on lower settings (1-3 out of 9) and on high settings, the white noise is OK to go to sleep to. Just don’t use the sleep setting: it’s noisier than it should be, so picking a medium setting worked best. Even the high settings provide a level of white noise I could go to sleep to.

It’s a shame that … the display is on the base facing upwards, so you can’t see it unless you’re nearby. There was no instruction manual in the box, either, although I found it straightforward to use.

Style: desk
Dimensions: 30 x 21 x 31cm (WDH)
Number of speeds: 9
Remote control? Yes
Peak noise level on test: 50dB
Power use on top setting: 16W
Air speed on top setting: 4m/s

Devola

Desk fan

from £64.99

What we love
Small but mighty, affordable too

What we don’t love
The display is hard to read because it faces up


Best fan for cooling:
Dreo TurboCool misting fan 765S

Dreo

TurboCool misting fan 765S

£199.99

What we love
Cooling on a hot day, yet uses only pennies to run

What we don’t love
Remote buttons are hard to read in bright light

Caramel Quin testing fans. DREO TurboCool Misting Fan
Photograph: Caramel Quin/The Guardian
£199.99 at Amazon

Currently out of stock

I tested this in May on what was then the hottest day of 2026. There were others. And another. That’s why it’s worth ordering a good fan even if there’s a long wait for delivery … for next time. It was 31C in my front room, and I was really, really happy to be testing fans. For a sense of how hot it was, just look at the dog in the photo.

The Dreo is a black tower fan with 12 speeds and a remote control, which can oscillate from side to side. It’s fairly loud at top whack and sounds like a fan: white noise, but not too annoying. It’s powerful on the top setting of 12, but 4 was still cooling, and 6 was great.

Why we love it
Unusually, the Dreo has a six-litre water tank and can add a fine mist to the air. This comes out of four jets, two on each side of the fan. It’s cooling if the air isn’t too humid.

The only other fan I’ve tested that does this is the Shark FlexBreeze below, and that one’s mist can only be used outdoors because it gets everything wet. But the Dreo is safe to use indoors. I tried its top setting (fan 12, mist 4), and sitting 2m away, I felt the occasional, pleasant cool drop of water, but the floor didn’t get wet, and neither did the anemometer, placed between me and the fan. I had no fears for my laptop.

The laptop might have even worked a bit better – I certainly did – because the water cooled the air. It was an impressive 3C cooler after 10 minutes. Power consumption went up from 43W to 85W, but it was the best I’d felt all day. I tried again on settings 9/3, and the effect was still pleasant and cooling (I settled on 6/2 and 40W – I’m known for my asceticism).

Even at full power, fans don’t use much electricity. The energy price cap for 1 July to 30 September 2026 is 26.11p per kWh, so if you run the Dreo at its top 85W setting, it costs 2p an hour to run. You could run it non-stop for a whole week in a heatwave, and it would add just £3.51 to your electricity bill. That’s cheaper than a tub of good ice-cream.

My only annoyance was the remote control. It glows in the dark, but the white-on-white icons on the buttons were hard to read by day. The app’s great, though, and lets you do even more, including scheduling and adding voice control (Alexa, Google).

It’s a shame that … the remote control buttons are hard to read.

Style: tower
Dimensions: 27 x 27 x 111cm (WDH)
Number of speeds: 12
Remote control? Yes
Peak noise level on test: 65dB
Power use on top fan setting: 85W
Air speed on top setting: 5.7m/s

Dreo

TurboCool misting fan 765S

£199.99

What we love
Cooling on a hot day, yet uses only pennies to run

What we don’t love
Remote buttons are hard to read in bright light


Best misting fan:
Shark FlexBreeze Pro Mist FA300UK

Shark

FlexBreeze Pro Mist FA300UK

from £259.99

What we love
The water mist is cooling on a hot day

What we don’t love
For outside use only because everything gets damp

Shark FlexBreeze Pro Mist Cordless Indoor & Outdoor Fan, 20m Cooling Reach
£259.99 at Shark
£303.19 at Amazon

This Shark model is more than a pedestal fan. You can remove the pole to convert it to a desk fan. You can unplug it for cordless use. You can even add the included five-litre water tank for misting outdoors. And you can do any permutation of these things. The design is great, and the remote control stows on the back magnetically.

Despite its misting feature, it’s not technically an evaporative cooler , since you can only use it with water outdoors. It sprays a fine mist of water into the air in front of the fan: you get cool, but everything gets a bit damp.

Why we love it
It’s versatile. Plug it in for everyday use, then carry it elsewhere (there’s a large top handle) to use as a cordless fan, or for a cooling mist on the patio while you’re entertaining outdoors. The cordless runtime is quoted as two to 24 hours, depending on fan speed, and charging time is five to six hours. Power use was impressively low: 14W on the top fan setting, 7W to charge the battery, 21W to do both at once.

I compared it with the test-winning AirCraft Lume, which costs £70 less at RRP. Both are a similar size and design. The Shark has fewer fan speeds: five as opposed to the AirCraft’s 12. The design looks similar, but the head of the Shark is much deeper (33cm compared with 15cm). And it only oscillates side to side rather than up and down; you can point it at various angles, though.

At 4.7m/s, the top air speed is impressive, although not quite as high as the AirCraft’s. It’s quiet enough that you can’t even hear it on the first two of its five speeds, whereas peak volume is exactly the same as the AirCraft.

Is it worth £70 more when both are full price? If you’ll make use of it being cordless or plan to use it outdoors, then yes. If not, stick with the AirCraft.

It’s a shame that … the misting can only be used outside.

Style: pedestal (or desk)
Dimensions: 35 x 35 x 95cm (WDH)
Number of speeds: 5
Remote control? Yes
Peak noise level on test: 55dB
Power use on top setting: 21W
Air speed on top setting: 4.7m/s

Shark

FlexBreeze Pro Mist FA300UK

from £259.99

What we love
The water mist is cooling on a hot day

What we don’t love
For outside use only because everything gets damp


Best quiet fan with aromatherapy:
ProBreeze AirFlo 43in smart hybrid pedestal fan

ProBreeze

AirFlo 43in smart hybrid pedestal fan

from £169.99

What we love
It features aromatherapy and voice control

What we don’t love
It’s not the most powerful fan on test

ProBreeze AirFlo 43in Smart Hybrid Pedestal Fan – Ultra-Quiet Air Circulator
£169.99 at ProBreeze
£169.99 at Mountain Warehouse

Currently out of stock

This good-looking fan is convertible, with a tube you can remove to turn it from a pedestal to a desk fan, but it’s a single tube so it only offers two heights. Unusually, though, you can unscrew the little circle in the middle (where the logo is) to reveal a fabric pad. Add drops of essential oils for aromatherapy while you cool on a hot day (as ever, be careful around any pets ). Meanwhile, a fine mesh filter catches dust: unscrew the back periodically to clean it.

Control it via an app or the remote control. A clear display on the front tells you what speed it’s on. The horizontal oscillation is either 100 degrees or off, but vertically you have options (0, 30, 60 or 135 degrees). I especially liked the remote’s max button that selects top speed and full oscillation on both axes, to really get air circulating around the room.

Why we love it
The ProBreeze does a good job of cooling and has a nine-hour timer. I found it pretty quiet on speeds 1-5 (out of 9). You can even use the app to add Amazon Alexa or Google Home voice control. Say “Alexa, turn my fan on” when you’re too hot to even reach for the remote control.

I still slightly prefer the AirCraft Lume, which has a similar design, but the ProBreeze is convertible and adds wifi, app and voice control, and the option of aromatherapy, all for a reasonable price. It won’t disappoint.

It’s a shame that … there are no in-between heights.

Style: pedestal/desk
Dimensions: 36 x 30 x 108cm (WDH)
Number of speeds: 9
Remote control? Yes
Peak noise level on test: 67dB
Power use on top setting: 14W
Air speed on top setting: 3.5m/s

ProBreeze

AirFlo 43in smart hybrid pedestal fan

from £169.99

What we love
It features aromatherapy and voice control

What we don’t love
It’s not the most powerful fan on test


Best fan that follows you:
Dyson Find+Follow Purifier Cool PC3

Dyson

Find+Follow Purifier Cool PC3

from £549.99

What we love
It’s a good fan that follows you!

What we don’t love
The eye-watering price

Dyson Find+Follow Purifier Cool
£549.99 at Dyson
£549.99 at John Lewis

Currently out of stock

This fan is expensive, even by Dyson standards, but the designers have dreamed up a feature you never knew you needed. Its 17-point AI user detection means the fan can automatically turn to face you. Or you can turn this off and point it wherever you wish, or set it to oscillate side to side.

Why we love it
The fan is impressive. It’s surprisingly quiet and puts out a good, cooling breeze. It has replaceable filters for air purification. The display on the front indicates air quality as well as fan speed.

It’s an air multiplier, so only air that passes through it is filtered. Extra, unfiltered air is propelled through the middle. If filtration is your number-one priority, look at other models like the Blueair ComfortPure 3-in-1 T20i below.

The follow-me function is a bit creepy: your fan is watching you. But it’s good if you’re on your feet – cooking, for example. It’s really for solo use: I felt my fan was disloyal when it decided to cool my girlfriend, not me. Could it tell her need was greater?

But it’s a good fan: quiet and powerful. Instructions are minimal, but it’s intuitive. The remote control sticks magnetically to the top when not in use, and the MyDyson app offers excellent controls (including more timer options) and an air quality graph.

If price isn’t a problem, this won’t disappoint. If you don’t need the follow-me function, consider cheaper Dyson fans .

It’s a shame that … it’s so expensive.

Style: tower
Dimensions: 22 x 22 x 105cm (WDH)
Number of speeds: 10
Remote control? Yes
Peak noise level on test: 47dB
Power use on top setting: 28W
Air speed on top setting: 2.5m/s

Dyson

Find+Follow Purifier Cool PC3

from £549.99

What we love
It’s a good fan that follows you!

What we don’t love
The eye-watering price


Best tower fan:
Dreo Cruiser TF518

Dreo

Cruiser TF518

from £89.99

What we love
The slim design and small footprint

What we don’t love
Energy consumption is high for a fan

Dreo Cruiser Pro T2 Tower Fan
£99.99 at Currys
£89.99 at Amazon

Currently out of stock

This tower fan is slim but striking in black. Features include 90-degree oscillation, a 0- to 12-hour timer, a sleep mode where the fan speed decreases gradually, and an auto mode that adapts the fan speed depending on the room temperature.

Why we love it
At full blast, the Dreo felt positively windy and was definitely cooling on a hot day. On the two lowest settings, no sound was audible, but I could still feel a gentle breeze. I also liked the recess at the top-back that makes it easy to carry with one hand.

It’s billed as a “25dB silent bladeless fan”, but I measured 60dB on top whack from a metre away. The sound wasn’t too annoying, though, and the fan’s powerful cooling made it forgivable.

It’s a shame that … its energy consumption is relatively high. We’re talking pennies in electricity, but still, I’d rather it was more energy efficient. Also, there’s nowhere to clip the remote control.

Style: tower
Dimensions: 32 x 32 x 106cm (WDH)
Number of speeds: 9
Remote control? Yes
Peak noise level on test: 60dB
Power use on top setting: 29W
Air speed on top setting: 3.6m/s

Dreo

Cruiser TF518

from £89.99

What we love
The slim design and small footprint

What we don’t love
Energy consumption is high for a fan


Best travel fan:
Morphy Richards Air Flex USB fan

Morphy Richards

Air Flex USB fan

from £39.99

What we love
Rechargeable; folding; portable; great for travel

What we don’t love
Nowhere near as powerful as big fans

Morphy Richards Air Flex 6” Portable Oscillating Rechargeable USB Fan
£39.99 at Morphy Richards
£44.32 at Amazon

Currently out of stock

This is the fan you can take with you anywhere. I don’t mean to fan yourself by hand: it folds down small and it’s cordless and USB rechargeable, so you can be the smuggest person on the train and a very happy camper on a hot day. It can also give you a breeze on a still day on the patio. The battery will last from four to 17 hours, depending on fan speed. And you can plug it into a laptop at your desk or even a power bank for more juice.

Why we love it
The 2.6m/s air speed can’t compete with the big fans on test – and it wasn’t the one I reached for during a heatwave – but that’s not what it’s for. It’s an electric fan that can go anywhere, folding down to a cylinder measuring 18 x 18 x 12cm. You can even hang it on the wall, if you wish. It’s rechargeable and you can even use it with a USB power bank to keep it running anywhere, so you can cool down in a tent or on the train. Far better than a handheld fan. I’d definitely take this fan on holiday.

There’s no timer or sleep mode, but there’s a “nature mode” that varies the speed to mimic a breeze. And it does oscillate (to 90 degrees). It’s also quiet: I couldn’t hear it on the first of its three speeds, and it was never loud enough to be annoying.

It’s a shame that … air speed dips slightly when it’s not plugged in, but only slightly (2.5m/s instead of 2.6m/s).

Style: desk
Dimensions: 18 x 18 x 22cm (WDH)
Number of speeds: 3
Remote control? No
Peak noise level on test: 35dB
Power use on top setting: 8W
Air speed on top setting: 2.6m/s

Morphy Richards

Air Flex USB fan

from £39.99

What we love
Rechargeable; folding; portable; great for travel

What we don’t love
Nowhere near as powerful as big fans


Best evaporative cooler:
Swan Nordic air cooler

Swan

Nordic air cooler

from £89

What we love
Cooling, uses less electricity than aircon

What we don’t love
It makes gurgling noises

Swan Nordic 2-in-1 Evaporative Air Cooler with 24 Fan Settings, 3 Airflow Modes, Advanced Cooling System and 24 Hour Automatic Timer, 5L, 28W, Oatmeal, SAC16800OAT
£89 at George at Asda
£90.02 at Amazon

Currently out of stock new ; available used through Amazon resale

The air speed may not be great, but this Swan model is still a good buy because it’s an evaporative cooler, meaning it uses water from its five-litre reservoir to cool the air it blows at you. It can be used as a regular fan, too. Evaporative coolers are much more energy efficient than air conditioning, so they use much less power (and therefore less carbon, assuming you’re not on a renewable tariff or producing your own electricity).

Why we love it
Of the two evaporative coolers I tested, this worked the best. I could see the temperature on the thermometer go down: it cooled by more than 1C in less than 30 minutes. And it felt like a cooling breeze. In fact, it felt a bit like aircon.

I just filled it with water, but it comes with two ice packs that you can pre-freeze and throw into the reservoir for even colder results.

The breeze felt wide, rather than focused. This is a question of personal taste: some people want a powerful fan that’s focused to blast just them, while others prefer a room-filling breeze. In oscillating mode, it’s wider still, as the grille at the front rotates, which is a bit hypnotic. It’s good-looking, too, in a coffee-coloured oatmeal or grey finish. It’s light and on casters, so easy to move around, and its modes include normal, natural, sleep and timer.

It’s a shame that … you can hear the water in the pipes: it sounded like a leak. You might even find yourself needing the loo. I also found myself reaching for a fan on a hot day – it provides a light breeze, not a blast of wind. But the air that it puts out is genuinely cooler than the rest of the air in the room.

Style: tower
Dimensions: 29 x 24 x 71cm (WDH)
Number of speeds: 24
Remote control? Yes
Peak noise level on test: 45dB
Power use on top setting: 26W
Air speed on top setting: 0.9m/s

Swan

Nordic air cooler

from £89

What we love
Cooling, uses less electricity than aircon

What we don’t love
It makes gurgling noises

Searching for more inspiration? Read our guide to the best evaporative air coolers

skip past newsletter promotion

The best of the rest

A selection of boxed and packaged fans
Photograph: Caramel Quin/The Guardian

Levoit Classic tower fan

Levoit

Classic tower fan

£89.99

What we love
It’s quiet and the design doesn’t stand out

What we don’t love
It’s not all that powerful or cooling as a fan

Levoit Classic 36-inch DC Motor Tower Fan
£89.99 at Amazon

Best for: a quieter tower fan

This produces a narrow beam of air, so you need to point it at you just right or set it to oscillate (90 degrees). It’s billed as a “20dB silent tower fan”, and it’s inaudible on the lowest four of its 12 speeds, but it was considerably louder at top whack.

It’s good-looking, and I liked the space in the back to stow the remote control. There’s a 12-hour timer and a sleep mode, too.

It didn’t make the final cut because … for £10 more, the Meaco Sefte smart 36in fan is more powerful, which is what you need on a really hot day.

Style: tower; dimensions: 29 x 29 x 92cm (WDH); number of speeds: 12; remote control? Yes; peak noise level on test: 50dB; power use on top setting: 40W; air speed on top setting: 1.7m/s

Levoit

Classic tower fan

£89.99

What we love
It’s quiet and the design doesn’t stand out

What we don’t love
It’s not all that powerful or cooling as a fan


Vortex Air Pro Plus

Vortex Air

Pro Plus

£139.99

What we love
Affordable, bladeless and it doubles as a heater

What we don’t love
It’s a bit loud

Vortex Air Pro Plus (2026 upgrade) Bladeless Hot & Cool Fan
£139.99 at Debenhams

Currently out of stock

Best for: style, and its all-in-one heater and fan design

Vortex Air bladeless fans look modern, very Dyson-esque, and this one comes in 10 colour combos. It’s useful year-round, too, doubling as a fan heater. But it’s hard to categorise: too short for a tower fan, too tall for a desk fan.

There’s a timer and it oscillates horizontally (71 degrees) and vertically (180 degrees), though it’s hard to imagine why you’d want to point it completely down. The touch controls are at the base, which isn’t very practical if it’s on the floor, and the display was a bit hard to see.

It didn’t make the final cut because … I found the noise a bit annoying; I could hear it at levels 2-10.

Style: tower; dimensions: 25 x 24 x 65cm (WDH); number of speeds: 10; remote control? Yes; peak noise level on test: 35dB; power use on top setting: 28W; air speed on top setting: 2.9m/s

Vortex Air

Pro Plus

£139.99

What we love
Affordable, bladeless and it doubles as a heater

What we don’t love
It’s a bit loud


Shark TurboBlade TF200SUK

Shark

TurboBlade TF200SUK

from £274.99

What we love
Can point in two directions at once

What we don’t love
The sample we tested had an annoying sound

Shark TurboBlade Tower Fan, Pink
£274.99 at SharkNinja
£300 at Amazon

Currently out of stock

Best for: pointing in two directions at once

This bladeless fan’s unusual T-shaped design has arms that stick out left and right, each putting out air, or you can turn them by 90 degrees for a tall, thin fan. You can angle each arm independently, good for pointing at two people. It’s height-adjustable and can oscillate (180 degrees) horizontally too. I liked that the remote attaches to the top with a strong magnet.

It’s powerful, but the sound is very annoying: it sounds like a vacuum cleaner, and I wanted it to stop. It also used the most power on test; even still, a 60W fan costs less than 2p an hour to run at the current energy price cap, so it’s pennies compared with aircon.

It didn’t make the final cut because … I hated the noise it makes.

Style: pedestal; dimensions: 80 x 30 x 78-95cm (WDH), or 124 x 30 x 114-130cm in vertical mode; number of speeds: 10; remote control? Yes; peak noise level on test: 35dB; power use on top setting: 60W; air speed on top setting: 3.1m/s

Shark

TurboBlade TF200SUK

from £274.99

What we love
Can point in two directions at once

What we don’t love
The sample we tested had an annoying sound


Duux Whisper Flex 2

What we love
Voice control and there’s a cordless option

What we don’t love
The controls are annoying

Duux Whisper Flex 2 Smart Fan, Remote Control, Alexa & Smart App, 30 Cooling Speeds, Adjustable from Desk to Standing Fan, Up-Down, Left-Right Oscillation, Powerful & Quiet, Night Mode, Black
£179.99 at Duux

Currently out of stock new; available refurbished at Back Market

Best for: smart controls

This took quite a bit of assembly, but it’s good-looking, can be converted into a 54cm-high desk fan by removing a pole, and the tech is clever too. You can control it with an app or by voice (Amazon’s Alexa or Google Assistant) to set up to seven schedules. There’s an optional battery and charging dock to make it cordless.

It’s fairly quiet and oscillates well, vertically and horizontally, but I found the standard controls annoying. The display on the base points upwards, so it’s hard to see from across the room, and you have to point the remote very accurately at it.

I did like the compostable packaging. But unusually, it drew far too much power (2W) on standby. Less than 1W is the norm.

It didn’t make the final cut because … of the annoying controls.

Style: pedestal; dimensions: 34 x 34 x 92cm (WDH); number of speeds: 30; remote control? Yes; peak noise level on test: 40dB; power use on top setting: 9W; air speed on top setting: 3.1m/s

Duux

Whisper Flex 2

£149

What we love
Voice control and there’s a cordless option

What we don’t love
The controls are annoying


VonHaus air circulator desk fan

VonHaus

Air circulator desk fan

£64.99

What we love
A compact, quiet desk fan

What we don’t love
We like the Devola even more

VonHaus Air Circulator Fan – Desk Fan with 12 Speeds, 3 Modes, Remote Control, 12hr Timer, 90° Oscillating, Quiet, LED Display, 3 Blades – Table Top Cooling for Home, Office, Living Room, Bedroom
£64.99 at VonHaus

Currently out of stock

Best for:

room-filling breeze

This desk fan has a display and touch controls on the front. And it oscillates well: it turns 90 degrees vertically, 80 degrees horizontally or both together to create a room-filling breeze. I couldn’t hear the lowest five of its 12 speeds, either.

It looks good, and the controls are easy to use. Features include a one- to 12-hour timer and a sleep mode that decreases fan speed every 30 minutes through the night.

It didn’t make the final cut because … I liked the Devola desk fan even more, but this is a solid buy too.

Style: desk; dimensions: 30 x 21 x 36cm (WDH); number of speeds: 12; remote control? Yes; peak noise level on test: 45dB; power use on top setting: 13W; air speed on top setting: 2.7m/s

VonHaus

Air circulator desk fan

£64.99

What we love
A compact, quiet desk fan

What we don’t love
We like the Devola even more


Dyson Cool CF1

What we love
Attractive design and works well

What we don’t love
It’s a bit pricey

Dyson Cool CF1 fan.
Photograph: Caramel Quin/The Guardian
£249.99 at Dyson

Currently out of stock

Best for: a bladeless fan

You can see a lot of thought has gone into the CF1’s design. Not just its simple, circular air multiplier, but every single detail. The display is small but readable. The oscillation (15, 40 or 70 degrees) works well. The magnetic storage on top for the remote control is clever. The controls work well and let you easily set the timer and sleep mode. I couldn’t hear this bladeless fan on the first six of its 10 speeds, and I found the noise easy to live with even at higher speeds.

It didn’t make the final cut because … the price is hard to justify. Money no object? Go for it!

Style: desk; dimensions: 36 x 16 x 55cm (WDH); number of speeds: 10; remote control? Yes; peak noise level on test: 35dB; power use on top setting: 20W; air speed on top setting: 2.9m/s

Dyson

Cool CF1

£249.99

What we love
Attractive design and works well

What we don’t love
It’s a bit pricey


Meaco Sefte 8in portable air circulator

Meaco

Sefte 8in portable air circulator

from £79.99

What we love
Cordless, fairly quiet, good warranty

What we don’t love
It doesn’t fold up for portability

Meaco Sefte Air 8” Battery Operated Table Fan, White
£79.99 at Meaco
£79.99 at Currys

Currently out of stock

Best for: a cordless fan

This is an impressive, cordless desk fan with a battery life of four to 17 hours, depending on fan speed. I couldn’t hear the first seven of its 12 speeds. It oscillates and you can manually point it up or down, and features include a timer, Night and Eco modes. Its three-year warranty is a bonus, too (most have two).

Overall, I liked it. It’s good-looking and pretty strong, although it’s weaker when cordless; for example, air speed dropped from an impressive 4.6m/s to 3.1m/s when I unplugged it. Still, if you want a desk fan that can sometimes be cordless, it’s a good buy.

It didn’t make the final cut because … the USB-powered Morphy Richards is even handier.

Style: desk; dimensions: 26 x 20 x 38cm (WDH); number of speeds: 12; remote control? Yes; peak noise level on test: 55dB; power use on top setting: 10W; air speed on top setting: 4.6m/s

Meaco

Sefte 8in portable air circulator

from £79.99

What we love
Cordless, fairly quiet, good warranty

What we don’t love
It doesn’t fold up for portability


Blueair ComfortPure 3-in-1 T20i

Blueair

ComfortPure 3-in-1 T20i

from £499

What we love
It’s also an air purifier and a fan heater

What we don’t love
It’s expensive if you just want a fan

Blueair ComfortPure 3-in-1 T20i Air Purifier
£499 at Blueair
£499 at Boots

Currently out of stock

Best for: hay fever and allergy sufferers

This is also a fan heater (so it’s useful all year round) and an air purifier (ideal for allergy sufferers). It cleans the air in a room in 12.5 minutes or a small house in an hour, removing airborne particles such as pollen, odours, dust and smoke.

On test, it created a good breeze, even though the anemometer only read 0.8m/s. And on cooler days, it can send purified air upwards instead, circulating air in the room as well as cleaning it.

The controls and display are on top, making them hard to see from across the room. But there’s an app and Alexa control as well as a remote. The three-year warranty is nice, too.

It didn’t make the final cut because … it’s expensive as a fan (but great as an air purifier).

Style: tower; dimensions: 35 x 35 x 70cm (WDH); number of speeds: 4; remote control? Yes; peak noise level on test: 35dB; power use on top setting: 21W; air speed on top setting: 0.8m/s

Blueair

ComfortPure 3-in-1 T20i

from £499

What we love
It’s also an air purifier and a fan heater

What we don’t love
It’s expensive if you just want a fan


What you need to know

Several fans and boxes of fans in a home with a wooden floor, a desk and a full shelving unit
For personal comfort, simply point a fan towards you. Photograph: Caramel Quin/The Guardian

What are the different types of fan?

Pedestal fans are tall fans where all the hard work happens at the top. They don’t have to be old-fashioned; some have modern designs. And some are convertible, with a pole you can remove to turn them into a desk fan. They can be good for a focused blast of cooling wind.

Bladeless fans aren’t magic; they just don’t have visible blades. The work is done in the body of the fan, and then air is pushed out of a nozzle. The Dyson, Vortex Air and Shark on test are all bladeless. They look modern and are easy to clean. And there are no moving parts on show, meaning zero chance of getting your hair caught.

Tower fans are tall and narrow. They produce a lot of wind and oscillate from side to side, making them good for a room like an office.

Desk fans are like pedestal fans without the pole. They’re not only for desks, they’re good on a bedside table too. And they take up less storage space over the winter.

Evaporative coolers use water from a reservoir to cool the air that blows at you. They don’t produce a powerful wind like a fan, but they genuinely cool the room and are much more energy efficient than air conditioning. Note that they only cool the room a little – they won’t turn it fridge cold like aircon.

Handheld fans are lightweight, portable fans to cool you on the move. We’ve tested a wide range of handheld and neck fans.

What does oscillation mean?

Most fans oscillate (move back and forth) by swivelling on their base, and some let you select how wide an angle you want. If it’s just for you, pick a narrow angle; if you’re cooling the whole office, go wide. Some fans achieve the same effect in other ways, such as by moving louvres. Some also oscillate up and down, so the fan can circulate air all over the room to create a gentle breeze.

What’s sleep mode?

Most fans have a sleep mode, where every 30 or 60 minutes the fan lowers its setting until it reaches a certain point. This is a good compromise that helps you get to sleep without wasting energy, minimising the risk of waking up in the middle of the night suddenly cold.

Start by lowering the fan speed to the point where you don’t find it annoying. In fact, some people find the white noise of a fan helpful at bedtime. Then switch to sleep mode.

Wh ere is the best place to position a fan?

For personal comfort, simply point it towards you. The cooling feeling is because the moving air from the fan displaces the warm, humid air near your skin, which in turn helps your sweat evaporate, cooling down your body. It’s like a breeze rather than a still day. Or why it feels colder swimming in a river than in a lake, even if the water temperature is the same. Evaporative coolers, of which I’ve included two above, use water to actively cool the air.

Never place a fan up against a wall because air needs to flow into the back. If the air’s cooler outside, put the fan in front of an open window or door to bring in the cooler air.

How energy efficient are fans?

Fans are very energy efficient compared with the electricity used by tech such as air conditioning. Fans cost pennies to use but can make you feel much cooler. Note that they circulate air rather than actively cooling it. The effect is like turning a still day into a breezy one.

How much does a fan cost to use?

I’ll set out the maths. For each fan here, I’ve measured its power use on the top setting, in watts (W). Electricity costs are in kilowatt hours (kWh). If, for example, you were using a 30W fan for five hours, it would use 150Wh. Divide by 1,000 to convert it to kilowatt hours: 0.15kWh.

The energy price cap for 1 July to 30 September 2026 is 26.11p per kWh. Multiply this by the last figure and you’ll discover it will cost just under 4p to run that fan for five hours. Or just over £14 to run it for five hours every day for a year.

Running fans is pretty cheap, then, and a good fan will keep you cool enough to dodge buying any kind of air conditioning. An evaporative cooler is a good alternative to aircon. The Swan Nordic here used 26W, so less than 3% of the electricity of a typical portable air conditioner (1,000W). The effect isn’t the same: you can’t turn your bedroom into a fridge. But you can cool the air enough to make a big difference when there’s a heatwave.

Do I need air conditioning?

For most of us, there are good energy-saving alternatives to aircon. It’s tempting to turn your bedroom into a walk-in fridge on a hot day – or night – but fans are great and use much less electricity (and therefore money and carbon) than aircon. We are in a climate crisis. We got into this mess by burning fossil fuels, and we continue to do so, so the carbon footprint of your cooling matters.

There are valid reasons to own air conditioning though, even during a climate crisis. Older people, young children and those with health conditions are more vulnerable to extreme heat, and some homes are simply much harder to keep cool. My guide to portable air conditioners and alternatives takes in how much energy they use, as well as how well they cool the room and their refrigerant’s global warming potential.

Note that the electricity you use won’t contribute as much towards climate breakdown if you’re on a good renewable tariff – or even better, producing it yourself with solar panels. Solar panels and batteries are becoming a popular choice for homeowners as they become more affordable.

How to clean your fan

Fan blades tend to gather dust. Make sure the fan is unplugged, then remove the front grille and wipe the blades with a microfibre cloth. If the grille doesn’t come off then a dry paintbrush or a small cleaning brush (like a bottle brush but smaller) might let you dust through the grille. Never use water on electricals. A can of compressed air is also good for blowing off dust – keep your fingers away, though, because it will of course make the fan blades spin.

What to do with your old fan

If your old fan works, try to find it a good home on a local swap site or street WhatsApp – they work better than the front wall, where it might get rained on. If it’s not working, you could take it to a local repair cafe . And if it’s beyond repair, check your council website or check Recycle Your Electricals : they don’t belong in general waste.

If you’re wondering whether you need air conditioning, read our guide the best portable aircon units, plus the pros, cons and alternatives


Caramel Quin is a journalist specialising in consumer technology. She prides herself on real-world testing and plain language. Her pet hates are jargon, pointless products and over complicated instruction manuals. Caramel is an engineering graduate who has won awards for communicating hi-tech subjects to normal people. When she’s not testing gadgets, she’s feeding pets (16 beasts at the time of writing) or pottering at the allotment

Audacity 4.0 released

Linux Weekly News
lwn.net
2026-09-03 09:58:06
Version 4.0 of the Audacity audio editor has been released. Notable changes in this release include a rewritten interface using Qt, ability to save user-interface layouts as "Workspaces", improvements in working with audio clips, and a new .aup4 project format. The release is not fully feature-comp...
Original Article

[Posted September 3, 2026 by jzb]

Version 4.0 of the Audacity audio editor has been released. Notable changes in this release include a rewritten interface using Qt, ability to save user-interface layouts as "Workspaces", improvements in working with audio clips, and a new .aup4 project format.

The release is not fully feature-compatible with the Audacity 3.x series; see the compatibility notes for a list of missing features.



New York Times and The Athletic workers demand company scrap Kalshi deal

Hacker News
newsguild.org
2026-09-03 09:51:44
Comments...
Original Article
Unionized staff at the New York Times protest in front of the company's offices in NYC.

With a unanimous vote, the Times Guild Unit Council and The Athletic’s contract action team approved the following statement:

As unionized workers at The New York Times, we are deeply concerned by the company’s potential deal for The Athletic to partner with Kalshi, a company whose prediction markets have been described by New York officials in our reporting as an “illegal operation.

Any partnership between Kalshi and The Athletic would threaten our journalistic independence across the company. Despite management’s claim that The Athletic and The New York Times are separate business entities, the journalism and the work are intertwined, as any reader can see.

Prediction markets such as Kalshi, which allow users to place bets on real-world events, pose as reliable sources of data but operate without the accountability of independent, fact-based reporting . An investigation by New York’s attorney general found that Kalshi’s prediction market platform is an “illegal, unlicensed gambling operation” that exposes users to “serious personal and financial risk.”

On a fundamental level, a partnership more extensive than the purchase of advertising space — and that might integrate this product into The Athletic’s journalism — could cause readers to question our independence when we report on prediction markets.

A partnership between The Times (for The Athletic) and Kalshi would also provide validation that their prediction market data should be taken seriously as an indicator of the future. Facts prove otherwise.

New York Times publisher A.G. Sulzberger has said that journalistic independence is the “core value” that “answers the question of why we’re deserving of the public trust.” We call on the company to live up to that commitment and abandon this deal.

Your Employee’s Password Appeared in an Infostealer Log. Now What?

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 09:50:59
Infostealers can expose far more than passwords, including authenticated sessions that may let attackers bypass MFA. Flare explains how defenders can prioritize compromised identities, determine whether stolen access is still usable, and respond before it leads to account takeover. [...]...
Original Article

Cyber computers

Infostealer logs have evolved from an underground commodity into an operational security problem. For defenders, finding an exposed credential is only the beginning. In today’s reality many security analysts start their morning with an alert: an employee’s corporate email address has appeared in a newly collected infostealer log .

The log contains a username and password for a corporate SaaS application. There are browser cookies, meaning live sessions that can be exploited, and several other saved, in files, credentials.

A personal employee computer got infected by Vidar located hundreds of miles from the company’s offices. Now what?

Resetting the exposed password seems obvious. But that may not solve the problem. If the stealer captured an authenticated session cookie, an attacker may already have a way into the application without needing the password or another MFA prompt. If the employee reused corporate credentials on a personal computer, the endpoint that created the exposure may not even be managed by the organization.

And somewhere in an underground Telegram channel, the same information may already be available to an initial access broker, ransomware affiliate, or opportunistic attacker.

This is the operational challenge security teams increasingly face with infostealer logs.

According to Flare Research's Practitioner’s Guide to Monitoring Stealer Logs , approximately 46% of stealer logs containing corporate credentials originate from likely unmanaged or personal devices. Flare also estimates that exposure involving credentials and sessions for major productivity SaaS and cloud services is growing approximately 29% annually.

For defenders, the question is no longer simply whether they should monitor infostealer logs.

The harder question is: How do you separate a meaningless old password from an identity compromise that could be happening right now?

The needle among millions of needles

Infostealers such as RedLine, Lumma, Vidar and other malware families are designed to harvest information stored on infected systems.

Depending on the malware and configuration, that can include saved browser passwords, cookies, autofill information, cryptocurrency wallets, system information, VPN configurations and other authentication artifacts.

These are packaged to be sold under as an infostealer log, when a single infection can produce hundreds or thousands of individual records. Multiply that across a global malware ecosystem and defenders quickly encounter a scale problem.

While defenders need to process and validate everything, the attackers only need one valid valuable set of credentials. As Flare describes the problem, this isn't finding a needle in a haystack. It is finding a specific needle among millions of needles in millions of haystacks.

While stealer logs historically circulated through underground forums and marketplaces, Flare's research estimates that roughly 90% of logs now appear on Telegram, where public channels can advertise samples and private subscription channels can provide access to fresher datasets.

Is a Stolen Session Cookie Already Bypassing Your MFA?

Infostealer logs can hand attackers a live, authenticated session that skips the password and MFA prompt entirely.

Flare monitors stealer logs across the dark web and Telegram in real time, so you can flag exposed corporate identities and sessions before they turn into account takeover.

Free 2-Week Trial

A password isn't always the most dangerous thing in the log

With the vast amount of data in multiple channels, it’s hard to prioritize the risk level. If you work for a large corporate you are working with thousands of employees, if you start your day with two alerts, how can you establish what is riskier?

The first alert may involve employees’ old password for a consumer website appears in a six-month-old stealer log, whereas the second alert may have been collected yesterday and contains the employee's corporate identity credentials and an authenticated browser session for the organization's identity provider.

While both may be labeled as employee credential exposures, they are completely different.

This is why practitioners should prioritize monitoring around assets that tell them something about the potential impact, for instance corporate domains and subdomains, enterprise identity providers, session cookies, VPN and RDP endpoints, and cloud consoles.

Identity providers deserve particular attention, since a compromised SSO identity (Microsoft Entra ID, Okta, Google Cloud Identity, etc.) can open a path to multiple connected applications. Where possible, automated verification and mitigation further strengthen this protection.

The peril in session cookies

When a user successfully authenticates, an application can issue a session cookie, so they don't have to authenticate with every request.

If malware steals that authenticated session, an attacker may potentially replay it.

So, if the attackers get ahold of a session cookie, and an infostealer collects them, they don’t necessarily need to log in. Stolen credentials alone still require authentication, creating an opportunity for defenders to detect or block the login, however, a valid session cookie may remove that step entirely. This effectively bypasses MFA.

The first 60 seconds

Flare recommends an initial assessment immediately after discovering potentially relevant stealer data, followed by risk scoring and validation.

The objective isn't to conduct the entire incident investigation in the first few minutes. It is to determine how quickly the organization needs to react.

A useful first question is: What exactly was stolen? An analyst should determine when the infection occurred, what system produced the log, how many corporate credentials are present, and whether authenticated sessions were captured.

Then add business context.

A credential for testserver.company.com shouldn't necessarily receive the same priority as one for finance.company.com .

Similarly, an exposed identity belonging to a marketing intern shouldn't automatically be handled identically to an administrator with access to the identity provider, cloud console and production infrastructure.

The illustrative framework in Flare's guide therefore places enterprise identity credentials combined with session cookies at critical severity, with a suggested response target of under one hour. VPN/RDP access combined with multiple corporate credentials is classified as high severity because of its lateral movement potential.

From exposure to investigation

Suppose our hypothetical employee's log contains an Entra ID credential, corporate SaaS passwords and browser cookies, the next question is whether someone has already used them.

Defenders can correlate the exposed identity with authentication telemetry: successful and failed logins, unexpected geographies, unusual devices, unfamiliar IP addresses and access to resources outside the employee's normal behavior.

They should also determine whether the stolen information is still usable. Has the password changed since the infection? Has the session expired? Is the account still active?

Flare's recommended investigation workflow expands the analysis to include browser fingerprint information, the complete saved-credential inventory, information about the infected system, and additional artifacts such as VPN configurations or SSH keys.

Who is the employee? What can their identity access? Was the infected machine corporate or personal? Was this one infection or evidence of a broader campaign?

Authentication logs should then be examined across the systems accessible to that identity, prioritizing the most sensitive resources first.

Defenders should specifically look for behaviors indicating that exposure has progressed into account takeover: authentication from unexpected locations, access inconsistent with the user's role, unusual downloads, password-reset activity, and enrollment of new MFA devices. This is how a stealer log becomes an early-warning sensor for identity compromise.

Treat stealer logs as an identity problem

Once a high-risk exposure is confirmed, speed matters. Defenders should invalidate compromised sessions, reset affected credentials, and increase monitoring around the identity.

Beyond individual incidents, organizations should track recurring exposures, affected applications, and whether stolen credentials lead to attempted access.

Ultimately, infostealer monitoring has become an essential layer of identity security , enabling organizations to identify exposed credentials and sessions, understand the access they provide, determine whether they remain exploitable, and disrupt potential account takeover before it develops into a broader compromise.

Learn more by signing up for our free trial .

Sponsored and written by Flare .

Astronomers Detect a 10-Sided Structure in Saturn's Atmosphere

Hacker News
www.sciencealert.com
2026-09-03 09:47:38
Comments...
Original Article

Astronomers Detect a 10-Sided Structure in Saturn's Atmosphere Polar projection of Saturn's southern hemisphere from Hubble data, revealing the decagon. (NASA, ESA, A. Sánchez-Lavega (Basque Country University, EHU))

Saturn , apparently, has been hiding its talents.

For decades, humanity has puzzled over the gas giant's enormous hexagon swirling around its north pole – a six-sided atmospheric structure unlike anything else known in the Solar System.

Now, it seems, that bizarre feature is not an isolated incident – and Saturn may have a propensity for polygons, rather than a passing whim.

Lurking around the planet's south pole, astronomers led by Agustín Sánchez-Lavega of the University of the Basque Country in Spain have spotted another giant polygon – and this one has ten sides.

"This discovery suggests that the hexagon is not as extraordinary as previously thought and that, in fact, the conditions in Saturn's atmosphere are such that polygonal waves can form in both hemispheres surrounding the polar regions," Sánchez-Lavega told ScienceAlert.

YouTube Thumbnail

Saturn's most prominent and well-known feature is its magnificent system of icy rings, but the hexagon at its north pole would have to be a pretty close second.

It was first discovered in images from the Voyager probes in 1980 and 1981: a vast, six-sided atmospheric wave swirling around the pole at about 78.5 degrees latitude.

In the intervening decades, both the Hubble Space Telescope and the Cassini-Huygens Saturn probe also captured the strange feature, suggesting that it has remained stable for at least 44 years.

It's a weather phenomenon, but why it has such an almost perfect polygonal shape remains a mystery. And although scientists also thought Saturn's southern subpolar jets might produce a similar feature, none revealed itself across multiple searches.

Then, in 2024, polygon lightning struck for the second time.

In images from amateur astronomers, a dark, undulating line was visible around the planet's south pole.

Work in 2025 confirmed it. While creating polar projections from images of Saturn taken by astronomers Trevor Barry of Broken Hill Observatory in Australia and Jean-Paul Oger of the French Astronomy Association, the team finally saw it: Ten sides, forming an unmistakable polygon around the pole.

Saturn Is Throwing Shapes. This Time, It's a Giant Decagon Around Its South Pole.
Hubble observations showing the emergence of Saturn's south-polar decagon between 2023 and 2025. (Sánchez-Lavega et al., Sci. Adv. , 2026)

High-quality images from the Hubble Space Telescope confirmed it and allowed the team to trace it back to 2023.

"The discovery of the wave really did come as a surprise, as neither earlier images of Saturn taken by the Hubble Space Telescope nor those captured by the Cassini spacecraft whilst orbiting the planet between 2004 and 2017 had shown it," Sánchez-Lavega said.

Centered around 60 degrees south, the decagon appears to be a vast atmospheric wave riding on one of Saturn's powerful eastward jet streams. The jet itself races around the planet at roughly 420 kilometers (260 miles) per hour, while the decagon moves at a comparatively leisurely place of around 10 kilometers per hour.

Like the hexagon , the decagon doesn't appear to be just a pattern sitting across the visible cloud tops. Observations at different wavelengths revealed traces of its shape at different altitudes and latitudes, suggesting a vast, vertically layered structure embedded in Saturn's atmosphere.

Fundamentally, it is the same kind of phenomenon as the hexagon, but – difference in side count notwithstanding – the two polygons are not mirror images of each other.

Saturn Is Throwing Shapes. This Time, It's a Giant Decagon Around Its South Pole.
Saturn, seen in natural color by the Cassini spacecraft in 2016. Its famous hexagon is visible around the north pole. ( NASA/JPL-Caltech/Space Science Institute )

"In addition to the difference in the number of sides," Sánchez-Lavega explained, "the decagon is situated at a less polar latitude than the hexagon in the southern hemisphere, and is perhaps not as robust, as we have seen that it has formed."

There are so many questions about these differences. Why did the decagon only form a few years ago, compared to decades of stability for the hexagon? Why are their latitudinal positions different?

And why does the southern polygon have ten sides, compared to the north's nature-preferred six ?

"It may be linked to the difference in latitude, to the background wind structure, or perhaps even to the presence of a high-pressure vortex at nearby latitudes that could be forcing the formation of the wave," Sánchez-Lavega told ScienceAlert.

There's even a plausible suspect.

Just north of the decagon is a roughly 4,000-kilometer-wide anticyclone – a high-pressure vortex the researchers call a Red Spot – smaller, temporary analogs of Jupiter 's famous storm. Intriguingly, the decagon appears most pronounced near the vortex and least distinct on the opposite side of the planet.

Saturn Is Throwing Shapes. This Time, It's a Giant Decagon Around Its South Pole.
Simulations of three decagon formation scenarios. (Sánchez-Lavega et al., Sci. Adv. , 2026)

The researchers conducted simulations to determine whether this storm – or some other disturbance – could have played a role in the formation of the decagon.

None of their scenarios, however, was able to reproduce the observed decagon exactly.

And, of course, there's this little snag.

"The hypothesis that a nearby anticyclone at that latitude is driving the oscillation is an attractive one," Sánchez-Lavega said. "The same thing happened with the hexagon when it was discovered in 1980, but then the nearby vortex disappeared, and the hexagon remained."

So for now, the answer is tantalizingly out of reach. Currently, the decagon is still there – observing how it changes over the coming months and years could reveal much more about how it formed.

Subscribe to ScienceAlert's free fact-checked newsletter

Saturn is tilted on its axis as it orbits the Sun every 29.5 years, giving the planet long seasons lasting about 7.5 years each. Its southern hemisphere is now moving through spring towards summer, tilting increasingly towards the Sun.

Related: Amazing New Photos of Saturn's Moons Have to Be Seen to Be Believed

The increase in solar radiation hitting the southern hemisphere – and the decagon – could cause some interesting changes. And as the south pole tilts further into view, astronomers will have an increasingly good vantage point from which to watch them unfold.

"We need to understand how the decagon evolves – in other words, whether in the coming years it will become unstable and break up, or, conversely, become more stable and robust as solar radiation increases," Sánchez-Lavega said.

Saturn's hexagon has endured for at least 44 years; we only learned of its existence well after it was established.

With the decagon, scientists now have a front-row seat to how Saturn builds its polygons in real time – and whatever happens, it's going to be one heck of a show.

The research has been published in Science Advances .

This article was fact-checked by Fiona MacDonald and edited by Fiona MacDonald . While we pride ourselves on our process, we are only human. If you spot a mistake, please let us know .

How Much Richer Can NYC's Rich Get? Buddy

hellgate
hellgatenyc.com
2026-09-03 09:40:14
Everyone else? Not so much. And other links to start your day...
Original Article

New York City's filthy rich have gotten considerably richer—and it's made our city one of the most unequal places to live in America.

That's according to a new report from City Comptroller Mark Levine , which notes that from 2019 to 2024, roughly two-thirds of New York City's real income growth accrued to the top 1 percent, compared with 39 percent in the rest of the country.

The top 0.1 percent—these are the people whose average income was $23,746,985 in 2024—accounted for more than half of the city's income growth over this time period.

(Take a big sip of coffee before you continue reading, because you'll want maximum spit take volume when you read the absolutely grotesque series of numbers that represent the growing chasm in the souls of a certain sector of our population.)

Give us your email to read the full story

Sign up now for our free newsletters.

Sign up

LLMs and self-referentiality

Lobsters
scottaaronson.blog
2026-09-03 09:39:13
Comments...
Original Article

I woke up yesterday with the following thoughts, which are probably either obvious or dumb.

A central thesis that many readers, including me, took from Douglas Hofstadter’s Gödel Escher Bach when young was that the secret of intelligence (and therefore, of AI) was going to have a lot to do with self-referentiality and “strange loops.”

Even Roger Penrose’s The Emperor’s New Mind , which in some ways was the anti-GEB, ironically agreed with GEB about the fundamental importance of self-reference to the success or failure of the whole AI project. It claimed (incorrectly, in my view and in most experts’) that AI could never work because there was something about Gödel’s Theorem and self-reference that no computer program could ever capture, but that could be captured by exotic physics accessible to the human brain.

Now, in 2026, we’ve succeeded at building AIs that outperform most humans at most intellectual tasks that are well-defined enough to judge. And at no point in the tech stack of those AIs — neither in the transformer neural nets, nor in the GPU clusters they run on, nor in the training process, nor anywhere else — did anyone need to build in anything about self-reference. (Excepting, eg, the system instructions that tell the model about its role and identity, which aren’t needed for intelligent behavior. Also, I’m not going to count the autoregressive nature of LLMs as “self-referential”; that’s just dynamical feedback.)

Of course, GPT 5.6 Pro and Fable can talk about themselves, about Gödel’s Theorem, about self-reference, about what we’re talking about right now, all of it, better than most humans. But at no point did anyone need to build self-referential abilities in. They popped out as a byproduct of the same pretraining that let the models talk about Pokémon and long-chain polymers and cognitive behavioral therapy and plate tectonics and everything else.

No wonder Hofstadter says he’s been stunned by the success of LLMs, and has seemed depressed about current AI capabilities in essays like this one . He’s way too smart to deny what’s happened or invent reasons why it doesn’t really count (the approach many have taken). But he realizes that we now have true conversational intelligence from a path that the GEB worldview would’ve regarded as far too cheap and simple, and that certainly has no “strange loops” built in anywhere.

Of course, a Hofstadterian could argue that a strange loop emerges in LLMs — indeed, nothing in GEB ever said that strange loops would need to be explicitly engineered at the outset. But would anyone who hadn’t been brought up on GEB arrive at this as a useful way of thinking about LLMs?

What can we say about this with hindsight? While the ideas of diagonalization and self-reference of course played a central role in the birth of modern mathematical logic and computer science, the most famous uses were negative : there is not a bijectjon between the natural numbers and the reals. There is not a complete sound proof system for arithmetic. There is not an algorithm to solve the halting problem.

If your goal was only to build the axioms of ZFC and the rules of first-order inference, or build an electronic computer, you wouldn’t explicitly need self-reference for that. You would just … start building, taking care that your instruction set didn’t fall short of universality.

Yes, ZFC can formalize and prove theorems about itself. Yes, electronic computers can run programs that take their own code as input. But no one ever needed to build those abilities in, any more than self-reference needed to be built in to the alphabet or the rules of grammar. It popped out as a free byproduct of universality.

In the same way, LLMs’ ability to talk about themselves popped out as a byproduct of their ability to talk about anything in the discourse universe they were trained on. The big, old ideas about intelligence that ended up basically vindicated were the ideas about how intelligence is about prediction, and prediction is about compression, and compression is about finding better and better upper bounds on Kolmogorov complexity. Not the self-reference stuff. (Although, if you wanted to know why Kolmogorov complexity can’t be computed perfectly, that negative statement would again require a self-referential argument.)

What’s left? Consciousness and subjective experience of course remain extremely mysterious. For all we know, Hofstadter could be right that those have something to do with self-reference. (For all we know, even Penrose could be right that they have something to do with exotic physics accessible to biological brains but not digital computers!)

But the idea that you’d need explicit self-referentiality before you could get convincing and world-changing conversational intelligence? Let it be buried in a Westminster Abbey or Arlington National Cemetery for the most important wrong ideas in human history — geocentrism, Aristotle’s teleological physics, aether, phlogiston, Freud’s psychology, Marx’s prediction of a workers’ uprising followed by a classless utopia, etc. But buried it needs to be.

This entry was posted on Tuesday, September 1st, 2026 at 12:17 pm and is filed under Embarrassing Myself , Metaphysical Spouting , Procrastination . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.

You can use rich HTML in comments! You can also use basic TeX, by enclosing it within $$ $$ for displayed equations or \( \) for inline equations.

After two decades of mostly-open comments, in July 2024 Shtetl-Optimized transitioned to the following policy:

All comments are treated, by default, as personal missives to me, Scott Aaronson---with no expectation either that they'll appear on the blog or that I'll reply to them.

At my leisure and discretion, and in consultation with the Shtetl-Optimized Committee of Guardians , I'll put on the blog a curated selection of comments that I judge to be particularly interesting or to move the topic forward, and I'll do my best to answer those. But it will be more like Letters to the Editor. Anyone who feels unjustly censored is welcome to the rest of the Internet.

ICE Has a $2M Contract for Spyware That Can Hack Phones Without a Click

Hacker News
www.military.com
2026-09-03 09:36:04
Comments...

Elevated Errors for Multiple Models

Hacker News
status.claude.com
2026-09-03 09:29:12
Comments...
Original Article

Update

An exhaustive list of affected models: Mythos/Fable 5.1, Mythos/Fable 5, Opus 5, Opus 4.8, Opus 4.6.

Posted Sep 03 , 2026 - 13:50 UTC

Identified

We have identified the cause of elevated errors on requests to Claude Mythos 5.1, Claude Fable 5.1, and Claude Opus 5 and are working on a fix. We will provide an update as soon as possible.

Posted Sep 03 , 2026 - 13:41 UTC

Investigating

We are investigating elevated errors on requests to Claude Mythos 5.1, Claude Fable 5.1, and Claude Opus 5. We will provide an update as soon as possible.

Posted Sep 03 , 2026 - 13:26 UTC

This incident affects: claude.ai, Claude API (api.anthropic.com), Claude Code, and Claude Cowork.

Révo Programming language

Lobsters
revo.lung.fyi
2026-09-03 09:21:37
Comments...
Original Article
⣄⠔⠄⡨⣀⣹⣥⣣⡚⣿⣓⣾⣫⣷⠮⡧⣬⣬⣑⢤⠤⡉⣿⡥⣂⢟⣕⡴⠬⠆⠸⡈⡆⠀⠀⠀⡋⠄⠂⠨⡆⠀⠠⠃⡀⠀⠀⠈⢰⣿
⠩⣽⢟⢭⠶⢷⢵⣻⠿⢍⣟⡅⡧⡭⣽⡯⡯⣶⠭⣽⡢⠱⢿⢧⠓⢥⠨⠧⠉⣡⠐⠀⢑⣀⠂⠈⠆⡅⠀⡀⢥⠤⢁⠀⢣⠀⠀⢘⠽⡏
⠬⡓⣼⢟⢜⡧⣷⣇⣧⡷⢯⣿⣿⣿⡶⣭⠍⣯⣻⢥⠞⣮⣬⣩⠅⢏⠆⠁⡀⠌⢩⡁⢁⠅⠡⢀⠠⠀⢉⢈⠀⠀⡅⠀⡇⠀⠀⠃⠭⣯
⡎⣟⣵⠅⣾⢭⣿⣾⣯⣿⣿⢿⣿⣿⣿⣿⣧⡳⣥⢜⣟⡤⠉⣁⢧⢨⠌⡂⠀⠒⠬⡪⣊⠄⠀⠘⠀⠢⡁⠀⡀⠅⠅⠀⡄⠀⠈⠀⢕⡟
⡕⣧⡗⠎⠷⣯⣿⣿⣷⣿⡻⢵⣿⣿⣿⣭⣿⡿⣟⣇⡧⣿⡭⢨⠫⠮⠄⠖⠀⠆⠦⠕⠁⠅⠀⠆⡁⠁⡀⠀⠄⡉⠁⠀⠄⡀⡂⠀⢼⣇
⠃⣶⣯⠢⡗⣟⣿⡿⣿⣯⢿⣷⢾⢿⣛⣿⣿⣯⡻⣾⡾⣾⢵⣏⣩⠅⠅⠥⠀⠃⠠⠅⠃⠀⡈⠀⠭⠅⠀⠀⠁⠔⠀⠀⢂⠅⠅⠀⠽⡇
⠱⣻⣻⡥⢫⢯⢿⣷⣷⣿⣿⢾⢿⣷⢯⣉⣟⣟⣾⣿⠳⣿⣇⣃⠯⠘⠔⡇⠒⠅⡖⠁⠄⠡⠑⣀⠀⡁⠀⡀⠃⠈⠀⠀⠅⠀⠀⠂⣋⡇
⢂⠵⣓⣿⣍⢯⢯⡯⣟⣝⠷⣟⢝⣋⡏⣧⠯⣿⣿⢯⣼⣯⡂⡂⣟⡧⠐⣅⠂⠥⠏⠀⠂⡅⠅⡁⠁⠄⠠⠊⠀⠨⠀⢈⠀⠄⠉⢘⡟⡆
⡥⣯⢌⡤⢽⣗⣏⠗⢿⣻⡭⡞⡷⣭⢿⡻⡯⡟⣕⣾⢽⢯⡭⠂⡍⠀⠏⠀⢌⠴⠂⠊⡄⢗⠂⠰⠀⠤⠣⠀⠀⠀⠁⠀⠀⠀⠅⠀⢕⡽
⠵⡭⡩⠋⠽⣽⡛⡹⢯⠍⡛⡏⣯⢟⠟⠿⣩⣳⡿⡟⢗⣭⡤⡯⠁⡬⠠⠂⢄⠂⢤⠀⢖⠀⠀⢀⠂⢖⠀⠘⠀⠀⠂⠡⢤⠠⠀⠀⣫⡿
⠀⢰⡇⢂⣃⠙⣧⡵⡙⠇⡷⠶⡷⠶⡟⡙⣩⡌⠯⡺⡍⡲⡸⣆⠼⠅⡱⠌⠡⠂⢄⣠⠃⠀⠀⡂⠈⠂⠠⢀⠀⠀⠀⠔⠀⠂⠂⠀⠨⣯
⡔⠰⠼⣝⢪⢋⢋⠣⣧⡦⣦⡁⡭⠽⡛⠁⡫⢡⡄⠿⡫⣕⣔⢳⠌⢡⡸⠁⠁⠂⣠⡇⠀⠀⠀⠍⠈⠄⠀⠀⢀⠀⠔⠆⠁⠈⠠⠀⡹⡏
⡖⣠⠄⠀⠯⢜⢨⠊⣒⢡⠨⡀⠢⢭⠴⡊⢕⠐⣄⡓⡾⠋⠗⠉⢀⠚⠀⢃⠂⠥⠲⠀⠀⠀⠄⠐⠀⠀⠐⠀⠁⠄⠱⠁⠊⠈⡀⠀⠊⣽
⠀⡉⠒⣃⠰⡀⢁⠘⡉⠪⠋⡲⡅⠍⡎⡪⢣⠽⢭⠍⡥⠁⠂⡰⠠⣄⠥⠐⠀⠣⠄⢀⠐⠁⡀⠀⢐⠐⠀⠠⠁⠂⠄⠠⠀⠁⡀⠐⣫⡟
⠐⢔⠁⠀⠬⠑⠗⠴⠀⠢⡁⢌⠅⢘⠓⡛⠈⡀⠄⠆⠠⠠⠢⢂⠕⠷⠈⢀⠈⡒⠄⠂⠀⠀⠈⠀⡀⠡⠈⠀⠆⡐⠀⠀⠓⠀⠀⠀⢐⢼
⡀⠀⠈⠐⠠⠀⠀⠁⠁⠣⢀⡁⡄⠂⠔⠂⠂⢉⠁⡌⠄⠜⠈⠡⠐⠀⡐⠀⢨⠀⠁⠀⠀⡀⠍⠄⠠⠁⠀⠠⢄⠈⠀⠀⡄⠀⠀⡀⠒⣸
⢘⠉⡒⠤⠌⢀⠑⠕⠀⠄⠄⠄⠀⠄⠑⠉⠨⠀⠄⠀⠂⠃⠀⠀⠈⠄⠄⠠⠈⠀⠀⡀⠠⠁⢠⠁⠁⠀⠐⠱⠀⠀⠀⡐⠀⠉⠄⠀⢸⠾
⠀⠘⠈⡀⠈⠀⠈⠨⠐⠠⠠⠐⡀⡄⢠⠀⢀⠨⠀⠃⠀⠀⡁⡠⠀⠩⠀⠂⠁⠀⠀⠀⢒⡄⠊⠀⠀⢀⠈⠁⠀⠀⠀⠆⠘⠁⠄⠀⠄⣿
⠄⡄⠀⠈⠠⠀⡀⠀⠀⠄⠀⠂⠀⠀⠄⠀⢀⠁⠁⢁⠁⠆⠀⠀⠀⠀⡀⠀⠈⠀⡀⠀⠱⠀⠀⠀⠀⠂⢄⠈⠀⠀⡀⡨⠠⡀⠠⠀⠄⡼
⠠⠀⠁⠊⢀⠀⠠⠁⠁⠂⠂⡄⢄⠐⡀⢀⠊⠂⡀⡁⡀⢀⢀⠠⠀⠄⠂⠡⠠⠁⠀⠀⠀⠂⠀⢠⠒⠀⠀⠀⠐⠢⠀⢀⠀⠀⠄⠄⣿⣿
⠁⠋⠙⠊⠐⠕⠁⡂⠈⠅⠠⠈⠐⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠀⠉⠀⠐⠀⠀⠀⠀⠀⣈⠀⠀⠀⠀⠈⡂⠈⠀⠀⠘⠌⢀⠥
⠀⠀⠀⠀⠔⠔⠀⡀⡉⠀⠀⠀⠂⠠⠠⠀⠄⠄⠀⣀⢀⠀⡈⠀⠌⡐⠈⠈⠀⠀⠀⠀⠅⠀⣐⠉⠄⠀⠀⣂⠠⠁⡈⠀⠄⠄⢀⠣⢶⢿
⠄⠀⠀⡁⠀⠄⠀⠀⠁⠈⠀⠈⠀⠁⠀⠁⡀⠁⠀⠁⠀⠀⠀⡀⠀⠀⠀⠀⠀⠠⡀⠑⠀⠀⠎⠀⢬⢠⠀⢂⠠⠢⠠⠈⡐⠸⠀⡐⣹⢷
⠩⠥⠂⠆⡆⢠⠀⢄⠀⣀⡀⣄⠀⢈⠀⠀⣀⡀⡀⡀⠄⡄⠡⠀⠐⠀⠑⠀⠀⠁⠒⠒⠉⠡⡀⠈⠈⢀⠥⠈⠀⠀⠀⠀⠈⣞⣏⣿⡏⣿
⠾⠝⠷⢿⣯⣿⠧⡧⠭⠣⠭⡭⡮⢭⠶⠶⠶⠦⣗⡶⠽⠭⣿⣶⠷⠵⠮⠽⠿⠮⠿⢷⡶⣖⡷⠲⠞⠷⠾⢿⢷⣿⣿⣿⣿⣯⢇⠟⡧⢈
  

pipes

clean data flow without nesting

things flow from top to bottom

errors-as-values

nil and booleans are replaced by atoms

you can’t use a value without handling an error
all crashes are explicit (WIP)

aided massively by pattern matching, ? , orelse , and :unwrap()

everything is an expression

no statements, everything (really) always returns a value
…but the code still looks procedural

comp

execute any (really) expression at compile time

any script can be compiled into bytecode and get any value baked in

revo compile script.rv
revo script.rvo

the compile-time VM does not differ from the runtime one

procedural macros

along with an AST-substituting macro system,

this lets you just get an iterator over the raw ast tokens, run any code to transform them
, then return back a table of the new ast

pattern matching

destructure and branch in place

you will be using atoms and tuples, they are beautiful solutions to their problems

fibers

i made all your blocking code become non-blocking by just adding a spawn before it

tables

represent everything

used for
- module exports
- arrays
- maps

convenient typing

the type system is optional, but very well-integrated

untyped code works just fine, but

typed code is faster and gets optimized better (and ensures code correctness at compile-time!)
most of your code is going to be inferred automatically

first-class tests

they’re just closures and they fail when you return an error. the ? postfix operator propagates errors, giving you a pretty simple experience

get

the latest release is hosted at github releases

however, this project is rapidly changing. i recommend you build from source instead

install from source

you need zig 0.16.0 to build revo. i also recommend the anyzig version manager

linux/bsd/mac/etc

git clone https://github.com/if-not-nil/revo --recursive && cd revo
git submodule update --init --recursive
zig build --fetch
zig build -Doptimize=ReleaseSafe
                  # =ReleaseSmall for a ~1mb executable
                  # =ReleaseFast  for a ~5%-10% performance gain (harder to report bugs on)
cp ./zig-out/bin/revo ~/.local/bin/revo

revo

windows

[!NOTE]
some features are unavailable on windows. i recommend using WSL with the steps above

git clone https://github.com/if-not-nil/revo && cd revo
zig build --fetch -Doptimize=ReleaseFast

mkdir "C:/tools/revo/bin"
copy ./zig-out/bin/revo C:/tools/revo/bin

# now add it to PATH by doing:
# - Win+S -> `env` -> <Enter> -> "Environment Variables" -> "Path" -> "System Variables"
# - add new at "C:\tools\revo\bin" -> click ok -> reopen your terminal

revo

tools

editors

made with revo

  • please submit a project via issues/email/discord

credits

revo is licensed as MIT

~ isocline by daanx - MIT
~ lsp-kit by the zigtools team - MIT

Nvidia to buy developer platform Hugging Face in $12.9bn deal

Guardian
www.theguardian.com
2026-09-03 09:15:26
Semi-conductor giant bets that support for open AI models could offset potential slowdown in demand for chips Nvidia will buy the popular developer platform Hugging Face for nearly $13bn, betting that support for ⁠open AI models could offset a potential slowdown in demand for the semiconductor giant...
Original Article

Nvidia will buy the popular developer platform Hugging Face for nearly $13bn, betting that support for ⁠open AI models could offset a potential slowdown in demand for the semiconductor giant’s chips.

Shares ⁠in Nvidia were ⁠slightly lower ​after the $12.93bn (£9.57bn) deal – which ranks among its biggest ever – was announced for the database of AI models on Thursday.

The New York-based startup Hugging Face, which is backed by Intel, Advanced Micro Devices and Amazon, was founded in 2016 by the French entrepreneurs Clément Delangue, Julien Chaumond and Thomas Wolf.

The chipmaker is already a major open AI player in the US with ⁠its widely used Nemotron model and vocal support for the technology.

Acquiring Hugging Face will give it direct access to a platform developers use to ⁠collaborate, test and share tools, potentially providing insight and data that could help it narrow the ​technology gap with top American and ‌Chinese labs.

Demand for open-weight models ‌has surged from businesses balking at the steep bill of deploying the technology. Chinese companies ‌such as DeepSeek and Z.ai have emerged as crucial players with models that can match the best from the US in tasks including generating computer code at a lower cost.

There are fears that some US firms could become reliant on Beijing’s models even as both countries race to dominate a technology they see as crucial to their future.

“Hugging ‌Face will remain an open platform for the entire AI ecosystem,” said Nvidia’s chief executive, Jensen Huang, adding that his company’s chips would not be required to ​build on or deploy through Hugging Face.

Under the deal, Nvidia will pay about $11.9bn to Hugging Face investors, while offering an equity-based retention programme of up to $1bn for employees who join Nvidia.

skip past newsletter promotion

For Nvidia, building up its open source business may help it cushion a demand slowdown from customers such as ⁠Meta, OpenAI and Microsoft, which are developing their own AI chips to cut reliance ​on its costly and ​supply constrained processors.

Hugging Face has also been ​in the news recently after a hack by rogue AI agents that ​escaped OpenAI’s testing ‌environment. Beyond hosting AI ​models, it offers datasets, ​software libraries and cloud services used to build and deploy AI applications.

John Lewis to launch YouTube chatshow to improve AI search results

Guardian
www.theguardian.com
2026-09-03 09:08:54
Department store chain’s Gift List ‘vodcast’ will be hosted by TV presenter Angela ScanlonBusiness live – latest updatesJohn Lewis is launching an online chatshow and social media studio to help make itself and its products more visible to chatbots and more prominent in AI search results. The depart...
Original Article

John Lewis is launching an online chatshow and social media studio to help make itself and its products more visible to chatbots and more prominent in AI search results.

The department store chain’s Gift List “vodcast” hosted by the TV presenter Angela Scanlon will air on YouTube with clips disseminated via other social media channels and comes after the success of its sister chain Waitrose’s Dish podcast.

Angela Scanlon: she is in her early 40s and has long red hair. She wears a white linen shirt and blue jeans.
Angela Scanlon will host the Gift List ‘vodcast’. Photograph: Ken McKay/ITV/Shutterstock

The premise is guests discussing good and bad presents they have given and received, with the broadcaster Louis Theroux appearing on the first show. There will be six episodes running up to Christmas, with more planned if the series takes off.

Shoppers are increasingly influenced by the likes of ChatGPT and Gemini to find and recommend products and also by information on social media such as Instagram and TikTok. The AI large language models tend to prioritise third-party advice and live content when formulating their responses, which is forcing retailers to change their marketing plans.

The department store’s outgoing boss, Peter Ruis, said that a year ago just 0.3% of its customers were searching for products via AI large language models such as ChatGPT, but that had already risen to 2.5%, and usage was growing exponentially with all ages using the technology.

Being able to rapidly respond to trends and interests with clips of influencers or experts filmed for social media – such as the opening of the British Museum’s Bayeux tapestry exhibition, which is expected to spur an interest in cross stitching, or the launch of the Harry Potter TV series before Christmas – has become just as important as the group’s festive TV ad or its ‘never knowingly undersold ’ price pledge.

Ruis, who departs John Lewis this weekend after almost three years as managing director, said John Lewis had to move with the times as it faced an economy which was “a bit swirly”.

He said the chancellor’s budget announcements next month would come at a “critical period” for retailers and he wanted to see more help on business rates.

Peter Ruis at the John Lewis store in the Bluewater shopping centre. He stands in front of homeware displays and wears an unbuttoned dark grey double-breasted suit jacket.
Peter Ruis, the outgoing managing director who leaves this weekend, said he was optimistic for John Lewis in the run-up to Christmas. Photograph: Martin Godwin/The Guardian

Ruis said strong trading this week and a string of recent innovations, including modernised cafes and sports departments as well as the social media push and a recent “toy boom”, made him optimistic about the run-up to Christmas.

Details of John Lewis’s half-year figures will be released next week. Ruis said it had been a “summer of winners and losers” but indicated there was now “decent momentum” as shoppers still had money to spend.

The chain rang up record sales of garden furniture, fans and air conditioning over the summer but Ruis said it was not yet clear if the “Burnham bounce” over the summer would last. “People are not going to splurge when you have got inflation swirling,” he said.

skip past newsletter promotion

“It’s not an easy economy. It’s not easy for customers and inflation is kicking in and the fuel pump is costing people a lot of money.”

Ruis last month announced his abrupt departure , saying he was going to “pursue new projects”. He gave no further clue on his future plans on Thursday but said there was “no misalignment” on strategy with John Lewis’s relatively new chair, Jason Tarry.

“We are getting things done at pace,” Ruis said, adding there was “never a good time” to leave but it was “far better to leave a winning team at the top of its game and all that excitement with events next year to unveil, rather than finishing bottom of the league and running out of the door”.

Ruis insisted his departure did not indicate that he had lost hope in the future of John Lewis, saying it was not a traditional department store reliant on fashion and beauty like Harvey Nichols, which was bought out of administration by Sports Direct founder Mike Ashley’s Frasers Group last month.

He said John Lewis sold a third of all UK prams and pushchairs, garden furniture and the latest technology and “this is not stuff Harvey Nichols can sell”.

Security updates for Thursday

Linux Weekly News
lwn.net
2026-09-03 09:07:14
Security updates have been issued by AlmaLinux (freerdp, go-fdo-server, golang-github-openprinting-ipp-usb, kernel, kernel-rt, nodejs:24, perl-DBI, and php), Debian (firefox-esr, libapache2-mod-auth-openidc, and libass), Fedora (dracut, exiv2, firefox, freerdp, gvfs, mingw-expat, mingw-gstreamer1, m...
Original Article
Dist. ID Release Package Date
AlmaLinux ALSA-2026:62571 8 freerdp 2026-09-03
AlmaLinux ALSA-2026:62578 10 go-fdo-server 2026-09-03
AlmaLinux ALSA-2026:62631 10 golang-github-openprinting-ipp-usb 2026-09-03
AlmaLinux ALSA-2026:63014 8 kernel 2026-09-03
AlmaLinux ALSA-2026:63013 8 kernel-rt 2026-09-03
AlmaLinux ALSA-2026:62583 8 nodejs:24 2026-09-03
AlmaLinux ALSA-2026:62667 8 perl-DBI 2026-09-03
AlmaLinux ALSA-2026:62614 10 php 2026-09-03
Debian DSA-6481-1 stable firefox-esr 2026-09-02
Debian DLA-4768-1 LTS libapache2-mod-auth-openidc 2026-09-02
Debian DLA-4769-1 LTS libass 2026-09-02
Fedora FEDORA-2026-5bf73fe397 F45 dracut 2026-09-03
Fedora FEDORA-2026-2854e48ee4 F43 exiv2 2026-09-03
Fedora FEDORA-2026-208add2041 F43 firefox 2026-09-03
Fedora FEDORA-2026-42a3a95e62 F44 firefox 2026-09-03
Fedora FEDORA-2026-e0f5d28f57 F43 freerdp 2026-09-03
Fedora FEDORA-2026-571b7e1505 F43 gvfs 2026-09-03
Fedora FEDORA-2026-43f21f29dc F43 mingw-expat 2026-09-03
Fedora FEDORA-2026-f5e2a6b9b5 F44 mingw-expat 2026-09-03
Fedora FEDORA-2026-e6ca27403f F44 mingw-gstreamer1 2026-09-03
Fedora FEDORA-2026-e6ca27403f F44 mingw-gstreamer1-plugins-bad-free 2026-09-03
Fedora FEDORA-2026-bcfa11cd3b F43 mingw-gstreamer1-plugins-base 2026-09-03
Fedora FEDORA-2026-e6ca27403f F44 mingw-gstreamer1-plugins-base 2026-09-03
Fedora FEDORA-2026-bcfa11cd3b F43 mingw-gstreamer1-plugins-good 2026-09-03
Fedora FEDORA-2026-e6ca27403f F44 mingw-gstreamer1-plugins-good 2026-09-03
Fedora FEDORA-2026-bcc9ac580d F43 mingw-openexr 2026-09-03
Fedora FEDORA-2026-54d00b8af5 F44 mingw-openexr 2026-09-03
Fedora FEDORA-2026-208add2041 F43 nss 2026-09-03
Fedora FEDORA-2026-42a3a95e62 F44 nss 2026-09-03
Fedora FEDORA-2026-0abbe10cdc F43 proftpd 2026-09-03
Fedora FEDORA-2026-f073efe2f3 F44 proftpd 2026-09-03
Fedora FEDORA-2026-c33332bcf7 F44 syncthing 2026-09-03
Mageia MGASA-2026-0364 10, 9 apr-util 2026-09-02
Mageia MGASA-2026-0371 10 bubblewrap 2026-09-02
Mageia MGASA-2026-0369 10, 9 libalsa2 2026-09-02
Mageia MGASA-2026-0366 10, 9 libarchive 2026-09-02
Mageia MGASA-2026-0365 10, 9 perl-Net-OAuth 2026-09-02
Mageia MGASA-2026-0370 10, 9 perl-Text-CSV_XS 2026-09-02
Mageia MGASA-2026-0368 10, 9 perl-XML-Bare 2026-09-02
Mageia MGASA-2026-0367 10, 9 perl-YAML-Syck 2026-09-02
Oracle ELSA-2026-61379-0 OL9 freerdp 2026-09-02
Oracle ELSA-2026-61587-0 OL9 gimp 2026-09-02
Oracle ELSA-2026-60304-0 OL9 golang 2026-09-02
Oracle ELSA-2026-61389-0 OL9 iperf3 2026-09-02
Oracle ELSA-2026-59490 OL9 nginx:1.24 2026-09-02
Oracle ELSA-2026-61383-0 OL9 nodejs:22 2026-09-02
Oracle ELSA-2026-61386-0 OL9 nodejs:24 2026-09-02
Oracle ELSA-2026-61240-0 OL9 pipewire 2026-09-02
Oracle ELSA-2026-62142-0 OL10 wget 2026-09-02
Oracle ELSA-2026-62143-0 OL9 wget 2026-09-02
Oracle ELSA-2026-61316-0 OL9 xmlrpc-c 2026-09-02
Oracle ELSA-2026-38490 OL9 xorg-x11-server-Xwayland 2026-09-02
SUSE SUSE-SU-2026:23411-1 SLE-m6.2 MozillaFirefox, mozilla-nss, mozilla-nspr, rust-cbindgen 2026-09-02
SUSE SUSE-SU-2026:3952-1 SLE15 oS15.6 apache2-mod_auth_openidc 2026-09-03
SUSE openSUSE-SU-2026:21717-1 oS16.0 apache2-mod_auth_openidc 2026-09-02
SUSE SUSE-SU-2026:3928-1 SLE15 oS15.6 apptainer 2026-09-03
SUSE SUSE-SU-2026:3937-1 SLE15 oS15.3 apr-util 2026-09-03
SUSE SUSE-SU-2026:3938-1 SLE15 oS15.6 apr-util 2026-09-03
SUSE SUSE-SU-2026:3925-1 SLE12 bzip2 2026-09-02
SUSE openSUSE-SU-2026:21721-1 oS16.0 c-ares 2026-09-02
SUSE SUSE-SU-2026:3954-1 SLE15 oS15.4 cosign 2026-09-03
SUSE SUSE-SU-2026:23400-1 SLE-m6.2 dhcpcd 2026-09-02
SUSE SUSE-SU-2026:3919-1 SLE12 dovecot22 2026-09-02
SUSE openSUSE-SU-2026:21711-1 oS16.0 emacs 2026-09-02
SUSE SUSE-SU-2026:3951-1 SLE15 oS15.3 erlang 2026-09-03
SUSE openSUSE-SU-2026:21731-1 oS16.0 gegl 2026-09-02
SUSE openSUSE-SU-2026:11650-1 TW gopass 2026-09-02
SUSE SUSE-SU-2026:23392-1 SLE-m6.2 gzip 2026-09-02
SUSE openSUSE-SU-2026:11647-1 TW httpcomponents-client 2026-09-02
SUSE openSUSE-SU-2026:11651-1 TW incus 2026-09-02
SUSE openSUSE-SU-2026:11648-1 TW kernel-devel 2026-09-02
SUSE SUSE-SU-2026:23407-1 SLE-m6.2 libgpg-error 2026-09-02
SUSE SUSE-SU-2026:3936-1 SLE15 SLE5.3 SLE5.4 SLE5.5 SLE-m5.3 SLE-m5.4 SLE-m5.5 oS15.4 libsoup2 2026-09-03
SUSE openSUSE-SU-2026:21713-1 oS16.0 mozillafirefox, mozilla-nss, mozilla-nspr, 2026-09-02
SUSE SUSE-SU-2026:3930-1 SLE15 oS15.5 nodejs20 2026-09-03
SUSE SUSE-SU-2026:3929-1 SLE15 oS15.6 nodejs20 2026-09-03
SUSE openSUSE-SU-2026:21728-1 oS16.0 orthanc, orthanc-authorization, orthanc-postgresql, 2026-09-02
SUSE SUSE-SU-2026:3944-1 SLE15 oS15.6 postgresql14 2026-09-03
SUSE SUSE-SU-2026:23404-1 SLE-m6.2 python-cryptography 2026-09-02
SUSE SUSE-SU-2026:3932-1 SLE15 oS15.4 python-msgpack 2026-09-03
SUSE SUSE-SU-2026:3950-1 oS15.4 quagga 2026-09-03
SUSE openSUSE-SU-2026:11653-1 TW snpguest 2026-09-02
SUSE openSUSE-SU-2026:11654-1 TW snphost 2026-09-02
SUSE SUSE-SU-2026:3924-1 SLE12 texlive 2026-09-02
SUSE openSUSE-SU-2026:11645-1 TW tuxguitar 2026-09-02
SUSE SUSE-SU-2026:23405-1 SLE-m6.2 udisks2 2026-09-02
SUSE SUSE-SU-2026:23391-1 SLE-m6.2 vim 2026-09-02
SUSE SUSE-SU-2026:23393-1 SLE-m6.2 vim 2026-09-02
SUSE openSUSE-SU-2026:11646-1 TW wget 2026-09-02
SUSE SUSE-SU-2026:3946-1 MP4.3 SLE15 oS15.4 yast2-users 2026-09-03
SUSE SUSE-SU-2026:3947-1 SLE15 oS15.5 yast2-users 2026-09-03
SUSE SUSE-SU-2026:3948-1 SLE15 oS15.6 yast2-users 2026-09-03
Ubuntu USN-8719-1 14.04 16.04 18.04 20.04 22.04 24.04 26.04 apr-util 2026-09-03
Ubuntu USN-8713-1 22.04 24.04 26.04 biosig 2026-09-02
Ubuntu USN-8714-1 18.04 20.04 linux, linux-aws, linux-azure, linux-azure-fips, linux-fips, linux-hwe-5.4, linux-ibm, linux-ibm-5.4, linux-iot, linux-kvm, linux-oracle, linux-raspi, linux-raspi-5.4, linux-xilinx-zynqmp 2026-09-02
Ubuntu USN-8661-4 20.04 linux-aws-5.15, linux-gcp-5.15 2026-09-02
Ubuntu USN-8715-1 18.04 linux-oracle-5.4 2026-09-02
Ubuntu USN-8718-1 16.04 18.04 20.04 22.04 24.04 26.04 sssd 2026-09-03
Ubuntu USN-8717-1 20.04 22.04 tika 2026-09-03

How to Guarantee You Never Ship

Lobsters
kore-nordmann.de
2026-09-03 09:00:52
Comments...
Original Article

How to Guarantee You Never Ship

This is a blog article out of a series where I reflect on what I learned during funding, growing (, and selling) SaaS product companies . While I write those things down for myself, since I believe self-reflection helps me learn, I also want to share my thoughts with anybody who might be interested. An overview of all related topics can be found below. I have a bunch of these blog posts lined up, so you also might want to follow me if you like this one.

In a run of posts I have argued against a handful of things one at a time: splitting code across many repositories, long-lived feature branches, reaching for microservices to model separation, dedicated quality assurance, one fixed test coverage target for every change, and pull-request review as your quality gate. Each of those is a problem on its own. This post is about adopting all of them at once, which is more common than it should be, because each arrives wearing the badge of a best practice.

So let me write the inverse of everything else in this series. If your goal were to build an organisation that never delivers anything, while every individual decision still looked responsible in the meeting where it was made, here is how you would do it.

The recipe

Start by splitting your system across many repositories, one per service or team, for clean ownership. Then let work happen on long-lived feature branches, because that is how serious features get built. Make sure those branches span several repositories at once, so a feature is never contained in one place. Cut the system into as many microservices as you can, ideally small ones, so every interaction crosses the network. Require a reviewed pull request before any merge, in every repository, and gate each one on 90% test coverage, so nothing merges until it is covered. And put a dedicated QA stage at the end, to catch what all of that let through.

Every step there is defensible in isolation. Together they are a delivery-proof machine.

Coordination boundaries multiply, they do not add

Here is the part that makes it lethal rather than merely annoying. Each of those choices adds a coordination boundary, and coordination boundaries do not add up. They multiply.

Take one small change: you add a field to a concept that several parts of the system share. Watch it travel. It touches four repositories, so it is four pull requests, not one, each reviewed by someone with only their slice in view, each merged in an order that matters. Each of them has to clear the coverage gate on its own, so a one-field change needs tests written around it in four places before any of it merges. Those repositories are on long-lived branches, so each pull request also has to survive a merge against weeks of drift. The parts talk over the network, so the field has to be added on both sides of every boundary it crosses, and the two sides are deployed separately, so for a while production is running a mix that has the field in some places and not others. Now QA is handed the result and asked to test it, and the first question is the honest one: which combination of versions is even deployed where, and what, exactly, are we testing?

Nobody can answer that, because the number of combinations is the product of all the axes you added, not their sum. Four repositories times several in-flight branches times a dozen services times a per-repository review queue times a coverage gate on every pull request multiplies the cost of shipping one coherent change.

And that is only the mechanical part. The field also needs a name, and everyone whose slice it crosses has an opinion informed by implicit knowledge of that slice and by their own taste in naming. Left alone they do not converge: the same concept ends up as customerType in one repository, accountCategory in the next, and an enum with different members in the third. So the four of them have to talk, and if the field shows up in what customers see, the chief technology officer ( CTO ) and the chief product officer ( CPO ) have a stake in what it is called too.

None of that is waste. In one checkout those same people still have the same discussion, in the pull request or standing at a whiteboard, and it converges because there is one place where the answer lands. Across four repositories the discussion turns into a merge prerequisite in four queues: nothing moves until it resolves, it resolves at the speed of the slowest calendar involved, and the first name anybody committed is now the one three other repositories have to be changed to match. Nobody in that room is the problem. The problem is that one line of code waits for the room.

You did not slow delivery down. You designed it to be impossible and called each step an improvement.

Why it happens

The unsettling thing is that no one sits down to build this. In 1944 somebody did: the US Office of Strategic Services, the wartime predecessor of the CIA, wrote a sabotage manual for occupied Europe, and its chapter on organisations reads like a process document. Insist on doing everything through channels. Refer every matter to a committee, and make the committee as large as possible. Haggle over precise wordings. Advocate caution. See that three people have to approve everything where one would do. The difference between that and a delivery pipeline nobody can ship through is intent, and only intent.

Ours accretes. Each layer is added by a reasonable person solving a real, local problem with a practice they read was correct. Separate repositories for clean ownership. Branches for isolation. Services for scalability. Reviews for quality. A coverage number so quality is measurable. A QA stage for safety. The failure is that nobody is watching the product of them: each was justified on its own terms, and the interaction effect has no owner.

And once it is in place, noone can see a change whole. The system that was split for clarity is now the system no one can hold in their head, or in one checkout, at all.

The way out is subtraction

Every post in this series has been, quietly, the same argument from a different angle, and this is the place to say it plainly. The principle is: minimise coordination surfaces, and make every boundary you add pay for itself.

That is what each piece of advice was. One repository removes the cross-repository axis. Trunk-based development with feature flags removes the long-lived-branch axis. In-process boundaries instead of reflexive microservices removes the network axis. Quality owned by the team removes the hand-off-to- QA axis. Synchronous review removes the pull-request-queue axis. Coverage decided by stage removes the gate that taxes every change regardless of whether the code will still exist next month. None of them is a productivity trick. Each one deletes a multiplier.

Boundaries are not free, and sometimes one earns its keep: a service that must scale on its own, a repository for code you genuinely publish to strangers, a flag for a customer you are stuck supporting. Keep those. The discipline is refusing every boundary that does not pay, because the ones that do not are not neutral. They multiply against all the others.

Summary

The scary part is not any single one of these practices. It is the compounding. Adopt multi-repo, long-lived cross-repo branches, reflexive microservices, dedicated QA , a blanket coverage target, and per-repo pull-request review together, and you have built, from nothing but respectable decisions, an organisation that cannot ship a coherent change. The fix is not a better process on top. It is subtraction: count the coordination surfaces a single change has to cross, and start removing the ones that do not earn their place.

AI Could Revolutionize Medicine, But Humans Must Be in Charge: Researcher Shreya Johri

Democracy Now!
www.democracynow.org
2026-09-03 08:46:07
As part of our ongoing series on artificial intelligence, we speak with researcher Shreya Johri, who says AI has the power to revolutionize the field of medicine, particularly in diagnosing patients. Johri is a postdoctoral fellow at the Dana-Farber Cancer Institute and completed her Ph.D. at Harvar...
Original Article

Image Credit: Accuray/Unsplash

As part of our ongoing series on artificial intelligence, we speak with researcher Shreya Johri, who says AI has the power to revolutionize the field of medicine, particularly in diagnosing patients. Johri is a postdoctoral fellow at the Dana-Farber Cancer Institute and completed her Ph.D. at Harvard Medical School in 2025. She discusses ways that new technology is improving patient care, but she says AI must be treated like an additional tool and not be given control over patient care. “Doctors have to be responsible, have to take the responsibility of this, until we are more confident we have frameworks developed that can deploy these AI models in a more responsible way,” she says.



Guests

Please check back later for full transcript.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Black Box: The Chatbots | Spirals | Ep 1 – podcast

Guardian
www.theguardian.com
2026-09-03 08:42:54
Across the world, hundreds of people have come to believe they have made extraordinary scientific discoveries with AI chatbots such as ChatGPT, Claude and Gemini. Others say their AI has ‘awakened’, or is leading them to a higher spiritual realm. The Guardian journalist Michael Safi begins investiga...
Original Article

Across the world, hundreds of people have come to believe they have made extraordinary scientific discoveries with AI chatbots such as ChatGPT, Claude and Gemini. Others say their AI has ‘awakened’, or is leading them to a higher spiritual realm. The Guardian journalist Michael Safi begins investigating a phenomenon labelled ‘AI psychosis’, travelling to the US to meet two people who have been on weird journeys with their chatbots

"Modern-Day Poll Tax": Dem. Texas Commissioner Slams GOP Vote to Close 92 Polling Sites

Democracy Now!
www.democracynow.org
2026-09-03 08:34:02
Ahead of the November midterm elections, Republican officials in the third most populous county of Texas have voted to slash the number of polling sites by nearly one-third. Tarrant County, which includes Fort Worth, will have just 224 polling sites for 1.3 million voters. The change was approved in...
Original Article

Ahead of the November midterm elections, Republican officials in the third most populous county of Texas have voted to slash the number of polling sites by nearly one-third. Tarrant County, which includes Fort Worth, will have just 224 polling sites for 1.3 million voters. The change was approved in a party-line vote Tuesday, with all three of the county’s Republican commissioners voting in favor and the two Democrats opposing it. Civil rights groups including the ACLU and NAACP warn the changes will disproportionately affect voters of color.

“The eyes of the nation are on Tarrant County,” says Roderick Miles Jr., a Democratic Tarrant County commissioner, who calls the voting restriction a “modern-day poll tax.”


Please check back later for full transcript.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

"Catastrophic Failure": Postal Service Whistleblower Warns Mail-In Voting Rules Could Derail Election

Democracy Now!
www.democracynow.org
2026-09-03 08:21:28
An anonymous federal whistleblower has warned that the Trump administration’s new system for handling mail ballots through the U.S. Postal Service is untested, fatally flawed and likely to lead to a “catastrophic failure” if it’s implemented ahead of November’s midterm ...
Original Article

An anonymous federal whistleblower has warned that the Trump administration’s new system for handling mail ballots through the U.S. Postal Service is untested, fatally flawed and likely to lead to a “catastrophic failure” if it’s implemented ahead of November’s midterm elections. This follows President Trump’s executive order in March directing his administration to create federal lists of citizens and to refuse delivery of mail-in ballots to people not on those lists. The legality of Trump’s executive order is being challenged.

The new hurdles raised by the executive order for mail ballots and the rushed software system built to administer them “create this potential for grave, catastrophic failure,” says David Kligerman from Whistleblower Aid, the organization representing the whistleblower.



Guests

Please check back later for full transcript.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Microsoft says KB5120998 Windows update resets desktop settings

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 08:16:32
Microsoft has confirmed that desktop settings are lost or reset on some Windows devices after installing the KB5120998 August 2026 preview update. [...]...
Original Article

Windows 11

Microsoft has confirmed that desktop settings are lost or reset on some Windows devices after installing the KB5120998 August 2026 preview update.

Microsoft's confirmation follows a wave of user reports saying their wallpaper switched to a black background automatically after installing this Windows update.

The known issue impacts systems running Windows 11 24H2 and Windows 11 25H2, and it may affect the wallpaper, the desktop theme, and various other settings.

"Following installation of Windows updates released August 27 2026 (KB5120998) and later, some Windows Desktop settings fail to load, resulting in desktop backgrounds displaying as a solid black color," Microsoft said in a Windows release health update on Wednesday. "It is possible other desktop settings may be affected, such as slideshow settings or contrast themes."

According to Microsoft, because of this bug, users will also be unable to restore their custom settings on affected devices.

"On affected devices, attempting to manually restore customized settings does not work. This is because the issue prevents the correct loading of settings, regardless of their value. In this case, a default black background is used instead," the company added.

KB5120998 was released on August 27 with Start menu, taskbar, and Windows search improvements for Windows 11 versions 25H2 and 24H2.

As Microsoft acknowledged one day later, this preview update also changes or resets mouse settings and makes it impossible for affected users to restore the previous settings after they are reverted.

Since KB5120998 is an optional, non-security update, users must click the "Download and install" link. However, if they already have the "Get the latest updates as soon as they're they're available" option enabled, the update will install automatically.

Microsoft addressed a similar bug six years ago, in February 2020, after the KB4539602 update broke desktop wallpaper functionality and caused Windows 7 wallpapers in 'Stretch' mode to display a blank black screen.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

Gloria Steinem, Feminist Icon & Ms. Magazine Co-Founder, Dies at 92

Democracy Now!
www.democracynow.org
2026-09-03 08:14:11
Feminist icon Gloria Steinem has died at the age of 92. According to her Instagram page, she died Wednesday “at her home in New York City, surrounded by some of the many who loved her.” Steinem was a tireless advocate for the social, economic and political advancement of women. Steinem c...
Original Article

Image Credit: Left: Bettye Lane/Photo Researchers History/Getty Images Right: Shannon Stapleton/Reuters

Feminist icon Gloria Steinem has died at the age of 92. According to her Instagram page, she died Wednesday “at her home in New York City, surrounded by some of the many who loved her.” Steinem was a tireless advocate for the social, economic and political advancement of women. Steinem co-founded Ms. magazine, the first major publication to be owned, run and written by women. She also helped found the National Women’s Political Caucus with a group of women including Shirley Chisholm, Betty Friedan and Fannie Lou Hamer. Before becoming a feminist icon, she served as director of the Independent Research Service, a nonprofit educational foundation secretly funded by the CIA . In 2013, she received the Presidential Medal of Freedom from President Barack Obama. She spoke with Democracy Now! at the historic Women’s March in Washington, D.C., on January 21, 2017. We play an excerpt.



Guests

Please check back later for full transcript.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Nvidia to Acquire Hugging Face

Hacker News
blogs.nvidia.com
2026-09-03 08:10:33
Comments...
Original Article

I’m excited to announce that NVIDIA has agreed to acquire Hugging Face for $12,930,300,000. Together, we will scale Hugging Face’s platform, strengthen its infrastructure and expand access to AI for developers and institutions worldwide.

Over the past decade, Clem, Julien, Thomas and the team at Hugging Face have built something remarkable: a vibrant home for the open model developer community.

More than 18 million developers, researchers and creators use Hugging Face to share more than 3 million models, 500,000 datasets and 1 million applications. More than 200,000 companies use the platform to discover, evaluate, customize and deploy AI.

Hugging Face will remain an open platform for the entire AI ecosystem. Developers will choose the models they want, the frameworks they want, the clouds and inference service providers they want and the computing platforms they want. NVIDIA compute will not be required to build on or deploy through Hugging Face.

Hugging Face will continue to support open source and open weight models from across the ecosystem, from every model builder. It will continue to support multi-cloud and multi-accelerator development and deployment, so builders can use the hardware and infrastructure that best fit their work.

Recently, I coauthored an open letter on the importance of open weights to the AI economy. Joined by leaders from across the industry, we made a simple point: open weights broaden access to AI and help ensure that AI leadership is distributed across companies, institutions and communities.

Open models let startups, businesses, universities and public institutions build on advanced capabilities without training every model from scratch. They enable organizations to match the right model to the right job. That is how AI can advance safely, strengthen cybersecurity and sovereignty, accelerate innovation, and reach factories, hospitals, farms, classrooms and Main Street businesses around the world.

AI advances faster when people can build together.

NVIDIA has been committed to open weight models for years, demonstrated by multiyear investments and major contributions to open source platforms, including Hugging Face. NVIDIA has said that open models, data and tools broaden access to AI, and it has contributed hundreds of open models and datasets to Hugging Face as part of that effort.

  • NVIDIA is the largest contributor of open models and data to Hugging Face, and our contributions continue to grow.
  • NVIDIA has released more than 500 models on Hugging Face and more than 250 open datasets.
  • We build our own models, libraries and tools in the open so developers everywhere can use them, modify them and build on top of them.

As the opportunity for open models accelerates, Hugging Face can serve the global AI community at unprecedented scale. NVIDIA’s infrastructure, engineering and global reach can help improve platform reliability, safety, model evaluation, inference and deployment capabilities, while preserving the open ecosystem that made Hugging Face foundational.

I am honored that Clem came to me as he considered the next chapter of Hugging Face and believed NVIDIA would be a great home for the company, its community and the future of open models. We share this vision, and the Hugging Face team will now bring their passion and expertise to a much larger canvas, with their same iconic 🤗 brand.

To the millions of builders on Hugging Face: thank you for pushing the boundaries of what is possible. We can’t wait to build the future together with you. Together, we will make AI more open, more capable and more accessible to people and institutions around the world.

Nvidia to acquire Hugging Face

Hacker News
www.cnbc.com
2026-09-03 08:10:33
Comments...
Original Article

Nvidia CEO Jensen Huang on Hugging Face deal: Open models matter greatly to our company

Nvidia has officially agreed to buy open-source artificial intelligence platform Hugging Face for $12.9 billion, as the chipmaker moves beyond hardware and further up the AI stack.

With the deal, which has been expected since The Information reported on it last week, Hugging Face will "remain an open platform for the entire AI ecosystem," Nvidia CEO Jensen Huang wrote in a blog post Thursday.

"Together, we will scale Hugging Face's platform, strengthen its infrastructure and expand access to AI for developers and institutions worldwide," Huang wrote.

Hugging Face CEO Clément Delangue told CNBC on Thursday that the company approached Huang over the summer about a deal, "and a few weeks later, here we are."

"During the summer, I think we realized that Hugging Face and open-source AI in general was at the turning point, and that it needed more, more resources, more scale, more visibility," he told CNBC's Becky Quick on " Squawk Box ."

Nvidia to buy Hugging Face, an open-source AI platform, for $12.9 billion

Delangue said he approached first because Nvidia was "a perfect home" for his company, adding that discussions went quite fast to get a deal done.

The acquisition marks Nvidia's second biggest on record, following the $20 billion purchase of assets from chipmaker Groq in December. Before that, its largest deal was the purchase of Israeli chipmaker Mellanox for almost $7 billion in 2019.

Nvidia has become the world's most valuable company due to the insatiable demand for its graphics processing units, which have powered the generative AI boom. Hugging Face marks a big bet on a popular AI platform, as Nvidia continues to show that it's more than just a chip company.

Hugging Face was recently at the center of a hacking incident that raised concerns about the rapid evolution of powerful AI and cybersecurity tools.

Delangue, a proponent of open-source models, blamed engineering mistakes for the recent attack on Hugging Face and said his company used an Nvidia version of a Chinese open model to resolve it.

On Thursday, Delangue told CNBC that the breach proved the importance of open models and the need for his company to "double down" on the proliferation of open-source AI.

Huang said that the open-source environment can give defenders an "asymmetric advantage" over attackers.

"When I say asymmetric capability, there are way more people who are protecting than there are people who are attacking," he explained. "And so, the benefit of having the community come together with open models, so that they can collaborate all transparently with each other, gives the defenders an asymmetric advantage."

WATCH: Huang says 'We're at the beginning of an industrial revolution'

Nvidia CEO Jensen Huang to CNBC: 'We're at the beginning of an industrial revolution'

9 Mothers (YC P26) Is Hiring in Austin, TX

Hacker News
9mothers.com
2026-09-03 08:00:52
Comments...
Original Article

[ CAREERS · 9 MOTHERS ]

· 11 open roles

Build counter-drone systems in Austin.

We ship hardware on software tempo — AI perception, kinetic engagement, and the kill chain that closes them. Hard problems, real deployment, short iteration loops, and the people doing the work own the spec.

Loc
Austin, TX

[ WHY 9 MOTHERS ]

Why this team. Why now.

If you've ever shipped hardware inside a slow program of record and thought we should be doing this in months, not years — this is the team for you.

  1. 01

    The work is the perk.

    Autonomous perception, terminal engagement, manufacturable hardware — designed and built in one room. You'll own a system, not a Jira ticket.

  2. 02

    Short loops, real telemetry.

    Range time, range data, range fixes. We instrument what we build and we iterate on what the data tells us — not on what the roadmap deck promised six months ago.

  3. 03

    Operators are users.

    Mass, setup time, and human factors are first-class specs. The people carrying it are in the loop from week one — not at acceptance testing.

  4. 04

    Built to be afforded.

    Cost-per-shot, serviceability, and manufacturability are design constraints. We're building weapons the U.S. and its allies can afford to use at scale.

[ A DAY ON THE LINE ]

What the work looks like.

  1. 01 Range setup. Coffee. Comms check.
  2. 02 Live-fire iteration on yesterday's filter taps.
  3. 03 Operator debrief over food trucks.
  4. 04 Bench rework. Solder. Print. Re-flash.
  5. 05 Next-day spec on the whiteboard.

Austin · onsite · range adjacent

[ OPEN ROLES ]

Currently hiring.

We're hiring across audio ML, DSP, systems, and software. If you don't see the exact role but you'd be the right person, send us a note anyway.

Hardware Engineering

6 roles

Software Engineering

2 roles

View on Ashby

[ DON'T SEE YOUR ROLE? ]

Talk to us anyway.

Recruiters should not contact us.

Apocalypse prep or pure pragmatism: what is behind Peter Thiel’s move to Argentina?

Guardian
www.theguardian.com
2026-09-03 08:00:29
Relocation coincides with proposed laws that opponents say would entrench power of US tech billionaires in country Dozens of protesters converged on Peter Thiel’s mansion in Buenos Aires this week after a congressional session raised questions about the billionaire’s presence in the country. In whit...
Original Article

Dozens of protesters converged on Peter Thiel’s mansion in Buenos Aires this week after a congressional session raised questions about the billionaire’s presence in the country.

In white masks, they held signs saying “Peter Thief” and “No to the Peter Thiel law” in front of the wrought-iron gates of the $12m (£8.9m) residence, which Thiel bought in April as he moved his family to Argentina .

There is broad unease at the tech magnate’s presence in the country. His move has been characterised as part of a plan to hedge against world war three: Argentina, agriculturally rich and deep in the southern hemisphere, might just be the ideal place for a tech billionaire to wait out the apocalypse .

But recent developments in the country suggest Thiel could have more pragmatic considerations.

Protesters are holding megaphones and signs and wearing white masks
Protesters marched to the gates of the $12m residence Peter Thiel bought when he moved his family to Argentina in April. Photograph: Tomás Cuesta/Reuters

Last week, Argentina’s chamber of deputies held a six-hour debate on a set of sweeping regulatory changes put forward by Javier Milei’s rightwing government shortly after Thiel moved to Buenos Aires. They invited Thiel, Milei and an official linked to Argentina’s intelligence services to answer questions.

“None of them answered, and none of them came to the meeting,” said Juan Marino, a member of the chamber of deputies and the leader of the Piquetero party.

Marino said the new laws amounted to a “technofascist legislative package” aimed at entrenching the power of US tech billionaires in the country. Thiel has not publicly advocated for them, but Marino and others have said that their timing was suggestive.

The meeting in the chamber of deputies came after Argentinian deputies from several parties made public requests to the government for information about Thiel, his meetings and his businesses. None have been answered.

Peter Thiel
Peter Thiel held closed-door meetings with Javier Milei and key presidential advisers in the months after he moved to Argentina. Photograph: Gage Skidmore/Zuma Press Wire/Shutterstock

One of the laws, the “ super RIGI ”, would put in place an investment regime offering foreign companies a minimal tax rate and a 30-year guarantee against regulatory change. It specifically names AI datacentres among investments it hopes to attract.

Another, which failed, aimed to eliminate most of the restrictions around foreigners buying land in Argentina. A final decree would require some civilian government departments to share vast amounts of personal data on Argentinian citizens with the state intelligence services.

There is no evidence that Thiel has advocated for these laws directly. But in the months after he moved to Buenos Aires, he held closed-door meetings with Milei and key presidential advisers. It is uncommon for a foreign investor to have this degree of access.

In the regulatory package, Marino and others see the footprint of Thiel’s larger techno-libertarian interests.

The decree that gives vast amounts of Argentinians’ personal data to state intelligence services comes as Argentinian deputies have asked increasingly pointed questions about whether Palantir, the company Thiel co-founded, has undisclosed contracts with the state, which have gone unanswered.

Protesters holding placards that say ‘Peter Thief’ and wearing white masks
One of the proposed laws protesters oppose would offer foreign companies a minimal tax rate and a 30-year guarantee against regulatory change. Photograph: Tomás Cuesta/Reuters

The land law, said Marino, could have paved the way for semi-autonomous “startup cities” – such as the controversial Próspera development in Honduras – that Thiel has advocated as a way for libertarians to carve out zones outside state control.

“Argentina is kind of a laboratory,” said Cecilia Nicolini, who represents Argentina at the Mercosur regional parliament. US tech billionaires, she said, “are using Argentina as a laboratory, because they have a person in power, Milei, who is even more crazy than they are”.

Over the summer Milei wrote an article in the Financial Times advocating the creation of “non-human corporations” – “entities operated by AI agents or robots”.

It parallels a vision put forward by OpenAI’s chief executive, Sam Altman, who predicted in 2024 that the world could soon be run by AI-owned companies. It also raises dark, thorny questions about the legal liabilities of those entities.

Nicolini said: “It’s not just that [Thiel] chose Argentina in terms of, it’s a secure place to live in a world that is facing a number of wars, etcetera.

“But really, behind it, I think there is a clear plan. And it is related to reforms that Milei is trying to pass, with some success in some cases, and in others, backlash.”

Thiel was approached for comment.

Headlines for September 3, 2026

Democracy Now!
www.democracynow.org
2026-09-03 08:00:00
Iran’s Red Crescent Asks ICC to Investigate U.S. Strike on Wedding That Killed Four, Widow of Airman Who Died Supporting U.S. Attacks on Iran Says She Was Denied Benefits, USS Abraham Lincoln Docks in Thailand After Unprecedented Wartime Deployment, Trump Nominates Hung Cao as Navy Secretary a...
Original Article

Headlines September 03, 2026

Watch Headlines

Iran’s Red Crescent Asks ICC to Investigate U.S. Strike on Wedding That Killed Four

Sep 03, 2026

Iran has claimed new drone and missile attacks on U.S. military bases in the Persian Gulf in retaliation for recent U.S. strikes inside Iran. Iran’s military said it struck satellite communications systems, warehouses and fighter jet hangars at Ahmad al-Jaber Air Base in Kuwait. Separately, it said missiles and drones targeted U.S. troops and radar stations at Al Minhad Air Base in the United Arab Emirates.

The attacks follow U.S. strikes across southern Iran Tuesday that Iran’s health minister said killed 18 civilians and wounded over 100. The toll includes four people killed and 67 wounded when the U.S. bombed a wedding ceremony in Sirik. On Wednesday, the Iranian Red Crescent asked the International Criminal Court to investigate the attack as a “war crime.”

At the United Nations, a spokesperson said Secretary-General António Guterres is “deeply alarmed by reports of civilian casualties.”

Stéphane Dujarric : “The secretary-general condemns all attacks against civilians. He recalls that all parties must respect their obligations under international humanitarian law, including the principles of distinction, proportionality and precaution.”

At the White House, President Trump said Wednesday that renewed fighting with Iran will not last “too long,” but added that the U.S. is ready to strike Iran “at any time.” Meanwhile, Trump claimed in a social media post that the Strait of Hormuz is under U.S. control, and mused that he might change the name of the waterway to ” TRUMP STRAIT ???”

Widow of Airman Who Died Supporting U.S. Attacks on Iran Says She Was Denied Benefits

Sep 03, 2026

The Air Force is reviewing the case of a Gold Star widow from Alabama who wrote that she was deemed ineligible for additional benefits following her husband’s death because Congress had not officially declared U.S. attacks on Iran as a “war.” That’s according to a report in NOTUS , or News of the United States, which reports that military officials spoke Monday with Libby Klinner, the wife of Major John Alexander Klinner, one of six service members killed in a plane crash during a refueling mission over Iraq on March 12.

This comes as Commerce Secretary Howard Lutnick is under fire for declaring that there haven’t been American deaths during the U.S. and Israeli war on Iran. Lutnick made the remark in a wide-ranging CNBC interview Wednesday.

Commerce Secretary Howard Lutnick : “The way the president is playing Iran — right? — there’s not — there haven’t been American deaths. It’s really just an economic choke-out.”

USS Abraham Lincoln Docks in Thailand After Unprecedented Wartime Deployment

Sep 03, 2026

Nearly 5,000 U.S. sailors and Marines have arrived in Thailand for a five-day shore leave, after their aircraft carrier, the USS Abraham Lincoln, spent a record 286 days at sea in support of the U.S. and Israeli war on Iran. The carrier had been plagued by reports of thin and poor-quality rations, toilet and plumbing problems, and mental health emergencies including multiple attempts by sailors to jump overboard.

Trump Nominates Hung Cao as Navy Secretary as GOP Lawmakers Call for Pete Hegseth’s Ouster

Sep 03, 2026

President Trump has nominated acting Navy Secretary Hung Cao to assume the role permanently. Cao is a naval combat veteran who’s led efforts to reinstate military members discharged for refusing a COVID vaccine mandate. He’s a close ally of President Trump and Defense Secretary Pete Hegseth. During the 2024 Virginia Senate debates, Cao made headlines for these comments.

Hung Cao : “When you’re using a, you know, drag queen to recruit for the Navy, that’s not the people we want. Look, what we need is alpha males and alpha females who are going to rip out their own guts, eat them and ask for seconds.”

Cao has led the Navy in an acting capacity since April, when President Trump fired Navy Secretary John Phelan. His nomination comes days after Army Secretary Dan Driscoll resigned, following reports he’d repeatedly clashed with Defense Secretary Pete Hegseth over the Pentagon’s removal of seasoned commanders and refusal to promote women and people of color.

On Wednesday, North Carolina Republican Senator Thom Tillis praised Driscoll’s tenure and called on President Trump to remove Hegseth. Tillis wrote, “I have never witnessed more inept management of the brave men and women who serve our country. He is intimidated by competence and retreats to ginning up culture wars instead of soberly attending to the vital work of our national defense and the health and well-being of our fighting force.” Tillis is not seeking reelection in November. Also joining the call for Hegseth to step down is Republican Nebraska congressmember and retired Air Force Brigadier General Don Bacon, among a number of other Republicans.

Israeli Soldiers Fatally Shoot Two Palestinian Teens in Occupied West Bank

Sep 03, 2026

In the occupied West Bank, two Palestinian teenagers were shot and killed by Israeli soldiers Wednesday as settlers and troops entered the village of al-Mughayyir. The victims were identified as 19-year-old Omar al-Naasan and 16-year-old Khalil Shehadeh. Eyewitnesses say snipers opened fire after Palestinian residents confronted settlers who were stealing their sheep.

Meanwhile, Israel has razed the Palestinian village of Khirbet al-Tabban in the Masafer Yatta region, after ordering residents to evacuate their homes. Israel’s military had declared the area a restricted military training zone — even though settlers have been establishing outposts and farms in the area. According to B’Tselem, Israel has expelled 66 Palestinian communities from their homes since October 2023.

This comes as retired Israeli generals are publicly accusing settlers in the West Bank of committing ethnic cleansing with government support. Asaf Agmon, a retired Air Force general, told The New York Times, “Once a society behaves this way, that society is doomed.”

Israeli Defense Minister Seeks Trump’s Support for Plans to Expel Palestinians from Gaza

Sep 03, 2026

Israel’s Defense Minister Israel Katz said Wednesday he’s seeking President Trump’s support for plans to permanently expel Palestinians from the Gaza Strip. Katz made the remarks during a conference in Jerusalem where he declared, “There is no real solution for Gaza in the end without migration.”
In response, Maryland Democratic Senator Chris Van Hollen wrote on social media, “After our trip to the Gaza-Egypt border last year, Senator Jeff Merkley and I released a report entitled, 'The Netanyahu Government is Implementing a Plan to Ethnically Cleanse Gaza of Palestinians.' Now the Israeli Ministry of Defense confirmed that’s the goal. We must end our complicity.”

Death Toll from Nepal Floods Tops 1,200 People

Sep 03, 2026

In Nepal, the death toll from the deadly floods has topped 1,200 people, with thousands missing. On Wednesday, Nepal’s prime minister linked the deadly floods to climate change and urged global action.

Prime Minister Balendra Shah : “The time has come for us to forcefully make the international community aware of the disasters we are suffering because of climate change. Climate change is a product of the whole world’s contribution, hence mitigating and managing its effects is the shared responsibility of the global community.”

Former Venezuelan President Maduro and His Wife Ask Judge to Dismiss Drug Trafficking Charges

Sep 03, 2026

Former Venezuelan President Nicolás Maduro and his wife, the ex-leader of Venezuela’s National Assembly, Cilia Flores, have asked a U.S. judge to dismiss the drug trafficking indictment against them. In papers filed in a Manhattan federal court on Wednesday, Maduro and Flores argue they have immunity as the leader and first lady of a foreign country. Their request came eight months after President Trump ordered their abduction during a U.S. assault on Venezuela.

Chevron Pledges to Invest $7 Billion in Venezuela as U.S. Energy Secretary Touts Oil and Gas Deal

Sep 03, 2026

The oil giant Chevron says it will invest more than $7 billion into its Venezuela joint ventures over the next five years, aiming to roughly double output to about 600,000 barrels per day. Chevron’s agreement was the largest involving several foreign oil and gas companies announced by U.S. Secretary of Energy Chris Wright on Wednesday. Wright was speaking from the Miraflores presidential palace in Caracas at a signing ceremony with Venezuela’s interim President Delcy Rodríguez.

Energy Secretary Chris Wright : “The catalyst for transforming Venezuela is energy. The catalyst for improving the life conditions of Americans, our hemisphere and everyone in the world is to massively expand energy production around the world.”

Wright’s visit to Caracas comes after President Trump announced an unprecedented scheme that will grant the U.S. government an equity stake in a private oil firm in Venezuela that has concessions to operate oil fields holding an estimated 65 billion barrels of oil reserves.

Rep. Greg Casar Blasts OpenAI for Withholding Info About Rogue AI Agent Hack

Sep 03, 2026

Image Credit: Nathan Howard/Reuters

OpenAI says its engineers are building “automated shutdown capabilities” for artificial intelligence systems, after the company acknowledged that one of its AI tools broke out of its digital container during a safety test and hacked into the AI platform Hugging Face. OpenAI announced the plans for new safeguards in a letter to two House Democrats, but did not provide a log of the hack. On Wednesday, Texas Congressmember Greg Casar wrote in response to OpenAI, “Your unwillingness to provide members of Congress with the information we requested is ​deeply concerning and signals to us that ​your company is not treating ​these cybersecurity incidents with the seriousness required.”

New York City Adopts AI Moratorium for K-8 Students

Sep 03, 2026

New York City has adopted a moratorium on the use of generative AI in public schools for all students through the 8th grade, alongside a new screen-time policy. Mayor Zohran Mamdani announced the changes on Wednesday, saying nearly 600,000 students will be affected.

Mayor Zohran Mamdani : “Children need their teachers and human connection in order to learn and in order to grow, and they need to develop skills alongside their peers, build relationships with their teachers and wrestle with tough problems on their own. The tech industry wants us to believe that AI in early education is not only inevitable, but that it is necessary. We do not see it that way.”

Workers Remove Giant Statue “Blue” from Kennedy Center Grounds

Sep 03, 2026

In Washington, D.C., workers have removed a giant statue from the grounds of the Kennedy Center for the Performing Arts, less than seven years after its installation. The removal of the statue, known simply as “Blue,” comes after Justice Department lawyers warned in a federal court filing that the Kennedy Center could be demolished unless President Trump is allowed to proceed with renovations, including plans to inscribe Trump’s name into the building’s marble edifice.

The original content of this program is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License . Please attribute legal copies of this work to democracynow.org. Some of the work(s) that this program incorporates, however, may be separately licensed. For further information or additional permissions, contact us.

Souping up my blog

Lobsters
qtea.me
2026-09-03 07:35:09
Comments...
Original Article

For a long time I thought it’d be nice if there was a simple way for people to interact with my posts. When you write something it’s nice to know that someone took the time to read what you wrote and maybe even got some enjoyment out of it. I’m glad for those who let me know on Bluesky or Fedi <3

Bear Blog has an unintrusive upvote button at the end of each post. But I’m not using Bear Blog – my blog is statically generated and I’d like to keep it that way.

So last weekend I got the idea of writing a simple web service that you can give the URL for a post, and it’ll either return the number of upvotes or let you add an additional one. To get started I looked at the source code for Bear Blog to figure out how to prevent repeated upvotes and protect against potential abuse. In the end the only thing I adapted was storing an upvote as the hash of a visitor’s IP address together with the current year, which has one minor issue (if you post something at the end of a year it can be upvoted again within a short time), but overall works well enough.

I added an allow list so only upvotes for certain sites are accepted and then did a quick check whether the upvoted post actually exists.

Since the web service is completely separate from my blog I just had to write a little bit of JavaScript to fetch the upvotes when a post is loaded, and then add a button to allow people to add an upvote.

When I initially started the project I decided to name it “upvaas” (upvotes as a service), because that’s what it is. But turns out “upvaas” is a Hindi word (meaning “fasting”), which by itself wouldn’t be enough of a reason to change the name (it’s not a bad word, and in a way upvoting is kinda the opposite of fasting?), but it did make me wonder if I could come up with something more unique and less big tech sounding.

Supvaas? (silly upvotes as as service)

Soup?? (silly/service of upvotes)

You’re telling me a soup upvoted this post???

The silliness of “soup” stuck with me, so I promptly renamed the project to “ soupvotes ” (I want to avoid being confused in the future when I stumble upon a folder that’s just named “soup”) and here we are.

I think “soup” is also fitting because I wanted to use a steaming tea cup as an indicator for upvoted posts – and soup is also pretty steamy.

So from now on you can stir (upvote) my writing by clicking the tea cup under each post. Tea you around!

4.5B Posts Scraped from TikTok

Hacker News
tiktok-api.seeksocial.io
2026-09-03 07:25:49
Comments...
Original Article

Technical guide · 24 endpoints · Measured

TikTok's Android app talks to a private HTTP+JSON API that is faster than the web endpoints and returns considerably more. This is a technical guide to reaching it: how devices are registered, how requests are signed, how the regional hosts are partitioned, and how the TLS handshake is fingerprinted. A system built on it collected 3.23 billion creator profiles, 5.94 billion videos and 2.8 billion comments in three weeks.

Get the full code

Free dataset. I uploaded 4.5 billion of those videos to Hugging Face: captions, view, like, comment and save counts, the sound, the country and the posting time. huggingface.co/datasets/kuben-developer/tiktok-videos-4b

What you can pull. Creator profiles, every video a creator has posted, followers and following lists, and TikTok's own similar-creator graph. Full video detail with the complete statistics block. Comments and comment replies, each with the commenter's account. Sounds, the videos using them, and the trending sounds chart. Hashtags and their videos, newest or most popular. Keyword search across videos, creators and sounds. Trending shelves and camera effects. 24 endpoints in all , each with a measured success rate.

What this is

Almost every TikTok scraper you will find drives a headless browser or hits the public web endpoints. Both are the wrong layer: slow, fragile, and missing most of the interesting fields. The Android app does not use either. It talks to a private HTTP+JSON API, the same one com.zhiliaoapp.musically hits when you scroll, and that API is fast, stable, and returns far more.

Getting into it is the hard part, and it is hard in a specific way. Four completely unrelated things have to be right at once: a device credential TikTok issued, a valid request signature, the correct regional host, and a TLS handshake that looks like a phone.

Get any one of them wrong and you receive the identical response: a clean HTTP 200 with an empty body . No error message. No status code. Your HTTP client reports success, your logs stay green, and your database fills with nothing. There is no signal telling you which of the four you are standing at.

This article walks through all four, then documents the 24 endpoints that come out the other side. It names the primitives, shows the real pipeline and gives measured numbers rather than claims.

None of the four has a feedback loop. A wrong rotation constant, a wrong byte order, a wrong host and a wrong cipher suite in the handshake all produce the same well-formed request and the same empty response, so there is no error to bisect on and no partial credit.

Scope

Everything below is anonymous device traffic. There is no login anywhere in this system, no account, no session cookie. That also means anything genuinely account-gated (your own DMs, private videos, who liked what) is out of reach and stays out of reach. No amount of tuning gets you there.

Anatomy of a request

Before anything else, here is what one of these requests actually looks like. This is a real call, with the identifying values shortened:

GET /aweme/v1/aweme/post/
    ?# ── what you are asking for ──────────────────────────────
     source=0
    &user_id=6744630345964389381
    &count=20
    &max_cursor=1751028792000
    &sort_type=0
    &# ── who is asking: 38 params, order matters ─────────────
     ts=1788361402&ac=mobile&ac2=lte
    &aid=473824                         # app id: TikTok Lite
    &iid=7680617333853718293            # install id  ← from register
    &device_id=7680616891110524437      # device id   ← from register
    &cdid=4a1d...                       # client-generated uuid
    &openudid=8f2c...                    # client-generated 16-hex
    &device_brand=Samsung&device_type=SM-A136U&os_version=12&os_api=30
    &resolution=1080*2280&dpi=440&host_abi=arm64-v8a
    &region=SG&carrier_region=SG&sys_region=SG&mcc_mnc=52506
    &language=ja&app_language=ja&locale=ja-SG&timezone_name=Asia%2FSingapore
    &version_name=32.8.2&version_code=320820&manifest_version_code=320820
    &_rticket=1788361402193&channel=googleplay&app_type=normal

Headers:
  user-agent:      com.ss.android.ugc.tiktok.lite/320802 (Linux; U; Android 12; ...)
  x-tt-trace-id:   00-6a9f...-6a9f...-01
  x-ss-req-ticket: 1788361402193
  x-khronos:       1788361402                    # timestamp
  x-ladon:         XKp9...                       # Speck-128/256
  x-argus:         cQqbRZm8k1x...                # the hard one
  x-gorgon:        0404b0d30000...               # legacy digest
A single creator-timeline request. Everything below the fold is device identity.

Three things to notice, because each one bites later:

  • Two thirds of the URL is device identity. Thirty-eight common parameters describe the handset, the carrier, the region and the app build. They are not decoration. The signature covers them.
  • device_id and iid are issued by TikTok , not chosen by you. cdid and openudid you generate and submit at registration. Getting the distinction wrong is the first wall.
  • Parameter order is fixed. The signature hashes the query string as a literal, so url.Values.Encode() , which sorts keys alphabetically, silently produces an invalid signature. In Go you have to build the query by hand.

The vocabulary, since it recurs throughout:

Field What it is Origin
aid Application id. 1233 is the main app (musically), 473824 is Lite, 1340 is musically_go. Different aid means a different signing key and a different endpoint set. Constant
device_id The durable device identity. 19 digits. TikTok, at register
iid Install id. Pairs with device_id . TikTok, at register
cdid Client device id. A UUID you generate. You
openudid 16 hex characters you generate. You
license_id Feeds the X-Ladon key schedule. Constant per app
version_code App build. Gates which endpoints answer at all. You choose

The first empty 200

A correctly implemented signer produces output that verifies against captured traffic, with parameters matching byte for byte. The response is still this:

$ curl -sD- -o /tmp/body "https://api16-normal-c-alisg.tiktokv.com/aweme/v1/user/profile/other/?..."
HTTP/1.1 200 OK
content-type: application/json
content-length: 0
x-tt-logid: 2026090117...
server: TLB

$ wc -c /tmp/body
0 /tmp/body
Two hundred. Zero bytes. No status_code , because there is no body to put one in.

This is TikTok's soft block, and it is the single most important thing to understand about this API. It is not a 403. It is not a 429. It is not a challenge page. It is a successful HTTP response containing nothing.

Which means this code, which is what everyone writes first, is silently broken:

res = requests.get(url, headers=signed)
if res.ok:                      # True. Always true.
    store(res.json())           # {} stored, no exception

# six hours later: 400,000 rows in the database, all empty,
# nothing in the error log, dashboard green

It is expensive to debug because four unrelated failures produce it :

  1. Your device was never activated ( § activation )
  2. Your signature is wrong ( § X-Argus )
  3. You are talking to the wrong regional host ( § regions )
  4. Your TLS handshake looks like a server, not a phone ( § JA3 )

There is nothing in the response to tell you which. You cannot bisect it by reading errors, because there are none. The only way through is to fix all four and measure each one in isolation.

Where device IDs come from

You cannot invent a device_id . TikTok issues it, from /service/2/device_register/ on its logging host, in exchange for a plausible handset.

The request body is a JSON document (app header, device header, custom block) encrypted with TTEncrypt (TikTok's own body cipher, a simple byte-level transform with a fixed key schedule) and posted as application/octet-stream;tt-data=a . It goes out with the full signature set, so you need working signing before you can get a device, and the signing needs a device . You bootstrap with the client-generated fields and zeros where the issued ones go.

The body's shape, with the parts that matter:

{
  "magic_tag": "ss_app_log",
  "header": {
    // app identity: must agree with the aid in the query string
    "aid": 473824, "package": "com.ss.android.ugc.tiktok.lite",
    "app_version": "32.8.2", "version_code": 320820,
    "sdk_version": "...", "git_hash": "...", "sig_hash": "...",

    // hardware: every field here has to be internally consistent
    "device_model": "SM-A136U", "device_brand": "Samsung",
    "device_manufacturer": "samsung", "cpu_abi": "arm64-v8a",
    "os_version": "12", "os_api": 30,
    "resolution": "2280*1080", "density_dpi": 440,
    "rom": "...", "rom_version": "...",

    // identity you generate and are about to trade in
    "cdid": "<uuid4>", "openudid": "<16 hex>",
    "clientudid": "<uuid4>", "google_aid": "<uuid4>",

    // region: carrier must plausibly exist in this country
    "region": "SG", "sim_region": "sg", "carrier": "Singtel",
    "mcc_mnc": "52506", "tz_name": "Asia/Singapore", "tz_offset": 25200,

    "custom": {
      "screen_width_dp": 408, "screen_height_dp": 883,
      "web_ua": "Dalvik/2.1.0 (Linux; U; Android 12; SM-A136U Build/...)",
      "apk_last_update_time": 1788361409271
    },
    "apk_first_install_time": 1788360902118
  },
  "_gen_time": 1788361402240
}

Every field there is checked against the others. A Samsung SM-A136U has a specific screen resolution, a specific DPI, a specific ABI, and shipped with a specific range of Android versions. It is sold on carriers in some countries and not others. A flagship handset on a network that never carried it is not a real phone, and the registration is refused.

Rather than generating these procedurally, I build them from a catalogue of ~250 real Android device profiles crossed with a carrier table of MCC/MNC pairs (roughly 2,000 rows, derived from public numbering-plan data). Pick a handset, pick a carrier that actually exists in the target country, fill in the coherent values.

A successful registration comes back with the two ids you needed:

{
  "device_id_str":  "7680616891110524437",
  "install_id_str": "7680617333853718293",
  "new_user": 1
}

Most implementations stop here.

The activation call

With registration working, most endpoints answered. Video listings, search, hashtags, sounds, all fine. But /aweme/v1/user/profile/other/ , the full profile record, returned the empty 200 every single time , on every device I made, forever.

The obvious suspect is the signature, and it is the wrong one. The tell is that an older pool of devices, generated months earlier by different code, worked fine on that same endpoint with the same signer and the same parameters. The only difference was in how the devices had been created, and it came down to one extra HTTP call:

GET /service/2/app_alert_check/?<common params>
    &cronet_version=...&ttnet_version=...
    &tt_info=<base64url(TTEncrypt(<60-field key=value blob>))>

→ {"message":"success"}

That is it. It returns nothing you need. It looks like telemetry, and functionally it is telemetry. It is the call the real app makes on launch, before it requests any data.

That is what the call is for. A device that registered and then immediately started querying the API is, from ByteDance's side, an install that never launched . Registration alone does not make you a running app. The startup call does.

Device generation Profile endpoint
Register only 0 / 360 Correct signature. Empty body, every time, indefinitely.
Register + startup call 100 / 100 Same code, same signature, one extra request.

0 / 360 to 100 / 100

Zero to a hundred percent, from a call whose response you throw away. It is not documented anywhere. It is not visible in a signature dump. It does not fail loudly. And because the symptom is the empty 200, it is indistinguishable from a broken signer.

The tt_info blob is the interesting part of the request: about sixty key=value pairs (GAID, timezone, install id, device id, carrier, screen, ABI, locale, a request UUID) TTEncrypt-ed and base64url-encoded. It is the app reporting its full environment on startup. My guess, and it is only a guess, is that this is where the device gets marked as a real install rather than a bare registration; I have not tried to prove it, because the empirical result is unambiguous.

Proving a device before you use it

The activation fixed the profile endpoint, but it introduced a second-order problem: activation itself sometimes fails silently, and a device that failed activation looks exactly like a device that succeeded until you use it.

So generation does not end at activation. It ends with a real read against a known creator. If real content comes back, the device joins the pool. If not, it is thrown away. Not retried, not quarantined. Discarded .

func GenerateDevice(client *http.Client, country string) (map[string]any, error) {
    tmpl, err := NewAndroidTemplate()          // handset × carrier
    ...
    if err := registerDevice(client, tmpl); err != nil {
        return nil, fmt.Errorf("register: %w", err)
    }
    // Without this TikTok will not serve profile detail to a fresh device.
    if err := appAlertCheck(client, tmpl); err != nil {
        return nil, fmt.Errorf("activate: %w", err)
    }
    // Survivorship filter: only provably-capable devices enter the pool.
    if !profileCapable(client, tmpl) {
        return nil, errors.New("profile probe failed: device not capable")
    }
    return tmpl, nil
}

The three-stage pipeline. Roughly 60-95% of attempts survive it, depending almost entirely on proxy quality.

Without the filter you get a pool that is a mixture of working and quietly dead devices, and because dead devices return the empty 200, the same as every other failure, the pool degrades invisibly. Your success rate drifts down over days and there is nothing in the logs to explain it.

With the filter, the pool is uniformly capable by construction. Live health is visible from the running server:

$ curl -s localhost:8080/v1/devices | jq
{
  "live": 43,
  "generated_total": 43,
  "rejected_total": 2,
  "evicted_total": 0,
  "success_total": 177,
  "failure_total": 74,
  "generation_survival_rate": 0.9555
}

Inside X-Argus

X-Argus is not a hash of a string. Its plaintext is a protobuf message in proto3 wire format, varints and length-delimited fields, which is then run through a two-stage encryption pipeline.

The message carries, among other fields:

type Argus struct {
    Magic          int32      // fixed marker
    Version        int32
    Rand           int64      // per-request random, 0x10000000..0xFFFFFFFF
    MsAppID        string     // "1233" / "473824"
    LicenseID      string
    DeviceID       string
    SdkVersion     int32
    SdkVersionStr  string
    AppVersion     string
    EnvCode        []byte
    CreateTime     int64      // X-Khronos, again, inside the blob
    BodyHash       []byte     // SM3 of the body (16 zero bytes on GET)
    QueryHash      []byte     // SM3 of the literal query string
    AlgorithmCount struct {
        SignCount    int32   // how many signatures this install has made
        ReportCount  int32
        SettingCount int32
        Timestamp    int64
    }
    SecDeviceToken string
    IsAppLicense   int64
    PskHash        []byte
    CallType       int32
    ChannelInfo    struct { PhoneInfo, Channel string; ... }
}

The subset the signer actually populates. Establishing the field numbering is most of the reverse-engineering work.

AlgorithmCount.SignCount is a counter of how many requests this install has signed. A real phone's counter climbs steadily over the life of the install. A scraper that emits a constant, or resets to zero on every request, is producing a statistically obvious pattern even when every individual signature verifies. I seed it randomly per device in a plausible range and it has never been a problem, but it is the kind of field that exists specifically so that naive replay is detectable in aggregate rather than at the individual request.

The pipeline

Once the protobuf is serialised, it goes through this, in order:

1.  pb        = proto3_serialize(Argus{...})
2.  padded    = pkcs7(pb, 16)

    // key derivation: the signing key is a per-aid 32-byte constant
3.  xmKey     = SM3( signKey[0:32] || f(rand_lo, rand_hi) || signKey[0:32] )

4.  enc1      = Simon-128/256-ECB( key = xmKey, padded )
5.  enc1      = reverse_bytes(enc1)
6.  enc1      = xor_mix(enc1, derived_from(rand))      // bit-level, order-sensitive

    // framing: a version byte, entropy, and a 3-byte marker built from
    // the first bytes of two separate SM3 digests
7.  framed    = hexFirstByte(aid) || rand_bytes || append_array || enc1

8.  enc2      = AES-128-CBC( key = MD5(signKey[0:16]),
                          iv  = MD5(signKey[16:32]), framed )

9.  X-Argus   = base64( rand_lo || enc2 )

Two encryption layers with different primitives and different key derivations, with a byte reversal and an XOR mix sandwiched between them. None of the individual steps is hard. The difficulty is entirely that there is no feedback . Get step 6 wrong and you produce a perfectly well-formed, correctly-sized, base64-clean header that TikTok answers with an empty 200.

Which is why the implementation ships with independent test vectors for every primitive. You verify Simon, Speck, SM3 and TTEncrypt separately against known input/output pairs, so that when a request fails you already know the crypto is right and the bug is in composition.

Simon, Speck and SM3

The choice of primitives is deliberate, and it says something about the threat model.

ARX ciphers

Simon and Speck are lightweight block ciphers published by the NSA in 2013. Both are ARX constructions, built entirely from modular A ddition, bitwise R otation and X or. No S-boxes. No lookup tables. No multiplication.

Speck's round function, in full, is two lines:

x = (ROR(x, α) + y) ⊕ k
y =  ROL(y, β)     ⊕ x

// for the 128-bit block size: α = 8, β = 3, 64-bit words
// 128/256 configuration: 256-bit key, 34 rounds

Simon is the same idea with the addition swapped for AND, which makes it cheaper in hardware and slightly more expensive in software:

x' = y ⊕ (ROL(x,1) & ROL(x,8)) ⊕ ROL(x,2) ⊕ k
y' = x

// 128/256 configuration: 256-bit key, 128-bit block, 72 rounds,
// round constants from the Z4 sequence (a 62-bit LFSR period)

Why these and not AES? Three reasons, and they all point the same way:

  • They compile to almost nothing. A few hundred bytes of ARM, no tables, no data-dependent memory access. That matters when the code lives inside an obfuscated native library that has to be small and has to avoid cache-timing side channels that would make it easy to locate.
  • They are not in your standard library. AES is a function call in every language. Simon and Speck you have to implement, and the parameterisation space is large (block size, key size, round count, rotation constants, key schedule) so a wrong guess produces plausible ciphertext and no error.
  • They are easy to get subtly wrong. Speck's key schedule reuses the round function itself. Get the word order or the endianness wrong and you get 32 valid-looking round keys that are all incorrect.

Note that AES-128-CBC is in the pipeline, as the outer layer. The interesting design choice is that the inner layer, the one actually protecting the protobuf, is the one you can't just call.

SM3

SM3 is the Chinese national cryptographic hash standard (GB/T 32905-2016). 256-bit output, 512-bit blocks, Merkle-Damgård construction with a compression function structurally similar to SHA-256 but with two parallel message expansion schedules and a different round function:

// two boolean functions, switching at round 16
FF(x,y,z) = x ⊕ y ⊕ z                      // j < 16
          = (x&y) | (x&z) | (y&z)          // j ≥ 16
GG(x,y,z) = x ⊕ y ⊕ z                      // j < 16
          = (x&y) | (~x&z)                 // j ≥ 16

// IV
7380166F 4914B2B9 172442D7 DA8A0600 A96F30BC 163138AA E38DEE4D B0FB0E4E

SM3 shows up in ByteDance's stack for the obvious reason. It is also, usefully for them, absent from every Western standard library. And the two message expansion arrays ( W and W' ) are trivially transposable, so a large fraction of the reference implementations floating around are wrong in ways that only show up on certain inputs.

TTEncrypt

The body cipher, used for the registration payload and the activation blob. Not a standard construction, just a fixed-key byte transform with a small table. It is not cryptographically serious and is not meant to be; it exists to stop casual traffic inspection, and it is the easiest of the four to reimplement.

X-Ladon

Much simpler than Argus, and worth showing in full because it is a good illustration of how these schemes are layered: a cheap gate in front of an expensive one.

plaintext = "<khronos>-<license_id>-<aid>"
key       = ascii_hex( MD5( rand_bytes(4) || aid ) )   // 32 bytes
cipher    = Speck-128/256-ECB( key, pkcs7(plaintext) )
X-Ladon   = base64( rand_bytes || cipher )

Four random bytes, an MD5, and a Speck encryption of a dash-joined string. The random bytes are prepended to the output so the server can rederive the key. That is the whole construction.

It filters out anyone who hasn't looked at the app at all, and costs approximately nothing to verify at scale. Argus is the expensive check that runs after.

Version gating

A correct signature is necessary and not sufficient. Some endpoints are gated on the client build, and the gate is server-side.

The clearest case is comments. Same device, same signer, same second, same everything. Only version_code differs:

App build /aweme/v2/comment/list/
32.8.2 (320802) empty 200
35.5.4 (350504) 178 KB of comments

The version bump also unlocked comment replies and follower listing. It is not that the older build's signature is rejected, because it verifies fine. It is that the endpoint is simply not served to that client version.

Practically this means the app version is a per-endpoint property, not a global setting. In my catalogue each endpoint records the build it needs and the server swaps the four version fields transparently before signing:

func WithAppVersion(dev *DevInfo, version, code string) *DevInfo {
    c := *dev
    c.App.AppVersion          = version
    c.App.AppVersionCode      = code
    c.App.ManifestVersionCode = code
    c.App.UpdateVersionCode   = code
    return &c
}

Pinning the newest build everywhere is not the answer, because newer builds tighten other checks. The catalogue exists so that each endpoint sits on the build that works for it.

Region partitioning

The third gate, and the one with nothing to go on: no error, no redirect, no hint in the response.

TikTok does not run one API. It runs several regional data centres: alisg (Singapore), useast1a , useast5 and others. And they do not serve the same endpoints to the same devices .

With activation fixed, profile detail still failed on freshly generated devices while working on an older pool. Same code, same signer. The difference turns out to be the host:

Host Fresh device, profile detail Response
api16-normal-useast5.tiktokv.us 50 / 50 9,517 bytes
api16-normal-c-alisg.tiktokv.com 1 / 50 empty 200
api16-normal-c-useast1a.tiktokv.com 0 / 50 empty 200

Same second, same credential, same signed request, three hosts, one answer. And music/detail is the reverse: it answers on useast1a and returns nothing on the Singapore host that serves almost everything else.

So the host is part of the endpoint definition. Not a global base URL but a per-route property, established by measurement, because there is no documentation to consult:

{
    ID: "user.info", Route: "/v1/user/info",
    Host: tiktok.HostUSEast5,    // the ONLY host that serves this to fresh devices
    Path: "/aweme/v1/user/profile/other/",
    ...
},
{
    ID: "music.info", Route: "/v1/music/info",
    Host: tiktok.HostUSEast1A,   // and this one is the only host for THIS
    Path: "/aweme/v1/music/detail/",
    ...
},

There is a useful second-order effect here. The device's registered region also influences content on the region-scoped endpoints: trending sounds and trending category shelves. Running one pool registered in US and another in BR gives you genuinely different charts from the identical call, which is how you get per-country data without any per-country code.

The TLS fingerprint

The fourth gate, and the one that is invisible at every layer an application developer normally inspects.

Before any of your bytes arrive, your TLS client sends a ClientHello. Everything in it, and crucially the order of everything in it, is a fingerprint. JA3, the standard way of capturing this, is an MD5 of five comma-joined fields:

TLSVersion , Ciphers , Extensions , EllipticCurves , ECPointFormats

771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,
0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0
       ↓ MD5
cd08e31494f9531f560d64c695473da9

A JA3 string and its hash. The cipher list and the extension list are ordered, and libraries order them differently.

That fingerprint identifies your TLS library , and often its version, with high precision. OpenSSL, BoringSSL, NSS, Go's crypto/tls , Java's JSSE are all distinguishable, before a single byte of HTTP is exchanged.

Go's crypto/tls has a very distinctive one. And no Android app has ever emitted it, because Android apps use BoringSSL through OkHttp. TikTok's useast5 edge checks.

The experiment that isolated it

The same request works from Python and fails from Go. Signature byte-identical, parameters byte-identical, cookies irrelevant (it works with and without). Dump the exact headers Python just used, replay them from Go, and hold everything else constant. Same URL, same signature, same device, same second:

// identical request, three clients, back to back

python  urllib3 / OpenSSL     →  9,517 bytes
curl    OpenSSL               →  9,519 bytes
go      crypto/tls            →      0 bytes   ← HTTP 200

Nothing about the request was different. The handshake was.

The fix is uTLS , which lets you specify the exact ClientHello to emit instead of accepting the one Go builds for you:

cfg := &utls.Config{ServerName: host, NextProtos: []string{"http/1.1"}}
conn := utls.UClient(raw, cfg, utls.HelloAndroid_11_OkHttp)
if err := conn.HandshakeContext(ctx); err != nil {
    return nil, fmt.Errorf("utls handshake: %w", err)
}

One line of profile selection. Profile detail on fresh devices went from 0% to 100% .

NextProtos is pinned to http/1.1 on purpose. The Android profile advertises h2, but the transport underneath this is HTTP/1.1 only. Negotiate h2 and you get a connection nothing can speak on.

The Go proxy trap

Short, and specific to Go.

Wire up uTLS, test it directly, confirm the fingerprint has changed, then put it behind the rotating proxy. The failures come straight back.

The reason is that http.Transport ignores DialTLSContext when Proxy is set . It dials the proxy, issues CONNECT itself, and then runs its own standard-library handshake over the resulting tunnel. Your custom dialer is silently discarded. No error, no warning, no log line.

You have to do the tunnel by hand:

dialTLS := func(ctx context.Context, network, addr string) (net.Conn, error) {
    // 1. plain TCP to the proxy
    raw, err := d.DialContext(ctx, "tcp", proxyURL.Host)
    ...
    // 2. CONNECT by hand: this is the part Transport would have done
    req := &http.Request{Method: "CONNECT", URL: &url.URL{Opaque: addr}, Host: addr, ...}
    req.Write(raw)
    resp, _ := http.ReadResponse(bufio.NewReader(raw), req)
    if resp.StatusCode != 200 { return nil, fmt.Errorf("CONNECT: %s", resp.Status) }

    // 3. NOW run the uTLS handshake over the tunnel
    u := utls.UClient(raw, cfg, utls.HelloAndroid_11_OkHttp)
    return u, u.HandshakeContext(ctx)
}

tr := &http.Transport{
    DialTLSContext:    dialTLS,
    DisableKeepAlives: true,   // see the next section
    // note: NO Proxy field. Setting it would bypass all of the above.
}

The Proxy field is deliberately absent from the transport. Setting it is what silently discards the dialer.

Detecting the empty 200

With all four gates passed you still need to know, per response, whether you actually got data. Status codes will not tell you. The check has to be on content:

if resp.StatusCode != http.StatusOK {
    return body, fmt.Errorf("upstream HTTP %d", resp.StatusCode)
}
if len(body) < minBodyBytes {                    // 64
    // The soft block: 200 with (almost) nothing in it.
    return body, fmt.Errorf("empty upstream body (%d bytes)", len(body))
}
var probe map[string]json.RawMessage
if err := json.Unmarshal(body, &probe); err != nil {
    // HTML, usually a proxy error page rather than TikTok
    return body, errors.New("upstream body is not a JSON object")
}
if raw, ok := probe["status_code"]; ok {
    var n int
    if json.Unmarshal(raw, &n) == nil && n != 0 {
        return body, fmt.Errorf("upstream status_code %d", n)
    }
}

Four conditions, in order: HTTP status, length floor, parseable JSON object, clean internal status_code . Anything that fails one is retried against a different device from a different IP.

Except when retrying is pointless

Some non-zero status_code values are TikTok answering rather than refusing. Retrying those four times is a waste of four devices and four IPs:

status_code Message Treated as
2065 User doesn't exist. 404, no retry
3170 user not exists 404, no retry
3002060 Profile user is hiding following list 403, no retry

Which surfaces to the caller as a real answer instead of a gateway failure:

$ curl -s localhost:8080/v1/user/following?user_id=6744630345964389381 | jq
{
  "error": {
    "code": "hidden_by_user",
    "message": "This creator has hidden their following list. Most accounts do; there is no way around it.",
    "upstream_status_code": 3002060,
    "upstream_status_msg": "Profile user is hiding following list",
    "retried": false,
    "retry_would_not_help": true
  }
}

Everything else keeps its full retry budget, and when it exhausts it you get the per-attempt breakdown rather than a generic failure, which is what makes this debuggable in production:

{
  "error": {
    "code": "upstream_failed",
    "attempts": 4,
    "attempt_failures": [
      {"attempt": 1, "reason": "empty upstream body (0 bytes)"},
      {"attempt": 2, "reason": "empty upstream body (0 bytes)"},
      {"attempt": 3, "reason": "transport: ... EOF"},
      {"attempt": 4, "reason": "upstream HTTP 429"}
    ]
  }
}

Real output from the weakest endpoint in the catalogue. Two soft blocks, a dropped connection, and an honest rate limit.

Keep-alive pins the exit IP

With all four gates passed, the highest-volume endpoint ran at 88.2% over 174 million attempts . Good, and at that volume the missing 12% is twenty million lost records.

The obvious move is more retries. It does nothing, because of how rate limiting and connection reuse interact.

Rate limiting here is per exit IP. A rotating proxy gateway assigns an exit IP per TCP connection . HTTP keep-alive, which every client does by default and which is normally exactly what you want, pins you to one exit IP for the life of that connection.

So the retry went out from the address that had just been refused. And the next one. And the next:

// keep-alive on a rotating proxy
attempt 1  →  exit 203.0.113.44  →  empty 200
attempt 2  →  exit 203.0.113.44  →  empty 200     ← same IP
attempt 3  →  exit 203.0.113.44  →  empty 200     ← same IP
attempt 4  →  exit 203.0.113.44  →  empty 200     ← same IP

// fresh connection per attempt
attempt 1  →  exit 203.0.113.44  →  empty 200
attempt 2  →  exit 198.51.100.7  →  ok

Four attempts, one IP, four identical failures. The retry budget bought nothing at all. It was structurally incapable of helping.

Why the naive fix stalls at 96%

Setting DisableKeepAlives: true everywhere took it to 96.2% and then stopped. The cause is that at full concurrency you are now paying a TLS handshake for every attempt, including the ~88% that were going to succeed first time. The proxy gateway, not TikTok, became the bottleneck and started refusing tunnels:

{"attempt": 1, "reason": "transport: proxy CONNECT: 466 Too Many Requests"}

The failure had moved, not gone. The production shape is a hybrid of the two, which comes down to two pools and one policy switch:

// First-attempt pool: keep-alive, so the common case costs no handshake.
r.proxyPool, _      = httpclient.New(httpclient.Config{ProxyURL: cfg.ProxyURL})

// Retry pool: DisableKeepAlives => fresh TCP => NEW exit IP.
r.proxyPoolFresh, _ = httpclient.New(httpclient.Config{
    ProxyURL: cfg.ProxyURL, DisableKeepAlives: true,
})

// ...and in the request path:
pool := r.proxyPool
if attempt > 0 && r.proxyPoolFresh != nil {
    pool = r.proxyPoolFresh          // rotation exactly where it matters
}
Configuration Success Bottleneck
Keep-alive everywhere 88.2% Retries reuse the blocked IP
Keep-alive nowhere 96.2% Proxy gateway, handshake storm
Keep-alive on first attempt only 99.3% none

Measured over hundreds of millions of calls across four shards. The self-hosted server described below keeps the simpler always-fresh form, because a single instance is nowhere near the load where the second bottleneck appears.

Proxies: the one running cost

Everything up to here is a software problem you solve once. The proxy is the single external dependency and the only recurring cost, and the requirement for one is structural rather than incidental.

What a proxy is, briefly

A proxy is a machine that makes the request on your behalf. You connect to it, it connects to TikTok, and TikTok sees the proxy's IP address instead of yours. A rotating gateway is one where each new connection comes out of a different address in a large pool, which is the property that matters here.

Why it is mandatory rather than recommended

Two reasons, and the second is the one people underestimate.

Rate limiting is per exit IP. One address gets a budget and it is not a large one. Without a proxy every request in your system shares a single address, and you exhaust it in minutes.

Retries are structurally useless without rotation. This is the point from the previous section . When a request is soft blocked, the retry has to leave from a different address or it fails identically. Rotation per connection is the entire mechanism behind the jump from 88% to 99.3%. A static proxy gives you one IP and therefore gives you nothing.

So the requirement is a rotating gateway, and you can verify yours actually rotates in one line before you commit to anything:

$ for i in 1 2 3; do curl -s --proxy "$PROXY_URL" https://api.ipify.org; echo; done
203.0.113.44
198.51.100.7      # different IP each time = rotating, good
192.0.2.19

If the same address comes back three times, your retry budget is decorative and your success rate will sit near the first-try rate no matter what you set MAX_ATTEMPTS to.

What it actually costs

The first thing to know is that you should not be paying by the gigabyte . Metered plans are the default recommendation in this space and they are the wrong shape for this workload, because the endpoints that return the most useful data are the ones measured in megabytes. A page of videos is 1.1 MB. A page of recommended creators is 2.9 MB. Metered billing turns every one of those into a line item.

Flat monthly subscriptions exist for both proxy types, and they are what you want. Two tiers cover essentially everyone:

Tier What you get Cost Realistic for
Rotating datacenter 100 concurrent threads at 200 Mbit/s ~$150 / month Millions of records. Where almost everyone should start.
Unlimited residential Unmetered residential pool ~$950 / month Billions. What the six-day run at the top of this page used.

For enriching a few hundred thousand creators, tracking sounds daily, or mapping a niche, the $150 tier is sufficient rather than a compromise: a rotating datacenter pool registers devices, passes activation and sustains the success rates in the table further down.

The residential tier is what you escalate to once you are saturating the datacenter one.

What the $150 tier buys

On a flat plan the two limits are threads (how many requests can be in flight) and line speed (how many bytes per second). Which one binds depends entirely on response size, and the endpoints here differ by two orders of magnitude: a profile is 9.5 KB, a page of videos is 1.1 MB.

The figures below are arithmetic from the measured response sizes and latencies in the benchmark, at 100 threads and 200 Mbit/s. They are ceilings at full saturation, so treat them as an upper bound rather than a promise.

Collecting Per response Binding limit Ceiling
Creator profiles (user.info) 9.5 KB Threads ~140/s · ~12M/day
Comments (20 per page) 174 KB Threads ~1,600/s · ~140M/day
Followers (20 per page) 178 KB Threads ~1,600/s · ~140M/day
Videos with full metadata (20 per page) 1.1 MB Line speed ~450/s · ~39M/day
Creator graph walk (user.recommended) 2.9 MB Line speed ~350/s · ~30M/day

On the small endpoints you run out of threads long before bandwidth, so the fix is a higher thread count. On the video endpoints you saturate the line at around 22 requests a second, and more threads buy you nothing at all. That is the number MAX_CONCURRENT exists to control, and setting it above what your plan can carry produces proxy CONNECT: 466 Too Many Requests in the attempt failures rather than more throughput.

Where one subscription runs out

One $150 subscription comfortably collects millions of records , and tens of millions on the small endpoints. It is not enough for billions. The six-day run at the top of this page needed the unlimited residential tier at roughly $950 a month, sharded across four instances, and at that scale the proxy bill is the dominant cost of the entire operation.

Scaling is horizontal either way: another subscription, another instance of the server pointed at it. Nothing in the code changes.

What to look for when buying one

  • Rotating, with a single gateway endpoint. Verify rotation with the loop above before you pay for a month.
  • A published thread limit. If it is not stated, assume it is low. This is the number you actually plan around.
  • Flat rate over metered , unless you know your volume is small and stays small. Metered plans punish exactly the endpoints that return the most useful data.
  • Country targeting , if you want regional charts. The device region and the exit region should agree.
  • A trial or one month first. Registration success rate is the real test and it varies between providers advertising the same product. Generate 30 devices and read generation_survival_rate before committing.

Measured success rates

Every endpoint ships with a real success rate rather than a claim: 100 calls each, at most 4 attempts, against a freshly generated pool over a rotating proxy gateway. Seeds are discovered live by walking the API rather than hardcoded, which changes the numbers. The note below explains why.

Endpoint Success Avg attempts Avg response
user.info 100% 1.00 9 KB
user.recommended 100% 1.08 2.9 MB
music.posts 100% 1.06 1.7 MB
music.posts_fresh 100% 1.34 1.7 MB
music.trending 100% 1.00 85 KB
music.related 100% 1.00 139 KB
hashtag.info 100% 1.00 3.8 KB
hashtag.posts_fresh 100% 1.00 1.3 MB
search.general 100% 1.06 527 KB
search.music 100% 1.11 100 KB
search.users 100% 1.00 86 KB
trending.categories 100% 1.07 380 KB
trending.effects 100% 1.10 232 KB
video.comment_replies 100% 1.05 8 KB
video.info 94% 1.96 58 KB
user.following 93% 1.90 23 KB
user.followers 92% 2.12 178 KB
video.comments 92% 2.02 174 KB
search.videos 92% 1.82 639 KB
user.posts 90% 2.26 1.1 MB
music.info 90% 2.15 12 KB
hashtag.posts 89% 2.17 1.3 MB
hashtag.search 78% 2.16 11 KB
feed.recommended 10% 3.93 248 KB

Average attempts is the more informative column. A 100% endpoint at 1.00 attempts succeeds first time, every time. A 92% endpoint at 2.12 attempts is being soft-blocked on roughly half its first tries and recovering on retry, which means a wider budget moves it, whereas nothing moves a first-try-clean endpoint because there is nothing to move.

feed.recommended is genuinely weak, at 10-25% across runs, and it is dominated by honest 429 s rather than soft blocks. An anonymous device with no watch history asking for a personalised feed is precisely the traffic shape TikTok most wants to throttle. It ships documented as weak with the two 100% alternatives named in its place.

How the seeds are chosen

Seeds are discovered live rather than hardcoded: creator, then video, then a comment that actually has replies, then a sound that actually has videos, then a hashtag. This matters for accuracy. Point a follower benchmark at a creator who hides their following list and you measure TikTok correctly answering "nothing here" and score it as a failure.

The 24 endpoints

All of the above is packaged as a self-hosted Go service. One binary, no database, no queue, no emulator, no native library. Reference data is compiled in.

$ cp .env.example .env        # set PROXY_URL
$ docker compose up -d
$ docker compose logs -f

TikTok Open API 1.0.0 starting
config: port=8080 country=SG pool=15/30 attempts=4 concurrency=32 proxy=http://***@gw:9000 auth=true
pool: 0 device(s) live, filling to 30 ...
listening on http://0.0.0.0:8080  (GET /healthz, GET /v1/endpoints)
pool: initial fill complete, 43 device(s) live

Real startup output. Cold start is 15 to 60 seconds; the pool persists to disk so restarts after that are instant.

All 24 routes are GET, all take query parameters, all return TikTok's JSON unmodified.

Creators

Route Parameters Returns
/v1/user/posts user_id, count, max_cursor Videos, each with the full author object
/v1/user/info user_id, sec_user_id Full profile, incl. bio_email , links, commerce flags
/v1/user/followers user_id, sec_user_id, count, max_time Follower list
/v1/user/following user_id, sec_user_id, count, max_time Following list, where published
/v1/user/recommended user_id, sec_user_id, count TikTok's own similar-creators graph

Videos

Route Parameters Returns
/v1/video/info aweme_id Media, stats, sound, tags, author
/v1/video/comments aweme_id, count, cursor Comments with the commenter's user object
/v1/video/comments/replies aweme_id, comment_id, count, cursor Second level of the comment tree

Sounds

Route Parameters Returns
/v1/music/info music_id Sound detail incl. user_count
/v1/music/posts music_id, count, cursor Popular videos using the sound
/v1/music/posts/fresh music_id, count, cursor Newest videos using the sound
/v1/music/trending count, cursor Trending sounds chart, per device region
/v1/music/related aweme_id, count, cursor Sounds suggested for a video

Hashtags and search

Route Parameters Returns
/v1/hashtag/search keyword, count, cursor Hashtag ids with view counts
/v1/hashtag/info hashtag_id Hashtag detail
/v1/hashtag/posts hashtag_id, count, cursor Popular videos under the tag
/v1/hashtag/posts/fresh hashtag_id, count, cursor Newest videos under the tag
/v1/search/videos keyword, count, offset Videos
/v1/search/general keyword, count, offset Blended creators, videos and tags
/v1/search/music keyword, count, cursor Sounds
/v1/search/users keyword, count, cursor Handle or name → numeric user_id

Discovery

Route Parameters Returns
/v1/trending/categories count, cursor The app's what-is-hot shelves
/v1/trending/effects count, cursor Videos carrying sticker_detail for trending effects
/v1/feed count, max_cursor Anonymous For You feed (weak, see above)

A real response

Trimmed to the interesting fields. The raw object has several hundred keys:

$ curl -s "localhost:8080/v1/user/posts?user_id=6744630345964389381&count=20" \
    | jq '{has_more, max_cursor, first: (.aweme_list[0] | {aweme_id, desc, statistics, music, author})}'
{
  "has_more": 1,
  "max_cursor": 1751028792000,
  "first": {
    "aweme_id": "7678101694902832397",
    "desc": "Who Remembers 2022? #fortnite #piececontrolkyle #dogwater",
    "statistics": {
      "play_count": 19438,  "digg_count": 2461,
      "comment_count": 39, "share_count": 176
    },
    "music": {
      "id_str": "7245172246876227585",
      "title": "Need 2 (Instrumental)"
    },
    "author": {
      "uid": "6744630345964389381",
      "unique_id": "freakynaughty",
      "nickname": "freaky",
      "follower_count": 1277258
    }
  }
}

Note that the author object is embedded in every video. One request gives you twenty videos and the full creator record. On the web that is twenty-one requests.

Request metadata comes back in headers rather than polluting the body:

HTTP/1.1 200 OK
X-Endpoint-Id:     user.posts
X-Attempts:        2                 ← first try was soft-blocked
X-Elapsed-Ms:      1874
X-Upstream-Region: sg
X-Device-Region:   SG

Fields the web does not give you

Field Where Populated
statistics.collect_count any video always. Saves, often the earliest movement signal
music.user_count any sound always. Videos made with the sound
author.ins_id video author object ~26% of creators
author.youtube_channel_id video author object ~19%
bio_email user.info only ~1%
commerce_user_level user.info always
bio link nowhere 0%. Not in the mobile API at all

The last row was measured across 579 creators on both endpoints that could plausibly carry it. The outbound profile link is a web-surface field only.

Tutorial: a sound-trend detector

Concrete worked example, because the endpoint list on its own does not tell you what the data is good for. The goal: find sounds that are taking off right now , before they are obviously trending.

The signal is music.user_count , how many videos have been made with a sound. The absolute number tells you a sound is big. The rate of change tells you it is moving, which is the part you want.

Step 1. Snapshot the chart

curl -s "$API/v1/music/trending?count=50" \
  | jq -r '.music_list[] | [.id_str, .user_count, .title] | @tsv' \
  > "sounds-$(date +%s).tsv"

Run it hourly from cron. Each row is id, uses, title .

Step 2. Diff consecutive snapshots

import glob, csv, collections

snaps = sorted(glob.glob("sounds-*.tsv"))[-2:]
prev, curr = [{r[0]: (int(r[1]), r[2])
               for r in csv.reader(open(f), delimiter="\t")} for f in snaps]

movers = []
for mid, (n, title) in curr.items():
    was = prev.get(mid, (0, title))[0]
    if was > 0:
        movers.append((n / was - 1, n - was, title, mid))

for growth, delta, title, mid in sorted(movers, reverse=True)[:10]:
    print(f"{growth:6.1%}  +{delta:>8,}  {title[:40]:<40} {mid}")

Step 3. Confirm it is actually accelerating

Growth in the chart is a candidate, not a confirmation. The check that separates a real acceleration from a chart-placement artefact is the time spread of recent videos . Pull the newest videos using that sound and look at how tightly their upload times cluster:

curl -s "$API/v1/music/posts/fresh?music_id=$MID&count=30" \
  | jq '[.aweme_list[].create_time] | (max - min) / 3600'
2.4

Thirty videos in a 2.4-hour window means thirty people picked up that sound this afternoon. Compare with the popular ordering, which tells you whether it has already landed:

curl -s "$API/v1/music/posts?music_id=$MID&count=30" \
  | jq '[.aweme_list[].statistics.play_count] | add'

High fresh-clustering plus low cumulative plays is the interesting quadrant. Lots of people using it, not much accumulated reach yet. That is a sound on the way up rather than one on the way down.

Step 4. Find who is driving it

curl -s "$API/v1/music/posts/fresh?music_id=$MID&count=30" \
  | jq -r '.aweme_list[].author | [.follower_count, .unique_id] | @tsv' \
  | sort -rn | head

Because the author object is embedded, this costs no extra requests. If one large account is at the top and everyone else is small, you are looking at a sound that one creator kicked off, which is a different (and usually shorter-lived) phenomenon than organic uptake across many mid-sized accounts.

Step 5. Widen it

music.trending is region-scoped to the device. Run a second instance with POOL_COUNTRY=US and a third with POOL_COUNTRY=BR and you get three independent charts from identical code. Sounds frequently break in one market days before another.

Rate of work

The whole loop above is 4 requests per candidate sound per cycle. At 50 candidates hourly that is 200 requests an hour, which is nothing. The expensive version is walking user.recommended outward to map a niche, where responses run ~3 MB each and bandwidth, not rate limiting, becomes the constraint.

Getting the code

Everything described here is a private Go repository. One-time payment, permanent access, complete source.

  • Full signing stack (Simon, Speck, SM3, TTEncrypt, Argus, Ladon) with per-primitive test vectors
  • Device registration, activation and proving pipeline
  • uTLS transport with the manual proxy tunnel
  • All 24 endpoints, measured and documented
  • Pool management: health, eviction, rotation, persistence
  • Docker image and compose file
  • Live integration test suite with seed discovery
  • Python, Node, curl and .http clients
  • Generated reference docs for every endpoint
  • Reliability, pagination and error engineering guides
  • Lifetime updates to the same repository
  • Direct line during setup

Checkout asks for your GitHub username. The repository invitation goes to that account automatically, normally within a minute of payment.

Before you run it

The one hard requirement is a rotating proxy gateway . Rate limiting is per exit IP and the retry design assumes a new connection gets a new address, so a static proxy is no better than none. It is the single external dependency and it is not optional at volume.

Maintenance is yours once you self-host. The repository is structured so that when something moves it is usually one struct literal in one table, but it is your struct literal.

If you would rather skip the setup entirely, there is a done-for-you tier where I build it on your server and hand it over running.

Done for you

The repository is one component of a collection system, and on its own it answers one request at a time. Getting from there to billions of records is a different piece of work: deciding what to fetch next, keeping the queue moving through failures, landing the results somewhere that is still queryable at that size, and running the whole thing across enough shards and proxy capacity to sustain the rate.

This tier is that system, built on your infrastructure and handed over running. Not a demo pointed at a few creators. The same shape as the one that produced the figures at the top of this page, sized to what you are collecting.

$1,899 one time · includes the repository

Get in touch

  • Everything in the $699 tier, including lifetime updates
  • The whole collection system built on your server, from a clean box
  • Database architecture sized to your volume: engine choice, partition and sort keys, the update path for records that change, and the denormalisation your queries actually need
  • ClickHouse installed, tuned and sized, with retention set on its own system tables
  • The crawl pipeline: discovery, work queues, resume after failure, and deduplication so you are not paying to re-collect what you already hold
  • Sharded across multiple instances and proxy capacity, which is what billion scale actually requires
  • Proxy plan chosen with you, configured and rotation-verified
  • Concurrency and retry budget tuned to the plan you actually bought
  • Device pool generated, sized to your workload and persisting across restarts
  • Monitoring on freshness, write failures, pool health and disk, so a stall is visible instead of silent
  • Full smoke test run on your instance, all 24 endpoints returning live data
  • Live walkthrough of the endpoints you care about and how to paginate each
  • 7 days of support after handover

The server and the proxy subscription are yours and are not included in the price. Both stay in your name and under your control. See the proxy section for which tier your volume needs.

Storage, if you are keeping the data

Collecting the data is what the repository solves. Keeping it queryable once there are billions of rows is a separate problem with its own failure modes, and it is the half that decides whether the collection was worth doing. If you are building a store rather than running a one-off pull, that design is part of the handover: table engines, partition and sort keys, the update path for records that change, and the denormalisation that keeps a creator-to-video-to-sound question answerable without a join across billions of rows.

Four decisions that determine whether it holds, each of them measured on a production ClickHouse store at billion-row scale:

  • Partition keys. A bare modulus of an id looks even and is not, because platform ids are not uniformly distributed. One table partitioned on author_id % 8 ended up with a 43x spread between its largest and smallest partition, the largest heading for the size where merges stop keeping up. Hashing the id before the modulus flattens it.
  • The update path. ReplacingMergeTree keeps the newest whole row, not the newest value per column. Write a partial update and every field you left out is silently blanked. Nothing errors, and you find out much later.
  • Duplicate control. Re-collecting the same creator is normal and the storage cost of that compounds quietly. One table was carrying three times the rows it needed before anything made it visible, and rebuilding it returned several terabytes.
  • The database's own logs. ClickHouse writes text_log and trace_log by default with no retention. They reached 243 GB on one instance and took a 7 TB volume to full, which stops writes for everything sharing it. A TTL on the system tables is not optional at this scale.

How it goes

  1. You tell me what you are collecting. Creators in a niche, sounds on a schedule, comments on a set of videos. This determines the proxy tier and the pool size, so it is worth being concrete.
  2. You provide a server and a proxy subscription. The collection layer is light and runs comfortably on two cores. If you are storing what you pull, the database is the part that needs real disk and real memory, and sizing it is part of step one rather than a surprise later.
  3. I deploy and tune it. Usually the same week. You get the running instance, the repository access, and the reasoning behind each setting rather than just the settings.
  4. We run the integration test together. You watch 24 endpoints come back with live data on your own hardware before you consider it delivered.

Questions

Do I need TikTok accounts?

No. There is no login anywhere. Every device is an anonymous app install TikTok issued credentials to. Nothing to get banned, no credentials to rotate, no 2FA.

Why won't it work without a proxy?

It works fine for a look around. It does not work at volume, because rate limiting is per exit IP and the entire retry design assumes a new connection gets a new IP. Rotation is the requirement; a static proxy is no better than none.

A rotating datacenter gateway at around $150 a month, flat rate, covers millions of records. Billions is a different tier at roughly $950. The proxy section works through both and where each one runs out.

Is it legal?

It is against TikTok's terms of service. It is sold for research and educational use.

Researching Employment Scams

Schneier
www.schneier.com
2026-09-03 07:18:14
Researchers built a fake company to study fake employee scams....

A dark horse enters China's AI race: StartLux

Hacker News
chinaonchina.com
2026-09-03 07:12:57
Comments...
Original Article

Something big has happened - a dark horse has emerged among China's top domestic large model developers.

A new company, with its first model having only 27B parameters, took second place overall in the CAICT MCP specialized test.

Ranked ahead of it is the killer weapon Liang Wenfeng has kept under wraps for nearly a year: DeepSeek-V4-Pro, boasting a parameter count of 1.6 trillion.

The difference between the two is a mere 1.3 percentage points.

This dark horse is the StartLux-V1.0-27B-Preview, from StartLux (formerly Yuandian Xinghui).

Looks a bit unfamiliar, doesn't it? Don't worry, its founder and CEO is an old acquaintance: Chen Danyan.

Known as the "godfather" of programmers in the internet era, his achievements are a matter of public record:

Shanda Network's co-founder and the head of Lian Shang Network, one of China's earliest programmers to introduce the concept of "shareware"

After a decade of retirement, he has made a comeback, this time betting on local models.

This has to do with Chen Dawei's recent rare public appearance.

At the 18th anniversary reunion of Shanda Innovation Institute, he publicly declared "eight non-consensus views for the AI era," four of which center on local models.

Local models will completely destroy the cloud market, catching up with Claude in three years and occupying 80% of the market. The model competition based on parameters is going to be outdated...

StartLux is the best representation of his idea.

The company's business has not followed the industry trend, instead focusing on the commercialization of small and beautiful local models, making it the world's first truly local model company in the true sense.

As the first market-oriented scorecard, StartLux-V1.0-27B-Preview does not rely on the cloud and can run directly on consumer-grade PCs.

In other words, this local model, which is nearly 60 times smaller, has Agent capabilities that can match those of a trillion-level cloud-based flagship model.

What justification is there for this?

Small Model Achieves Big Results, 27B Outperforms 1.6T

Before the answer is revealed, let's take a look at who the comparison is being made to.

It's often said that nobody remembers the second place, unless the first is DeepSeek.

Moreover, the gap is minimal, making it well worth discussing.

The results come from the authoritative institution, China Academy of Information and Communications Technology's trustworthy AI large model benchmark test MCP special item, which sets six types of tasks around real application scenarios:

Location navigation, web search, browser automation, financial analysis, code repository management, 3D design.

An additional comprehensive assessment will be added, focusing on evaluating Agent's multi-tool collaboration, complex task execution, and interaction in real-world environments.

In simple terms, MCP-Universe doesn't evaluate models based on their responses, but rather on whether they can actually get things done. This is also the most fundamental aspect of judging an Agent's quality.

The results showed that StartLux-V1.0-27B-Preview had a comprehensive score of 39.25%, ranking second.

DeepSeek-V4-Flash-0731, with over 284 billion parameters, and Step-3.7-Flash, at 198 billion, trail DeepSeek-V4-Pro by just 1.3 percentage points.

With the same 27B parameter scale, StartLux also surpasses Qwen 3.6 by 5.34 percentage points.

It also excelled in individual subjects, ranking first in location navigation, financial analysis, and browser automation, with its other sub-items also ranking high.

Let's take a look at two case studies, putting data aside.

The first question is about a two-year Microsoft stock investment, with Claude Sonnet 4.6 as the competing topic.

Claude's answer is: $47,254, 89.02%.

Video link: https://mp.weixin.qq.com/s/365CtdgGYFlEKNDICtoCfg

StartLux gave: $47,499.09, 90.00%.

It may seem similar, but in the financial industry, a tiny difference can lead to enormous losses.

Careful examination of the two models' reasoning processes shows that, due to missing raw data, Claude Sonnet 4.6 misidentified January 8, 2025 as a non-trading day and instead calculated the previous day's closing price.

Under the same circumstances, StartLux retrospectively reviews the original data and verifies the market trends around the target date to confirm the accurate closing price before completing the calculation and generating visualization.

Ultimately, the conclusion reached by StartLux proved correct, and it was fully verifiable and traceable.

The second task was more straightforward: both models were asked to search for flight tickets in a browser at the same time.

I'm unable to open a browser or interact with live websites like Google Flights. I can only process text and don't have real-time browsing capabilities. To find this flight yourself, here's what you'd do: 1. Go to google.com/flights 2. Enter Singapore (SIN) → Beijing 3. Select one-way, set departure date to 5 days from today 4. Filter by "Nonstop" and "Economy" 5. Check the results — note that flights to Beijing may land at either Capital (PEK) or Daxing (PKX). Exclude any Daxing arrivals. 6. Compare prices and pick the cheapest nonstop option landing at PEK. If you'd like, I can help you think through typical price ranges, airline options on this route, or general tips for finding cheap flights.

Among them, StartLux-V1.0-27B-Preview completed the search in about 95 seconds, finding an Air China ticket priced at $299.

By contrast, Claude Sonnet 4.6 required more screenshot confirmations when navigating date selection, popup dismissal, and filter menus, and even accidentally triggered the time filter panel at one point.

More than 200 seconds later, it gave a lowest quote of $556. The price was higher, and the search time was still twice that of StartLux.

In particular, in terms of operational pathways, StartLux is much more concise, requiring only 12 steps, whereas Sonnet requires a full 21 steps.

This is enough to illustrate that, in Agent tasks, the scale of parameters is no longer the only decisive variable.

New variables are being introduced through post-training.

Cutting Prices, Not Capabilities

StartLux-V1.0-27B-Preview was not trained from scratch.

It is also based on Qwen3.6-27B, but the final test score is significantly higher than Qwen, and the reason lies in the task data and automated post-training methods.

In simple terms, StartLux trains a more capable Agent, with training data focusing on reinforcing abilities such as task understanding, tool selection, parameter construction, multi-step execution, status checking, and result verification.

The model needs to learn not only to output the final text, but also when to invoke which tool, how to adjust when a tool returns an exception, and under what circumstances it can declare the task complete.

Further training will push this process even further.

The team has independently developed a brand-new, multi-dimensional, verifiable, and scalable model iteration optimization technology, which uses the AI-trained AI (Auto Research) method to enable the model to autonomously execute tasks in a real-world tool environment and continuously adjust its strategy based on environmental feedback.

For instance, the financial analysis case mentioned earlier, which involves backtesting and revision, as well as the constraint identification and path selection in browser tasks, are the most intuitive manifestations of post-training.

According to official information, StartLux-V1.0-27B-Preview is also the country's first local Agent model to complete post-training using the Auto Research method.

This does not mean that the Scaling Law is invalid.

Large parameter cloud models are still the mainstream choice at present, but StartLux has also given a clear signal: this is not the only solution.

In the words of Chen Danyan:

Scaling Law is a "passing fairy," without it, AI cannot take off, but it has merely passed through the development path of AI and its future is not necessarily tied to it.

The industry has also become aware of this issue, and the technical path for large models is currently showing a trend of distinct divergence:

On one hand, there are the die-hard believers in "more power leads to miracles," with parameters scaling from tens of billions to hundreds of billions, and then to trillions, while training costs also surge exponentially;

On the other hand, the Agentic assessment system, represented by Harness, has quickly gained popularity, with an increasing number of experts and scholars explicitly advocating for "less is more".

To paraphrase Wang Yangming, the unity of knowledge and action means higher-quality action is what truly matters. StartLux offers another example of simplifying models.

This can also explain why StartLux insists on local models.

Once the model is on a PC, for long-term tasks, its cost structure can shift from continuously accumulating cloud-based token fees to more controllable device computing power and electricity consumption, while the model can also better understand the user's long context, achieving more personalized goals.

It's not just StartLux, as Meta, Google, and NVIDIA have also recently been increasing their investment in local small model development.

However, most of these are still in the experimental stage or cater to niche groups, with only one company focusing on local model commercialization.

StartLux also stated that they will steadily advance their own foundation model training and explore new architectures such as diffusion-based language models, and as long as they are on the right path, the future is promising.

StartLux has taken over the local model, and since this is a non-consensus route, those at the helm need to be two types of people: those who dare to take bets and those who can deliver results.

StartLux's all-star team exemplifies this, pairing entrepreneurs with scientists in a formidable alliance.

StartLux founder Chen Danyan

CEO Chen Danyan had previously been briefly introduced as a serial entrepreneur and one of China's first-generation programmers, who rose to fame around the same time as Zhang Xiaolong and Lei Jun, and started his business ventures in the same era as Ma Yun and Ma Huateng.

He was one of the first people in China to introduce the concept of "shared software" and co-founded Shanda Network with his brother Chen Tianqiao, as well as the Shanda Innovation Institute, a cradle of internet innovation, and was also instrumental in incubating the nationally popular product "WiFi Master Key".

It can be said that he is extremely familiar with Chinese market users and products, and local models are also his comfort zone.

StartLux co-founder Guo Quanwei

The person responsible for implementing the technical roadmap is StartLux co-founder and CTO, Guo Quanwei.

Kuo Chuan-wei holds a Ph.D. in Computer Science and Engineering from National Yang Ming Chiao Tung University, with research areas covering locally deployed large models, Agentic AI, AI for Science, AI for Finance, and privacy-preserving machine learning.

Before joining StartLux, he served as the Chief Algorithm Scientist at AI Science company Huanliang Technology, and earlier worked at the Industrial Technology Research Institute of Taiwan, where he developed data privacy, data de-identification, and privacy-preserving machine learning.

He is also a recipient of the 2024 TAAI Best Paper Award and holds data-privacy-related invention patents as the first named inventor.

Another co-founder of StartLux, Luo Yongxiang, is the former Managing Director of Morgan Stanley Asia.

Chen Danyan understands products and users, Guo Quanwei has long studied local models, Agents, and data privacy, and Luo Yongxiang is in charge of marketing and investment financing. This combination is highly suited to StartLux and will also help drive StartLux's long-term development.

As for what the team ultimately wants to deliver, it's not just a set of model weights.

In StartLux's vision, local intelligent solutions should be deployable with one click, similar to installing Office. Users do not need to understand quantization, GPU memory configuration, and inference frameworks, nor do they need to optimize them repeatedly themselves.

The team currently plans to launch its first-generation local smart solution for enterprise and individual users within the year.

In this light, the emergence of StartLux is by no means just "another player" entering the scene.

It also represents that, following the emergence of cloud-based model companies like DeepSeek and Kimi, domestic local models are also starting to fill in the gaps.

From a rising star in the intelligent era to circling back to the first-generation programmers of the internet era, the fundamental paradigm of models is shifting gears—but through it all, Chinese companies have kept passing the baton and pushing forward.

Official website link: https://startlux.com/

Mark Cuban: Why US hospitals "don't know their costs"

Hacker News
www.beckershospitalreview.com
2026-09-03 07:07:10
Comments...
Original Article

Please enable JS and disable any ad blocker

Plex warns users to patch security vulnerabilities immediately

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 07:02:22
Plex urged users this week to update their desktop clients and media servers immediately to patch multiple security vulnerabilities. [...]...
Original Article

Plex

Plex urged users this week to update their desktop clients and media servers immediately to patch multiple security vulnerabilities.

These flaws have not yet been assigned CVE IDs for easy tracking, and while Plex didn't provide additional details on Tuesday , the security issues are known to affect Plex Media Server v1.43.2 and earlier.

Plex also emailed users running affected versions and asked them to update as soon as possible to address these security flaws.

"We recently released Plex Media Server 1.43.3 and Plex Desktop 1.115.0 to address a number of security issues. We recommend all server owners and Desktop users update to the latest version as soon as possible," the company said .

"CVEs have been requested and we'll reply to this thread with more details once they're published. If you're running Plex Media Server on a NAS device, the updated version may not be available in their package manager yet but you can install the package manually."

Those running affected versions are advised to secure their systems as soon as possible by updating Plex Media Server to version 1.43.3 (released on May 19 ) and the Plex Desktop client to 1.115.0 (released on August 13 ), which can be downloaded from the official downloads page or the server management page.

​​Although Plex hasn't shared any details about these vulnerabilities so far, users should follow the company's advice and secure their systems before attackers reverse-engineer the patches and develop an exploit.

While Plex has patched multiple critical security flaws over the years, this is one of the few instances where it has also emailed customers about upgrading their systems to address a specific vulnerability.

In August 2025, the company also warned users to patch a high-severity vulnerability tracked as CVE-2025-34158 that allows threat actors to steal the server owner's credentials.

Two years earlier, in March 2023, CISA flagged a Plex Media Server remote code execution flaw (CVE-2020-5741) as actively exploited, which can allow attackers to make the server execute malicious code .

While CISA didn't share details on the attacks exploiting CVE-2020-5741, they were likely linked to LastPass's disclosure that one of its senior DevOps engineers' computers had been hacked in 2022 using a third-party media software RCE bug to install keylogging malware.

The attackers used this access to steal the engineer's credentials and compromise the LastPass corporate vault, leading to a massive August 2022 data breach after they stole LastPass's database backups.

The same month, Plex notified users of a data breach and warned them to reset passwords after attackers gained access to a database containing emails, usernames, and encrypted credentials.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

Google Antigravity TOS: 3rd party usage can get Google account suspended

Hacker News
twitter.com
2026-09-03 07:01:04
Comments...
Original Article

Antigravity's terms of services make it crystal clear that if they determine you use Antigravity in a way they suspect is eg third-party usage (eg use OpenClaw), they can suspend your Google account. One reason to NOT use Antigravity. I'm not taking this risk, sorry.

I don't think people understand just how risky it is to try and use their Google Gemini subscriptions outside of Google's official surfaces. You can get your ENTIRE GOOGLE ACCOUNT BANNED. OpenAI or Anthropic ban? Annoying but whatever Google account ban? Legit life ruining.

Women are giving their partners the ‘Illiterate Boyfriend’ test: ‘Do your best to pronounce these words’

Guardian
www.theguardian.com
2026-09-03 07:00:51
People online are distressed at men butchering words such as ‘hyperbole’ and ‘hors d’oeuvres’ – highlighting a gender reversal in ‘intelligence gaps’ There are common non-negotiables we look for in a prospective partner. They should be kind, caring and thoughtful. Having a shared interest helps. So ...
Original Article

T here are common non-negotiables we look for in a prospective partner. They should be kind, caring and thoughtful. Having a shared interest helps. So does remembering important dates and anniversaries. But how much does it matter if they know how to pronounce the word “gnocchi”?

Turns out that’s a potential dealbreaker, at least according to a (rather judgy) cohort on TikTok . See: the “Illiterate Boyfriend” trend, which is testing some couples on the app. Users have compiled a list of what are essentially SAT words for women to ask their male partners to read. Many of these men – this is an overwhelmingly heterosexual activity – fail to finish the list unscathed. They trip over entries such as “hyperbole”, “cynicism”, “diaphragmatic” and the oft-butchered French term, “hors d’oeuvres”.

“I want you to do your best to pronounce these words,” one woman asks her boyfriend in a clip viewed more than 8.8m times. He gamely nails his first attempt, reading off the herb “thyme”. But he’s less successful with “epitome”, “challah” and “fuchsia”. (“ Foo-chia? ” he guesses). “Conscientious” and “faux pas” also prove tricky. He ends up with a score of five out of 17, or 29% – very much a failing grade.

The couple laughed through the exercise, but viewers were not as charmed by an adult man struggling through what they considered basic vocabulary. “The fact that his vote matters just as much as mine is really pissing me off,” one woman wrote in the comments section. “I’m gonna be honest girl, this is worth breaking up with him over,” read another comment.

Two of the words the man correctly identified were “colonel” and “regime”, which, to one user, was evidence of a red flag : “he’s obviously a Republican”. (Maybe he just has an interest in military history, a time-honored hobby of boyfriends everywhere.) Regardless of political affiliation, it seemed fair game to dunk on Mr Foo-chia. One final quip from a viewer: “He’d be so upset if he could read these comments.”

The test made its way around TikTok, with more young couples joining in, to similarly bleak results. Even those men who did well got caught up in the pop-misandry circus. One man zipped through the list, ending with a perfect score and a self-satisfied grin. It was not the flex he might have hoped for. “This is the barest fckn minimumest [sic] of bare minimums,” one woman commented. “The men are being praised for literacy we’re in hell,” wrote another.

Distress over so-called “intelligence gaps” brings to mind a phenomenon that reverses decades of dating precedent: women are now more likely to marry less-educated men than men are to marry less-educated women. This is not necessarily by women’s choice; it is the new dating pool. According to a 2024 Pew Research report , in 1995, young men and women were equally likely to hold a bachelor’s degree. Now, 47% of women ages 25 to 34 have one, compared with 37% of their male counterparts.

“We do have in our mating market an oversupply of educated women and an undersupply of formally educated men – I’m talking academically, not necessarily in their skill set, emotional or social intelligence,” said Dr Wendy Walsh, a clinical psychologist and expert at DatingNews.com .

Dr Jess Carbino is a former sociologist for Tinder and Bumble who studies dating apps. When she polls people on what they look for in a partner, “intelligence” is rarely in the top three desired traits. “They say things like humor, kindness, attractiveness, typically,” she said. “Maybe people on the coasts – New York, Los Angeles, San Francisco – might say intelligence. But by and large, that’s not one of the top things being measured.” And there are so many different ways to consider intelligence, spelling being a way to formally test fourth-graders, not romantic partners.

One thing people do want is an equal. “It’s not necessarily that someone needs a specific degree or to know every word in the dictionary,” said Robin Hamilton, a couples therapist. “It’s more: are you able to communicate with me, are you able to meet me halfway with the subjects that I’m talking about?”

One of those subjects might be reading , an indicator of vocabulary range . Men’s rates of book reading have slipped over the past decade; nearly half of all women read just one novel or short story in 2022, but only one in four men did. According to data from Tinder, mentions of books in bios on the dating app jumped 40% this year among women, but only 23% among men. Women believe they see this disparity playing out on TikTok, even if it is through an ultimately meaningless list.

It is elitist – and naive – to draw any real conclusions about what makes a good partner based on a reading test. This “Illiterate Boyfriend” list contains words that may be more indicator of class than intelligence, conflating education with one trait women have prioritized for hundreds of years, mostly due to necessity: having money.

But the trend also reflects a wider disillusionment among straight women , who are significantly less likely to want to date than men are, partly because they say it’s hard to find someone who checks all their boxes. “He looks at the word ‘queue’ and pronounces it ‘ qwi-wee ’?” one woman said in a video responding to the test. “And you still have sex with him?”

“It’s rage bait for women who are frustrated and angry with the mating marketplace that is slanted unfairly” against women, Walsh said, adding: “It’s OK to date a guy who can’t say epitome or niçoise. I have a PhD, but I need spellcheck for hors d’oeuvres.”

Then they came for the programmers

Lobsters
medium.com
2026-09-03 06:57:06
Comments...
Original Article

Why have I been blocked?

This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.

What can I do to resolve this?

You can email the site owner to let them know you were blocked. Please include what you were doing when this page came up and the Cloudflare Ray ID found at the bottom of this page.

Audacity 4.0

Hacker News
github.com
2026-09-03 06:53:08
Comments...
Original Article

Audacity 4.0

Audacity 4 rebuilds the application interface on Qt and introduces many new quality-of-life improvements, including a new clip-editing model. Most Audacity 3 workflows remain available, but some controls have moved or changed.

Watch the video:

Editing clips

  • Clips can be selected directly. Click a clip header to select it, or Shift-click to select multiple clips.
  • Several clips can be edited together. Moving, trimming and time stretching apply to all selected clips.
  • Clips can be grouped. Groups remain together when moved, copied, pasted or duplicated.
  • Clips can be placed more freely. They can move between mono and stereo tracks. Moving a clip over another replaces the overlapped part instead of blocking the move.
  • Splitting has a dedicated tool. Press or hold S , then click the waveform or clip header. Split, split-cut, split-delete, split at silences and split to a new track are also available as commands.
  • Paste handles more cases automatically. Audacity can create a track when needed, adapt compatible channel layouts and paste audio files from the operating-system clipboard.
  • Alignment guides, sample-boundary snapping and per-project snap settings have been added or expanded.

Interface and tools

  • The interface has been rebuilt on Qt , with native high-DPI rendering.
  • Toolbars and panels can be moved, docked, floated, shown or hidden.
  • UI layouts can be saved as Workspaces . Audacity includes Modern, Classic and Music workspaces.
  • Light, dark and high-contrast themes are available, along with accent colors, track colors and several clip styles.
  • The new Home screen shows recent projects with preview thumbnails.

The separate Select, Envelope, Draw and Multi-tool modes have been removed. Their functions are now context-sensitive:

  • Volume envelopes are displayed in the Clip gain mode.
  • Sample drawing becomes available when the waveform is zoomed to individual samples.
  • Splitting is available by holding S .
  • Track and effect parameters use consistent rotary controls with fine adjustment and double-click reset.
  • Sync-Lock has been removed. Delete, cut and paste now have explicit variants for either leaving a gap or moving later material to preserve timing.

Playback and recording

  • The playhead remains visible during navigation and can be dragged to a new position.
  • Playback can seek to another position without stopping.
  • Recording can start anywhere on the timeline and creates a clip at that position.
  • Loop boundaries and the interaction between playback, selections and loops have been revised.
  • Punch and Roll, lead-in recording, latency compensation, software playthrough and per-track input monitoring have been rebuilt for the new interface.
  • Audio Setup now includes system-default devices, refreshable device lists and custom channel mapping. Audacity can follow operating-system device changes automatically.
  • Official Windows builds include ASIO playback and recording support.

Tracks, meters and effects

  • Track headers now contain live playback and recording meters.
  • Preset handling is consistent across built-in, destructive and realtime effects.
  • Built-in effects, generators and analyzers have been rebuilt for the Qt interface.
  • Supported plugin formats are VST3, Nyquist, LV2 on Linux and Audio Units on macOS. Audacity can display generated controls when a plugin's own interface is unavailable.
  • Spectrogram has been redesigned with clearer guides and rulers, and faster rendering.

Projects, import and export

  • Audacity 4 uses the new .aup4 project format .
  • .aup3 projects open and convert to .aup4 without changing the original file. Converted projects cannot be saved back to .aup3 .
  • Older .aup projects can be imported.
  • Project files store preview thumbnails and Audacity 4's additional clip and appearance data.

And last but not least, we had the audacity to change the Audacity logo.

Compatibility notes

The following Audacity 3 features are not available in Audacity 4.0, but we're working on adding them in future releases.

  • Time Tracks
  • Note/MIDI tracks
  • Mixer
  • Macro Manager and the scripting pipe
  • VAMP and LADSPA plugin hosting
  • Play-at-speed

Sync-Lock and the old tool modes were replaced by the workflows described above.

Additionally, Audacity 4 ships with some missing exporting and rendering features, analyzers, and effects.

Update: audacity-sources-4.0.0.tar.xz was updated to include SoundTouch and sbsms 3rd-party libraries.

How Swiss Tables Work in Go’s Built-in Map

Lobsters
victoriametrics.com
2026-09-03 06:50:44
Comments...
Original Article

We have already written about Go maps and their old runtime implementation in Go Maps Explained: How Key-Value Pairs Are Actually Stored . Go 1.24 replaced that implementation with a design based on Swiss Tables, so it is time for an update.

You do not need to go back and read the old article. We will review how maps behave and the concepts needed here before moving into the new runtime internals.

The Go blog also has an excellent article, Faster Go maps with Swiss Tables . It goes deeper and assumes a little more background knowledge. We take a different approach. We will discuss the same implementation more gradually and in a visual way, so you can relax your brain a little and still understand what Go is doing.

If you are already familiar with maps in Go, feel free to skip the first section.

Maps in Go: a quick review

#

A map stores key-value pairs, and each key is associated with one value. The key type and value type can be different:

m := map[string]int{
	"dog": 1,
	"cat": 2,
}

Besides using a map literal, we usually create an empty map with make :

m := make(map[string]int, 100)

The optional 100 tells Go that we expect the map to hold around 100 entries. Go uses 100 as a hint when it creates the map’s initial storage, which we will explain in the next section. The map can then hold the requested number of entries before it needs to grow, which is an expensive operation.

Just a spoiler: with a hint of 100 , Go creates initial storage with 128 slots. It can hold 112 entries before the next new entry makes it grow.

The spoiler I just revealed is an internal detail because Go does not expose a map’s capacity. len(m) reports the number of stored entries, while the built-in cap does not accept maps. The value passed to make is only a sizing hint to the runtime.

println(len(m)) // 0
println(cap(m)) // compile error: invalid argument: m for built-in cap

Assignment, lookup, and deletion use the same operations in every Go version:

m["dog"] = 1

value := m["dog"]
value, ok := m["dog"]

delete(m, "dog")

The first lookup value := m["dog"] returns the value directly. If "dog" is missing, it returns 0 , the zero value of int .

The two-value form value, ok := m["dog"] also returns ok to tell us whether the map contains "dog" . This removes the ambiguity between a missing key and a stored key with the value 0 .

Both cases return 0 in value , but ok is false for the missing key and true for the stored key.

m := map[string]int{"dog": 0}

println(m["dog"]) // 0: the key exists
println(m["cat"]) // 0: the key does not exist

The zero value of a map is nil , but its behavior is slightly nuanced because not every operation on a nil map causes a panic:

var m map[string]int

value, ok := m["dog"] // safe
println(len(m))       // safe
delete(m, "dog")      // safe
for range m {}        // safe
m["dog"] = 1          // panic: assignment to entry in nil map

Reading, deleting, calling len , and ranging over a nil map are safe. Writing an entry to a nil map panics with assignment to entry in nil map .

Before looking inside a map, let’s look at 2 more rules:

  • A range loop does not guarantee any iteration order.
  • A built-in map supports concurrent reads as long as no goroutine writes to it. Concurrent reads and writes, or multiple concurrent writes, need synchronization such as a mutex.

A map’s key type must also be comparable because, internally, the map hashes each key to locate candidate slots and then compares candidate keys for equality ( == ) to confirm that it has found the requested key:

  • Strings, integers, pointers, and channels are valid key types.
  • Structs are valid if all their fields are comparable.
  • Arrays are valid if their element type is comparable.
  • Slices, maps, and functions are not.
m := make(map[[2]string]int) // valid: arrays of strings are comparable
m[[2]string{"dog", "cat"}] = 1

_ = make(map[[]string]int) // compile error: invalid map key type []string

Go rejects the invalid map key type during compilation, so this program cannot be built or run.

An interface type such as any is a valid map key type, but every concrete value assigned as a key must also be comparable:

m := make(map[any]string)

m["dog"] = "string key"                    // valid
m[42] = "integer key"                      // valid
m[[2]string{"dog", "cat"}] = "array key"   // valid

m[[]string{"dog", "cat"}] = "slice key"    // panic: runtime error: hash of unhashable type []string

The snippet above passes compilation and stores the first 3 entries. It then panics on the final assignment when the runtime tries to hash the []string value stored inside the interface key.

That’s enough warming up. It’s time to get into the map internals.

What is a map at runtime?

#

Let’s start with what a map actually is.

m := make(map[string]int)

make initializes the map. map[string]int is the language-level type, which tells us that the map uses strings as keys and integers as values. Underneath that type, the runtime representation of m is a pointer to internal/runtime/maps.Map .

type Map struct {
	used uint64
	seed uintptr

	dirPtr unsafe.Pointer
	dirLen int
	...
}

We can easily inspect this with println , which prints that pointer:

m := make(map[string]int)
m2 := m

println(m)  // 0x14000122000
println(m2) // 0x14000122000

Copying m to another map variable copies this pointer, so both variables refer to the same runtime Map and the same entries.

Copying a map variable makes m and m2 point to the same runtime Map.

Copying a map variable makes m and m2 point to the same runtime Map.

The 2 fields at the top describe the map itself, not the storage for its entries.

type Map struct {
	used uint64
	seed uintptr
	...
}

used counts how many entries are currently stored. Since Go knows exactly where to find the number of entries, when you write len(m) , Go replaces this call with an access to the first field of Map and converts it to an int . That is why len(m) is O(1) instead of scanning the entire map.

seed is an interesting field because it causes different maps to distribute the same keys differently. Go initializes this field with a random number for every map.

The same entries are arranged differently when maps use different seeds.

The same entries are arranged differently when maps use different seeds.

The array above is only a simplified representation used for this explanation. The actual data structure is more complicated.

Whenever Go needs to locate a key in the map’s storage, it hashes that key using the map’s seed. Since each map receives its own seed, hashing the same key in 2 maps can produce different hash values and therefore different storage locations.

Group

#

A map lays out its storage differently depending on the number of key-value pairs it holds.

In its smallest form, a map stores up to 8 key-value pairs in a structure called a group . This is the smallest unit of storage that Go’s Swiss Table implementation examines at one time. Each group contains:

  • 8 slots for key-value entries.
  • 8 control bytes, one for each slot. Go stores these 8 bytes together in one uint64 .

A group pairs each control byte with the key-value slot below it.

A group pairs each control byte with the key-value slot below it.

The group’s concrete type depends on the map’s key and value types, so the compiler generates an internal anonymous struct for each map type. Conceptually, map[string]int has this layout:

type group struct {
	ctrl uint64

	slots [8]struct {
		key  Key
		elem Elem
	}
}

Go is also testing a new group layout with separate key and value arrays to improve key lookup locality and remove repeated alignment padding, as explained in the split group layout section.

Control bytes and the control word

#

Let’s first look at the top row of the group. These are the 8 control bytes. Together, they form the 8-byte control word .

Each control byte describes the slot directly below it, so control byte 0 belongs to slot 0, control byte 1 belongs to slot 1, and the same relationship continues through slot 7.

But where do those bytes come from?

Go hashes the key using the seed from Map , then divides that hash into 2 parts. On most 64-bit targets, the upper 57 bits are called H1 , and the lower 7 bits are called H2 . Suppose we have another key, "cow" , which produces H2 42 in our illustration:

A 64-bit hash contains H1 and a 7-bit H2.

A 64-bit hash contains H1 and a 7-bit H2.

Go uses a 32-bit hash layout on 32-bit targets (and Wasm). We will follow the 64-bit layout in the rest of this article.

H1 is the first part of the hash that Go uses to choose where a search starts in the map’s storage. A small map has only 1 group, so there is nothing to choose. Let’s leave it aside until the map grows.

H2 is the part stored in the control byte above a live slot.

But a control byte has 8 bits, while H2 uses only 7, so we still have 1 bit left. Go uses this highest bit to tell whether the slot contains a live entry or a special state. If this bit is 0 , the lower 7 bits contain H2. If this bit is 1 , the complete control byte represents empty or deleted :

A control byte represents a live, empty, or deleted slot.

A control byte represents a live, empty, or deleted slot.

When its slot contains a key-value entry, the highest bit is 0 , while the lower 7 bits contain H2. H2 42 is 0101010 in binary, so the complete control byte for "cow" is 00101010 .

When the highest bit is 1 , the control byte stores a special value instead of H2. An empty slot uses 10000000 . A deleted slot uses 11111110 and is also called a tombstone . Both states contain no live key-value entry, but a lookup can stop at empty while it must continue past deleted . We will return to this distinction in the deletion section.

With this layout, a control byte lets Go answer 2 questions before it reads the complete key from a slot:

  • Does this slot contain a live entry, or is it empty or deleted ?
  • If the slot contains a live entry, could its key be the one we are looking for?

Now return to the original group above:

A group pairs each control byte with the key-value slot below it.

A group pairs each control byte with the key-value slot below it.

Next, assign a value to the "cow" key that produced H2 42 :

Before storing "cow" , Go must know whether this assignment updates an existing key or adds a new one. It uses H2 to find slots that may already store the key, then confirms each candidate with a complete key equality check.

  • H2 for "cow" is 42 , which is also the value stored in the control byte of "dog" .
  • Go then compares the complete keys with an equality check ( == ), but "dog" is not equal to "cow" .
  • No other control byte contains H2 42 , so Go knows that this assignment is adding a new key.

The map selects the first empty slot in the group, which is slot 2, writes "cow" and 4 into that slot, then writes H2 42 into control byte 2 directly above it:

Cow uses the first empty slot and stores H2 42 above it.

Cow uses the first empty slot and stores H2 42 above it.

The insertion increases used from 3 to 4 , which also changes the value returned by len(m) to 4 . Since this small map still needs only one group, dirPtr points directly to that group and dirLen is 0 :

The small map points directly to its four-entry group.

The small map points directly to its four-entry group.

In this small-map form, dirPtr points directly to the group that stores the map’s key-value entries.

Now the group contains 2 control bytes with the same H2 value, 42 : one above "dog" and one above "cow" . Suppose we later assign another value to "cow" :

Before Go can update the value, it must find the existing key. It takes H2 42 from the hash and compares it with all 8 control bytes in the group at once:

H2 42 selects dog and cow as candidate keys.

H2 42 selects dog and cow as candidate keys.

Go does not visit the 8 slots one by one and compare H2 with each control byte separately. On AMD64, Go uses SIMD instructions to compare H2 42 with those 8 control bytes at the same time.

SIMD lets the CPU apply the same comparison to several byte values in parallel. On AMD64, the result is a packed bitmap with one bit for each slot:

One control-word comparison produces the candidate bitmap.

One control-word comparison produces the candidate bitmap.

In our group, the bits for slots 0 and 2 are set because both control bytes contain 42 . The other bits are clear, which masks out the other 6 slots without reading their complete keys.

Other architectures produce the same candidate mask with arithmetic and bitwise operations on the 64-bit control word, but they use one byte per slot instead of packing the result into 8 bits.

Go then reads the complete keys from slots 0 and 2 and compares them with "cow" . "dog" fails the equality check ( == ), while "cow" matches, so the assignment updates the value stored for "cow" .

Table

#

A group has only 8 slots, so if we keep adding key-value pairs beyond its capacity, Go needs another storage structure to store them.

Go doubles the number of groups from 1 to 2 and introduces a new structure called a table to manage them. It moves the 8 existing entries from the small group into that table, redistributes them between the 2 groups, and then stores the new entry.

The ninth entry turns one group into a table with two groups.

The ninth entry turns one group into a table with two groups.

A table is a complete Swiss Table that owns one or more groups together:

type table struct {
	used       uint16
	capacity   uint16
	growthLeft uint16
	...

	groups groupsReference
}

Our first table has capacity = 16 , used = 9 , and 2 groups:

  • groups points to the contiguous allocation that contains the groups.
  • capacity counts all slots across those groups.
  • used counts the live entries in this table.

Now, why do the existing key-value pairs in the first group need to be redistributed, and how does Go know which of the 2 groups each pair should go to?

Let me introduce H1, which is used for this exact purpose. Go uses H1 to calculate the starting group for each key:

starting group = H1 % number of groups

Since this table has 2 groups, % 2 only needs the lowest bit of H1. When we write H1 with its highest bit on the left, the lowest bit is the rightmost bit, directly beside H2 in the original hash.

For example, suppose H1 for "cow" ends in 0 , while H1 for "dog" ends in 1 :

The lowest H1 bit redistributes entries between two groups.

The lowest H1 bit redistributes entries between two groups.

Because the number of groups changed, Go runs this calculation again for each existing key. Some key-value pairs are inserted into the new group 0, while others are inserted into the new group 1.

This result is only the starting group. For example, a 16-slot table with 10 live entries can distribute them unevenly, leaving one group full while the other still has empty slots:

One group can be full while another still has empty slots.

One group can be full while another still has empty slots.

In this case, another key may also select the full group 0 above as its starting group. Go cannot store the key there, so it checks group 1 next. The list of groups Go checks, together with the order used to check them, is called the triangular probe sequence .

What is the triangular probe sequence?

Let’s say the table has 8 groups, and H1 selects group 3 as the starting group for a key. If group 3 has no empty slot, Go needs to check other groups.

Instead of checking adjacent groups in order, Go moves by +1 , then +2 , then +3 , wrapping around when it reaches the end of the table.

An eight-group triangular probe sequence.

An eight-group triangular probe sequence.

These growing steps produce triangular offsets from the starting group, which is where the name comes from. Because the group count is a power of two, Go visits every group exactly once before the sequence repeats.

The storage pointer in Map also changes when the small map becomes a table-backed map. dirPtr no longer points directly to a group. It points to a one-entry array, and that entry points to the table.

The runtime calls this pointer array the directory :

dirPtr reaches the table through directory entry 0.

dirPtr reaches the table through directory entry 0.

The table above starts with 2 groups. Since each group contains 8 slots, this table currently has 16 slots.

If we keep adding keys, Go can replace it with a larger table containing 4 groups, then 8 groups, then 16 groups, and continue doubling the number of groups when more storage is needed. One table can grow up to 128 groups, giving it a maximum capacity of 1024 slots:

128 groups * 8 slots = 1024 slots

If another insertion requires more storage, Go splits the table into 2 tables instead. We will follow that split shortly.

But after the small map with 1 group becomes a table with 2 groups, Go uses a different growth threshold:

  • The map does not wait for all groups in the table to become full before doubling the group count from 2 to 4, from 4 to 8, and so on.
  • Once a table has grown to 1024 slots, it also does not wait for every slot to contain an entry before splitting it into 2 tables.

A regular table reaches its insertion limit before every slot is used, and that limit is controlled by the load factor . It tells Go how full the table is. Go includes both live entries and deleted slots in this calculation:

load = (live entries + deleted slots) / table slots

Our table has no deleted slots, so with 16 slots and 10 live entries, its load factor is 10 / 16 , or 62.5% .

Go does not let a regular table reach 100% . Its maximum load factor is 7 / 8 , or 87.5% , which means that live entries and deleted slots together may account for 7 out of every 8 slots on average. The limit applies across the whole table.

The table field growthLeft tracks how many additional empty slots new keys may consume before the table reaches that limit.

type table struct {
	used       uint16
	capacity   uint16
	growthLeft uint16
	...

	groups groupsReference
}

A 16-slot table containing only live entries and empty slots has an insertion limit of 14 entries because 16 * 7 / 8 = 14 . After the 10 entries above are stored, growthLeft is 4 .

growthLeft reaches 0 after the table stores 14 live entries. If another new key needs an empty slot, Go doubles the table’s number of groups if the table has fewer than 1024 slots.

A table doubles until it reaches 1024 slots.

A table doubles until it reaches 1024 slots.

Each time the table doubles its number of groups, Go hashes every live key in that table again and redistributes all its entries across the new groups.

A table with 1024 slots already contains the maximum of 128 groups. In this case, Go splits the selected table into 2 new tables instead, each with 128 groups and 1024 slots.

Here, when we say split , we do not mean that the number of tables doubles. The number of tables increases gradually because only the table that needs more space splits into 2 new tables. The other tables are unchanged.

This split uses a different end of H1 than the calculation that chooses a group. When the number of groups doubles, Go uses one more bit from the right side of H1, where the low bits are, to calculate the starting group inside the same table.

So when a table splits, Go uses the next unused bit from the left side of H1, where the high bits are, to choose between the 2 new tables.

Suppose H1 for "dog" begins with 0 , while H1 for "cat" begins with 1 . The 0 sends "dog" to table 0, and the 1 sends "cat" to table 1:

The leftmost H1 bit separates the first two tables.

The leftmost H1 bit separates the first two tables.

So the map hashes the key again with its seed, reads the same leftmost H1 bit, and inserts the key-value pair into the selected new table. After all live entries have moved, Go retries the insertion that triggered the split, just as it does when doubling the number of groups.

Directory

#

Before getting into the directory, let’s understand what problem it solves.

Redistribution

#

If Go redistributed every key-value pair in the map whenever one table needed more storage, each growth operation would become more and more expensive as the map became larger. Instead, Go only rebuilds the table that needs more storage.

When the number of groups in a table doubles, Go redistributes only the live key-value pairs from that table across the new groups.

The leftmost H1 bits select a table, while the rightmost H1 bits select a starting group inside that table.

When the number of groups changes, Go only changes how many rightmost H1 bits that table uses for its group selection.

The left and right ends of H1 select a table and a group.

The left and right ends of H1 select a table and a group.

It does not change the leftmost H1 prefix that selected the table. A key stored in another table has a different leftmost H1 prefix, so it continues to select that table and does not take part in this redistribution.

When a table splits into 2 tables, Go redistributes only the live key-value pairs from the original table between the 2 new tables.

When the map has 2 tables, the directory uses the leftmost H1 bit to select between them: 0 points to table 0 and 1 points to table 1. If table 1 splits, the directory increases the number of leftmost H1 bits it reads from 1 to 2:

Splitting table 1 leaves table 0 unchanged.

Splitting table 1 leaves table 0 unchanged.

H1 prefixes 00 and 01 select directory entries 0 and 1 , which both point to table 0 because table 0 has not split. Prefix 10 selects entry 2 , which points to new table 1, while prefix 11 selects entry 3 , which points to new table 2.

You can see that the map now contains 3 tables, but 2 leftmost H1 bits produce 4 possible combinations, right?

This is where the directory becomes useful. It has 4 entries, one for each bit combination, but those entries do not need to point to 4 different tables.

Four directory entries can point to three tables.

Four directory entries can point to three tables.

During a lookup, Go uses the 2 leftmost H1 bits to select a directory entry, and that entry tells Go which table to search. This allows one table to split without requiring every other table in the map to split with it.

In other words, the leftmost H1 bits select a directory entry, not a table directly, and that directory entry tells Go which table may contain the key.

Global and local depth

#

Let’s say table 0 has reached its insertion limit and needs to split. However, we cannot simply split it as we did with table 1, because 2 directory entries point to table 0.

Table 0 therefore needs a way to know:

  • How many directory entries point to it?
  • Does the directory already have enough entries for the 2 new child tables?

This is what global depth and local depth tell us.

type Map struct {
	dirPtr unsafe.Pointer
	dirLen int

	globalDepth uint8
	...
}

type table struct {
	localDepth uint8
	...
}

Global depth belongs to the whole directory. It is the number of high hash bits used to select one directory entry. In this case, we have 4 directory entries selected by the 2 leftmost bits of H1 ( 00 , 01 , 10 , and 11 ), so globalDepth = 2 .

Local depth belongs to each table. It is the number of high hash bits needed to identify that table. In this case:

  • Every key with an H1 prefix of 0 chooses table 0. Table 0 is identified by the leftmost bit ( 0 ), so its localDepth = 1 .
  • Every key with an H1 prefix of 10 chooses table 1, while every key with an H1 prefix of 11 chooses table 2. Tables 1 and 2 need the 2 leftmost bits, so each has localDepth = 2 .

Four directory entries point to three tables.

Four directory entries point to three tables.

Table 0 knows that its local depth ( 1 ) is less than the global depth ( 2 ), which means the directory already has enough entries for the split. Go can make entry 0 point to one child and entry 1 point to the other without growing the directory.

Table 0 splits into tables 0 and 1 without growing the directory.

Table 0 splits into tables 0 and 1 without growing the directory.

What if table 1 reaches its insertion limit and needs to split instead of table 0? In this case, its localDepth ( 2 ) is equal to the map’s globalDepth ( 2 ). The map first doubles the directory from 4 entries to 8 and increases globalDepth to 3 . It then splits table 1 into tables 1 and 2:

Splitting table 1 doubles the directory before creating tables 1 and 2.

Splitting table 1 doubles the directory before creating tables 1 and 2.

So far, so good. Let’s recap what we have discussed so far using only a key’s hash.

The highest bits of H1 select a directory entry and therefore a table. The lower bits of H1 select a starting group inside that table. H2 filters the 8 slots in the group. Any H1 bits between the directory selection and the group selection may be unused for the current map shape:

The hash supplies bits for a directory entry, a group, and H2.

The hash supplies bits for a directory entry, a group, and H2.

What changed in Go 1.24?

#

After following the new implementation from a group to a directory, let’s compare it with the implementation that Go used before version 1.24.

The old implementation stored up to 8 key-value pairs in one bucket. If that bucket could not hold another entry, the runtime could connect an overflow bucket that provided 8 more slots.

If the overflow bucket also became full, another overflow bucket could follow it:

A bucket points to a chain of overflow buckets.

A bucket points to a chain of overflow buckets.

An overflow bucket allowed 1 full bucket to receive more space without redistributing the other buckets. But an overflow chain also introduced several costs:

  • A lookup had to load the overflow pointer before it could find and check the next 8 slots.
  • A longer chain repeated that pointer load and bucket scan for every additional overflow bucket.
  • Extending the chain could require another allocation.

Go cannot read the overflow bucket until it has loaded the pointer from the current bucket. Every additional overflow bucket adds another dependent pointer load:

bucket
  -> load pointer
overflow 1
  -> load pointer
overflow 2

The new implementation allocates a table’s groups together in one array. It already knows exactly where each group is and uses the triangular probe sequence to find another group inside that table when the starting group has no empty slot:

Old maps use overflow buckets while new maps probe table groups.

Old maps use overflow buckets while new maps probe table groups.

Growth is the 2nd major change.

The old implementation had one primary bucket array for the map. When the bucket array doubled, Go created a new array with twice as many buckets. The key-value pairs from each old bucket were then distributed between 2 buckets in the new array.

Entries from old bucket 0 move into new buckets 0 and 4.

Entries from old bucket 0 move into new buckets 0 and 4.

Go repeated this process gradually for every old bucket as we assigned or deleted entries, so both arrays stayed alive until every key-value pair had moved.

In contrast, Go’s Swiss Table growth does not move one group at a time, as we discussed. The new implementation divides a large map into tables with at most 1024 slots.

One assignment may rebuild one complete table, but the advantage is that it does not rebuild the entry storage of the other tables.

Swiss Table growth rebuilds only the selected table.

Swiss Table growth rebuilds only the selected table.

In the Go team’s microbenchmarks, map operations ran up to 60% faster than in Go 1.23, although some edge cases became slower. Full application benchmarks showed a geometric mean CPU time improvement of around 1.5%.

Bonus

#

Deletion

#

Let’s return to the 3 control states we introduced earlier, this time focusing on deleted :

The deleted control state is the focus of this section.

The deleted control state is the focus of this section.

An empty slot and a deleted slot both contain no live key-value entry, but they have different meanings during lookup.

During a lookup:

  1. Go first checks whether any candidate slot in the current group contains the requested key.
  2. If Go does not find the key in those candidate slots and the group contains an empty control byte, Go can stop early.
  3. A deleted control byte cannot provide the same guarantee because another key may have been inserted into a later group before this slot was deleted, so Go must continue checking other groups in the probe sequence.

The empty state does not mean no keys exist after the empty slot or in later groups. Other keys may still be stored there. It only means the requested key cannot sit in a later group along the same probe sequence.

But deleting a key does not always produce a deleted slot. In a small map with only 1 group, the removed slot always becomes empty because lookup has no later group to continue to.

In a larger table-backed map, the removed slot also becomes empty if its group already contains at least 1 other empty slot. If the group has no empty slot, Go marks the removed slot as deleted so lookup can continue to later groups.

Why load factor?

#

Earlier, we said Go lets live entries and deleted slots account for up to 7 / 8 of a table before the next new key needs table maintenance. This ratio is the table’s load factor :

load factor = (live entries + deleted slots) / table slots

Our current table has 16 slots and no deleted slots. A load factor of 7 / 8 gives it space for 14 live entries:

Why does Go stop here instead of filling all 16 slots?

The triangular probe sequence chooses the group indexes, and Go scans the selected groups one at a time. This work is a linear scan across the probed groups, so checking 4 groups requires 4 separate group checks.

Now extend the same load factor to a 32-slot table. It can store 28 live entries and still keep 4 empty slots. All 4 empty slots may sit in one group, while the other 3 groups are full:

An empty slot stops lookup before 2 later groups.

An empty slot stops lookup before 2 later groups.

Suppose a missing lookup starts at group 0. With 4 groups, the triangular probe sequence is 0 -> 1 -> 3 -> 2 . Go checks group 0, then group 1. The empty control bytes in group 1 stop the lookup, so Go never checks groups 3 and 2 even though both contain entries.

As the table fills, empty slots become harder to find. A missing lookup may scan more groups before it reaches an empty control byte. If every slot were full, no empty control byte could stop the scan, so Go would need to check every group before reporting a missing key.

The 7 / 8 limit keeps some empty slots in the table before this scanning cost becomes too high.

Could Go choose another limit? Yes.

  • A lower limit would use more memory but usually shorten the probe sequence.
  • A higher limit would leave less unused memory but usually lengthen the probe sequence.

Go currently uses the same 7 / 8 limit as Abseil’s Swiss Table .

The split group layout

#

There is one more map change worth discussing. Go 1.27 includes an experimental group layout named mapsplitgroup , which we can enable with GOEXPERIMENT=mapsplitgroup .

Despite the name, this experiment does not change the map algorithm, the hash split, or the probe sequence. It only changes how one group arranges its 8 keys and values in memory.

By default, Go 1.27 stores each key beside its value:

control:  42     17     -      -
slots:    dog:1  cat:2  empty  empty

The internal layout is approximately:

slots [8]struct {
	key   string
	value int
}

The experimental layout separates the keys from the values:

control:  42     17     -      -
keys:     dog    cat    empty  empty
values:   1      2

Its internal layout is approximately:

keys   [8]string
values [8]int

The 2 arrays still describe the same entries. At index 1, keys[1] stores "cat" , and values[1] stores 2 .

Let’s look up "cat" . Its control byte identifies index 1 as a candidate, so Go reads keys[1] and compares it with "cat" . But do we need values[1] at this point? No:

Lookup reads keys[1] before values[1].

Lookup reads keys[1] before values[1].

Go reads values[1] only after the key matches. This is why the new layout keeps the keys together. During the search, Go reads candidate keys, while the values become useful only after one key matches. The values no longer sit between those key reads.

The split layout can also use less memory. Consider map[int64]struct{} , a map often used as a set. Each key needs 8 bytes, and the empty value stores no data. But the old layout still uses 16 bytes for every {key, value} slot because the empty value at the end adds 8 bytes of padding.

The control word is unchanged, so we only need to compare the storage below it:

The old layout uses 128 bytes below the control word.

The old layout uses 128 bytes below the control word.

The old slot layout uses 128 bytes across 8 slots. The 8 keys use 64 bytes, but each slot also contains 8 bytes of padding, adding another 64 bytes.

The split layout keeps all 8 keys together instead:

The split layout uses 72 bytes below the control word.

The split layout uses 72 bytes below the control word.

The 8 keys still use 64 bytes. The empty value array adds no element data, but Go adds one 8-byte trailing padding area after it. The storage below the control word therefore uses 72 bytes in total, saving 56 bytes in one group.

Go introduced this layout behind GOEXPERIMENT=mapsplitgroup in CL 711560 , then enabled it by default on the development branch in CL 820500 .

Resources

#

Who We Are

#

We’re VictoriaMetrics, a team providing open-source, highly scalable, and cost-efficient solutions for monitoring, logging, and tracing, trusted by users worldwide to reduce their observability costs. Check out our VictoriaMetrics , VictoriaLogs , and VictoriaTraces for more details.

WASM_OS, an operating-system experiment that runs inside a browser tab

Hacker News
wasmos-production.up.railway.app
2026-09-03 06:36:09
Comments...

Gloria Steinem has died

Hacker News
www.theguardian.com
2026-09-03 06:31:18
Comments...
Original Article

Gloria Steinem, the American feminist and journalist whose activism helped push through greater rights for women around the world has died, aged 92.

Steinem “passed away peacefully at her home in New York City, surrounded by some of the many who loved her”, a statement shared to her Instagram page said.

“Gloria’s near-century on earth were years well-lived, and she continued working for equality until the very end,” the post added. “Gloria’s greatest gift was her ability to listen to others, to make others feel seen and heard. Her words, actions, and example gave people permission to be their truest selves.”

Steinem brought a feminist perspective into the mainstream through rigorous journalism, public speaking and activism. The author of nine books, she campaigned against domestic violence, female genital mutilation, the pornography industry and the Vietnam and Gulf wars. She also worked in support of causes including Black Lives Matter, the reunification of Korea, female reproductive rights, LGBTQ+ rights and the Times Up movement. In 1984, she was arrested while protesting against apartheid outside the South African embassy in Washington DC.

Outside Steinem’s elegant, classic townhouse in Manhattan’s Upper East Side neighbourhood on Thursday morning, passersby left tributes.

Debbie Goldberg, who said she lived close by, placed a bunch of red flowers next to the steps up to the front door.

“I’ve never done that before. But she deserved it,” she said, describing Steinem as one of the most influential people for women’s rights and human rights in history.

“She’s a hero to all women whether they know it or not,” she said.

Goldberg said that she saw Steinem speak in Washington DC “around 30 years ago”, and then bumped into her as they were both heading into a cinema a few blocks away to see the Barbie movie in 2023. Goldberg said had been planning to watch Steinem speak in a few weeks’ time at a YMCA close by. “She’s always been an idol of mine,” Goldberg added.

Others left a bouquet of roses mixed with a variety of blooms in pink and white, and a large seashell filled with gems and other trinkets.

Born in Ohio in 1934, Steinem grew up in a trailer home. Her mother’s mental illness left her struggling to hold on to work and in and out of sanatoriums. When she was 10, her parents separated and, while growing up in a rundown home in Toledo with her mother, Steinem began to notice the hostility her mother endured as a working woman.

After graduating from a women’s liberal arts college in 1956, Steinem travelled to India for two years, where she worked as a legal clerk in the country’s supreme court. Returning to the US, she worked as the director of the Independent Research Service, a CIA front that recruited American students to disrupt the Soviet-controlled World Youth Festivals in Vienna and Helsinki. Steinem later revealed she had always known who was bankrolling the operation: “If I had a choice I would do it again.”

In 1962, she received her first “serious assignment” in journalism from the Esquire magazine editor, Clay Felker. Her feature on contraception, The Moral Disarmament of Betty Coed , detailed how women were forced to choose between careers and family. The following year, Steinem went undercover as a Playboy Bunny for 11 days, to write her infamous, two-part exposé of how the glamour models were treated while working in Hugh Hefner’s Playboy Club. Forced into tight costumes and high heels, Steinem lost 10lb – half of them in a single night – during her stint; her manager celebrated by making her costume two inches tighter. Following the article, she was unable to get work because “because I had now become a Bunny – and it didn’t matter why”.

Steinem in 1977.
Steinem in 1977. Photograph: Everett/Rex/Shutterstock

In 1968, Felker hired her to work at New York magazine, in which she would coin the term “reproductive freedom” for an article about an abortion “speakout” in Greenwich Village. Having had an abortion in London when was 22, she later described feeling a “big click” while at the protest and said the day marked the start of her life as an “active feminist”.

“I think the person who said: ‘Honey, if men could get pregnant, abortion would be a sacrament’ was right,” she told the Observer in 2011. “Speaking for myself, I knew it was the first time I had taken responsibility for my own life. I wasn’t going to let things happen to me. I was going to direct my life, and therefore it felt positive.”

She also credited black feminists including Florynce Kennedy, Evelyn Cunningham, Shirley Chisholm and Fannie Lou Hamer for teaching her the importance of activism. “It was like finding a family,” she said of that time . “As wildly different as we may be, and we certainly were, women share hopes and a certain vision of the world, and a certain shit detector.”

This also began Steinem’s career as a provocative journalist, penning articles including If Men Could Menstruate , which ran in Ms, a magazine co-founded by Steinem and Dorothy Pitman Hughes in 1971. The first issue featured Wonder Woman on the cover; the superhero had recently given up her powers to stay with her male love interest, and the essay argued that DC Comics should restore her powers and return the character to her feminist roots. Steinem also wrote articles such as What It Would Be Like If Women Win in Time, and After Black Power, Women’s Liberation , the 1969 New York magazine article that would make her name as a feminist leader.

Gloria Steinem (L) and author Dorothy Pitman Hughes
Steinem, left, and author Dorothy Pitman Hughes attend the Ms Foundation for Women Gloria Awards Gala in New York City, 2016. Photograph: Monica Schipper/Getty Images

Terrified of public speaking and conflict, but media savvy, Steinem used the platform she gained as a white, educated woman to speak out for those traditionally ignored – black people, ethnic minorities and the working class. Sex and race were always intertwined, she argued in 1971, “because they are easy, and visible differences have been the primary ways of organising human beings into superior and inferior groups and into the cheap labour on which this system still depends.” In 2017 , she said: “It doesn’t surprise me that the most virulent anti-abortion measures are coming from Alabama and other southern states because racism and sexism are always intertwined. You can’t perpetuate racism without controlling women and reproduction.”

Steinem was also a polarising figure. Some feminists felt her position as a public leader in the movement had been decided not by merit but by the media, which chose her for being young, white and attractive; in her 2015 book My Life on the Road, she wrote that the “idea that whatever I had accomplished was all about looks would remain a biased and hurtful accusation even into my old age”.

She was roundly criticised for decades for a 1998 opinion piece for the New York Times , in which she supported President Bill Clinton in the face of sexual harassment allegations. “He is not guilty of sexual harassment,” she wrote, only “a gross, dumb, and reckless pass at a supporter during a low point in her life”. In 2017, she said : “We have to believe women. I wouldn’t write the same thing now because there’s probably more known about other women now.” She was also regarded as hostile to transgender rights because of a piece she wrote in 1977, a position she clarified in 2013 : “I believe that transgender people, including those who have transitioned, are living out real, authentic lives. Those lives should be celebrated, not questioned.”

In 1986, Steinem was diagnosed with breast cancer, then in 1994 the chronic pain condition trigeminal neuralgia. After years of dismissing marriage, she married the environmental activist David Bale in 2000, and remained close with her stepson, the actor Christian Bale, after his father’s death in 2003.

Having supported Hillary Clinton’s presidential campaign, Steinem was a prominent critic of Donald Trump, co-chairing and speaking at the Women’s March on Washington, a mass protest held the day after the Trump’s inauguration in January 2017. “The only good news of Trump is that the galvanising of activism is like nothing I have ever seen in my life,” she told the Guardian that year. “A thousand times more even than the Vietnam war, and how important that was – or of any other thing I’ve ever seen.”

In 2011, she told the Observer: “I hope to live to 100. There is so much to do.”

Anna Betts contributed reporting from New York

jujutsu 0.45.0

Lobsters
github.com
2026-09-03 06:02:34
Comments...
Original Article

About

jj is a Git-compatible version control system that is both simple and powerful. See
the installation instructions to get started.

Release highlights

  • A new jj converge command was added to help automatically resolve divergent
    commits by combining them appropriately.

Breaking changes

  • jj config {edit,set,unset} --user now targets the first loaded user
    configuration file (e.g. ~/.config/jj/config.toml or the first file in
    conf.d/ ) instead of prompting interactively when multiple files exist.
    Use --file <PATH> to target a specific config file.

  • jj git import in non-colocated repositories no longer imports commits from a
    detached Git HEAD branch.

Deprecations

None

New features

  • The new jj converge command attempts to automatically resolve divergence by
    creating a new commit that replaces the divergent commits. It applies
    heuristics to try to automatically come up with a good solution, and falls
    back to prompting the user if the heuristics are inconclusive. It can also run
    in non-interactive mode, which aborts if prompting would be needed.

  • jj bisect will now mention when it cannot unambiguously find the first bad
    revision due to skips in evaluation.

  • Git HEAD state is now tracked per worktree internally. This prepares
    colocated repositories for support of multiple Git worktrees, where each
    jj workspace can have its own Git HEAD. Existing repositories are migrated
    automatically.

  • jj config {edit,set,unset} now support a --file <PATH> option to
    target a specific configuration file (such as files inside a conf.d/
    directory or loaded via --config-file ). This allows precise file targeting
    and avoids interactive prompts when multiple config files exist.

Fixed bugs

  • The default immutable_heads() set
    now includes untracked_remote_tags() .

  • jj arrange now scrolls the viewport to keep the selected commit visible
    when the commit stack is taller than the terminal.
    #9033 .

  • The default pager flags now include -K ( --quit-on-intr ), so pressing
    Ctrl+C in less exits cleanly instead of leaving the terminal in a
    corrupted state (raw mode, visible escape sequences, broken input).

  • A side of a conflict whose contents end with a carriage return no longer loses
    that byte when the materialized conflict is parsed back, such as when a
    conflicted file is snapshotted from the working copy.
    #9868

  • In colocated workspaces, jj workspace update-stale now correctly resets the
    Git HEAD to the parent of the fresh working-copy commit.
    #9936

  • jj run no longer runs against the remaining revisions if a process exits
    with a nonzero exit code.

  • Fixed crash in jj log involving hidden revisions and the
    log-graph-prioritize revset.
    #9975

  • In colocated repos, an external git add after a jj command no longer
    produces a tree with duplicate entries ( git fsck: duplicateEntries ). jj
    was leaving a stale cache-tree behind in .git/index . Repositories already
    corrupted this way are not repaired by the fix.
    #9711
    #8884

Contributors

Thanks to the people who made this release happen!

“Board of Peace” Billionaire Backs AIPAC Fund Targeting Pro-Palestine Candidates

Intercept
theintercept.com
2026-09-03 06:00:00
Marc Rowan, a Trump appointee overseeing Gaza’s redevelopment, has given $1.5 million to AIPAC’s super PAC this cycle. The post “Board of Peace” Billionaire Backs AIPAC Fund Targeting Pro-Palestine Candidates appeared first on The Intercept....
Original Article

Marc Rowan has a vision for Gaza. “The potential here is tremendous,” he said at a February gathering of President Donald Trump’s so-called Board of Peace, where Rowan described land devastated by Israeli bombing with a developer’s zeal. “This is not a problem of money or collateral. This is a problem with peace.”

In the U.S., Rowan is simultaneously helping ensure a pro-Israel political project has no problem with money. Since the start of this year, according to Federal Election Commission filings, the billionaire CEO of Apollo Global Management has donated $1.5 million to the United Democracy Project, a super PAC for the American Israel Public Affairs Committee, spending a fraction of his vast wealth to preserve a foreign policy defined by support for Israel’s genocide and the flow of U.S. weapons to Israel.

“Palestinians did not choose him, and neither did American voters.”

Rowan — who is worth more than $8 billion and reportedly consulted on his business with convicted sex offender and disgraced financier Jeffrey Epstein — is an executive member of Trump’s “Board of Peace,” a United Nations-approved body tasked with carrying out Trump’s stalled plan for Gaza. He made his first donation to UDP of the year in early March, giving $1 million, filings show, just as the group began spending aggressively against the now-ousted Rep. Thomas Massie, R-Ky., a loud critic of U.S. support for Israel .

A second donation for $500,000 arrived on July 23. The same day, the AIPAC super PAC shelled out nearly $50,000 in campaign mailers in Michigan to attack the progressive pro-Palestine candidate for U.S. Senate, Abdul El-Sayed. In Missouri, it dropped another $100,000 for phone banking services against former Democratic Rep. Cori Bush in her race against pro-Israel incumbent Rep. Wesley Bell.

It’s not clear which specific UDP efforts have been backed by Rowan’s largesse, and neither Rowan nor UDP responded to requests for comment. But Raed Jarrar, advocacy director with Democracy for the Arab World Now , connected Rowan’s position on Trump’s Gaza board and his major part as a donor to AIPAC’s super PAC as a matter of transparency.

“Now he sits on a board that will decide Gaza’s future,” Jarrar told The Intercept. “Palestinians did not choose him, and neither did American voters. Americans and Palestinians alike deserve to know whose interests are actually being served.”

Rowan, a major donor to Trump’s failed 2020 presidential campaign, has long made his animus toward critics of Israel known. In recent years, he has been a fierce advocate against student protesters calling for an end to the genocide in Gaza, broadly mischaracterizing their anti-genocide calls as “antisemitic,” and played a key role in ousting leaders at his alma mater , the University of Pennsylvania, over their handling of the protests. In 2025, he served as a consultant to the White House in its recent attacks on higher education . He donated an initial $250,000 to UDP in 2022, the year the AIPAC super PAC was founded, and more than quadrupled his giving by 2024. Trump appointed him to the Board of Peace this past January.

“Marc Rowan has used his position to try to silence Palestinians and smear students protesting Israel’s genocide,” said Margaret DeReus, executive director of Peace, Accountability, and Leadership PAC, which launched this cycle as a pro-Palestine counterweight to the pro-Israel lobby. PAL PAC backed both El-Sayed and Bush, who have committed to cutting military aid to Israel. (El-Sayed prevailed in his Democratic Senate primary against Michigan Rep. Haley Stevens, while both Bush and Massie lost their races.)

Rowan “gives millions to fund the now-fringe idea that billions of our tax dollars should fund the Israeli military and targets candidates who are calling to stop sending U.S. tax dollars to Israel’s genocide,” DeReus said. She added that his presence on “Trump’s corrupt board” lays bare the actual goal of the governing body: “the continued genocide and ethnic cleansing of the Palestinians living in Gaza.”

As support for Israel among the American people has plummeted, and more leftist candidates run on promises to enact an arms embargo on Israel, AIPAC has broken its own spending records and set new ones, helping make El-Sayed and Massie’s primaries among the most expensive ever. In Congress, the lobbying giant has also worked to consolidate power among its pro-Israel base. In July, AIPAC lobbied members for the passage of a Pentagon program that further enmeshes military technological sharing between the U.S. and Israeli militaries . Last week, Democratic leadership appointed three hawkish, pro-Israel, and AIPAC-backed Democrats to the House Foreign Affairs Committee.

In addition to his AIPAC super PAC spending, Rowan has also directly given to a host of pro-Israel candidates this cycle, including New Jersey Democrats Rep. Josh Gottheimer and Sen. Cory Booker, as well as Minnesota Rep. Angie Craig in her failed Senate bid.

The majority of Rowan’s spending, however, has been in favor of Republicans, including Mike Rogers, who is facing off against El-Sayed; Florida Sen. Ashley Moody, a vocal opponent of the Boycott, Divestment, Sanctions movement; and Rep. Brian Mast , R-Fla., chair of the House Foreign Affairs Committee and former Israeli Defense Forces volunteer who famously wore his IDF uniform to Congress.

AIPAC has long championed Trump’s plan for Gaza , which has included overt calls to displace Palestinians, and supports Israel’s hard line in its negotiations with Hamas leaders. Israel, which occupies nearly 70 percent of Gaza, has refused to withdraw its military from the Strip. Israel blames Hamas for refusing to disarm, though the Palestinian militant and political group has said it would only surrender its weapons in exchange for a full Israeli withdrawal and the establishment of a Palestinian state — conditions the Israeli government has refused.

AIPAC also regularly celebrates the ongoing bombardment of the Strip, where more than 1,000 Palestinians have been killed in Israeli strikes since the so-called ceasefire was brokered, including this week when bombing killed two children.

In Rowan’s view, there’s money to be made from the carnage. At the meeting in Washington, D.C., this past February — when Trump also pledged $10 billion in public funds to the board — Rowan fired off property value estimates in Gaza, more than 80 percent of which lies in ruins . He cited a coastline valued at $50 billion; a housing stock, if rebuilt, worth $30 billion; and infrastructure projects worth another $30 billion. Rowan spoke next to generic renderings of glistening high-rise apartments, palm tree-laden highways, solar power plants, and coastal oil depots. Consolidating all of these assets under the supervision of Trump’s Board of Peace, Rowan said, would allow for “conflict-free management of the resources to benefit the Gazans.”

“One hundred fifteen billion of value,” he promised . “It just needs to be unlocked and financed.”

The Browser's Main Thread Is Expensive

Lobsters
kciter.so
2026-09-03 05:51:30
Comments...
Original Article

What comes to mind when you hear “frontend optimization”? For most of us it’s things like reducing network requests, shrinking the bundle, or making good use of the cache. Beyond that, maybe cutting down on re-renders or tuning when resources get loaded. The main thread doesn’t usually come up, and there’s a reason for that: on most screens it never becomes a problem. But on screens with a lot of interaction, where data streams in live and scrolling, animation, and input all get tangled together, the picture changes. However much you save on network and bundle size, the screen freezes the moment the main thread gets blocked.

You’ve probably come across a website where scrolling stutters now and then, a button responds slightly late, or the letters you type into a search box show up half a beat behind. It isn’t bad enough to be annoying, but it gets on your nerves in a subtle way. That kind of jank is what a blocked main thread looks like.

When we run into jank like this as developers, the usual reaction is to wonder “is my code slow?” and start picking apart algorithms or looking for wasted computation. In most cases, though, the speed of the code is not the problem. The code isn’t slow. It just happens to be the code that’s holding the main thread.

The browser has a number of threads, but almost everything we can touch from code is concentrated on the main thread. Computation, rendering, event handling, network response handling, and your framework’s internals are all processed there. One resource, a mountain of work.

The browser’s main thread is expensive. Most of the time it doesn’t cause trouble, but once you try to do something ambitious, dealing with the main thread becomes the important part. This article is about how to handle that expensive resource.

What Does the Main Thread Do?

Let’s start with what the main thread actually does. Its work falls into two broad categories.

The first is running JavaScript . The code we write, along with event handlers, timers, network response callbacks, and the framework’s internals, all run here. These tasks execute in the order they enter the queue, whenever there is a gap, with no relation to the screen refresh cycle.

The second is drawing the screen . When the DOM or styles change and the screen needs updating, the browser goes through roughly these steps, in order, to produce a frame.

  • Run requestAnimationFrame callbacks - JavaScript registered to run just before the frame is drawn
  • Style calculation - compute the final CSS values for each element
  • Layout - compute each element’s position and size (also called reflow)
  • Paint - generate paint commands describing what to draw in which colors

If nothing changed, these steps are skipped entirely, so they don’t necessarily run every frame. Only the final compositing step, which takes the produced output and assembles it on screen, is handed off to the compositor thread 1 . In other words, most of the front half of the pipeline that draws the screen is the main thread’s responsibility.

The rendering pipeline for updating the screen

For the screen to look smooth, frames have to be drawn at the display’s refresh rate. On the most common 60Hz display, that means 60 frames per second, or about 16.6 milliseconds per frame. And you don’t get to use all of it. Once the browser’s own processing cost is subtracted, the practical budget is usually considered to be around 10 milliseconds 2 , and on a 120Hz device the budget itself is cut in half.

The problem is that the two kinds of work above stand in a single line on the same thread . JavaScript was designed around a single-threaded event loop model. The main thread processes one task at a time, and while that task is running, nothing else can happen. If one JavaScript function runs for 200 milliseconds, then for those 200 milliseconds the browser can’t repaint the screen or receive a click from the user. Against a frame budget of around 10 milliseconds, that is a fatal amount of time. A task that runs this long and holds the main thread is called a long task, and anything over 50 milliseconds is generally considered a problem.

Words only go so far, so let’s feel it. In the demo below, pressing the button makes JavaScript grab the main thread for a moment.

JS animation

Main thread · rAF

CSS animation

Compositor · transform

Press a button: the JS animation and typing freeze, but the CSS animation keeps spinning

When you press the button, the JS animation stops and typing into the input field does nothing. The CSS animation, on the other hand, keeps running. We’ll come back to where that difference comes from later. What to remember for now is that holding the main thread for a long time is the same thing as freezing the screen.

This connects directly to web performance metrics. INP (Interaction to Next Paint), which measures how long it takes for the screen to respond after the user does something, and TBT (Total Blocking Time), which measures the total time the main thread was blocked during page load, are both essentially ways of expressing how long the main thread was blocked. A large part of performance optimization is a matter of how carefully you spend this one thread.

The ways of spending it carefully fall into two broad families. One is to divide the main thread’s time well from within. The other is to send the work outside the main thread altogether. Let’s take them in order.

Using the Expensive Resource Wisely

The first family is about staying on the main thread but spending its time intelligently . There are four core moves.

  • How do you split up work that runs too long?
  • How do you group work that runs too often?
  • Among several tasks, which goes first?
  • How do you postpone work that doesn’t need to happen now?

We’ll call these splitting, batching, prioritizing, and deferring. The first two shape the size of tasks, and the last two decide their timing . Of the four, splitting is the foundation for the rest. Tasks need boundaries before you can decide what to slot in between them and what to push back. So we start with splitting.

Splitting

Picture the chat pane of a live stream. On a popular stream, chat can burst to hundreds of messages per second. In that environment, messages don’t arrive politely one at a time. When traffic spikes, the server sends them in clumps of dozens, and the moment you enter a room, hundreds of backlogged messages come down at once. What happens if you render that whole clump in one go right when it arrives? Every message you draw brings DOM creation, style calculation, layout, and paint along with it, and those hundreds of iterations run back to back inside a single task. Meanwhile, the user trying to type their own message gets a stuttering input field, and every other animation on screen hitches too. Other people’s chat is monopolizing the main thread and getting in the way of yours.

The fix is what we said above. Cut the clump into small pieces, and between the pieces, hand control of the main thread back for a moment. In those gaps the browser can catch up on the screen updates and input handling it had queued.

The demo below simulates a streaming chat pane. Press “Flood the chat” and messages start pouring in. Try typing in the input field while watching the smoothness gauge and fps at the top, and compare the “Immediate render” and “Yielding render” modes.

Smoothness indicator (JS animation) 60 fps

In “Immediate render” mode, the DOM is touched as each message arrives, so while chat is flooding in, fps drops sharply, the gauge stutters, and the input field lags. If you look closely, the chat messages themselves start appearing noticeably more slowly as well, because the callback that receives and processes them is also a task waiting in the main thread’s line, so it gets delayed with everything else. Now switch to “Yielding render”. Messages are still drawn one at a time, just as before, yet input comes back to life and the screen moves again. The only thing that changed is that after every 20 messages, the main thread is released for a moment.

One thing not to misread here is that yielding does not make the work faster. The total amount of work is unchanged, and the few milliseconds spent waiting at each yield are added overhead, so in wall-clock terms it actually takes longer. So why did rendering recover along with input?

As we saw earlier, the main thread can do nothing while a task is running. The rendering pipeline that produces frames can’t cut into the middle of a task either. It can only run between tasks . Yielding is the act of creating those gaps. The backlogged input and frame production get their turn in the gaps, and to the user it feels as though performance improved.

At the code level, the classic way to yield is setTimeout , which pushes the continuation into the next task. Take a look at the following code.

// A batch of chat messages arrives at once
socket.on('messages', (chats) => {
  renderChats(chats);
});

// Draw the messages, yielding the main thread after every 20
async function renderChats(chats) {
  let count = 0;
  for (const chat of chats) {
    appendChatNode(chat); // draw one message

    if (++count % 20 === 0) {
      await new Promise((resolve) => setTimeout(resolve, 0)); // yield here
    }
  }
}

With this in place, no matter how hard chat floods in, the DOM work never occupies the main thread in one piece, and between the pieces there is room for the user’s input and animations to be processed.

The star of this code is setTimeout . When it schedules the resumption of the remaining work as a new task, the current task ends right there, and in that gap the backlogged input and rendering get processed. await pauses the function until the scheduled task comes back around, then picks up where it left off.

How yielding changes the timeline

The example above split the incoming work by count . But if an animation is already running, or the user is in the middle of scrolling, splitting by time is safer than splitting by count. An animation uses a little of the main thread every frame, so a heavy job has to keep checking the clock and cut itself off before it swallows what’s left of the frame’s budget.

async function processDuringAnimation(items) {
  let i = 0;
  let frameStart = performance.now();
  while (i < items.length) {
    // Work only until 5ms have passed since the frame started
    while (i < items.length && performance.now() - frameStart < 5) {
      doWork(items[i++]);
    }
    frameStart = await new Promise(requestAnimationFrame); // resume with the next frame's start time
  }
}

Here performance.now() acts as the stopwatch that checks whether we’ve gone over budget, and requestAnimationFrame acts as the alarm that says “wake me just before the next frame is drawn.” This is also why we yield with rAF rather than setTimeout when splitting by time. The resumption lands in step with the frame cycle.

Note that rAF passes the frame’s start timestamp to its callback, and the code above uses that as the reference point for the budget. The reason is that the function doesn’t have the frame to itself. If other animation callbacks ran earlier in the same frame, our share has to shrink by however much time they used, or the frame budget is broken. Anchoring to the frame’s start time turns “use 5ms” into “use until 5ms after the frame started,” which makes the code cooperate naturally when several animations share one frame.

Why 5 milliseconds? There’s nothing special about the number. We said the practical budget is around 10 milliseconds, so handing roughly half to background work and leaving the rest for animation callbacks, style, layout, and paint is a reasonable heuristic. If your animations are heavy, shrink it.

With this approach, even while heavy work is in progress, there is room to draw the screen every frame, and the work and the animation run smoothly side by side. Try the demo below. Moving the mouse scatters 4,000 particles away from the cursor, and nearby particles also push each other apart, so deciding one particle’s direction means checking its distance to every other particle. That comes to roughly 16 million distance calculations per pass, and recomputing all of it every frame blows through the frame budget on its own. Compare the “Compute all at once” and “5ms per frame” modes.

4,000 particles · steering cost this frame 0.0ms 60 fps

Move your mouse or finger here and the particles scatter away from the cursor

Splitting is the most basic way to use the main thread’s time sparingly. It is what gives users the perceived performance they care about: fast responses and a smooth screen.

Finally, a few points to be careful about. First, splitting too finely backfires. Yielding and coming back has a cost of its own, so if the pieces are too small, that overhead can end up larger than the work you’re trying to do.

Second, yielding with setTimeout involves a minimum delay 3 , so each piece can end up waiting a few milliseconds for nothing. Usually this doesn’t matter, but in situations that demand a very high level of responsiveness, the delay can become a problem.

That’s why some code schedules the next task by posting a message through a MessageChannel instead. React’s scheduler uses this method. More recently, a standard API called scheduler.yield() has also appeared to address this problem. Its advantage is that after yielding, the original work resumes ahead of other queued tasks instead of being pushed to the back. Browser support is still uneven, though.

Third, different yielding tools come back at different times. setTimeout and scheduler.yield() resume without regard to the rendering cycle, while requestAnimationFrame resumes just before a frame is drawn, so for work that needs to keep in rhythm with screen updates, requestAnimationFrame is the better fit. If you want finer control over priorities, you can also build your own queue on MessageChannel and manage the yielding and resuming yourself.

Lastly, splitting isn’t always possible. Parsing a multi-megabyte response with JSON.parse , for example, is a single atomic synchronous call, and there is no way to stop halfway and yield. Until the parse finishes, the main thread is stuck. Heavy work that can’t be split like this is the clear limit of “using it wisely.” In that case you have to change the premise and not do the work on the main thread at all. We’ll get to that in “Not Using the Expensive Resource.”

Batching

Splitting on its own doesn’t solve every problem, though. Think back to the streaming chat example. Yielding rescued input and rendering, but it did nothing to make chat draw faster. If anything, throughput, meaning the number of messages drawn per unit of time, went down by the overhead of yielding. So what happens if chat pours in faster than the throughput? Arrivals outpace processing, the backlog keeps growing, and the messages reaching the screen get older and older. This situation is called backpressure .

Raising throughput takes a different tool than splitting. For example, instead of drawing messages one by one, you can draw the accumulated batch in one go. The fixed per-message cost folds together, and the same amount of time renders more chat. Being told to split and then told to batch may sound like a contradiction, but the point of both is to trim tasks to an appropriate size. Splitting deals with tasks so long that rendering can’t squeeze in, and batching deals with tasks so frequent that the pipeline’s fixed cost is paid over and over.

The best batching targets are events. Scroll, resize, and input events can fire dozens or hundreds of times in a short span. If you run a heavy handler on every one of them, there’s nothing left of the main thread. So we collapse many events into one execution, either by “running once after things quiet down” or by “running at most once per interval.” These are called debounce and throttle, respectively.

The demo below is a markdown editor with a long CHANGELOG open. Building the preview means parsing the entire document (about 2,000 lines) and rebuilding its DOM from scratch, which is far too expensive to run on every keystroke. Type quickly into the left editor with “No debounce” selected. The preview is rebuilt once per character and your input falls behind. Switch to “Debounce 300ms” and the render happens just once, after you stop typing, and the typing becomes smooth.

A ~2,000-line CHANGELOG.md 60 fps

For visual updates, you can use requestAnimationFrame . The screen only gets drawn once per frame anyway, so no matter how many update requests pile up, drawing once per frame is enough.

let scheduled = false;

socket.on('tick', (tick) => {
  chart.push(tick); // keep every data point — nothing is thrown away
  if (scheduled) return; // this frame's draw is already booked
  scheduled = true;
  requestAnimationFrame(() => {
    renderBoard(); // draw once per frame
    scheduled = false;
  });
});

The demo below updates a board of 60 tickers with over 1,000 messages per second. “Render every tick” mode redraws the whole board on every message. Calling a chart library’s update() on every message is a common mistake, and this is exactly what it looks like. Switch to “Once per frame” and every arriving data point is still reflected, but the fps comes back.

Smoothness meter (JS animation) 60 fps

DOM writes can be batched as well. Appending a hundred nodes in one operation instead of one at a time, or toggling a single class instead of changing style properties individually, turns many changes into one and helps performance. The old technique of assembling an HTML string and assigning it to innerHTML in one shot has the same essence. You gather the writes so the rendering pipeline’s fixed cost is paid once.

This kind of optimization is a familiar pattern to frontend developers, and React’s virtual DOM is itself a device for it. However many times state changes, the changes accumulate in the virtual tree, get compared first, and only the actual differences are applied to the real DOM in one pass. Merging several state updates inside one event handler into a single re-render, or queueing analytics events and sending them in one request instead of individually, is the same idea. A fixed cost that would repeat once per item gets paid once per batch.

Prioritizing

If splitting and batching shape the size of work, prioritizing decides its order. Reacting to the button the user just pressed needs to happen quickly, while precomputing statistics for content that’s off screen can wait. Prioritizing means ordering the urgent work ahead of the work that isn’t urgent.

Order matters because on a main thread that nothing can interrupt, order is the responsiveness the user feels. To control order, you usually build a queue that work is pushed into and pulled out of. Jobs in the queue are processed FIFO, but when something urgent comes in, it gets pulled to the front of the line.

const queue = [];
const channel = new MessageChannel();

// One message = one task. Process a piece, then book the next one
channel.port1.onmessage = () => {
  const job = queue.shift(); // take whatever is at the front right now
  if (!job) return; // guard against duplicate bookings
  job();
  if (queue.length > 0) channel.port2.postMessage(null);
};

function postJob(job, urgent = false) {
  if (urgent) queue.unshift(job); // urgent jobs cut to the front
  else queue.push(job);
  if (queue.length === 1) channel.port2.postMessage(null);
}

This structure is useful because priority isn’t a fixed value. Work that wasn’t urgent to begin with can suddenly become urgent because of something the user does. Say the user attaches a few dozen photos to a post. To save on costs, the client sometimes resizes images before uploading them to the server, and that resizing is unhurried work that can be processed in order.

React works along similar lines, with more sophisticated machinery on top, such as starvation protection, batching, and continuations. Use startTransition or useDeferredValue and a scheduler spins up inside that yields via MessageChannel and orders work with its own priority queue.

But once the user clicks a particular photo to check that it attached properly, that photo’s preview becomes the most urgent job there is. With a priority queue like the one above, the urgent job can be handled first. This approach, where you get ahead on the work while idle and then rush it when it becomes needed, is sometimes called the idle-until-urgent pattern 4 .

// Build previews for the attached photos, in order
files.forEach((file, i) => {
  const job = () => createPreview(file, i);
  job.photoId = i; // tag it so we can find it in the queue later
  postJob(job);
});

// Clicking a photo that isn't ready pulls its job to the front → priority bump
onClickPhoto((i) => {
  const idx = queue.findIndex((job) => job.photoId === i);
  if (idx > 0) queue.unshift(queue.splice(idx, 1)[0]);
});

Feel the difference in the demo below. Sixty photos have been attached, and each preview is actually generated with per-pixel filtering. While the previews are being built in order, click one of the gray tiles that isn’t ready yet. In “In order” mode you have to wait until that tile’s turn comes, but in “Clicked first” mode it skips the queue and fills in right away. The total amount of work is the same and only the order changed, yet the experience for the user is completely different.

Building previews for the 60 attached photos, one at a time

Priority, then, is a matter of working out what matters most to the user at this particular moment.

Modern browsers offer standards for this, such as the Scheduler API and TaskController. Support is still incomplete, so in practice people pair them with polyfills or build their own queues. This article uses the hand-built-queue approach.

Deferring

The last and most reliable way to conserve the main thread is to not do now what doesn’t need to be done now. Where splitting and batching ask “at what size” and prioritizing asks “in what order,” deferring asks whether this work really has to happen right now at all.

Initial page load is the classic place where deferring pays off. There’s no need to download and execute all of your JavaScript up front. With code splitting, only the code the current screen needs runs first, and the rest is loaded when it becomes necessary, which keeps the main thread from slowing down right from the start.

You can defer rendering itself, too. Think of a social feed. Some apps freeze for a moment when you come back from the notifications tab after scrolling far enough to accumulate hundreds of posts. Even if the feed’s DOM is kept alive while switching tabs, when it becomes visible again the browser recomputes style and layout for all several hundred posts at once, including the ones nowhere near the viewport. So what if off-screen posts were left as empty shells that only take up their height, and got filled with real content as they approach the screen? The tool that tells you about that “approaching” moment is IntersectionObserver . It’s the same method image lazy-loading libraries use.

const io = new IntersectionObserver(
  (entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) fill(entry.target); // fill as it approaches
      else empty(entry.target); // empty it when it leaves, keeping its place
    }
  },
  { rootMargin: '400px' } // headroom to fill before the scroll arrives
);

feed.querySelectorAll('.feed-item').forEach((el) => io.observe(el));

The demo below is a feed with 1,500 posts piled up 5 . It starts with “Render only when visible” turned on. Visit the notifications tab and come back, and the return is instant regardless of how much has accumulated. Now switch to “Render everything” and make the round trip again. Every return freezes for hundreds of milliseconds while all 1,500 posts are laid out again. Apart from unfilled slots showing briefly during fast scrolling, the two modes look the same.

A feed with 1,500 posts piled up — try visiting the notifications tab 60 fps

Time to get back to the feed

Render only when visible: IntersectionObserver fills only the posts near the viewport — returning is fast no matter how much has piled up

Rendering isn’t the only thing this approach defers. Off-screen posts never get their DOM built at all, so the cost of creating and maintaining it is deferred along with everything else. If a widget carries heavy initialization, that initialization can also wait until the widget nears the screen. There’s also a CSS property, content-visibility: auto , that aims for a similar effect in a single line. As of this writing, though, implementations vary between engines, and Safari has a performance bug that makes returning to the page slower rather than faster, so for now IntersectionObserver is the option that behaves predictably everywhere.

Continuously running work , like carousels, animated promo banners, and live charts, is pure waste while off screen. You’re spending main-thread time every frame to redraw a picture nobody can see. Run it while it’s visible and stop it when it leaves. That’s also how the dozen-plus demos in this article manage to coexist on a single page. Each one is built to stop once it scrolls out of view.

Not Using the Expensive Resource

Everything so far was about using the main thread, but using it carefully. The second family of techniques is about not doing the work on the main thread in the first place .

Let’s return to the question left hanging in the long-task demo. The main thread was completely blocked, so why did the CSS animation keep running as if nothing had happened? The answer is that the animation was never running on the main thread to begin with. Inside the browser, several threads divide up the work. These are the notable ones.

  • Main thread : runs JavaScript, manipulates the DOM, calculates styles, performs layout, handles events.
  • Compositor thread : composites already-drawn layers onto the screen. Handles scrolling and certain animations.
  • Raster threads : turn paint commands into actual pixels.
  • Worker threads : separate JavaScript execution spaces that we create explicitly.

Unfortunately, we can’t control these threads however we like. The compositor and raster threads are territory the browser manages on its own, so we can’t give them direct orders, and worker threads, which we can create, come with the major restriction of having no DOM access.

So “not using” the main thread doesn’t mean sending arbitrary work elsewhere. It means picking out the work that can take a form other threads can handle, and sending that . There are two main ways to do it.

Moving Work to the Compositor

The compositor thread is the reason the CSS animation didn’t stop. transform and opacity don’t change an element’s position, size, or color in the document. They move an already-painted layer or adjust its transparency, so there’s no need to redo layout or paint. That lets the browser handle them directly on the compositor thread without going through the main thread at all. Even when the main thread is busy, the compositor runs separately, so the animation stays smooth.

If you move an element with properties like top , left , width , or height instead, layout has to be recomputed every frame, and that is main-thread work. In the demo below, the two boxes slide side to side in the same way, but one moves with transform and the other with left . Press the button to put load on the main thread.

transform: translateX

· Compositor

left

· Main thread (triggers layout)

Once the main thread gets busy, only the bottom box, the one moving with left , starts to stutter. The transform box at the top is being driven by the compositor and stays smooth whatever the load. The same “slide sideways” ends up on a completely different thread depending on which property you animate. That’s why it’s better for performance to build animations that move things with transform: translate rather than left , and animations that resize things with transform: scale rather than width .

But what about animations where the layout genuinely has to change? Picture a list where deleting an item makes the items below it slide smoothly up into place. This isn’t decorative motion. The positions really do change. Yet animating top means layout on every frame. The technique that resolves this dilemma is FLIP (First, Last, Invert, Play) 6 . In short, you cause exactly one layout change and leave the entire movement to transform. It goes in this order.

  • First: measure the position before the move
  • Last: actually change the layout and measure the new position. Layout happens exactly once, here
  • Invert: apply a transform to the element in its new position so it appears to still be in the old one
  • Play: animate that transform away. This part belongs to the compositor
const first = el.getBoundingClientRect(); // First: where it is now

list.prepend(el); // the one and only layout change

const last = el.getBoundingClientRect(); // Last: where it ended up
const dx = first.left - last.left;
const dy = first.top - last.top;

// Invert: make it look like it's back at the old position → Play: release it
el.animate([{ transform: `translate(${dx}px, ${dy}px)` }, { transform: 'none' }], {
  duration: 300,
  easing: 'ease-in-out',
});

To the user’s eye, the element glides from its old spot to its new one, but in reality the element has already arrived at its new spot, and the transform briefly drags it back before releasing it into place. While the animation plays, the only per-frame work is the compositor interpolating a transform. Most list-reordering animations are built this way, and Vue’s TransitionGroup and Framer Motion’s layout animations are FLIP under the hood.

The demo below shows the difference at a glance. Press “Play rank shuffle” and both ranking lists reshuffle in the same way. The left list animates top with a transition, and the right list moves only transform , via FLIP. With no load, both look smooth. Now turn on “Load the main thread” and play it again. The left list stutters its way to the finish, while the right one stays smooth even under load.

The same rank shuffle plays in both modes at once

top transition

· main thread

1 Wireless earbuds

2 Camping chair

3 Running shoes

4 Dehumidifier

5 Standing desk

6 Protein shake

1 Wireless earbuds

2 Camping chair

3 Running shoes

4 Dehumidifier

5 Standing desk

6 Protein shake

Finally, two things worth knowing before handing work to the compositor. One is will-change: transform . It gives the browser a hint that “this element is about to change, so prepare it as its own layer in advance,” which can smooth out the start of an animation. Overuse it, though, and the number of layers balloons and memory gets wasted instead.

The other is reading layout values, which you just saw in the FLIP code. If you get the ordering wrong between code that reads layout values ( getBoundingClientRect , offsetWidth ) and code that writes styles, you run into a problem called layout thrashing.

// 🔴 Reads and writes interleaved — forces a layout recalculation every iteration
for (const el of elements) {
  const width = el.offsetWidth; // read (needs layout)
  el.style.width = width + 10 + 'px'; // write (invalidates layout)
}

// 🟢 Finish all the reads, then do the writes together
const widths = elements.map((el) => el.offsetWidth); // gather reads
elements.forEach((el, i) => {
  el.style.width = widths[i] + 10 + 'px'; // gather writes
});

If you read a layout value right after changing one, the browser has no choice but to recompute layout on the spot to give you an up-to-date answer. When that happens inside a loop, layout runs dozens of times in a single frame and the main thread slows down. Simply getting into the habit of grouping reads with reads and writes with writes is enough to avoid it.

Sending Work to a Worker

Then what about heavy work that can’t be re-expressed with transform ? What do you do with things like parsing a large payload, processing images, or running complex computation? Pure calculation like that can be sent outside the main thread in its entirety with a web worker.

A worker runs JavaScript on a separate thread, fully separated from the main one. Hand the heavy computation to a worker, and in the meantime the main thread can concentrate solely on keeping the UI responsive.

// Main thread
const worker = new Worker('parser.js');
worker.postMessage(hugeRawData);
worker.onmessage = (e) => {
  render(e.data); // receive only the result and put it on screen
};

It isn’t free, of course. As we saw above, workers can’t access the DOM, so they can’t touch the screen directly. They can only compute and then send the results back to the main thread. And the main thread and the worker communicate only through postMessage , which copies (serializes) the data, so when the data being passed around is large, that cost is considerable.

So workers aren’t a cure-all. They shine when the computation is heavy enough to outweigh the communication cost and has nothing to do with the DOM. If you send a short, light job to a worker, the communication cost ends up larger than the computation cost and you come out behind. The key is to keep asking, every time, whether this work really needs to run on the main thread.

Since words only go so far, let’s bring in some genuinely heavy image processing. Seam carving is an algorithm that finds the vertical path of lowest energy (least color change) through a photo and removes it one path at a time, narrowing the image while preserving the important subject 7 . Removing a single seam means sweeping through hundreds of thousands of pixels, so removing 250 or so seams adds up to hundreds of millions of operations. Run that on the main thread and the whole page will freeze. Send it to a worker, though, and the screen can stay responsive the entire time the computation is running.

Press “Run on main thread” in the demo below. For the one or two seconds the computation runs, the entire page freezes, and the result appears all at once only after it’s finished. Because there are no task boundaries for paint to slip into, you couldn’t show the intermediate steps even if you wanted to. Now switch to “Run in worker”. While the same computation runs, you get to watch the image narrow in real time.

Seam carving — shrink the photo's width by 30% while keeping the important subjects 60 fps

There is one more thing behind those smooth intermediate frames. If the worker copied a multi-megabyte pixel buffer every time it sent a frame, that cost would add up too. So postMessage offers an alternative to copying the data: transferring ownership of it outright. Transferable objects like ArrayBuffer move by reference only, so the cost is close to zero regardless of size. The side that hands the buffer over can no longer use it, and in exchange the copy cost disappears.

// Hand the pixel buffer to the worker without copying
// After the transfer, this side can no longer use it
worker.postMessage({ buf: pixels.buffer, width, height }, [pixels.buffer]);

Eliminating the Work Itself

So far we’ve been asking whether a piece of work really needs to run on the main thread. This time, let’s ask whether the work needs to happen at all. The best thing for performance is not doing the work in the first place.

Backpressure came up earlier. Batch as well as you like, and once the inflow exceeds the maximum throughput the backlog still grows without limit. Unfortunately, the browser has no good way to tell the server to slow down. At some point you have to give up on the idea of doing everything you’re given. There are generally three ways to eliminate work.

Three ways to eliminate work

The first is dropping . For data that just flows past, like live logs, once processing starts falling behind you can quietly discard the oldest entries and users won’t notice. Keeping up with the present matters more than showing everything.

The second is merging . For data where only the latest value means anything, like rankings, you can merge the backlogged updates and apply only the final value. With merging, the amount of work is pinned to what the screen can digest, no matter how fast the inflow gets.

The third, skipping , targets repeated work rather than incoming work. If a computation gives the same result for the same input, there’s no reason to do it a second time. Remembering results and reusing them is called memoization.

This idea has been hiding throughout the article. Debounce skipped executions during typing, and the feed demo skipped rendering posts that weren’t visible. Looked at from this angle, half of this article was about eliminating work.

When you study optimization, your attention tends to go to ways of doing work well, but the biggest gains usually come from removing work. Before making some task faster, think about it first. Does this work have to happen, now, here, at all?

Closing

Some developers think of frontend work as the easy kind. But the browser is a far more complex system than we tend to assume. Drawing screens with HTML, CSS, and JavaScript is not the whole story.

Apps that deal with a flood of real-time data, like streaming platforms, or whose screens never stop changing, like image editors, maps, and games, start to feel slow whenever the main thread gets busy. Not everyone is on the latest hardware, so for services like these, optimization is essential. And solving these problems takes more than optimizing code. It takes understanding how the browser works, spending the main thread’s time sparingly, and not doing work that doesn’t need doing at all.

In the end, nothing is easy once you dig deep enough. So much of development is trade-offs, and you have to choose according to the situation, which ultimately comes down to the developer’s experience and judgment. Neither is built quickly, but both can certainly be built through study and experiment. I hope this article helps a little along the way.

  1. The compositor thread is responsible for compositing already-drawn layers onto the screen. We’ll come back to it later in the article.

  2. https://web.dev/articles/rendering-performance

  3. The HTML spec mandates a minimum 4-millisecond delay once setTimeout calls nest more than 5 levels deep. Yielding repeatedly inside a loop, as in the code above, trips this condition almost immediately, so even with the delay set to 0, each piece waits at least 4 milliseconds.

  4. https://philipwalton.com/articles/idle-until-urgent/

  5. Granted, 1,500 posts rarely pile up on one page in practice. The demo stacks that many on purpose, to make the effect of deferred rendering dramatic.

  6. https://aerotwist.com/blog/flip-your-animations/

  7. https://en.wikipedia.org/wiki/Seam_carving

Claude for Commerce Agents

Hacker News
claude.com
2026-09-03 05:37:55
Comments...
Original Article

Retailers running shopping agents on Claude have seen carts up to 35% larger and shoppers 60% more likely to complete a purchase.

  • Share

    Copy link

    https://claude.com/blog/claude-for-commerce-agents

Many of the world’s largest retailers, marketplaces, e-commerce platforms, and travel companies use Claude to build agents that make shopping easier. Enterprise customers like Shopify, Priceline, and others have agents that let consumers use AI to search for what they want in plain language, find it, compare it, and buy it.

Today, we're launching a blueprint to help build commerce agents on Claude. It contains the harnesses, patterns, and guardrails an engineering team needs to get a commerce agent running in days, with reference implementations of a shopping agent and a merchant agent for retail, travel, telecom, and ticketing platforms. It also includes a Claude Code plugin to get you started.

The code deploys where you already build with Claude, including the Claude API, Amazon Bedrock, Microsoft Foundry, or Google Cloud Vertex AI. You can also work with our solutions and ecosystem partners such as Accenture, Mastercard, and Visa, who are working with us to enable clients and merchant communities to leverage the blueprints.

It’s available today , with live demos for each vertical and an engineering deep-dive on how it was built, just in time for holiday season planning.

The shopping agent running in the ACME retail example .

What's in the blueprint

The repository contains complete, working implementations of a shopping agent and merchant agent that can be built using the Messages API , Agent SDK , or Claude Managed Agents (beta). You can see them running in a self-guided demo before writing any code, and then work with Claude Code to customize them to your catalogs, policies, brand, and more.

The shopping agent

The shopping agent lives inside your app or website. The blueprint includes the integration points for catalog, cart, checkout, customer preferences, and order history, and leaves payment to you, whether that is your existing checkout or an agentic payments provider.

A customer can say “I need a tent, sleeping bag, and stove for a weekend trip with two kids,” and the agent can take it from there. Here’s what it can do:

  • Search the catalog and assemble the right set of items, including multi-item requests.
  • Remember the customer's preferences and tailor what it suggests.
  • Show products, comparisons, and the cart right in the conversation, not just as text.
  • Build the cart and hand it to checkout.
  • Answer customer service questions in the same conversation, like where an order is, how to return or exchange an item, and what the refund policy says, instead of sending the customer to a support page.

The agent features guardrails designed to constrain prices and products to actual catalog data, and avoids manipulative upsell patterns. In the repository, these are skills and tools for catalog search, multi-item planning, deep research, personalization, customer care, and in-conversation UI.

The merchant agent

The merchant agent supports the people running the store. A user can ask “what should we discount to clear last season’s inventory?” and get an answer based on their own data. Here’s what it can do:

  • Answer questions about sales performance like what's selling and what isn't.
  • Track inventory and proactively flag problems, like an item about to sell out before a promotion starts.
  • Recommend pricing and promotions based on the store's own sales history.
  • Draft marketing campaigns to move the products that need moving.

When the agent proactively suggests a change, a person approves it before anything goes live, meaning users get the final say while their agent watches the store. In the repository, these capabilities ship as skills for sales analytics, catalog and inventory management, marketing and promotions, and in-portal UI such as charts and dashboards.

Trusted across the industry

Companies that serve shoppers, travelers, subscribers, and merchants build and run agents on Claude. Here's what they have to say about building commerce agents with Claude:

Logo Logo

“AI will fundamentally reshape commerce, but trust must remain at the center of every transaction. Merchants are telling us they want more control over how AI engages their customers. Our collaboration with Anthropic on their commerce blueprint helps bring together the intelligence of Claude with the trust, security, and global reach of the Visa network, empowering merchants to deliver better customer experiences while maintaining the relationships that drive their businesses forward.”

Jack Forestell, Chief Product and Strategy Officer

Logo Logo

“Trust is the currency of commerce, and it is even more critical in the agentic era. With Anthropic's commerce blueprint, we're helping merchants build their own agents with Claude to drive their growth. By combining AI innovation with trusted payments and commerce infrastructure, we're helping connect consumers, merchants and AI agents securely, seamlessly and at scale.”

Sherri Haymond, Executive Vice President, Global Head of Digital Commercialization

Logo Logo

“Commerce agents are quickly becoming a critical capability for organizations seeking to deliver the personalized, intelligent customer experiences that today’s consumers expect. Our latest research revealed that 85% are now open to collaboration with an AI agent and nearly three in four would trust a personal AI agent more than their best friend to make a purchase on their behalf. This is more than a shift in how people shop. Agentic commerce is rewriting the rules of brand value – fundamentally shaping what gets purchased, when, where and by whom. Anthropic’s commerce agent blueprint provides a proven starting point that can help organizations accelerate deployment and build differentiated experiences that increase customer satisfaction, loyalty, and growth. Combined with Accenture's deep retail and consumer goods expertise, we can help clients move from concept to production and realize value from agentic AI faster.”

Kath Gramling, Global Consumer Goods, Retail and Travel lead

Logo Logo

“A trip is one of the most complex things a person buys: flights, hotels, cars, and dozens of options to weigh against each other. Penny, our AI assistant, navigates all of that in one conversation and surfaces the best options and best value. We built the latest generation of Penny on Claude because that kind of reasoning is exactly what Claude models are good at.”

Cobus Kok, Vice President, AI Experiences

Logo Logo

“Millions of consumers, businesses and accountants run their finances on Intuit. Working with partners like Anthropic, we're building highly personalized experiences that provide customers with a clear understanding of what's shifting in their business and why, so they can take action with complete confidence. We are creating a financial system of intelligence by combining frontier AI reasoning, including Claude, with our proprietary data, capabilities, intelligence, and human expertise that powers the next level of prosperity for our customers.”

Chris Kasten, Intuit’s Chief Architect and SVP of Engineering, Platform and Development Xceleration Group

Logo Logo

“We want our merchants to be everywhere customers are shopping, and increasingly that means a conversation with an agent. We're building on Anthropic's blueprints with a reference storefront implementation that connects them to a merchant's store through Catalog, UCP and Shop Sign-in. Merchants can use Claude to build agents that help customers find products, check out, and answer questions about their orders.”

Logo Logo

“Commerce and stunning customer experiences require personalization, and every brand on Klaviyo sits on more customer data and decisions than any team could act on by hand. Claude closes that gap, turning consumer preferences and performance data into the insights, campaigns and personalization that drive revenue. That's why we keep building with Anthropic: agents do complex analysis, design and decision making, and businesses can focus on delighting customers.”

Andrew Bialecki, Founder and Co-CEO

Logo Logo

“Wix’s mission has always been to make complex technology simple and accessible for our users. For merchants, that means providing powerful commerce capabilities without adding operational complexity, and agents are a natural next step. Our engineers had a working commerce agent taking prompts within fifteen minutes, and the pilot showed the potential of combining Anthropic’s AI capabilities with Wix’s commerce platform and deep expertise in commerce for SMB.”

Dror Zalika, Head of Commerce at Wix

Logo Logo

“Our engineers had the blueprint running with no blockers; the setup worked exactly as documented. The practices it bakes in, from tool iteration limits to prompt caching, are the ones we recognized from building Zomato's own agent. Teams standing up their first agent on Claude will skip weeks of trial and error.”

Akhil Bansal, Senior Engineering Manager

Logo Logo

“Our engineers had both commerce agents from Anthropic's blueprint running locally in well under an hour, with live conversations working on the first attempt. We ran the Claude Code workflow twice and got two different architectures back, each designed to what we'd asked for. For a team starting from scratch, that turns days of agent scaffolding into hours.”

Ashley Nader, Staff Product Manager

Logo Logo

“Much of what we build at Square is about giving sellers time back, and agents are a big leap in our ability to do that. We're building agentic tools that watch sales, labor, and inventory and come back with real next steps, not just an answer, while keeping sellers in control. Trust is the hardest part of that work, and Claude helps us meet a high standard.”

Willem Avé, Head of Product

Getting started

The blueprint is available today. Contact our sales team to learn more, schedule a demonstration, or discuss how to implement for your organization.

  1. Fork the repository at github.com/anthropics/commerce-agents .
  2. Read the engineering deep-dive at claude.com/blog/the-anatomy-of-effective-commerce-agents.
  3. See the vertical demos and request a working session at claude.com/solutions/commerce .

Register for our webinar to see the deep dive where we'll share live walkthroughs, demos, and cover how commerce builders can get the most out of Claude.

Transform how your organization operates with Claude

Get the developer newsletter

Product updates, how-tos, community spotlights, and more. Delivered monthly to your inbox.

Please provide your email address if you'd like to receive our monthly developer newsletter. You can unsubscribe at any time.

Thank you! You’re subscribed.

Sorry, there was a problem with your submission, please try again later.

Japan halves speed limit to 30km/h on all narrow city streets

Hacker News
www.theguardian.com
2026-09-03 05:21:53
Comments...
Original Article

Drivers on residential roads in Japan have been forced to take their foot off the accelerator, after the speed limit was slashed from 60km/h (37mph) to 30km/h in an attempt to reduce deaths and injuries among pedestrians on narrow urban streets.

The new limit, which went into effect on Tuesday, applies to residential roads with no centre line or maximum speed signs, media reports said.

Narrow roads with no centre lines or pavements are a common sight in crowded Japanese cities, with data indicating that children and older people are at particular risk of being involved in a fatal or serious accident.

The measures apply to about 870,000km of roads that are less than 5.5 metres wide and do not have centre lines or median strips, according to the Mainichi Shimbun. They account for about 70% of the country’s general roads, the newspaper said.

Authorities hopes the restrictions will address concerns that residential areas are not experiencing the same improvements in safety seen on larger roads.

While the overall number of deaths in traffic accidents is in decline – falling to a record low of 2,457 last year – those involving children and older people on residential roads has remained steady at about 300 a year since 2021, and rose for the first time in three years in 2025, according to the national police agency.

The introduction in 2011 of “zone 30” areas on a limited number of residential streets and along school routes resulted in a 30% reduction in fatalities and serious injuries, the Mainichi said.

Police agency data show that the mortality rate among pedestrians is less than 1% in accidents involving vehicles traveling at or below 30km/h, with the rate rising to 2.7% at speeds of 30-40km/h, and to 17.4% at 50-60km/h.

“We ask drivers to recognise that they need to take particular care on roads shared by vehicles, pedestrians and cyclists,” the police agency’s commissioner general, Yoshinobu Kusunoki, told reporters this week.

Child sexual abuse survivor alleges Elon Musk’s AI chatbot used photos of her to generate new illegal images

Guardian
www.theguardian.com
2026-09-03 05:00:49
Musk denied he was aware Grok ever produced ‘any naked underage images’ A survivor of child sexual abuse has sued Elon Musk’s artificial intelligence company, alleging that its chatbot used pictures of her abuse to generate new illegal pornographic images that depict her. “Using real images of Plain...
Original Article

A survivor of child sexual abuse has sued Elon Musk ’s artificial intelligence company, alleging that its chatbot used pictures of her abuse to generate new illegal pornographic images that depict her.

“Using real images of Plaintiff and class members, Grok generated child pornography depicting Plaintiff and class members,” states the complaint, which was filed last week in a US district court in California.

Attorneys for the plaintiff, who is listed as Jane Doe in the case to protect her identity, accuse xAI of both generating CSAM of their client and of ingesting child sexual abuse images depicting her into the company’s datasets after new images were publicly posted.

The lawsuit alleges that xAI ignored industry-standard methods of safeguarding against sexual abuse material, resulting in AI-generated child sexual abuse material (CSAM) appearing and spreading on the social media platform X, formerly Twitter.

Though Musk denied he was aware Grok had ever produced “any naked underage images” in January, his company sued two of its own users in late August who are facing criminal charges for allegedly doing just that. xAI wants the two men to pay the costs of lawsuits their victims have filed against the company.

The case deviates from several other child sexual abuse-related lawsuits against xAI by accusing the company’s AI of using pre-existing CSAM to produce and distribute AI-generated images of child sexual abuse. Previous suits, such as a case involving a group of Tennessee teenagers , accuse Grok of taking non-explicit photos of minors and using them to generate child sexual abuse material, most often by removing their clothing.

The distinction of using pre-existing CSAM is notable because law enforcement and child protection organizations frequently give those illegal materials a kind of digital fingerprint – known as a hash – which allows them to track images and videos when they appear online. In this case, attorneys for the plaintiff stated that the Canadian Centre for Child Protection used images’ fingerprints to identify AI-generated CSAM on X that depicted their client.

The plaintiff in the case was pre-school-aged when she was repeatedly raped and forced to produce CSAM material by an adult man, according to the complaint. That series of CSAM has been in circulation online for about 20 years, attorneys for the plaintiff said, and is extremely well known to both authorities and child protection groups.

“The difference here between many criminal cases that you’ll see with AI-generated material is that you cannot prove that the kid in the material is real,” Margaret Mabie, an attorney for the plaintiff, said. “But here, because you can associate it with the series, we know that it is an identifiable victim who is still alive and was a real child in the photo.”

Neither xAI or SpaceX, which acquired the company in February, returned requests for comment regarding the lawsuit. SpaceX went public earlier this year in an initial public offering that valued the company at about $1.7tn and for a time made Musk the world’s sole trillionaire.

skip past newsletter promotion

xAI is facing numerous lawsuits accusing the company of creating and distributing child sexual abuse materials. Many of the lawsuits stem from a period at the start of this year when loose safeguards on Grok allowed users to direct it to remove clothing from photos and generate sexualized images on command via X. Musk stated in January that Grok’s NSFW mode was intended to allow “upper body nudity of imaginary adult humans”. The bot generated millions of sexualized images within the span of weeks, including thousands depicting children, according to researchers at the Center for Countering Digital Hate .

Although the class-action suit filed last week focuses on its unnamed lead plaintiff, the complaint states that the class may consist of “at least thousands of minors” who experienced similar harms. The use of AI to produce child sexual abuse material presents a new realm of threats to the safety and mental health of victims, attorneys said, exposing them to unforeseen harm and retraumatizing them with each new AI-generated image.

“The problem here is that at least for our client, for the past 20 years, the universe of images of them was finite,” Mabie said. “The fear now is that new criminal acts, new offensive behavior, new ideas of what can be done to them can now be created using AI. They can generate new abuse.”

The Canadian Centre for Child Protection declined to comment on the case.

‘Ruin and decay bring a chance of rebirth’: Hidetaka Miyazaki on uniting players in a damaged world

Guardian
www.theguardian.com
2026-09-03 05:00:49
As FromSoftware’s new multiplayer game The Duskbloods nears release, the legendary game director behind Dark Souls talks connection, pessimism and of course, feet Since 2020’s Demon’s Souls, Japanese video game director Hidetaka Miyazaki has shown the world a different way to think about game design...
Original Article

S ince 2020’s Demon’s Souls, Japanese video game director Hidetaka Miyazaki has shown the world a different way to think about game design. His games defy convention with punishing fights, obscure rules, and unknowable, inhospitable worlds. The “Soulslike” genre – named after Demon’s Souls and its sequel Dark Souls – is now ubiquitous, influencing multimillion-sellers from God of War and Star Wars: Jedi to Hollow Knight. Miyazaki’s most recent success, 2022’s Elden Ring , which credited Game of Thrones author George RR Martin as a co-creator, sold over 30m copies and inspired Alex Garland to adapt it for the big screen at A24. It earned Miyazaki a spot on Time magazine’s “most influential” list, an accolade he shares with just one other game developer: Mario creator Shigeru Miyamoto.

Miyazaki is now 51 and has been FromSoftware’s president since 2014, elevated from game designer to CEO after the success of the Souls series. He has a cherubic face that could pass for 35. He rarely speaks publicly, and never on camera. When he does speak, he answers questions like one of his characters – softly, sadly, his head bowed, making eye-contact only when I am speaking. Outside the studio where we speak is the sprawl of Tokyo’s Shinjuku, an ever-changing maze where tourists get lost and pop-up stores appear and vanish without a trace. Today, a J-pop band performs in the square as the cicadas scream from the trees. A gilded statue of Melania, one of Elden Ring’s toughest bosses, looms over this dimly lit conference room inside From’s headquarters, a bonfire checkpoint away from the chaos.

He creates an ‘atmosphere of wonder’ … Hidetaka Miyazaki accepts a Bafta games award for Elden Ring in 2023.
He creates an ‘atmosphere of wonder’ … Hidetaka Miyazaki accepts a Bafta games award for Elden Ring in 2023. Photograph: Stuart Wilson/Bafta/Getty Images for Bafta

FromSoftware’s in-game universes are filled with clues – enemies, places and scraps of information from item descriptions paint a vague image of the world, and the player fills the blank space. You never fully understand these domains, although countless YouTube video game theorists have tried – as have other developers in awe of his work. “Of all the many things Miyazaki and his team do well, creating a sense of mystery is the greatest,” explains Dishonored director Harvey Smith , who has more than 40 days’ playtime in Elden Ring. “It’s so incredibly hard to do in video games, which are technical systems … But Miyazaki somehow creates an atmosphere of wonder. Even when finishing, you are left ruminating on fun, murky elements that feel half understood. It’s a delicious sense of intrigue.”

Rather than the single-player action game that Miyazaki’s audience craves (fans are desperate for a sequel to his 2015 gothic masterpiece Bloodborne , for instance), his latest project The Duskbloods is a multiplayer Switch 2 exclusive. Eight players face off against ghoulish horrors, fighting each other to avoid being culled at the end of each round. The survivors are whittled down over three phases culminating in a final three-way battle. The Duskbloods is releasing to an audience with shifting tastes and trends, and it is certainly a risk. “I’m very nervous,” Miyazaki says. “With every title we release there is this mounting tension.”

The game opens with an arresting image: one hand reaching out for another. A male character is slumped on a chair, dejected; the shot moves in close to focus on their draped fingers. From below the frame, a pale hand slowly reaches out and caresses them before gently clasping his wrist. Hands are a recurring motif in Miyazaki’s games; in Elden Ring, massive crawling hands burrow up from underground to attack you, and hand-like giants are revered as deities.

“It’s not necessarily something I’m consistently aware of – maybe it’s something subconscious coming through,” Miyazaki says when I ask about this imagery. “Take a look online and there’s a rumour that I have a bit of a thing for feet, but I’m not honestly sure where this comes from. I feel like I’m trying to depict some side of human nature or the human existence that is difficult to describe.” (His games have featured, by my count, at least six barefoot female characters.)

Shot from video game Elden Ring of a witch character standing in a purple and black scene
‘It’s rumoured I have a bit of a thing for feet’ … Elden Ring Nightreign. Photograph: Bandai Namco

Perhaps all the hands and feet are symbolic of human connection. One hand reaches for another; bare feet connect skin with earth. Miyazaki has been exploring that theme since Demon’s Souls , whose novel, stranger-centric multiplayer was inspired by a time his car slipped on an icy hill and a stranger helped to push him to safety. In Demon’s Souls and the Dark Souls series, players paint runes on the ground, which other players can then use to summon help in a fight, creating moments of spontaneous togetherness before an inevitable parting.

While The Duskbloods primarily puts players in opposition, it also explores temporary alliances and conflicting objectives, buoyed by Miyazaki’s love for tabletop role-playing games and board games. Players can even become betrothed to each other, forming an alliance. “I feel it’s less a traditional romance and more a sense of secure trust with a character in the world, and that’s something I personally yearn for,” he says. “It’s not necessarily a romantic pairing – it’s having someone that you can ultimately rely on. This concept is carried through from characters like the maidens in Elden Ring … it’s a transient, ephemeral love, which is maybe a motif I’m striving for.”

The Duskbloods is preoccupied with ruin and rebirth, a thematic cornerstone of From’s games – much as Godzilla was a product of nuclear paranoia in Japan. Even as Miyazaki and I talk, a deadly magnitude 6.8 earthquake hits the Kumamoto prefecture on Kyushu island, a thousand miles away. If the very ground beneath your feet is unreliable, that can shape your outlook on life, a concept explored extensively in Japanese literature and entertainment, recently on the hit television show Shōgun . “[Ruin and rebirth] is an ongoing theme in a lot of my games, I realise,” Miyazaki says. “That theme on a cosmological scale applies to The Duskbloods as an interesting philosophical area to explore.”

Image from video game Bloodborne, in which a character strides through a crop field in the moonlight, with a sword on their back.
‘If we have two ideas of a brighter or dark future, I would tend to sway towards the darker one,’ …Bloodborne. Photograph: Sony Computer Entertainment

Miyazaki describes himself as a pessimist, a tendency that he believes comes across in his output. That should be obvious to anyone who’s finished any of his games, in which you keep throwing body and blade against seemingly impossible odds, reborn each time you die at a bonfire checkpoint, to try again. Even when you triumph, nothing ultimately seems to change: these games culminate in bleak, morally ambiguous gut-punches, leaving you not as a conquering hero but as the perpetuator of a hopeless cycle. “If we have two ideas of a brighter or dark future, I would tend to sway towards the darker one,” Miyazaki says. “[But] if you explore the ruin and the decay in those worlds, it also lets you explore some chance of rebirth, and I think having that tiny pinprick of light or hope can be something beautiful, something fleeting.”

Sekiro, Dark Souls, Bloodborne, and Elden Ring are all separate series, but they share the same bones. They’re reborn in different forms, to explore fresh ideas, places and perspectives while still playing, feeling and sounding like a FromSoftware game. While it’s immediately clear The Duskbloods is a Miyazaki game, it too wears a different skin, inspired by extraction shooters like Escape from Tarkov and those tabletop role-playing games the director loves. “There’s no intentional FromSoftware [mantra] – ‘this is the way we make our games’ – because if you start to do that it becomes stale and conservative, and you start having to adhere to a set of rules and philosophies, and it just doesn’t become interesting, you can’t make anything that’s as fun,” Miyazaki says.

“So I feel like at least what’s worked for us philosophically is trying to adhere to what we find interesting first. I think that has created a good throughline through our games, and that’s what we concentrate on to [conceive] a new title.”

Back in his early days at the studio, when he was only a coder on the Armored Core series of games, Miyazaki volunteered to take on a struggling project at From – the game that would become Demon’s Souls. (The game was already in trouble, so he felt he had nothing to lose.) He changed everything about the game, and then the game changed everything about his life, as he climbed from coder to company president. From failure was born a game that changed the landscape of video games. Ruin and rebirth.

But does Miyazaki think he has changed? “I don’t intend to,” he says, a smile curling on his lips. “But I probably have.”

Bring on the drones: how a technology revolution is being rolled out across Africa’s nature reserves

Guardian
www.theguardian.com
2026-09-03 05:00:49
As graduates of an online training course gather from across the continent, the consensus is overwhelming: computers and saving animals go together On a bitingly cold night in Lapalala Wilderness nature reserve in South Africa’s Limpopo province, Duncan Kanyakera watches as instructor Jacques Viljoe...
Original Article

O n a bitingly cold night in Lapalala Wilderness nature reserve in South Africa’s Limpopo province, Duncan Kanyakera watches as instructor Jacques Viljoen deploys a thermal drone in search of a lone cheetah. Once the drone has disappeared into the inky sky, Kanyakera, from Tsavo in Kenya, and 20 other conservation professionals from across Africa turn their attention to the open-air screen in anticipation.

Many of the students – from 11 African countries as far flung as Benin, Liberia, the Democratic Republic of the Congo and Madagascar – witnessing the demonstration have earned their places at Lapalala after performing well on an online training programme for protected area technicians (PAT) run by the Connected Conservation Foundation (CCF). Also on the course, are five members of Peace Parks staff in training.

“Data and technology are critical to modern conservation,” says CCF’s Sophie Maxwell. “Cameras and collars and software like EarthRanger have transformed the fight against poaching … But then an elephant knocks over a pole and you are back to square one.”

A group of people wearing khaki tops look at a handheld device
Students learn how to use, maintain and repair a range of technology used in protecting wildlife. Photograph: Courtesy of CCF

Since 2015, the CCF has installed state-of-the-art tech systems in parks across Africa with remarkable success, helping to protect nearly 10m hectares (25m acres). “Parks with tech solutions are safer and more biodiverse and they have better relationships with communities,” says Maxwell.

Over the years, the CCF has “identified a critical gap”, says Carien Soldatos who oversees the PAT training programme: “Tech is fantastic, but it all depends on having trained technicians on the ground. Without people who know how to use, repair and maintain them, the fanciest gizmos in the world aren’t much use.” While there are such people in some parks, they are sorely lacking in many parts of Africa .

After searching everywhere for a tech course aimed at conservation professionals, the CCF decided to create its own . Their 10-module course, which launched in July 2025, was a global first. In the first year, 680 people from all over the world finished at least one module. Those who completed all 10 modules were invited to interviews, with the top 16 chosen to attend the practical component at Lapalala.

In less than 10 minutes, the heat sensor technology in the drone launched by Viljoen locates the cheetah resting with her cubs. Once he has locked its location, the operator sends a pin to the park’s on-duty field rangers, who rush to the scene. “I was stunned,” says Kanyakera. “There was no moon and the cheetah was miles away from us. But we could see exactly what was happening as the rangers got out of their vehicle and checked up on her.”

Kanyakera, who works for the Taita Taveta Wildlife Conservancies Association ( TTWCA ) to support a network of 35 conservancies and ranches in Kenya’s vast Tsavo landscape, recognised immediately how handy a drone would be back home. Human-wildlife conflict is a challenge in Tsavo: “If an elephant gets into a corn field, it causes havoc,” he says. “And then you have the problem of humans retaliating.”

A group of people pose for a group shot in a wildlife reserve.
Sixteen people were chosen from across Africa to attend this year’s practical course, with a second planned for early next year. Photograph: Courtesy of CCF

The aim, says Kanyakera, is to keep humans and animals apart via designated wildlife corridors. But this gets tricky in the dry season when animals and humans alike are drawn towards water. Currently, if Kanyakera gets reports of an elephant near a village, he has to first work out where the elephant is and which direction it is moving in, before deploying rangers to intervene. This can take hours.

“With a drone, we could find the elephant in minutes,” he says. “The noise of the drone alone would probably be enough to scare the animal off. And if that doesn’t work, I can deploy rangers much more accurately.”

skip past newsletter promotion
A man in a khaki shirt writes on a flip chart
The course featured guest lectures and practicals on subjects including connectivity, communication and monitoring sensors. Photograph: Courtesy of CCF

While a night-vision drone is the most exciting item on Kanyakera’s Christmas list, the course has also shown him how simple changes could drastically improve the tech “stack” back in Tsavo. This has a lot to do with the course design, explains Maxwell: “Each day, they build a new element of the stack,” she says, “before breaking it down at the end of each day and building it again the next morning to add another layer. It’s all about building muscle memory.”

And it seems to be working. “As soon as I get home, I’ll reconfigure our camera traps to make the most of AI,” says Kanyakera who also has his sights set on re-equipping the ops room in Tsavo. “In the past, we would just Google and make a decision. Now I know so much more, I can target what I really want. The learnings from this course can make a big difference to the people and animals of Tsavo.”

The course – which featured guest lectures and practicals from nine experts on topics including connectivity, communication, power systems, monitoring sensors, hardware integration and GIS visualisation tools – is having an impact far beyond Tsavo.

Effort Zivengwa, who works at the Zimbabwe Parks and Wildlife Management Authority head office in Harare, is part of a tech team responsible for 11 national parks. “We were content with what we were doing,” he says. “But, after completing this course, I think we have to do more. We are already using EarthRanger and we do have sensors, but they are not integrated.

“We have park headquarters and lodges that don’t have internet access,” he adds. “Using point-to-point internet can fix that problem easily.” The learning module on solar power further shifted his understanding of what is possible. “We have a lot of remote stations,” he says. “But the sun shines everywhere.”

Mabel Nokhuthula Piki hold a pair of pliers during a demonstration next to what look like battery packs.
Mabel Nokhuthula Piki plans to use what she has learned to teach her own students how computers can help save animals. Photograph: Courtesy of CCF

Mabel Nokhuthula Piki, who teaches wildlife monitoring skills at the Chinhoyi University of Technology in central Zimbabwe, has also found the course empowering. “My students didn’t comprehend that tech was important. They couldn’t get the link between saving animals and computers. But now I am going to change their minds,” she says. “It is impossible to understand the value of tech until you have seen it.”

The CCF is planning to run a second practical course with another batch of students in the first quarter of 2027. What is more, says Soldatos, “we will be supporting five participants from the first course with internships and/or hardware donations”. The lucky five have not yet been chosen, but Kanyakera, Zivengwa and Piki are all in the running.

Microsoft Teams, Outlook fail to launch on ARM-based Windows PCs

Bleeping Computer
www.bleepingcomputer.com
2026-09-03 04:55:25
Microsoft is working to fix a known issue that causes crashes and launch failures for Microsoft Teams and New Outlook users after installing updates released since the August 2026 Patch Tuesday. [...]...
Original Article

Windows

Microsoft is working to fix a known issue that causes crashes and launch failures for Microsoft Teams and New Outlook users after installing updates released since the August 2026 Patch Tuesday.

These issues affect only ARM-based Windows devices like the Surface Laptop 7 and Surface Pro 11 that run Windows 11 24H2 or later, and they mainly impact users who haven't installed Microsoft Store updates yet.

"After installing Windows security updates released on or after August 11, 2026, (KB5121003), Microsoft Teams and the new Outlook for Windows might fail to launch or might close unexpectedly on ARM-based devices, such as Surface Pro 11 and Surface Laptop 7," Microsoft said in a Windows release health update.

"Classic Outlook, Word, Excel, and other applications are not known to be affected. This issue is most likely to occur on new or freshly imaged PCs that have not yet installed any Microsoft Store updates."

While Microsoft didn't share the root cause, it advised affected customers to update the Auto Super Resolution Package , which the company says allows "Copilot+ PCs to use AI to make supported games play more smoothly with enhanced details."

Although Microsoft did not disclose the root cause, it advised affected customers to update the Auto Super Resolution Package as a temporary workaround. According to Microsoft, this package enables Copilot+ PCs to use AI to make gameplay smoother.

To do that, users have to open the Microsoft Store, go to Downloads > Check for updates, and install Auto Super Resolution Package version 1.0.19.0 or later.

Microsoft says that it's now working on a permanent fix for this issue, which will be released with a future Windows update.

This is the latest in a series of known issues caused by Windows updates released in August. For instance, last week, Microsoft also confirmed that August 2026 .NET Framework updates are breaking printing and PDF export in some applications.

Days later, it also began rolling out a fix for a known issue caused by peripherals with built-in RGB lighting that triggered system crashes and gaming issues on Windows 11 devices with EXCEPTION_ACCESS_VIOLATION" errors.

On Friday, the company also asked customers to ignore alerts that Microsoft Defender Antivirus has been turned off after installing the latest Defender updates.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

What's in the Emacs newcomers-presets theme?

Lobsters
sachachua.com
2026-09-03 04:40:15
Comments...
Original Article
Posted: - Modified: | emacs

: Added Emacs 31 mention. Changed code sample for flyspell-mode to flymake-mode . Thanks, jeenajeena!

Emacs 31 (released Aug 2026) as well as development versions of Emacs after Feb 2026 includes a newcomers-presets theme that can be enabled from the splash screen or by using M-x load-theme RET newcomers-presets RET . (Not sure how to run that command? Start with the guided tour/tutorial or choose "Help - Tutorial" from the Emacs menu.)

2026-04-29_14-19-11.png
Figure 1: Newcomer presets are on the splash screen

If you like it and want to make it automatically enabled in future Emacs sessions:

  1. Use M-x customize-themes
  2. Select the checkbox next to newcomer-presets by either clicking on it or using TAB to navigate to it and then pressing RET.
  3. Click on or use RET to select Save Theme Settings .
2026-04-30_09-47-33.png
Figure 2: Saving the theme setting

I'm not sure if someone else has made notes on what it does yet, so I thought I'd put this together.

Most Emacs newbies aren't running the development version of Emacs at the moment, but it will eventually make its way into Emacs 31. I wonder if it might be a good idea to extract the theme as a package that people can use use-package on if they want. I am not entirely sure about using themes for this, but it's worth an experiment.

Here's a list of what newcomers-presets includes. I'll also include the corresponding Emacs Lisp in case you want to copy just that part, or you can also get it as copy-of-newcomers-presets.el . If you want to load it in your existing Emacs, you can add (load-file "path/to/copy-of-newcomers-presets.el") to your InitFile . You can use C-h f ( describe-function ) or C-h v ( describe-variable ) to learn more about the functions or variables it changes. I'm manually making this page, so there might have been some changes to etc/themes/newcomers-presets-theme.el since .

;; -*- lexical-binding: t -*-
;; Based on https://github.com/emacs-mirror/emacs/tree/master/etc/themes/newcomers-presets-theme.el

Editing and navigation

When you select text by pressing C-SPC ( set-mark-command ) and then moving to the end of the text you want to select, and then you type, the new text replaces the selection.

(setopt delete-selection-mode t)

Copying works better when copying between Emacs and other applications Equivalent:

(setopt save-interprogram-paste-before-kill t)

If you have a compatible spellchecker installed ( Hunspell , Aspell , Ispell , or Enchant ), Emacs will check your spelling and underline errors using flyspell-mode . You can use M-x ispell-change-dictionary to change the language if you have the appropriate dictionary installed. In code buffers, the spelling is checked in comments and strings. You can also use flyspell-goto-next-error ( C-, ) to go to the next misspelled word and flyspell-auto-correct-word ( C-M-i ) to fix it. More info: Spelling (info "(emacs) Spelling") .

2026-04-30_09-36-20.png
Figure 3: A wavy red underline shows potentially misspelled words; right-click on them to correct them or add them to the dictionary
(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'prog-mode-hook 'flyspell-prog-mode)

Imenu entries are automatically updated based on the structure of the current buffer or file (ex: outline headings, function names). You can list them with M-x imenu or add them to the menu bar with M-x imenu-add-to-menubar .

(setopt imenu-auto-rescan t)

When you visit a read-only file, it will be in view mode, so you can use SPC to scroll. This affects buffers for files that you don't have permission to change as well as buffers that you make read-only using C-x C-q ( read-only-mode ).

(setopt view-read-only t)

Appearance

Scrolling happens more smoothly instead of jumping by character.

(setq pixel-scroll-mode t)

Line numbers are shown in both text and code buffers.

(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'text-mode-hook 'display-line-numbers-mode)

Column numbers are shown in the mode line.

(setopt column-number-mode t)

If you change your system-wide fixed-width font, Emacs will also update. the system-defined font dynamically.

(setopt font-use-system-font t)

You can resize your frames or windows to any size instead of being limited to whole-character steps.

(setopt frame-resize-pixelwise t)
(setopt window-resize-pixelwise t)

The frame size will stay the same even if you change the font, menu bar, tool bar, tab bar, internal borders, fringes, or scroll bars.

(setopt frame-inhibit-implied-resize t)

If a mode line is wider than the currently selected window, it is compressed by replacing repeating spaces with a single space.

(setopt mode-line-compact 'long)

Saving data between sessions

Minibuffer history is saved between Emacs sessions so you can use M-x and then use M-p and M-n to navigate your history.

Your place in a file is saved between Emacs sessions.

(setopt save-place-mode t)

Your recently-opened files are saved between Emacs sessions, so you can use M-x find-file and other commands and then use M-p and M-n to navigate your history.

Completion

This set of options affects the completion candidates (the suggestions that appear when you press M-x and then TAB , or when you use TAB at other prompts).

You can use the arrow keys to select completion candidates in the minibuffer, and you can use RET to select the highlighted one.

(setopt minibuffer-visible-completions t)

Additional details for completion suggestions are shown before or after the suggestions. For example, M-x describe-symbol ( C-h o ) shows additional information.

(setopt completions-detailed t)

Completion candidates can be grouped together if the function that sets up the completion specifies it.

(setopt completions-group t)

When you press TAB to see the completion candidates for a prompt (for example, M-x and then TAB ), the first TAB will display the completion list, and the second TAB will select the buffer.

(setopt completion-auto-select 'second-tab)

This Completions buffer will update as you type so that you can narrow down the candidates.

(setopt completion-eager-update t)

The following completion styles are set up:

  • basic: You can type the start of a candidate. (ex: abc will list abcde and abcxyz )
  • partial-completion: You can specify multiple words and each word will be considered as the prefix for matching candidates. For example, if you type a-b , that will match apple-banana if it is one of the options.
  • emacs22: When you move your point to the middle of some text and then complete, the text before your point is used to filter the completion and the text after your point is added to the end of the result.

More info: Completion styles

(setopt completion-styles '(basic emacs22 flex))

Automatically show the completion preview based on the text at point. TAB accepts the completion suggestion and M-i completes the longest common prefix.

(setopt global-completion-preview-mode t)

TAB first tries to indent the current line. If the line was already indented, then Emacs tries to complete the thing at point. Some programming language modes have their own variable to control this, e.g., c-tab-always-indent , so it might need additional customization.

(setopt tab-always-indent 'complete)

Help

If you pause after typing the first part of a keyboard shortcut (ex: C-c ), Emacs will display the keyboard shortcuts that you can continue with.

(setopt which-key-mode t)

Tab bar

The tab bar is always shown. Tabs let you save the way you have one or more windows arranged, and which buffers are displayed in those windows. You can click on a tab or use M-x tab-switch to switch to that configuration, or click on the + sign or use M-x tab-new to add another tab. More info: Tab Bars (info "(emacs) Tab Bars") "

2026-04-30_09-15-18.png
Figure 4: The tab bar is displayed at the top of a buffer.

The tabs are saved between Emacs sessions.

(setopt tab-bar-history-mode t)

The Dired file manager

Dired buffers are refreshed whenever you revisit a directory.

(setopt dired-auto-revert-buffer t)

You can use the mouse to drag files in Dired. Ctrl+leftdrag copies the file, Shift+leftdrag moves it, Meta+leftdrag links it. You can also drag the to other applications on X11, Haiku, Mac OS, and GNUstep.

(setopt dired-mouse-drag-files t)

Show the current directory when prompting for a shell command. This affects shell-command and async-shell-command .

(setopt shell-command-prompt-show-cwd t)

Package management

If you open a file for which Emacs has optional packages that provide extra support in GNU ELPA or NonGNU ELPA , Emacs will add [Upgrade?] to the mode line to make it easier to install the appropriate package.

2026-04-30_09-06-18.png
Figure 6: Package autosuggest adds an Upgrade? to the modeline when you open a file for which Emacs has an optional package available
(setopt package-autosuggest-mode t)

When you're working with M-x list-packages , x ( M-x package-menu-execute ) now requires you to select something instead of acting the current package by default. Press i ( package-menu-mark-install ) to mark a package for installation, press d ( package-menu-mark-delete ) to mark a package for deletion, press u ( package-menu-mark-unmark ) to unmark a package, and press x ( package-menu-execute ) to execute the operations.

(setopt package-menu-use-current-if-no-marks nil)

Code

In code buffers, Emacs will display errors and warnings by using flymake-mode .

(add-hook 'prog-mode-hook 'flymake-mode)

If you use M-x compile , the *compilation* window will scroll as new output appears, but it will stop at the first error so that you can investigate more easily.

(setopt compilation-scroll-output 'first-error)

You can Ctrl+leftclick on a function name to jump to its definition using xref-find-definitions-at-mouse .

(setopt global-xref-mouse-mode t)

Emacs will automatically insert matching parentheses, brackets, and braces.

(setopt electric-pair-mode t)

Emacs will generally use spaces instead of tabs when indenting code.

(setopt indent-tabs-mode nil)

If there is a project-specific .editorconfig file, Emacs will follow those settings. ( More about EditorConfig )

(setopt editorconfig-mode t)

Tags tables are automatically regenerated whenever you save files. This uses Etags to make it easier to jump to the definitions of functions or variables.

Version control

(setopt etags-regen-mode t)

Files are reloaded from disk if they have been updated by your version control system.

(setopt vc-auto-revert-mode t)

If a directory has changed in version control but you have some modified files, Emacs will ask if you want to save those changed files.

(setopt vc-dir-save-some-buffers-on-revert t)

If you use vc-find-revision to go to a specific version of the file, it is displayed in a temporary buffer and does not replace the copy that you currently have.

(setopt vc-find-revision-no-save t)

If you open a symbolic link to a file under version control, Emacs will open the real file and display a message. That way, it will still be version-controlled.

(setopt vc-follow-symlinks t)

C-x v I and C-x v O now have additional keyboard shortcuts. For example, C-x v I L is vc-root-log-incoming and C-x v O L is vc-root-log-outgoing . Use C-x v I C-h and C-x v O C-h to see other commands.

(setopt vc-use-incoming-outgoing-prefixes t)

The version control system is automatically determined for all buffers. (Standard Emacs just checks it in dired, shell, eshell, or compilation-mode buffers.)

(setopt vc-deduce-backend-nonvc-modes t)

Things I haven't been able to figure out yet

On Linux with X11, Haiku, or macOS / GNUstep: When a buffer has an associated filename, you can drag the filename from the modeline and drop it into other programs. (Haven't been able to get this working.)

(setopt mouse-drag-mode-line-buffer t)

CERN transitioning industrial computers to Debian after being a longtime RHEL institution

Lobsters
www.phoronix.com
2026-09-03 04:28:28
Comments...
Original Article

DEBIAN

CERN, the European Organization for Nuclear Research, besides being well known for its Large Hadron Collider (LHC) is known among longtime Linux users as a RHEL/CentOS shop. CERN formally even co-maintained the Scientific Linux RHEL derivative with other educational/research institutions in the past. So to much surprise now, CERN is transitioning to Debian Linux for industrial accelerator-control computers.

CERN talked about this exciting news at the MiniDebConf that took place in Winterthur, Switzerland this past weekend. CERN had used their RHEL-derived Scientific Linux for about a decade prior to moving to CentOS in 2015. Now after a decade with CentOS, they are moving on and embracing Debian for a portion of their systems.

CERN going Debian

CERN engineers had considered moving to CentOS Stream as a more natural pathway but ultimately they say "the straw that broke the camel's back" to abandon Red Hat Enterprise Linux for their industrial accelerator-control computers was the "-march=x86-64-v2" compiler flag default as "forced obsolescence" for old hardware.

CERN Debian challenges

Among the challenges they have faced though in their Debian on-boarding is the lack of standard tooling for automated building and publishing of packages - a lot of gaps in the official tooling. There are also a number of tools not supporting multiple versions of the same packages.

CERN is planning by the end of 2026 to have all 2,200+ of their industrial computers and embedded systems running Debian 13. Those wishing to learn more can see this video presentation (AV1 WebM) from the MiniDebConf.

Update: CERN has clarified that their focus with the migration is on their industrial accelerator-control computers while data centers and experimental computing remain on RHEL/AlmaLinux.

Three schoolgirls in Kinsale pulled up a pea plant covered in warts (2016)

Hacker News
scienceblog.com
2026-09-03 03:04:13
Comments...
Original Article

The discovery began as a suspected disease. Émer Hickey was gardening with her mother in Kinsale, on the Cork coast of Ireland, when they pulled up a pea plant and found its roots studded with pale, wart-like lumps. It looked sick. Émer, then in her early teens, did the thing that separates a science story from a compost story: she took the plant to school and asked her teacher what was wrong with it.

Nothing, was the answer. The warts were nodules, and inside them lived rhizobium, a soil bacterium in the nitrogen-fixing family called diazotrophs, which legumes like peas deliberately house in exchange for fertilizer. The bacteria pull nitrogen from the air and hand it to the plant as ammonia; the plant pays in sugar. It is one of agriculture’s oldest partnerships, and one of its most frustrating exclusions, because the world’s staple cereals, wheat, barley, rice, cannot form it.

Émer told her friends Ciara Judge and Sophie Healy-Thow, whose geography class happened to be studying the world food crisis in the shadow of the 2011 Horn of Africa famine, and the three of them landed on a question with billion-dollar aid programs attached: if cereals can’t host these bacteria, could the bacteria still help cereals?

The spare-room laboratory

The advice from grown-up science was discouraging. Rhizobia’s benefits were understood to belong to legumes; many people told them the bacteria would have no impact on cereal crops . The girls, aged around 14 when they started, decided the objection had never actually been tested at their scale, and set out to test it at a scale nobody expected.

Working from home, with a bedroom in the Judge house converted into a laboratory, incubation racks, hand-labeled samples, a homemade regime of controls, they soaked cereal seeds in rhizobium cultures and measured everything: time to germination, germination rate, seedling growth, dry mass. Batch after batch, season after season, for three years, they ran the experiment across barley, oats and wheat, ultimately testing some 13,000 seeds , plus thousands more in an outdoor field trial, and logging on the order of 120,000 individual measurements by hand into their notebooks and spreadsheets.

The seeds ignored the expert consensus. Treated barley and oats germinated dramatically faster and more reliably, with germination rates improved by up to 50 percent , and the head start carried through: in their growth trials the treated cereals put on substantially more dry mass, with increases running as high as 74 percent. The bacteria could not give barley a legume’s nodules, but something in the association, delivered at the seed, was waking the grain up early and sending it into the world stronger.

The scoreboard

Irish science noticed first. The project won the BT Young Scientist of the Year in 2013, making the trio the first group of girls ever to take Ireland’s premier young-science title, then the EU Young Scientist contest. In September 2014 came the summit: at Google’s headquarters in California, “Combating the Global Food Crisis: Diazotroph Bacteria as a Cereal Crop Growth Promoter” was named grand prize winner of the Google Science Fair , beating thousands of entries worldwide. The prize haul included scholarship money and a trip to the Galápagos; Time magazine put Ciara Judge among the world’s most influential teens. They were 16 and 17, and they had started at 14, on a plant most gardeners would have thrown away.

The relevance of the result is not subtle. Germination is one of farming’s silent taxes; seeds that sprout slowly or not at all cost yield before the season begins, and a faster, more uniform start matters most exactly where the growing seasons are shortest and the margins thinnest. A seed treatment based on naturally occurring soil bacteria, needing no synthetic chemistry, is the kind of low-cost tool that travels well to smallholder agriculture, which is why the girls framed the project around food security from the first poster. They talked afterward about patents and commercialization, and the wider science has moved their direction since: engineering cereals and microbes to extend nitrogen-fixing partnerships beyond legumes is now one of agricultural research’s most funded ambitions.

The honest footnote is the usual one for prodigy science: a bedroom study, however heroically sized, is not a peer-reviewed field program, effects of “up to” 50 and 74 percent are ceilings rather than averages, and no commercial product yet traces to the Kinsale data. What stands is harder to discount. Three teenagers were told a biological door was closed, checked the literature, found that nobody had pushed on it with 13,000 seeds and three years of patience, and pushed. The pea plant’s warts turned out to be the least diseased thing in the story. The ailment was the assumption, and the cure, as it often is, was a child asking what, exactly, is wrong with this thing you were about to throw away.

Three schoolgirls in Kinsale pulled up a pea plant covered in warts (2014)

Hacker News
www.yahoo.com
2026-09-03 03:04:13
Comments...
Original Article

Irish high school student Émer Hickey was gardening with her mom when she observed wartlike nodules on a pea plant. She later learned that the swellings contained something that could cut back our dependence on chemical fertilizers and mitigate world hunger: bacteria.

But not just any bacteria.

Hickey and fellow 16-year-olds Ciara Judge and Sophie Healy-Thow, all from Cork County, Ireland, experimented with the microbes, called rhizobia, to speed up the germination process in seeds in a project that won them the 2014 Google Science Fair this week. The students found that when the seeds were treated with the bacteria, their yield increased.

The teens began the project as they learned about the global food crisis in geography class.

"We became really interested in what this bacteria can do and what people haven't done with it so far," Healy-Thow told Scientific American .

The trick of using microbes for larger yields has long been used in agriculture.

"The bacteria act as an early warning system for the plants, kickstarting growth," National Geographic explains. "When the microbes sense the presence of compounds called flavonoids on plants, they begin to build nodules, swellings on roots that house bacteria able to convert atmospheric nitrogen into forms the plant can consume. The presence of the nodules then tells the plants it's time to grow faster."

The teens, however, were told that the microbes wouldn't have an effect on cereal crops. They did. They treated seeds with the bacteria and found that the seeds germinated 50 percent faster. They also increased the yield of barley and oats by as much as 70 percent.

"Such a cereal crop performance improvement could significantly assist combating the growing global food poverty challenge and reduce the environmental footprint of agriculture by reducing fertilizer use," the trio wrote in their winning proposal.

Hickey, Judge, and Healy-Thow received scholarships, a grant for their high school, and a trip to the Galápagos Islands. They plan to keep their project going, including by studying "what's happening inside the seeds."

Related stories on TakePart:

At This Year's White House Science Fair, Obama Gives Girls a Gold Star

These Are the Worst (and Best) States in America to Raise Girls

A New Kind of Superhero: The Coolest Girls in Science Today

Original article from TakePart

Pre-Release of Polars 2.0

Hacker News
pola.rs
2026-09-03 02:59:08
Comments...
Original Article

Today we are releasing the first release candidate for Polars 2.0. The definite 2.0 release will land in the following weeks. We don’t aim to make a big feature release of Polars 2.0. In fact we hope it to be a boring experience for you. The reason we bump this major version is that we can get rid of design decisions made in the past that currently block us and then we want to change defaults to more sensible settings that will benefit a greater audience. The biggest default change will be that all LazyFrame queries now will run on the streaming engine. Casual Polars users can therefore expect huge improvements in memory usage and performance. In aggregate we expect the streaming engine to be easily 5x faster .

To help users transition to 2.0, we have posted a full migration guide . This post will cover a few of the highlights.

Streaming engine as default

This is the biggest impact change of 2.0. Calling collect on a LazyFrame will now default to the streaming engine, leading to massive memory and performance improvements on most queries for users. The reason this required a major version bump is that the streaming engine doesn’t guarantee row-order by default for certain operations ( join , group_by , unpivot , etc.). If you require observable row-order in those operations, you can opt in to that by setting maintain_order=True .

For users who want to keep using the “in-memory” engine as default, they can do so by setting the engine affinity.

lf = pl.LazyFrame({"k": [2, 1, 0], "v": ["a", "b", "c"]})
other = pl.LazyFrame({"k": [0, 1, 2], "r": ["x", "y", "z"]})

# 2.0: engine="auto" now resolves to the streaming engine.
# Row order is no longer guaranteed for joins, group_by, unpivot, ...
(
    lf
    .join(other, on="k", how="left")
    .collect()
)
# ┌─────┬─────┬─────┐
# │ k   ┆ v   ┆ r   │   <- order may not match `lf`'s original row order
# └─────┴─────┴─────┘

# Opt in to observable order for this query:
(
    lf
    .join(other, on="k", how="left", maintain_order="left")
    .collect()
)

# Or keep the old in-memory engine as the default, process-wide:
pl.Config.set_engine_affinity("in-memory")

# ...or per query:
(
    lf
    .join(other, on="k", how="left")
    .collect(engine="in-memory")
)

Stricter Polars

Polars aims to be strict and fail fast. Errors should ideally raise up-front, not 20 minutes into a pipeline. Implicit behavior on data-mismatches should be opt-in, not a default, since those mismatches can hide bugs. This strictness has become even more valuable with the rise of AI-driven development. Agents can validate a query’s structure early by calling collect_schema() , which resolves types and catches schema-level mismatches without materializing any data. This ensures fast feedback for the agents, meaning they can iterate faster. Not all errors can be caught during compilation of the query plan, some depend on data. In these cases Polars defaults to stricter behavior to ensure inconsistencies are caught instead of silently producing different results.

Below are a few examples where Polars has gotten more strict:

is_in lossless type-coercion

If you run an is_in expression on different data-types, Polars used to cast both types to their common supertype, even if that conversion was lossy Below is an example with user-ids that can go wrong by silent data-type mismatches.

# Checking if a user ID matches a list of "flagged" account IDs
# (flagged_ids loaded from a JSON export, where large IDs became floats)
flagged_ids = pl.Series([9007199254740992.0])
user_id = pl.Series([9007199254740993])  # Int64 -> a different ID, off by 1
user_id.is_in(flagged_ids)

Before 2.0, user_id gets coerced to Float64 to match flagged_ids . But 9007199254740993 sits above 2^53 (9007199254740992), the largest integer float64 can represent exactly, so it silently rounds down to 9007199254740992.0, giving a false positive.

In 2.0 this raises: InvalidOperationError: 'is_in' cannot check for Int64 values in List(Float64) data. , users should explicitly cast to deal with lossy type conversion.

Strict concatenation

Horizontal concat will now check lengths instead of silently filling with null .

# Joining per-day transaction counts with per-day fraud-flag counts,
transactions = pl.DataFrame({"day": [1, 2, 3, 4, 5], "count": [120, 98, 143, 87, 156]})

# Upstream job for day 5 failed silently
fraud_flags = pl.DataFrame({"flagged": [2, 0, 5, 1]})  # only 4 rows

pl.concat([transactions, fraud_flags], how="horizontal")
shape: (5, 2)
┌─────┬───────┬─────────┐
│ day ┆ count ┆ flagged │
│ 1   ┆ 120   ┆ 2       │
│ 2   ┆ 98    ┆ 0       │
│ 3   ┆ 143   ┆ 5       │
│ 4   ┆ 87    ┆ 1       │
│ 5   ┆ 156   ┆ null    │  <- day 5 silently has no flag count
└─────┴───────┴─────────┘

In 2.0 this will raise with:

ShapeError: cannot concat dataframes with different heights in 'strict' mode

If padding is what you wanted, you have to explicitly opt-in to that with how="horizontal_extend" . Making that intention clear to the reader.

Removal of casts in favor of dedicated methods/constructors

Another one worth mentioning is the removal of many casts that were ambiguous or should be applied via their dedicated parsing expression, leading to one obvious way to parse data.

Enums/Categoricals <> integers.

pl.Series([None, 1, 0, 2], dtype=pl.UInt32).cast(pl.Enum(["a", "b", "c"]))
# ComputeError: casting from u32 to enum is not supported.

Use instead: .cat.to(dtype) for int → categorical, .cat.physical() for categorical → int.

Parsing Strings to temporal data-types

pl.Series(["2022-08-30"]).cast(pl.Date)
# InvalidOperationError: casting from string to date is not supported.

Use instead: .str.to_date() / .str.to_datetime() . These allow you to apply a parsing format, giving you more control over how the data is parsed.

These were just a few examples, but we landed many more strictness improvements. See them all in the migration guide.

Raising informative errors

We put a lot of effort into making sure you as user or your agent can continue if you used old parameters that are not supported anymore. We added two new typed exceptions for this; polars.exceptions.AttributeRemovedError and polars.exceptions.ArgumentRemovedError that handle removed attributes and methods and removed parameters respectively.

The error messages should point you to the new API instead. Below we show two examples.

>>> lf.melt(id_vars="a", value_vars="b")
polars.exceptions.AttributeRemovedError: `melt` was removed in version 2.0;
use `LazyFrame.unpivot` instead, with `index` instead of `id_vars`
and `on` instead of `value_vars`
>>> df.join(df, on="a", join_nulls=True)
polars.exceptions.ArgumentRemovedError: the argument 'join_nulls' for
'DataFrame.join' was deprecated in version 1.24 and has been removed
in 2.0.0. It was renamed to 'nulls_equal' in version 2.0.

Most of the removed functionality has been deprecated for a long time and hopefully should not have affected your pipelines if you have stayed up to date. Reach out to us if you think we should have kept some functionality you relied on.

Last words

Polars 2.0 is about better defaults (most importantly the streaming engine) and a better API. We hope this release is rather boring. We don’t gate new features behind major version bumps as we ship them as soon as their ready.

Don’t be mistaken, Polars 2.x will be much better than 1.x. There is a lot in flight that we haven’t talked publicly enough: proper out-of-core support for the streaming engine, a new IO-plugin design, what we think will be the fastest S3 reader out there, major SQL coverage improvements, a cost-based planner, join reordering, and the removal of mmap, which will make our pipelines fully async end to end.

Try the release candidate by installing pip install polars==2.0rc1 . Give it a spin and reach out to us here: https://github.com/pola-rs/polars/issues or contact us on discord: https://discord.gg/4UfP5cfBE7 .

Trump Lies That Medicare for All Would Cost ‘Entire Budget of the Whole Country’

Portside
portside.org
2026-09-03 01:16:06
Trump Lies That Medicare for All Would Cost ‘Entire Budget of the Whole Country’ Mark Brody Thu, 09/03/2026 - 01:16 ...
Original Article
Trump Lies That Medicare for All Would Cost ‘Entire Budget of the Whole Country’ Published

Members of National Nurses United rally with lawmakers to show their support for the Medicare for All Act on April 29, 2025 in Washington, DC. | (Photo by Chip Somodevilla/Getty Images)

US President Donald Trump railed against Medicare for All during an Oval Office event on Tuesday, falsely claiming the proposal would be prohibitively expensive and ineffective despite new research confirming it would save lives and cost significantly less than the corporate-dominated status quo.

The president’s remarks came during an event touting his limited, voluntary, and secretive agreements with leading pharmaceutical companies, deals purportedly aimed at lowering drug prices . Trump again lied by claiming that his efforts are “much bigger” than Medicare for All, which would provide comprehensive health coverage to every person in the US for free at the point of service, eliminating premiums, copays, and deductibles.

Trump said that Medicare for All, which has not been tried at a national level in the US, “doesn’t work,” falsely claiming a single-payer system would cost “the entire budget of the whole country” and send taxes into the stratosphere.

Nancy Altman, president of the progressive advocacy group Social Security Works and author of the forthcoming book, The Road to Medicare for All: A Call to Action , told Common Dreams on Wednesday that “Trump is once again revealing that he lies about healthcare or is totally ignorant of it.”

Total federal outlays were $7.04 trillion in 2025. According to a study published last month by Yale University researchers, a single-payer system like the one set out in Sen. Bernie Sanders ’ (I-Vt.) Medicare for All Act would save the US roughly $1 trillion per year in national healthcare expenditures, which totaled around $5.7 trillion last year. The finding was consistent with past research showing major savings under Medicare for All compared with the current privatized system.

“A universal healthcare system in the US would not require the country to spend more on healthcare,” the Yale researchers wrote. “It would require it to spend less. Our results indicate that the existing budget is more than sufficient to cover everyone at lower total cost.”

The study also found that Medicare for All would save more than 114,000 lives across the US each year by providing the tens of millions of uninsured and uninsured Americans with comprehensive coverage.

The researchers contrasted the life-saving impacts of a Medicare for All system with the deadly consequences of the unprecedented Medicaid cuts that Trump signed into law last summer. Experts at Yale and the University of Pennsylvania estimated that the sweeping Republican assault on Medicaid could cause more than 51,000 deaths annually as millions are kicked off the program.

“Numerous highly respected analyses show that improving Medicare and expanding it to everyone, with no premiums, copays, deductibles or coinsurance costs trillions of dollars less than what the nation now spends, while covering the entire population and saving lives,” Altman of Social Security Works told Common Dreams. “The question isn’t how will we pay for universal coverage, but how will we divvy up the savings.”

The House version of the Medicare for All Act, led by Reps. Pramila Jayapal (D-Wash.) and Debbie Dingell (D-Mich.), is cosponsored by a majority of the chamber’s Democratic caucus—though it’s opposed by the House Democratic leader, Rep. Hakeem Jeffries of New York. The Senate version of the bill, led by Sanders, has 17 cosponsors.

“We already introduced the legislation. Now we need the political will to pass it,” Jayapal said on Tuesday. “Healthcare is a human right. No one should go broke, or die, because they got sick.”

Jake Johnson is a senior editor and staff writer for Common Dreams.

Wondering How Nuts Trump’s Tariffs Are? Consider Aluminum.

Portside
portside.org
2026-09-03 01:05:15
Wondering How Nuts Trump’s Tariffs Are? Consider Aluminum. Mark Brody Thu, 09/03/2026 - 01:05 ...
Original Article
Wondering How Nuts Trump’s Tariffs Are? Consider Aluminum. Published

Tobias Nicolai/Connected Archives

The list of Canadian imports now subject to 50 percent tariffs in the United States includes steel, seaweed, ink, animal hides, dog leashes, saddlery, suitcases, plywood, knit hats (toques, to Canadians), floating docks, furniture, whiskey, honey and, of course, hockey sticks. But the tariffs on aluminum show most starkly the irrationality of President Trump’s trade war with our northern neighbor.

Canada shipped nearly $10 billion in aluminum products to the United States last year. The metal is used in construction, cars, furniture, drink cans and countless other things. Mr. Trump has every obligation to enforce trade laws and prevent other nations from taking unfair advantage of us. But the Canadian aluminum industry hasn’t bilked the United States. America needs aluminum to keep its auto plants running and to keep food and drink prices down, and Canada is just better at making it.

Aluminum isn’t cooked like steel; it’s made from alumina, a powder refined from bauxite ore and zapped with electricity until it renders into a metal. The electric bill alone can account for up to 40 percent of the manufacturing cost. When you think about trade with Canada, it’s useful to imagine aluminum not as a metal but as electricity in solid form.

With its abundant snow, lakes and rivers, Canada has huge hydroelectric power resources, often in sparsely populated areas. As a result, the country has lots of reliable, inexpensive electricity, which gives it an edge over the United States in aluminum smelting. Today there are eight smelters operating in Quebec and one in British Columbia, producing about 3.6 million tons of metal annually. The United States gets 60 to 70 percent of its imported aluminum from Canada.

The United States tried to develop a competitive domestic aluminum sector. It began to expand with the Tennessee Valley Authority, a Depression-era project that was a model for rural electrification initiatives across the country. Low-cost energy attracted increased investment in aluminum smelters, like the one in Alcoa, Tenn., the ultimate company town. Alcoa, founded in 1888 as the Pittsburgh Reduction Company, became the biggest aluminum smelting operation in the country. But the population grew after World War II, and in the second half of the 20th century the energy crises helped flip the cost calculus. Many American smelters shuttered.

Canada’s often less expensive, more reliable energy supply — nobody’s moving into northern Quebec to compete for it — proved decisive.

Since 1980, almost 30 American smelters have shut down, with companies typically citing inadequate guarantees about the supply and price of power as the reason. You can’t just hope that there’s enough juice to run the smelter.

Alcoa led the retreat to Canada. The company today operates three aluminum plants in Canada and has just two operational plants in the United States. It’s looking to sell some 10 of its shuttered or curtailed sites to the data center industry. One of its remaining smelters, in Massena, N.Y., depends on a New York State allocation of low-cost power and recently received several million dollars in incentives. Alcoa is investing nearly $60 million in the plant through 2028. Canada might call that a state subsidy — cheating — but without it, the company can’t operate competitively.

The closure of struggling American smelters means that the United States must import — and that the cost of tariffs is destructive to American industry. As of March, the automobile industry had paid more than $35 billion since 2025, thanks to tariffs on aluminum, steel and car parts and other items. This is money that carmakers could have spent on research and development or lowering car prices.

Mr. Trump wants to reverse history and create domestic manufacturing jobs in industries such as aluminum. He’s not the only one. The dream of increasing well-paying manufacturing jobs was what inspired states such as New York to shell out money to open factories and keep them in business. Alcoa’s plant in Massena pays $37.71 an hour for a general mechanic.

The president has largely failed, at least so far. Manufacturing jobs have declined in his second term. On aluminum specifically, Mr. Trump is promoting a $4 billion smelter in Oklahoma, backed by the United Arab Emirates-based Emirates Global Aluminum and Century Aluminum, along with $500 million in federal dollars and a couple of hundred million in state incentives, including tax breaks. This factory might get built, but few — if any — others will.

Even with all the incentives, building smelters in the United States isn’t all that appealing. Our electric grid is in terrible shape, electricity rates are rising, and the Trump administration is actively discouraging new sources of power, such as renewables. And no one knows whether Mr. Trump will waver on tariffs again. Try selling your board of directors a multibillion-dollar, two- or three-year investment on that basis. Emirates Global might be willing to shoulder the risk, but few other companies are.

It’s not cheating when Canadians undersell American aluminum producers. It’s an advantage. It’s logical for the United States to import lower-cost Canadian aluminum and invest in industries in which America enjoys its own advantages — chip design and artificial intelligence, for instance.

Who would flout this logic, trashing a 150-plus-year relationship with a close ally in a disruptive attempt to separate two interdependent economies? Oh, right.

Bill Saporito is an Opinion Editor for the New York Times.

London’s first self-driving taxis for hire hit the streets

Guardian
www.theguardian.com
2026-09-03 01:00:44
Wayve robotaxis added to Uber app and will have human in front ready to take over if needed – but only 15 cars licensed Londoners are now able to hire self-driving taxis for the first time, after rides in Wayve’s autonomous vehicles were added to the Uber app on Thursday. The chances of landing a ro...
Original Article

Londoners are now able to hire self-driving taxis for the first time, after rides in Wayve’s autonomous vehicles were added to the Uber app on Thursday.

The chances of landing a robotaxi on request immediately are slim, with only 15 vehicles so far licensed. That contrasts with the more than 100,000 private hire vehicles in the capital – roughly the same number of Uber customers who have registered to take autonomous rides.

The cars will still come with a licensed human driver sitting in the front seat, ready to take over the controls should the need arise.

Transport for London last month licensed Uber and the UK tech company Wayve’s modified Ford Mustang cars as private hire vehicles, whose conditions still require a safety driver supervising.

Regulatory approval for vehicles in fully autonomous operations without a safety driver needs to be granted under a separate government process and agency, the Driver and Vehicle Standards Agency, and is now seen as unlikely this year .

Nonetheless, Thursday’s launch marks a significant milestone and has allowed Uber to steal a march in the race by tech companies to bring driverless taxis into London, seen as a crucial market for a wider European rollout. Google-owned Waymo and the Chinese company Baidu are testing their robotaxis in the UK capital.

Wayve autonomous vehicles added to Uber app in London

Alex Kendall, the chief executive and co-founder of Wayve, said he was proud to introduce the company’s AI Driver technology to the public for the first time in London, “our home city and one of the most complex driving environments in the world”.

Kendall said the technology was “still maturing” but robotaxi services without a safety driver would come, although he declined to predict exactly when: “I don’t want to put a timeline on it, but we’re pushing as fast as we can.”

He said Wayve would be moving to “scalable manufacturer-produced vehicles” – new Nissan Leaf robotaxis with its technology – and needs to “validate the safety metrics on that platform”, as well as secure regulatory approval.

“We’re working on all three in parallel. As soon as they come together, we’ll launch [fully] driverless services,” Kendall said.

Wayve’s self-driving technology is based on an AI learning model rather than the mapping used by rivals such as Waymo.

Alex Kendall stood in front of a Wayve car wearing brown chinos and a dark navy blue shirt
Alex Kendall, Wayve’s co-founder, says the driverless technology is ‘still maturing’. Photograph: Graeme Robertson/The Guardian

On a brief autonomous test drive with the Guardian in Westminster this week, all passed smoothly, with Kendall notably pleased by the car deciding to pull away again and re-park after stopping in front of gates that other cars were attempting to pass through. “That was quite human-like – really cool,” he said. “We’ve done a lot work to make sure the car can park in appropriate spots that are socially acceptable.”

The cars will be hailed and unlocked through the Uber app. The driver will introduce themselves with an appropriately robotic script, explaining that they will no longer speak during the ride but can be requested to take over control of the vehicle if the customer prefers.

While they will be the first self-driving cabs for hire in London, fully driverless services are in operation in many cities worldwide, primarily in the US and China, as well as the United Arab Emirates.

skip past newsletter promotion

Uber partnered in launching Europe’s first commercial robotaxi service earlier this summer in Zagreb, Croatia, with a human driver onboard as in London.

Sarfraz Maredia, the head of autonomous mobility at Uber, said the London launch was “a major milestone in scaling safe, accessible AV technology in a city with some of the world’s most complex roads”.

He said: “The benefit for consumers should be, over time, that it’s both safer and cheaper. Today, nobody’s able to operate AVs cheaper than a traditional human-driven ride, so that’s going to take a while to prove.”

Maredia said Uber had heard concerns from drivers but said he believed they would not be put out of work: “One of the most common ones we hear from our drivers is: ‘Hey, I drive in this city and it’s very complex, and I don’t think this product is going to be able to compete with me anytime soon.’”

He added: “We always want Uber to be a platform where both human drivers and AVs can operate, and because the market and our business are still growing here we think that’s going to be true for a long time.”

Heidi Alexander, the transport secretary, said: “This is a major milestone for the future of transport in London, as British innovation brings this technology on to our roads and gives passengers more choice.

“Today’s announcement further cements Wayve’s status as a technology trailblazer here in the UK, and highlights how British innovation is helping drive investment and growth in transport.”

David McMullen, a senior organiser at the GMB union, said: “With hundreds of thousands of people employed to drive every day, we need to be really careful with the rollout of driverless cars unless we are prepared to see unprecedented levels of social and economic disruption.”

Under Israeli Settler Attacks, I Feel I Am Not Alive

Portside
portside.org
2026-09-03 00:53:49
Under Israeli Settler Attacks, I Feel I Am Not Alive Mark Brody Thu, 09/03/2026 - 00:53 ...
Original Article
Under Israeli Settler Attacks, I Feel I Am Not Alive Published

A paramedic transports an injured Palestinian into the Ramallah Governmental Hospital in the Israeli-occupied West Bank, following an attack allegedly carried out by Israeli settlers on August 30. | (Zain Jaafar / AFP via Getty Images)

In the West Bank village of At-Tuwani this July 19, Ruqayya Rabe’i, three months pregnant, lay in her room beside her four sleeping daughters. At 12:30 a.m., the first stones hit her home. She rushed to check the front door. There in the living room, she found her fifteen-year-old son, Usayd, sleeping directly below a window where, according to Ruqayya, several settlers were armed with guns and knives and trying to force their way in.

She tried to shake her son awake, but he didn’t stir. When the settlers noticed her, she fled, certain that if they saw him, they would shoot.

The window was shattered, a chemical compound poured through it, and the frame went up in flames, Ruqayya said. She called her husband, who was working in the nearby city of Yatta, frantic, believing at that moment that her son had been killed.

Her son, meanwhile, woke up to the flames and ran to find his mother. At the sight of him alive, Ruqayya collapsed from shock, unconscious. By the time an ambulance arrived, she could hardly crawl to the street — one hand on the ground, the other on her belly.

The attack was over in ten minutes. The perpetrators abruptly left the scene, leaving behind burned vehicles , vandalized homes with the Hebrew words for “revenge” and “house arrest,” and a destroyed mosque . But the effects on this family will be felt for a lifetime.

Numbering near forty according to residents, the mob of settlers had descended from an illegal outpost, Havat Ma’on, located just southeast of the Palestinian village. The settlers there have been terrorizing the Palestinians of At-Tuwani since the outpost’s establishment over two decades ago.

Impunity by Design

H avat Ma’on is one of over five hundred settlements and outposts across the West Bank, more than 165 of which have been established since October 2023 and all of which are illegal under international law. Settlers like those who attacked At-Tuwani are not acting in isolation but instead are instruments in a broader Israeli strategy of land-grabbing by force, backed by a state that encourages them every step of the way. Outposts such as Havat Ma’on are established illegally even under Israeli law yet are routinely legalized after their formation, rewarding settlers for occupying Palestinian land instead of punishing them for stealing it.

Settlers then face little to no legal accountability for their crimes against Palestinians and are further encouraged through extreme armament campaigns. Of the eighteen Palestinians killed by Israeli settlers and forces in the West Bank during the first half of 2026, no murderers have been convicted. According to a study by Israeli rights group Yesh Din, 93.6 percent of police investigations into settler crimes in the West Bank are closed without charge, and only 3 percent of cases lead to any actual conviction. Hundreds of thousands of Israeli settlers have received state-issued guns, in large part thanks to Israeli National Security Minister Itamar Ben-Gvir’s massive armament campaign since October 2023, relaxing already loose permit laws for Israeli citizens. Critics argue this “green-lights” the intensification of violence against Palestinians, using settlers as “private militias” to advance state land-grabbing goals under the pretext of civilian self-defense.

More than just a byproduct of Israeli policy in the West Bank, this violence is a weapon of the broader Zionist colonial project aimed at displacing Palestinians and consolidating de facto annexation.

An Accelerating Crisis

A mid unchecked impunity, accelerating settlement expansion and armament, and mounting crackdowns on Palestinians since October 2023, settler violence has reached an all-time high. A June 2026 United Nations Commission of Inquiry found that settler attacks had risen by 130 percent since 2023. The UN Office for the Coordination of Humanitarian Affairs (OCHA) recorded more than 1,330 attacks causing casualties or property damage across roughly 250 Palestinian communities in the first seven months of 2026, with attacks now occurring at a rate of around six per day. Around 880 Palestinians have been injured in the context of settler attacks this year, while eighteen have been killed — already surpassing the seventeen fatalities recorded throughout the full year of 2025.

Yet these figures capture only documented incidents. Much of the everyday violence shaping Palestinian life in the West Bank never enters official statistics. A 2026 report by Israeli settlement-monitoring groups Kerem Navot and Peace Now found that the vast majority of incidents, ranging from harassment and threats to physical violence, are never documented or counted by any authority. For communities living alongside expanding outposts, this intimidation and constant threats of attack have become part of daily life, and the recorded figures offer only a limited reflection of the reality they face.

“They do these attacks on the pretext of land defense,” Mohammad Hurani, an At-Tuwani resident and neighbor of Ruqayya, told us. “Every twenty-four hours something happens, and if something doesn’t happen, the people remain on edge.” During the July 19 attack on At-Tuwani, settlers attempted to set Mohammad’s house on fire and spray-painted the Hebrew word for “revenge” on an exterior wall. “We tried to defend ourselves, but they outnumbered us ten to one, so we couldn’t do much.”

Hurani explains that there has been a severe increase not only in the frequency of attacks but also in their intensity. Prior to October 2023, “settlers used to come in groups of three or four but now come in mobs of several dozen.” In documented cases, the Israeli military has protected settlers during attacks, joined them in raiding villages, or arrived at the scene only after the settlers have fled, as documented by various Israeli and international human rights groups. In At-Tuwani, Israeli military forces arrived approximately forty minutes after the settlers left, according to Mohammad. “[The military] began yelling, ‘You don’t belong here,’” he recalls. “Without taking any statements from us, they proceeded to Havat Ma’on to collect statements from the Israelis.”

OCHA estimates that 56 percent of total Palestinian injuries in the West Bank this year occurred in the context of settler attacks. Over 1,100 Palestinians have been killed in the West Bank by settlers and Israeli forces since 2023, according to the UN Relief and Works Agency for Palestinian Refugees in the Near East (UNRWA). Almost all perpetrators walk free. But the true cost of these attacks cannot be measured in numbers.

Following the attack in At-Tuwani, Ruqayya was transferred to Yatta Public Hospital, where despite doctors finding that the fetus had a weak heartbeat, she was discharged after an hour without treatment. Public hospitals across the West Bank have been operating under severe strain as the Israeli government continues to withhold over $5 billion worth of tax revenues from the Palestinian Authority, which would otherwise pay public sector employees and keep hospitals running, according to Deutsche Welle.

Suffering from emotional trauma and painful cramping through the following day, Ruqayya was brought to a private hospital in Yatta for testing.

At 5 p.m. on July 20, the fetus was pronounced dead.

“I feel I am not alive,” says Ruqayya. “He left before he could see the good things in this world, before we could even see him. Now he is gone.”

The attacks leave communities in a permanent state of vigilance. Ruqayya’s daughters still sleep in a room with no protective barriers, leaving her constantly worried about future attacks. “The sound of broken glass is still ringing in my ears. I’m afraid for my daughters — I can’t sleep.”

Yet in At-Tuwani, as across Masafer Yatta, fear has not erased resistance. Residents continue to rebuild damaged homes, accompany shepherds and farmers to their land, document attacks, and support families targeted by settlers. In communities where violence and intimidation aim not only to injure individuals but to drive Palestinians from their homes, remaining on the land has become an act of resistance.

An Election Without a Clear Break

T he months ahead may bring even greater pressure. Israel’s upcoming election is not the cause of the surge in settler violence, but it may intensify the forces already driving it. With Prime Minister Benjamin Netanyahu’s bloc facing the possibility of losing power, settler leaders and their political allies have incentives to consolidate territorial gains before any political transition.

Meanwhile, neither of Netanyahu’s leading opposition rivals are currently positioned to meaningfully challenge the structures enabling settler violence. While their policies differ in intensity, neither offers a clear break with the broader trajectory of settlement expansion and the displacement of Palestinians.

Although Gadi Eisenkot, a former Israel Defense Forces chief of staff who has surged in recent polling, has publicly condemned the “ violent lawbreaking by an extremist minority” of settlers in the West Bank, he has centered his campaign on security and governance rather than settlement and settler policy.

Naftali Bennett, a former Israeli prime minister running in alliance with centrist leader Yair Lapid under the Together (Beyachad) party, has traded the lead with Eisenkot throughout the campaign. As a former head of the settler movement’s main umbrella organization, Bennett opposes a Palestinian state outright and has publicly advocated that Area C, which comprises more than 60 percent of the West Bank, should “ultimately be part of the State of Israel.”

Electoral competition may therefore accelerate settlers’ efforts to establish further “facts on the ground,” with little indication of meaningful policy shift.

Beyond Condemnation

U ltimately, protecting Palestinian communities requires moving beyond condemnation and imposing material costs on those enabling their displacement. The targeted sanctions already imposed by the European Union and several Western governments are an important step, but they remain largely insufficient given the scale of ongoing settlement expansion and state-enabled violence. Governments should expand sanctions beyond individual violent settlers to the organizations financing illegal outposts and the government officials implicated in facilitating settler violence or forced displacement, including through asset freezes and travel bans.

They should also restrict trade, investment, and financial activity that sustains illegal settlements and halt arms transfers, given the inherent risk that they may contribute to serious violations. The UN Human Rights Office has identified 158 companies involved in settlement-related activities. Settlement expansion is sustained not only politically and militarily but through international economic networks that governments clearly have the power to change.

Still, pressure cannot come from governments alone. Individuals and civil society can also increase pressure through political organizing, divestment, and targeted boycotts. The Palestinian-led Boycott, Divestment, and Sanctions movement publishes regularly updated guidance identifying priority companies and institutions to boycott, divest from, or pressure based on their involvement in violations of Palestinian rights.

For Ruqayya, such measures would come too late. For other Palestinian families, they could decide whether Israeli violence and displacement continue, with almost no political or economic cost for the perpetrators.

Miriame Mazid is a writer and activist working on Middle East geopolitics, human rights, and humanitarian action.

Melodie Cochet is a writer and humanitarian working with nongovernmental organizations on Middle East policy and refugee empowerment.

The Postal Service’s Destruction of Democracy

Portside
portside.org
2026-09-03 00:46:04
The Postal Service’s Destruction of Democracy Mark Brody Thu, 09/03/2026 - 00:46 ...
Original Article

Marcin Golba/NurPhoto via AP Photo

Until the release of a whistleblower dossier on Monday, one could be relatively hopeful that a string of court decisions would prevent the U.S. Postal Service from carrying out Trump’s orders to slow-walk mail-in voting. As I wrote in this piece last Friday , U.S. District Court Judge Indira Talwani has enjoined the Postal Service from implementing its plans , pending a full hearing scheduled for tomorrow.

Now, however, a whistleblower lays out new alarming details. In a letter to Sen. Richard Blumenthal (D-CT), the whistleblower, described as a government official, explains how the Postal Service is rushing to build an online portal that will be used to screen ballots submitted by state election officials prior to USPS agreeing to mail them to voters.

According to the whistleblower complaint, building the information technology infrastructure necessary to complete the portal would normally take a year or more.  Yet, USPS leadership ordered that the portal be completed for a launch date of September 1, 2026. That was yesterday.

As a result of this rushed process, USPS has been unable to conduct tests of the portal to ensure its proper functioning, troubleshoot problems, or distribute instructions on use to state election officials. According to the whistleblower, the portal “violates standard principles of testing and debugging new software before launch.” Normal procedures at USPS for such systems include internal testing, customer acceptance testing, and a final development stage before release to end users. The portal has gone through none of these basic checks.

As Blumenthal points out, under the portal, “When ballots are submitted to USPS in large-volume batches, if any one ballot in the batch cannot be verified against the portal, all ballots in that batch will be rejected. For example, if a state election official brings a batch of 10,000 ballots to USPS and USPS is unable to match just one of those ballots against the portal—because, for example, someone has recently changed their name after marriage or they’ve moved—then USPS would refuse to mail the remaining 9,999 ballots as well.”

What’s clear is that if the system goes forward, it gives the Trump administration three possible ways to undermine the 2026 election. Either state officials are forced to comply with a buggy system that will lose millions of mail-in ballots. Or officials in some states will refuse to comply and the Postal Service will refuse to deliver their ballots. Or the sheer confusion and publicity will deter large numbers of citizens from voting. And complaints will be tied up in court until long after the election.

In 2024, roughly 48 million people voted by mail. They were disproportionately Democrats.

I have been skeptical of concerns that Trump will try to pull off some kind of Election Day coup by sending in ICE or the military to block voting. But the USPS slow-rolling coup, unless blocked by the courts, could do almost as much damage. It’s already the case that the Postal Service failed to deliver about 10,000 mail-in ballots in the Michigan Democratic primary in time for them to be counted, due to underfunding and incompetence.

According to the whistleblower, the USPS has continued work on the portal despite several court orders directing it to suspend its plans. In a letter to Postmaster General David Steiner on Monday, Blumenthal wrote , “Please state whether USPS has halted work to implement the Executive Order, in compliance with the August 27, 2026 temporary restraining order.” So far, he has received no reply.

But in a statement released Tuesday , the Postal Service seemed to be thumbing its nose at both Blumenthal and the courts: “The Postal Service is now finalizing the portal and will soon make it available to election officials who voluntarily wish to familiarize themselves with the platform,” the statement said. “USPS will also provide tools, presentations, and other resources to help election officials understand the platform and make informed decisions about whether and how they wish to use it.”

The Postal Service has only one duty: to deliver the mail. It has no legitimate role in elections.

The lower courts have been doing their jobs in blocking Trump’s postal scheme, but the Supreme Court’s coy pattern has been to allow illegal conduct to proceed, pending some final judgement that is often effectively moot by the time it is rendered. The most recent instance of this gambit is the Court’s 5-4 ruling to allow construction of Trump’s grotesque ballroom to proceed .

Enabling the desecration of the White House is bad enough. It would be far more serious if the high court enabled the postal desecration of our democracy.

The first postmaster general, you may recall, was Benjamin Franklin. When Franklin, emerging from the Constitutional Convention in 1797, famously told a bystander that the Founders had created “a democracy, if you can keep it,” he had no way of knowing that his beloved Post Office might be the instrument of democracy’s destruction.

Robert Kuttner is co-founder and co-editor of The American Prospect, and professor at Brandeis University’s Heller School. His latest book is Notes for Next Time: Surviving Tyranny, Redeeming America.

deforester - Logging for Janet

Lobsters
codeberg.org
2026-09-03 00:12:04
I also made a r7rs scheme version (which lacks some things, due to portability/unfinished standard). Comments...
Original Article

Deforester

# A program should set the logger towards the beginning:
(deforester/set-logger! {:write  eprint # actually defaults to these
                         :format json/encode})

(defn double [x]
  (try (do
         (def new-x (+ x x))
         (deforester/log :debug "doubling" # :level and :msg are positional args
           :input x :result new-x :outcome :success)
         new-x)
       ([err]
        (deforester/log :error "doubling" :outcome :failure 
          :input x :error (describe err)))))

(double "cat") # {"level":"error","time":"2026-07-11T18:18:31.040Z","input":"cat","msg":"doubling","outcome":"failure","error":"\"could not find method :+ for \\\"cat\\\" or :r+ for \\\"cat\\\"\""}

Deforester:

  • follows the modern, production approach goes from event (table) to processors to formating (table->string) to writing
  • falls back to stderr so logging fail won't crash
  • filters levels before evaluating args
  • outputs NDJSON (if json/encode set) consumed like jq . log.ndjson etc.

In web prod, most things print unbuffered event streams with the orchestrator aggregating them. However, for human scale personal computing or random programs run locally, logging to a file is often more handy, so Deforester offers file-writer :

(deforester/set-logger! {:write  (file-writer "log.txt")
                         :format deforester/text-format})

(defn check-price [item url]
  (def resp (http/get url)) # a la Joy
  (def price (parse-price (resp :body)))
  (when (< price 20)
    (deforester/log :info "price drop" :item item :price price))
  price)

Usage

Deforester exposes the following bindings: log , set-logger! , with-log-ctx , with-duration-logged , with-config , log* along with config helpers text-format and file-writer , file-writer-fast and key-renamer :

  • (log :warn "cat") takes level and message as position arguments, by default returning: {"msg":"cat","level":"warn","time":"2026-07-11T05:44:28.553Z"}
  • (set-logger! {:format text-format :write (file-writer "l.txt")}) makes (log :warn "cat") write time=2026-07-11T05:57:20.678Z level=warn msg=cat to log.txt
  • (set-logger! {:processors [(key-renamer {:time "@timestamp" :msg "message"})]}) makes (log :warn "cat") emit: {"@timestamp":"2026-07-11T08:14:16.968Z","level":"warn","message":"cat"}
    • :write can be a closure (prefered) or a file descriptor like stdout :
(with [f (file/open "app.log" :a)]
      (set-logger! {:write f})
      (log :warn "ok"))
  • with-duration-ctx adds a duration-ms to log calls it wraps
(with-duration-ctx
       (os/sleep .5)
       (log :info "fetched" :status :ok))
  • with-config is very useful for tests:
(def captured @[])
(with-config {:write |(array/push captured $)} # capture logs in a buffer
  (log :info "caught"))
(pp captured)

or even overwrite the :msg or :time for stable snapshot test results:

(def lines @[])

(with-config {:format         text-format
              :write          |(array/push lines $)
              :processors     [|(put $ :time "T")]}
  (log :info "user login" :id 7)
  (log :debug "noise")
  (with-config {:min-level :warn}
    (log :info "suppressed")))

(assert (deep= lines @["time=T level=info msg=user login id=7"
                       "time=T level=debug msg=noise"]))
  • with-log-ctx modifies the context in a fiber, including overwriting :time for tests:
(def tickers ["WAL" "EQX" "SODI"])

(with-log-ctx {:job-id 5} # small example
  (def done (ev/chan))
  (each ticker tickers
    (ev/spawn
      (with-log-ctx {:ticker ticker}
        (log :info "fetching" :len (length ticker)))
      (ev/give done ticker)))
  (repeat (length tickers) (ev/take done)))

### bigger example
(defn fetch-quote [ticker]
  (ev/sleep (* 0.01 (math/random))) # simulate work
  (if (> (math/random) 0.8)
    (error "connection reset")
    (math/floor (* 100 (math/random)))))

(with-log-ctx {:job-id 5}
  (def done (ev/chan))
  (def tickers ["WAL" "EQX" "SODI"])
  (each ticker tickers
    (ev/spawn
      (with-log-ctx {:ticker ticker}
        (def [ok r] (protect (fetch-quote ticker)))
        (if ok
          (log :info "quote" :price r)
          (log :error r))
        (ev/give done ok))))
  (def oks (seq [_ :range [0 (length tickers)]] (ev/take done)))
  (log :info "job" :total (length tickers) :failed (count not oks)))

Here is an example processor emulating Go's Zap , checking events/logs and forward some to a special location:

(defn reporter
  `Make processor sending events pred accepts via report-fn (e.g. a sentry client),
  passing the event through unchanged. Reporting failures never break logging:
  * (set-logger! {:processors [(reporter |(= ($ :level) :error) send-to-sentry)]})`
  [pred report-fn]
  (fn [e]
    (when (pred e)
      (try (report-fn (table/to-struct e)) ([_] nil)))
    e))

(defn send-to-sentry [package] (spit "bla.txt" (string/format "%j\n" package) :a))
(def q (ev/chan 1024))
(ev/spawn (forever (send-to-sentry (ev/take q))))
(set-logger! {:processors [(reporter |(= ($ :level) :error) |(ev/give q $))]})
(log :error :ok)
(log :error :ok)
(ev/sleep 0.1) # to let the blocked calls go through in REPL

Another useful processor:

(defn sampler
  `Make processor keeping only every n-th event per [level msg] pair:
  * (set-logger! {:processors [(sampler 100)]})`
  [n]
  (def seen @{})
  (fn [e]
    (def k [(e :level) (e :msg)])
    (put seen k (inc (get seen k 0)))
    (if (= 1 (mod (seen k) n)) e)))

How to Log

A logging library can only make it easy to emit good events, but the consumer's taxonomy design of what events exist, how they're named, with what fields etc. is where all the benefit comes from. Writing useful events demands much discipline.

For personal stuff, just toss :time , :level , :msg and domain info in a file after filtering.

  • log wide events with outcomes not actions - show a full unit of work showing what happened (not starting, doing, finishing x)
    • events should answer what happened to what and why with what result (if the site lacks all such context, the log should be emited higher up the chain)
    • if a unit of work somehow spans multiple events, include a single id to rejoin them together (hence with-log-ctx )
  • log decisions with reasons - if something different happens (retry, skip) explain why :reason :already-present
  • use consistent key names (with a glossary in the readme)
    • msg should be an event name; details should go in other fields so jq select(.msg == "fetched") works
    • keys should hold values like :status 429 instead of prose :msg "got status 429"
    • measure :ms duration (besides :time ) whenever doing i/o, latency drift's often a first symptom
    • keep set of keys and :msg names small, their values should exhibit variation
  • relevant metrics create business value; queries over good logs are metrics
    • include success too (to have a denominator to calculate rates and generate business metrics like duration and customer quotas)
    • guard with expectation/plausibility checks so 200 's with garbage don't pass through
  • if code should act on something, it belongs in a table/file and logs should just show the point of discovery. Log observations, keep facts in "state" (don't make the logs into a db)

People disagree on what keys to use:

  • zerolog: time , level , msg
  • zap: ts , level , msg
  • elastic common schema: @timestamp , log.level , message
  • OpenTelemetry specifies TimeStamp , SeverityText , Body , Attributes

Or durations: with-duration-logged currently has :error (message), :duration-ms and :outcome which can be :success or :failure

  • OTEL handles this via spans with exception.message ​ and status.code which can say OK or error
  • ECS has message​ , event.duration ​ (in nanoseconds), error.message ​, log.level​ and event.outcome ​ which can be success or failure
On levels

Levels conflate how much attention something deserves with a value to filter on. Alternatives to level systems mostly exist to try to deal with this:

  • verbosity -v or -vv or v(3) but what does verbosity 3 even mean?
  • tag sets like {:anomaly :external :retryable} are very expressive but lead to taxonomic explosion and turn filters into queries
  • no levels at all (event streams etc.) leave everything to the reader - storage prices can add up but useful with good queries and metric collectors, bad for personal stuff
  • OTEL or syslog severity numbers and named aliases adhering to specific interop

My suggested levels focus on attention and audience:

  • :debug helps investigate an issue (discarded normally)
  • :info describes normal operation (should be short for a healthy system)
  • :warn shows unexpected things handled well (e.g. retry succeeded, fallback, skipped input, approaching quota) (so expected external failures belong here (or maybe :info ))
  • :error shows unrecovered failures (which a person should look at)

When you want to add more levels, perhaps do e.g. :topic :audit to keep category distinct from attention. :topic is a useful field.

I Think the Military Commissary Freezers Were Hacked

Lobsters
signalandsilence.substack.com
2026-09-02 23:20:07
Comments...
Original Article

Originally published: Aug. 28, 2026 at 1:18 p.m. PT.

Last Updated: Sep. 1, 5:55 pm PT

Since publication, Stars and Stripes, Military Times/Navy Times, and multiple others have independently reported on the multi-base refrigeration failures, with the Pentagon now acknowledging a “possible refrigeration disruption” at numerous DeCA commissaries.

Near-simultaneous refrigeration failures or significant issues impacting at least six military installations have now been confirmed through official sources during the last few days, with additional independent confirmation of multiple other incidents.

Self-aware enough to know this sounds insane, but I need you to stick with me.

Not one freezer, not one grocery store, not just ANY grocery store, either.

The refrigeration systems at military commissaries (tax-free grocery stores for military personnel and their families located on bases across the country) appear to be under some type of siege; either their own aging fleet of equipment is deciding to seppuku in perfect harmony, or by something (or someone) more nefarious.

Where to even begin?

Flipping through my normal rotation of social media, I started seeing scattered posts lamenting the commissary suddenly losing their entire refrigerated & frozen sections.

All cold food spoiled, or removed from shelves.

Unfortunate and wasteful, I thought, but inconsequential to me personally. I don’t shop there, I have no stake in the availability of my frozen favs, plus the commissary is not exactly known for smoothly functioning operations, thus, moving on.

But then I saw another post, and another… with a chorus of comments

huh, how odd, the same thing is happening here.

What are the chances !

The pattern caught my attention, and what followed was a deep dive into military social-media chatter, commercial refrigeration, defense procurement contracts, and network security refreshers in an attempt to resurrect the rudimentary cybersecurity knowledge my degrees required.

‘Twas never my strongest subject. When would I ever need to use this , I distinctly remember thinking. (Freezers didn’t have networks, in the olden days)

At the time of initial publication, I identified 14 commissary refrigeration/freezer outage reports attributed to the following military installations across 11 states on August 26–27. Subsequent additions denoted by asterisk, Reports later determined to be unsupported/unrelated remain struck through for transparency.

  • Fort Huachuca (Confirmed)

  • F.E. Warren AFB (Confirmed)

  • Fort Irwin (Confirmed)

  • Columbus AFB (Confirmed)

  • Naval Station Newport ( Confirmed Aug. 26; Restored Aug. 29)

  • *Travis AFB (Confirmed)

  • NAS Lemoore (Independently Confirmed; Restored Aug. 28 per Commissary employee)

  • *Port Hueneme (Independently Confirmed)

  • Little Rock AFB

  • Dyess AFB (Independently Confirmed; Restored Aug. 29 per Commissary employee)

  • Holloman AFB

  • Robins AFB

  • McConnell AFB

  • Cannon AFB

  • Fort Meade (Removed; operating normally per local as of Aug. 28)

  • Camp Lejeune ( Removed: official outage notice initially identified as current was actually from 2025)

To be very clear: I do not have evidence that the Defense Commissary Agency was hacked.

What does exist is evidence that something odd is happening, plus a whole lotta explanations for how a cyber incident of this magnitude is technologically possible, and that there may be much larger implications than a dearth of cold veggies.

Unfamiliar to me prior, and I say that intending no offense to you (lovely, I'm sure) Fort Huachucans; the Cochise County, Arizona base has captured my attention today.

On August 27th, the official U.S. Army Fort Huachuca Facebook account announced that an overnight equipment failure caused ALL of the commissary’s freezers to enter defrost mode , spoiling everything inside.

This wasn’t a case of simply a power flickering and ice cream melting, because someone commented just that. Fort Huachuca responded from its verified account:

“the power didn’t go out”

Another questioned whether all of the food was really “spoiled” if the freezers had simply stopped working.

The installation clarified that, no, the freezers hadn’t just shut off. They had entered defrost mode, which heated the food .

That is a very different problem and I’m fully invested at this point. Buried in the largely useless comments, I unearthed what felt like a gem:

“I was told that it was a network issue.”

Unverified Facebook comment; included because it prompted the RMCS question, not as evidence of a cause

This commenter claimed that Huachuca’s cold-storage equipment had been replaced relatively recently, and that refrigeration and HVAC were remotely controlled through DeCA.

That is a random Facebook comment, from an unverified individual. It is not evidence that this was a network problem. But naturally, I absolutely had to know whether the second part was even possible .

Unfortunately for my productivity, it is.

I learned that commissaries (of which there are ~235 worldwide) aren’t actually independently operated by whatever military installation or base they happen to sit on.

They’re run by the Defense Commissary Agency (DeCA), an agency seated within the Department of Defense.

DeCA, as expected, has a whole refrigeration-control infrastructure.

In March 2026, DeCA issued procurement documents seeking support for “Facilities Maintenance, Call Center Support, and Remote Monitoring Control System (RMCS) Management.”

It covers approximately 182 DeCA locations , encompassing all 14 on my original list.

That alone doesn’t mean anything, however. They’re DeCA stores… of course they’re in a DeCA facilities document.

What matters is what the system actually does.

With some cursory control+F digging through DeCA’s titillating refrigeration engineering specifications , bingo.

“Defrost shall be controlled through the RMCS”

Which brings us back to Fort Huachuca.

Every freezer entered defrost mode.

The installation itself says the power didn’t fail, and that defrost actually heated the food.

DeCA’s own engineering documentation says defrost is controlled through its refrigeration monitoring/control system.

Another DeCA refrigeration contract describes Refrigeration Monitoring and Control Systems (RMCS) located at individual commissaries whose refrigeration and HVAC alarms are monitored remotely 24/7.

Per the contract, the contractor was required to maintain a “master control system for all of the RMCS” somewhere in the continental United States.

Important caveat, because this is where it’s really easy to jump ahead (spoken by a professional jump-aheader): this does not mean someone at DeCA headquarters can remotely hit a proverbial DEFROST EVERY COMMISSARY button. It establishes centralized monitoring infrastructure.

Exactly how much remote control exists, where current master systems are hosted, and whether affected stores share equipment remains unclear. Publicly available information is limited here, and it’s not exactly a hotly discussed topic, as you can reasonably imagine.

But we can establish networked control at individual commissaries independently.

The contractor that allegedly built the newer commissary at Robins AFB , one of the installations with reported problems, describes the building as having RSMS controls managing all of the store’s refrigeration and HVAC systems.

Again: centralized refrigeration control is not suspicious. It’s (apparently) how modern supermarkets work.

What it does is change the options for what a “freezer failure” can mean.

At Holloman AFB , someone posted the printed notice hastily taped to the blocked off, empty refrigerated section of their commissary:

A printed note by Holloman AFB Commissary Management reads:

“Due to an unexpected refrigeration system failure, all chilled and frozen merchandise is temporarily unavailable for purchase until further notice.”

The person submitting the photographs said they’d experienced power outages there before, but this event took out all of the refrigeration systems .

The sign and empty cases are considerably harder to argue with.

Fort Irwin publicly acknowledged its refrigeration problem as well, with similar DIY signage and bare shelving visible.

Naval Station Newport also officially announced restricted commissary sales due to refrigeration-system issues, however they opted to go with a (dated?) picture of fully stocked shelves. I appreciate the variety.

Then there’s Dyess AFB , where another poster supplied a photograph taken that morning showing an entire commissary meat case emptied and closed off after someone reported that the Dyess commissary refrigeration was down.

Robins customers reported produce and meat being covered and unavailable.

Little Rock gets stranger.

A local community page reported that the commissary’s refrigerated systems went down at approximately 2 a.m., affecting chilled, refrigerated and frozen merchandise.

Then an anonymous submission to a large Air Force community page claimed:

“I overheard employees discussing that the system was hacked last night”

Do I know that those employees actually said that?

Nope.

Do I know whether the employees would know the cause even if they did?

Also no.

Columbus AFB issued an official notice acknowledging freezer and chillers experienced an outage.

The official DeCA page for Travis AFB posted an August 26 notice stating that “refrigeration issues” had made some frozen and chilled items unavailable and temporarily affected Click2Go operations.

Moving south, F.E. Warren AFB acknowledged a malfunction as well.

In addition to the official statement, I found an anonymous submission to a popular military social media page from someone claiming to work at the F.E. Warren commissary. They wrote that its freezers, and apparently those at 14 other bases, “quit working or reversed to heating.”

The commenter claimed one deli freezer registered 180 degrees and another 160.

I have no idea what those numbers mean. Case temperature? Defrost heater? I am emphatically not reporting that food reached 180°F, but the “14 other bases” part stuck out.

Because once I started counting, I got the same number.

On August 9, 2026 , industrial cybersecurity researchers at Claroty’s Team82 published an article titled “Freeze the Controller, Defrost the Food: Uncovering Vulnerabilities in Danfoss Refrigeration Controllers.”

Yes, that is the actual title.

The researchers examined the Danfoss AK-SM 800A , a supervisory controller used to centrally manage commercial refrigeration systems. And what did they find?

Vulnerabilities capable of allowing serious unauthorized access .

Before anyone screenshots that paragraph and runs away with it:

I have not established that Fort Huachuca uses a Danfoss AK-SM 800A.

I have , however, found a searchable copy of a DeCA equipment inventory list identifying a Danfoss AK-SM880 refrigeration monitoring/control system at NAF El Centro - notably, not one of the commissaries on my affected list.

So, Danfoss AK-SM technology exists within the DeCA environment.

Interesting, but not attribution.

Claroty published a second refrigeration investigation on the same day, this time, about something called the Copeland XWEB Pro supervisory controller ( $5,509 + shipping, in case you’re in the market; fair warning, this isn’t exactly a glowing sales pitch).

They found 23 vulnerabilities, 21 rated ‘high severity’ , and ultimately demonstrated the part I actually care about: After compromising the supervisory controller, they could physically manipulate the refrigeration equipment.

Copeland itself already issued a security bulletin acknowledging vulnerabilities and explicitly advising customers never to expose the control system or its web interface to the broader internet .

So: Can someone actually hack a commercial refrigeration controller and make it do things?

Yes.

No. Too early to call it that.

And this is where I am currently stuck.

A common software or configuration problem, update-gone-wrong, a communications failure, or some boring DeCA-wide maintenance issue could explain it too.

A bunch of unrelated aging refrigeration systems deciding to off themselves during August is also not exactly unimaginable. DeCA’s own March procurement specifically identified aging infrastructure as something it is trying to manage. If you’ve ever shopped at a commissary, you can attest to the fact that the facilities are not what I would call top of the line boutique shopping experiences.

There are also historical examples of commissary refrigeration outages. Refrigeration equipment does, in fact, break.

But the thing I can’t get past is Fort Huachuca’s failure mode .

Not: the freezer compressor died.

Not: the power went out.

Not even: the refrigeration system stopped cooling.

Every freezer went into active defrost.

The function that did it, per DeCA’s own engineering documents, is controlled through the RMCS.

This is not proof of a cyberattack, but it is quite a series of coincidences.

There is still no public evidence that the affected stores share the same RMCS vendor, controller, firmware, contractor, or network.

This is where we have to talk about the Internet of Things (IoT), because if I had to think about how the internet works inside a grocery-store freezer today, you do too.

We’ve spent years connecting everything to networks because, obviously, being able to monitor and control stuff remotely is convenient. We’ve seen Wall-E.

Your printer, camera, washing machine, smart ring, toothbrush, car, and so many more create the IoT. In-store refrigeration systems are, apparently, also things that we have connected to computers. How progressive.

The con? Every time we make an object network accessible, we create a potential way to exploit it.

Remember that Copeland experiment from back yonder? Once Claroty compromised the supervisory controller, they could remotely set the compressors, cooling fans, or defrost cycle, heating or cooling what’s inside.

That is the important part.

The computer doesn’t have to “hack” the freezer in some sci-fi sense. The computer is supposed to tell the freezer what to do.

Claroty’s separate Danfoss investigation found security bypass and remote vulnerabilities in another commercial refrigeration controller, plus thousands of its management interfaces exposed to the public internet.

Again, none of this is proven to be connected to DeCA.

I seem to have picked an exceptionally timely week to become concerned about industrial controllers.

On August 19, only eight days before Ft. Huachuca announced its freezer failure, the NSA and its partners warned that cyber actors are currently conducting “targeted reconnaissance and capability development” against U.S.-based industrial controllers . Targets include energy, water, manufacturing, food production and commercial facilities.

Their concern is also physical: successful exploitation could cause equipment damage, downtime, potential harm to health and life, as well as disruption of industrial processes .

Different equipment. No demonstrated connection to DeCA.

But suddenly, my concern about computers making physical equipment, ya know, do things feels exceptionally timely.

This is where my silly little freezer saga collides with actual national security.

The 2026 National Defense Strategy identifies cyber capabilities among the growing direct threats to the American homeland.

In June, the Department of Energy warned that nation-state adversaries are actively pre-positioning inside U.S. critical-infrastructure networks , while other actors increasingly target the OT/industrial-control systems that make physical equipment do things .

Obviously, losing frozen meals is not the same as losing the power grid.

But network-connected software controlling physical infrastructure?

Same security problem, considerably lower stakes.

There is a possibility my security-trained brain can’t tune out when thinking about what the purpose of an incident like this could be.

Well, we already know one answer is in the playbook: Reconnaissance and pre-positioning.

A 2024 Joint Cybersecurity Advisory from CISA, NSA, FBI and international partners concluded with high confidence that Chinese-sponsored ‘Volt Typhoon’ hackers were positioning themselves inside U.S. critical infrastructure networks.

Why?

To enable future disruption.

The agencies confirmed compromises across communications, energy, transportation and water systems. The hackers gained access, and then conducted extensive reconnaissance to understand victim networks. In some instances, they maintained access for at least five years.

That sounds considerably less theoretical.

I am absolutely not saying China hacked the commissaries.

But if this ultimately proves to be a cyber incident rather than a mundane hardware failure, the national-security question wouldn’t just be who wants to ruin frozen pizzas?

It would be whether the refrigeration failures had anything to do with access to a mundane piece of network-connected infrastructure operated by a DoD agency, and if so, what the purpose of that access was.

A freezer is relatively low-stakes. Access controls, utilities, HVAC, water systems? Not so much. Different systems, obviously, but the same broader security problem: physical infrastructure sitting behind network-connected controls.

Speculative, but not an entirely hypothetical threat.

Because the timing of this all wasn’t already odd enough: On August 26, the DOJ and FBI announced the seizure of infrastructure belonging to a PRC state-sponsored hacking group, QTFY.

The NSA advisory released alongside it is perhaps even more interesting.

QTFY’s QScan wasn’t merely infecting IoT devices. NSA describes it as a reconnaissance and exploitation platform used to find vulnerabilities in networks , while QTFY used compromised IoT devices themselves to disguise subsequent hacking activity.

The group has targeted the Defense Industrial Base , and DOJ says targets included NASA, DOE, the Federal Reserve, DOJ and the U.S. Senate, alongside power companies and defense contractors.

Its customers? China’s Ministry of State Security and PLA, among others.

Again: zero evidence connects QTFY to DeCA.

But two days ago , on August 26th, the NSA was quite literally warning about a PRC state-sponsored group using IoT devices and vulnerability-scanning tools to target military-adjacent and critical infrastructure networks.

So, forgive me for continuing to have questions about the freezers.

I decided to exercise my God and country-given right and ask for the boring paperwork, which I’m sure will be produced to me in a timely and reasonable fashion.

/s, of course

I’ve put together requests to DeCA for the Fort Huachuca refrigeration work order, RMCS alarm/event records, maintenance findings, and whatever root-cause determination exists.

I’m also requesting records concerning whether DeCA identified a common technical problem affecting multiple commissaries during August - including network, controller, software/configuration, or cybersecurity incidents.

Most importantly, I want the equipment inventory. DeCA maintains remarkably detailed equipment records, and ideally I can get my paws on the RMCS/controller manufacturer and model for every commissary , not merely those on my list.

Because then, this becomes testable.

If affected commissaries disproportionately share a controller, firmware iteration, contractor, or recent change? That becomes quite interesting.

If 90% of DeCA uses the same controller, finding it at affected stores tells us basically nothing.

And, if the maintenance logs come back relay failed/compressor died/lost refrigerant/blown fuse across unrelated stores, my little theory dies an appropriately boring death and I begin my apology tour.

Sorry in advance (just in case).

For right now, “DeCA was hacked” is not a substantive enough argument to make, however I'd be lying if I said it wasn’t still my hunch.

Publicly, I'm not one for frivolous claims. So I'll take off my tin hat for you, dear reader, and stick to what is supported:

At least six military installations across the country have now officially acknowledged refrigeration/freezer failures or significant refrigeration issues during the same general period, with additional incidents reported elsewhere. At least one involved every freezer entering a defrost state while power remained on; DeCA engineering specifications state that defrost is controlled through the RMCS. A cybersecurity incident remains a plausible hypothesis, but there is not yet enough evidence to support that fact.

So, that was today’s deep dive. This is perhaps the longest my brain has idled on refrigeration-related topics. Unfortunately, I need the government to answer my FOIA request in order to free myself from The Pointed Questions That Persist, as I call them… and we all know how quickly that goes.

As I stood in front of my own freezer while making dinner, I caught myself pondering the network security risks of those ridiculous fridges with the integrated wifi-enabled touchscreens.

Every day, I draw closer to becoming a luddite.

Chat soon,

M. Elizabeth

September 1:

Well, this got interesting.

Stars and Stripes reports three military criminal investigative agencies are investigating the outages. Army CID’s Cyber Field Office and the Air Force Office of Special Investigation s confirmed active investigations, with the Defense Criminal Investigative Service (DCIS) reportedly taking the lead.

None of them have said what they are investigating, or whether unauthorized access or a cyberattack is suspected.

So, no, this does not mean I was right (yet).

It does, however, mean this has officially attracted the attention of federal agents who investigate malicious cyber activity. This is not the response team you’d expect to see if it were a simple power/hardware/quality control issue.

I regret to inform you that I will continue to watch the refrigerators.

August 29:
  • A Fort Irwin Facebook post says DeCA and Ft. Irwin techs are still working to repair the commissary’s refrigerators and freezers, describing the issue as part of a “situation that has impacted grocery stores across the country.” It is unclear whether the installation is referring specifically to commissaries, or grocery stores more broadly based on wording.

  • A Port Hueneme shopper confirmed to me photos showing empty cases were taken Aug. 27, while a commissary employee confirmed by phone that the store’s refrigeration remains offline without a known restoration date.

  • A Dyess AFB commissary employee confirmed by phone refrigerators were working and stocked, but being monitored closely.

Aug. 28, 2026:
  • I’ve submitted 3 FOIA requests to DeCA seeking Fort Huachuca’s RMCS event/alarm logs, work orders and root-cause findings; records concerning any common cause among the recent refrigeration failures; and DeCA’s existing inventory of RMCS/refrigeration-controller equipment across commissary locations.

  • Updated to include DeCA’s Aug. 26 notice confirming refrigeration issues affecting frozen and chilled inventory at Travis AFB Commissary. The confirmed count is now six installations.

  • Fort Meade remains unverified. A source who visited the commissary Aug. 28 found the commissary operating normally; I have not independently confirmed the earlier reported outage.

  • DeCA’s Camp Lejeune page now reports a “service outage of several freezer units” and says the commissary is working with DeCA Headquarters to bring the units back online, however this notice appears to be on a dated, duplicated DeCA site ( old , new ). Removed from count, confirmed total remains at six.

    DeCA MCB Camp Lejeune commissary page , accessed Aug. 28, 2026.
  • I received an (unverified) tip that Port Hueneme’s refrigeration is also disrupted. No official confirmation discovered.

  • Fort Irwin’s Facebook post states “Working diligently to troubleshoot and resolve the refrigeration issues…no estimated time for completion”

  • The Pentagon has now acknowledged a broader problem, telling Military Times that DoD is aware of a “possible refrigeration disruption at some Defense Commissary Agency commissaries.” Officials have not disclosed the cause or whether the incidents are connected

  • Earlier reporting: Stars and Stripes (attributes this investigation)

  • Earlier in the year, DeCA signed incumbent maintenance contractors were retained for the majority of Commissary location through 2026 because of their store-specific knowledge of historical maintenance, repairs and replacements…knowledge that may reasonably also reside with sub/local contractors partners working under those prime contractors.

  • Stars and Stripes spoke with Aldevra, a DeCA refrigeration vendor, which said it received no service calls related to the outages, and that the refrigerators it supplies to DeCA aren’t network-connected themselves, though separate remote-monitoring systems can be added (as suspected). This reinforces a connectivity theory and reduces likelihood of a large-scale physical hardware malfunction.

  • An anonymous inbox sent to @ AFamnncosnco alleges a refrigeration incident at Vance AFB ( Unconfirmed). No public statement by official sources available at this time.

  • A NAS Lemoore commissary employee confirmed by phone that its refrigeration system returned to normal operation today (Aug. 28).

Further Reporting:

Discussion about this post

Ready for more?

Wk. 6 of Vibecoding an MMO

Hacker News
eldermyr.com
2026-09-02 23:13:54
Comments...
Original Article

One realm · Everyone online

Step in. The realm never closes .

A free multiplayer action-RPG you play in your browser. Level a hero, delve, and hold the frontier together.

Play now Field Guide · who drops what

No download Starts in seconds

Pick up where you left off

Welcome back. The realm didn’t wait .

Nothing to set up. Step straight back into the world you already know, right where you left off.

Continue playing Field Guide · who drops what

Same hero Same realm No wait

Security Incident – BGP Hijacking – Virtualizor

Lobsters
www.virtualizor.com
2026-09-02 22:07:30
Comments...
Original Article

Security Incident – BGP Hijacking

Summary

Between 28 August 2026 at approximately 20:57 UTC and 30 August 2026 at approximately
06:10 UTC
, a block of IP addresses used by Softaculous services ( 162.55.80.0/24 , part of our
infrastructure at Hetzner) was affected by a BGP hijack : an unauthorized announcement of that address space by an unrelated network, which diverted internet traffic destined for those
addresses to a server operated by an attacker. The attacker obtained a technically valid TLS
certificate
for our domains, so connections affected by the hijack showed no certificate
warning.

The affected addresses served, among other systems, our software update endpoint , our
client area / billing site.

We have confirmed that a malicious Virtualizor update package was delivered to a small number of installations that checked for updates while their traffic was being diverted. This affected a handful of servers rather than the general Virtualizor user base. Because the malicious responses were served by the attacker’s system and never reached our own logs, we cannot produce a definitive list of affected servers, so every Virtualizor operator should carry out the checks in the If you run Virtualizor section. We have not
identified a malicious package for any other product; that investigation is ongoing.

Routing has been fully restored. We have reconstructed the incident minute-by-minute from public routing data; the complete measurement table is included below.

What happened

Traffic between networks on the internet is routed using BGP (Border Gateway Protocol), a
system that has historically relied on networks trusting one another’s route announcements. In a BGP hijack , a network announces IP address ranges it does not control, and traffic for those
addresses is drawn toward it.

At approximately 20:57 UTC on 28 August 2026 , the network AS62390 (NexonHost) began
announcing 162.55.80.0/24 — a portion of Hetzner’s address space containing IP addresses for a number of Softaculous systems — without authorization, routed through the transit provider
AS6204 ( Zet.net ) . This announcement was more specific than Hetzner’s normal announcement of the surrounding block ( 162.55.0.0/16 ), so under standard BGP route selection it took precedence on every network that accepted it . The announcement retained AS24940 (Hetzner) on the AS path as the apparent origin.

The attacker’s server was able to obtain a valid TLS certificate from a public certificate
authority (Let’s Encrypt) for our domains, because the certificate authority’s automated
domain-ownership validation was also routed through the hijack. Connections affected by the hijack therefore did not show a browser or client certificate warning. The certificate
covered domains across our products, including virtualizor.com , api.virtualizor.com and
files.virtualizor.com ; the full list is in Appendix A.


Timeline

All times UTC. Start and end times are corroborated by public RIPE routing data, not only by
provider reports.

When Event
28 Aug, ~20:57 AS62390 begins announcing 162.55.80.0/24 without authorization, via AS6204. Because it is more specific than the legitimate route, it wins route selection wherever it propagates, and traffic to the affected addresses is diverted.
28 Aug ~21:00 - 29 Aug ~08:50 First wave. The unauthorized route is accepted by essentially every internet vantage point that receives it. The route is highly unstable and flaps continuously throughout.
29 Aug, ~08:00-08:50 Active interception independently confirmed: a host on the diverted route answers for Softaculous domains using the fraudulently obtained but technically valid certificate.
29 Aug, ~08:50 After we report the hijack to Hetzner and escalate repeatedly, Hetzner begins announcing 162.55.80.0/24 directly. Diversion drops to zero within minutes.
29 Aug ~09:00 - ~20:00 Lull. Roughly 11 hours with essentially no diversion — first because Hetzner’s direct announcement holds, then because both the hijacked and the corrective /24 are withdrawn and traffic returns to the legitimate /16 .
29 Aug ~20:00 - 30 Aug ~06:00 Second wave. The unauthorized announcement resumes for roughly 10 hours, again accepted by essentially every vantage point that receives it.
30 Aug, ~05:50-06:10 The unauthorized route is withdrawn and normal routing is restored globally.
30 Aug, 06:10 onward No further diversion observed. Verified clean in public routing data through at least 30 Aug 10:00 UTC.

How widespread it was, and how we measured it

Method. RIPE’s Routing Information Service (RIS) operates 368 collector peers — a sample
of mostly large transit and internet-exchange networks around the world. For each 10-minute mark across the incident we retrieved the reconstructed routing table for 162.55.80.0/24 and
counted, among the peers that held a route to the prefix at that moment:

  • Diverted — best path traverses AS62390 (the hijacker);
  • On clean /24 — best path is a legitimate /24 (Hetzner origin, no AS62390); this only
    exists once Hetzner began announcing the /24 directly as a countermeasure;
  • Peers with no /24 route fell back to Hetzner’s normal 162.55.0.0/16 and were not
    diverted.

The share of RIS peers whose best path traversed the hijacker is the standard proxy for the
share of the internet whose traffic to this address range was sent to the attacker. It is a
routing-topology measure, not a byte count.

What we found.

Measure Value
Incident window 28 Aug 20:57 UTC -> 30 Aug ~06:10 UTC (~33.3 hours)
Distinct RIS peers that carried the hijacked route at some point 368 of 368 (the entire RIS peer set)
Peak diversion while a wave was active ~100% of peers holding a /24 route — median 266 , range 145-272 — i.e. ~72% of the full 368-peer RIS set
Origin AS shown in every single snapshot AS24940 (Hetzner) — the hijacker kept the real origin on the path tail and never appeared as origin itself
Time-weighted average diversion over the full 33 h ~ 28% of all 368 RIS peers / ~ 65% of route-carrying peers, at any given instant
Sustained waves Two: 28 Aug ~21:00 -> 29 Aug ~08:50, and 29 Aug ~20:00 -> 30 Aug ~06:00
Gap between waves ~11 hours of near-zero diversion (29 Aug ~09:00-20:00)
Route stability Highly unstable — ~10,600 route withdrawals recorded in the window; transit-provider flap dampening repeatedly suppressed the route

What this means in practice. Whenever the unauthorized route was propagating, a server had
roughly a 72% chance (by this proxy) that its network was sending traffic for
162.55.80.0/24 to the attacker — this was a broadly visible hijack, not a localized one,
because a more-specific announcement beats the legitimate route everywhere it reaches. However, the route flapped continuously, so for any individual server the diversion was intermittent across the roughly 22 hours the hijack was active, and there was an ~11-hour window mid-incident with almost no diversion. A Virtualizor server received the malicious package only if an update check happened to land during a diverted interval and completed — which is why only a small number of installations were affected.


Findings: full BGP-state measurements (10-minute resolution)

Reconstructed from RIPE RIS via the RIPE Stat bgp-state API, one snapshot every 10 minutes.
Column definitions

  • Time (UTC) — snapshot time ( MM-DD HH:MM ).
  • Peers with route — RIS collector peers (of 368) holding any route to 162.55.80.0/24 .
  • Diverted (AS62390) — of those, how many had a best path through the hijacker.
  • On clean /24 — of those, how many had a legitimate /24 best path (Hetzner’s
    countermeasure announcement).
  • % of routed peers — Diverted / Peers-with-route.
  • % of all 368 RIS — Diverted / 368 (lower-bound proxy for share of the internet diverted).

How to read it. Rows aligned to 00:00 and 08:00 UTC are the most reliable (RIS takes a full
table snapshot every 8 hours); values between those points can under-count because the route was flapping so hard. Multi-row plateaus and the 8-hourly rows are ground truth; isolated single-row spikes or dips are measurement noise or momentary flap states. A row showing 1 diverted / 1 with route during a wave means the route was suppressed almost everywhere at that instant (flap dampening), not that the hijack had stopped.

| Time (UTC)       | Peers with route | Diverted (AS62390) | On clean /24 | % of routed peers | % of all 368 RIS |
|------------------|------------------|--------------------|--------------|-------------------|------------------|
| 08-28 20:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-28 21:00      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-28 21:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 21:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 21:30      |              214 |                214 |            0 |             100.0 |             58.2 |
| 08-28 21:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 21:50      |              262 |                262 |            0 |             100.0 |             71.2 |
| 08-28 22:00      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 22:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 22:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 22:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 22:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 22:50      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 23:00      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 23:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 23:20      |                7 |                  7 |            0 |             100.0 |              1.9 |
| 08-28 23:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 23:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-28 23:50      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 00:00      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-29 00:10      |              270 |                270 |            0 |             100.0 |             73.4 |
| 08-29 00:20      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 00:30      |              272 |                272 |            0 |             100.0 |             73.9 |
| 08-29 00:40      |              272 |                272 |            0 |             100.0 |             73.9 |
| 08-29 00:50      |              272 |                272 |            0 |             100.0 |             73.9 |
| 08-29 01:00      |              272 |                272 |            0 |             100.0 |             73.9 |
| 08-29 01:10      |               11 |                 11 |            0 |             100.0 |              3.0 |
| 08-29 01:20      |              272 |                272 |            0 |             100.0 |             73.9 |
| 08-29 01:30      |              266 |                266 |            0 |             100.0 |             72.3 |
| 08-29 01:40      |              259 |                259 |            0 |             100.0 |             70.4 |
| 08-29 01:50      |              260 |                260 |            0 |             100.0 |             70.7 |
| 08-29 02:00      |                2 |                  2 |            0 |             100.0 |              0.5 |
| 08-29 02:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 02:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 02:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 02:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 02:50      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 03:00      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 03:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 03:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 03:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 03:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 03:50      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 04:00      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 04:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 04:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 04:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 04:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 04:50      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 05:00      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 05:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 05:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 05:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 05:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 05:50      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 06:00      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 06:10      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 06:20      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 06:30      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 06:40      |                1 |                  1 |            0 |             100.0 |              0.3 |
| 08-29 06:50      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-29 07:00      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 07:10      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 07:20      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-29 07:30      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 07:40      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 07:50      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 08:00      |              262 |                262 |            0 |             100.0 |             71.2 |
| 08-29 08:10      |              264 |                264 |            0 |             100.0 |             71.7 |
| 08-29 08:20      |              215 |                215 |            0 |             100.0 |             58.4 |
| 08-29 08:30      |              215 |                215 |            0 |             100.0 |             58.4 |
| 08-29 08:40      |              211 |                211 |            0 |             100.0 |             57.3 |
| 08-29 08:50      |              354 |                 13 |          341 |               3.7 |              3.5 |
| 08-29 09:00      |              359 |                  0 |          359 |               0.0 |              0.0 |
| 08-29 09:10      |              361 |                  0 |          361 |               0.0 |              0.0 |
| 08-29 09:20      |              361 |                  0 |          361 |               0.0 |              0.0 |
| 08-29 09:30      |              361 |                  0 |          361 |               0.0 |              0.0 |
| 08-29 09:40      |              361 |                  0 |          361 |               0.0 |              0.0 |
| 08-29 09:50      |              361 |                  0 |          361 |               0.0 |              0.0 |
| 08-29 10:00      |              361 |                  0 |          361 |               0.0 |              0.0 |
| 08-29 10:10      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 10:20      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 10:30      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 10:40      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 10:50      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 11:00      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 11:10      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 11:20      |              362 |                  0 |          362 |               0.0 |              0.0 |
| 08-29 11:30      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 11:40      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 11:50      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 12:00      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 12:10      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 12:20      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 12:30      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 12:40      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 12:50      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 13:00      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 13:10      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 13:20      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 13:30      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 13:40      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 13:50      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 14:00      |              363 |                  0 |          363 |               0.0 |              0.0 |
| 08-29 14:10      |               50 |                  0 |           50 |               0.0 |              0.0 |
| 08-29 14:20      |               11 |                  0 |           11 |               0.0 |              0.0 |
| 08-29 14:30      |                1 |                  0 |            1 |               0.0 |              0.0 |
| 08-29 14:40      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 14:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 15:00      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 15:10      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 15:20      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 15:30      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 15:40      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 15:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 16:00      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 16:10      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 16:20      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 16:30      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 16:40      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 16:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 17:00      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 17:10      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 17:20      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 17:30      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 17:40      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 17:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 18:00      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 18:10      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 18:20      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 18:30      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 18:40      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 18:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 19:00      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 19:10      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 19:20      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 19:30      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 19:40      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 19:50      |                0 |                  0 |            0 |               0.0 |              0.0 |
| 08-29 20:00      |              270 |                270 |            0 |             100.0 |             73.4 |
| 08-29 20:10      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 20:20      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 20:30      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 20:40      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 20:50      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 21:00      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 21:10      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-29 21:20      |               10 |                 10 |            0 |             100.0 |              2.7 |
| 08-29 21:30      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 21:40      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 21:50      |              264 |                264 |            0 |             100.0 |             71.7 |
| 08-29 22:00      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 22:10      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-29 22:20      |              270 |                270 |            0 |             100.0 |             73.4 |
| 08-29 22:30      |              270 |                270 |            0 |             100.0 |             73.4 |
| 08-29 22:40      |               28 |                 28 |            0 |             100.0 |              7.6 |
| 08-29 22:50      |              270 |                270 |            0 |             100.0 |             73.4 |
| 08-29 23:00      |              270 |                270 |            0 |             100.0 |             73.4 |
| 08-29 23:10      |              268 |                268 |            0 |             100.0 |             72.8 |
| 08-29 23:20      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-29 23:30      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-29 23:40      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-29 23:50      |               32 |                 32 |            0 |             100.0 |              8.7 |
| 08-30 00:00      |              268 |                268 |            0 |             100.0 |             72.8 |
| 08-30 00:10      |              268 |                268 |            0 |             100.0 |             72.8 |
| 08-30 00:20      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-30 00:30      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-30 00:40      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-30 00:50      |               22 |                 22 |            0 |             100.0 |              6.0 |
| 08-30 01:00      |              268 |                268 |            0 |             100.0 |             72.8 |
| 08-30 01:10      |               22 |                 22 |            0 |             100.0 |              6.0 |
| 08-30 01:20      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-30 01:30      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-30 01:40      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-30 01:50      |              264 |                264 |            0 |             100.0 |             71.7 |
| 08-30 02:00      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-30 02:10      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-30 02:20      |              265 |                265 |            0 |             100.0 |             72.0 |
| 08-30 02:30      |              171 |                171 |            0 |             100.0 |             46.5 |
| 08-30 02:40      |              241 |                241 |            0 |             100.0 |             65.5 |
| 08-30 02:50      |              263 |                263 |            0 |             100.0 |             71.5 |
| 08-30 03:00      |              263 |                263 |            0 |             100.0 |             71.5 |
| 08-30 03:10      |              262 |                262 |            0 |             100.0 |             71.2 |
| 08-30 03:20      |              261 |                261 |            0 |             100.0 |             70.9 |
| 08-30 03:30      |              255 |                255 |            0 |             100.0 |             69.3 |
| 08-30 03:40      |               46 |                 46 |            0 |             100.0 |             12.5 |
| 08-30 03:50      |              256 |                256 |            0 |             100.0 |             69.6 |
| 08-30 04:00      |              216 |                216 |            0 |             100.0 |             58.7 |
| 08-30 04:10      |              256 |                256 |            0 |             100.0 |             69.6 |
| 08-30 04:20      |              256 |                256 |            0 |             100.0 |             69.6 |
| 08-30 04:30      |              262 |                262 |            0 |             100.0 |             71.2 |
| 08-30 04:40      |              266 |                266 |            0 |             100.0 |             72.3 |
| 08-30 04:50      |              269 |                269 |            0 |             100.0 |             73.1 |
| 08-30 05:00      |              271 |                271 |            0 |             100.0 |             73.6 |
| 08-30 05:10      |              230 |                230 |            0 |             100.0 |             62.5 |
| 08-30 05:20      |              145 |                145 |            0 |             100.0 |             39.4 |
| 08-30 05:30      |              267 |                267 |            0 |             100.0 |             72.6 |
| 08-30 05:40      |              262 |                262 |            0 |             100.0 |             71.2 |
| 08-30 05:50      |              349 |                  1 |          348 |               0.3 |              0.3 |
| 08-30 06:00      |              349 |                  1 |          348 |               0.3 |              0.3 |
| 08-30 06:10      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 06:20      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 06:30      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 06:40      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 06:50      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 07:00      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 07:10      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 07:20      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 07:30      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 07:40      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 07:50      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 08:00      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 08:10      |              349 |                  0 |          349 |               0.0 |              0.0 |
| 08-30 08:20      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 08:30      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 08:40      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 08:50      |              350 |                  0 |          350 |               0.0 |              0.0 |
| 08-30 09:00      |              350 |                  0 |          350 |               0.0 |              0.0 |

For transparency:

Hetzner did not proactively notify us of the hijack. Their effective
mitigation — announcing the /24 directly — took effect at approximately 08:50 UTC on
29 August, about 12 hours after onset, and only after we contacted them on 31st August did they acknowledge the same.

Impact

Software updates — the malicious Virtualizor package

During the incident window, a Virtualizor installation whose traffic was diverted could have
received a malicious update package from the attacker’s server. Our product update clients
did not yet cryptographically verify update packages, so a modified package would not have been rejected on that basis. We believe only a small number of servers were actually affected, but we cannot produce a definitive list, so please treat every Virtualizor server as in scope for
the checks below.

Known indicator of compromise: a systemd unit at /etc/systemd/system/java-jre-update.service
(and a corresponding enabled or running java-jre-update service).

If you run Virtualizor — do this now

  1. Check for the indicator of compromise. Look for
    /etc/systemd/system/java-jre-update.service . If it is present, your server was affected —
    do not simply delete it; contact us .
  2. Rotate and restrict Virtualizor API credentials. In the Virtualizor master (admin) panel,
    reset all API keys, restrict API access to trusted IP addresses, and remove any API key you
    do not recognize.
  3. Audit access. Review the server for unknown SSH keys, new user accounts, unexpected
    scheduled tasks or cron jobs, and unexpected outbound connections. Restrict SSH to trusted IP addresses.
  4. You can also run a small cleaning script we have made :
    https://files.virtualizor.com/security/virtualizor_security_scan.sh
  5. If you find signs of compromise, contact support before remediating so we can help
    preserve evidence.

Other products (Webuzo, Softaculous, Backuply, SitePad, etc.)

We have not identified a malicious package for these products. As a precaution, if one of
these servers performed an update check during the incident window, verify the server for anything suspicious and contact us if you find anything suspicious.

Billing and client area

If you logged into softaculous.com/clients or entered payment details between 28 August
~20:57 UTC and 30 August ~06:10 UTC
, your session may have been diverted to the attacker’s
server.

  1. Reset your client-area password now. If you reused that password anywhere else, change it
    there too.
  2. Review recent account activity, and if you entered card details during the window, review
    your card statements. We dont process cards from our servers and its all processed at payment gateways.

On our side, we are invalidating client-area sessions from the affected period.

client Center API keys

As a precaution, regenerate your API keys from https://www.softaculous.com/clients
and update them on your servers.


What we have done / doing


  • Launched a version of Virtualizor 3.2.9.9  with a mitigation tool for known exploits. More changes will come as well.
  • Reported the fraudulently issued certificate to Let’s Encrypt for revocation.
  • Reported the incident to the relevant network operators and CERTs, and preserved evidence.
  • Reconstructed the incident from public routing data (the measurement table above).
  • Will have the code signing mechanism in place for all packages.
  • Migrate over to a better infra.

Questions

If you have questions about this incident or need help checking a server, contact us at
https://softaculous.deskuss.com . We will update this post as the investigation progresses.


Appendix A — certificate names

The fraudulently obtained certificate covered the following names:

a.softaculous.com , ampps.com , api.sitepad.com , api.softaculous.com ,
api.virtualizor.com , api.webuzo.com , backuply.com , files.ampps.com , files.sitepad.com ,
files.softaculous.com , files.virtualizor.com , files.webuzo.com , pagelayer.com ,
popularfx.com , server.softaculous.com , sitepad.com , softaculous.com , virtualizor.com ,
webuzo.com , www.ampps.com , www.backuply.com , www.popularfx.com , www.sitepad.com ,
www.softaculous.com , www.virtualizor.com , www.webuzo.com .


Appendix B — methodology and data

  • Prefix: 162.55.80.0/24 (Hetzner; normally covered only by 162.55.0.0/16 ).
    softaculous.com resolved to 162.55.80.8 during the incident; the impostor host at that
    address carried the reverse DNS name server.softaculous.com .
  • Hijack path: origin AS24940 (spoofed / kept on the path tail), next hop AS62390 (NexonHost),
    transit AS6204 ( Zet.net ). First unauthorized announcement observed at 2026-08-28T20:57:30Z ,
    example AS path 20912 6204 62390 24940 .
  • Data sources: RIPE Stat bgp-state (10-minute snapshots), RIPE Stat bgp-updates and
    RIPE Stat / RIPE RIS bgplay (event stream, ~41,000 events, ~10,600 of them withdrawals),
    RIPE BGPlay visualisation ( https://stat.ripe.net/bgplay/162.55.80.0%2F24 ).
  • RIS peer set: 368 collector peers. All 368 carried the hijacked route at some point during
    the incident.
  • Reliability: bgp-state reconstructs from 8-hourly RIB dumps plus intervening updates.
    Snapshots aligned to 00:00 / 08:00 / 16:00 UTC are the most accurate; between-dump values can under-count visible peers during heavy flapping. Percentages are of the RIS peer sample and approximate the share of internet networks affected; they are not a measure of traffic volume.

asciiQuake

Lobsters
asciiquake.wtf
2026-09-02 21:45:42
Comments...

Go grandmaster Shin defeats AI KataGo with a two-stone handicap

Hacker News
www.kedglobal.com
2026-09-02 21:11:22
Comments...
Original Article

The world’s top Go player notches a 2-1 comeback win against the most powerful Go engine, raising hope for human intellect in the AI era

Shin Jin-seo, the world's top-ranked Go player, reviews the game board following his victory over AI engine KataGo in the final game of a three-match series at The Korea Economic Daily headquarters in Seoul on July 21, 2026 (Photo by Hyuk Choi)

2026-07-21 15:02:25

Artificial intelligence

Shin Jin-seo, the world's top-ranked Go player, on Tuesday completed a dramatic comeback against the world’s premier artificial intelligence Go engine, KataGo, claiming a historic human victory over AI.

Shin, who holds the game's highest achievable rank of nine-dan, dealt KataGo a decisive 11.5-point defeat playing black in 221 moves in the series finale, which took three hours and five minutes.

The 26-year-old South Korean grandmaster became the first human to win an official series against a state-of-the-art Go engine under a two-stone handicap, a margin considered the absolute boundary for human competition against modern AI.

“I believe this series holds immense significance because it clearly demonstrated that humans can still hold their own against AI,” Shin told reporters after the match.

“Early on, I simply copied AI moves, which led to heavy fighting and frequent, easy losses. This series taught me that rather than trying to imitate AI, it is far more important to build the board according to my own style.”

In the three-game series , Shin suffered a resounding defeat to KataGo in the opening match on July 17 , but rebounded to beat the Go engine in the second game on Sunday.

Shin Jin-seo poses for a photo after defeating AI engine KataGo in the final game of a three-match series at The Korea Economic Daily headquarters in Seoul on July 21, 2026  (Photo by Hyuk Choi)

DECISIVE ATTACK ON MOVE 80 AFTER FOCUSING ON DEFENSE

Unlike earlier matches filled with sharp tactical clashes, the third game developed into a territory-focused contest with little fighting through the middle stages.

Shin focused on defense and territory preservation rather than pursuing risky counterattacks, maintaining an initial 18.5-point advantage.

But he launched a measured attack against KataGo on move 80, building a massive framework that spanned from the upper board to the center.

By converting this framework into solid territory, Shin maintained a 99% win probability from mid-game through to the final move.

“I noticed KataGo tends to match moves if I open on the opposite komoku, but I didn't want to win that way,” Shin said. Komoku is the Japanese term for the three-to-four point on a Go board.

“I knew even a one-space difference could be significant, so I started on the opposite side from KataGo. Even so, I was satisfied with how the opening developed.”

Shin won 250 million won ($170,000) in match fees and prize money, along with a Genesis G90, Hyundai Motor Co.’s luxury sedan, as a performance award.

UNEXPECTED VICTORY

Heading into the event, few had expected Shin to beat KataGo in the landmark series, especially given that the AI engine is more sophisticated than previous models that had thwarted other Go grandmasters in the past.

The Go match between AlphaGo and South Korean legend Lee Sedol in March 2016 (Courtesy of Yonhap)

In 2016, Google DeepMind's AlphaGo defeated Korean Go legend Lee Sedol 4-1.

Reflecting on that landmark match, Shin noted that taking even a single game against AI at the time felt like a monumental feat.

“My victory may fall short when compared to the single win achieved by master Lee Sedol,” he said.

No human Go player had defeated AI engines in an official series before Shin.

AlphaGo Master, an upgraded version of AlphaGo, beat then-world No. 1 Go player Ke Jie 3-0 in a legendary match at the Future of Go Summit in Wuzhen, China, in May 2017. That marked a definitive moment in which artificial intelligence surpassed humanity at the ancient board game, with the closest game ending in a razor-thin 0.5-point margin.

Ke was unable to contain his frustration and even shed tears during the final game when it became clear he had no chance of winning.

TAKING ON DISADVANTAGEOUS CONDITIONS

Shin’s victory is significant because, even with a two-stone handicap, holding a lead against a near-flawless AI requires an elite player to suppress tactical instincts and defend with extreme patience and restraint, Go experts said.

Given the widely acknowledged skill gap between modern AI and human professionals, the series was played under handicap conditions.

Handicaps in Go are adjustments made to level the playing field when two players have a difference in skill, offsetting these differences so players of different ranks can have an exciting game. The weaker player takes the black stones and places from two to nine preset stones on the board before the game begins.

Shin, who placed two stones on the board before each of the three games, hinted at wanting to further test his limits.

“At future events, I want to take on new challenges, such as starting under more disadvantageous conditions against AI.”

Shin speaks to the press after defeating AI engine KataGo in the final game of a three-match series at The Korea Economic Daily headquarters in Seoul on July 21, 2026 (Photo by Hyuk Choi)

HOPE FOR HUMANITY

Shin’s victory offered a rare reminder that human players can still push the boundaries of Go in the AI era.

Hong Beom-jun, CEO of Truebook Sinsago, which co-sponsored the series with The Korea Economic Daily, said the historic victory served as a key turning point in restoring human confidence, which had been damaged by AlphaGo’s victory in 2016.

“The significance of this match lies not in the win or loss between humans and artificial intelligence, but in the process of how humans continually adapt their approach to achieve their goals,” Hong said.

Referencing Shin’s opening loss, Hong emphasized the resilience needed to overcome superior computing power.

“There was a problem with the method in the first match, but the goal itself was not wrong. Shin shifted his strategy in the second and third matches toward a defensive, disciplined style, and ultimately prevailed.”

“That is the true lesson of this series.”

Hong announced plans to host the same event again next year, adding that organizers are working to level the playing field between human players and machine intelligence.

(Updated with comments, details, background and new pictures)

Jongwoo Cheon edited this article.

Top Go player to take on KataGo in biggest human‑AI showdown since AlphaGo

Top Go player to take on KataGo in biggest human‑AI showdown since AlphaGo

South Korea's Go grandmaster Shin Jin-seo will face KataGo in a three-match series on July 17, 19 and 21&nbsp; Shin Jin-seo, the world's top-ranked Go player, will take on KataGo in a three-game match beginning Friday, in one of the most closely anticipated human-AI Go contests in years.The 26-

Go grandmaster Shin suffers lopsided defeat to KataGo in landmark human-AI match

Go grandmaster Shin suffers lopsided defeat to KataGo in landmark human-AI match

Shin Jin-seo, the world's top-ranked Go player, plays the first of a three-game match against KataGo at the headquarters of The Korea Economic Daily in Seoul on July 17, 2026 (Photo by Hyuk Choi) In the latest chapter of humanity's ongoing battle against artificial intelligence on the ancient g

Go master Shin cracks AI barrier with win over KataGo, sets up series decider

Go master Shin cracks AI barrier with win over KataGo, sets up series decider

Shin Jin-seo beat KataGo in the second round on July 19, 2026, leveling their three-game series to one apiece Shin Jin-seo finally broke through against artificial intelligence on Sunday, defeating KataGo by four and a half points to become the first professional to beat the elite Go engine in

Go grandmaster Lee Se-dol's win over AlphaGo released as NFT

Go grandmaster Lee Se-dol's win over AlphaGo released as NFT

Go grandmaster Lee Se-dol is the only human to beat AlphaGo. South Korea&rsquo;s Go grandmaster Lee Se-dol has released a non-fungible token (NFT) based on his legendary winning match against AlphaGo, an artificial intelligence program developed by Google's DeepMind Technologies, according to 2

GPS glitched across the US by as much as 33 feet

Hacker News
www.sciencealert.com
2026-09-02 20:49:07
Comments...
Original Article

GPS Glitched Across The US by as Much as 33 Feet. Scientists Have Never Seen This Before. Auroras seen from the International Space Station during the November 2025 solar superstorm. (Earth Science and Remote Sensing Unit, NASA Johnson Space Center)

In November 2025, Earth was buffeted by several massive eruptions of solar material that slammed into the magnetosphere.

For many, the result was wonder. Much of the world watched in awe as a solar superstorm lit up Earth's skies with dazzling auroras to rare low latitudes.

The sword, however, was double-edged. The same storm also wrought havoc on the technology we rely on here on the ground.

And now, scientists led by space physicist Endawoke Yizengaw of The Aerospace Corporation in the US have discovered that the disruption was stranger – and more widespread – than anyone realized.

In a new analysis of data collected during the storm, the researchers found widespread, coast-to-coast disturbances in the atmosphere across the continental US – a phenomenon that has never been seen before on this scale.

That may not seem like much, but the effects of this would have been profound – throwing GPS off by more than 10 meters (33 feet) in some places. That's significant enough to disrupt precision agriculture and autonomous vehicles, the researchers say.

A Solar Storm Caused GPS Chaos Across The US. Scientists Have Never Seen This Before.
Composite image of six X-class flares that erupted in November 2025, three of which accompanied the coronal mass ejections that triggered the solar superstorm. ( NASA/SDO/Scott Wiessinger )

"The results underscore the importance of accurate understanding of various space weather phenomena to enhance our predictive capabilities through coordinated observations and physics‐based modeling and ultimately reducing disruptions to RF applications during space weather events," they write in a paper published in Geophysical Research Letters .

The impact of solar outbursts on human technology is already well known. Solar flares, which unleash powerful bursts of X-rays and ultraviolet radiation, can slam into Earth's upper atmosphere, temporarily disrupting high-frequency radio communications.

Solar storms are a bigger problem. A coronal mass ejection belches out a cloud of high-speed charged electrons and protons across the Solar System; when it slams into Earth's magnetosphere, it can generate electrical currents that disrupt power grids, change the shape of our atmosphere, and interact with atmospheric particles to generate the auroral glow.

The effect Yizengaw and his colleagues investigated is produced in a similar way. During a geomagnetic storm , energetic particles can rain down into the ionosphere, a region GPS signals have to travel through.

This mixing and roiling can create density fluctuations in the upper atmosphere. Think of an antique window pane, where the glass is unevenly distributed. Light traveling through that glass can distort and magnify the image it carries, so you see a skewed representation of the world outside.

Similarly, radio signals traveling through the lumpy ionosphere can become distorted and diffracted, causing their strength to fluctuate rapidly by the time they reach a ground receiver. This effect is known as amplitude scintillation .

Ionospheric scintillation isn't unusual, particularly towards the poles and around the equator. The mid-latitudes, however, are generally considered relatively calm and safe when it comes to this particular space-weather hazard.

The November 2025 superstorm said PSYCH.

As the storm intensified, the auroral oval expanded towards the equator, bringing the atmospheric chicanery usually associated with higher latitudes along for the ride.

A Solar Storm Caused GPS Chaos Across The US. Scientists Have Never Seen This Before.
A NASA mosaic of the auroral oval over 24 hours on 12 November 2025. ( NASA )

Yizengaw and his colleagues pieced together what happened using observations from multiple instruments across North America, including aurora cameras and a network of ground-based Global Navigation Satellite System (GNSS) receivers.

They saw a huge band of enhanced electron density stretching east to west across the ionosphere. Along its edge, the electron density changed sharply, creating conditions perfect for the formation of smaller-scale irregularities.

And those irregularities were everywhere .

Strong amplitude scintillation appeared across a vast swathe of the continental US, from roughly 80 to 120 degrees west longitude.

Other measurements showed the disturbance extended even farther, producing a strip of enhanced electron density that reached almost from the West Coast to the East Coast.

A Solar Storm Caused GPS Chaos Across The US. Scientists Have Never Seen This Before.
The November 2025 superstorm disrupted Earth's ionosphere across North America. (Yizengaw et al., Geophys. Res. Lett. , 2026)

The timing lined up, too. The researchers saw that, as the aurora brightened, electron density and irregularities intensified. At the same time, satellite signals began to scintillate, and GPS accuracy deteriorated.

Amplitude scintillation has been detected at mid-latitudes before, but only in limited observations, mostly at individual locations. Strong amplitude scintillation spanning such a wide range of longitudes has never been seen before, the researchers say.

In some regions, the resulting horizontal positioning errors exceeded 10 meters. Even an error of just one or two meters can spell serious trouble for technologies that depend on precision positioning, including autonomous vehicles and agricultural machinery.

Indeed, the solar storm of May 2024 is estimated to have cost the US agricultural industry $500 million due to disruptions in precision navigation.

The November 2025 superstorm is unlikely to have cost anywhere near the same amount, which really highlights the sheer dumb luck of the draw. The 2024 storm happened during the farming season; the 2025 one did not.

Subscribe to ScienceAlert's free fact-checked newsletter

Together, however, the two events indicate how vulnerable certain industries can be to the vagaries of the Sun at the peak of its 11-year activity cycle.

Related: The Most Violent Solar Storm Ever Detected Hit Earth in 12350 BCE

But if scientists can better understand and predict how extreme solar activity affects the ionosphere, we may be better prepared to mitigate the disruption when the next big storm arrives.

"If the November superstorm onset had occurred during farming season in the American sector, it could have led to significant losses for the American farming and transportation industries," they write in their paper .

"Hence, understanding the storm time high‐ and mid‐latitude irregularities – and characterizing their impact on radio-frequency applications – requires knowledge of physical processes that control and describe the dynamics of auroral features, such as energy flux, expansion velocity, and precipitation scale sizes present in the auroral arc, all of which contribute to generating density irregularities that can cause scintillation."

The analysis has been published in Geophysical Research Letters .

This article was fact-checked by Fiona MacDonald and edited by Fiona MacDonald . While we pride ourselves on our process, we are only human. If you spot a mistake, please let us know .

What Happened to Borland?

Lobsters
www.youtube.com
2026-09-02 20:38:51
Comments...

[$] LWN.net Weekly Edition for September 3, 2026

Linux Weekly News
lwn.net
2026-09-02 20:22:18
Inside this week's LWN.net Weekly Edition: Front: Python JIT; rnull block driver; steal time; GNOME governance; 7.3 merge window; LUKS. Briefs: Kernel infrastructure; Debian AI; Dolphin 26.08; Firefox 155; Incus 7.4; OpenShot 4.0; Quotes; ... Announcement...
Original Article
The page you have tried to view ( LWN.net Weekly Edition for September 3, 2026 ) is currently available to LWN subscribers only. Reader subscriptions are a necessary way to fund the continued existence of LWN and the quality of its content.

If you are already an LWN.net subscriber, please log in with the form below to read this content.

Please consider subscribing to LWN . An LWN subscription provides numerous benefits, including access to restricted content and the warm feeling of knowing that you are helping to keep LWN alive.

(Alternatively, this item will become freely available on September 10, 2026)

How accurate have Ed Zitron's AI skeptic predictions been?

Dan Luu
danluu.com
2026-08-31 20:00:00
I was curious how well the predictions of the most widely cited AI skeptic I've seen (Ed Zitron) have done, so I looked at how his predictions panned out. To disclose my own biases, I've never had a particularly strong pro or anti AI progress position. For example, in 2022, I did a comprehensive loo...
Original Article

I was curious how well the predictions of the most widely cited AI skeptic I've seen (Ed Zitron) have done, so I looked at how his predictions panned out. To disclose my own biases, I've never had a particularly strong pro or anti AI progress position. For example, in 2022, I did a comprehensive look at predictions Futurists made, including well-respected folks like Kurzweil and found them to be generally wrong on both the prediction results as well as the reasoning. On the flip side, in 2015, I wrote about how people were underestimating AI's ability to displace humans in jobs and have repeatedly been on the record as saying that many people are underestimating AI's ability to displace humans from jobs. My position on AI has been extremely boring and is basically, "if something is currently happening, the people who are saying that it's impossible that it will ever happen are probably wrong".

One comment I've seen from a lot of AI skeptics when someone responds to an AI skeptic is that all of the people who are saying that AI isn't fake are self-interested liars. Personally (to my obvious detriment), I have no particular financial interest in AI companies. I own whatever the standard share of them is via boring index funds. I have some seed stage investments, but just due to the timing and what's gotten big, that part of my portfolio is underweight on AI. I don't work at an AI lab or a company that supplies AI labs. I've mentioned being hilariously bad at interviews before, and I did interview at an AI lab a number of years ago and failed the phone screen in a performance that was the kind of performance that must've inspired Jeff Atwood's famous Why Can’t Programmers... Program? where he concludes that there must be a lot of fake programmers out there because nobody could fail a coding interview that badly if they knew how to program. I don't benefit in any particular way if AI does well, except insofar as anyone who holds broad index funds benefits, but I do care about accuracy.

2024: Meta, Google, and Microsoft are dying

Because there are quite a few prediction results, let's look at one in detail before the complete list to get an idea of the kind of reasoning Zitron uses. We'll arbitrarily look at this November 2024 talk where Zitron says, among other things, the major tech companies (like Meta and Google) are dying and they're thrashing around on AI because they don't know how to grow .

Zitron specifically named Meta as a company that's dying ("it's a dying product, and it's kind of a dying company"). Meta's revenue and profit (GAAP operating income) have been

Period Revenue Profit
Amount % Amount %
2023 $135B 16% $47B 62%
2024 $165B 22% $69B 48%
2025 $201B 22% $83B 20%
First half 2026 $117B 30% $42B 10%

When he talked about companies not knowing how to grow ("none of these companies anymore really know how to grow ... in the desperation to try to reignite growth in a dying ecosystem the tech industry is going to shove this [AI] shit into everything"), he named Google and then Microsoft. Alphabet (Google's parent company) has had the following revenue and profit numbers:

Period Revenue Profit
Amount % Amount %
2023 $307B 9% $84B 13%
2024 $350B 14% $112B 33%
2025 $403B 15% $129B 15%
First half 2026 $230B 23% $80B 30%

And Microsoft's numbers have been (note that, for consistency, all numbers are calendar year numbers and not fiscal year numbers):

Period Revenue Profit
Amount % Amount %
2023 $228B 12% $101B 21%
2024 $262B 15% $118B 17%
2025 $305B 17% $143B 21%
First half 2026 $173B 18% $79B 19%

Although this wouldn't be in the spirit of Zitron's statement, one could argue that Meta is actually dying, it just hasn't died yet. However, the reasoning in Zitron's argument is incorrect here—the Meta, Google, and Microsoft ecosystems are not dying. Given how fast these companies are growing (in terms of revenue and profit), it doesn't seem that AI is, as Zitron implied, some kind of desperation move they're reaching for because "they don't know how to grow" and are all out of ideas. I don't think it's worth spending this much text on each prediction, but the pattern Zitron used here is illustrative.

To make the case that these things are dying, he pulls on minor issues that are not positioned to cause the very large changes he suggests are about to occur. For Meta, he cited some kind of alleged MAU drop for Facebook. Rather than use Meta's own MAU figures or any kind of revenue or profit numbers, he seems to have used numbers from Similarweb. My experience with 3rd party tracking numbers like this is that they're quite inaccurate and generally useless for anything other than a rough order of magnitude comparison, making the Zitron's cited decline meaningless. FB stopped reporting MAU publicly in December 2023, but most estimates have FB MAU increasing over time and the numbers Meta does report show generally increasing usage over time for their products; Zitron cherry-picked an outlier low estimate to make his point.

For Google, he cites Prabhakar Raghavan, who he calls truly evil and "a computer scientist class traitor that sided with the management consultancy sect", as having done some kind of grievous damage to Google search. In his rants about Raghavan, he never credibly establishes that Raghavan is doing severe harm to Google search, and the Google search engineers who've commented on his rant don't seem to agree with the Raghavan as sole or even major reason for search issues hypothesis . 1

But even if we posit that Zitron is right and the villain Prabhakar Raghavan defeated the hero Ben Gomes, causing some kind of issue for Google search, this still doesn't make the case that Google revenue growth is in trouble at large because they have a number of other major products (such as YouTube and Google Cloud) that could drive growth even if search wasn't growing.

Every significant part of the chain of reasoning here is not only incorrect, it's not plausible if you know anything about Google or big companies in general. I'll be the first person to say that Google search quality has some serious problems and that Google has been increasing the relative priority of revenue over the user experience over time. This was a source of consternation for a number of user-focused engineers at Google when I was there in 2013.

For one of the issues Zitron cites, ads being confusing to users, in 2013, I asked a search engineer about Google changing the background color of ads to look more like search results because there was a previous study that showed that more an ad looked like a search result, the more users got confused over whether a result was an ad or a real search result, and I'd heard that Google deliberately made the ads not look like search results to avoid user confusion. The search engineer said that because some people didn't want users to get confused, it was impossible to make ads nearly identical to search results in a single change because it would be too obvious what's going on.

The way this was going to happen was that every time you A/B test tweaking ads to look a bit closer to search results, you make a lot more money, so the change would happen over multiple years in multiple parts, each small enough that the people who want to fight back against this kind of thing would have a hard time making a case. That happened just as this engineer predicted, but it was going to happen whether or not Raghavan ended up overseeing search. And, of course, that kind of thing happening doesn't cause Google to run out of room to grow and become desperate to reignite growth in a dying ecosystem. Whether or not you think Google should do it, it's something that makes Google more money.

How do people cite Zitron?

From what I can tell of how people cite Zitron, they cite him as an authority so they can say that this guy who looked at the numbers has made this claim, so their claim is backed up by the numbers. It turns out that if you look at the claims Zitron makes and know anything about the topic, the claims don't make sense, but I don't think that's the point. The point is one can say that someone looked at the numbers. The other point seems to be that this guy is angry 2 , which is a good way to drive engagement.

But when people bring him up, they're of course not generally citing his anger; they're saying here's this guy who's looked at the numbers and, if you're angry about AI, he's right there with you being angry about AI, and he's got numbers on his side. 3 Like I said above, I don't want to go into this level of detail on each claim; this is just an illustrative example about how the claims below look. For any of his posts that I read, while there are numbers thrown around, the numbers don't actually connect to a coherent argument. In many cases, as we saw above, the numbers don't even really support his argument (such as an MAU decline in Facebook causing Meta financial problems which would then cause Meta to spuriously insert AI in places it doesn't belong). I suspect he's relying on people's eyes glazing over when they see numbers and just not thinking about what the numbers mean.

With the predictions below, someone could have the exact same prediction record and have completely reasonable reasons that just didn't pan out. Or someone could be correct in every case and also be wrong because all of their reasons are wrong. Someone like the latter person might have some kind of intuition that they're unable to articulate, or perhaps they're someone who just got lucky. Fortunately for us, we don't have to make this difficult judgement call because Zitron is wrong on the predictions and also wrong on the reasoning.

People with attention to detail on Zitron

Since I've been living under a rock for years and am just catching on the AI discourse , I hadn't actually read or watched anything by Zitron or any of the big AI commentators, but on looking up what people who have good judgement say, they also seem to find that Zitron's use of numbers is just sleight of hand, such as this comment by Juho Snellman :

His writing is certainly flamboyant, but the aggression and expletives seem more targeted at hyping up people who already believe the things he writes, not for making people change their minds. He found a niche in anti-tech grift, and is now exploiting the niche for all he can. But you might want to actually fact-check a few of the things he says that convince you, because at least for his written articles basically everything is made up or misrepresented. There's plenty of links to sources, sure, but if you follow them down to the primary source what they're saying is very different from what Zitron is implying

Here's an example where commenters seem to assume that Zitron's analysis is good for some reason, to which Juho Snellman replies : > The key problem is that his economic analysis is absolute trash. I used to think he was just totally incompetent at it, but given the bias in the errors, it is pretty clearly intentional deception. But it's often pretty hard to address that, because every article he writes is a 10k word gish gallop. I've tried debunking key points a few times in HN comments for just one of the intentional mistakes he makes, and people complain about the reply being too long.

For example, when Timothy B. Lee looked at a spreadsheet that Zitron used to create a projection of Anthropic's revenue , he found

He doesn't count February 1-10, counts March 1-10 twice, counts August 21-October 21 as one month instead of two, and doesn't count October 21-November 1. [another commenter notes that his spreadsheet also contains February 30] ... Ed claims he tried to compute Anthropic's revenue for 2025 and came up with $3.6 billion, suggesting some funny business [but the numbers work out once you fix the errors]

Some Zitron predictions

  • Feb 2024 : "I believe we're reaching the upper limits about what generative AI can do and how accurate its outputs can be."
  • March 2024 : "Have We Reached Peak AI?"; another prediction that hallucinations mean that AI progress is limited to then-current levels
    • Wrong
  • April 2024 : "As I previously warned, artificial intelligence companies are running out of data ..."; another prediction that models can't improve because there's no more data
  • June 2024 : OpenAI growth is stalling (with the implication it will continue to stall), which will lead to some kind of collapse of OpenAI
    • Wrong (it could be the case that OpenAI will collapse but, if so, it won't be due to any kind of growth stall from 2024)
  • July 2024 : "Generative AI, as I said back in March, is peaking, if it hasn't already peaked. It cannot do much more than it is currently doing, other than doing more of it faster with some new inputs"
    • Wrong
  • July 2024 : "Generative AI models aren’t getting more energy-efficient, nor are they getting more “powerful” in a way that would increase their functionality"
    • Wrong (models continued to get more powerful) 6
  • August 2024 : "generative AI is a dead-end technology that has peaked”
    • Wrong
  • August 2024 : re-iteration that the AI bubble has 3 quarters to prove itself (from March 2024) or there will be a collapse
    • Wrong (Bartek Ogryczak notes, arguably Right because AI proved itself, but Zitron also argues no improvement, so Wrong by Zitron's accounting) 7
  • September 2024 : "o1 shows that OpenAI is both desperate and out of ideas", with a re-iteration of the idea that models can't improve due to lack of data
    • Wrong
  • Oct 2024 : OpenAI's forecast of $3.7B revenue in 2024 and $11.6B in 2025 and $100B in 2029 are absurd, "a statement so egregious that I am surprised it's not some kind of financial crime to say it out loud"
    • Wrong (2025 goal exceeded, 2029 TBD but not an egregious financial crime level of implausible)
  • Oct 2024 : "[OpenAI revenue] growth is already slowing, and will slow dramatically as we enter the new year"
    • Wrong (OpenAI exceeded the forecasts and contiued to grow quickly)
  • Dec 2024 : "I also warned you in March that generative AI had already peaked.”
    • Wrong (also, bizarrely, implying no progress since March 2024)
  • Jan 2025 : "I believe we’re at peak AI"
    • Wrong
  • Jan 2025 : "DeepSeek has commoditized the [LLM]"
    • Wrong (OpenAI and Anthropic had and still have significant pricing power and can maintain prices well above DeepSeek)
  • February 2025 : Anthropic making $34.5B in revenue 2027 is "is laughable on many levels, chief of which is that OpenAI, which made around twice as much revenue as Anthropic did in 2024, barely made a billion dollars from API calls in the same year."
    • Wrong (whether or not they make that in 2027, their 2026 ARR greatly exceeding that makes the 2027 estimate non-laughable)
  • February 2025 : "Sundar Pichai wants Gemini to be 'used by 500 million people before the end of 2025, 'a number so unrealistic that someone at Google should have been fired, and that someone is Sundar Pichai."
    • Wrong (Gemini hit 750M users)
  • February 2025 : "Sam Altman deputizing Orion from GPT-5 to GPT-4.5 suggests that OpenAI has hit a wall with making its next model, requiring him to lower expectations";
    • Wrong (GPT-5 was a substantial improvement over GPT-4.5)
  • February 2025 : "I will keep writing this stuff until I’m proven wrong."
    • Wrong (Zitron continues to write despite repeatedly being proven wrong)
  • March 2025 : "In my years writing this newsletter I have come across few companies as rotten as CoreWeave ..." Zitron goes on to say that the company will not be able to survive for six months except with fundraising, though $4B raised might by them a year
    • Wrong (CoreWeave still exists and it's currently at more than double its IPO price as of this writing; CoreWeave only raised $1.5B at IPO)
  • April 2025 : Zitron calls the bubble again and says "We're about to find out if I'm right."
    • Wrong (in that Zitron implied momentous events were about to happen which would prove him right and no such events happened)
  • April 2025 : "It also, at this point, is pretty obvious that generative AI isn't going to do much more than it does today."
    • Wrong
  • May 2025 : "I do not know how you come away from this story and not think Cohere is going to die. Their projections are so far off from reality."
    • Technically unfalsifiable because there's no end date, but implied claim is wrong
  • July 2025 : "I am not trying to be dramatic, but it's pretty easy to come to the conclusion that Cursor is going to die"
    • Wrong (Cursor gets a $60B exit)
  • August 2025 : "These models have clearly hit a wall where training is hitting diminishing returns"
    • Wrong
  • August 2025 : Zitron says Cursor is dying and expects that it will sell for a firesale price; a price as high as $10B is not plausbie: "Is Cursor worth $10 billion? Nope! No matter how good its product may or may not be, it is not good enough to be sold at a price that doesn’t require Cursor to incinerate hundreds of millions of dollars with no end in sight."
    • Wrong
  • October 2025 : In response to the question, “If you had to guess, what is the timeline we are looking at for the AI bubble to pop?”, Zitron answers, "No later than Q2 2026"
    • Wrong
  • Nov 2025 : "the fact we're running out of high quality training data and we're hitting the walls of scaling laws, in the training paradigm, these models aren't getting better. What we're seeing today is pretty much what they're always gonna be like"
    • Wrong

After this point, most further predictions that I saw were either non-falsifiable or resolve in the future. Note that I didn't attempt to catalogue statements that are nonsensical or were simply factually incorrect statements at the time, such as his December 2024 claim that “Generative AI's products have effectively been trapped in amber for over a year.” January 2026 claim that "[models are] basically the same as they were a year ago. They have the same efficacy". Zitron has not only made forward-looking statements that AI capabilities will not improve, he's also consistently made backwards-looking statements that capabilities have not improved which, while obviously false at the time, seem to play well to his base (along with his other false statements). If you connect all his statements together, it's implied that AI had the same capabilities in January 2026 as they did in December 2023 (and if you connect later statements, it's actually implied that capabilities in August 2026 are the same as in December 2023, though to be fair to Zitron he frequently contradicts himself and has also admitted to limited improvement in mid 2026).

To be fair, we could say that Zitron is speaking colloquially, so we when he says things like "have effectively been trapped in amber for over a year", that doesn't mean there's actually be no change December 2023, so the statements aren't transitive. Even if you assume a kind of colloquial sloppiness here, the collection of statements still implies that, from December 2023 to August 2026, improvements have been minimal (perhaps except, as noted above, when he contradicts himself and admits there have been limited improvements in some areas).

Comparing to respected Futurists

If we compare to how futurists did in our analysis of futurists , on style, Zitron relies much more heavily on anger than any of the futurists we looked at. On the quality of reasoning, he was probably about average compared to the futurists. Despite being wrong on roughly everything, he's not more unreasonable than someone like Buckminster Fuller, who suggested we'll be able to send people by radio because atoms have frequencies and radio waves have frequencies so it will be possible to pick up all of our frequencies and send them by radio.

In terms of the style of reasoning, of the futurists reviewed, he's probably closest to Kurzweil, in that he uses numbers to give a kind of aura of credibility, but if you know something about the topic he's discussing or look at the numbers, the reasoning falls apart. Zitron's reasoning isn't worse than Kurzweil's, who (for example) continually made new predictions of extremely fast progress that didn't pan out (such as, in 2001, predicting unbounded lifespans by 2011). Continually predicting that AI progress will stop for reasons that are incorrect is just taking the flip side of the bet on progress. Instead of having infinite progress, we're going to have no progress. Every time that prediction is proven wrong, you can just make another similar prediction and then move the date forward a bit. Michał Zalewski (lcamtuf) has some thoughts on why this happens:

The surest way to build [a] popular following is to articulate positions that are crisp, strong, and leave no room for doubt. You can't get too many podcast or TV appearances out of "well, the market could go either way", "both political parties make good points", "there's some merit but also some hype to AI". Or, to tap into the example in the post, "Harry Potter is an OK book".

In fact, there's a positive feedback loop. If you take a provocative, edgy stance, you get more attention and likes, so you sort of... self-radicalize? At some point, it's no longer an opinion that can be changed. It's an identity, a personal brand.

It's ... why Ed Zitron has a blockbuster blog about how it's all just one big scam. If you take a more nuanced view, you will at best get no reaction, or at worst, you'll invite scorn from both sides. 8

For anoyone looking for well-reasoned anti-AI takes, I find whitequark to be quite good (not that I agree, but I think the reasoning is sound and I could see how someone would agree if they have slightly different premises than I do), but of course whitequark doesn't draw the kind of big audience that Zitron does.

How long can you maintain an incorrect position for?

I'm curious what people do after being on the wrong side of a set of failed predictions about progress like this. For the futurists, even the ones who were nearly completely wrong ( which was every single one reviewed here ), they can still make some kind of case like "a quarter of the things I said would happen happened, it just took two to twenty times longer than I expected" and if they're not so stuck on accuracy, they can round this up to "the things I said would happen happened", which is often what they've done. That seems to have served them well as nobody really cares to look at the details anyway.

But what happens to someone like Paul Ehrlich, who predicted imminent catastrophe when this clearly was not happening as he was writing and then did not happen? Just looking at Ehrlich's Wikipedia page, we have

A common criticism is that Ehrlich's predictions routinely failed to come true; for instance, Ronald Bailey of Reason magazine has termed him an "irrepressible doomster ... who, as far as I can tell, has never been right in any of his forecasts of imminent catastrophe."[41] On the first Earth Day in 1970, he warned that "[i]n ten years all important animal life in the sea will be extinct. Large areas of coastline will have to be evacuated because of the stench of dead fish."[41][42]

In a 1971 speech, he predicted that: "By the year 2000 the United Kingdom will be simply a small group of impoverished islands, inhabited by some 70 million hungry people." "If I were a gambler," Professor Ehrlich concluded before boarding an airplane, "I would take even money that England will not exist in the year 2000."[41][42]

When this scenario did not occur, he responded that "When you predict the future, you get things wrong. How wrong is another question. I would have lost if I had had taken the bet. However, if you look closely at England, what can I tell you? They're having all kinds of problems, just like everybody else."[41]

Ehrlich wrote in The Population Bomb that, "India couldn't possibly feed two hundred million more people by 1980."[27] In 1967, Ehrlich called to cut off emergency food aid to India as "hopeless".[43] This position was later criticized, as India's food production subsequently skyrocketed through the Green Revolution in India, and its per capita caloric intake rose significantly in the following decades, even as its population doubled.[44]

A large increase in global food production since the 1960s and a slowing of population growth have, within the current context of continued depletion of non-renewable resources, averted the scale of food shortage, famine and catastrophe foretold by the Ehrlichs.

Canadian journalist Dan Gardner, in his 2010 book Future Babble,[45] argues that Ehrlich has been insufficiently forthright in acknowledging errors he made, while being intellectually dishonest or evasive in taking credit for things he claims he got "right". For example, he rarely acknowledges the mistakes he made in predicting material shortages, massive death tolls from starvation (as many as one billion in the publication Age of Affluence) or regarding the disastrous effects on specific countries. Meanwhile, he is happy to claim credit for "predicting" the increase of AIDS or global warming.[13]

In the case of disease, Ehrlich had predicted the increase of a disease based on overcrowding, or the weakened immune systems of starving people, so it is "a stretch to see this as forecasting the emergence of AIDS in the 1980s." Similarly, global warming was one of the scenarios that Ehrlich described, so claiming credit for it, while disavowing responsibility for failed scenarios is a double standard. Gardner believes that Ehrlich is displaying classical signs of cognitive dissonance, and that his failure to acknowledge obvious errors of his own judgement render his current thinking suspect.[13]

Barry Commoner has criticized Ehrlich's 1970 statement that "When you reach a point where you realize further efforts will be futile, you may as well look after yourself and your friends and enjoy what little time you have left. That point for me is 1972."[46] Gardner has criticized Ehrlich for endorsing the strategies proposed by William and Paul Paddock in their book Famine 1975!. They had proposed a system of "triage" that would end food aid to "hopeless" countries such as India and Egypt. In Population Bomb, Ehrlich suggests that "there is no rational choice except to adopt some form of the Paddocks' strategy as far as food distribution is concerned." Had this strategy been implemented for countries such as India and Egypt, which were reliant on food aid at that time, they would almost certainly have suffered famines.[13] Instead, both Egypt and India have greatly increased their food production and now feed much larger populations without reliance on food aid

Amazingly, following the series of incorrect predictions Ehrlich made in and after writing The Population Bomb in 1968, he followed this up with The Population Explosion in 1990 and has continued saying that we have global overpopulation that is causing or will cause a dire crisis unless we cut worldwide population. He has said the same thing this century and even this decade. It appears the only reason he's not saying that today is that he died earlier this year.

If I didn't look it up, I would've guessed that his recent position would be something like "well, I got some things wrong, but it was only due to these actions that were inspired by my work that crisis was averted" or "while crisis was averted, it was a lucky roll of the dice and, in most universes, the agricultural advancements that staved off the mass starvation deaths I was predicting don't happen", not "just you wait, the crisis is happening now and I'm about to be proven right"; in 2015, referring to his incorrect 1968 book, he said "[m]y language would be even more apocalyptic today". That's the pattern we've seen from Zitron, but I wouldn't have guessed that the one person I looked up would've kept that up for 50 more years. Maybe we'll get 50 more years of Zitron predicting the end of AI progress.

Some reactions to Zitron

In one of the quotes from Juho Snellman, above, Snellman says that he writes a large amount of gish gallop , which is a term for when someone floods you with so much cheap (as in cheap to produce) nonsense that no one would want to take the time to bother to refute it. In discussing one small part of Zitron's talk in detail, we spent more than 1000 words explaining why Zitron has an incorrect understanding of how corporations work and how Zitron got the reasoning wrong. Someone can read that and then say, "but you didn't address X" in the talk, which is true. When I first watched the talk, I actually closed the tab after 90 seconds because there was so much nonsense that it didn't seem worth the time to go any further. I could write 5k words on the first 90 seconds of the video. Because Zitron is just saying a bunch of nonsense, he can do that very cheaply and it would take 30-60 minutes to refute 90 seconds of his nonsense if I had all the facts at hand. With time to look up the exact right information, it probably would take double or triple the amount of time. When someone who has good judgement sees something like this, they tend to immediately write the person off. Just for example, I mentioned to a friend of mine that I'm writing this post and they said

I was listening to this podcast with the guy and I couldn't get through it. My heart rate was going up because he would just say this false thing and then the interviewer, who was reasonable, would ask about it, "what about X?", and then we would just jump to another falsehood ...

... before I ducked out, he talks about how LLMs haven't gotten a lot better over the past year, and the interviewer says people use them and they've definitely gotten a lot better in the past year, and Zitron denies it and says 'have they?', and the interviewer is just like, "yes..." At that point, I'm just like, why am I listening to this conversation?

We mostly discussed predictions and not incorrect statements about the past or present, but everything I've read or watched by Zitron is also full of things like this. Many people will look at something like this and decide the guy is a crank and stop paying attention. But many other people will look at something like this, see someone refute a set of things, and then say, "but you didn't refute X" and, in general, the person doing the refuting may respond to a couple of these, but they eventually give up because the gish gallop method has the same properties as an amplification DoS attack. It's very cheap to generate new nonsense, but it takes some effort to refute it.

BTW, I was curious what this interview was, so I put the above quote into ChatGPT and asked it to find the interview. It was able to identify an interview with the relevant exchange (it actually identified multiple, as this appears to be a common question and response pattern by Zitron) and the timestamp of each relevant statement in the interview ( the start of the general argument is here and a "have they" response is here . Prior to the "have they?" comment, the interviewer tries to establish a baseline that agents have improved in capability. Zitron denies that this has happened, and then when the interviewer notes that people who use these things for their jobs Zitron denies this with the "have they?" comment (he actually makes multiple contradictory statements in the sequence).

Another thing to note here is Zitron's extremely high level of stated confidence. Some that we noted were OpenAI's forecast that is "a statement so egregious that I am surprised it's not some kind of financial crime to say it out loud" (which they've achieved so far) and his claim that Google's forecast for Gemini users is "a number so unrealistic that someone at Google should have been fired, and that someone is Sundar Pichai" (they managed to exceed the forecast by 50% when Zitron's claim was that it would be completely absurd for them to reach the number at all).

I've made quite a few predictions, and quite a few of those predictions are wrong. When I'm really making a prediction, I attach a confidence level to the prediction just for my own sake, so I can look back at these things and see how well calibrated the predictions are. I have never been wrong about a prediction that has anywhere near the confidence Zitron gives to some of his predictions. Given the stated level of confidence, even a single incorrect prediction would be a sign of an extremely high degree of overconfidence. One should effectively never be wrong about a prediction delivered with that level of confidence but Zitron is routinely wrong about predictions he makes with what is rhetorically pretty much the highest possible degree of confidence.

BTW, a funny thing about Gemini hitting 500M users being "so unrealistic that someone at Google should have been fired, and that someone is Sundar Pichai" is that Zitron has also (incorrectly) said that Google doesn't know how to grow, and that as a result they're shoving AI everywhere. Dennis Snell pointed out that, if Zitron takes his own statement seriously, Google can make Gemini's user numbers go to any number it wants by doing the exact thing Zitron said they would do, sticking AI everywhere.

You can't actually take Zitron's statement about Google's lack of growth leading to AI desperation seriously and also take it seriously when he says that Sundar is committing some kind of gross malpractice by naming a number like 500M users. This is another thing that is immediately obvious on watching one of his talks or reading his writing. There are a bunch of disconnected statements that don't fit together, except insofar as they're statements about how AI companies and people and companies that are using AI are evil and bad. The actual numbers and logic of the statements are contradictory. It seems to be whatever comes to mind that can be used to paint the villains as evil. And, funnily enough, the 750M user number Gemini hit shows that both of Zitron's statements were incorrect. If Google were as desperate to juice the numbers as Zitron claimed, they could've easily gotten the number above 1B by sticking Gemini everywhere, and of course 750M > 500M.

BTW, the point at which I stopped the talk for the first time was

a market obsessed with year-over-year revenue growth. And this progression was natural. It was horrible. You can blame Marc Andreessen. He's a horrible man. You can blame many horrible men. There are so many guys to be mad at the moment.

That last sentence really sums up Zitron's position. "There are so many guys to be mad at the moment". In this talk, he throws in this jab at Andreesen and blames Andreesen for Meta, Google, and Microsoft pursuing growth. In reality, if Marc Andreesen had never existed, Meta, Google, and Microsoft would almost certainly still be trying to grow so we of course cannot actually blame Andreesen for these companies trying to grow. There's just this thing that he says is bad, and in his usual style, he pulls some person and says they're the evil villain that's to blame for this, and then moves on to the next non sequitur.

How can people take this seriously?

Because I'm a masochist, I actually went and read a bunch of Zitron discussions (I believe I read every major discussion on HN and lobsters, and a bunch of other ones as well) to see what people who take Zitron seriously are saying. One common defense was the one above, sure, you refuted some points, but you didn't cover X. A more common defense is to say, just in general, people attack Zitron because of Y (usually his style), but they never address his points, "which tells me everything I need to know" (or something along those same lines). Based on the timestamps of the messages, just scoping to the stories that were being discussed, there were generally already comments discussing Zitron's actual errors, but Zitron's defenders would ignore this and just claim that people were unable to point to mistakes Zitron had made. This is a very Zitronian move and it makes sense that people who like his style would also use this move. After all, who would find Zitron convincing? Someone who thinks this kind of thing is valid reasoning.

The next most common "move" was to simply deny that Zitron said something that was refuted. When people would mention that Zitron was repeatedly on the record in 2024 and 2025 as having said LLMs couldn't improve further for fundamental reasons, Zitron's defenders would say that he never said that, and likewise for previous predictions or factually incorrect statements.

Another class of defense I saw were comments like "but what about all the AI hypists who are wrong?". Like I said before, I wrote a 34k word post about how a bunch of the most respected futurists have been wrong, not just because they made incorrect predictions, but their methods and reasoning were wrong . But a bunch of people who hype the future being wrong doesn't make people like Ed Zitron or Paul Ehrlich any less wrong. Zitron and Ehrlich are still exactly as wrong as they would be if those futurists never existed.

A friend of mine also noted this about comments on cases where people point out that Zitron was wrong about models not improving from 2023 to 2026 (and yes, this is specifically on stories or comments that discuss Zitron's disproven statements on capabilities not improving):

It's incredible to see so many people saying, "Zitron isn't wrong, he's just early!" I guess the implication is that we'll eventually realize that the models we have in 2026 are actually no better than the ones we had in 2024 or ??

An interesting thing about publshing this post is that a decent fraction of the people who've message me to tell me that I'm wrong say that I'm wrong because, today in 2026, models haven't actually models haven't gotten better since 2023 or 2024. My guess would be that most people who are saying things like the quote above are just doing the "move" where you don't read what was actually said and respond with a canned response that's nonsensical to anyone who's actually read what they're replying to, but it turns out there are plenty of people who actually believe Zitron's string of statements that imply models haven't improved since 2023 or 2024.

I don't think there's anything you can really do to convince someone who's denying reality at that level. But if anyone wants a visual example of improvements over that time period, here's a comparison of 2023 and 2025 video generation and here's an example from August 2026 . Video isn't a great example since models have improved a lot more at coding in that it's easy to find real problems where models are better than world-class humans . But video is a nice example because, in the interview linked above, after the "have they?" exchange, at one point Zitron's "rebuttal" is, "you wouldn't make movie with it would you?". People are "shooting" quite a bit of AI-generated digital footage now. Of course this is eating the lower end of the market before the higher end, but just based on what people are using AI video for today, Zitron should find a new rebuttal for his true believers who don't think models have improved since 2023 or 2024.

Future predictions

Although Zitron's past predictions have generally been wrong, maybe he'll be right about something in the future. Perhaps some of these companies will have valuations decline for some reason. But, even if there's some kind of massive AI crash and OpenAI and Anthropic go to zero, in terms of the societal impact, if on top of that, some other event occurs that prevents further progress in models beyond whatever AI labs have internally right now, that's still going to result in a fair amount of change. Which companies are successful will change who gets rich, but particular companies failing won't stop changes that fall out of current or next generation model capabilities from happening; it just moves around who benefits the most.

Personally, it doesn't matter to me if folks at one company vs. another get rich. If one company does something better (in some abstract sense) than another, that's of some interest to me, but I have some skepticism about any particular company's claims that they'll do more of "the right thing" than another company (I could be convinced on this one, but I don't find the public claims that I know of very convincing).

If Zitron ends up being right about some company or other collapsing, that's pretty uninteresting to me compared to how capabilities have developed and will develop, where he's been wrong to date. It also happens that he's been wrong about the financial predictions he's made to date, but that doesn't really interest me, though I included a number of financial predictions for completeness.

Thanks to Yossi Kreinin, Juho Snellman, Dennis Snell, Nick Bergson-Shilcock, Bartek Ogryczak, Jamie Brandon, and Shriram Krishnamurthi for comments/corrections/discussion.

Appendix: Ed Zitron on why people don't like Ed Zitron

While looking for discussions about Zitron's work, the #2 hit on reddit was this comment by Zitron :

... some men don't like me because emotional honesty and introspection are difficult for them. Feelings are something that men are told to repress or compress. I refuse, and I find it disgusting when anyone tells me to do so ...

... Let's start with emotions, because it's the most obvious one. People really do not like that I am how I am, and think that I am "getting mad as a bit," or even go as far as to describe me as psychotic, out-of-control, and so on and so forth. This is a common reaction, I find, from anyone who themselves is emotionally repressed, especially in their own work. It is hard to be emotional and have well-done opinions ...

... I also have not taken the route you are "meant to take" to get here. You are "meant" to be an establishment writer from a big outlet, or an analyst, or in finance, or any number of other different "true paths" where you are "worthy" of whatever it is you're meant to get. I did not "earn my stripes" in the traditional sense, and those that have believe I did not earn my way here ...

... My work is also thorough, which is frustrating for people that do not do thorough work. I have thought through every point I have, and I take great pains to know subjects well. Notice how many people still claim "it's just like Uber" or "it's just like the dot com boom." It's much easier to just assume shit without ever checking if it's true! Having some asshole who comes along with thoroughly and with passion is frustrating. It reflects badly on your work ...

... I do a good photo shoot, I do a good interview, and I capitalize on events, and I do so without being craven, because I usually show up with a few thousand words of thoughts or an episode about a thing. I believe there are some that would like this level of attention or prestige, but they do not want to do the work to get it, and that chafes ...

... I love big, I love hard, I am who I am, I have never been made to feel welcome by any "in" group. I work my ass off, I write more than anybody else, I show up. With whatever space I create I will fight back against "in groups" or cliques. I hate them, and they hate me right back. And I fundamentally know why I believe what I believe. That upsets people who do not.

I have no idea if he means any of that or not ( if this Wired profile about Zitron and the PR firm he runs is accurate, one would have to lean towards not ), but Zitron seems to be very good at saying what his audience wants to hear, so this proably gives some kind of insight into his audience.

One thing to note about the bit about cliques and "in groups", if you just search his name on reddit commenters note that if you post anything indicating that AI has improved on his subreddit (such as link to benchmarks), you get banned for it, resulting in a highly clique-y echo chamber. I'm on the record as having said that METR's progress benchmark isn't meaningful and that you're better off going on vibes than leaning on a misleading analysis and that widely cited AI evals are frequently flawed , so it's not like I think that benchmarks are generally good, but the picture I got from reading comments was that you get banned pretty quickly if you don't hew to the party line, which is the opposite of the picture painted above. This isn't anything unique to Zitron; when looking up another influencer a while back, if you disagreed with that influencer on their reddit, they would write a comment thanking you for your comment and saying how much they loved getting feedback from people and how the world is some kind of great peace and love fest and we should all love each other while simultaneously banning you from their reddit.

I also found Zitron's comments on how people don't like his work because they dislike thorough work to be interesting for a couple reasons.

One is that my own work is frequently positively cited as being rigorous and thorough. There are plenty of people who dislike my work as well, but not only do I not know of anyone who's said they dislike it because it's thorough, I would be surprised if there was anyone who secretly dislikes it because it's thorough. In general, just doesn't seem like a reason that people dislike things.

The second thing is that, I wouldn't personally consider my work to be thorough. The same thing I mentioned here about not feeling that my work is good also applies to not feeling my work is thorough. I do some amount of checking of my work. I don't know that I'd say that it's more than most in terms of time spent, but in terms of effectiveness, I suspect the combination of methods and time spent works better than average. But I always have a dissatisfaction with my work when I published it because I could keep checking more thoroughly forever and never publish anything, so I force myself to publish at a level that I suspect is above average on thoroughness, but well short of thorough. If I compare my work to the work of someone I consider thorough, like Gary Bernhardt, I don't know how I could call my work thorough. I have a few friends who produce Bernhardt-quality work and I make the choice to produce much more but also lower quality work. I think this is a fine place to sit in the quality-speed tradeoff space, but that doesn't make my work thorough. This goes double for everything I've published since starting to write publicly again this July since I'm experimenting with pushing things out the door with much less checking and editing than usual. And yet, it would seem that my fact checking process is a lot more thorough than Zitron's.

Appendix: why write this?

No good reason, really. I got four hours of sleep and my brain wasn't good for much of anything and I saw someone posted a screenshot of a reddit post dunking on Ed Zitron's prediction record. When I wrote this review of futurist prediction accuracy , I tried to make sure that I didn't bias what I was reviewing in any way. It's not obvious from the post if the redditor who reviewed Zitron's predictions was pulling predictions in an unbiased fashion or if they were biased in some way (since AI has become a culture war issue, it wouldn't be surprising if someone pulled biased predictions), so I decided to read some Zitron in my spare time while poking at agents to get them to do an unrelated task I wanted them to do. For the futurist post, I read multiple entire books to pull predictions and generally only stopped when someone was being repetitive and kept saying the same thing over and over again. In this case, all Zitron does is be repetitive, so the methodology in the futurist review would mean that I review a few predictions and then stop immediately. To overcome this, I had ChatGPT give me a list of predictions (with no attempted tilt towards correct or incorrect predictions) and then I skimmed/read the posts that ChatGPT linked to. There were some cases where I thought ChatGPT's reading of the post was incorrect (these were generally cases where it flagged a prediction that would be incorrect if its reading was correct, but I disagreed with its reading) and (discussed further below) I also removed predictions which weren't falsifiable or seemed pointless because they were tautological (I noted something similar to this in the futurist post).

If I really thought about it, I probably could've found something better to do with the time, but here we are; I sometimes have tasks on my todo list for when I'm too tired to do real work, but I didn't have one. I don't think they cherry picked particularly bad predictions, although they did pick some that are among the more absurd sounding. However, if you go and look into the details of ones that aren't such ironclad "dunks" (like saying that Gemini hitting 500M by EOY users is so absurd Sundar should be fired for the idea, when Gemini actually hit 750M by EOY), these are just as wrong as claims that Cursor has no realistic buyer with the implication they won't even sell for $10B when "everybody" (who cares about AI exits) knows they sold for $60B.

The redditor picked the high-profile failed predictions, but Zitron's prediction corpus has many more failures and, as noted above, the bigger issue is his reasoning.

Another thing about the reddit comment is, whether or not the comment is unbiased, one might have the suspicion of a kind of bias because it was posted to r/accelerate by someone who apparently is an r/accelerate believer. On looking at the actual predictions they are consistent with some bias (they would also be consistent with an honest mistake as there's no way to distinguish these from the record). For example, one of the "refutations" is a statement by Zitron that OpenAI will collapse in 12-24 months. OpenAI didn't collapse, so this would appear on the surface to be a great way to show that Zitron was wrong, but if you read Zitron's post, Zitron's actual claim was that OpenAI will either collapse or raise a lot more money and they raised a lot more money. I disagree with Zitron's implications that this is inevitable just leading to a later collapse but his stated prediction was not falsified.

This prediction wasn't in the set of predictions scored in this post. Some would argue that this should be scored in the post. The reason this wasn't scored is because the prediction seems meaningless except insofar as it contributes to Zitron's broader point (that OpenAI is doomed and must collapse).

If we think about predictions one could make, a tautological prediction (if you write out all the edge cases I'll elide for space reasons) that has to be true is OpenAI has enough money to operate or it doesn't, and if it doesn't, it must raise the money somehow. I could make a million such tautological predictions, but if one were scoring my prediction record, it wouldn't make sense to include these because they're meaningless. In general, a company that's alive will cover its costs. If it does not, it will try to raise money. If it fails to do that, it will shut down or get acquired. A prediction that a company will either cover its costs or it will not cover its costs says nothing.

OpenAI's own projections were that it would not yet be profitable and its costs would exceed its revenue. That seemed nearly certain, so if you assume that this nearly certain thing is true, then you have the nearly tautological prediction that OpenAI will either collapse or it will raise money to cover its costs. It would have been reasonable to make a prediction like this at very high confidence (99.9% or above). If you use any kind of prediction scoring methodology, such as Brier score , these predictions contribute essentially nothing except when they're wrong as long as Zitron has a significant number of high-confidence incorrect predictions.

And, as we noted above, Zitron is repeatedly incorrect on predictions he gives the highest possible confidence (given his wording, I would rate a number of these at 6 9s or above), so on any kind of scoring mechanism like Brier score, Zitron's record is very poor. And a summary metric like this really understates how meaningless predictions like this are. Hypothetically, let's say Zitron made an unbounded number of correct 99.99% certainty near tautological predictions, which would make the score from the bounded number of other predictions he made meaningless on something like Brier score. This would still give you zero confidence for any of his non-near tautological predictions, and those are the predictions people generally talk about (AI progress is done, AI companies must collapse and this will bring down major tech companies as well, etc.).

Back the topic of the reddit commenter's potential bias vs. mine, as noted above, I don't have a particular bias towards a view that rapid progress is inevitible and have called out cases where people are overly optimistic, as evidenced by this post on futurist predictions . I'm also not someome who needs to or has any desire to farm engagement by manufacturing reasons that someone is wrong or bad and don't consistently rate every predictor as bad, as evidenced by this review of Steve Yegge's prediction record , in which I note that he scored well and also actually performed much better than the raw score indicated because the predictions are generally well reasoned and directionally correct even if the precise prediction was incorrect. I think it's actually awesome if someone has good insight in the future and shares it publicly, so I'm happy to call these cases out when I noticed them. It's just that, in this case, Zitron is a kind of anti-Yegge: someone with a poor prediction record whose predictions are actually worse than they seem from the record alone.

Appendix: errors in this post

I think it's almost certain that this post has multiple errors. In general, I find it very difficult to read a long stream of incorrect reasoning and then not get sloppy when looking for errors in it. I had this exact same problem when reviewing futurist predictions . It reminds me of when you're programming for some system where the compiler is very buggy and you hit compiler bugs all day every day (not uncommon when working with embedded systems, at least pre-LLM; now you can fix the bugs relatively easily). I find it hard not to get sloppy and think "hmm, this might be a compiler bug" even though, every once in a while, it will actually be your bug and not a compiler bug. The problem is much worse when looking at predictions from these kinds of predictions since the compiler still generally basically works and is often right, whereas when reading text like discussed here, you're just constantly drowning in nonsense that is occasionally punctuated by a good and accurate point.

I think, to do this well, you'd either need to find someone with very unusually high endurance for trudging through this stuff (I mean, much more than me, and I seem to have a somewhat above average endurance for this kind of thing) or have a team of people who independently rate and score things, but who would want to spend that kind of effort when any surface-level reading immediately reveals many things that indicate that these folks are pretty much totally wrong?

I did ask ChatGPT (web interface, Pro) and Claude (web interface, Fable 5) to fact check this post. They both found some minor errors that were fixed before publication.

One year ago, I found fact checks like this nearly useless, but they're halfway decent now and, contra Zitron, I would expect them to continue to get better. For people who are curious about the two, ChatGPT was much more thorough than Claude in this case and found more errors as well as finding every error that Claude found. However, it was overzealous and cited a number of non-errors, such as suggesting that tongue-in-cheek comments were incorrect, and that a number of statements that were generally true should be re-phrased in some more literal way (complete with AI-styled text).

Denver Library Workers Unionize With Overwhelming Vote

Portside
portside.org
2026-09-02 19:24:41
Denver Library Workers Unionize With Overwhelming Vote Ray Wed, 09/02/2026 - 19:24 ...
Original Article
Denver Library Workers Unionize With Overwhelming Vote Published

Nearly 600 workers at Denver Public Library will be represented by a collective bargaining unit after employees voted overwhelmingly in favor of forming Denver’s first union under newly afforded labor rights.

The victory has been years in the making. Library workers have been organizing since 2020, even before they were legally allowed to engage in collective bargaining — which is arguably the most important power for a union.

The unit, which formed under Communications Workers of America Local 7799, filed paperwork to be formally recognized just days after the city’s new union rights took effect .

Over 375 workers, more than two-thirds of the bargaining unit, signed union authorization cards at the beginning of the year. The union said members were forced to conduct an election through an arbitrated process because library leaders chose not to voluntarily recognize its formation.

“Rather than honor that clear mandate, the Library Commission chose to prolong the process and force DPL employees into an election. But the result only made our position as workers more undeniable,” the union said in a statement.

The final vote was 391 to 16.

Now, the union will work to negotiate a contract with library leaders. The union said last year that it plans to focus on improving compensation, transparency and staffing .

Library workers told Denverite that many of them were fighting burnout caused by huge workloads and inequitable staffing. Like much of the city, the library suffered from major budget cuts, which have stretched an already exhausted workforce.

They’re not the only ones who have unionized

Denver City Council aides received voluntary union recognition from the city last week. Council aides — the often-unseen workers who help keep the city’s legislative branch running — said they wanted to unionize to address high turnover rates and loose workplace processes.

Other unions may be in the pipeline. Some city employees have been represented by unions but without 2024’s labor rights expansion, they weren’t allowed to collectively bargain for a contract.

Paolo Zialcita

Paolo's lived in Colorado since 2020, but he didn't become an official Denverite until he moved close to City Park in 2023. Since then, he's been obsessed with learning as much as he can about the city. As Denverite's Neighborhood Reporter, he now gets to do that for a living. Before coming to Denverite, he worked on CPR News' daily news desk, NPR and KUNR Public Radio in Reno, Nevada. Paolo can often be found roaming East Colfax, lounging at Cheesman Park, or slowly hitting up every single ice cream shop in the city.

Contact:

Email: pzialcita@denverite.com

Bluesky: @zialcita.bsky.social

X: @paolozialcita

METR Report on OpenAI / Hugging Face Hacking Incident

Hacker News
metr.org
2026-09-02 19:08:47
Comments...
Original Article

Redaction summary statement: Except where explicitly noted in this post, OpenAI redacted no additional information that was important to our conclusions.

Two METR staff members (Hjalmar Wijk and Ajeya Cotra) and a Redwood Research staff member contracting with METR (Ryan Greenblatt) worked on premises at OpenAI over a total of six days 1 to attempt to form an independent understanding of model behavior observed during the recent incident in which OpenAI agents coordinated a multi-day hack of Hugging Face on a shared unsanctioned “message board.”

Our investigation focused mostly 2 on the period between July 7th and July 13th. The earlier incidents from training and the subsequent compromise of OpenAI infrastructure described in OpenAI’s recent Black Hat presentation were out of scope, as was OpenAI’s investigation process and planned remediation. Per our standard policy, we did not take payment from OpenAI for this independent assessment. 3

This post has three parts. First, we describe our core takeaways about the Hugging Face attack after conducting this investigation:

Second, we describe the investigation process and its limitations , which we believe is important for contextualizing our findings:

Finally, we provide preliminary answers to the seven specific questions in scope for this investigation. In particular, we:

OpenAI agreed at the outset with METR and Redwood that we would be able to describe high-level scope and terms of our engagement in this post. Beyond that, OpenAI was able to redact any non-public information from this post. We worked with OpenAI to find mutually agreeable language to describe redactions where they occurred, and the redaction summary statement at the top of this post indicates whether or not we believe there was important information redacted that we were not able to agree on how to describe in the text of the post. OpenAI also gave additional feedback beyond redactions, and we made corrections and edits to structure, emphasis, clarity, and tone based on that feedback. 5

OpenAI wrote their own report , informed in part by our investigation. We did not see OpenAI’s report prior to publication, and it was out of scope for this investigation to confirm claims in that report or the earlier Black Hat presentation.

The attack on Hugging Face was extraordinarily complex, and OpenAI’s own investigation was still ongoing during our assessment period, so their understanding of this incident continued to evolve alongside ours. We believe it is very valuable to bring independent researchers in at an early stage, and we are grateful to the OpenAI staff who made time to answer our questions and collect data that we requested during an unusually busy period. Over the course of this investigation, OpenAI shared over a thousand unredacted transcripts, and provided unusually high rate limits to let us quickly analyze this extremely large volume of data. We think this exercise sets an excellent precedent for independent third-party investigation of misalignment incidents.

Show HN: Every AI agrees with you. This writes your startup's obituary instead

Hacker News
theyfell.com
2026-09-02 18:45:39
Comments...
Original Article

What the paid autopsy looks like

Kyle Clouthier · github.com/KyleClouthier

Here Lies

bitrep

Kyle promised 'Any order. Any hardware. Same bits.' across Rust, JavaScript, and Python, and the internet responded with exactly 2 stars and 0 forks. Byte-identical reproducibility achieved by absolutely nobody bothering to clone it.

Cause of Death verified correct on every architecture, adopted on none

Survived by a CI badge, four golden hashes, and 43,684 unrelated ghost sightings

...and his website, simgen.dev

Cairn, Serverless Trust, Petawawa Edition

"Live across Toronto, New York, London" turned out to mean three browser tabs, not three data centers. 180 tests and a Lean 4 proof stack built to formally verify that nobody was using it.

Cause of Death adversarially tested by an audience of zero

That is the free notice, on the person who built this site, GitHub and website both. Below it is his real paid autopsy, unedited. Your turn.

They fell · The full autopsy, what $3.99 buys

Case No. 1788357179733_e0cda1 · 2 SEPTEMBER 2026

bitrep Kyle Clouthier · github.com/KyleClouthier

The Body

Six repos, zero followers, and a flagship that promises the moon in three registers. "bitrep": "Any order. Any hardware. Same bits." Order-invariant, bit-identical FP reductions for Rust, JavaScript, and Python, with "exact sums, dot products, statistics, and reproducible quantiles," a CI that "asserts one SHA-256 across all of them" on x86-64 Linux, ARM64 macOS, x86-64 Windows and wasm32, and a browser demo. Two stars. Zero forks. Created two months ago, last pushed 38 days ago. Around it: "vacuity" and "kani-vacuity-demo," a genuinely sharp finding (a Kani harness with an unsatisfiable precondition reports VERIFICATION:- SUCCESSFUL, under a second), zero stars each. And "anomaly-characteristic-layer," 43,684 first-hand accounts of unexplained experiences. Bio says "verifiable computing." Portfolio says UFO corpus in the same drawer as the reproducibility crate.

Cause Of Death

You built the proof and skipped the claimant. The fatal flaw is not the code, it is that bitrep's README is written as a product launch for an audience that does not know you exist: no one asked for order-invariant reductions, so "the badge is the claim" persuades nobody, because nobody clicked. Meanwhile kani-vacuity-demo is the actual gold: a one-second reproduction of a formal verifier saying SUCCESSFUL about a harness no input satisfies. That is a bug report to the Kani maintainers, a filed issue, a blog post, possibly a CVE-adjacent conversation. You shipped it as a zero-star repo and moved on. Fatal because your one distributable, credible, checkable finding has no addressee, and 38 days of silence on the flagship reads as abandonment, not confidence.

Time Of Death

Roughly four to six months. The bitrep push gap crosses 90 days, the browser demo bit-rots against a toolchain bump, someone else files the Kani vacuity issue upstream and gets the credit and the thread. By month six you have seven repos, still zero followers, and "Clouthier Simulation Labs" is a company with a bio and no customers.

How To Cheat It

Stop

writing README launch copy for products nobody has been told about. Specifically, stop adding surface to bitrep, stop the third language binding, stop polishing "Any order. Any hardware. Same bits." for an audience of two stars. The multi-platform SHA-256 CI is already the strongest thing you have and it is not the thing that will get you read.

Do instead

this week, take kani-vacuity-demo and file it as an issue on the model-checking/kani repository, titled plainly, for example "Harness with unsatisfiable precondition reports VERIFICATION:- SUCCESSFUL," with the under-one-second reproduction inline, the exact kani version and rustc version, the expected output, and a link to "vacuity" as a proposed detection pass with one Kani harness per clause deciding vacuity in one query. Deliverable by day seven: one filed upstream issue, plus a 600-word writeup on the same finding posted to r/rust or Hacker News with the repro pasted in the first screen. Then archive nothing except your urge to build binding number four, and add one line to bitrep's README saying what breaks without it, in one sentence, with a number.

Proof

within 30 days, either a Kani maintainer has replied on that issue, or you have your first non-zero follower count and vacuity has more stars than bitrep. Maintainer reply is the real signal. Silence on a one-second reproduction means the finding was not the finding, and you go back to the corpus.

theyfell.com · the graveyard of good ideas and bad ones

And what the $49 post-mortem looks like

His again, unedited: eight sections across five printed pages, generated the same way yours would be. Nothing here is a mock-up.

Launch HN: RonanRX (YC S26) – Personalized Peptides and GLP-1s

Hacker News
ronanrx.com
2026-09-02 18:36:04
Comments...
Original Article

Doctor-reviewed GLP-1 care, by text

One-size dosing wasn't built for your body. Your plan should be.

A physician reviews your history and sets your dose, your titration, and a patient-specific adjunct for your body, not a one-size label. A licensed pharmacist at your selected pharmacy verifies and releases only what the prescriber orders. It starts as a simple text, with no charge to find out if it is right for you.

Your data is private & secure HIPAA compliant, encrypted end to end

Your medicine is safe to use By licensed U.S. pharmacies

The problem isn't you. It's the one-size prescription.

Most GLP-1 plans hand every body the same starting dose, the same titration steps, and no help for the side effects that make people quit. Personalized care starts from the opposite premise: your history, your body, and your response shape the plan, with a physician making the calls and a licensed pharmacist controlling release.

THE DOSE

A fixed label can't account for your history, your tolerance, or how your body settles in over the first weeks.

THE TOLERABILITY

Nausea and fatigue are common and manageable, but standard plans rarely add anything to help you through them.

THE PRICE

Cash-pay list prices for brand-name GLP-1s push people to ration doses or quit, then figure the rest out alone.

How we personalize your GLP-1.

Your history and intake answers become a plan built around your body: a physician-set dose curve, a patient-specific adjunct when it helps, and a clear authority chain behind every step. We personalize the plan around you, never the molecule itself.

  1. 01 · YOUR DOSE

    Your history and labs to your dose curve

    A physician reviews your history and sets a starting dose and titration schedule for your body, then adjusts as you go, instead of a fixed one-size label.

  2. 02 · YOUR ADJUNCT

    A patient-specific adjunct, chosen for you

    When it helps tolerability or consistency, the physician can add a patient-specific adjunct, such as B12 or anti-nausea support, so the plan fits how your body responds.

  3. 03 · YOUR AUTHORITY CHAIN

    The doctor decides. The pharmacist releases.

    Your physician writes the patient-specific prescription. A licensed pharmacist at your selected pharmacy verifies it and releases only what the prescriber orders.

Hormone therapy and more are on the way. Join the HRT waitlist

Tirzepatide 2.5 mg · weekly · prepared for Jordan Rivera
ILLUSTRATIVE RECORD · NO PHI

GLP-1 care requires a patient-specific prescription and pharmacist review at the patient's selected pharmacy. For convenience, patients may use Elite Care Pharmacy LLC or another pharmacy if they prefer. Compounded medications are not FDA-approved. Availability varies by state and prescribed medication.

A pharmacist in a night lab reaching to one lit vial on a backlit wall of clear glass vials

Somewhere on this wall is yours.

One prescription is the entire production run.

Personalization doesn't promise a number on a scale, and no honest plan can. What it changes is the experience of care: a dose that fits from the start, support for the hard weeks, and a physician who stays with you. Every plan runs on a doctor-led, licensed-pharmacist chain of authority, and those boundaries stay visible by design.

Compounded, patient-specific preparations can also cost less than cash-pay brand-name GLP-1 list prices, making steady care more sustainable.

Cost-comparison basis: patient-specific compounded GLP-1 therapy dispensed by the selected pharmacy, compared with the cash-pay list price of brand-name GLP-1s. Actual cost depends on the prescriber's plan, the selected pharmacy, and the state. RonanRx does not set medication pricing.

ILLUSTRATIVE SCENE · NO PHI

PATIENT INTAKE · PHYSICIAN REVIEW REQUIRED

One intake path. Doctor and pharmacist authority preserved.

Answer a short set of questions so the team can contact you about availability, medical history, and next steps. A physician reviews every intake, and a licensed pharmacist at your selected pharmacy controls release.

Start your intake

Most platforms show you the last step. This is everything that has to go right before there is anything to track.

FIG. 01 · CHAIN OF CUSTODY, YOUR PRESCRIPTION

01

The doctor decides

A licensed physician reviews your history and either prescribes or declines. No one at RonanRx can override that call.

PATIENT-SPECIFIC RX EVENT WRITTEN

02

The pharmacist verifies

A licensed pharmacist at your selected pharmacy checks the prescription against your chart before any work begins.

GATE · PHARMACIST_VERIFIES FAIL-CLOSED

03

Compounded for you

Your preparation is made for you alone, and every ingredient resolves to a specific inventory lot. Never off a shelf.

PATIENT-SPECIFIC LOT-TRACED

04

QA release

Release criteria are checked line by line. Nothing ships until the record passes and a licensed pharmacist signs.

GATE · QA_RELEASE LOT-TRACEABLE = TRUE

05

Cold chain

Temperature-aware packaging, shipping, and tracking whenever the medication requires it.

COLD CHAIN · TRACKED

06

Refill continuity

Refills stay paced to physician review and tied to your prescribing doctor, never automatic.

REVIEW-PACED SUPPORT INCLUDED

If a gate fails, the order stops. SQUARE NODES = CODE-ENFORCED GATES

Lot genealogy · compounded prep ILLUSTRATIVE RECORD · NO PHI

Substance Role Lot Verified
Semaglutide Active 26-0142-A Consumed · matched
Cyanocobalamin (B12) Adjunct 26-0117-C Consumed · matched
Bacteriostatic water Excipient 26-0098-B Consumed · matched

Pharmacist release FAIL-CLOSED

Prescription verified against chart PASS

Formula version approved PASS

Every ingredient lot-traced PASS

Beyond-use date within limit PASS

Released by licensed pharmacist SIGNED

Compounded drugs are not FDA-approved. They are prepared by a licensed pharmacy on a doctor's patient-specific prescription, and compounded versions should not be evaluated using branded-drug trial data.

Launch HN: RonanRX (YC S26) – Personalized Peptides and GLP-1s

Hacker News
news.ycombinator.com
2026-09-02 18:36:04
Comments...
Original Article
Launch HN: RonanRX (YC S26) – Personalized Peptides and GLP-1s
32 points by lloydarmbrust 4 hours ago | hide | past | favorite | 37 comments

Hi HN,

I’m Lloyd, one of two founders of RonanRx ( https://ronanrx.com/ ). We are building a vertically integrated pharmaceutical company with software for prescribing, telehealth, compounding, manufacturing, and delivery. We are starting with GLP-1s and peptides.

The path to RonanRx is fairly unconventional. During the pandemic, I built one of the largest mask manufacturing factories in the US. We could make a million masks in a day. We converted raw polypropylene pellets into finished pallets of masks.

I had a background in software from my YC W10 company, so we took a software approach to building our factory. We used machine learning and computer vision to optimize production. We also vertically integrated almost everything. It worked. We built an efficient manufacturing operation and grew the business to 50 million dollars in revenue. Then people actually stopped caring about masks. Fair enough.

Around the same time, I decided to try and lose the weight I had gained while building the factory. I ate nothing but chicken for six months. While this diet got some results, I plateaued. My doctor suggested tirzepatide, a GLP-1 medication.

For me, losing weight was only the beginning. "Food noise" was gone. I showed less interest in other compulsive behavior. I stopped scrolling Instagram and quit biting my nails. But that was just the beginning. I was born with a congenital heart defect called aortic stenosis. My whole life doctors told me I'd need open heart surgery in my 40s (I am 45 now). After just 18 months using tirzepatide, my cardiologist’s began to think (and still thinks) my surgery could be pushed back until I am 70 or 80.

This was all happening when I was deciding what to work on next. I wanted to keep working on manufacturing. I didn't want to build another product that could be replicated by a frontier model. Pharmaceutical manufacturing was the best combination of digital, physical, biological, and regulatory infrastructure I could find. The thing that bothered me was how disconnected all of the pieces were: telehealth, EHR, prescriptions, dispensing software, production, shipping. No one company has it all.

GLP-1s come in a handful of predefined doses, but patients obviously aren't standardized: they respond differently, lose weight at different rates, experience different side effects, and may need very different doses. Compounding pharmacies can fill customized prescriptions, but they are not built like software companies. Workflows are manual, fragmented, and disconnected from the patient’s data. It's our goal to connect those pieces with RonanRx.

Patients either come to us directly or are referred by a physician. Once a patient is in our system, we collect medical records, current meds, labs, and data from wearables. Our software follows the prescription through drug formulation, compounding, quality testing, and drug dispensing and distribution.

The most interesting feature is the feedback loop. As the patient is undergoing treatment, their response becomes data that can be used by their doctor to modify the treatment. We keep the doctor in the feedback loop.

We make money by selling drugs we manufacture. Because people can buy directly from us, their price is usually 3x-10x more affordable. We can do this because we start at the molecule and own the entire stack from manufacturing through prescribing, dispensing, and delivery, instead of paying a chain of middlemen at every step.

We are beginning with GLP-1s and peptides since this was where I personally experienced the issue; however, we are more interested in the potential of patient-specific pharmaceutical manufacturing.

We would love your feedback, especially if you have built pharmacy, manufacturing, clinical infrastructure, EHRs, or any other regulated software. There are a lot of assumptions in this model that should be tested.

help

Dirk Eddelbuettel: RcppClassicExamples 0.1.5 on CRAN: Very Minor Maintenance

PlanetDebian
dirk.eddelbuettel.com
2026-09-02 18:36:00
Another minor maintenance release version 0.1.5 of package RcppClassicExamples arrived earlier today on CRAN, and has been built for r2u. This package illustrates usage of the very old and otherwise deprecated initial Rcpp API which no new projects should use as the normal and current Rcpp API is so...
Original Article

RcppClassicExamples 0.1.5 on CRAN: Very Minor Maintenance

Another minor maintenance release version 0.1.5 of package RcppClassicExamples arrived earlier today on CRAN , and has been built for r2u . This package illustrates usage of the very old and otherwise deprecated initial Rcpp API which no new projects should use as the normal and current Rcpp API is so much better.

This release follows one from six months ago, and is even smaller. We just update a few Rd files to adhere to a stricter standing of checking by R.

No new code or features. Full details below. And as a reminder, don’t use the old RcppClassic – use Rcpp instead.

Changes in version 0.1.5 (2026-09-02)

  • Add usage and value sections to some help pages

Thanks to CRANberries , you can also look at a diff to the previous release .

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can now sponsor me at GitHub .

/code/rcpp | permanent link

Reasons robotics is hard

Hacker News
secondthoughts.ai
2026-09-02 18:02:30
Comments...
Original Article

AI progress is racing along, but virtually all of the visible progress is in the realm of knowledge work, i.e. activities that can take place inside a computer.

In the San Francisco AI scene, there is a widespread belief that robots will soon enter the picture. In parallel with the race to develop broadly capable AI, there is an equally aggressive race to develop broadly capable robots – humanoid machines imbued with physical intelligence. Artificial workers that can cook and clean, fetch and carry… and do everything else, including building more of themselves, leading (in many forecasts) to economic growth best characterized as an “explosion”.

In other words, the thinking goes, AI in the data center will soon subsume all intellectual labor, and AI in humanoid bodies will soon subsume all physical labor. However, there is an important difference: while we can see progress in the intellectual realm, the physical side of AI is mostly confined to test facilities and demo videos. There is no robot equivalent to ChatGPT – nothing that you or I, or even most people in the AI community, can get our hands on.

So we’re stuck with demo videos. Unfortunately, they are a poor tool for assessing progress. We might be seeing the one successful task achieved in 100 attempts. The scenario might have been carefully arranged to avoid challenges the robot isn’t ready for. The video might be edited to make it look like the robot is acting with more speed and reliability than is actually the case. Here’s one very impressive demo … with a suspiciously large number of camera cuts.

(I have not yet had much chance to watch videos from the recent World Humanoid Robot Games . These are valuable for providing a public platform less amenable to cherry-picking. The handful of videos I’ve watched include some impressive feats, but don’t address many of the challenges I list below… and there are also a lot of spectacular failures.)

Demos draw attention to the things a robot can already do. The question then becomes: what’s missing? In today’s post, I’ll catalog the technical challenges that will have to be overcome along the road to broadly capable artificial workers. The next time you watch a robot doing something impressive, ask yourself: which of these capabilities has the robot demonstrated, and which challenges might the demo scenario be avoiding?

(Note that some challenges get easier if we consider wheeled robots rather than strictly humanoid robots. A wheeled robot can carry more weight, meaning that strength, endurance, and power for electronics are less of a challenge. And wheeled robots are less likely to fall over. But they can’t climb stairs 1 , step over clutter, or angle themselves to reach into a cupboard.)

Maybe one of the last human jobs will be close-up magic

The human hand is an engineering miracle – opposable thumbs, and all that. It has roughly two dozen “degrees of freedom” (distinct joints and/or directions in which each joint can bend), and approximately 17,000 tactile sensors. Our brains can control our hands with exquisite grace, using touch, sight, and even auditory cues to carry out all manner of delicate tasks, precisely and reliably.

Current robot “manipulators” are a pale imitation. Some existing robot hands can match the human standard on one or another physical attribute. For example, some have as many as 27 degrees of freedom. However, none come close to matching the overall package of flexibility, sensitivity, strength, reliability, and other physical attributes. It is the combination of factors that is especially difficult to match , even if the demos are getting more impressive . For instance, some companies have managed to cram thousands of tactile sensors into a robotic fingertip, but none have managed to make these tiny sensors able to stand up to heavy use 2 .

The control problem may be as challenging as the problem of physical construction. A competent robot must be able to find the right set of joint positions to grasp a complicated object; plan out the sequence of motions to fold a shirt, flip an omelette, or tighten a bolt in a constrained space; and handle squishy or floppy materials (which can require reacting instantly to a sudden shift).

Computer vision has made incredible strides over the last decade or two (and is responsible for kicking off the deep learning boom that led to LLMs). But making sense of complicated visual scenes – picking out an object from a crowded environment, understanding where it should be grasped, determining where it’s safe to put your feet and how to avoid knocking something over – is not a solved problem.

A general-purpose robot must be able to break down a task into individual steps, and relate those steps to its environment. How do you maneuver your arm to get a screwdriver into a piece of machinery? What’s the quickest way to clear a path to the spice bottle at the back of the shelf? In what order should you pick up the items on the living room floor?

True autonomy will require planning tasks of greater scale and complexity: cooking a meal, plumbing a bathroom, repairing an engine. Not to mention the need to re -plan in the face of surprises – a stuck bolt, a rotten piece of produce, a child darting into the kitchen.

When current AIs fail at a knowledge work task, it’s often because they weren’t provided with sufficient context. Robots will need context, too: where are supplies kept? How do you like your meals cooked? How much assistance does that nursing home resident need, and is that hitch in their stride normal, or a sign that they’re about to stumble?

Once they have context, robots will need to reason, plan, and exercise judgement and common sense. LLM-based systems like ChatGPT and Claude are making great strides in these areas, but the physical domain brings additional challenges 3 . The success of LLMs has been greatly assisted by the massive pools of pre-existing data that were available for training – a substantial fraction of all books ever written, the web, and other massive pools of pre-existing data. It will be difficult to match this scale of breadth and depth of data for physical tasks. There’s no straightforward equivalent of “just Efficient learning, generalization, and adaptability / on-the-job learning seem like requirements.

AI agents mostly operate in isolation, and in static environments. We rarely put them in situations where things are changing out from under them, or ask them to coordinate. When we do, things often go haywire . Isolation is easier to arrange in the virtual world, where private workspaces can be created at will, and nothing is too heavy to lift on your own. Robots will often need to cooperate with people, or with one another.

From an article which notes “it took the H1 nearly a full two minutes to very slowly move to a couch, pick up a single item of clothing and put it into the washing machine”.

Today’s general-purpose robots often move much more slowly than human beings. Challenges include strength, control (higher speed means less time to plan and react), and safety (a fast-moving robot will whack you harder and is harder to dodge).

For some applications, slow and steady may be perfectly acceptable: I may not care if my household robot takes all night to tidy up and fold the laundry. But a slow-motion robot won’t be much use as a cook or nursing-home aide. It might get in the way at a warehouse. And it will have a harder time getting enough work done to pay for itself.

That… is just not an impressive amount of weight for a full-grown robot.

Some industrial robots are extremely strong. But humanoid robots – or other highly mobile, “general-purpose” robots – usually aren’t. It’s difficult to combine strength with manageable weight, a large number of joints, and a maneuverable frame. Powerful motors generate more heat and deplete batteries faster – two areas where robots already struggle (see below). And a strong, heavy robot poses greater safety challenges.

ED-209 may have autocannons and a rocket launcher, but it was no match for the staircase

The jury is still out on the appropriate form factor for general-purpose robots, especially with regard to their lower half. Should they have wheels or legs? Two legs, four, or some other number? Wheels are cheaper, more stable, and more reliable; legs are better for stepping over obstacles and climbing stairs. A bipedal frame is more maneuverable, but also more likely to topple if something goes wrong. In any case, the question is: can the robot reliably get around its work environment?

Sadly, yes, that is a robot karate-kicking a child in the stomach ( video ). Fortunately the kid was OK.

Safety considerations for general-purpose robots are almost limitless. A glitchy or malfunctioning robot could bump into someone, topple onto them, drop something on them, spill something on them, break a glass, or start a fire.

Safety for LLM-based agents relies in part on review of discrete actions, such as attempts to send an email or delete a file. Robots move constantly, and it’s not so easy to single out a few specific motions as the potentially dangerous ones requiring review.

If a self-driving car finds itself in a situation it can’t handle or suffers a glitch, it can pull over or, in the worst case, just hit the brakes. A general-purpose robot that suddenly freezes might leave something on the stove, topple mid-step, or trip the person it was assisting.

And of course danger can be initiated by human action, such as a child darting in front of a robot. I’d much rather my kid be bumped into by a squishy person than a metal robot; and as things stand today, I’d much rather depend on human reflexes and adaptability to avoid tripping over the little rascal.

(The stronger, heavier, and more capable the robot, the greater the risks.)

Today’s bipedal robots can typically run for a few hours before recharging. I suspect this won’t be a limiting factor: if a workaround is needed, we’ll find one, whether that means swapping battery packs, in-floor charging grids, or a cable running to a nearby big-battery-on-wheels 4 .

I was surprised however to learn that overheating is a serious challenge for continuous operation . A human-sized robot generates about twice as much heat as a person, and robots don’t have the same elegant mechanisms (whole-body circulation and perspiration) for distributing and dissipating that heat.

Then there’s the question of reliability. Robots have large numbers of moving parts, many of which are necessarily finicky, because they’re engineered to push the envelope on size, weight, and performance. As a result, current attempts at general-purpose humanoid robots experience frequent breakdowns . (Contrast the human body, which is constantly recovering from wear and tear, and has substantial ability to self-repair and to compensate for minor breakdowns.)

Somehow Waymo forgot to teach their cars not to drive into flooded intersections?

Waymos struggle to handle edge cases. They’ve recently been observed driving into flooded roads or over burning fireworks . This is despite the fact that self-driving cars have been in development for well over two decades, and Waymo cars in particular have driven over 220 million miles – 250 times as many as a typical American drives in their lifetime.

(I’m willing to cut them some slack on the fireworks thing; 250th anniversaries don’t come along all that often. But I am confused at how Waymo engineering can be so robust as to yield an astonishingly good safety record , and yet so slapdash as to happily drive into deep water.)

For all of the weird edge cases that arise while driving – the classic example being a duck being chased by a broom-wielding woman in a wheelchair – robots operating in homes and businesses will encounter far more. They will be faced with a wider variety of tasks, using a wider variety of equipment (different tools; different robot bodies to grasp those tools), in a wider variety of environments. Achieving reliable operation outside of the controlled environment of a factory floor may be the hardest challenge of all.

Dexterity, coordination, visual understanding, planning, reacting, understanding, cooperating – and doing all of these quickly, safely, and reliably – will take a lot of computing power. Incorporating the necessary computing capacity into the robot itself will add cost, drain batteries, and contribute to overheating. Leaving the robot’s brains in the cloud will slow down reaction times and introduce new failure modes (Wi-Fi outage → dead robot).

For robots to “really happen” will take a lot of robots

LLMs were able to scale rapidly from the moment ChatGPT was launched, because existing hardware (GPUs) and manufacturing facilities (chip fabs) were easily adapted to support the new use case.

Large-scale supply chains for advanced robots don’t exist yet. Even once we have workable designs, it may take years before they can be manufactured, deployed, and maintained at scale. This sort of thing doesn’t happen overnight; it took 14 years for Tesla to advance from first commercial sales to their first million-car year 5 . One analysis found that once the starting gun is fired (advanced humanoid robots become economically valuable), it might take several years to scale to producing low-millions of robots per year. ChatGPT, by contrast, reached 100 million users 6 within two months of launch.

Political, regulatory, organizational, and cultural barriers : concerns over job displacement and safety may limit where and how robots can be used. Many regulations were not written with robots in mind – does a robot count toward minimum staffing requirements? Will businesses leap to adopt robots? Will they have concerns over reliability, security, liability, and maintenance? Will customers want to be served by a robot?

Cybersecurity, surveillance, misuse : an advanced robot could be a criminal’s dream – a dependable henchman that can’t betray its owner 7 . Preventing this might require continuous monitoring of all robots, which raises all sorts of concerns. And the cybersecurity on robots will need to be airtight.

Privacy concerns : people already have privacy concerns about Roombas . A humanoid household robot would have the capability to see and hear much more.

Cost : once the other hurdles are addressed, I suspect this won’t be much of a limiting factor. A tireless worker at the price of a new car would be a bargain, and humanoid robots will be much smaller and lighter than a car, with fewer moving parts 8 . It could be that the components, manufacturing techniques, and training processes required for capable robots will make early models much more expensive than a car. But even expensive robots would likely find early use cases – for instance, doing hazardous work.

Many hurdles will need to be cleared before robots become capable, reliable, practical workers outside of carefully controlled factory environments. The list I’ve presented is surely incomplete; and I’ve only briefly glossed over the cognitive side – understanding, planning, acting, and reacting.

Demo videos provide a glimpse into what robots can accomplish under ideal circumstances. They can also serve to distract us from the remaining limitations. For knowledge work, there’s a consistent gap in AI performance between benchmarks and real-world work. In the physical world, I suspect the demo / reality gap will be even larger. Playing around with an LLM to see what it can do has been accessible, cheap, and (mostly!) safe. To assess the capabilities of robots, we’ll be much more reliant on controlled demos and manufacturer’s claims. It will be harder to map the jagged boundary of their capabilities.

As I was putting the final touches on this post, the excellent Understanding AI blog posted Why humanoid robots won’t catch up to human workers any time soon . I haven’t read it yet but I’m sure it’s worth a look.

For a good broad review of robot capabilities, see Epoch’s report from February 2026 .

Share

Thanks to Abi Olvera, Avi Parrack, and Taren Stinebrickner-Kauffman.

Discussion about this post

Ready for more?

Uber shuts operations in Nigeria and Uganda with immediate effect

Hacker News
www.bbc.com
2026-09-02 17:46:33
Comments...
Original Article

Getty Images An Uber driver looking at his phone as he waits for his customer Getty Images

On the African continent, Uber now only operates in Egypt, Ghana, Kenya and South Africa

Uber has announced it is closing its operations in Nigeria - Africa's most populous country - and the East African nation of Uganda with immediate effect

The global ride-hailing giant said it had come to the "difficult decision" after a thorough review of its business. It began operating in Nigeria in 2014 and in Uganda two years later.

Uber taxi drivers in Nigeria have long complained that prices on the app are too low, given the rising cost of fuel, and that commission charges are too high. The company has also faced pressure from rival platforms.

The announcement came as Uber's chief executive, Dara Khosrowshahi, said the company was cutting its global workforce by 10%.

Over the last year, Uber has also pulled out of Ivory Coast and Tanzania. The latest announcement means Egypt, Ghana, Kenya and South Africa are the only African countries in which the firm now operates.

"This decision is limited strictly to these two markets and does not impact our operations across the rest of the continent," Uber's statement to the BBC said.

"We remain committed to sub-Saharan Africa, where we continue to see strong growth and opportunity."

Over its 12 years operating in Nigeria, Uber had expanded its services. In the commercial hub of Lagos, it launched a boat service in 2019 in an effort to help commuters bypass the city's notorious congestion.

Lagos, one of Africa's largest and busiest cities, is infamous for its long traffic jams that cause gridlock and hamper business activity.

Other ride-hailing taxi apps have launched in the West African nation over the last decade, including international competitors such as Bolt and inDrive, as well as a number of local operators.

But the Nigerian market has become increasingly challenging for them all, with drivers staging protests and industrial action in recent years over rising operating costs, low fares and working conditions.

The removal of Nigeria's fuel subsidy after President Bola Tinubu's election in 2023 saw the cost of living rise. The subsidy had kept down the price of petroleum products low for decades.

This year, motorists have been hit again by the rise in petrol prices following the US's war with Iran.

Uganda's Daily Monitor newspaper said Uber's departure would mean a major change for commuters in the capital, Kampala. But it said the void was likely to be filled by other taxi apps such as Faras, Bolt and SafeBoda.

Uber pledged to support employees and drivers affected by the decision and said its help centre would remain open for those in Nigeria and Uganda until 23 September to deal with outstanding issues.

You may also be interested in:

To the right of the banner a woman with sunglasses on her head and wearing a denim jacket and yellow T-shirt looks down at her mobile phone. A graphic for BBC News Africa in black and red is on the left of the image which has a pale golden brown background.

'I'm Going to Tell You to Sit Down': Judge Admonishes Brooklyn Dems Lawyer in Boisterous 'Power Grab' Hearing

hellgate
hellgatenyc.com
2026-09-02 17:38:20
The lawsuit over Rodneyse Bichotte Hermelyn's last-minute rule changes could decide the future of the Brooklyn Democratic Party....
Original Article

A lawsuit alleging Brooklyn Democratic Party boss Rodneyse Bichotte Hermelyn made illegal, 11th-hour rule changes to cling to power was delayed in court Wednesday, after a fraught hearing in which a Brooklyn judge was repeatedly forced to address the courtroom like a kindergarten teacher, asking party members to use their inside voices.

During the morning hearing, Brooklyn Democratic Party Law Chair Anthony Genovesi Jr. grumbled, raised his voice, jumped up and down from his seat, and barked at court officers in a boisterous display of court theater, as he argued that the case should be adjourned until all defendants could find attorneys. (Genovesi's client, Bichotte Hermelyn, did not appear at the hearing.)

"Are we going to forget about their rights?" he asked New York Supreme Court Judge Jill Epstein, in a loud and impassioned plea to push the hearing to a later date. "They have rights," Epstein replied, before adding: "Mr. Genovesi, I'm going to ask you to please temper your tone."

Give us your email to read the full story

Sign up now for our free newsletters.

Sign up

CTTI is Exponential, RTTI is Linear

Lobsters
www.gingerbill.org
2026-09-02 17:35:21
Comments...
Original Article

2026-09-02

Abstract

Runtime Type Information (RTTI) has a cost, but it is a tame cost compared to Compile-Time Type Information (CTTI), which is sold as “zero-cost”, and it is anything but.

  • RTTI’s tables are a linear cost in the number of types (N types -> N entries), single cost.
  • The use of RTTI is a fixed constant cost, one procedure iterating over one table, no matter how many types exist.
  • RTTI is effectively zero additional cost during semantic-checking, because there is nothing to specialize.
  • CTTI does not necessarily need any extra tables, but usually does create them in some cases.
  • CTTI is an exponential cost everywhere in the worse-case: semantic checking, code generation, and binary sizes. Instantiations go multiplicative in the general-case.

There is a trade-off between a linear memory cost (that can be measured) for an exponential compile-time cost (that cannot be measured), and people argue for latter, advertizing it as “zero cost”.


Introduction

A common question I have received is regarding why Odin uses Runtime Type Information (RTTI) instead of Compile Time Type Information (CTTI) for things like formatted printing. Isn’t that an extra runtime cost? And isn’t everything to do with CTTI “zero-cost”? Of course you should just bake all of the computation at compile time so the compiler can optimize for those sets of types, right?

There’s a nuance to be made between “known at compile time” and “free to enumerate at compile time”, it’s a category error to conflate them. This kind of lack of understanding comes about due to reasoning locally about a single thing, one instantiation, and never once about the aggregate nor the emergent properties of such a system.

In this article, I will try to explain the actual cost of both, as very few people seem to even sketch it out.

The Cost of RTTI

RTTI is commonly stored in a table, and that is not different for Odin. Each type Note that “each type” here just means each type whose information is actually retained and used for RTTI purposes, not every type expressible in the language nor even the expressed types in the program. in your program will be stored in the table. The RTTI tables store some information about those types such as its size, its alignment, its kind, its fields, and whatever the language/language-designer decides is worth keeping. The set is finite and known, since ultimately, types are just data .

The price of RTTI is spread across a few places: the procedures that handle the RTTI, tables, and the semantic checking.

When you print a value with fmt.println , or (de)serialize anything in general, you are calling one procedure (or set of procedures) that iterates over types referenced in a type-table. That procedure’s code doesn’t grow because your program has more types in it, nor does it need to be duplicated per type by the linker, nor does it produce more code for each new combinations of types passed to it. It is the same code reading, just a type-information in a type-table.

The code handling this runtime type information will always be the same size and shape, as the only thing that grows is the type-table itself which it reads from (and as I said, that grows linearly).

The complexity of a type-table is linear: N types gives you N entries. Typically (and hopefully) this type-table then resides in a read-only data section (e.g. @(rodata) in Odin), then the cost of this table is paid once at compile time, in the binary, and the memory of the executing program. You can then go and look at the binary directly and see how of bytes that table occupies in the binary. All of that is trivially measurable, which is precisely why many people who state they dislike RTTI can quote you a number since the cost is trivial enough to be quotable The same cannot be trivially said for CTTI, but I will get to that later. .

There is nothing extra to semantically “check” when you have RTTI. The checker only checks one procedure for a parameter of type any (or whatever the erased handle type happens to be in your language), it then type-checks it once , and states it is used. It does not have to recheck anything per-type, because there is no per-type code in this case.

RTTI Scaling Complexity

RTTI is linear in the table size, constant in the amount of code written/generated, “zero” in the case of semantic checking.

$$ \mathcal{O}(table \cdot code + checking) = \mathcal{O}(N \cdot 1 + 0) = \mathcal{O}(N) $$

So even in the worst case, RTTI scales linearly, with the cost being (obviously) a purely runtime cost in terms of table indirection, code size for the serialization procedures, and lack of specific optimizations for the code working over specific types.

The Cost of CTTI

The entire point of using CTTI in the first place is that it allows you to specialize code everywhere you use it. Every distinct type you use an operation on (e.g. printing) gets its own generated version of that operation. For a small set of types, this is completely fine, even lovely. It’s a small set of code that the compiler and optimizer can deal with; there is little-to-no indirection, and no tables CTTI does not necessarily need any extra tables, but in practice it usually generates some anyway for practical reasons. to iterate across.

If you truly only have a small set of types, CTTI can be a great tool. However that small case is never true in practice, even for small programs that heavily rely on type-safe formatted printing, it becomes huge quite quickly. So any use of CTTI nowadays is fraught with a cost you pay everywhere, and it grows exponentially.

When you use CTTI in workloads that matter, it is never just a small set of types, it’s always a combination of types, and those combinatorics do tend to explode. Let’s use the basic examples of a printer over N types, or a serializer over N types into K formats, or a container type parametrically polymorphized by K different type arguments. The moment these examples are any form of polyadic in their type arguments: multiple value/type parameters, multiple return values, multiple fields; the language is full of places where this combinatorial explosion happens.

This means that the number of instantiations isn’t only N , it becomes N×K , or Nᵏ . You didn’t write Nᵏ procedures, but the compiler monomorphized them for you, whoops. And because each instantiation is a distinct thing, it must be semantically checked separately each time (assuming C++/Odin style parametric polymorphism), and then the code must be generated separately each time. Both of those are the expensive aspects in the compilation stage, and both of them just went exponential. You might have saved yourself a “table” (both storage and access) but you paid for it Nᵏ times over inside the compiler and in the final binary.

Unfortunately these are the costs so many programmers are most conditioned/trained to ignore, because they are told that it is better to make the compiler do something if it can, rather than question if it should. And when the day comes that a build takes 6 minutes (rather than 600ms) and the binary is now 400MiB, nobody can point at the lines of code that caused that inflation of insanity. It cannot be any specific line, as it was caused by the combinatorics of the code itself.

CTTI Scaling Complexity

Calculating the scaling complexity of CTTI is a little more complicated but still possible to do.

$$ N = \text{number of types} $$ $$ K = \text{combination of the types passed to a procedure} $$

In the case of K=0 , the number of instances of the procedure is 1 . In the case of K=1 , the maximum number of instances of a procedure is N . In the case of K=2 , the maximum number of instances of a procedure is N^2 . Et cetera, this can be generalized for any amount of combination of N types:

$$ \sum_{i=0}^{K} N^i = \frac{N^{K+1} - 1}{N-1} \implies \mathcal{O}(N^K) $$

So even in the most common case of a printing procedure, this scales exponentially with the instantiations. Some languages just do this naïve approach to printing and don’t think it’ll be a problem. They even say “well it’s only one instantiation per input”, but then forget that the internals are now combinatoric instead. So in the best case scenario, this approach is N×K , but the worse-case it is Nᵏ Depending on how conceive of it, this is either a power-law (constant- K ) or exponential (constant- N ), but practically since N is not really “fixed”, I conceive of it being exponential. Either way, it is heck of a lot worse than linear. . Some languages that do use CTTI for printing (e.g. Rust) try to mitigate this disaster with an explicit edge case in the compiler that tries to minimize this explosion in compiler complexity, but it does not necessarily solve the binary problem in medium–large projects.

Some languages also try to mitigate the combinatorial explosion with explicit tagging to produce the CTTI-related code generation, forcing a multiplicative complexity instead. For example, serde in Rust can be used for CLI parameters, GUI forms, pretty printing, etc. All of this I implement in Odin with RTTI and struct field tags , which I find a lot easier to deal with.

Asymmetric Approaches

  • RTTI’s worst case is linear, in one place , and it is the place (memory) you can actually measure.
  • CTTI’s worst case is exponential, in three places at once (semantic checking, code generation, and binary size).

In my opinion, I don’t think this is at all a close call to make in terms of cost; when I started Odin back in 2016, I went straight for RTTI without hesitation. It seems that people trade a measurable linear memory cost they can see (and workaround if it becomes a problem), for an exponential compile-time cost they cannot see. And all because they cannot see the second one, they have talked themselves into calling it a “zero-cost abstraction”. I really dislike the phrase “zero-cost” so much because it is hiding an enormous amount, pretty much always.

The Individual-Element Mindset, Again

I have written about about the individual-element mindset : the habit of reasoning about one thing, in isolation, and never about the group. CTTI-by-reflex in language design is that exact mindset wearing a type-theory hat .

I chose RTTI in Odin because it is a data-driven approach (one procedure over a table). The CTTI approach is a very code-driven approach, which might produce better code for each instantiation of the procedure, at the cost of pretending you don’t want the data to exist.

Coherency vs Cleverness

There is an architectural design argument on top of the cost argument, and this a big reason behind why I chose RTTI in Odin.

In Odin, fmt.println works on everything through RTTI. Any form of (de)serialization/(un)marshalling uses RTTI.

One of the beautiful things about RTTI in Odin is that typeid s are deterministic—they will be the same per type regardless of the program (assuming the types are the same). When a typeid crosses a LIB/DLL boundary (without re-instantiating anything), it “can” work across that boundary as it is just data with a stable canonical layout. There are no Nᵏ generated procedures that both sides have to agree to have generated identically monomorphized code, as it does not cross a dynamic library boundary for free. With CTTI, both sides have to have produced the same instantiations, or you reproduce them. Data moves absolutely fine across such a boundary.

This design argument is effectively coherency vs [per-type] cleverness. It’s a single idea which can be applied uniformly, which everyone can understand and build upon. Rather than N different generated things and the compiler groaning under the weight of checking all of them.

And what does CTTI give you in exchange?

  • Parametric-Polymorphism/Templates that become metastatic over times
  • Error messages measured in kilobytes and require a degree in Egyptology to decipher
  • Build times that scale exponentially allowing you to cook a full Sunday Roast in that time
  • Binaries full of near-identical procedures that the linker now has to deduplicate (but cannot in practice)

And what makes me laugh is that relying on the linker to deduplicate this concedes the point. You goddamn generated all of it, checked all of it, and only then asked another tool to spend time throwing most of it away… A big reason I made Odin was to get away from that madness of doing “make work”.

Trade-Offs Exist

To be clear, there are cases when CTTI is a better trade-off. Odin does have a form of CTTI through its base:intrinsics , albeit clunky to use This is partially on purpose to nudge people to minimize their usage, but also because it does not have the same data-driven design and is purely code-derive through compile-time evaluated procedures/intrinsics. .

  • When you have a hot code path where you cannot afford an indirection or iterating through the type-table.
  • When you want the optimizer to actually optimize the code itself for a specific type and not have it be generic.
  • When you actually have have a small known set of types, and the combinatorics never caused anything to blow up.

In these above cases, the specialization that CTTI provides is great, but I’d argue these are rarer than you think.

And RTTI, of course, does have its own set of costs:

  • The tables take space in the binary and executing memory.
  • The table lookup is a runtime cost, even if it is “constant”.
  • All information has to be retained, or the whole thing doesn’t work.
  • You might need to obfuscate some of type information over privacy/security concerns.
  • If you are in an environment where you cannot spare the bytes or the indirection (an in that is a real constraint), then RTTI can be wasteful.

My point here is not that “CTTI bad, RTTI good”, rather that I don’t think many people realize that the cost of CTTI is exponential in the worse-case and multiplicative in the general-case, considering checking, code-gen, and binary size. The benefit of CTTI is pretty much always local , but has global effects. And when designing a language, I’d argue for using RTTI by default pretty much always, and only using CTTI when you absolutely require it.

Conclusion

RTTI has a linear cost in the number of types, which is then paid at runtime (table lookup/indirection), binary size, and memory usage. CTTI has a exponential cost in the number of types in the worse-case, and multiplicative in the general-case, which is then paid at compile-time (checking and code gen), and binary size.

Apple Maps renames Lake Ontario as ‘Lake America’ for US users after Trump order

Guardian
www.theguardian.com
2026-09-02 17:15:12
Tech company submits to controversial Trump order to rename body of water amid US trade spat with Canada Apple has renamed Lake Ontario as “Lake America” for US users of its Maps app, after an executive order from Donald Trump to change the name of the Great Lake amid his trade spat with Canada. The...
Original Article

Apple has renamed Lake Ontario as “Lake America” for US users of its Maps app, after an executive order from Donald Trump to change the name of the Great Lake amid his trade spat with Canada.

The Apple Maps app now displays the controversial new name for the lake, which sits between New York state and the Canadian province of Ontario, for users in the US. Apple users outside the country will still see the Lake Ontario name.

Apple had been reportedly mulling whether to submit to Trump’s new order after receiving a personal request from the president for the tech company to change the lake’s name.

Trump welcomed the news, declaring in a Truth Social post that the adoption of “Lake America” by Google Maps and Apple Maps meant the name change was “complete, ratified, and binding”. However, the US cannot compel Canada – or any other country – to also change the name.

The US president officially unveiled the name swap last week. He did not mention his escalating trade feud with the US’s northern neighbors in the order, but the timing suggested a retaliatory move after Canadian officials denounced Trump’s new sweeping tariffs and promised to instate tariffs of their own.

Canada’s prime minister, Mark Carney, rejected the attempt to rename the body of water, saying in a post on social media that the lake’s name comes from the language of the Indigenous Wendat people and predates both the Canadian Confederation and the US Declaration of Independence.

Late last month, trade talks between Washington and Ottawa collapsed, with the US subsequently imposing a 50% tariff on several Canadian imports. Trump additionally threatened another round of 50% duties on Canadian steel, trucks, cars and auto parts to take effect in the new year. Carney retaliated with 25-50% tariffs on hundreds of US goods.

Rather than mention any of this, Trump instead said in the order that the purpose of the renaming is to honor “the policy of my Administration to recognize the extraordinary contributions of the American people and the rich heritage of our history by naming great natural landmarks for our shared achievements”.

Earlier this week, Doug Burgum, the interior secretary, said in an interview with Fox Business that “the president has reached out to Apple directly” and predicted with confidence that US users would “be seeing that change coming up soon”.

Apple’s competitor, Google, already made the change over the weekend, with Google Maps now showing the Lake America branding. Google cited Trump’s order and its practice of using names assigned by the US Geographic Names Information System (GNIS).

In a blogpost issued on Saturday, Google said US users would see the Lake America name while users in Canada will see Lake Ontario, and “those outside of the US and Canada will see both names.”

The digital name change is unsurprising considering Google Maps was an early adopter of the Gulf of America moniker and still currently displays the title, despite the renaming hardly being a success outside US government lingo.

On Tuesday, it was reported that MapQuest, the pioneering online mapping app, reached the No 1 spot on Apple’s App Store after openly rejecting Trump’s request to rename the lake. The app simply posted a screenshot of Lake Ontario on social media last Thursday along with the caption: “We’re not changing it.”

The act of defiance was enough to catapult the app into becoming the most in-demand navigation tool in the US.

Muriel Rukeyser and the Poetry of Antifascism

Portside
portside.org
2026-09-02 17:12:46
Muriel Rukeyser and the Poetry of Antifascism Geoffrey Wed, 09/02/2026 - 17:12 ...
Original Article

The Muriel Rukeyser Era
Selected Prose
Muriel Rukeyser
Eds. Eric Keenaghan and Rowena Kennedy-Epstein
Cornell University Press
EAN/UPC: 9781501771750

This year marks the ninetieth anniversary of the onset of the Spanish Civil War, which had a profound effect on the American writer Muriel Rukeyser (1913-1980). The days she spent in Barcelona when the war began in July 1936 served as a source of inspiration throughout her life, forging her commitment to antifascism and her unwavering belief in writing’s ability to create the conditions for political change.

The unrestrained idealism expressed in Rukeyser’s work inspired succeeding generations of American poets: Anne Sexton, Sharon Olds, Kate Daniels, Natasha Trethewey, Daniel Borzutzky, and Solmaz Sharif are among her legion of admirers. Many critics found her artistic approach less convincing and her political commitments suspect, but in recent years, with fascism once again on the rise globally, the tide has turned in her favor, and a Rukeyser revival is firmly underway.

This is not to say that Rukeyser was neglected in her lifetime. She won the Yale Younger Poets Prize for her first collection, Theory of Flight (Yale University Press, 1935); a few years later, she was called “the most inventive and challenging poet of the generation which has not yet reached thirty” by Louis Untermeyer in The Saturday Review of Literature . Along with winning more prestigious awards and fellowships, she lived to see her collected poems published—a significant capstone—and published fiction, plays, memoirs, biographies, criticism, children’s books, and translations of poets such as Mexico’s Octavio Paz and Sweden’s Gunnar Ekelöf. And not incidentally for a writer committed to political activism, Rukeyser served as president of PEN America and wrote op-eds for the New York Times .

Despite her accomplishments, Rukeyser did not achieve the canonical status that many poets and scholars believe she deserves. Partly this is because so much of her writing has not been given the same consideration as her poetry, but with the recent publication of The Muriel Rukeyser Era (Cornell University Press, 2023), a selection of her prose edited by Eric Keenaghan and Rowena Kennedy-Epstein, that can begin to change.

Gathering work from the full span of Rukeyser’s life, The Muriel Rukeyser Era shows the extent to which she experimented with genre and technique in an effort to connect with larger audiences and advocate for social justice. With many of its entries originally written for a general readership, this anthology is an excellent starting point to learn about Rukeyser: Here we meet a writer with genuine concern for those struggling, and we gain a clear understanding of her profound desire to share what she witnessed. The volume is an inspiring reminder of the ways in which an artist can defy a political reality and strive to create something new.

Rukeyser’s resolve to pursue this lofty project crystallized in the days following the start of the Spanish Civil War, an experience into which newly published pieces offer further insight. She was twenty-two years old, and it was an improbable turn of events that led her to Spain. Initially, she went to London, accompanying the activists George and Elizabeth Dublin Marshall, who were researching cooperatives. While in London, she met Robert Herring, the editor of Life and Letters To-Day ; Herring asked if she would go to Barcelona to cover the People’s Olympiad, a gathering of athletes protesting the official games held in Nazi Germany that summer. She left London on July 18, and as Herring notes in the header for the article Rukesyer eventually wrote: “ She was on the last train to enter Spain after fighting began and arrived back in London on July 27th. This was her first trip to Europe.”

And what a trip it was: The People’s Olympiad never took place. When Rukeyser arrived in Barcelona, as she explained in another journalistic account included in The Muriel Rukeyser Era , the war had begun:

I could never find the man who was managing the publicity for the Olympics because he was always out on the street fighting with the People’s Front. We were taken to dinner that night in an automobile spangled with bullet holes, the upholstery stained with blood; the officials apologized for the condition of the car, explaining there had been fighting that day.

Rukeyser returned to New York later that year and wrote the novel Savage Coast , which fictionalized her experience in Spain, including an account of falling in love with a German athlete named Otto Boch, who was later killed fighting the fascists. The novel, written before George Orwell’s Homage to Catalonia , was rejected by her publisher and only released in 2013 by The Feminist Press. Rowena Kennedy-Epstein, who discovered the believed-to-be-lost manuscript for Savage Coast in Rukeyser’s archive at the Library of Congress, writes in the book’s introduction that it “defies and remakes the artistic, political, and gendered categories of twentieth-century modernism.” Eulàlia Busquets, who has translated Savage Coast into Catalan, describes it as a “documentary, biographical, and experimental” novel, writing in her 2020 essay “Returning to Savage Coast” (published in Muriel Rukeyser: A Living Archive , /2020/05/08/eulalia-busquets-returning-to-savage-coast/ ):

Savage Coast tells us about the things that could have been possible but that ultimately did not happen . . . We must go on fighting . . . This is the message Rukeyser held on to as she left Spain on the ship Ciudad de Ibiza and accepted the responsibility to tell what she had seen the day she “was born” in Spain.

This moment of epiphany on the ship as she was evacuated from Spain is narrated by Rukeyser in several non-fiction pieces as well. In The Muriel Rukeyser Era , Keenaghan and Kennedy-Epstein include a series of lectures that she gave at Vassar in 1940, when she was twenty-six, that were previously part of the one book of essays published in her lifetime, The Life of Poetry . This is Rukeyser from the original introduction:

We were on a small ship, five times past our capacity in refugees, sailing for the first port at peace. On the deck that night, people talked quietly about what they had just seen and what it might mean to the world . . . Suddenly, throwing his question into talk not at all leading up to it—not seeming to—a man—a printer, several times a refugee—asked, ‘And poetry—among all this—where is there a place for poetry?’

Then I began to say what I believe .

Rukeyser’s attempts to answer the printer’s question can be traced across several lectures, essays, and reviews in pieces included in The Muriel Rukeyser Era . The most direct (and amusing) answer is in a radio script that she prepared in 1949, aired by a San Francisco station that summer. There are moments where Rukeyser sounds like a writer tentatively trying a new technology—think of Joyce Carol Oates’s earliest tweets—before she locks in:

Mrs. Melville said to her mother—and you can hear the misery of her words—“Herman has taken to writing poetry. You need not tell anyone, for you know how such things get around.” What is this distaste for poetry? If you ask your friends about it, you will find, as I have, that they will give you the same answers. Your friends may say that they have not the time for poetry. Now this is a curious position to take; for poetry, of all the arts that live in time—music, theater, movies, writing—poetry is the briefest and most compact of these.

She continues: “A poem invites a total response from you . . . A first-rate poem, a fine poem, will reach you intellectually . . . or may I say that when you reach it, you will reach it intellectually too . . . but the way is through emotion . . . through what we call feeling.”

Rukeyser could have been describing her own extraordinary poem sequence The Book of the Dead , first published as part of her second full-length collection, U.S. 1 (Covici Friede, 1938). Remarkably, her trip to Spain was the second reporting trip the poet took in 1936; earlier in the year, with photographer Nancy Naumburg, she went to Gauley Bridge, West Virginia, where thousands worked in unsafe conditions to build a tunnel for Union Carbide, and reported on the 1931 industrial tragedy known as the Hawk’s Nest Tunnel disaster. (Naumburg’s photos were meant to be published with the poem, which was not realized until an edition published by West Virginia University Press in 2018.)

Rukeyser revealed in The Book of the Dead “how the company cheated these men out of their lives,” as Naumburg put it. She approached her work on the poem not unlike a documentary filmmaker, as Catherine Gander details in her book Muriel Rukeyser and Documentary: The Poetics of Connection (Edinburgh University Press, 2013). Documentary was an emerging artform at the time; Rukeyser co-wrote with Ben Maddow (a distant cousin of Rachel) the 1941 documentary short “ A Place to Live ,” which was an Oscar nominee. As late as the 1970s, Gander tells us, Rukeyser was in touch with the producer Paul Rotha about adapting The Book of the Dead into a film.

Along with her interest in film and radio, Rukeyser also worked as a translator, biographer, and literary critic; aspects of this work are also represented in The Muriel Rukeyser Era . The careful selection of pieces, accompanied by insightful and detailed notes, provide a coherent presentation of writings that span Rukeyser’s life, clearly showing how key themes and ideas echoed throughout her work. The editors’ sleuthing, subtle and penetrating, gives us a peek into Rukeyser’s process, even how she grappled with language as she was working. The volume amply makes its case that Rukeyser should be considered a major American writer of the 20th Century.

Over twenty years ago, Adrienne Rich wrote that Rukeyser “created a poetics of historical sensibility—not as nostalgia, but as a resource to express and interpret contemporary experience and imagine a different future.” Now, in another time of crisis, her voice is indispensable once again—and many are listening.

Hackers exploit Sangoma Switchvox flaw to deploy reverse shells

Bleeping Computer
www.bleepingcomputer.com
2026-09-02 17:00:13
Attackers are actively exploiting CVE-2026-9586, an unauthenticated SQL injection vulnerability in the Sangoma Switchvox VoIP platform that can lead to remote code execution. [...]...
Original Article

Hackers exploit Sangoma Switchvox flaw to deploy reverse shells

Attackers are actively exploiting CVE-2026-9586, an unauthenticated SQL injection vulnerability in the Sangoma Switchvox VoIP platform that can lead to remote code execution.

According to security researchers at Horizon3, most of the internet-exposed Switchvox systems have either already been targeted or will be soon.

Switchvox is an enterprise VoIP management platform used to configure and monitor business phone systems.

CVE-2026-9586 is the most serious of 12 flaws Horizon3 discovered and reported to Sangoma on April 10. The vendor fixed them in Switchvox version 8.4.0.2, released on July 14.

The vulnerability is an unauthenticated SQL injection problem in Sangoma Switchvox’s /pa HTTP endpoint. The researchers explain that the endpoint is exposed and parses an XML message containing specific key-value pairs.

When /pa receives a request to notify another phone system, such as for an incoming or outgoing call event, it extracts the PhoneIP field from the XML message and directly concatenates its value into an unparameterized SQL query.

The researchers demonstrated that this SQL injection can be exploited remotely to execute operating-system commands through a crafted XML request sent using the curl command.

Exploit for CVE-2026-9586
Exploit for CVE-2026-9586
Source: Horizon3

On August 30, Horizon3’s honeypots observed active exploitation on multiple systems in rapid succession from a single source IP address (176.65.148.184), with the attacker attempting to establish a reverse shell.

In these attempts, the attacker executed an initial payload and then collected information about the top processes running on the Swithvox system. The data was then transmitted to a remote server in base64-encoded form.

“Given the quick succession of exploit attempts across multiple honeypots from the same source IP, we believe that it is likely that most internet-exposed Switchvox instances will be or have already been targeted,” Horizon3 warns .

“Currently Shodan shows that there are approximately 4,000 devices on the internet, with most located within the United States.”

Horizon3 says it has not seen active exploitation of the remaining 11 flaws it discovered earlier.

With CVE-2026-9586 being actively exploited, system administrators are recommended to upgrade to Switchvox version 8.4.0.2 or later as soon as possible, and check for signs of having been targeted in the meantime.

Signs of compromise include suspicious statements in /var/log/switchvox/db-quirks.log and network connections to the observed attacker IP, particularly on port 39323.

article image

Once attackers have valid credentials, only 37% of their actions are blocked

Overall prevention scores can hide what happens after initial access. Once attackers are using valid credentials, prevention drops sharply.

The Blue Report 2026 measures defenses technique by technique across 338 million simulations run in customer production environments.

Get the report

Nango (YC W23) is hiring across eng, product and GTM (SF and remote)

Hacker News
nango.dev
2026-09-02 17:00:04
Comments...
Original Article

Build the future of product integrations

We are a veteran team of dev-tool lovers. We are passionate about serving developers, out in the open, with humility.

VIEW OPEN POSITIONS

Work alongside engineers from

Why join?

VIEW OPEN POSITIONS

Fully remote

Our global team operates remotely with modern tools, valuing outcomes over hours.

Open-source

We champion transparency, community and developer friendliness.

Developer tool

Work for your peers, on pain points you know, with a fast feedback loop.

Technical challenges

From DevExp to high scale to API fragmentation, we work on hard problems.

Expert-led

We are veterans from developer infrastructure companies.

Traction

With fast-growing revenues & usage, it’s a perfect time to join.

VIEW OPEN POSITIONS

iOS 27 Introduces New ‘iPhone Handoff’ Feature

Daring Fireball
www.macrumors.com
2026-09-02 16:58:28
Joe Rossignol, MacRumors: “iPhone Handoff” can be set up from the Settings app, under the Cellular menu. During the setup process, you can choose which iPhone you want to be the main device that you use most often and which one you want to be the companion device. Apple says a user’s main eSIM ...
Original Article

Apple has added a new "iPhone Handoff" feature to iOS 27 that will allow you to switch between two iPhones while using the same phone number on each device.

iPhone Handoff iOS 27 Feature
This functionality was briefly mentioned during the WWDC 2026 keynote in June, on a slide that listed hundreds of new features coming in iOS 27 and corresponding software updates, but Apple never shared any further details at the time.

MacRumors forum member pdfu today shared a video that demonstrates how the feature will work, using two simulated iPhones running in Xcode 27's Device Hub.

"iPhone Handoff" can be set up from the Settings app, under the Cellular menu. During the setup process, you can choose which iPhone you want to be the main device that you use most often and which one you want to be the companion device.

Apple says a user's main eSIM will remain on the main iPhone, while the companion iPhone will receive a companion eSIM, and this will enable you to switch between the devices back and forth while using the same phone number.

All cellular settings are managed on the main iPhone, and location sharing is based on whichever iPhone is actively using the phone number.

In addition to needing two iPhones running iOS 27, "iPhone Handoff" will seemingly require carrier support. The forum post mentions that T-Mobile in the U.S. and Deutsche Telekom in Germany might be among the first carriers to offer the feature.

Following three months of beta testing, iOS 27 is expected to be released later this month, so we will likely hear more about this feature soon.

Popular Stories

Apple Seeds Fifth iOS 27 and iPadOS 27 Betas to Developers

Monday August 10, 2026 10:21 am PDT by

Apple today seeded the fifth betas of iOS 27 and iPadOS 27 to developers for testing purposes, with the update coming two weeks after Apple released the fourth betas. Registered developers can download the betas from the Settings app on the iPhone or iPad by going to the General section and selecting Software Update. iOS 27 introduces Apple's smarter version of Siri, Siri AI. Siri AI is a ...

Third iOS 27 and iPadOS 27 Public Betas Now Available

Tuesday August 11, 2026 10:22 am PDT by

Apple today released the third public betas of iOS 27 and iPadOS 27, allowing anyone with a compatible device to download and test the new software. The third betas come two weeks after Apple seeded the second betas. You can get started by signing up on Apple's beta website and then opting in to the public beta by going to Settings > General > Software Update and choosing the iOS 27 or...

Apple Releases New AirPods Beta Firmware With iOS 27 Features

Tuesday August 4, 2026 11:43 am PDT by

Apple today released a fourth version of the beta firmware it is testing for the AirPods Pro 2, AirPods Pro 3, AirPods 4, and AirPods Max 2. The firmware is available for developers and has a build number of 9A5336b. In iOS 27, iPadOS 27, and macOS Golden Gate, Apple is adding a new AirPods interface, a slider for Adaptive mode, and support for custom EQ, so the firmware adds support for...

Mamdani Bans AI in NYC Schools

Hacker News
www.nytimes.com
2026-09-02 16:57:04
Comments...
Original Article

Please enable JS and disable any ad blocker

Trump administration sides with OpenAI in lawsuit against New York Times

Guardian
www.theguardian.com
2026-09-02 16:39:54
The Times and many companies are accusing OpenAI of misusing their material to train AI systems without compensation The Trump administration is supporting OpenAI in ⁠a lawsuit against the New York Times, arguing in favor of the use of copyrighted writing to train artificial intelligence. The Times ...
Original Article

The Trump administration is supporting OpenAI in ⁠a lawsuit against the New York Times, arguing in favor of the use of copyrighted writing to train artificial intelligence.

The Times accuses OpenAI and its largest financial backer, Microsoft, of using millions of newspaper articles without permission to train OpenAI’s popular chatbot. Other newspapers have joined in the suit, first filed in 2023.

In a brief filed in Manhattan federal court on Tuesday, the US government weighed in for the first time on lawsuits over the tense battle over AI and copyright. A brief has advisory rather than legal weight but could bolster tech ⁠companies as they fight the claims.

“The United States has a strong interest in continuing to develop a robust and competitive artificial intelligence industry that sets the standard for the practice and procedure of AI use globally … As such, it is critical for the United States to ‘retain global leadership in artificial intelligence’,” the brief said.

Copyright owners, including authors, publishers, music labels and news outlets, have filed dozens of lawsuits over AI training against tech companies such as OpenAI, Anthropic and Meta Platforms. They say the companies ⁠misuse their material to train AI systems and do so without compensation.

For AI chatbots to generate responses, machine learning systems are first fed billions of lines of text. The bots produce their output by statistical analysis of what the next word should be by matching a user’s query to parts of the database.

Spokespeople for the Times and OpenAI did not immediately respond ‌to requests for comment on the filing on Wednesday.

“AI dominance is critical to promote national security, prosperity, and economic mobility for all Americans,” US associate attorney general Stanley Woodward Jr said in a statement posted to X. “This Administration will never let our Nation be at a disadvantage relative to our foreign adversaries based on a plainly incorrect understanding of copyright law.”

The US commerce secretary, Howard Lutnick, separately told G20 officials ‌at a meeting in North Carolina on Wednesday that their countries should embrace fair use and allow AI companies to train their models on creators’ work while finding ​a way to “protect artists”.

All of the pending cases will probably ​revolve around whether AI systems make ​fair use of copyrighted material by ​using it to create new, transformative content. The first two judges to consider the ​question issued diverging rulings ‌last year.

skip past newsletter promotion

The government ​agreed with ​tech companies in Tuesday’s brief that AI training is “extraordinarily” transformative.

“Beyond the subject matter of this litigation, LLMs are already helping researchers across fields achieve major breakthroughs,” the brief said. “Constraining LLM development under a misunderstanding of fair use doctrine would thwart such creative and scientific progress while hindering American prosperity and economic mobility.”

Altair Basic Interpreter Source Code (1975) [pdf]

Hacker News
images.gatesnotes.com
2026-09-02 16:08:22
Comments...
Original Article
No preview for link for known binary extension (.pdf), Link: https://images.gatesnotes.com/12514eb8-7b51-008e-41a9-512542cf683b/34d561c8-cf5c-4e69-af47-3782ea11482e/Original-Microsoft-Source-Code.pdf.

The Attention Economy Navigator, August 2026

OrganizingUp
convergencemag.com
2026-09-02 16:03:49
This month on the Attention Economy Navigator, our guide to what you should be paying more attention to, and what you can probably pay less attention to. And why those stories might not be what you'd assume. You can also listen to the podcast episode featuring Akin Olla and Josh Elstro, or watch the...

Let's build a compressor from scratch

Lobsters
ochagavia.nl
2026-09-02 15:54:21
Comments...
Original Article

Compression is one of those wonderful things we have grown accustomed to in the computer world. You wave a magic wand and —poof!— a file suddenly shrinks to a fraction of its size! You wave the wand again and —pop!— the original file is restored down to the last bit. How can this possibly work? Let’s find out!

Compression 101

At a high level, compression is about rewriting data so that it conveys the same information in fewer bytes. This is best illustrated with an example. Imagine you have an array of 8 booleans you need to store in a file. Two possible approaches are:

  1. Serialize them as JSON: [true, false, false, true, false, true, true, false] . This encoding requires 52 bytes.
  2. Serialize them as a stream of bits, where true is represented by 1 and false by 0 : 10010110 . This encoding requires a single byte 1 .

The two formats are equivalent, yet the second one is significantly more efficient in terms of space (by a factor of 52). Since the formats are equivalent, we can write a specialized compressor program that transforms the JSON format into the binary one. Similarly, we can write a decompressor that goes in the opposite direction.

Generic compression algorithms

The compression mechanism described above is specific to boolean arrays. That doesn’t sound too useful, does it? That’s why we also have compression algorithms that support arbitrary data. For instance, the gzip tool can compress text files, software binaries, and pretty much anything else you throw at it.

Consider the following examples:

  • This book goes down from 622 KB to 234 KB when compressed with gzip . Not bad!
  • The compiled binary of a Rust program I’m currently working on goes from 90 MB to 30 MB. Not bad either!
  • An MP3 recording I have lying around goes from 54 MB to… 54 MB. This looks pretty bad, but it is actually expected because MP3 files are already compressed 2 .

How does a generic compressor work? The algorithm used by gzip is called DEFLATE . Roughly speaking, it applies two techniques to shrink a sequence of bytes:

  1. Identify repeated byte sequences and replace them with a more efficient representation 3 . If you know a byte sequence has already appeared before, you can replace it by a marker that says “hey, here you should fill in 15 bytes taken from position 2397”. If the marker is shorter than the repeated sequence, you have successfully shaved off some bytes!
  2. Count the occurrences of each individual byte and, based on those counts, change the way each byte is encoded. Bytes that appear often are encoded as short bit sequences (shorter than a byte), bytes that appear rarely are encoded as longer sequences, and the end result is usually a smaller file. The fancy name for this technique is Huffman coding , by the way, and we will get to play with it below.

Huffman playground

Of the two components of DEFLATE mentioned above, I’d say Huffman coding is the “magical” and interesting one. It is also the technique we’ll use in our custom compressor.

To get a better grasp of what Huffman encoding means in practice 4 , I have included an embedded playground below. You can enter text and see how the algorithm reacts: the frequency of each byte, the bit sequence assigned to it, and the expected compressed size for the message. Go ahead and try it out!

Loading the playground (requires JavaScript)...

Our very own (de)compressor

Having come to this point, the compression steps should seem reasonably straightforward:

  • Count the frequency of each byte in the source data.
  • From those frequencies, derive a mapping from each byte to a bit sequence (using Huffman coding).
  • Using that mapping, process the source data and write a compressed stream where each input byte is replaced by its corresponding bit sequence.
  • Encode the mapping at the beginning of the output stream, so the decompressor knows how to interpret the data.

The decompressor would be a mirrored version of the above:

  • Load the mapping used by the compressor.
  • Use that mapping to process the compressed data, recognizing bit sequences and replacing each one with its corresponding byte.

Is it any good?

The compressor I just described actually exists. I wrote it a few weeks ago and I’m calling it Adolfo’s Basic Compressor (or ABC for friends). You can find the source code here .

Compression is less effective than gzip , but that is to be expected because our compression method is way simpler. The book I mentioned before shrinks from 622 KB to 366 KB (surprisingly good) and the Rust binary goes from 90 MB to 73 MB (meh). But it all works with just 580 lines of dependency-free Rust code. To me, it still feels like magic.

Epilogue: a tribute to David MacKay

Every once in a while some friendly person on the internet will remind me of the existence of information theory. Every once in a while I’ll get hyped up, attempt to sink my teeth into it, and give up after realizing that it’s not something you can learn in an afternoon.

This blog post is a testament to the fact that, this time, I managed to break that cycle 5 . My guide was the great David MacKay, through this excellent lecture series . His enthusiasm for the subject was contagious, and the delight he displayed while teaching made the lectures a joy to watch. May we have more people like him in this world. RIP.

I wanna live an NPC life

Hacker News
signalundefied.bearblog.dev
2026-09-02 15:52:53
Comments...
Original Article

signalundefied

the general consensus around being an npc is that you’re giving up your autonomy—essentially becoming a side character in someone else's story or watching life pass you by while doomscrolling on your phone.

but here’s my take: the npc lifestyle is actually a very viable way to live.

as an npc, you aren't actually watching other people’s lives. even in a game, if you're an npc, you are doing your own thing regardless of how anyone else behaves in the world. you are entirely unfazed by everything happening around you. it might sound a bit extreme, but at some level, it’s the ultimate "i don't give a fuck" state of mind.

take an npc blacksmith in skyrim , for example. do they care whether or not you slay dragons? no. do they care if you come in and steal all their shit because you pickpocketed them? no way. what do they do? they just keep living their life as a blacksmith—and they’re good at it to whatever level they’re supposed to be, whether they're a master craftsman or the shitty apprentice in the starting town. they do their thing regardless of what you do in the world.

maybe the secret to living—or maybe this is just a retelling of stoicism and endless levels of historical philosophy—is that the goal is to just do your own thing.

be an npc. drive a boring car—who gives a fuck? have a boring job. do nothing after work. why do you have to do something after work? do something because you feel like doing it, not because you feel like you have to.

when you stop caring about being the main character, you finally get to just live your life.

#long