Daily Digest — 2026-09-08

26 newsletters today.

In this digest


Abandoned Futures

The Mikoyan MiG-105 Spiral (EPOS): The Soviet Air-Launched Spaceplane That Flew in 1976, Predicted the Dream Chaser by 40 Years, and Got Killed Because Brezhnev Wanted a Copy of the American Shuttle

2026-09-08

In 1965, chief designer Gleb Lozino-Lozinsky's team at Mikoyan started work on a spaceplane program the Soviets called Spiral. The concept was radical even by 1960s standards: a hypersonic mothership would carry a small crewed orbiter to Mach 6 at 30 km, release it, and a rocket booster would take it the rest of the way to orbit. On return, the orbiter would glide back to a runway on retractable jet engines.

The orbiter β€” designated MiG-105-11 EPOS (Experimental Passenger Orbital Aircraft) β€” had a shape that looks eerily familiar in 2026: a stubby lifting body with an upturned nose that earned it the nickname Lapot ("bast shoe" or "clog"). The wings folded upward to 60 degrees during reentry to hide behind the fuselage's heat shield, then rotated down for landing. It was 8 meters long, weighed 4.2 tons, and looked almost identical to what Sierra Space's Dream Chaser would become four decades later.

It actually flew. Between October 1976 and September 1978, test pilot Aviard Fastovets took the MiG-105-11 on eight subsonic test flights from a rough airfield at Faustovo. Some were self-powered takeoffs on a small turbojet; others were air-drops from a modified Tu-95KM bomber at 5,500 meters. On its last flight the landing gear collapsed and the aircraft was damaged. It never flew again.

The reason wasn't the crash. It was 1976 politics. When American plans for the Space Shuttle solidified, the Soviet Council of Ministers ordered a direct competitor. Spiral was shelved. Lozino-Lozinsky was reassigned to lead Buran β€” the Soviet Shuttle clone that flew exactly once, unmanned, in 1988, and then rusted in a hangar until the roof collapsed on it in 2002. The Spiral hardware went to the Monino museum.

What died with Spiral was every idea that turned out to be right:

  • Small crew capsule, big payload separation. The Shuttle carried its crew and its 24-ton cargo bay together, meaning every satellite launch risked seven lives. Spiral separated them.
  • Air-launch to reduce delta-V. Starting from Mach 6 and 30 km saves roughly 15% of orbital energy. Pegasus, Stratolaunch, and Virgin Orbit spent the next 50 years proving this works.
  • Lifting-body reentry with hot-structure heat shield instead of the Shuttle's fragile tile mosaic that eventually killed Columbia in 2003.
  • Runway landing on retractable jet engines for genuine airfield flexibility β€” no California-to-Florida ferry flights on a 747.

Why it could work now. The hypersonic mothership was the hard part in 1965 β€” Tupolev's proposed Mach 6 carrier aircraft was beyond the metallurgy of the day. In 2026 we have:

  • Reusable methane-oxygen rocket engines (Raptor, Prometheus) that make a smaller expendable booster stage economical without needing an air-breathing mothership.
  • Toughened Reinforced Carbon-Carbon and improved TUFROC tiles (as flown on X-37B for over 900 combined orbital days) that survive reentry without inspection between flights.
  • Autonomous flight control β€” the X-37B has landed itself dozens of times. Spiral's original spec required a pilot; that constraint is gone.
  • Composite airframes that would cut the 4.2-ton empty mass by roughly a third.

Sierra Space's Dream Chaser is now scheduled to fly cargo to the ISS in 2026 on a Vulcan booster. Its planform is nearly identical to the MiG-105-11 that Fastovets landed on a dirt strip in Faustovo in 1978. The Soviets had the shape right. They just picked the wrong political moment to bet on it.

Key Takeaway: The Soviets built and flew a lifting-body spaceplane whose design has been vindicated by the X-37B and Dream Chaser, but killed it in 1976 to chase political parity with the American Shuttle β€” the exact vehicle whose flaws Spiral had already engineered around.

ArXiv Paper Digest

The History Is the Detector: Executing CVE Patch History, End-to-End

2026-09-08

Authors: Qiushi Wu, Kevin Eykholt, Youngja Park, Xiaokui Shu

ArXiv: 2609.05335v1

PDF: Download PDF

Every time a serious software vulnerability is discovered, it gets a public entry in a database (a CVE) that describes what went wrong, which piece of code was affected, and β€” crucially β€” the exact patch that fixed it. Over the years, we've accumulated hundreds of thousands of these records. They're a goldmine of information about how software breaks. The problem? They're written for humans to read, not for machines to act on.

Here's the frustrating consequence: the same kind of buggy pattern that got fixed in one project probably exists, undiscovered, in dozens of other codebases. But nobody's systematically hunting for it, because turning "here's the diff that fixed CVE-2019-XXXX" into "here's a detector that finds this bug everywhere else" is genuinely hard work.

This paper proposes a clever inversion of the usual approach. Instead of trying to teach a static analyzer abstract rules about what "unsafe code" looks like, the authors treat the patch history itself as the detector. The idea, roughly:

  • Take a known CVE and its fixing commit.
  • Extract what the unsafe condition looked like before the fix β€” the actual code shape, control flow, and data flow that made the bug possible.
  • Turn that into an executable check you can run against any target codebase to see if the same unsafe pattern is lurking there.

The "end-to-end" part matters: rather than requiring a security engineer to hand-craft a rule from each CVE, the pipeline goes from raw advisory + patch β†’ runnable detector automatically. That's the shift. It treats the vast archive of past fixes as a self-updating library of vulnerability signatures.

Why is this a big deal? Two reasons. First, known bug classes recur constantly β€” the same off-by-one, the same missing bounds check, the same forgotten sanitization β€” because developers keep writing similar code and copying patterns across projects. If a fix taught the community something, that lesson should transfer. Second, current vulnerability scanners lean heavily on either version-matching (does your dependency list contain a known-vulnerable version?) or generic rules that produce mountains of false positives. Neither catches the "same bug, different codebase, no advisory" case that this work targets.

The core insight is philosophical as much as technical: the historical record of how software gets fixed is more precise than any abstract rule we could write about what "safe code" looks like. Real patches encode real developer understanding of real bugs. Executing that history β€” literally replaying it against new code β€” turns a passive archive into an active defense.

Why it matters: It transforms the world's accumulated CVE patch history from a human-readable archive into an automated bug detector, letting past fixes hunt down the same latent flaws still hiding in unrelated codebases.

Daily Automotive Engines

Ignition Coil Dwell Time: Charging the Coil Before It Fires

2026-09-08

An ignition coil is just a transformer with a story: energy has to be stored in a magnetic field before it can be dumped into the spark plug as high voltage. Dwell time is how long the ECU (or old-school points) keeps the primary winding grounded, letting current ramp up and saturate the core. Get it wrong in either direction and the engine either misfires or eats coils for breakfast.

The physics: A coil primary is an inductor with resistance. When you switch it to ground, current doesn't jump instantly β€” it climbs on an exponential curve governed by the L/R time constant. A typical modern coil has ~0.5 ohm primary resistance and ~5 mH inductance, giving a time constant of about 10 ms. But you don't need full theoretical current β€” you need enough to saturate the magnetic core, which usually happens at 7–10 amps.

Old-school dwell (points ignition): Measured in degrees of distributor rotation. A small-block Chevy V8 spec is about 30Β° dwell on a 45Β° cam lobe. At 3000 RPM engine speed, the distributor spins at 1500 RPM, so 30Β° = 3.3 ms of dwell. At 6000 RPM, that same 30Β° collapses to 1.67 ms β€” and the coil never fully saturates. That's why points-triggered engines lose spark energy at high RPM.

Modern coil-on-plug (COP): The ECU controls dwell directly in milliseconds, decoupling it from RPM. Typical values are 2.5–4.0 ms at 14 volts. The ECU also runs a dwell compensation table that lengthens dwell at low battery voltage β€” at 10V cranking, dwell might jump to 5.5 ms because the current ramp is slower.

Rule of thumb: Multiply desired peak current by inductance, divide by battery voltage. For 8A peak, 5 mH coil, 14V system: dwell β‰ˆ (8 Γ— 0.005) / 14 = 2.86 ms. That's your ballpark starting point.

