content by LCUS
The gap between the people who make music and the people who distribute it is a gap of technical vocabulary. Ask any of the mid-level staff at a major distribution service to define a sample, and the answer will orbit somewhere near “a piece of a song.” Ask them what a song recorded on a Roland JD‑08 is, and you will get silence, then a shrug, then a request for “clearance documentation” for a track that has no cleared material in it because there is nothing to clear.
A sample is a piece of somebody else’s recording, lifted and dropped into your own — the drum break from an Amen record, four bars of a Fela horn line, a Whitney vocal ad‑lib pitched down. If you use one, you owe money to the person who made the original recording and, usually, to the person who wrote the underlying song.
Samples are fine. They have always been fine, provided the person using them pays the person who made the original recording. That is the line. Some of what I release does use samples, and every one of those is licensed and paid for. The problem is not sample use. The problem is a distribution industry that cannot tell a licensed sample from a synth patch from an uncleared clip — and treats all three the same way: guilty until you prove otherwise, and even then, held for weeks.
A song recorded on a Roland JD‑08 is a song recorded on a Roland JD‑08. The JD‑08 is a synthesizer. It generates the sound; nobody else recorded that sound; there is nothing to sample. The factory presets are Roland’s, and Roland sells the synth on the understanding that you use its presets to write music — that is what the box is for. Every synthesizer ever sold works this way. If a synth preset were a copyright‑cleared sample, no one from Prince to Skrillex would have released a note in the last forty years.
The distribution services don’t know this. Worse: they don’t need to know it, because they’ve built a business where you have to negotiate with them anyway, and if they hold your release for three weeks over a phantom clearance question, you have no recourse. That is the mechanism. Ignorance is the product.
What they do to your music without asking
Since I last released through the majors, the list has gotten longer:
- They change your name. The name I signed with is not the name that appears on the platform. Some services append
‑Topic or the label’s tag; some rename artists whose real name is “too similar” to another artist already in their database — first come, first named, and the second person is told to pick a new identity.
- They change your speed. Loudness normalization is universal now, but some services also apply “tempo smoothing” to tracks flagged as inconsistent. If your song is the inconsistency — a live take, a rubato passage, a deliberate rush — you don’t get to have it. It comes out flat.
- They change your song. Some services will trim silence, cross‑fade abrupt endings, or apply “clean‑up” mastering to a track that was mastered on purpose. The version listeners hear is not the version you delivered.
- They change the name you’re allowed to use. Trademark disputes, artist‑name collisions, and platform‑specific naming rules mean a name that was fine last year is a legal question this year. You have to rebrand, or the release doesn’t ship.
- They can pull it down without telling you. DMCA takedowns are automated; false positives are common; and the appeal process is slower than the release cycle.
This is why I have not put out a song through the distribution services in a long time.
The music on this site is the way I made it. The BPM is the BPM I chose. The title is the title I wrote. The name on the release is mine. If a track sounds like a JD‑08 patch, it is a JD‑08 patch, played by me on the actual synth, recorded on the day I played it. When a track does use a sample, that sample is licensed and paid for — the line is not hard to draw when you are willing to draw it. Nothing on this site has been cleaned up by an algorithm that thinks silence is a defect.
If any of that changes, it will change because I changed it. Not because someone in a support queue mis‑classified my recording as a sample of itself.
Listen to the music →
An escape interposer solves one problem completely: your die has a pitch your board cannot build. Instead of dragging an HDI process across the whole design, you confine it to one small substrate and hand the board underneath an ordinary footprint.
The situation it exists for
You have silicon on a fine grid — say 48 × 32 pads at 0.8 mm. Run the channel arithmetic on that footprint and you get a hard answer: at 0.8 mm pitch with 0.35 mm pads and an ordinary 0.2 mm clearance, the gap between two adjacent balls is 0.05 mm and a trace is 0.075 mm. Nothing passes between two balls. Anywhere. On any layer.
So you have three options.
| Option |
What it costs |
| Build the whole board on an HDI process |
Every square millimetre pays HDI prices, and your fabricator shortlist collapses |
| Use a coarser package |
Board area. 1,536 balls at 2.0 mm needs 94 × 62 mm of ball field alone |
| Put an interposer between them |
One small HDI substrate, and the main board stays ordinary |
What it physically is
A small multilayer substrate with two pad grids on opposite faces and the copper that joins them.
| Top face |
1,536 pads, 48 × 32, 0.8 mm pitch, 0.35 mm pads — 37.6 × 24.8 mm |
| Bottom face |
the same 48 × 32 array at 2.0 mm pitch, 0.9 mm pads — 94.0 × 62.0 mm |
| Ratio |
2.5× radial fan-out. Pad (i,j) on top maps to pad (i,j) underneath |
| Stackup |
12 copper layers — 6 signal, plus ground and power planes |
Note what the bottom face is: 48 × 32 at 2.0 mm is exactly an ordinary coarse-pitch BGA footprint. Whatever the die needed, the board below sees 2.0 mm pitch with 1.1 mm of clear space between pads — three traces per gap on a normal process.
Why it is worth doing
The difficulty is bounded. An HDI substrate 94 × 62 mm is a small, cheap thing to build compared with a 256 × 112 mm main board on the same process. You buy the expensive process only where the density actually is.
It is solved once. The escape is a self-contained geometry problem with no system context. Solve it, verify it, and it does not need solving again for the next revision, the next board, or the next product using the same silicon.
Your fabricator list stays long. The main board goes to anyone. Only the substrate needs a shop that quotes laser-drilled microvias and via-in-pad.
Rails get cheap. Power and ground balls do not need an escape channel at all — they drop straight into a plane through their own via. On this interposer 576 of the 1,536 balls are rails, so only 960 ever compete for routing space. That is a large fraction of the problem that simply disappears.
What it costs you, honestly
An extra interface. Two solder joints per net instead of one. That is a yield and reliability consideration, and it is real.
Z-height and inductance. You have added a substrate to the stack. For most signalling that is nothing; for the tightest power delivery or the fastest edges it is a number you have to actually check rather than wave at.
It is genuinely HDI. Laser-drilled microvias, blind vias, via-in-pad, and capture pads sized to the drill. Get a quote before you commit — it will not price like a two-week prototype, and a fabricator who says “sure, HDI” without asking about stacked versus staggered vias is not the one you want.
The escape may not be complete. A fine-pitch fan-out is a hard routing problem and honest suppliers tell you the coverage figure rather than implying 100%. Ask for it. If nobody will give you a number, that is the number.
When you do not need one
If your part is already coarse — 1.8 or 2.0 mm pitch with generous pads — run the channel arithmetic and you will find you have three traces per gap and no problem to solve. An interposer there is pure added cost and an added interface. The tool is for the case where the arithmetic returns zero.
The one-line test
band = pitch - pad_diameter - 2 x clearance
band >= track -> route it directly, you are fine
band < track -> HDI everywhere, or an interposer
The AutoPhi 1536 escape interposer — the routed 12-layer substrate, its KiCad project, 3D models, a full fabrication package and the design notes explaining what constrains the escape and what was measured — is available as an editable blueprint at the store. We ship the design. You build the board.
One number decides whether a BGA is routable on your process: how many traces fit between two adjacent balls. It is a subtraction, it takes ten seconds, and almost nobody does it before committing to a part.
The formula
Between two adjacent balls you have the pitch. Subtract one pad diameter — half from each of the two pads facing each other. Subtract the clearance twice, once to each pad. What is left is the usable band:
band = pitch - pad_diameter - 2 x clearance
Now fit traces into it. n traces need n widths plus the n−1 gaps between them:
n x track + (n - 1) x clearance <= band
That is the whole thing. The answer is usually 0, 1, 2 or 3, and which of those it is changes what the board costs by a large multiple.
Worked, on three real footprints
Track width 0.075 mm throughout. The clearance column is the one people forget is a choice — it comes from your netclass, not from the fabricator’s floor.
| Footprint |
Pitch |
Pad |
Clearance |
Band |
Traces |
| BGA-256 |
1.8 mm |
0.65 mm |
0.200 mm |
0.750 mm |
3 |
| BGA-1536 |
2.0 mm |
0.90 mm |
0.200 mm |
0.700 mm |
3 |
| BGA-900 |
0.8 mm |
0.35 mm |
0.200 mm |
0.050 mm |
0 |
Read that last row again. Not “tight”. Not “one if you are careful”. Zero. At 0.8 mm pitch with 0.35 mm pads and an ordinary 0.2 mm netclass clearance, there is 50 microns of band and a trace is 75. Nothing passes between two balls, anywhere on the part, on any layer.
This is a cliff, not a slope
Drop the clearance and watch what happens:
| Clearance |
1.8 mm / 0.65 |
2.0 mm / 0.90 |
0.8 mm / 0.35 |
| 0.200 mm |
3 |
3 |
0 |
| 0.100 mm |
6 |
5 |
2 |
| 0.075 mm |
7 |
6 |
2 |
The coarse footprints degrade gracefully — they have slack, and tightening the rule just buys more slack. The 0.8 mm footprint goes from impossible to two traces at 0.1 mm, and then stops improving, because below that the limit is no longer copper-to-copper spacing at all. It becomes the hole-to-copper rule around the via drills, which does not care how thin your traces are.
That is why fine-pitch BGA design has a step in it rather than a ramp. You are not gradually paying more for tighter rules. You are either on a process where the part routes or one where it does not.
What the number means for layers
Index the ball array from the outside in and count rings. Roughly, each ring of signal balls needs its own escape path out through the rings outside it, and each gap between adjacent balls carries however many traces the formula allows.
| Footprint |
Grid |
Rings |
| BGA-256 |
16 × 16 |
8 |
| BGA-900 |
30 × 30 |
15 |
| BGA-1536 |
48 × 32 |
16 |
Ring count grows like the square root of ball count. Six times the balls buys you twice the rings. That is why a 1,536-ball part is not six times the problem of a 256-ball part — and why pitch, which sets traces-per-gap, dominates the total, which only sets ring count.
Two corrections worth making to the estimate
Power and ground do not compete. A rail ball drops straight down into a plane through its own via and never uses a routing channel. On a real ball-out that can be a third or more of the total. On the AutoPhi 1536 interposer, 576 of 1,536 balls are rails, so only 960 ever contend.
The binding clearance is your netclass, not the board minimum. This one costs people days. Board setup will happily say min_clearance: 0.075 while the netclass every signal actually belongs to says 0.2. Channels sized off the board minimum route beautifully and then fail DRC everywhere at once. Check which number your nets are really held to before you count anything.
The ten-second version
band = pitch - pad - 2 x clearance
traces = largest n where n x track + (n-1) x clearance <= band
band < track -> nothing routes between balls. HDI, or an interposer.
1 trace per gap -> expect roughly one ring per layer pair
2-3 traces per gap -> an ordinary board
Do it before you pick the part, not after the layout stalls. If the answer is zero and you cannot move to an HDI process, the escape interposer exists precisely for that case — it converts a fine-pitch die footprint into a coarse-pitch one so the board underneath never sees the problem.
Complete editable KiCad blueprints for all of these — 256, 900, 1536 and the escape interposer — are at the store.
More balls is not harder. Finer pitch is harder. Those are different axes, and confusing them is the most expensive mistake available at the start of a board.
The AutoPhi V19 family comes in three ball counts — 256, 900 and 1536 — plus an escape interposer. People reasonably assume that is a difficulty ladder, with the 1536 as the monster. It is not. Here is what the three actually are, measured off the boards:
| Part |
Grid |
Pitch |
Pad |
Ball field |
Board |
| BGA-256 |
16 × 16 |
1.8 mm |
0.65 mm |
27.0 × 27.0 mm |
182.6 × 70.4 mm |
| BGA-900 |
30 × 30 |
0.8 mm |
0.35 mm |
23.2 × 23.2 mm |
172.5 × 69.8 mm |
| BGA-1536 |
48 × 32 |
2.0 mm |
0.9 mm |
94.0 × 62.0 mm |
256.7 × 112.0 mm |
Read the pitch column, not the ball count. The 900 is the difficult one. It has a third fewer balls than the 1536 and packs them into a ball field a quarter the area.
Why the 1536 is the easy one
1,536 balls at 2.0 mm occupy 94 × 62 mm. That is a large board — 256.7 × 112.0 mm finished — and large boards cost money by area. But every single design rule on it is ordinary. 2.0 mm pitch with 0.9 mm pads leaves 1.1 mm of clear space between adjacent balls. You can walk several traces through that gap on a normal four-layer process.
The 1536 trades board area for process difficulty. If your product has the room, that is very often the right trade, because area is a linear cost and process class is a step function.
Why the 900 is the hard one
0.8 mm pitch with 0.35 mm pads leaves 0.45 mm between pad edges. Once you subtract the clearance a normal netclass demands from each side, what is left will not pass a single trace. The 900 is not a board you route on a standard process at all — it needs HDI: laser-drilled microvias, blind vias, via-in-pad, and line/space down around 3 mil.
That is a real step in cost and in the number of fabricators who will quote it. It is not a reason to avoid the part. It is a reason to know before you commit, rather than after the first quote comes back.
Why the 256 exists
16 × 16 at 1.8 mm is the entry point. Coarse pitch, generous 0.65 mm pads, 27 mm square ball field, and an escape any competent four-layer board can absorb. It is the one to build first when you are validating a design, a supply chain or a fabricator, precisely because nothing about it is exotic.
The ring count, and why it matters more than the total
Index a ball array from the outside in and you get concentric rings. A ball on the outer ring has open board on three sides. A ball in the middle has to cross every ring outside it to reach anywhere. So the number of rings, not the number of balls, is what sets how many routing layers you need.
| Part |
Grid |
Rings |
Balls |
| BGA-256 |
16 × 16 |
8 |
256 |
| BGA-900 |
30 × 30 |
15 |
900 |
| BGA-1536 |
48 × 32 |
16 |
1,536 |
Six times the balls, twice the rings. That is the whole reason a 1536 is not six times the problem of a 256. Ring count grows like the square root of ball count, and it is ring count you pay for in layers.
Note also that a large fraction of any real ball-out is power and ground. Those balls do not need an escape channel at all — they drop straight down into a plane through their own via. On the AutoPhi 1536 interposer, 576 of 1,536 balls are rails, so only 960 ever compete for routing space.
So which one
| If you… |
Take |
| are bringing a design up, or proving a fab |
BGA-256 — nothing exotic to go wrong |
| are tight on board area and can pay for HDI |
BGA-900 — 900 balls in 23 mm square |
| have the room and want ordinary rules |
BGA-1536 — big, coarse, buildable |
| have a fine-pitch die but need a coarse board |
the escape interposer — it converts one into the other |
That last row is the one people miss, and it is the subject of its own article: an interposer lets you buy the 0.8 mm density where you need it and hand the board underneath an ordinary 2.0 mm footprint. The hard part gets solved once, in one small substrate, instead of contaminating the whole design.
All four are available as complete editable KiCad blueprints at the store — schematics, routed boards, libraries, 3D models and fabrication packages. We ship the design. You build the board.
Three product pages, about 1,800 words each, and not one number typed by hand. Every figure is read out of the design files at build time, so the copy cannot quietly stop being true.
Selling a PCB design is an unusual retail problem. The buyer cannot open the box. They are paying for schematics, a routed board, libraries and 3D models, and the only way to judge any of it before purchase is the description. So the description has to be specific, and specific claims rot.
Change a netclass, re-route a region, add a decoupling cap, and every hand-written sentence about layer counts and via geometry becomes a small lie. Not deliberately. Just because the page and the board are two copies of the same facts and only one of them got updated.
Facts First, Prose Second
The fix is to stop writing the numbers. One script opens each board and schematic and writes JSON:
collect_product_facts.py → _product_facts.json → build_descriptions.py → HTML
It pulls the board outline, the physical stackup in order with each layer’s type, per-layer track counts, a via census by type and by pad/drill geometry, the component and pad totals, every netclass with its clearance and widths, the net count, the schematic sheet list, and the do-not-populate list. What comes out:
|
BGA-256 |
BGA-900 |
BGA-1536 |
| Board size (mm) |
182.65 × 70.42 |
172.48 × 69.78 |
256.68 × 112.00 |
| Footprints / pads |
523 / 2,492 |
523 / 3,136 |
525 / 3,804 |
| Tracks |
7,205 |
6,707 |
8,388 |
| Vias |
1,136 through |
969 through |
1,753 through, 222 micro, 22 blind |
| Nets |
1,073 |
1,452 |
1,708 |
| Schematic sheets |
20 |
20 |
28 |
| Copper layers / netclasses |
12 / 11 |
12 / 11 |
12 / 11 |
Re-run it after a board change and the pages update themselves. The generator is a hundred and forty lines. It has paid for itself several times over already, mostly in claims it stopped me making.
It Also Publishes The Bad News
The interesting side effect is that a generator does not know to be flattering.
All three boards carry 191 nets whose names begin with unconnected-. Those are placeholders, not connections. And all three carry 15 components marked do-not-populate — the power section, deliberately left unpopulated pending a design decision, along with a documented over-voltage condition on U1.
None of that is flattering, and all of it is in the description, in its own section, because the script that counts tracks also counts DNP parts and does not have an opinion about which numbers are good for business. A buyer finding out after purchase that a section is unpopulated is a refund and a bad reputation. A buyer reading it on the product page before they click is an informed buyer.
Writing this by hand, the temptation to leave it out is real. Generating it, the temptation never arises.
The Icons Are Drawn, Not Generated
Four products needed images that read as a family. Photographs of bare PCBs all look alike and none of them looks like a blueprint, so the icons are drawn: a flat PCIe card in a minimal style, board outline, gold finger comb split at the PCIe key, the BGA as a ball grid, QSFP cages on the I/O edge, bracket down the side.
Two details do most of the work. Every shape carries a thin dark outline, which is most of why the style reads the way it does. And every icon is drawn on one shared coordinate grid, so the four line up as a set instead of four separate pictures that happen to use the same colours. The ball grid density encodes the part — 8 × 6, 10 × 7, 14 × 9 — so the icons are informative as well as decorative.
Three Magento Traps, For Anyone Who Hits Them
Getting this onto a Magento 2 storefront cost more debugging than generating it did. All three of these fail in ways that do not name the real cause.
Gallery images must be staged inside pub/media
Magento’s PathValidator rejects a path in /tmp outright. Stage the file in pub/media/import and the identical call succeeds. The error does not mention the path.
A zero-priced downloadable link blocks every full save
The downloadable ContentValidator refuses to save a product whose link has a price of zero — even when links_purchased_separately is off, which means the link price is dead data that no customer is ever charged. It fires on any full save(), so it blocks attaching a gallery image, a completely unrelated operation:
Link price must have numeric positive value.
Check the flag first. If links are genuinely sold separately, changing the price changes what buyers pay and you must not touch it. If they are not, set it to 1.00 and move on.
Store-scope overrides silently swallow your writes
Write a description at the default scope on a product that carries a store-level override, and the save succeeds, reports no error, and changes nothing a visitor sees. Writing through Product\Action::updateAttributes at every store scope that carries an override fixes it — and as a bonus, sidesteps the link validator above, because it does not perform a full product save.
The Principle
Anything true of both the artifact and its description should be read from the artifact. Not copied, not summarised at the time of writing, not “kept in sync” — derived, every time the page is built.
It is the same argument as generated API documentation, and it holds for the same reason: two hand-maintained copies of one fact are one fact and one future bug. The difference here is that the copy customers see is the one that gets out of date, because nobody runs a test suite against a product page.
The AutoPhi V19 blueprints — fabrication packages and full editable design sources — are at the store. Every number on those pages was read out of the files you would be buying.
I killed three autorouters mid-run and lost about 48 CPU-hours of routing. Then I said the crash dumps were forensic only. I was wrong, and the proof was 37,831 tokens sitting in a file I had already written off.
This one is a process failure with a technical rescue, and the process failure is the more useful half. So it goes first.
How To Kill Three Routers At Once
Three Freerouting instances were running on the same workstation: the BGA-900 board, the 1536 interposer, and a re-run of the 1536 main board. Long jobs. The 900 had been going for 27 CPU-hours.
Meanwhile, on the same machine and with no thought given to it, I started writing about 20 GB of minidumps, kicked off a video render, and began a 91 GB archive copy.
The machine ran out of headroom. The JVM running the 900 tried to spawn a thread while writing its results and got this:
_beginthreadex (EACCES)
It failed during the save. Not during routing — during the write. All three went down. Nothing landed on disk.
| Job |
Time invested |
| BGA-900 board |
27 CPU-hours |
| 1536 interposer |
17 hours |
| 1536 main board re-run |
3.7 hours |
There is no interesting engineering lesson in “do not start a 91 GB copy next to three long-running solvers”. There is one in what happened next.
The Wrong Call
Asked whether anything could be salvaged, I said the minidumps were forensic only — useful for reading a stack trace, not for recovering work product. That sounded right. Minidumps are small, they are for debuggers, they capture thread state and a bit of context.
The instruction that came back was three words: no check the dumps.
So I checked the dumps.
MDMP header valid
MemoryListStream present
Memory64ListStream present
occurrences of "(wire" 37,831
A minidump written with the full-memory flags is not a stack trace. It is a copy of the process address space. The router had built its finished session in memory and died before serialising it — which means the session was in the dump, in full, as text.
Carving A Session Out Of Process Memory
Specctra session files are S-expressions. They start with (session, they nest, and they close. That is enough structure to find them without knowing anything about the dump format:
- Scan the raw bytes for every occurrence of
(session.
- From each hit, walk forward tracking parenthesis depth until it returns to zero.
- Reject candidates containing bytes that cannot appear in an S-expression — a heap is full of half-overwritten copies and structures that merely start the same way.
- Score whatever survives by wire and via count, and keep the richest.
Step 3 is the one that matters. A live heap holds many partial versions of the same object: earlier routing passes, abandoned reallocations, fragments the allocator has partly reused. Several will parse. Only one is the finished article, and the way to tell is to count what it actually contains rather than trusting that it parsed.
The interposer session came out at 460,570 bytes:
| Wires |
1,230 |
| Vias |
2,521 |
| Nets |
891 |
| Header |
(session “autophi-1536-interposer” (base_design …) (placement (resolution um 10) … |
All three dumps were carved. The 27 CPU-hours came back.
Then KiCad Would Not Import It
Having recovered the sessions, the obvious move was ImportSpecctraSES from KiCad’s Python API. Headless, it returns False and does nothing. No exception, no message.
So the session gets parsed directly. It is not a difficult format once you have the two conversions that matter:
| Units |
(resolution um 10) → multiply by 100 for KiCad internal units |
| Y axis |
negated — Specctra is Y-up, KiCad is Y-down |
| Via names |
Via[0-1]_600:300_um encodes the layer pair and the pad/drill geometry in the identifier |
Get the sign of Y wrong and everything imports mirrored, which looks plausible enough in a thumbnail that it is worth checking against a known pad position before trusting it.
What This Actually Taught Me
“That is not recoverable” is a claim, and claims get checked. I had a real reason for saying the dumps were forensic only. It was still wrong, and the cost of checking was one script and a few minutes against 48 CPU-hours. The asymmetry was overwhelming and I did not do the arithmetic.
A long solver run is unsaved work. Twenty-seven hours of routing existed in exactly one place — volatile memory — with no checkpoint until the very end. That is the actual defect. The dump carve was a rescue, not a fix.
Resource contention kills the job that has the most to lose. The three routers were the long-lived, unsaved, irreplaceable work on that machine, and they were the things I starved.
Format knowledge is leverage. Knowing that a Specctra session is a balanced S-expression starting with a known token turned “the data is gone” into a scanning problem. Text formats survive crashes in a way binary ones frequently do not.
The tools from this — the dump scanner, the session carver, the direct .ses importer — are still in the AutoPhi toolchain. They have not been needed since. The routers now checkpoint.
The AutoPhi V19 design packages are at the store.
A 1,536-ball interposer, six signal layers, and a router that ran out of room after four rings. The fix was not more layers. It was noticing that five sixths of every layer was empty.
The AutoPhi V19 interposer has one job: take a die with 1,536 pads on a 0.800 mm grid and fan it out to a BGA with 1,536 pads on a 2.000 mm grid. Same 48 × 32 array on both sides, 2.5× bigger on the way out. Nothing clever. Just 1,536 connections that have to physically exist.
It took three rewrites of the router to get there, and every rewrite started with a wrong assumption that DRC eventually corrected. This is the whole sequence, including the parts that did not work.
The Board
| Die side (U1) |
1,536 pads, 48 × 32, 0.800 mm pitch, 0.35 mm round pads, 37.60 × 24.80 mm |
| Board side (BGA1) |
1,536 pads, 48 × 32, 2.000 mm pitch, 0.9 mm pads, 94.00 × 62.00 mm |
| Stackup |
12 copper: TOP, GND1, SIG1, SIG2, PWR1, SIG3, SIG4, PWR2, SIG5, SIG6, GND2, BOTTOM |
| Signal layers |
six — SIG1 through SIG6 |
| Nets |
960 signal balls, 576 on rails (GND, APH_VDD_CORE, 1V0) which drop straight to a plane |
| Geometry |
0.075 mm track, 0.20 mm microvia pad on 0.10 mm drill, 0.40 mm blind via pad on 0.20 mm drill |
Index the array from the outside in and you get sixteen concentric rings. Ring 0 is the outer edge, ring 15 is the four innermost columns. The outer rings are easy — a ball on the edge has open board on three sides. The inner rings are the whole problem, because a ball in the middle has to cross everything outside it to get anywhere.
Attempt One: One Ring, One Layer
The first router gave every ball a private drop lane and every ring its own layer. Ball leaves its die pad, jogs off the pad row, runs horizontally out past the edge of the die pin field, drops down a lane nobody else is using, runs back in to its board pad. Clean, easy to reason about, and provably free of crossings because no two balls ever share a segment.
It got through four rings and stopped:
| Ring |
Signal balls |
Layers consumed |
| 0 |
90 |
SIG1 |
| 1 |
86 |
SIG2 |
| 2 |
108 |
SIG3 + SIG4 |
| 3 |
100 |
SIG5 + SIG6 |
| 4–15 |
576 |
none left |
384 balls routed, all six signal layers gone, 576 balls with nowhere to go. Rings 2 and 3 needed two layers each because their left/right traffic and their up/down traffic both want the same corner quadrants, so they had to be split.
An autorouter was the obvious next move. Freerouting ran for hours on the same board and ended its log like this:
java.lang.NullPointerException
2026-07-26 07:26:09.288 ERROR Error during routing passes
java.lang.NullPointerException
2026-07-26 07:35:33.143 INFO Saving 'autophi-1536-interposer.ses'...
The file it saved was zero bytes.
The Thing I Had Wrong
The private-lane design was not just conservative. It was answering a question the board does not ask.
The die pads live on TOP. They are 0.35 mm circles on a 0.800 mm grid, and they are dense — that is what makes the die field look impassable. But a signal never routes on TOP. It drops through a microvia to a signal layer, and on that signal layer the die pads do not exist. The only copper there is the 0.20 mm microvia landing belonging to whichever balls were assigned to that particular layer.
Six signal layers, 960 signal balls. Spread evenly, any one signal layer carries about 160 microvia landings across an area of roughly 6,800 mm². The rest is empty. The first router was routing around an obstacle that was on a different layer.
Attempt Two: Measure First
So: model the real obstacles and let a router use the whole plane. A uniform 0.05 mm grid over the board gives 2,000 × 1,360 cells per layer. Mark what a trace centre cannot occupy, then run A* from die pad to board pad, with the direction of travel carried in the search state and a penalty on turns so the paths come out as long rectilinear runs instead of maze scribble.
The first measurement said SIG1 was 64.1% blocked. That did not match the argument above at all, which was the useful part — a number that disagrees with your reasoning is worth more than one that confirms it.
The cause was in my own occupancy code. I was blocking each existing trace by filling its bounding box. That is exact for an axis-aligned segment and catastrophically wrong for a diagonal one. And ring 0 was laid by an even earlier router as single straight diagonals:
| Layer |
Tracks |
Total length |
Average |
| SIG1 |
90 |
2,369.9 mm |
26.3 mm |
| SIG3 |
280 |
1,993.6 mm |
7.1 mm |
Ninety diagonals averaging 26 mm each, every one of them blocking a square roughly 26 mm on a side. Rasterising the actual swept area instead — a vectorised point-to-segment distance over the bounding box — dropped SIG1 from 64.1% to 13.4%. All six layers landed between 9% and 14%.
Four Things DRC Had To Teach Me
The router now produced clean-looking paths that failed DRC. Each round of failures was a real constraint I had not modelled, and each one is the kind of thing that is obvious in hindsight and invisible in advance.
1. A microvia is not a point on its landing layer
Setting a via’s layer pair to TOP–SIG5 does not put copper on SIG5. It puts a barrel through SIG1, SIG2, PWR1, SIG3 and SIG4 on the way down. I had stamped only the landing layer, so inner-ring balls that landed deep punched their barrels straight through the traces of rings 0–3:
[shorting_items]: Items shorting two nets (APH_HSIO_PAIR_238_N and APH_HSIO_PAIR_239_P)
@(2.8000 mm, -0.4000 mm): Track [APH_HSIO_PAIR_238_N] on SIG3
@(3.6000 mm, -0.4000 mm): Micro via [APH_HSIO_PAIR_239_P] on TOP - SIG5
This also inverts the cost of a layer choice. A ball landing on SIG1 blocks its die-pad location on one layer. A ball landing on SIG6 blocks it on all six. The die field is the scarce resource, so the router now tries shallow layers first and only goes deep when it has to.
2. The clearance that applies is not the one in the board rules
Board setup says min_clearance: 0.075. The netclass says clearance: 0.2. The netclass wins, and every channel I had sized off 0.075 was too tight by more than a factor of two:
[clearance]: Clearance violation ( clearance 0.2000 mm; actual 0.0625 mm)
The board minimum is a floor for what the fab can build. It is not what your nets are actually being held to.
3. Vias collide on layers the router never draws on
The die grid is 0.800 mm and the board grid is 2.000 mm, both centred on the same origin. Those two grids drift in and out of phase, and in places a die pad ends up 0.283 mm from a board pad. Their barrels then meet on PWR1 — a plane layer, where this router never places a single trace:
[shorting_items]: Items shorting two nets (APH_VDD_CORE and APH_MGMT_GPIO_149)
@(-5.0000 mm, 11.0000 mm): Blind via [APH_VDD_CORE] on PWR1 - BOTTOM
@(-5.2000 mm, 10.8000 mm): Micro via [APH_MGMT_GPIO_149] on TOP - SIG4
Via feasibility is therefore checked across all twelve copper layers, not the six the router cares about.
4. Moving a via invalidates the antipad that made it legal
Every barrel that crosses a power plane needs the pour to clear a hole around it. Re-point the via and that hole is in the wrong place. Twenty-one hole_clearance violations, all reading actual 0.0000 mm against a zone, disappeared the moment the fills were regenerated before saving.
The Bug That Only a Counter Can Fix
One more, and it is the most interesting of them.
Every ball needs a via at its die pad. Until a ball is routed, nobody knows which layers its barrel will cross — so the router reserves the worst case, TOP down to the deepest signal layer, for every ball still waiting. Otherwise an early ball routes straight across a later ball’s pad and strands it permanently.
But when a ball’s own turn comes, it has to hand that reservation back, or it blocks itself. With a boolean occupancy grid there is no way to do that: if two owners both marked a cell, clearing it for one clears it for both.
So occupancy is a count, not a flag. A ball decrements its worst-case reservation, asks what is reachable, and increments the barrel it actually committed to. Conservative early, exact by the end.
My first attempt at this was a shortcut — a set of cells near each ball’s pads that the search was allowed to treat as passable, on the grounds that a ball must be allowed to sit on its own keepout. It also let the ball sit on everyone else’s copper. Two traces 0.200 mm apart where 0.275 mm was required, for exactly that reason. A “just this once” exception in a constraint checker is a constraint checker with a hole in it.
Where It Stands
All sixteen rings re-routed from scratch: 506 of 960 signal
balls escaped, and DRC came back cleaner than the board had
ever been. Clearance 40 to 0. Shorting 2 to 0. Those forty clearance
violations were the original router’s, and re-laying its work removed
them.
| DRC category |
Before |
After |
| clearance |
40 |
0 |
| shorting_items |
2 |
0 |
| tracks_crossing |
0 |
0 |
| hole_clearance |
0 |
0 |
Getting there took two more mistakes worth naming. Clearing the traces
does not clear the via layer pairs, so 451 unrouted balls kept
microvias parked as deep as TOP–SIG6 while the occupancy model had
only reserved their guaranteed TOP–SIG1: five layers of copper the
model believed were empty, and 199 shorts. And reserving each waiting
ball’s worst-case barrel rather than its guaranteed one
blocked all six layers at all 1,536 die pads at once, which on a 0.8 mm
grid leaves single-cell channels and stalls the router outright.
Then I Stopped Tuning And Derived The Bound
Three rounds of tuning all landed near 510. When effort stops moving a
number, the number is probably not effort-limited.
A ball landing on signal layer k has a microvia spanning
TOP–k and a blind via spanning k–BOTTOM.
Those cross k and (N − k + 1)
signal layers respectively. Add them:
k + (N - k + 1) = N + 1 for every k
The layer choice cancels. Every ball costs seven
barrel-layer crossings on a six-signal-layer board regardless of where it
lands. 960 balls × 7 = 6,720, over six layers = 1,120 via
keepouts per signal layer, invariant. No assignment strategy
changes it. Load balancing helped — it took failures from 56 to 37
on a 250-ball sample — but only by balancing trace
congestion. It cannot touch the via load, and the via load is what binds.
That prediction was testable, so I tested it. If traces were the
constraint, halving the clearance should help:
| Netclass clearance |
Trace pitch |
Routed / 250 |
| 0.200 mm |
0.275 mm |
207 |
| 0.100 mm |
0.150 mm |
207 |
Identical. I had expected a clear gain and written the conclusion
before running it. Trace pitch is not the constraint.
What The Constraint Actually Is
The die grid is 0.8 mm and the board grid is 2.0 mm, both on
the same origin. 2.5 is not an integer, so the grids beat against each
other, and 240 board pads end up within 0.50 mm of a die pad. The
closest pair is 0.283 mm — at which a
0.20 mm microvia pad and a 0.40 mm blind via pad physically
overlap. No clearance rule reaches that. I tested 36 translations of the
BGA grid; the design as drawn is already the best of them.
The fix is not a rule and not a router. It is dog-boning
— putting the blind via beside its pad instead of in it. Sweeping
candidate sites around each colliding pad:
dog-bone reach 0.35 mm: 240/240 colliding pads get a legal via site, 0 still stuck
0.35 mm of offset clears every one of them, and a 0.9 mm pad
on a 2.0 mm grid has roughly 0.55 mm of room to give. The ceiling
is removable; it just is not removable by anything the router controls.
What I Would Tell Myself At The Start
Measure the obstacle before designing around it. Four
rings of routing were spent avoiding pads that were on a different layer.
A number that contradicts your reasoning is a gift.
“SIG1 is 64% blocked” was wrong, and chasing why found a bounding-box bug
throwing away four fifths of the board.
Read the DRC entries, do not just count them. Every
count moved in the right direction at least once while the design
underneath was still broken.
Constraint checkers do not get exceptions. Every
special case letting one object ignore the rules is a defect waiting for a
plausible reason to fire.
When tuning stops paying, derive the bound. Three
rounds of increasingly clever heuristics all landed within a few balls of
each other, because they were all optimising a quantity that provably does
not vary.
Update: Doubling the Layers, Confirming the Theory
The invariant said trace surface is where the gain lives, not via load. That prediction was testable, so it got tested. The interposer’s stackup was rebuilt with twelve signal layers instead of six — from twelve total copper to eighteen — and the router ran again against the fresh grid.
| Metric |
6 signal layers (v1) |
12 signal layers (v2) |
| Total copper layers |
12 |
18 |
| Signal balls per layer, invariant |
146.2 |
73.1 |
| Signal balls per layer, measured |
92 / 87 / 86 / 83 / 78 / 80 |
73 / 73 / 73 / 73 / 73 / 73 / 73 / 73 / 73 / 73 / 73 / 72 |
| Escape routed |
506 of 960 (52.7%) |
720 of 960 (75.0%) |
| DRC routing-quality violations |
0 |
0 |
The measured layer load matched the invariant prediction to a single ball. 877 signal balls that needed routing, twelve layers to spread them across, and A* placed 73 or 72 on each layer with no manual tuning of the load-balancing heuristic. The theorem does not care what the router thinks it is doing.
Escape coverage jumped by 214 balls — a 42% improvement in what actually reaches the BGA. DRC came back clean the first time the re-route finished, once 274 stray traces from the old routing had been swept off physical layer IDs that got renamed to plane layers during the stackup change. Those are the standard hazards of a stackup rewrite, not routing errors.
What the invariant does and does not fix
Layer choice cancels for via congestion (the derivation earlier in this post). Moving from six to twelve signal layers dropped per-layer via keepouts from 1,120 to 1,040 — a 7% improvement, exactly what the algebra predicted, and irrelevant next to the real constraint. The real gain was that trace surface per layer halved. Same 960 signal balls, twelve layers instead of six, means 80 balls of trace traffic per layer instead of 160. Half the trace congestion, same via congestion. The 214 balls of extra coverage came out of that trace headroom.
Cost of the extra layers on a small (94 × 62 mm) HDI substrate: around $300 per piece at typical per-square-inch HDI rates. Not a factor at the substrate’s list price.
The general lesson
The point of deriving the bound was to know which knob to turn. The invariant answered “not layer assignment, not netclass clearance, not routing effort.” That left “more signal layers” as the last remaining knob, and turning it produced exactly the improvement the algebra said it would.
The interposer on the store now ships with the 12-signal-layer stackup and 720/960 routed. The ESCAPE-THEORY.md document that goes with the source bundle is the same document as last week: the invariant does not change — only the choice of N does.
Update Two: 24 Layers, 815 of 960
The N=12 result begged the same question a second time. If doubling signal layers from six to twelve added 214 balls of coverage, what does going from twelve to eighteen do? The invariant already predicted the answer: less. Trace load per layer scales as 1/N, so each doubling helps by a smaller fraction than the last. Twelve to eighteen is not a doubling — it is a 1.5× — so the gain should be smaller still.
Ran the experiment: 24-layer stackup, 18 signal layers between four planes, same router, same lessons.
| Metric |
6 signal (v1) |
12 signal (v2) |
18 signal (v3) |
| Total copper layers |
12 |
18 |
24 |
| Balls per layer, invariant |
146.2 |
73.1 |
53.1 |
| Balls per layer, measured |
92/87/86/83/78/80 |
73/73/73/73/73/73/73/73/73/73/73/72 |
54/54/53×16 |
| Escape routed |
506 (52.7%) |
720 (75.0%) |
815 (84.9%) |
| Delta from previous |
— |
+214 balls (+42%) |
+95 balls (+13%) |
| DRC routing violations |
0 |
0 |
0 |
Third time the layer balance matched the invariant to a single ball. Two of the eighteen layers took 54; the other sixteen took 53. 956 ÷ 18 = 53.11. The two extra balls are the round-off.
Coverage improvement decelerated exactly as predicted. 6 → 12 signal layers bought +42%. 12 → 18 bought +13% on top. Extrapolate the same shape and 24 signal layers would buy another few percent and then flatten as the geometric limit (the 240 pads at the die-BGA grid collision distance) becomes binding rather than trace surface.
Same Design, Three Tiers
Because each stackup change is a fabrication cost knob rather than a design change — same pin map, same die, same escape routing algorithm — the three versions ship as three product tiers on the store. Same substrate design, different HDI process class, different price.
| Tier |
Stackup |
Escape coverage |
Fab class |
Price |
| Access |
12 layers, 6 signal |
506 of 960 (52.7%) |
Standard HDI |
$400,000 |
| Standard |
18 layers, 12 signal |
720 of 960 (75.0%) |
Advanced HDI |
$760,000 |
| Premium |
24 layers, 18 signal |
815 of 960 (84.9%) |
Premium HDI |
$1,200,000 |
Every tier ships the same package structure: editable KiCad source with libraries and 3D models, plus a fabrication package with gerbers, drill, IPC-2581, BOM and pick-and-place (CPL). Every tier also ships the same ESCAPE-THEORY.md document, because the invariant does not change — only the choice of N does.
The Access tier makes sense for buyers who can live with 506 signals routed on a lower-cost HDI process. The Standard tier is the middle: current mainstream HDI, 720 signals, the invariant analysis published a week ago. Premium runs at the process class where a single die substrate approaches full-density fan-out on this pad geometry.
The AutoPhi V19 blueprints — including this interposer, with its
escape coverage and every DRC entry disclosed on the product page —
are at the store. We ship the
design. You build the board.
Software acceleration for existing hardware.
You have 500 videos to transcode. You don’t sit down and write a parallel execution plan from scratch. You run one line:
python wpc-recipe.py ffmpeg-h264 .videos
…and out comes videos.plan.wpc.txt — one tuned command per file, ready to feed straight to WonderPhi Compute, which runs them across every core you own.
WonderPhi Library is the recipe book for WonderPhi Compute. It ships 25 pre-optimized recipes for the most popular command-line tools. Point a recipe at a folder, and it generates a WPC plan with the right flags already filled in — the ones you’d otherwise have to look up on Stack Overflow.
Three Steps
python wpc-recipe.py --list — see every recipe
python wpc-recipe.py <recipe> <folder> — generate the plan
wpc.exe that-plan.plan.wpc.txt — WonderPhi Compute runs it
Or, with the always-on watcher installed, add --inbox and the plan drops straight into the pipeline to run itself.
The Full Recipe Index
Media
| Recipe |
What It Does |
Needs |
ffmpeg-h264 |
Transcode each video to H.264 MP4 |
ffmpeg |
ffmpeg-audio |
Extract audio from each video to MP3 |
ffmpeg |
ffmpeg-thumb |
Grab a thumbnail from each video |
ffmpeg |
ffmpeg-gif |
Convert each video to an optimized GIF |
ffmpeg |
Images
| Recipe |
What It Does |
Needs |
img-resize |
Resize each image to max 1920px |
ImageMagick |
img-webp |
Convert each image to WebP |
ImageMagick |
img-thumb |
Make a 256×256 thumbnail of each |
ImageMagick |
img-compress |
Strip metadata and recompress |
ImageMagick |
Documents
| Recipe |
What It Does |
Needs |
pdf-text |
Extract text from each PDF |
pdftotext |
pdf-compress |
Compress each PDF |
Ghostscript |
pandoc-pdf |
Convert documents to PDF |
pandoc |
pandoc-docx |
Convert documents to Word .docx |
pandoc |
Archives and Integrity
| Recipe |
What It Does |
Needs |
zip-each |
Compress each file into its own .7z |
7-Zip |
unzip-each |
Extract each archive into its own subfolder |
7-Zip |
sha256 |
SHA-256 each file with a combined manifest |
certutil (built-in) |
md5 |
MD5 each file |
certutil (built-in) |
Web and Dev
| Recipe |
What It Does |
Needs |
curl-check |
HEAD health-check each URL in a list |
curl (built-in) |
curl-get |
Download each URL into the output folder |
curl (built-in) |
pytest-dirs |
Run pytest in each subdirectory |
pytest |
git-gc |
Run git gc on each repo subdirectory |
git |
git-pull |
git pull –ff-only in each repo |
git |
GPU Recipes
| Recipe |
What It Does |
Needs |
ffmpeg-nvenc |
GPU H.264 transcode via NVENC |
ffmpeg + NVIDIA |
ffmpeg-nvenc-hevc |
GPU HEVC transcode (smaller files) |
ffmpeg + NVIDIA |
whisper |
Speech-to-text transcription on GPU |
Whisper + CUDA |
realesrgan |
4x image upscaling on GPU |
Real-ESRGAN |
Every recipe uses one of three input models: files (scan a folder), dirs (one job per subfolder), or lines (one job per line in a text file). GPU recipes auto-detect your NVIDIA card and fall back to the CPU equivalent when no GPU is present.
No Lock-In
The Library generates plain-text plan files. You can read them, edit them, combine them, or write your own. Nothing is hidden. Nothing is compiled. The recipe is just the recipe — WonderPhi Compute is the kitchen.
Zero dependencies. Python standard library only. No network. No telemetry.
Get WonderPhi Library — $9.99 →
Browse the full WonderPhi product line
Software acceleration for existing hardware.
Theory is cheap. We measured WonderPhi Compute on real hardware — a workstation with dual Intel Xeon Gold 6138T processors (40 physical cores, 80 logical), an NVIDIA A10M GPU with 19 GB of VRAM, running Windows 11 Pro. Every number below is wall-clock time, single run, cold cache. No averaging. No cherry-picking.
The Machine
| CPU |
2x Intel Xeon Gold 6138T @ 2.00 GHz — 40 physical / 80 logical cores |
| GPU |
NVIDIA A10M — 19 GB VRAM, Ampere architecture, 7th-gen NVENC |
| OS |
Windows 11 Pro |
| WPC Config |
64 workers (cap 64, cores 80), GPU exposed as $WPC_GPU=1 |
This isn’t a cloud instance. This is a machine sitting on a desk, running production workloads around the clock, with WonderPhi’s three watchers armed and autonomous.
Test 1 — SHA-256 Hashing (Pure CPU Parallel)
The simplest possible benchmark: hash the same 500 MB file 40 times. CPU-bound, memory-bandwidth-sensitive.
| Serial (bash for-loop) |
96.61 seconds |
| WPC parallel (64 workers) |
6.84 seconds |
| Speedup |
14.1x |
Why not the full 64x? All 40 threads read the same file concurrently — memory bandwidth saturates before CPU does. That’s a DDR4 bottleneck, not a WPC limit. Workloads with distinct files per task (like the 541-domain health check we ran) hit 40-50x because each worker reads independent bytes.
Test 2 — 1080p H.264 Video Encoding (CPU vs. GPU)
Same 3-minute 1080p30 source (5,400 frames), 3 parallel encodes on each side.
| CPU (libx264, CRF 23) |
51.38s — 315 fps aggregate |
| GPU (A10M NVENC, CQ 23) |
48.07s — 337 fps aggregate |
| GPU speedup |
1.1x (6% faster) |
On 1080p H.264, this box’s 40-core CPU is competitive with the A10M. Use the GPU when you want to keep CPU free for other work, not for raw throughput.
Test 3 — 4K HEVC Encoding (CPU vs. GPU)
30-second 3840×2160 30fps source (900 frames), 2 parallel encodes.
| CPU (libx265 fast, CRF 28) |
36.27s — 50 fps aggregate |
| GPU (A10M NVENC, CQ 28) |
24.36s — 74 fps aggregate |
| GPU speedup |
1.5x (33% faster) |
At 4K, the GPU pulls ahead. HEVC at this resolution is far heavier than H.264 at 1080p. NVENC is silicon — it doesn’t care about resolution the way software encoders do. The gap widens with resolution: at 8K, expect 3-5x.
Test 4 — AV1 Encoding
An honest caveat: the A10M does not support AV1 hardware encoding. Ampere NVENC (7th gen, 2020) has H.264 + HEVC only. AV1 NVENC arrived with Ada Lovelace (2022). All AV1 results are CPU.
| libaom-av1 (reference encoder) |
219.87s — 4.1 fps |
| libsvtav1 (fast encoder) |
12.33s — 73.0 fps |
| Encoder choice speedup |
17.8x |
Encoder choice matters more than parallelism on AV1. And WPC parallelism helps for multi-file batches: 6 videos in parallel finished 3.1x faster than serial — but libsvtav1 is already multi-threaded internally, so you get diminishing returns.
The 541-Domain Health Check
We also ran a real-world operational test: a WPC plan with 541 independent curl health checks against live domains. Results: 442 reachable, 99 unreachable, total wall time 17.1 seconds. That’s 541 network requests, each with a 5-second timeout, completed in under 18 seconds.
Honest Takeaways
| Workload |
Best Option on This Box |
| Batch hashing, checksumming, validation |
WPC parallel CPU (14-50x) |
| Batch web scraping / health checks |
WPC parallel CPU (bounded by network) |
| 1080p H.264 encoding |
Either — CPU or NVENC depending on what else is running |
| 4K HEVC encoding |
A10M NVENC (1.5x, grows with resolution) |
| AV1 encoding |
libsvtav1 on CPU (17.8x over libaom; no GPU AV1 HW) |
| Real-time streaming |
A10M NVENC — consistent fps regardless of CPU load |
Every claim on the product page is backed by a number we measured. That’s the difference between marketing and evidence.
Get WonderPhi Compute — $99.99 →
Browse the full WonderPhi product line
Software acceleration for existing hardware.
Every machine you own has more power than you use. Cores sit idle. GPU memory stays dark. Background processes eat cycles you never asked them to. The operating system has its own agenda, and your work waits in line behind it.
WonderPhi Compute is the antidote: a constitutional parallel runner that reads a plain-text plan of shell commands and executes them across every CPU core, honestly showing you what it’s doing.
What Makes It Different
Most parallel runners — GNU parallel, make -j, xargs -P — grew organically over decades. A hundred flags. No philosophy. WonderPhi Compute is designed the other way: 10 immutable constitutional rules, hardcoded into every binary, verified at startup, and carved in stone.
| # |
Commandment |
What It Guarantees |
| I |
Sole Master |
No competing orchestrator overrides WPC mid-run |
| II |
No Other Gods |
Exactly one instance per working directory |
| III |
Not in Vain |
Malformed plans rejected, never silently mangled |
| IV |
Sabbath |
Idle workers sleep — no busy-waiting, no spinning |
| V |
Honour Thy Parents |
The plan format is frozen forever |
| VI |
Not Kill |
Log appends only — a crash never destroys history |
| VII |
Not Adultery |
Commands dispatched verbatim — no silent retry |
| VIII |
Not Steal |
Max 64 concurrent, 4 GB/task, 24-hour runtime cap |
| IX |
Not False Witness |
Exit codes and elapsed times reported truthfully |
| X |
Not Covet |
Zero dependencies, no network, no telemetry |
Every version of WonderPhi Compute that will ever exist is v1.0.0. Born once. Never updated. No subscription. No telemetry. No dependencies. That’s the constitutional guarantee.
How It Works
You write a plan file — a plain-text list of shell commands, one per line. Blank lines are barriers: everything above must finish before anything below starts. Comments start with #. That’s the entire format.
# WPC v1
# Stage 1 — extract text from every PDF in parallel
pdftotext report001.pdf out001.txt
pdftotext report002.pdf out002.txt
pdftotext report003.pdf out003.txt
# Stage 2 — aggregate (waits for stage 1)
cat out*.txt > combined.txt
Feed that to wpc.exe, and it runs every stage across every core simultaneously. A serial script that would run for two hours finishes in ten minutes.
GPU Awareness
WonderPhi Compute detects your NVIDIA GPU at startup and exposes $WPC_GPU=1 to every task’s environment. It doesn’t offload work to the GPU itself — that’s the job of your commands. But your scripts can branch on GPU availability, choosing the right silicon for the right job.
Always-On Mode
Three cooperating watchers turn WonderPhi into a drop-a-file-and-it-runs service:
- The Watcher — drop plan files into
wpc-inbox, they run automatically
- The Autoplan — drop 5+ files of the same type, and a plan is generated and dispatched automatically
- The Observer — samples your process list, and when it sees the same tool running 5+ times, suggests a parallel plan
None of these modify wpc.exe. The 10 Commandments and the v1.0.0 guarantee remain completely intact.
Who This Is For
If you work with media files, batch processing, data pipelines, web scraping, testing, archiving, or any other workload where the same command runs many times — this is for you. Whether you’re a video editor transcoding a season’s worth of footage, a researcher checksumming a forensic evidence archive, or a developer running tests across twenty repos at once — WonderPhi puts every core to work.
No subscriptions. No cloud dependency. No telemetry. Just your hardware, fully utilized, with honest reporting.
Browse the WonderPhi Compute product line →
WonderPhi Compute — $99.99 | WonderPhi Library — $9.99 | WonderPhi Autonomous Compute — $29.99
there's one of a kind art and then there's digital art, I have both for sale.
to cast without bubbles
MORE
300×300
Art piece 1
healthy fair curves and fine accents
300×300
Art piece 2
healthy fair curves and fine accents
300×300
Art piece 3
healthy fair curves and fine accents
Place a Bid at the Auction
there's invent and then the sort of invent patents or copyrights
Three Ways to Shop Inventions
if you need all of the inventions click here to see the bulk catalog and review all there is for sale. Or click here to see individual items at the store...
Archive with Historical Accuracy — a Frontpage designed and Bootstrap Updated View for your Enjoyment.