27 newsletters today.
Abandoned Futures
2026-05-12
On August 18, 1993, at White Sands Missile Range, a 12-meter conical rocket called the DC-X lifted off, hovered, translated sideways, and landed gently on its tail fins. A three-person ground crew turned it around for another flight in days. SpaceX would not replicate this feat until 2012 — nineteen years later.
The Delta Clipper Experimental was the brainchild of Max Hunter, a legendary McDonnell Douglas engineer, and was championed politically by retired General Daniel Graham of the "High Frontier" group. Funded not by NASA but by the Strategic Defense Initiative Organization (the "Star Wars" office) for roughly $60 million — pocket change in aerospace — the program's premise was radical: treat a rocket like an airplane. Land it, refuel it, fly it again the same week. No parachutes, no ocean recovery, no standing army of refurbishment technicians.
The vehicle used four modified Pratt & Whitney RL10A-5 engines burning liquid hydrogen and liquid oxygen, throttleable down to 30%. Between 1993 and 1995, the DC-X flew eight times, demonstrating in-flight pitch-overs, abort scenarios, and rapid turnaround. In 1995, NASA reluctantly inherited the program, upgraded it to the DC-XA "Clipper Graham" with a composite hydrogen tank, and flew it four more times.
Then, on July 31, 1996, after a successful flight, one of four landing struts failed to deploy because a pneumatic line had not been reconnected after maintenance. The vehicle tipped over and the LOX tank ruptured. The hardware was repairable. Congress and NASA chose not to.
Funding instead flowed to Lockheed Martin's X-33 VentureStar, a horizontal-landing lifting body with exotic linear aerospike engines and composite tanks that could not be made to hold cryogenic propellant. The X-33 was canceled in 2001 having never flown, after spending roughly $1.3 billion. The DC-X team scattered. Several engineers — including Jim Benson, Mitchell Burnside Clapp, and others — would later seed Blue Origin and inform SpaceX's culture of iterative testing.
Why it was killed, in short:
Why it should be revived now:
The DC-X did not fail. It was abandoned mid-stride because it was too cheap, too small, and too disruptive to survive its own success.
ArXiv Paper Digest
2026-05-12
Imagine you're trying to train a puppy, but every time you want to test out a new training technique, you have to raise a brand-new puppy from birth. That's roughly the situation researchers face today when they build "meta-agents" — AI systems whose job is to supervise, debug, or improve other AI agents. Every experiment means re-running the whole agent from scratch, which is slow, expensive, and makes it hard to compare what would have happened if the agent had taken a different path at some critical moment.
Shepherd is a new runtime system that fixes this by treating an AI agent's life history like a Git repository. Every time the agent does something — reads a file, calls a tool, gets a response — that interaction is recorded as a typed event in an execution trace. Crucially, you can rewind to any past moment, fork off a new branch, and try a different path. Think of it as save-states for AI agents, but with mathematical rigor.
Three things make this paper notable:
The key insight is treating agent execution as a functional, immutable data structure rather than a one-shot script. Once you can fork, replay, and branch agent runs cheaply and correctly, a whole class of meta-agent techniques — automated debugging, counterfactual evaluation, search over agent strategies, training data generation — becomes practical. Today, most agent frameworks treat a run as an ephemeral event; Shepherd treats it as a queryable artifact you can poke at after the fact.
If you've ever wanted to ask "what would my agent have done if I'd given it that other tool at step 47?" — and gotten an answer in seconds instead of dollars and minutes — this is the substrate that makes that question cheap to answer.
Daily Automotive Engines
2026-05-12
We've covered ignition timing and how the ECU pulls timing when knock occurs, but let's dig into the actual sensor that detects it. A knock sensor is essentially a contact microphone bolted to your engine block, tuned to hear the specific frequency of detonation.
Inside the sensor is a piezoelectric crystal — typically lead zirconate titanate (PZT) — sandwiched between a seismic mass and the sensor housing. When the engine vibrates, the mass compresses the crystal, which generates a tiny AC voltage proportional to vibration intensity. No power supply needed; the crystal generates its own signal.
The trick is frequency discrimination. Normal engine noise is broadband chaos, but knock has a characteristic resonant frequency determined by cylinder bore geometry. The rule of thumb:
Knock frequency (kHz) ≈ 1800 / bore diameter (mm)
So an LS3 with a 103.25mm bore knocks around 17 kHz. A Honda K20 with an 86mm bore knocks closer to 21 kHz. A diesel with a 100mm bore — about 18 kHz. The ECU runs a band-pass filter (or FFT in modern systems) tuned to this specific frequency, ignoring everything else. Valvetrain clatter at 2-3 kHz? Filtered out. Injector tick? Gone. Only the bore-resonant pinging gets through.
There are two main sensor types:
Placement matters enormously. The sensor must be bolted to the block where vibration transmits cleanly — typically the side of the block between cylinders 2 and 3 on an inline-4, or in the lifter valley on a V-engine (LS engines famously hide one knock sensor under the intake manifold, making replacement a 4-hour job).
Real-world example: GM's LS2 had knock sensors mounted externally on the block sides. They corroded from coolant intrusion and threw constant P0332 codes, causing the ECU to pull 6-8° of timing as a precaution. Owners would lose 30+ horsepower and not know why. GM moved them inside the valley on the LS3 — drier environment, more accurate readings, but a nightmare to service.
Torque spec also matters: most knock sensors require 15-20 Nm exactly. Under-torqued and the signal is muddy; over-torqued and you crack the piezo crystal, killing sensitivity permanently.
Daily Debugging Puzzle
2026-05-12
This function is supposed to return the same calendar day across count consecutive months — useful for billing schedules, subscription renewals, and recurring reminders.
// Returns the same day-of-month across N consecutive months.
// For Jan 31, 2025 with count=4, we expect:
// [Jan 31, Feb 28, Mar 31, Apr 30]
function getMonthlySchedule(start, count) {
const dates = [];
const d = new Date(start);
for (let i = 0; i < count; i++) {
dates.push(new Date(d));
d.setMonth(d.getMonth() + 1);
}
return dates;
}
const schedule = getMonthlySchedule(new Date(2025, 0, 31), 4);
console.log(schedule.map(x => x.toDateString()));
// Actual output:
// ['Fri Jan 31 2025', 'Mon Mar 03 2025',
// 'Thu Apr 03 2025', 'Sat May 03 2025']
February silently vanishes from the schedule. The user gets billed on the 3rd of the month for the rest of the year, and customer support gets an earful.
The culprit is setMonth's overflow semantics. Setting the month to February while the day-of-month is still 31 doesn't clamp to Feb 28 — it constructs the date "February 31, 2025" and lets it roll over: 28 days into February, then 3 more into March. So setMonth(1) on Jan 31, 2025 produces March 3, 2025.
The damage compounds. Once we've shifted to March 3, the next setMonth calls operate on day 3, not day 31. The "January 31" anchor is lost forever after a single overflow. Every subsequent month is now the 3rd.
This is the same family of bug that haunts Java's Calendar, Python's relativedelta in older versions, and SQL's DATEADD in some dialects. The behavior is technically documented but violates the intuitive contract: "go to the same day next month."
Don't mutate a running Date. Compute each target from the original anchor, then clamp the day to the target month's actual length:
function getMonthlySchedule(start, count) {
const dates = [];
const anchorDay = start.getDate();
const year = start.getFullYear();
const month = start.getMonth();
for (let i = 0; i < count; i++) {
// Day 0 of month (m+i+1) is the last day of month (m+i)
const lastDay = new Date(year, month + i + 1, 0).getDate();
const day = Math.min(anchorDay, lastDay);
dates.push(new Date(year, month + i, day));
}
return dates;
}
Two things changed. First, we recompute each date from the original anchor day, so a clamp in February doesn't poison March. Second, we explicitly clamp using new Date(y, m+1, 0) — a well-known trick that exploits day-zero rollover in the opposite direction to discover the last valid day of a month.
The general lesson: any API that accepts out-of-range values has to pick a behavior — reject, clamp, or roll over. JavaScript's Date rolls over, and the rollover is silent. Whenever you do month or year arithmetic, ask: "what happens on the 29th, 30th, and 31st?" If you don't know, you have a latent bug waiting for a long-tail customer.
Date.setMonth doesn't clamp the day to the new month — it overflows, so adding one month to January 31 silently produces March 3 and erases February from your schedule.
Daily Digital Circuits
2026-05-12
Every MOSFET has four terminals, not three. Software engineers learn about gate, source, and drain — but there's a fourth: the body (or bulk). Normally it's tied to the supply rails and forgotten. But if you can control its voltage independently, you gain a knob that lets you tune transistor behavior after the chip is already manufactured.
The physics: a MOSFET's threshold voltage VT depends on the voltage between source and body (VSB). This is the body effect. For an NMOS transistor:
The rule of thumb: VT shifts roughly 50-100 mV per volt of body bias, depending on process. At advanced nodes (FD-SOI especially), the sensitivity can hit 85 mV/V — letting you trade ~20% performance for ~10x leakage reduction.
Real-world example: STMicroelectronics' 28nm FD-SOI process exposes body bias as a first-class design knob. Mobile SoCs using it apply forward bias during compute bursts (faster CPU, accept the leakage hit for milliseconds) and reverse bias during idle (slower wakeup latency, but standby power drops 5-10x). Renesas and ST microcontrollers use this to hit microamp-level sleep currents while still hitting hundreds of MHz when awake.
Why this is hard: The body forms a parasitic diode with the source. If you forward-bias too aggressively (more than ~500mV typically), that diode turns on and you get massive current through what should be an insulating junction — potentially latchup, where a parasitic SCR locks on and destroys the chip. So body bias generators need careful clamps and are typically driven by on-chip charge pumps with current limiters.
Quick calculation: If your process has body factor γ = 0.4 V½ and you apply VSB = -0.3V (reverse bias on NMOS), the VT shift is approximately:
ΔVT ≈ γ × (√(2φF + |VSB|) - √(2φF)) ≈ 0.4 × (√1.0 - √0.7) ≈ 65 mV
That 65mV shift cuts subthreshold leakage by roughly 10× (since leakage is exponential in VT/VT,thermal with VT,thermal ≈ 26mV at room temp).
This is why modern chips have separate power domains for n-well and p-well voltages — they're not just decoupling, they're tuning knobs the firmware can twist in real time.
Daily Electrical Circuits
2026-05-12
Inductors are the problem child of analog design: they're bulky, expensive at high values, have parasitic resistance and capacitance, pick up magnetic interference, and don't integrate onto silicon. A gyrator sidesteps all of this by using an op-amp, a capacitor, and a couple of resistors to synthesize inductive behavior. The circuit doesn't store energy in a magnetic field — it stores it in the capacitor — but at its input terminals it looks electrically like a grounded inductor.
The classic single-op-amp gyrator (Antoniou's simulated inductor) has this topology: input signal feeds R1 to the op-amp's inverting input and also to one terminal of capacitor C. The op-amp's output drives the other terminal of C through R2, and its non-inverting input ties to the input node. The op-amp forces its output to whatever voltage maintains zero differential input, and the result is an input impedance:
Zin = R1 + jω(R1·R2·C)
The imaginary part behaves exactly like an inductor of value Leq = R1·R2·C, with R1 appearing as series DC resistance.
Worked example: Want a 10 H "inductor" for a subwoofer-frequency notch filter? Pick C = 1 µF, R1 = 1 kΩ, R2 = 10 MΩ. That gives Leq = 1k × 10M × 1µ = 10 H. A real 10 H inductor would be the size of a fist, weigh half a pound, and cost $40. The gyrator version fits in a TO-92 footprint and costs under a dollar.
Where you'll actually see this:
The catches you need to respect:
Rule of thumb: For audio-band synthetic inductors up to ~10 H, pick C in the 10 nF–1 µF range, then choose R1·R2 to land on your target L. Keep R2 ≤ 10 MΩ to avoid bias-current errors, and use a FET-input op-amp (TL072, OPA2134) for clean operation.
Daily Engineering Lesson
2026-05-12
Every real oscillating system loses energy. Damping is the mechanism that bleeds that energy away — converting kinetic and potential energy into heat, sound, or fluid motion. Without it, a plucked guitar string would ring forever and your car would porpoise down the road after every bump.
Damping is characterized by the damping ratio ζ (zeta), which compares actual damping to the critical value that just prevents oscillation:
The math: a mass-spring-damper system follows m·ẍ + c·ẋ + k·x = 0, where c is the damping coefficient. Critical damping occurs at ccrit = 2√(mk), and ζ = c/ccrit.
Three physical sources of damping:
Real-world example: car suspension. A passenger car's shocks are typically tuned to ζ ≈ 0.2–0.4 — underdamped, because critically damped suspension feels harsh and slow to recover. Race cars run closer to ζ ≈ 0.6–0.7 to keep tires planted through transients. Door closers, by contrast, target ζ ≈ 1.0 so the door settles without slamming or bouncing.
Rule of thumb: logarithmic decrement. Measure two successive peaks of a decaying oscillation, x₁ and x₂. Then δ = ln(x₁/x₂), and for light damping ζ ≈ δ/(2π). So if a beam's amplitude drops from 10 mm to 6 mm in one cycle: δ = ln(10/6) ≈ 0.51, giving ζ ≈ 0.08 — typical for welded steel structures.
Why this matters in design: too little damping and your structure rings at resonance, fatigues, and fails (Tacoma Narrows). Too much and your control system becomes sluggish (a critically damped servo can't respond fast enough to fast inputs). Engineers deliberately add damping with elastomeric mounts, tuned mass dampers (the 660-ton ball in Taipei 101), or magnetorheological fluids that change viscosity on command.
Forgotten Books
2026-05-12
Book: Architectural pottery; bricks, tiles, pipes, enamelled terra-cottas, ordinary and incrusted quarries, stoneware mosaics, faïences, and architectural stoneware by Lefêvre, Leon (1900)
Read it: Internet Archive
Buried in the title of Leon Lefêvre's 1900 manual is a phrase most modern readers will skim past without a second thought: "ordinary and incrusted quarries." That single word — incrusted — points to a manufacturing trick that floored Victorian railway stations, churches, and grand hotels, and which the 20th century almost completely forgot.
"…bricks, tiles, pipes, enamelled terra-cottas, ordinary and incrusted quarries, stoneware mosaics, faïences, and architectural stoneware."
A "quarry," in this trade, was a square unglazed floor tile (from the French carré). An incrusted quarry was something more clever: instead of painting a pattern on the surface — which would scuff off within a decade of foot traffic — the maker pressed a recess into the soft tile body and filled it with a different-colored clay slip. The colored inlay went all the way down, sometimes a quarter-inch deep. When the tile wore, the pattern wore with it. You could grind the surface to dust and the design would still be there.
Lefêvre, a French ceramic engineer writing at the height of the trade, was documenting techniques that had been industrialized only a few generations earlier — Herbert Minton's English patents in the 1830s revived a medieval Cistercian method that had itself been lost for three centuries. By 1900, every reputable manufacturer in France, England, Belgium, and the American Midwest was pressing these tiles by the millions.
Then came the 20th century. Mass-produced glazed tiles, linoleum, and finally vinyl made the laborious double-clay press uneconomical. Most of the great encaustic factories closed between 1920 and 1960. The know-how — kiln curves, slip viscosities, the trick of getting two clays with different shrinkage rates to fire without cracking apart — became the property of a handful of restorers.
What's striking about Lefêvre's casual listing is that incrusted quarries appear as routine, sandwiched between bricks and stoneware mosaics. To him they were nothing exotic; to us, replacing a single broken tile in a Victorian church vestibule can cost £80 and require a six-month wait from one of the three workshops in Europe that still make them.
The 1830s patent holders weren't innovating — they were re-learning. We may be due for the next re-learning ourselves.
Forgotten Darkroom
2026-05-12
Book: Вирирование бромосеребряных фотобумаг (Toning of Bromide-Silver Photographic Papers) by В. Яштолд-Говорко (1939)
Read it: Internet Archive
Buried in the table of contents of a slim 1939 Soviet photography manual is a section heading that would make a modern darkroom hobbyist's eyebrows climb to their hairline:
Вирирование солями урана... Коричневый цвет... Темнокоричневый цвет... Красно-коричневый цвет.
That is: "Toning with uranium salts — brown color, dark brown color, red-brown color." A nine-page chapter of a state-published amateur photographer's handbook, casually instructing hobbyists on how to use uranium compounds to color their family snapshots.
The book is Volume 10 of the Библиотека фотолюбителя (Amateur Photographer's Library), published in Moscow by Goskinoizdat in 1939. Its author, В. Яштолд-Говорко (V. Yashtold-Govorko), was a prolific Soviet writer on photographic chemistry. The book is a methodical catalog of how to chemically replace the silver in a black-and-white print with metal salts to produce different colors: iron for blue, copper for red, cobalt for salad-green, lead for yellow, nickel for cherry-red — and uranium for a distinctive warm red-brown that no other toner could quite match.
The author opens with a perfectly sensible aesthetic argument:
"You cannot, for example, tint a portrait green or bright blue. This will only ruin the picture. At the same time, coloring a portrait in brown or red-brown tones can significantly improve its quality."
Uranium toning was genuinely common from the 1890s through the 1950s. The chemistry involved uranyl nitrate and potassium ferricyanide, which deposited uranium ferrocyanide in the image, producing a saturated red-brown that photographers prized for landscapes and autumn scenes. It was sold in commercial kits by Kodak and Agfa.
The forgotten part: those prints are mildly radioactive — and still are, sitting in family albums and museum archives across the world. Conservators today routinely identify uranium-toned prints by sweeping them with Geiger counters. The activity is low (depleted-uranium territory), but it's real and permanent. The half-life of uranium-238 is 4.5 billion years; your great-grandmother's sepia-toned photograph will outlast the sun.
What makes this so striking to a modern reader is the casualness. There is no warning. No protective-equipment note. Uranium is listed between cobalt and aniline dyes as just another option on the color palette, the way a modern art store might shelve cadmium-red watercolors. Nuclear fission had been demonstrated only months before this book went to press — Hahn and Strassmann's paper appeared in Naturwissenschaften in January 1939 — and Soviet hobbyists were being told how to handle uranyl nitrate in their kitchen sinks.
The technique vanished not because it stopped working, but because the regulatory landscape around uranium tightened dramatically after 1945. By the 1960s uranyl salts were nearly impossible for amateurs to buy. An entire visual aesthetic — the deep, glowing red-brown of a uranium-toned print — was effectively legislated out of existence.
Forgotten Patent
2026-05-12
In April 1941, while bombs fell on Berlin, a 30-year-old civil engineer named Konrad Zuse filed German patent application Z 391 (later refiled as Z-23139 IX/42m) describing a machine that should not have existed for another decade. The Z3, completed in his parents' living room on May 12, 1941 — exactly 85 years ago today — was the world's first fully automatic, program-controlled, freely programmable computer using binary floating-point arithmetic. Every one of those adjectives matters, and together they describe a machine that beat ENIAC by five years and the Harvard Mark I by three.
Zuse's patent application — known internally as the "Verfahren zur selbsttätigen Durchführung von Rechnungen mit Hilfe von Rechenmaschinen" ("Method for the automatic execution of calculations with the help of computing machines") — described concepts that read like a modern computer architecture textbook:
The Z3 contained 2,600 telephone relays, ran at 5–10 Hz, and could perform a multiplication in about 3 seconds. By modern standards, glacial. But it was Turing-complete — proven retroactively in 1998 by Raúl Rojas, who showed that Zuse's instruction set, though lacking conditional branching, could simulate any computation through clever use of self-modifying address arithmetic.
The patent was rejected. The German Patent Office examiner ruled in 1967 — twenty-six years after filing — that the invention lacked sufficient "inventive step." Zuse fought the rejection for decades and lost. Meanwhile, the Z3 itself was destroyed in a 1943 Allied bombing raid on Berlin. No working unit survived the war. Zuse's company Zuse KG eventually built dozens of successors (the Z4 survived and ran at ETH Zürich until 1955), but the original was rebuilt only as a museum replica in 1961, now at the Deutsches Museum in Munich.
The modern connection runs deeper than "first computer." Zuse's 1945 Plankalkül — a programming language he designed in hiding in the Bavarian Alps after fleeing Berlin — included structured data types, arrays, records, conditional execution, and even a concept resembling object-oriented assertions. It predated FORTRAN by 12 years and ALGOL by 13. Because it was never implemented during his lifetime and not published until 1972, every concept Zuse invented had to be reinvented independently.
There's a particular cruelty in Zuse's story: isolation by war meant his work didn't influence Anglo-American computing at all. Von Neumann, Turing, Aiken, and Mauchly built parallel architectures without knowing he existed. We celebrate ENIAC and Colossus as origins, but a Berlin civil engineer with relay scraps and movie film had already crossed the finish line — alone, unfunded, and unrecognized.
Daily GitHub Zero Stars
2026-05-12
Language: Unknown (early-stage)
Link: https://github.com/LeonardTopno/gps-attendance-tracker
Among a sea of unnamed test repos and synthetic snippets, this one stands out because it actually tells you what it's for: a GPS-based attendance tracking app for village teaching centres. That single sentence of description carries more purpose than most well-funded SaaS landing pages.
The premise is quietly compelling. In remote or rural education settings — particularly the kind of village teaching centres common across South Asia and parts of Africa — verifying that teachers and students actually showed up is a genuinely hard logistics problem. Paper registers get fudged. Biometric scanners need power and hardware. But a phone with GPS, geofenced to a school's coordinates, gives you a low-cost, tamper-resistant proof-of-presence signal that scales to wherever cell service reaches.
Why it's interesting:
Who'd benefit from watching this repo:
The language is still listed as Unknown, suggesting the repo is brand new. Worth bookmarking to see whether it grows into something deployable or stays a personal experiment — either outcome is informative.
Daily Hardware Architecture
2026-05-12
Cache coherence protocols don't track bytes — they track cache lines, typically 64 bytes on x86 and ARM (some IBM POWER chips use 128). This granularity is a hardware compromise: tracking individual bytes would explode the directory state, while larger lines waste bandwidth on partial transfers. The consequence is a performance pitfall called false sharing.
False sharing happens when two cores modify different variables that happen to land on the same cache line. Logically, the threads are independent. Physically, MESI sees one line ping-ponging between caches. Every write forces the other core's copy to Invalid, triggering a coherence miss on the next access — even though the threads never touch each other's data.
Real-world example: A per-thread counter array:
uint64_t counters[16]; — eight counters fit in one 64-byte lineLinux's perf c2c tool was built specifically to catch this. The fix is padding:
struct { uint64_t v; char pad[56]; } counters[16]; — or in C++17, alignas(std::hardware_destructive_interference_size).
Rule of thumb — coherence miss cost:
If your line bounces between two cores at 1 GHz update rate, you're burning ~200ns × 10⁹ = the entire core. A loop that should run at 1 ns/iteration runs at 200 ns/iteration. That's the 200× slowdown people report on naive concurrent counters.
Where it bites in practice:
The flip side is true sharing, which looks identical in performance counters but isn't fixable by padding — you actually need the same data. Tell them apart with perf c2c: it reports HITM (hit-modified) events with offsets within the line. If the contending offsets are different fields, pad them apart. If they're the same field, you have a design problem, not a layout problem.
Hacker News Deep Cuts
2026-05-12
Link: https://www.sciencealert.com/the-worlds-first-nuclear-explosion-forged-an-impossible-crystal
HN Discussion: 1 points, 0 comments
At 5:29 AM on July 16, 1945, the Trinity test vaporized a 100-foot steel tower and fused the surrounding desert sand into a glassy green crust that scientists later named trinitite. For 80 years, trinitite was treated as a curiosity — a radioactive souvenir, scooped up by tourists before the site was bulldozed in 1953. This article reports something far stranger buried inside it: a quasicrystal, an atomic structure that mathematicians once thought was impossible.
Quasicrystals break the rules of classical crystallography. Ordinary crystals tile space with repeating units — squares, hexagons, cubes — and their atomic lattices have rotational symmetries of order 2, 3, 4, or 6. Anything else, like fivefold symmetry, was proven impossible to extend periodically. Then in 1982, Dan Shechtman observed a metal alloy with a perfect tenfold diffraction pattern. He was ridiculed (Linus Pauling famously called him a "quasi-scientist"), then awarded the 2011 Nobel Prize in Chemistry once the result held up. Quasicrystals are aperiodic — they have long-range order without translational symmetry, the atomic analog of a Penrose tiling.
What makes the Trinity find remarkable:
The technical audience here is broader than it looks. Materials scientists care about new synthesis routes. Condensed-matter physicists care about the symmetry implications. Nuclear nonproliferation researchers care about the forensic angle — trinitite samples remain one of the few well-characterized records of an early-design implosion device. And anyone who enjoys the moments where the universe quietly refuses to obey the rules we wrote for it will find something here.
It's also a reminder that scientific discoveries can sit in plain sight for decades. The trinitite samples were studied since 1945. Nobody thought to look for fivefold symmetry until someone did.
HN Jobs Teardown
2026-05-12
Source: HN Who is Hiring
Posted by: dickfickling
Of the ten postings, Dave.com's is the most strategically revealing because the macroeconomic framing is doing the heavy lifting — and that framing tells you exactly where this company thinks the next 18 months are going.
1. The tech stack (or lack thereof)
Notice what's missing: no stack is mentioned. For a fintech hiring "Senior Full Stack & Front end Engineers," that's an unusual omission. They're not selling the technology — they're selling the mission and the growth curve. This is a tell: Dave is past the stage where engineers join for the stack and into the stage where they join for the trajectory. Compare to AuditBoard's laundry list (Node.js, Ember.js, Kubernetes, Docker, C#, Python) — that's a company still recruiting on craft.
2. Stage and direction
The numbers buried in the posting are the real signal: 10,000 → 5,000,000 users in two years, with 12 employees. That's a 500x user growth on a headcount that barely moved. Either the product is genuinely viral (paycheck advances during a recession would be), or they've been deliberately lean and are now about to scale hiring hard. "Senior Full Stack & Front end Engineers" plural, plus relocation budget, plus LA onsite-only — they're building a physical engineering org from a tiny base.
3. Skills and trends highlighted
4. Red flags and green flags
Green: The user-to-employee ratio (~417,000:1) is genuinely impressive and suggests strong unit economics. Relocation budget signals real capital. The mission framing will resonate during a downturn.
Red: "Onsite only" in LA during a moment when remote work is becoming table stakes is a constraint that'll narrow the candidate pool sharply. The scare-quotes around "Onsite" hint the poster knows it. No stack disclosure can also mean legacy tech they don't want to lead with. And paycheck-advance economics depend on customers staying solvent enough to repay — a deep recession could invert the thesis.
Daily Low-Level Programming
2026-05-12
Every CPU has separate L1 caches for data (L1d) and instructions (L1i) — typically 32KB each on x86. You optimize data layout religiously, but your code competes for the same scarce resource, and an L1i miss stalls the front-end before any work can happen.
The L1i is filled by fetching 64-byte lines from L2 (or further). When you call a function, the CPU fetches the line containing its entry point. If that function calls another cold function on a distant page, you take an i-cache miss, possibly an iTLB miss, and the pipeline starves. Modern CPUs can issue 4–8 instructions per cycle, but only if the front-end keeps up.
How the compiler helps (and hurts):
.text section blow your i-cache. Tools like perf + BOLT or llvm-propeller reorder functions by call frequency..text and evicting other hot code. __attribute__((noinline)) on cold paths matters.__builtin_expect and PGO to put the hot path inline and push the cold path (error handling, logging) to the end of .text, often onto a separate page that's never fetched in steady state.Real-world example: Facebook's HHVM hit a wall where 30%+ of cycles were front-end stalls — pure i-cache pressure from a multi-MB hot working set. They built BOLT, which reorders functions and basic blocks using perf profiles. The result: 7–8% speedup on HHVM, ~5% on Clang itself, with zero source changes. Google sees similar wins with Propeller on Search.
Rule of thumb: If your hot working set of code exceeds ~32KB, you're thrashing L1i. Measure with perf stat -e L1-icache-load-misses,iTLB-load-misses. A miss rate over 1% on the hot path is a strong signal. For comparison: an L1i hit is ~4 cycles; an L2 hit is ~12; an LLC miss to DRAM is 200+. That's a 50× swing per fetched line.
Practical levers: Mark cold paths with __attribute__((cold)) — the compiler relocates them to a separate section (.text.cold). Use likely()/unlikely() macros. For real wins, enable PGO or AutoFDO; BOLT on top of that is the current state of the art. Avoid template explosions in hot loops — every instantiation is more bytes fighting for the same cache lines.
Reddit Small Subs
2026-05-12
Subreddit: r/vintagecomputing
Discussion: View on Reddit (1238 points, 111 comments)
This gallery is a rare insider's photo album from inside Netscape Communications Corporation during its mid-1990s heyday — the company whose browser, Netscape Navigator, was for a brief, electric moment the face of the World Wide Web. The poster shares candid shots of the Mountain View offices, the engineering bullpens, dev workstations piled with Sun pizza-boxes and early Pentium PCs, whiteboards scrawled with HTML and JavaScript proposals, and the famous Mozilla mascot lurking in lobby corners.
Why this matters to anyone interested in computing history:
The comment thread is full of ex-Netscape employees identifying coworkers and rooms, which adds an oral-history layer you rarely get with vintage hardware posts. It's worth scrolling through for the annotations alone.
For anyone who lived through the era, it's nostalgic; for younger readers, it's a useful corrective to the myth that web companies were born in glass towers. The web was built in cubicles, on borrowed Suns, by people who had no idea they were making history.
RFC Deep Dive
2026-05-12
If you've ever used a VoIP phone behind a home router — or made a WhatsApp call, a Zoom call, or any modern voice/video call routed through SIP infrastructure — you've benefited from this tiny three-character extension: rport. RFC 3581 is barely seven pages, but it's the patch that made SIP actually work on the real, NAT-ridden Internet.
The problem. SIP (RFC 3261) was designed with a beautiful, symmetric assumption: a client sends a request from some port, and the server sends responses back to the address and port the client advertised in its Via header. That works perfectly when endpoints have public IPs. It collapses the moment you put a NAT in the middle.
Here's the failure mode. A SIP phone behind a home router sits at 192.168.1.50:5060. It sends a REGISTER to a provider's server. The NAT rewrites the source to, say, 203.0.113.7:48291. But the phone wrote its private address into the Via header, and even if the NAT helpfully rewrites the IP, the port in Via still says 5060 — which is not the port the NAT mapped. The server dutifully sends the response to 203.0.113.7:5060, which the NAT drops because there's no mapping for it. Call setup silently fails. Worse, registrations from the same NAT collide because the server can't tell two phones apart.
The fix. Rosenberg and Schulzrinne proposed something almost embarrassingly simple: when a client wants symmetric routing, it adds an empty parameter rport to its Via header:
Via: SIP/2.0/UDP 192.168.1.50:5060;rport;branch=z9hG4bK...
The server, on receipt, observes the actual source IP and port the packet arrived from — the NAT's external mapping — and writes them back into the Via:
Via: SIP/2.0/UDP 192.168.1.50:5060;received=203.0.113.7;rport=48291;branch=z9hG4bK...
The response is then sent back to that observed address and port, which the NAT still has a mapping for. Symmetric routing achieved.
Design decisions worth noting.
rport is the signal. Servers MUST NOT do this unless asked, preserving backward compatibility with RFC 3261's strict semantics.received=. RFC 3261 already defined a received parameter for the source IP. RFC 3581 just extends the idea to the port. Minimal surface area.rport fixes routing during a transaction but doesn't keep the mapping alive between them — that's why SIP clients also send periodic keepalives (OPTIONS pings, double-CRLF, or STUN).Why it still matters. Every consumer VoIP service, every softphone, every SIP trunk between an enterprise PBX and a carrier — they all use rport. It's so universally deployed that most SIP stacks turn it on by default; some don't even expose a switch. It's the canonical example of a "small RFC that fixed a huge operational problem" — the same family as RFC 7413 (TCP Fast Open) or RFC 6555 (Happy Eyeballs). Symmetric response routing also foreshadowed the broader pattern that ICE (RFC 8445) later generalized for media: trust what you observe on the wire, not what the peer claims about itself.
Backstory. Jonathan Rosenberg, one of SIP's principal architects, has joked that a substantial fraction of his IETF output has been "papering over the fact that SIP doesn't really work through NATs." RFC 3581 is the smallest and most successful of those papers.
rport token is the reason your VoIP phone works behind your home router — a minimal NAT workaround so universal that SIP without it is effectively broken.
Stack Overflow Unanswered
2026-05-12
The asker is building a Brainfuck-to-arm64 compiler on macOS. Their compiler emits a raw binary — pure arm64 machine code with no headers, no load commands, no segments. They've correctly identified that macOS won't execute this directly: the kernel's execve path on Darwin only knows how to launch Mach-O binaries (or scripts via shebangs). They want to wrap that raw blob into a minimal Mach-O executable using ld.
Why it's harder than it looks: ld on macOS doesn't ingest raw binaries. It consumes Mach-O object files (.o) with symbol tables, relocations, and section metadata. There's no equivalent to GNU ld's -b binary --oformat trick that lets you embed an arbitrary blob as a section. Worse, since around Big Sur, every Mach-O executable on arm64 macOS must be code-signed — even an ad-hoc signature (codesign -s -) is required, or the kernel refuses to launch it with a killed: 9. And the modern ld (the "new linker," ld-prime) is stricter than its predecessor about needing a proper entry point symbol and an LC_MAIN load command.
Direction toward a solution:
ld — feed it what it wants. Wrap the raw blob in a tiny assembly stub that .incbin's the binary into a __TEXT,__text section with a _start (or _main) label at offset 0.as -arch arm64 stub.s -o stub.o, then link with ld -arch arm64 -platform_version macos 11.0 11.0 -e _start -o prog stub.o.codesign -s - prog. Without this, SIP/AMFI will kill it.ld entirely and hand-author a Mach-O header in your compiler. It's ~200 bytes of LC_SEGMENT_64 + LC_MAIN + LC_BUILD_VERSION load commands. otool -l /bin/ls shows the minimum viable shape.Gotchas:
__text on arm64 will fault. The stub or the generated code must end with an svc #0x80 to exit(0) (syscall #1).read/write syscalls — also via svc. The cell tape needs writable memory; consider emitting a __DATA,__bss section for it rather than putting it in __TEXT (which is RX-only).arm64, since arm64e requires signed pointers in places a hand-rolled binary won't provide.objcopy on Linux into an exercise in load-command archaeology.
Daily Software Engineering
2026-05-12
You've seen this code. A Customer.isEligibleForDiscount() method that grew from three lines to fifty. An Order.canBeShipped() with nested conditionals nobody dares touch. The business rules are tangled up with the entity, and every new requirement means more branches inside the same method.
The Specification Pattern extracts a business rule into its own object that answers one question: does this candidate satisfy the rule? Each spec exposes a single isSatisfiedBy(candidate) method. The magic is that specs compose: and, or, and not combine small specs into big ones without modifying any of them.
Concrete example. An e-commerce platform needs to decide which customers get a loyalty email:
HasMinimumOrdersSpec(5) — placed at least 5 ordersLastOrderWithinDaysSpec(90) — ordered in the last 90 daysHasOptedIntoMarketingSpec() — consented to emailIsInExcludedRegionSpec() — GDPR/region blockedThe campaign rule becomes one expressive line:
eligible = hasMinOrders.and(lastOrderRecent).and(optedIn).and(excludedRegion.not())
Next quarter, marketing wants to also include customers who spent over $500 lifetime, even if they haven't ordered in 90 days. You add one new LifetimeSpendSpec(500) and combine: (hasMinOrders.and(lastOrderRecent)).or(lifetimeSpend).and(optedIn).... No existing spec changed. No 200-line method got longer.
The bonus: query translation. A well-designed spec can expose two interpretations — an in-memory predicate and a SQL/ORM expression. The same LastOrderWithinDaysSpec filters a cached list or generates WHERE last_order_at > NOW() - INTERVAL '90 days'. One rule, two execution modes, zero duplication.
Rule of thumb: if a boolean method on an entity has more than 3 conditions or is used in more than 2 places (e.g., both UI filtering and a background job), extract it into a specification. Below that threshold, an inline conditional is fine — don't pattern-match for its own sake.
When NOT to use it. Rules that will never combine (a single one-shot validation), trivial single-field checks (user.age >= 18 doesn't need a class), or rules so tied to persistence that splitting predicate from query buys nothing. The pattern earns its keep when rules multiply and recombine.
The smell to watch for: any time you find yourself copying a conditional from a service into a repository query, or from a job into a UI filter — that's a specification asking to be born.
Tool Nobody Knows
2026-05-12
You've spent six hours hunting a heisenbug. It crashes once in twenty runs. You finally catch it in gdb — and then you fat-finger continue instead of step, blow past the moment of corruption, and have to start over. I've watched grown engineers cry over less.
rr (from Mozilla) is the answer. It records your program's execution — every syscall, signal, and thread interleaving — into a trace file, then replays it deterministically. Same memory addresses. Same scheduling. Same bug, every single time. And because it's deterministic, you can run it backwards.
Install (Debian/Ubuntu):
sudo apt install rr
# Needs hardware perf counters — enable for non-root:
sudo sysctl kernel.perf_event_paranoid=1
Record a flaky test, then replay it as many times as you like:
rr record ./my_flaky_test --seed 42
# ... eventually crashes ...
rr replay # drops you into gdb on the recorded trace
Inside the replay session, you get every gdb command plus the reverse variants:
(rr) continue # forward to crash
(rr) reverse-continue # rewind to previous breakpoint
(rr) reverse-stepi # back up one instruction
(rr) watch -l *0x7fff1234 # hardware watchpoint
(rr) reverse-continue # rewinds to the LAST write to that address
That last trick is the killer feature. Find a corrupted value, set a watchpoint on its memory, reverse-continue, and rr drops you at the exact instruction that scribbled on it. No more "who freed this pointer?" guessing — you literally rewind to the call.
Real workflow for an intermittent bug:
# Loop until it crashes, keeping only the failing trace
rr record --chaos -- ./server --port 8080
# --chaos randomizes thread scheduling to surface races faster
# When it dies, the trace is saved. List traces:
rr ls
# Replay the latest:
rr replay
# Or replay a specific trace and start at an event:
rr replay -g 12450 ~/.local/share/rr/server-3
--chaos mode is its own little miracle: it deliberately picks unfair schedules to provoke data races that never trigger under normal load. I've shaken loose race conditions in minutes that had hidden in CI for months.
Why it beats the mainstream alternative: plain gdb gives you a microscope. rr gives you a microscope plus a TARDIS. Core dumps are corpses — rr gives you a living, scrubable timeline. Compared to printf-debugging across runs, the trace eliminates variance entirely: the bug you see in replay is the bug from the original run, byte for byte, register for register.
Caveats, because I won't lie to you: Linux/x86_64 only (Intel and recent AMD). Roughly 1.5–2× slowdown during record, near-native on replay. Doesn't handle programs that use rdtsc directly (rare) or certain CPU features without flags. Don't bother on virtualized hosts unless the hypervisor exposes PMU counters — rr will tell you immediately if it can't run.
Bonus trick — share a bug with a coworker by sending them the trace directory:
rr pack ~/.local/share/rr/myapp-0
tar czf bug.tar.gz ~/.local/share/rr/myapp-0
# They run: rr replay myapp-0 — and see exactly what you saw
A reproducible bug report. Imagine that.
rr records program execution into a deterministic trace you can replay and step backwards through in gdb — the only practical way to debug heisenbugs, races, and "who corrupted this memory?" mysteries.
What If Engineering
2026-05-12
Earth's space elevator is the perennial sci-fi tease: a 36,000 km cable from the equator to geostationary orbit, requiring a material with specific strength roughly 50 GPa·cm³/g. The best carbon nanotubes measured to date hit ~60 GPa at the single-fiber level, but kilometer-long bulk cables top out near 4 GPa. Earth's elevator is a materials science fantasy. The Moon's, however, is buildable with off-the-shelf Kevlar.
Here's why the physics is so dramatically friendlier.
The Moon is tidally locked to Earth, so a lunar elevator doesn't anchor to a synchronous orbit around the Moon — it anchors to one of the Earth-Moon Lagrange points. Two configurations work:
The figure of merit for a space elevator is the characteristic length — how tall a uniform column of the material can be before it snaps under its own weight in the local gravity field. For a taper ratio (cable cross-section at top vs. bottom):
taper = exp(gravitational potential difference / specific strength)
For Earth's elevator, the integrated potential from surface to GEO is ~48 MJ/kg. Even with 50 GPa·cm³/g nanotubes (50 MJ/kg), the taper ratio is exp(48/50) ≈ 2.6 — manageable in principle but only with perfect material.
For a lunar L1 elevator, the integrated potential is just ~2.3 MJ/kg — twenty times less. The Moon's surface gravity is 1.62 m/s² (one-sixth of Earth's), and you only need to climb to L1 at ~58,000 km. Plug in Kevlar (specific strength ~2.5 MJ/kg, real bulk material, $30/kg):
taper = exp(2.3 / 2.5) ≈ 2.5
That's a buildable cable using existing aerospace materials. Zylon (PBO) at ~3.8 MJ/kg gives taper ~1.8. Even nylon climbing rope could technically work with absurd taper ratios.
For a cable rated to lift 10-ton payloads at 1g acceleration on the Moon (so ~16 kN of tension at the anchor), with a Zylon cable density of 1560 kg/m³ and 58,000 km length, the total cable mass works out to roughly 6,000 tons — comparable to a single large ocean tanker. SpaceX's Starship, fully reusable to lunar surface at projected ~100 ton payloads, could deliver the entire cable in ~60 flights.
Once built, the lunar elevator turns the Moon's surface into a launching platform with near-zero per-kilogram cost. Lunar polar ice — already confirmed at billions of tons — could be electrolyzed into LOX/LH₂ propellant and lifted to L1, where it would dramatically undercut the energy cost of every mission to Mars, the asteroid belt, or anywhere else in the outer solar system. The delta-v from L1 to a Mars transfer orbit is roughly 0.7 km/s, versus 4.3 km/s from Earth's surface to LEO plus another 3.6 km/s to escape.
The kicker: a lunar elevator could plausibly be operational by the 2040s with materials and launch capabilities available today. Earth's elevator requires a Nobel-prize-worthy materials breakthrough that hasn't happened in 30 years of trying.
Wikipedia Rabbit Hole
2026-05-12
Wikipedia: Read the full article
In 1851, Léon Foucault hung a 28-kilogram brass bob from the dome of the Panthéon in Paris and let it swing. The crowd watched the pendulum's plane of oscillation slowly rotate over the course of a day — and for the first time in history, ordinary people saw the Earth turn beneath their feet. It was a sensation. But Foucault wasn't satisfied. His pendulum proved Earth's rotation by appealing to a fixed cosmos as reference. He wanted a device that could detect rotation without looking at the sky at all.
So in 1852, he built the world's first gyroscope. And he gave it that name — from the Greek gyros ("rotation") and skopein ("to see"): literally, "to see the turning."
The device was deceptively simple: a heavy brass rotor spun at 12,000 RPM inside a set of gimbals that isolated it from any external torque. Once spinning, the rotor's axis stayed locked in place relative to the distant stars — what physicists now call inertial space. Because the Earth was rotating underneath it, an observer watching the gyroscope through a microscope would see its axis appear to drift westward, completing a full circuit every sidereal day at the poles (and proportionally slower at lower latitudes, by a factor of sin(latitude)).
Here's why this matters far beyond a parlor trick:
Foucault hit a practical wall: friction in the bearings let the rotor spin for only about 10 minutes before slowing enough that Earth's rotation became hard to detect. He proposed using electric motors to keep it spinning indefinitely — an idea that wouldn't become practical until decades later, when Elmer Sperry industrialized it into the gyrocompass that guided dreadnoughts through World War I.
The really mind-bending bit: the gyroscope works because of the conservation of angular momentum, which is itself a consequence of the rotational symmetry of physical law (Noether's theorem, 1918). Foucault built a tabletop device that effectively asks the universe what "not rotating" means — and the universe answers by pointing at the fixed stars. Why those particular stars? Nobody really knows. It's still an open question in cosmology.
Daily YT Documentary
2026-05-12
Channel: True Crime Unheard (263 subscribers)
Most of today's batch is hashtag-spam shorts and recycled "dark reality" filler, so this one stands out by actually naming a real case with verifiable specifics. The video profiles Peter Karasev, a Georgia Tech PhD and senior machine learning engineer in Silicon Valley whose outwardly enviable career masked a parallel life that ended in arrest.
What makes the Karasev case worth a documentary treatment isn't shock value — it's the cognitive dissonance at its core. He sat squarely inside the high-trust tech labor class: rigorous academic pedigree, six-figure salary, the kind of background that rarely intersects with the criminal justice system. True-crime storytelling usually leans on backgrounds of deprivation or instability, so a case that breaks that template is genuinely instructive about how motive, opportunity, and identity can decouple from circumstance.
The channel is small (263 subs) but the description signals it has done actual research rather than narrating a Wikipedia summary over stock footage. Expect a case walkthrough rather than a flashy production — useful if you're interested in how investigators reconcile a suspect's public profile with physical evidence pointing the other way.
Caveat: at 263 subscribers, production polish will be modest, and true-crime channels sometimes editorialize. Treat specifics about motive as the channel's framing, not court record.
Daily YT Electronics
2026-05-12
Channel: Kalectronics (641 subscribers)
Round IPS displays have become a popular form factor for smartwatch-style projects, automotive gauges, and retro-inspired UIs, but driving them well requires understanding the ST7789 controller and how to feed it pixels efficiently over SPI. This video walks through pairing a 1.28" 240×240 round panel with an ESP32, covering the wiring, library selection, and the graphics techniques needed to get genuinely smooth animation rather than the flickery tearing that plagues many hobbyist attempts.
What makes this worth watching over the usual "blink a pixel" tutorial is the focus on quality of output: bright colors, wide viewing angles, and the SPI bus speeds the ST7789 can actually tolerate. The ESP32's hardware SPI peripheral is fast enough to push full-frame updates at a respectable rate, and the video should clarify the tradeoffs between popular libraries like TFT_eSPI, LovyanGFX, and Arduino_GFX — each has different performance characteristics on round displays where you also need to mask out the corners.
For anyone building a custom dashboard, a desk clock, or a sensor readout that needs to look polished, this is a practical primer on a display family that's affordable (often under $10) but underdocumented. Kalectronics is a small channel that tends to focus on actual hardware integration rather than promo content, which is exactly what you want when wiring up a new peripheral.
Daily YT Engineering
2026-05-12
Channel: Fluidmapper (5 subscribers)
Caveat: today's batch is weak — mostly Hindi intro lectures, shorts, release notes, and clickbait. This one is borderline (it's a service explainer from a tiny channel) but the underlying engineering problem it frames is genuinely interesting.
Mixing inside chemical reactors is notoriously hard to characterize. Engineers typically reach for one of two tools: empirical correlations (Nagata, Zwietering, etc.) that estimate things like blend time or power number from impeller geometry, or CFD simulations that resolve the velocity field but require careful turbulence modeling and validation. Both leave you uncertain whether the real reactor matches the model.
Fluidmapper's pitch is a third path: directly measure the mixing field experimentally using tracer techniques and reconstruct a quantitative map of residence time distributions, dead zones, and short-circuiting inside the actual vessel. The video walks through how that data drives impeller selection, baffle placement, and feed-port location decisions.
Even if you don't use their service, the framing is a useful reminder that scale-up failures often come from trusting a correlation or a k-ε simulation past its validity envelope. Worth a watch if you design, scale, or troubleshoot stirred-tank reactors.
Daily YT Maker
2026-05-12
Channel: Glitches 3D Prints (1280 subscribers)
Note: this batch was unusually weak — nearly every candidate was a hashtag-spammed Short with no real instructional content. This pick is the least bad of the bunch rather than a standout.
This short from Glitches 3D Prints documents the full resin-printing process for a figure tied to Andy Weir's Project Hail Mary — presumably the Rocky character or the Hail Mary ship itself, both of which have become popular subjects for hobbyist resin prints since the book's release.
Resin printing has a steeper workflow than FDM: orienting the model to minimize support scars on visible surfaces, generating the support tree, slicing for the appropriate exposure curve, washing the green print in IPA, and finally UV-curing before sanding and painting. Even in a short-format clip, watching a small-business operator walk through their actual production sequence is more useful than a generic "look what I made" reel — it hints at the choices a maker makes when prints have to be repeatable and customer-ready.
If you've only done FDM and are considering a resin printer (Elegoo Saturn, Anycubic Photon, etc.), clips like this are a useful low-commitment way to see what the post-processing actually looks like before you commit to the mess and the safety gear.
Daily YT Welding
2026-05-12
Channel: Hammer Spark (3280 subscribers)
Note: today's batch is unusually thin — nearly every candidate is a hashtag-spam Short or a "factory compilation" with no narration. This pick is the least bad option, and it is also a Short, but it at least centers on one specific, recognizable smithing problem rather than generic forging B-roll.
Spring steel — typically 5160 or 9260 — is a favorite stock for knifemakers and tool smiths because it is tough, springy, and often available free from old leaf springs or coil springs. The catch is that it arrives curved, and straightening it is not as simple as hammering a mild-steel bar flat. Spring steel work-hardens aggressively and can crack if you try to bend it cold, so the smith has to bring it up to a uniform forging heat (a bright orange, around 1500–1900°F) before applying corrective blows.
The clip shows that workflow: heating a curved spring section, then using the anvil and hammer to walk the curve out. Watch how the smith places the bend over the anvil's edge or sweet spot and strikes the high side of the curve, letting gravity and the anvil do half the work. It is a small but genuinely useful skill if you ever plan to reclaim leaf springs into knife or tool blanks.