Real-world failure: The GM LS truck coils (D585 "square" coils) spec ~5.5 ms dwell. Tuners often copy dwell values from an LS1 tune (~3.5 ms) into a truck coil setup β€” the spark is weak, misfires appear under boost, and everyone blames the coils. Conversely, running 7 ms dwell into an LS1 coil cooks the internal ignitor within a few thousand miles. The tell: cracked epoxy at the coil base and heat-yellowed connectors.

The trade-off: More dwell = more spark energy = better ignition of lean or boosted mixtures. But excessive dwell wastes current as heat, drains the alternator, and destroys coils. The sweet spot is just past saturation β€” anything beyond is thermal suicide.

See it in action: Check out EFI Advanced: Ignition Coil Dwell Explained by Evans Performance Academy to see this theory applied.
Key Takeaway: Dwell time charges the coil's magnetic field before spark β€” match it to the coil's saturation point in milliseconds, because too little kills spark energy and too much cooks the coil.

Daily Debugging Puzzle

Python's dict.setdefault Eager Evaluation Trap: The Cache That Opens a Fresh Connection on Every Hit

2026-09-08

This helper is supposed to lazily create a database-backed session for a user and cache it, so subsequent calls with the same user_id reuse the same session without touching the database. It passes its unit tests. In production, the DB team files a ticket: connection pool exhausted, and the offending service is the one that "has a cache."

import time

def create_session(user_id):
    # Expensive: opens a DB connection, runs auth queries, allocates state.
    print(f"[db] opening connection for {user_id}")
    return {"user": user_id, "started": time.time()}

def get_session(user_id, cache):
    return cache.setdefault(user_id, create_session(user_id))

if __name__ == "__main__":
    cache = {}
    for _ in range(3):
        get_session("alice", cache)
    # Expected: one "[db] opening connection" line.
    # Actual:   three.

The Bug

dict.setdefault(key, default) is not lazy. It is a regular method call, and Python evaluates all arguments before the method sees any of them. That means create_session(user_id) runs on every single call β€” whether or not the key already exists. setdefault merely decides which value to return and whether to store; it can't decide whether to invoke the argument you already invoked.

People reach for setdefault thinking it behaves like the ternary cache[key] if key in cache else expensive(), but that intuition is imported from languages with lazy defaults (Kotlin's getOrPut, Rust's Entry::or_insert_with). Python has no such short-circuit for method arguments.

The tests missed it because they asserted on the returned dict, not on side effects. The cache does return the same object on every call β€” after all, the first-inserted value wins β€” but every miss and every hit still pays the full cost of creating a fresh session that immediately gets thrown away. On a lightly-loaded dev box, the wasted connections are invisible. Under production concurrency, they saturate the pool.

The performance hit is bad enough; the correctness hit is worse when create_session has side effects β€” inserting an audit row, incrementing a rate-limit counter, minting a token. Every "cache hit" now emits an audit row for a session that will never be used.

The Fix

Guard the expensive call yourself, or use a construct that actually is lazy:

# Option 1: explicit check. Boring, obvious, correct.
def get_session(user_id, cache):
    if user_id not in cache:
        cache[user_id] = create_session(user_id)
    return cache[user_id]

# Option 2: defaultdict, if the factory takes no args.
from collections import defaultdict
sessions = defaultdict(lambda: create_session_for_current_context())

# Option 3: functools.lru_cache when the "cache" IS the memoization.
from functools import lru_cache
@lru_cache(maxsize=None)
def get_session(user_id):
    return create_session(user_id)

The same trap applies to dict.get(key, default): the default is always evaluated. It doesn't matter as often there because get's default is usually a literal like 0 or None, but the moment someone writes d.get(k, fetch_from_api()), the bug is back.

Rule of thumb: if the "default" is anything more expensive than a literal or an already-constructed object, setdefault and get are the wrong tools. Use if key not in d, use defaultdict with a factory, or use a real memoization decorator.

Key Takeaway: dict.setdefault(k, expensive()) evaluates expensive() on every call β€” Python has no lazy arguments, so what looks like a cache is a cache plus a fresh side effect on every hit.

Daily Digital Circuits

Adaptive Body Biasing Loops: How Hardware Compensates for Process Variation by Tuning Threshold Voltage in a Feedback Loop

2026-09-08

You already know about body biasing β€” applying a voltage to the transistor's bulk terminal to shift threshold voltage (Vt). Reverse body bias raises Vt (less leakage, slower); forward body bias lowers Vt (faster, leakier). What we didn't cover: how a chip decides how much to apply, and updates it while running.

Every die comes off the wafer with a different process corner. A "fast" die has low Vt β€” it hits frequency easily but leaks like a sieve. A "slow" die barely meets timing at nominal voltage. Traditionally you bin them: fast dies get sold as high-performance parts, slow ones get downclocked. But binning wastes silicon, and both corners drift with temperature and aging.

Adaptive Body Bias (ABB) closes the loop. On-die sensors measure how fast the current process/voltage/temperature corner actually is, and a controller tunes the body-bias voltage to hit a target speed.

  • Speed sensor: a ring oscillator or critical-path replica whose frequency directly tracks the logic it mimics. Count its edges over a reference window.
  • Comparator: compare measured frequency against a target derived from the required clock speed plus margin.
  • Charge pump + regulator: generate the body-bias voltage (often outside the 0-to-VDD rail β€” negative for NMOS reverse bias, above VDD for PMOS reverse bias). See our Dickson charge pump lesson.
  • Controller: typically a slow digital loop (kHz-range updates) that nudges the bias voltage until the replica hits target.

Real example: Intel's Montecito Itanium (2006) used ABB per-core to compensate for die-to-die variation. Fast cores got reverse bias to cut leakage without losing frequency; slow cores got forward bias to reach the target clock. The chip effectively converted every die into a "typical" die at runtime, boosting yield and dropping leakage power by roughly 2Γ— on fast corners.

Rule of thumb: in modern bulk CMOS, each 100 mV of body bias shifts Vt by about 20–30 mV (the body-effect coefficient Ξ³ is roughly 0.2–0.3). To move Vt by 50 mV you need ~200 mV of bias, and the resulting leakage change is exponential β€” roughly 10Γ— per 80 mV of Vt shift at room temperature.

The catch: FinFETs (7nm and below) have almost no body effect because the fin is fully depleted and there's no meaningful bulk terminal to bias. ABB is a bulk-planar and FD-SOI technique. FD-SOI actually expanded the useful bias range to Β±3V, making ABB a signature feature of ST's 28nm and 22nm FD-SOI processes.

Key Takeaway: Adaptive body biasing turns each die's process corner into a runtime-controllable knob, using an on-chip speed sensor and charge pump to servo threshold voltage against a target β€” trading exponential leakage savings for a slow digital feedback loop.

Daily Electrical Circuits

Deboo Integrator: Non-Inverting Integration Without the Sign Flip

2026-09-08

The classic op-amp integrator inverts. That's fine for a lot of signal processing, but sometimes you need positive-going output for positive-going input β€” driving a scope timebase, ramping a control voltage, or feeding a downstream stage that expects the correct polarity. Cascading two inverting stages works but doubles the noise, offset, and parts count. The Deboo integrator solves this with a single op-amp by exploiting the Howland current-source topology.

How it works: The circuit uses a non-inverting op-amp with matched resistor networks and a grounded capacitor on the non-inverting input. The op-amp forces a current into the capacitor proportional to Vin, so the cap voltage ramps linearly. Because we're using the non-inverting input, the output tracks in the same direction as the input β€” no sign inversion.

Standard topology:

  • Input resistor R to the non-inverting pin
  • Capacitor C from non-inverting pin to ground
  • Feedback network: R from output to inverting pin, R from inverting pin to ground
  • Second R from Vin to non-inverting pin (matched to feedback R)

With all four resistors equal, the transfer function becomes Vout(s) = Vin(s) / (sRC) β€” a pure non-inverting integrator with time constant Ο„ = RC.

Real-world example: You're building a triangle-wave generator for a Class-D audio modulator, and the comparator downstream expects a positive ramp on positive input. You want a 20 kHz triangle from a Β±5 V square wave. Pick RC to yield a 25 Β΅s half-period ramp of 5 V peak: with a 5 V step input, dV/dt = Vin/(RC) = 5 V / 25 Β΅s = 200 kV/s. Choose C = 1 nF, then R = 5 V / (200,000 Γ— 1 nF) = 25 kΞ©. Use four matched 25 kΞ© 0.1% resistors β€” matching is critical.

