main
Caleb Version 0.3.0: new copper reader, dome via filter, every layer read from the photos, net evidence, measured confidence;… e874d7d
# id, chapter title, [(spoken, written)] where written=None means the spoken text is also the caption
S = lambda s, w=None: (s, w)
SCENES = [
("board", "The board", [
 S("This is a three phase motor controller. A power connector, a bank of capacitors, six MOSFETs."),
 S("A gate driver and a microcontroller in the middle, each turned forty five degrees.", "A gate driver and a microcontroller in the middle, each turned 45 degrees."),
 S("We have no design files in this flow. Just four photos."),
]),
("underside", "The other side", [
 S("Turn it over, and the copper shows through the solder mask."),
 S("Pours, fine tracks, gaps between them, and more than a thousand tiny domes where vias push up through the mask."),
 S("Everything from here on is read from pictures like these."),
]),
("ask", "The job", [
 S("The job: find the parts and the blocks. Copy all the copper. Work out what can't be seen, propose a layer count, say how sure you are, and list the tests that would settle the rest."),
 S("Then a harder bar. Put every piece of copper on a net. Make the layers match the photos. And keep going until confidence measures ninety percent, or say why it can't.", "Then a harder bar. Put every piece of copper on a net. Make the layers match the photos. And keep going until confidence measures 90%, or say why it can't."),
]),
("flow", "The flow", [
 S("This is A I Flow, reverse engineering. A Rust program does the measuring, and an A I supplies the judgment, like what a part is called.", "This is AI Flow: Reverse Engineering. A Rust program does the measuring, and an AI supplies the judgment, like what a part is called."),
 S("Eleven steps, from intake to report. Each one has a check that has to pass, and each one gets recorded.", "11 steps, from intake to report. Each one has a check that has to pass, and each one gets recorded."),
]),
("photos", "Photos", [
 S("First, the photos. It finds the board edge in each one and straightens it."),
 S("The bottom gets turned over and pinned to the top through forty holes that both sides share.", "The bottom gets turned over and pinned to the top through 40 holes that both sides share."),
 S("With one hole held out each time, they land within about three hundredths of a millimeter.", "With one hole held out each time, they land within about 0.03 mm."),
]),
("scale", "Scale", [
 S("Scale comes from the board itself. Header rows have standard pitches, two millimeters and two point five four.", "Scale comes from the board itself. Header rows have standard pitches, 2 mm and 2.54 mm."),
 S("The driver chip's six millimeter body confirms which standard they are. That gives forty six point six pixels per millimeter.", "The driver chip's 6 mm body confirms which standard they are. That gives 46.6 pixels per millimeter."),
]),
("parts", "Parts", [
 S("Next, the parts. A hundred and thirty seven of them, and a hundred and three get placed by their own pads.", "Next, the parts. 137 of them, and 103 get placed by their own pads."),
 S("Markings get read where they're legible, like this T I D R V eighty three twenty three S.", "Markings get read where they're legible, like this TI DRV8323S."),
 S("Most small ceramics carry no marking at all, so their values just aren't in the photos. The flow says so, and doesn't guess."),
]),
("blocks", "Blocks", [
 S("Silkscreen and circuit role sort them into eleven blocks.", "Silkscreen and circuit role sort them into 11 blocks."),
 S("Power entry, the power stage, sensing, the logic supply, the gate driver and the microcontroller. Then CAN, aux, the fan, motor temperature and the mounting holes.", "Power entry, the power stage, sensing, the logic supply, the gate driver and the microcontroller. Then CAN, AUX, the fan, motor temperature and the mounting holes."),
]),
("copper", "Reading the copper", [
 S("Now the hard part. Under solder mask, copper looks a little lighter than bare laminate, and thin dark lines mark the gaps."),
 S("The reader follows those gaps, and the board comes apart into islands."),
 S("Here's the published version next to this one. Fine tracks that used to be missing now come through."),
 S("That's eight hundred twenty eight pours and two thousand five hundred eighty eight tracks.", "That's 828 pours and 2,588 tracks."),
]),
("domes", "Dome shadows", [
 S("Looking closely found a real defect. The dark side of each dome was being cut out of solid pours."),
 S("So the reader learned what a dome's shadow looks like, and now those pours read solid. Domes with a hole beside them dropped from three hundred ninety six to sixty eight.", "So the reader learned what a dome's shadow looks like, and now those pours read solid. Domes with a hole beside them dropped from 396 to 68."),
]),
("vias", "Vias", [
 S("Vias get a shading test. A real dome is lit on one side and shadowed on the other, in the same direction as all the rest."),
 S("The published filter ringed silkscreen and missed most of the domes. The new one sits on them."),
 S("One thousand three hundred twenty nine kept. The top face shows none it can trust, so these all come from the bottom. A few are still missed along the edges.", "1,329 kept. The top face shows none it can trust, so these all come from the bottom. A few are still missed along the edges."),
]),
("layers", "Every layer", [
 S("It doesn't stop at copper. Each pixel gets sorted by material: mask, silkscreen, metal, or a part sitting on top."),
 S("Silkscreen, mask openings, exposed metal, holes and the outline all get read from the photos, then written into their own KiCad layers."),
]),
("copy", "The KiCad copy", [
 S("All of it goes into a real KiCad project, as photographed, before anything gets guessed. Here it is over the top photo, and over the bottom."),
 S("Every stage opens as an interactive board. Pick a net and all of it lights up: ground, the input rail, a phase."),
]),
("fidelity", "Against the photos", [
 S("Then a separate check compares what KiCad draws with what the photos show, on tiles the reader wasn't tuned on."),
 S("Green agrees. Red is drawn but not seen. Blue is seen but not drawn. Purple is hidden under a part, so it isn't scored."),
 S("The bottom scores point eight seven. The top, point eight two, on only about half the board, because parts cover the rest.", "The bottom scores 0.87. The top, 0.82, on only about half the board, because parts cover the rest."),
]),
("nets", "Every piece on a net", [
 S("Next, every piece of copper gets a net, and a record of how it got it. Pieces get stitched into conductors wherever no gap separates them."),
 S("Green means a pad touches it. Blue, it's joined through a via. Yellow is inferred, orange only by group. Red has no net."),
 S("Three quarters of the copper area now has direct evidence. But forty seven percent of track length is still red, so that goal isn't met.", "Three quarters of the copper area now has direct evidence. But 47% of track length is still red, so that goal isn't met."),
 S("A schematic comes out too. All seventy seven nets are still marked inferred.", "A schematic comes out too. All 77 nets are still marked inferred."),
]),
("router", "Routing what's hidden", [
 S("Now the connections nobody can see. The flow has its own router, and it uses every inner layer."),
 S("Real vias pass through pours, so crossing copper from the photos is expensive, not forbidden. And the length crossed gets reported."),
 S("At six layers, forty five of two hundred fifty three connections stay open. The white crosses are where it got stuck, mostly at the two chips.", "At 6 layers, 45 of 253 connections stay open. The white crosses are where it got stuck, mostly at the two chips."),
]),
("count", "Layer count", [
 S("That difficulty is how the layer count gets proposed."),
 S("Two layers cross four hundred fifty four millimeters of seen copper. Four layers, three hundred eighty four.", "2 layers cross 454 mm of seen copper. 4 layers, 384."),
 S("Six layers, just eleven. Eight, about eight. Past six, more layers stop helping. So the proposal is six.", "6 layers, just 11. 8, about 8. Past 6, more layers stop helping. So the proposal is 6."),
]),
("review", "Measured confidence", [
 S("Confidence isn't self graded. Auditors who did none of the work judge random crops, and some of the claims are planted false."),
 S("Pass one of those, and the whole sample gets thrown out. That actually happened here, on blocks."),
 S("Identity clears ninety. Vias, blocks and placement land around sixty. Values are at thirty four, because most small parts carry no marking.", "Identity clears 90. Vias, blocks and placement land around 60. Values are at 34, because most small parts carry no marking."),
 S("Copper scores nine, because through smooth green mask, an auditor mostly can't tell copper from bare board. Layers stop at thirty without outside evidence. And connectivity is zero, because KiCad finds more missing than expected.", "Copper scores 9, because through smooth green mask, an auditor mostly can't tell copper from bare board. Layers stop at 30 without outside evidence. And connectivity is 0, because KiCad finds more missing than expected."),
 S("Overall is the lowest category, so the loop reports stalled, at zero. It did not reach ninety. From photos alone, it can't: values, layers and nets need measurements on the real board.", "Overall is the lowest category, so the loop reports stalled, at 0. It did not reach 90. From photos alone, it can't: values, layers and nets need measurements on the real board."),
]),
("tests", "Tests for the unknowns", [
 S("Whatever is still unknown gets a test. A hundred and nineteen of them, each saying what to measure, what result to expect, and what to change if it's different.", "Whatever is still unknown gets a test. 119 of them, each saying what to measure, what result to expect, and what to change if it's different."),
]),
("key", "The answer key", [
 S("We did find the real design. It went in a sealed folder as an answer key. The flow never reads it, the agents never see it, and only totals come out."),
 S("Real vias went from forty two percent to over ninety five. Vias found, from twenty six to seventy five.", "Real vias went from 42% to over 95%. Vias found, from 26% to 75%."),
 S("Copper match went from sixty one to sixty seven on top, and from eighty to eighty nine on the bottom. And six layers is correct.", "Copper match went from 61% to 67% on top, and from 80% to 89% on the bottom. And 6 layers is correct."),
 S("Pin nets barely moved. Forty six percent to forty eight. That's the weakest result here.", "Pin nets barely moved. 46% to 48%. That's the weakest result here."),
]),
("notdone", "Not done", [
 S("So this isn't a finished board. Forty five connections stay open, and KiCad counts four hundred forty one missing.", "So this isn't a finished board. 45 connections stay open, and KiCad counts 441 missing."),
 S("Finer copper also made routing harder. New design rule errors at six layers went from six to five hundred ninety four. And these thresholds came from this one board, so a second board has to come next.", "Finer copper also made routing harder. New design rule errors at 6 layers went from 6 to 594. And these thresholds came from this one board, so a second board has to come next."),
]),
("record", "The record", [
 S("Every stage stays in the flow window, so you can step back through the whole run and open any board along the way."),
]),
("cost", "Cost", [
 S('From the first prompt to this point took about 13 hours of A I time in the main thread, with idle gaps cut out, plus 46 sub agents.', 'From the first prompt to this point took about 13 hours of AI time in the main thread, with idle gaps cut out, plus 46 sub-agents.'),
 S('About 3.4 million output tokens and 634 million cache reads, across 1,811 model calls. Next up: real measurements on this board, and a second board.'),
]),
]