The catch β€” resistor matching: The Deboo depends on the Howland balance condition. Any mismatch in the four resistors creates a finite input impedance at DC, which either causes the output to run away to a rail (positive feedback) or bleed off the integration (negative feedback). Rule of thumb: use 0.1% resistors minimum, and if you need long integration times (>10 ms), consider a reset switch (JFET or analog switch) across C to periodically zero the output.

Bonus: Because the capacitor is grounded (not floating like the inverting integrator's feedback cap), you can use polarized electrolytics for very long time constants β€” as long as the DC bias stays positive.

See it in action: Check out Op-Amp Saturation Problem No-1 by A 2 Z Engineering Classes to see this theory applied.
Key Takeaway: The Deboo integrator gives you non-inverting integration with a single op-amp and a grounded capacitor, but its accuracy lives or dies on the matching of four equal resistors β€” spec 0.1% or better.

Daily Engineering Lesson

Push-On External Retaining Rings (Star Washers / Palnuts): The Fastener That Installs with a Hammer and Never Comes Off

2026-09-08

You've seen these on cheap toys, casters, and appliance shafts: a flat stamped-steel disc with internal teeth, pressed onto a plain shaft with no groove. No snap ring pliers, no machining, no torque spec β€” just push it on with a socket or a mallet, and it stays forever. These are push-on retaining rings, sometimes called starlock washers, Palnuts, or push-nuts, and they're one of the cheapest permanent fasteners in industry.

How they grip: The internal teeth are stamped at an angle, sloping inward toward the direction of installation. When you press the ring onto the shaft, the teeth flex outward slightly and bite into the shaft surface. Try to pull the ring off, and the teeth dig harder β€” the geometry is a one-way ratchet. The holding force comes from elastic spring-back of the teeth combined with metal-to-metal friction and localized plastic deformation of the shaft.

Design rules of thumb:

  • Shaft must be softer than the ring. Push-on rings are hardened spring steel (Rockwell C 47–52). The shaft should be mild steel, brass, aluminum, or plastic. Try to press one onto hardened dowel pin and the teeth skate.
  • Shaft diameter tolerance is loose β€” typically the nominal shaft size Β±0.005". The teeth accommodate the slop.
  • Holding force β‰ˆ 2–4Γ— the axial installation force. A 1/4" push-on that takes 40 lb to install will resist ~120 lb of pull-off before the teeth slip.
  • Single-use only. Removal permanently deforms the teeth. To remove: pry, cut, or grind β€” plan on destroying the ring.

Real-world example: Look at the axle of a shopping cart caster. The wheel spins on a plain steel axle with no groove, no cotter pin, no threads. A push-on cap on each end holds the wheel captive. Assembly time: two seconds per side with a pneumatic press. Cost: pennies. It will outlast the cart.

When to specify one: Light axial loads (under ~100 lb for small sizes), non-serviceable assemblies, high-volume consumer goods, and any application where machining a retaining ring groove would double the shaft cost. Common on furniture casters, small motor shafts, appliance linkages, toys, and lawn equipment.

When NOT to use them: Anything requiring field service, high cyclic axial loads, precise axial positioning (there's typically 0.010–0.030" of play), or hardened shafts. Vibration and thermal cycling can walk them loose over years β€” fine for a $12 caster, bad for a safety-critical joint.

Key Takeaway: Push-on retaining rings trade serviceability and precision for near-zero part cost and instant assembly β€” the right choice when the shaft is soft, the load is light, and nobody ever needs to take it apart.

Forgotten Books

Iron Tanning: The Forgotten Middle Child Between Oak Bark and Chromium

2026-09-08

Book: Iron tannage by Hou, Te-Pang, 1890- (1921)

Read it: Internet Archive

Ask anyone how leather gets made and you'll hear one of two answers: the ancient way (soaking hides in tannin-rich oak or hemlock bark for months) or the modern way (chrome tanning, which turns hides into leather in a single day using chromium salts). Almost nobody remembers there was a third contender that occupied chemists for over a century.

Te-Pang Hou opens his 1921 Columbia dissertation with a startling historical claim:

As early as the latter half of the eighteenth century iron salts as tanning agents were proposed and experimented upon. From that time on attempt after attempt [was made].

Hou's dissertation methodically works through ferric hydroxide hydrosol tannage, chrome-iron joint tannage, pure iron tannage, and iron phosphate tannage β€” each a serious industrial proposal, each now essentially forgotten. The table of contents alone reads like a lost chemistry: "Hydrolysis and Decomposition of Ferric and Chromic Salts Compared," "On the Relation of Basicity to Stability in Iron Liquor," "Behavior of the Pelt towards Iron Tan Liquor."

The appeal was obvious to anyone paying attention in 1921. Vegetable tanning took months and required stripping forests. Chrome tanning, patented in 1858 and industrialized by the 1890s, was fast β€” but chromium was expensive, and its waste was already understood as a nasty pollutant. Iron salts, by contrast, were byproducts of steel pickling: essentially free, produced in vast quantities, and made from an element that constitutes 5% of the Earth's crust.

So why don't we all wear iron-tanned shoes? Hou's own experiments hint at the answer: iron-tanned leather tends to oxidize and turn reddish-brown, becomes brittle, and β€” critically β€” keeps reacting after the tanning is done. A chrome bond is stable. An iron bond wants to keep talking to oxygen. Your beautiful leather boot slowly rusts itself into a cracked husk.

What's remarkable in retrospect is who wrote this dissertation. Te-Pang Hou β€” the "Hou" of the Hou process β€” went on to become one of the most important industrial chemists of the twentieth century, revolutionizing soda ash production and becoming a founding figure of modern Chinese chemical industry. His first published work was an attempt to salvage a doomed technology by careful attention to basicity and hydrolysis. The insights he developed there β€” how metal ions bind to protein at controlled pH β€” are exactly the ideas that made him famous later.

There's a modern echo here worth noting: with chromium tanning under environmental pressure in the EU and elsewhere, researchers have quietly returned to iron-based tannages in the last decade, sometimes combined with plant polyphenols that stabilize the iron-collagen bond. The oxidation problem Hou described in 1921 is still the central obstacle. A hundred years later, the same puzzle sits on the same desk.

The forgotten claim: Iron salts were seriously investigated as a leather tanning agent for over 150 years β€” cheap, abundant, and almost workable β€” but the metal's stubborn tendency to keep oxidizing turned every promising batch of leather into a slowly rusting shoe.

Forgotten Darkroom

The Cold War Chemistry of "Neutral" Ions: A Soviet Insight Buried in a CIA File

2026-09-08

Book: PROCEEDINGS OF THE DEPARTMENT OF CHEMICAL SCIENCES by CIA Reading Room (1950)

Read it: Internet Archive

Buried in a declassified CIA translation of a Soviet chemistry journal from August 1949 sits a quietly radical claim by N. A. Izgaryshev, a corresponding member of the Academy of Sciences of the USSR. The document β€” stamped "CONFIDENTIAL" and marked 50X1-HUM, indicating human intelligence sourcing β€” was flagged as important enough for American analysts to translate, redact, and file away. Why would U.S. intelligence care about a Russian paper on electrolysis?

The paper's title is "The Relation of Electrooxidization Processes to the Nature of Positively Charged Ions." The CIA summary explains:

The author's investigations in this field are a further development of his study of the influence of "neutral" ions on the functioning of electrode processes, i.e., of ions which are present in electrolyzed solutions, but which should not have a direct effect upon the basic electrode process.

Read that again. Izgaryshev was arguing β€” in 1949 β€” that ions chemists had dismissed as chemically inert spectators were silently steering the outcome of electrochemical reactions. The scare quotes around "neutral" are the CIA translator's, but they preserve Izgaryshev's own skepticism. He was saying: the potassium, the sodium, the lithium sitting there in your electrolyte, the counter-ions you wrote off as bookkeeping β€” they matter. He tested this on chlorides of magnesium, calcium, barium, potassium, sodium, lithium, rubidium, and ammonium, and again on persulfate production across calcium, ammonium, lithium, magnesium, zinc, and aluminum systems.

Was he right? Astonishingly, yes β€” and modern electrochemistry has spent the last two decades catching up. Today's papers on the "electric double layer," on cation-specific effects in COβ‚‚ reduction, on the way lithium versus sodium versus potassium ions in a battery electrolyte can double or halve a catalyst's selectivity, are all describing the same phenomenon Izgaryshev was chasing with 1940s Soviet lab equipment. In 2022, Nature Catalysis papers on "cation effects" in electrocatalysis regularly frame the finding as surprising. It wasn't surprising to Izgaryshev in 1949.

Why did the CIA translate it? Persulfate chemistry β€” the second half of his study β€” matters for rocket oxidizers, for uranium processing, and for high-energy chemical weapons precursors. Anode processes for producing calcium and aluminum persulfates efficiently were of enormous industrial and military interest in 1949, the same year the Soviets tested their first atomic bomb. American analysts were combing Soviet chemistry journals for hints of the industrial capacity behind that program.

The forgotten piece here isn't the chemistry β€” it's the shape of the discovery. A Soviet chemist saw that "inert" wasn't inert, published it in a Moscow monthly, and the paper's most attentive readers turned out to be spies. The scientific insight then had to be independently rediscovered by Western electrochemists decades later, because the citation chain was severed by the Iron Curtain.

The forgotten claim: The "spectator" ions in an electrolyte aren't spectators β€” they change what happens at the electrode, a fact Soviet chemist N. A. Izgaryshev published in 1949 and Western electrochemistry rediscovered seventy years later.

Forgotten Patent

Elmer Sperry's "Gyroscopic Apparatus for Aeroplanes": The 1914 Autopilot That Flew a Plane Hands-Off While a Man Walked on the Wing β€” and Now Steers Every Airliner, Drone, and Self-Driving Car

2026-09-08

On June 18, 1914, over the Seine outside Paris, a Curtiss C-2 flying boat approached the judges of the Concours de la SΓ©curitΓ© en AΓ©roplane at 50 mph. The pilot, Lawrence Sperry, took his hands off the controls and raised them above his head. His mechanic, Emile Cachin, then climbed out of the cockpit and walked six feet along the right wing. The plane didn't roll. It didn't pitch. It flew straight and level, with a 170-pound man dangling off one side. The French crowd went wild; the judges awarded a 50,000-franc prize.

What kept the plane level was a set of four spinning gyroscopes, wired to the elevators, rudder, and ailerons through an electric servo system, all built by Lawrence's father, Elmer Ambrose Sperry. Sperry had filed the foundational patents starting in 1912 β€” most notably US Patent 1,368,226, "Airplane Stabilizer," and a family of related filings that ran through 1917. The invention was, in every meaningful sense, the first autopilot.

How it worked (in plain language): A gyroscope that's already spinning resists any attempt to tilt its axis. Sperry mounted two gyros on gimbals inside the plane β€” one aligned to detect pitch and roll, the other to detect yaw. When the plane deviated from level, the frame of the aircraft moved relative to the still-pointing gyro. That mechanical displacement closed electrical contacts. The contacts drove pneumatic servomotors. The servos pulled cables to the control surfaces. Deviation in β†’ correction out. It was a complete closed-loop feedback control system, running in analog, in 1914 β€” before radio navigation, before reliable altimeters, before the vacuum tube was even a decade old.

Why it matters now:

  • Every autopilot descends from it. Modern Airbus and Boeing fly-by-wire systems are enormously more complex, but the architecture β€” sense attitude, compare to reference, drive actuators β€” is Sperry's 1914 loop.
  • Inertial navigation. The gyro-plus-accelerometer scheme that guided Apollo to the moon and now steadies every submarine, ICBM, and airliner grew directly out of Sperry's stabilizer work at what became Sperry Gyroscope Company β€” later absorbed into Honeywell and Unisys.
  • Drones. A DJI quadcopter that holds position in wind is running the identical control law, just with MEMS gyros costing pennies instead of brass ones costing a fortune.
  • Self-driving cars. The IMU (inertial measurement unit) inside every autonomous vehicle is a 6-axis miniaturization of Sperry's rig.
  • Smartphone screen rotation, VR headset tracking, camera image stabilization β€” all use the same sense-compare-actuate pattern, now etched into silicon at MEMS scale.

The surprising part: Sperry didn't just invent a device. He operationalized feedback control theory in a physical machine two decades before Nyquist and Bode formalized it mathematically. Engineers building drone flight controllers today still tune PID loops that would look conceptually familiar to Sperry in 1914 β€” proportional response to error, integral response to persistent bias, derivative response to rate of change.

Lawrence Sperry later died in a 1923 crash over the English Channel. His father lived to see gyros stabilize battleship guns in WWI and ocean liners at sea. Neither lived to see one hold a Cessna on a GPS-defined arc β€” but that Cessna is running their patent.

Key Takeaway: The autopilot wasn't invented in the jet age or the computer age β€” it flew hands-off with a man on the wing in 1914, and every drone, airliner, and self-driving car since is running Elmer Sperry's feedback loop.

Daily GitHub Zero Stars

DominicSicilian/college_football_rankings

2026-09-08

This is one of those rare zero-star repos that quietly punches way above its weight. It's a resume-based college football ranking algorithm that judges teams strictly on what they've done on the field β€” no talent priors, no preseason polls bleeding into the math, no circular "good teams beat good teams because they're good teams" logic. Just accomplishments, strength of schedule, and quality of play.

What makes it genuinely interesting is the honesty of the framing. The author is upfront that this is a resume model, not a predictive talent model β€” and yet it still correctly predicts game winners around 72% of the time across 4,500+ games from 2021 through 2026. That's a striking result for a system that intentionally handicaps itself by refusing to peek at recruiting rankings, betting lines, or advanced tracking data. It suggests that "who you actually beat and how" carries more signal than the sports discourse usually gives it credit for.

The repo also auto-updates weekly, which turns it from a static academic exercise into a living leaderboard you can actually follow through a season. For a solo Python project with no marketing, that's real engineering discipline.

Who benefits:

  • Sports analytics hobbyists looking for a clean, opinionated alternative to the CFP committee or AP poll.
  • Data science learners β€” the "avoid circular logic" problem is a fantastic case study in feature design and iterative ranking (think PageRank cousins, Massey/Colley variants).
  • CFB fans who want a defensible answer to "did my team's schedule really matter?" without wading through paywalled advanced-stats sites.
  • Bettors and pool players, though the author wisely doesn't pitch it that way.

It's the kind of project where the constraints are the interesting part. Building a good ranker is easy if you let it see everything; building one that only looks at results and still hits 72% is a much harder problem, and worth studying.

Why check it out: A principled, transparent college football ranking system that proves resume-only models can rival talent-aware predictors.

Daily Hardware Architecture

The Store Buffer's Store-to-Store Forwarding: Why Two Writes to the Same Line Don't Always Merge

2026-09-08

When your code executes two stores to the same cache line back-to-back, you'd expect the CPU to just merge them in the store buffer and send one write downstream. Sometimes it does. Often it doesn't. Understanding when store-to-store forwarding kicks in β€” and when it silently fails β€” explains a surprising class of performance mysteries.

What the store buffer actually holds. Each entry tracks an address, a data payload, a byte-valid mask, and an age tag. When a new store retires into the buffer, the coalescing logic scans older entries for the same cache line. If it finds one that hasn't drained yet, the two may merge into a single entry with a combined byte mask. The merged entry then drains to L1 as one write, saving a cache port cycle and a coherence transaction.

When merging fails. Several conditions block coalescing:

  • Different memory types. A WB store and a WC store to the same line never merge β€” they follow different ordering rules.
  • Intervening fence. An SFENCE or MFENCE between the two stores forces the older one to drain before the younger one enters the merge window.
  • Older store already committed. Once a store leaves the buffer and hits L1, it's gone from the coalescing pool. Younger stores get their own entry.
  • Overlapping-but-different-width writes with dependencies. If a load between the two stores forwards from the first one, the CPU sometimes keeps them separate to preserve the forwarding path.
  • Buffer pressure. Some microarchitectures skip the associative merge check when the store buffer is under 25% full β€” the search costs more than the savings.

Real-world example. Consider a struct-init loop writing eight 8-byte fields of a 64-byte struct sequentially. With merging: one 64-byte write drains from the store buffer to L1. Without merging (say, because SFENCE separates each write in a persistence library like PMDK): eight separate L1 writes, eight coherence upgrades if the line was Shared, and ~8Γ— the store buffer occupancy. Benchmarks on Skylake show a 3–4Γ— slowdown when persistence fences defeat coalescing on hot cache lines.

Rule of thumb. On modern x86, expect coalescing to succeed for stores within roughly 10–20 cycles of each other to the same 64-byte line, with no fence between them, and same memory type. Outside that window, assume each store drains independently. A single MFENCE typically forces at least 20–40 cycles of drain latency because it must flush every pending buffer entry before proceeding.

The takeaway: store coalescing is silent when it works and invisible when it fails. Perf counters like MEM_INST_RETIRED.STLB_MISS_STORES and store-buffer-full stall events are the only way to see it.

See it in action: Check out Redmi 14c I How to Enable the Developer Options I For Usb Debugging Etc 2025// by SR Unlocker to see this theory applied.
Key Takeaway: The store buffer merges adjacent writes to the same cache line into single drains β€” but fences, memory-type mismatches, and forwarding dependencies quietly disable the optimization and multiply your store traffic.

Hacker News Deep Cuts

What WiFi Knows About Your Body

2026-09-08

Every WiFi packet in your home is passing through β€” and being subtly reshaped by β€” your body. This post almost certainly walks through the growing field of WiFi sensing: the practice of inferring physical presence, posture, breathing rate, gait, and even keystrokes from Channel State Information (CSI) collected by ordinary 802.11 radios.

The technical foundation is genuinely elegant. A WiFi access point transmits a known preamble across dozens of OFDM subcarriers. The receiver measures amplitude and phase distortion per subcarrier to equalize the channel. That per-subcarrier CSI matrix is, incidentally, a high-dimensional fingerprint of every reflector in the room β€” walls, furniture, and warm wet sacks of water that happen to be moving around. Feed a sequence of CSI frames into a small CNN or transformer and you get:

  • Presence and count β€” how many people are in a room, through walls
  • Vital signs β€” chest rise from breathing modulates the signal at ~0.2 Hz; heartbeats at ~1 Hz are visible with enough averaging
  • Activity recognition β€” sitting, walking, falling (the "grandma sensor" pitch)
  • Gait identification β€” individuals have distinguishable CSI signatures, meaning WiFi can, in principle, identify who is walking past
  • Keystroke inference β€” finger micro-motions near a laptop alter multipath in measurable ways

The technical audience angle is threefold. First, this is a privacy story hiding in plain sight: the 802.11bf amendment (ratified to standardize sensing) means your next router may ship WiFi sensing as a feature, and there is no equivalent of a camera LED to tell you it's on. Second, it's a signal-processing playground β€” CSI extraction used to require patched Intel 5300 firmware, but the Nexmon and ESP32-CSI toolchains have democratized it. You can build a through-wall breathing monitor for under $20. Third, it reframes threat models: an attacker who compromises your neighbor's router may not need to see your screen to know when you're home, when you're asleep, and roughly what you're typing.

Most engineers still think of WiFi as a data pipe. It's also a radar, a biometric sensor, and β€” increasingly β€” a surveillance surface baked into every building. Worth the ten minutes.

Why it deserves more upvotes: WiFi sensing via CSI is quietly becoming an IEEE standard while most technologists still don't realize their router is a low-resolution radar pointed at their bedroom.

HN Jobs Teardown

Lark Health: What Their Hiring Reveals

2026-09-08

Source: HN Who is Hiring

Posted by: maxbreaker

Lark Health's posting is a fascinating time capsule: an "Onsite [All remote for now]" tag in a Mountain View job listing, written by a VPE who casually notes "Healthcare, very important right now." That parenthetical does enormous work β€” this is a company scrambling to hire in the opening weeks of a global health emergency, and every word of the posting reflects it.

The Stack: JavaScript/TypeScript, Java, Kubernetes, AWS, Serverless, and React Native. This is a revealing combination:

  • React Native as a first-class hire signals a mobile-first product β€” unsurprising for a digital health coaching app, but the "Senior" qualifier suggests they've hit the pain point where hybrid apps start requiring native module expertise.
  • Kubernetes + Serverless + AWS together is telling. Most companies pick one orchestration philosophy; running both suggests either a migration in progress or a bifurcated architecture (long-running services in K8s, event-driven glue in Lambda). Either way, it's expensive to maintain β€” hence the Manager for the DevOps/Infrastructure team role.
  • Java alongside JS/TS hints at a legacy backend being wrapped or slowly replaced by Node services β€” a very common mid-stage pattern.

What the posting reveals: Lark is past product-market fit and deep in scaling pain. The role list is a diagnostic:

  • Multiple Engineering Managers = org is doubling, spans-of-control breaking.
  • Dedicated DevOps manager + senior DevOps ICs = infrastructure has outgrown the "one SRE holds it together" phase.
  • Generic "Backend Engineers" (plural, unspecified) = they need bodies, not specialists.

Skills/trends highlighted: The K8s-on-AWS expert has become the single most leveraged hire in mid-stage startups circa 2020. Also notable: healthcare tech's sudden willingness to abandon its historic on-prem/HIPAA-driven onsite culture in favor of remote work β€” the "[All remote for now]" is a hedge, but a hedge that quietly rewrites the industry's hiring geography.

Red flags: The posting is strategically vague. No compensation, no team sizes, no product specifics beyond "healthcare." "Preferred stack" listing six technologies suggests either a polyglot mess or unclear architectural ownership. The chipper "Come and help us make the world healthier! :)" tone with an emoji from a VPE reads as recruiting-by-vibes rather than a considered pitch.

Green flags: A VPE posting personally (rather than a recruiter) means direct hiring authority and faster loops. The willingness to convert an onsite role to remote β€” even temporarily β€” indicates organizational flexibility that many 2020-era healthcare companies lacked.

The signal: Healthcare tech is being forcibly modernized in real time β€” the companies that survive will be the ones whose VPEs can hire Kubernetes talent faster than their infrastructure debt accrues.

Daily Low-Level Programming

The x86 CMOVcc Instructions: Conditional Moves That Beat Branch Prediction on Unpredictable Data

2026-09-08

The CMOVcc family (CMOVE, CMOVNE, CMOVL, CMOVG, ...) is a conditional move: CMOVcc dst, src copies src into dst only if the flags satisfy the condition. Introduced with the Pentium Pro (1995), it lets the compiler turn a tiny branch into a straight-line sequence with a data dependency instead of a control dependency.

Why does that matter? A mispredicted branch on modern x86 costs 15–20 cycles because the entire pipeline (Reorder Buffer, ~200 in-flight Β΅ops) is flushed. CMOV never mispredicts β€” but it forces the dependent value to wait for the flags to resolve, adding roughly 1 cycle of latency on the critical path. The rule of thumb:

  • If the branch is predicted correctly >95% of the time, use a branch. Predicted branches are effectively free (0 cycles).
  • If the branch is data-dependent random (say a coin-flip on unsorted input), use CMOV. A 50% mispredict rate averages ~10 cycles of penalty vs CMOV's ~1 cycle.
  • Break-even is around 1/(mispredict penalty) β‰ˆ 5–7% mispredict rate.

Concrete example β€” the classic sorted-vs-unsorted array benchmark:

for (i = 0; i < N; i++)
    if (data[i] >= 128) sum += data[i];

On sorted data, GCC emits a JGE branch, the predictor hits ~100%, and the loop runs at ~1.5 ns/element. On the same data shuffled, the branch mispredicts ~50% and slows to ~10 ns/element β€” the famous 6Γ— slowdown. Compile with -O2 and modern GCC/Clang often emit CMOV instead: both sorted and shuffled runs land near ~2.5 ns/element. Sorted got slower; shuffled got 4Γ— faster.

The gotcha compilers know but you might not: CMOV always reads the source operand, even when the condition is false. This matters for two reasons:

  • You cannot use CMOV to guard a load from a potentially-invalid pointer β€” the load happens either way. if (p) x = *p; won't be if-converted.
  • CMOV is constant-time with respect to the condition. Crypto code deliberately uses it (__builtin_ctz-style tricks, CMOVE for constant-time selects) to avoid leaking secrets through branch timing side channels.

To force the compiler's hand: x = cond ? a : b; written on a plain scalar with no side effects is the idiom that most reliably lowers to CMOV. Check with -S or godbolt. If you see jne/je in a hot loop where the data is random, hand-massage the source or use __builtin_expect_with_probability(..., 0.5) to signal unpredictability.

Key Takeaway: CMOV trades a ~1-cycle latency dependency for the ~15-cycle mispredict penalty β€” a win only when the branch is genuinely unpredictable, and a mandatory tool when the timing must not depend on the condition.

RFC Deep Dive

RFC 874: A Critique of X.25

2026-09-08

RFC: RFC 874

Published: 1982

Authors: M.A. Padlipsky

RFC 874 is not a protocol specification. It is a polemic β€” a sharp-tongued essay from MITRE's Mike Padlipsky arguing that CCITT's X.25 packet-switching standard was a technical dead end and that anyone considering it as an alternative to the ARPANET protocols was making a serious mistake. In 1982, this was a live question: the telecom world (PTTs, CCITT, and the emerging OSI camp) was pushing X.25 as the way to build public data networks, and the U.S. DoD was under real pressure to align.

Padlipsky's central charge is a layering violation. X.25, he argues, conflates the network access protocol (how a host talks to its local packet switch) with an end-to-end virtual circuit abstraction. In the ARPANET model β€” later canonized as TCP/IP β€” the host-to-IMP protocol (RFC 1822) was strictly a local matter, and end-to-end reliability lived in a separate transport layer (TCP). X.25 fused these, so a "virtual circuit" wasn't actually end-to-end; it was really a concatenation of local circuits stitched together by the network, with hop-by-hop acknowledgements masquerading as end-to-end delivery guarantees.

His specific complaints, still worth reading today:

  • False end-to-end semantics. X.25 acknowledgements from the local switch don't mean the far host received anything. Applications that trust them will corrupt data.
  • Connection-oriented in the wrong layer. Forcing every conversation through a network-layer virtual circuit denies applications the choice of datagram service, which is cheaper and simpler for many workloads (DNS, RPC, telemetry β€” everything we now build on UDP).
  • Byte-count and window semantics leak across boundaries. Flow control at the network interface interferes with flow control the transport layer needs to do anyway.
  • "Interface" confused with "protocol." X.25 was a specification for how a host plugs into a specific carrier's network β€” a local interface β€” but was marketed as an internetworking solution.

The essay is written in Padlipsky's trademark style: acerbic, footnoted, self-aware, and occasionally hilarious. He coined the phrase "the ARPANET reference model" as a jab at OSI's seven-layer edifice, and RFC 874 is part of a broader body of work (collected in his 1985 book The Elements of Networking Style) arguing that the internet's rough-consensus, running-code culture would beat the standards-committee approach. History proved him spectacularly right.

Why read it in 2026? Because the arguments are structural, not historical. Every time someone proposes a "smart" network that terminates connections on your behalf, provides "reliable" delivery at layer 3, or fuses application semantics into transport (looking at you, some middleboxes and some service meshes), Padlipsky's critique applies verbatim. The end-to-end principle β€” later formalized by Saltzer, Reed, and Clark β€” has one of its clearest early defenses right here. QUIC's design decision to run its own transport over UDP rather than trust the network is a direct descendant of this reasoning.

It's also just good writing. RFCs today are dry by policy; RFC 874 reminds you that the early internet community was a small group of engineers with strong opinions, and they weren't afraid to publish them under the RFC banner. The series was, quite literally, a request for comments β€” including comments like "this competing standard is broken and here's why."

Why it matters: RFC 874 is the clearest early articulation of why end-to-end semantics must live above the network layer β€” a lesson the industry has to re-learn every time someone invents a "smarter" network.

Stack Overflow Unanswered

How to properly add a new section in internal RAM without breaking this linker script?

2026-09-08

Stack Overflow: View Question

Tags: c, linker, embedded, advice

Score: 0 | Views: 115

The asker is working on a Cortex-M7 firmware project and needs to introduce a brand-new output section β€” .new_section β€” that must live at the very beginning of internal RAM. The existing linker script already places .relocate, .bss, and the stack in RAM, all driven by symbols like _srelocate, _erelocate, and _sstack that the C runtime uses during startup to copy initialised data from flash and zero out BSS.

What makes this interesting is that a linker script is not just a layout description β€” it is a contract with the startup code. Naively prepending a new section changes the addresses that _srelocate and _sbss resolve to, which can silently break the boot process: the copy loop will write to the wrong place, or BSS clearing will trample your new section. On top of that, the Cortex-M7 has tight rules for the vector table (must be at the start of RAM if remapped) and for MPU-protected regions (base must be aligned to region size).

Direction toward a solution:

  • Define .new_section as the first output section in the RAM region, with an explicit ALIGN matching its intended MPU alignment. Something like:
    .new_section (NOLOAD) :
    {
        . = ALIGN(32);
        _snew_section = .;
        KEEP(*(.new_section .new_section.*))
        . = ALIGN(4);
        _enew_section = .;
    } > ram
  • Use NOLOAD if the section only needs runtime storage (no flash image). Drop it if you want initialised data copied from flash β€” but then you also need a load-address (AT>) and copy loop.
  • Attach data via a __attribute__((section(".new_section"))) in C, so nothing accidentally falls into it.
  • Leave the existing _srelocate/_sbss/_estack symbols anchored to the sections they describe β€” do not hoist them above your new section, or startup will misbehave.

Gotchas:

  • If the vector table was remapped to the RAM base (SCB->VTOR), pushing it down by sizeof(.new_section) means VTOR must be updated too β€” and it has its own alignment constraint (next power of two β‰₯ table size, minimum 128 bytes).
  • For MPU use, the section's size must be padded up to a power of two, or you'll fail to configure the region. Use . = ALIGN(size); . += size; tricks or a . = ORIGIN(ram) + poweroftwo; guard.
  • The DTCM vs regular SRAM distinction on M7 matters β€” "internal RAM" may actually be two disjoint regions, and only one is at a fixed low address.
The challenge: Linker scripts are a silent contract with startup code and the MPU β€” moving one symbol by a few bytes can break boot in ways that only surface after the CPU is already running.

Daily Software Engineering

The Sharding Pattern: Splitting Data Across Nodes When One Machine Can't Hold It All

2026-09-08

Sharding is horizontal partitioning: you split your dataset across N machines so each holds ~1/N of the data. You do this when a single node can no longer handle the storage, write throughput, or working-set memory of your workload. Replication makes copies; sharding makes slices. Most real systems do both.

The whole game is picking a shard key. Every read and write is routed by hashing or ranging on this key, so if you pick wrong, you'll pay for years. Three common strategies:

  • Hash-based sharding: shard = hash(key) % N. Even distribution, but range queries hit every shard, and adding a node reshuffles almost everything (fix this with consistent hashing).
  • Range-based sharding: shard 1 holds keys A–F, shard 2 holds G–M, etc. Range scans are fast, but sequential keys (timestamps, auto-increment IDs) create write hotspots on the "last" shard.
  • Directory-based sharding: a lookup service maps key β†’ shard. Maximum flexibility, but the directory becomes a single point of failure and a coordination bottleneck.

Real example: Instagram sharded Postgres by user ID. Every user's photos, comments, and likes live on the same shard, so loading a profile is one shard hit. But cross-user queries ("photos liked by users I follow") become expensive scatter-gather operations. That's the trade β€” you optimize for the 95% access pattern and eat the cost of the 5%.

The hotspot problem: If you shard tweets by user_id and one user has 200M followers (hi, Taylor Swift), that shard melts under fan-out writes while others idle. Fix: sub-shard hot keys, or use a hybrid key like hash(user_id, tweet_id % 100).

Rule of thumb for shard count: pick more shards than you think you need β€” typically 10–100Γ— your current node count. Rebalancing shards between nodes is cheap; splitting a shard in half under production load is nightmare fuel. Vitess, MongoDB, and Cassandra all lean into "many small shards" for this reason.

What breaks after you shard:

  • Joins across shards are now application-level scatter-gather.
  • Transactions spanning shards need 2PC or sagas (both painful).
  • Unique constraints on non-shard-key columns require a coordination layer or global index.
  • Resharding is a migration project, not a config change.

Don't shard until you have to. Vertical scaling, read replicas, and archival tables buy you years. Sharding is a one-way door β€” reverse it and you're rewriting your data layer.

See it in action: Check out What is DATABASE SHARDING? by Gaurav Sen to see this theory applied.
Key Takeaway: Sharding trades single-node simplicity for horizontal scale, and the shard key you pick on day one will define what queries stay cheap and which ones become distributed disasters for the life of the system.

Tool Nobody Knows

abidiff (libabigail): The ABI-Aware Diff That Tells You Whether Bumping libfoo.so.1 Will Actually Break Everything Linked Against It

2026-09-08

Semantic versioning is a promise. Shared-library ABIs are the reality. If you've ever bumped a package from 1.4.2 to 1.4.3, run ldconfig, and watched half of userspace segfault, you already know the mainstream answer β€” "compare headers, cross your fingers, run the tests" β€” misses the vast space of breakages that don't touch a single line of source: struct padding shifts because someone added a member in the middle, enum values renumber because a new constant landed at the top, a virtual method reorders and vtables slide by eight bytes.

libabigail is Red Hat's toolkit for this. Its flagship tool abidiff reads DWARF debug info from two ELF binaries and reports, at the actual ABI level, what changed and whether it's a compatibility break. You do not need source. You need debuginfo.

$ abidiff libfoo.so.1.4.2 libfoo.so.1.4.3
Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 3 Added
Variables changes summary: 0 Removed, 0 Changed, 0 Added

1 function with some indirect sub-type change:
  [C] 'function int foo_process(struct foo_ctx*, size_t)' at foo.c:142:1:
    parameter 1 of type 'struct foo_ctx*' has sub-type changes:
      in referenced type 'struct foo_ctx':
        type size changed from 384 to 448 (in bits)
        1 data member insertion:
          'uint64_t retry_count', at offset 320 (in bits) at foo.h:87:1

That size change means every binary that stack-allocated a foo_ctx will now corrupt its stack. No compiler warning. No test failure. Just weird crashes six months later.

Package-level comparison. abipkgdiff eats two RPMs plus their debuginfo packages and reports every ABI change across every shared library in the package:

$ abipkgdiff --d1 glibc-2.38-1.debuginfo.rpm --d2 glibc-2.39-1.debuginfo.rpm \
             glibc-2.38-1.rpm glibc-2.39-1.rpm

This is how Fedora and openSUSE catch accidental ABI breaks before the update lands in a repo.

Suppressions. Not every "change" is a break. A struct with a void *_reserved[4] that gets replaced by real members was intentional padding. libabigail reads INI-format suppression files:

[suppress_type]
  name = foo_internal_ctx
  ; opaque handle β€” never inspected by callers

Serialize ABIs to XML. abidw writes a full ABI description as XML, so you can commit a reference ABI to git and have CI run abidiff against it on every PR. Now your ABI is code-reviewed like everything else:

$ abidw --out-file libfoo-abi.xml libfoo.so.1
$ abidiff libfoo-abi.xml build/libfoo.so.1

abicompat: given an application binary and two versions of a library, will the app still work against the new one? It reads the app's undefined symbols and struct usage, then checks if the new library still satisfies them:

$ abicompat myapp libfoo.so.1.4.2 libfoo.so.1.4.3
ELF file 'myapp' might not be ABI compatible with 'libfoo.so.1.4.3'...

Compare that to ldd-plus-launch-and-pray. abidiff makes the invisible visible: struct layout, enum values, vtable order, symbol versions, function signature drift, all read straight out of the DWARF the compiler already emitted for you.

Key Takeaway: ABI breaks hide in struct padding and vtable order where source diffs can't see them β€” abidiff reads DWARF from two ELF binaries and tells you what actually changed at the ABI level, before your users' segfaults do it for you.

What If Engineering

What If We Built a Skyscraper-Sized Thermomagnetic Ferrofluid Loop That Pumped Itself With Nothing But a Permanent Magnet?

2026-09-08

Ferrofluid is oil laced with magnetite nanoparticles β€” it flows like a liquid but responds to magnetic fields. Heat it past its Curie point and it loses magnetization. That gives us a peculiar trick: put a permanent magnet next to a pipe, dunk a heat source downstream, and cold magnetic fluid gets pulled toward the magnet while hot demagnetized fluid gets pushed out. A self-pumping heat exchanger with zero moving parts. Now scale it to a 500-meter tower.

The driving force. The Kelvin body force on a magnetized fluid is f = ΞΌβ‚€Β·MΒ·βˆ‡H. With a tuned Mn-Zn ferrite ferrofluid (Curie ~65 Β°C, saturation magnetization M β‰ˆ 30 kA/m) and a neodymium array producing a gradient of ~10⁷ A/mΒ² near the pole face:

f = (4π×10⁻⁷) Γ— (3Γ—10⁴) Γ— (10⁷) β‰ˆ 377 N/mΒ³

For comparison, ordinary thermal buoyancy in water (Ξ”T = 50 K) delivers only ρgΞ²Ξ”T β‰ˆ 147 N/mΒ³. The magnetic pump is ~2.5Γ— stronger than natural convection β€” and it doesn't need a tall column of hot fluid to work. It works horizontally, or in microgravity, which is why NASA has actually studied this for spacecraft.

Heat carried. Ferrofluid density is ~1,400 kg/mΒ³ with specific heat ~2,000 J/(kgΒ·K). At a modest 0.1 m/s through a 1 mΒ² riser with Ξ”T = 30 K between hot and cold legs:

Q = ρ·c_pΒ·Ξ”TΒ·AΒ·v = 1400 Γ— 2000 Γ— 30 Γ— 1 Γ— 0.1 β‰ˆ 8.4 MW

That's the entire cooling load of a Class-A office tower moved with no pump, no fan, no electricity. Stack the magnets around the building's server rooms; run the return leg past a rooftop dry cooler. The building becomes a giant vertical heat pipe with magnetic circulation replacing wick capillarity.

Where it falls apart. Three problems, all serious:

  • Cost. Custom low-Curie ferrofluid runs ~$500/L. A 100 mΒ³ system (a 500 m loop of 0.5 m pipe) is $50 million just for fluid, before pipe, magnets, or seals. Ferrofluid also isn't infinitely stable β€” nanoparticles agglomerate over years, and surfactants degrade above 150 Β°C.
  • Magnet mass. To generate that field over a meter-scale pipe you need roughly a ton of NdFeB per pump station. Six pump stations up a tower = 6 tonnes of rare-earth magnet, another few million dollars, and a permanent 1.5 T hazard zone around every mechanical closet.
  • The gradient is local. Force falls off as 1/r⁴ from a magnet face. You get 377 N/mΒ³ within ~10 cm of the pole and essentially nothing at 30 cm. The "pump" is really a short accelerator zone; the rest of the loop coasts on inertia. Long horizontal runs will stall.

The honest verdict. This works β€” the physics is real and demonstrated at bench scale (solar collectors, CPU coolers, and a handful of published prototypes hit exactly these numbers). But at building scale, you're spending $60M+ to eliminate a $50k circulator pump that draws maybe 20 kW. The interesting play isn't cost parity; it's reliability. A skyscraper cooling loop with no bearings, no seals, no impellers, and no electrical dependency could run for a century between overhauls. For a nuclear plant's decay-heat loop, or a Mars habitat, that trade looks very different.

Key Takeaway: Ferrofluid thermomagnetic convection can move megawatts through a skyscraper with no moving parts β€” real physics, absurd economics, but genuinely compelling anywhere you'd trade dollars for decades of maintenance-free operation.

Wikipedia Rabbit Hole

Billiard-ball computer

2026-09-08

Imagine a pool table where every collision is a logic gate, every ball a bit of information, and the final resting positions encode the answer to a computation. This isn't a metaphor β€” it's a rigorously defined model of computation proposed by Edward Fredkin and Tommaso Toffoli at MIT in 1982, and it can, in principle, compute anything your laptop can.

The billiard-ball computer emerged from a deep question in physics: does computation have to dissipate energy? Rolf Landauer had shown in 1961 that erasing a bit of information necessarily releases heat (Landauer's principle) β€” but only when information is destroyed. Fredkin and Toffoli wondered if you could build a computer that never erased anything, and thus, in the idealized limit, consumed zero energy.

Their answer was a clockwork of perfectly elastic balls fired across a frictionless table studded with fixed reflectors. Balls represent 1s; empty paths represent 0s. When two balls collide at a right angle, they deflect in a way that implements a Fredkin gate β€” a reversible logic operation that preserves all input information in its outputs. Run the whole thing backward, and you get your original data back. No erasure, no heat, no entropy.

What makes this beautiful is how it connects three ideas you might already know:

  • Turing completeness β€” the billiard-ball model is universal, so a sufficiently large pool table could simulate Windows, ChatGPT, or itself.
  • Conservation laws β€” because Newtonian collisions conserve momentum and energy, the computation "rides along" on physics that nature performs for free.
  • Reversibility β€” the same principle underlies quantum computing, where all operations (except measurement) must be unitary and reversible. Fredkin gates are, in a sense, the classical ancestors of quantum gates.

Of course, the real world intrudes. Any tiny error in a ball's angle amplifies with each collision β€” a phenomenon related to Lyapunov instability. After a handful of interactions, the system diverges chaotically from its intended trajectory. To keep it on course, you'd need active correction, which itself dissipates energy. So the "zero-energy computer" remains a thought experiment β€” but a productive one.

The idea has spawned real research programs: reversible computing is being seriously investigated as a way past the thermodynamic limits that will eventually cap conventional CMOS chips. Researchers have also built physical analogs using vortices in superfluid helium, solitons in optical fibers, and even synchronized crabs β€” yes, a 2011 paper demonstrated logic gates using swarms of soldier crabs whose collisions mimic billiard-ball dynamics.

Perhaps the most subversive implication: if computation can be embedded in any system that supports elastic collisions and conservation laws, then computation isn't a special property of silicon or brains. It's latent in the physics of the universe itself β€” waiting for someone to arrange the reflectors just so.

Down the rabbit hole: A frictionless pool table can, in principle, run any program your computer runs β€” and researchers once built a working version out of live soldier crabs.

Daily YT Documentary

Why Humanity Built a Secret Arctic Backup Plan | Documentary |

2026-09-08

Why Humanity Built a Secret Arctic Backup Plan | Documentary |

Channel: Unfold Reality (199 subscribers)

Buried 130 meters into a sandstone mountain on a remote Norwegian island just 1,300 km from the North Pole sits one of humanity's most quietly ambitious engineering projects: the Svalbard Global Seed Vault. This documentary from a tiny 199-subscriber channel takes a serious look at why we built a facility designed to outlast wars, pandemics, climate collapse, and even the failure of electricity itself.

The vault currently safeguards over 1.3 million seed samples from nearly every country on Earth β€” a genetic backup of the crops that feed civilization. What makes it fascinating from an engineering standpoint is the layered redundancy: the location was chosen because permafrost would keep the interior naturally frozen at around -4Β°C even if the mechanical cooling systems failed permanently. The seeds are triple-sealed in foil packets, stored at -18Β°C, and the tunnel angles upward so meltwater can never reach the vault chamber.

The documentary is also expected to touch on the 2017 permafrost breach, when unexpectedly warm temperatures caused water intrusion into the entrance tunnel β€” a wake-up call that even our most future-proof designs may not be immune to the crisis they were built to survive.

It's a compact primer on agricultural biodiversity, geopolitics, and civilizational risk planning, all rolled into one Arctic bunker.

Why watch: A clear explanation of the engineering, biology, and geopolitics behind humanity's most literal insurance policy against catastrophe.

Daily YT Electronics

Mastering RF Power Detector PCB Design: A deep dive into Altium.

2026-09-06

Mastering RF Power Detector PCB Design: A deep dive into Altium.

Channel: WiredWhite (267 subscribers)

RF PCB design is one of those areas where the rules you learned for digital boards start to actively work against you. Trace impedance, return path continuity, component placement, and grounding all become first-class concerns rather than afterthoughts β€” and getting hands-on walkthroughs of real RF layouts is surprisingly rare on YouTube, especially from smaller creators willing to slow down and explain their reasoning.

This video takes you through the design of an RF power detector, a circuit that converts an incoming RF signal into a proportional DC voltage. These show up everywhere from transmitter power monitoring to received-signal-strength indicators, and they're a great teaching vehicle because they force you to think about signal integrity from the antenna port all the way to the ADC.

The walkthrough is done in Altium Designer, so viewers get exposure to a professional-tier PCB tool rather than the KiCad tutorials that dominate this space. Expect discussion of controlled-impedance traces, ground plane strategy, decoupling around the detector IC, and the placement decisions that keep RF energy where it belongs and out of the DC output path.

At 267 subscribers, WiredWhite is exactly the kind of small, technically substantive channel worth surfacing before the algorithm finds them.

Why watch: A rare, in-depth look at real RF PCB layout techniques in Altium β€” the kind of practical signal-integrity thinking that separates hobby boards from working RF hardware.

Daily YT Engineering

Adiabatic Flame Temperature Calculation β€” Combustion

2026-09-08

Adiabatic Flame Temperature Calculation β€” Combustion

Channel: AutoTherm (1 subscribers)

Adiabatic flame temperature is one of those quantities every combustion engineer needs but almost nobody wants to calculate by hand. The traditional textbook approach β€” iterating through JANAF tables, guessing a product temperature, summing sensible enthalpies, checking your energy balance, and revising β€” is tedious enough that most students walk away with a fuzzy sense of the concept rather than a working understanding of what actually sets the ceiling on combustion temperature.

This video from AutoTherm walks through a direct energy balance on a combustion reaction to solve for the adiabatic flame temperature without the manual table-hunting. That framing matters: once you see the enthalpy of reaction on one side and the sensible enthalpy rise of the product gases on the other, the physical meaning becomes obvious. The flame temperature is simply where all the chemical energy released has nowhere to go except into heating the combustion products themselves β€” no heat loss, no work extraction, no dissociation losses in the simplest treatment.

It's a solid pick for mechanical, chemical, or aerospace engineering students working through a thermodynamics or combustion course, and for practicing engineers who want a cleaner mental model than the one they got in school. AutoTherm is a brand-new channel (1 subscriber at time of writing) that appears to be building a focused library on applied thermodynamics β€” psychrometrics, second-law analysis, and combustion all posted the same day β€” which is exactly the kind of niche technical channel worth catching early.

Why watch: A clean energy-balance approach to adiabatic flame temperature that replaces tedious table iteration with real physical intuition.

Daily YT Maker

DIY Table Saw Fence Upgrade | Fixing My Titan Table Saw

2026-09-08

DIY Table Saw Fence Upgrade | Fixing My Titan Table Saw

Channel: D I White - Designs & DIY (643 subscribers)

Budget table saws are a rite of passage for a lot of hobbyist woodworkers, and the fence is almost always the first thing to betray you. This video tackles a very specific and very relatable problem: a Titan table saw fence that squares up perfectly under your hands but then shifts out of parallel the moment you lock the lever down. That kind of drift is maddening because it silently ruins cuts you thought were dialed in.

What makes this worth watching is that it's a real diagnostic and repair walkthrough on an entry-level saw, not a promo for a $400 aftermarket fence. Expect to see how the locking mechanism actually transfers force through the fence body, where the play originates (usually the rear rail engagement or a flexing clamp face), and what modifications restore repeatable parallelism to the blade. It's the kind of tuning knowledge that transfers directly to Ryobi, Craftsman, Skil, and other budget contractor saws with similar fence designs.

The channel is small (643 subs) and the format is unhurried, which usually means you get to see the failed attempts and measurement steps instead of a polished "and here's the finished mod" cut. For anyone fighting their own cheap table saw fence, this is exactly the kind of peer-level fix-it content that's hard to find in a sea of sponsored SawStop reviews.

Why watch: A practical, hands-on tuning walkthrough for the universally frustrating problem of a budget table saw fence that won't hold square when locked.

Daily YT Welding

SS Pipe TIG Root Pass Welding πŸ”₯ | 12mm Stainless Steel Root Pass | Ampere Setting & Technique

2026-09-08

SS Pipe TIG Root Pass Welding πŸ”₯ | 12mm Stainless Steel Root Pass | Ampere Setting & Technique

Channel: U.K.C welding life (1670 subscribers)

The TIG root pass on stainless pipe is one of the highest-stakes welds a fabricator does β€” get it wrong and you either burn through, leave lack of fusion at the root, or oxidize (sugar) the back side where no grinder can reach it. This video zeroes in on that exact operation on 12mm wall stainless, and importantly promises to cover ampere setting alongside technique, which is the pairing most tutorials skip.

What makes root pass work interesting is that it's a balancing act between several variables: heat input has to be low enough not to blow out the gap but high enough to fully fuse both bevels; travel speed has to match the puddle; filler wire has to be dipped at the leading edge without disturbing the keyhole; and back-purge argon has to be flowing correctly or the root turns black. A good demonstration shows the puddle behavior clearly enough that you can see the keyhole form, the filler wet in, and the ripple pattern that indicates proper penetration.

For anyone learning pipe welding β€” whether prepping for a 6G test, working toward CWB/AWS qualification, or just wanting to understand why their roots keep failing bend tests β€” watching an experienced welder call out actual amperage settings on real 12mm stainless is more useful than a dozen generic "TIG tips" videos. The channel is small (1.6k subs) but focused specifically on stick and TIG pipe work.

Why watch: Concrete amperage numbers and puddle technique for the hardest weld in stainless pipe fabrication β€” the root pass.

All newsletters