Archive — history, not state. Kept for its reasoning and its evidence; its plan is closed.
The press switch — ship/boot presses go through the P6 semantic linker
Branch p/press-switch, from dev @ 0c6f6aacd.
Ruling being executed: R6 — dev = per-module, ship/boot = fully linked.
1. What was wired, and where
The seam
pit-shop/boot_cart.cm, function pool_executable.
That function is the press. It is what both ship/boot lanes lower an executable’s modules through:
| caller | reaches it via | what it produces |
|---|---|---|
make seed / pit forge (boot press) | shop_build.bootstrap_artifacts → boot_cart.cement_root_cart → pool_executable (root exec + every resident) | boot/root.cart |
pit cement --app/--loader (ship press) | shop_tools/cement.ce → boot_cart.pool_executable | a pit.cart@2 image |
Nothing else calls it. grep -rn pool_executable returns exactly those two
consumers plus the definition.
The change
Before, per module, in isolation:
m.mcode.unit → mcode_lower.lowering_code → mach_lower.press_unit → pool
After, once per executable, over the whole module set:
[all mcode-bearing modules]
→ mcode_link.link_result(rows, PRESS_LINK_PLAN) // pit.mcode.program@1
├ import-edge finalization
├ linked streamline (profile ship, stage "link", inline: false)
└ program-granularity literal pool
→ per module: mcode_link.materialize_unit(program, unit_id)
→ mcode_lower.lowering_code → mach_lower.press_unit → pool
The link plan is a constant in boot_cart.cm:
PRESS_LINK_PLAN = {
schema: "pit.mcode.link-plan@1",
profile: "ship",
granularity: "program",
stripping: {names: false, logs: []}
}
valid_link_plan refuses a ship/boot profile that is not granularity: "program", so the plan and the ruling are the same statement.
What the dev lane does
Nothing changed. The dev realize lane lowers per module in
shop_build.compile_unit → finish_unit_mach → lower_mach_unit, which this
landing does not touch. boot_cart.cm is not on the realize path at all.
What does not go through the linker
Only mcode crosses it. A module row with m.mcode == null — a static native
module, a blob — never enters the row set and passes through the press
untouched, exactly the rule shop_tools/internal/diff_runner.cm follows.
2. Artifact deltas
pit cement --app pit-shop/logger (24 linked units) — clean measurement
| before | after | delta | |
|---|---|---|---|
| cart file bytes | 1,073,168 | 1,069,072 | −4,096 (−0.38%) |
| code bytes in image | 907.2 KiB | 903.7 KiB | −3.5 KiB |
| referenced code bytes | 804.3 KiB | 800.8 KiB | −3.5 KiB |
| mcode instructions | 107,298 | 106,395 | −903 (−0.84%) |
guards (is_*) | 9,627 | 9,459 | −168 (−1.75%) |
| literal rows | 1,144 | 557 | −587 (−51%) |
| finalized import sites | — | 0 | see §4 |
| pools/sections | 26 | 26 | unchanged |
| self-verify | OK | OK | — |
The cart shrinks, as predicted, but the shrink comes entirely from the linked streamline pass, not from import finalization. See §4.
boot/root.cart (make seed) — the cart GREW, and the reason is worth reading
| before | after | delta | |
|---|---|---|---|
| root.cart bytes | 9,224,208 | 9,474,064 | +249,856 (+2.7%) |
| pool sections | 129 | 131 | +2 |
| code bytes in image | 7.57 MiB | 7.81 MiB | +0.24 MiB |
| saved by dedup | 7.02 MiB | 6.97 MiB | −0.05 MiB |
The baseline is controlled. The committed boot/root.cart was pressed at
feeb31641, and git log feeb31641..HEAD~1 -- '*.cm' '*.ce' is empty — zero
source commits between that press and this branch’s base. So the “before” cart
is exactly the unlinked press of this same source tree.
Attributing the +249,856 bytes section by section:
NEW sections (2): pit-compiler/structured, pit-linker/mcode_link = +292,352 bytes
COMMON sections (129) net change = −45,158 bytes
net = +247,194 bytes
common sections that SHRANK: 68 GREW: 1 unchanged: 60
So the two effects are opposite and separable:
The press switch itself pays. 68 of 129 existing sections got smaller, exactly one got bigger, for a real −45,158 bytes of pressed code. Every individual module shrank the way the logger cement predicted (
archive/qop117.4→116.3 KiB,cake/plan148.6→147.1 KiB, and so on).The linker now ships in the boot cart.
pit-linker/mcode_link(138.1 KiB) andpit-compiler/structured(147.4 KiB) are new sections, together +292,352 bytes — 6.5× the savings.
Why: boot_cart.cm executes inside the shop actor, and the shop actor’s
own module closure is the root cart. Importing pit-linker::mcode_link into
the press therefore puts the linker’s code into the artifact the press produces.
I checked before wiring that pit-compiler/* was already in the cart (87
references) and concluded there was no new weight — that was right about the
compiler and wrong about the linker: mcode_link and structured were the
two modules the shop actor did not already carry.
This cost is specific to the boot cart. A pit cement app cart does not
carry boot_cart.cm in its closure, which is why the logger cart shrank cleanly
by 4,096 bytes with no new sections.
Three ways out, none of them taken tonight (they need a ruling):
- Accept +250 KB on the boot cart as the price of a linked press. Cheapest, and the boot cart already carries the whole compiler.
- Press outside the shop actor — the builder worker already owns lowering
(BUILD1) and is not in the cart’s closure. Structurally the right home, and it
is where per-module
lower_mach_unitalready goes. - Make the boot cart’s own press unlinked and link only
pit cementoutput. Contradicts R6 (“ship and boot are fully linked”), so I did not.
3. Gate results
All run on p/press-switch, cold-built worktree, on a machine carrying five
other night agents (load average 10–15).
| # | gate | result |
|---|---|---|
| 1 | rm -rf .pit build cold-build pit && make | exit 0 |
| 2 | make seed fixpoint | forge: two clean boot presses are byte-identical + forge: promoted clean binary + boot fixpoint, exit 0 |
| 3 | sh scripts/gate.sh "vm suite" ./pit test run tests/vm_suite.ce | check: vm suite OK |
| 4 | ./pit test suite | 475 passed / 0 failed / 475 |
| 5a | ./pit test run tests/mcode_link.cm | 16 passed / 0 failed / 16 |
| 5b | ./pit test run tests/compile.cm | 187 passed / 0 failed / 187 |
| 6 | ./pit fuzz 100 (seed 175890) | 2226 passed / 0 failed; linked_unlinked 746/0 with shapes 6/0, optimized_unoptimized 740/0, join_types 740/0 |
| 7 | boot sanity | daemon starts from the linked cart, ./pit ps answers, hot ps 0.029 s |
Gate 2 is the one that mattered
make seed is also the R4 first-generation proof. The press code that
produced the final artifacts is the changed code, running inside the generation
it built — forge presses a candidate, rebuilds clean, and byte-compares. Two
clean boot presses coming out byte-identical means the linked press is
deterministic and self-reproducing. It was not hand-promoted around.
Gate 7 is worth stating plainly too: the daemon this branch is now running was booted from a cart whose every module section was pressed out of the linked program. The switch is not merely built, it is executing.
4. THE FINDING John needs: import finalization is inert on this lane
This is the one thing to read if you read nothing else.
The press compiles its units on the STATIC link lane, so there are no import edges for P6 to finalize.
shop_build.cm sets link_mode from msg.link == "pool" ? "pool" : null.
No press caller passes link: "pool" — not seed_fleet_entry, not
prepare_boot_executable, not cement.ce. Grepped: the only producers of
link_mode: "pool" in the tree are shop_tools/compile.ce --link-mode pool,
diff_runner.cm, and tests/*.
Measured directly (probe against the live compiler, both modes, same source
def p = use('provider')\nreturn {f: function() { return p.v }}):
plain (default press lane): import ops = 0, imports table = 1
pool (link_mode: "pool"): import ops = 1, load ops = 2, imports table = 1
In the static lane a use() lowers to a context load, not an import
instruction:
["context",2] ["literal",3,0] ["load",4,2,3] ...
mcode_link.rewrite_function finalizes a ["load", d, s, "member"] only
when slot s traces back to an ["import", d, id]. With zero import ops in
the unit, stats.finalized_sites is 0 — which is exactly what the press
reports on every executable it links.
So the press switch delivers, today:
- ✅ linked streamline — the whole
−903 instructions / −168 guards / −4 KiBwin above - ✅ program-granularity literal pooling — literal rows halve. (Byte-neutral
in the pressed pool, because
mcode_lower.lowering_inline_literalsinlines each referenced literal into its instruction before the emitter sees it. The win is in the mcode program, not in the pressed section.) - ⛔ import-edge finalization / CP2b call directness — structurally
unreachable until the press compiles with
link: "pool".
This is a wall, and I did not force it. Flipping the press to
link: "pool" is not a one-line change and is not what “wire link_result
into the press” means:
boot_cart.press_unitpresses one unit per pool, and a cart section is a pool. A finalized cross-unit edge becomes["function_ref", d, provider_unit_id, fn_id, member], whichsource/mach_pool.c:4590lowers — but the referenced function must be resolvable by the fragment linker. With one unit per pool it is not: it is in a different section.- Making it resolvable means either (a) one pool per executable instead of one
pool per module — which changes what a cart section is, what
execs/module rows name, and every hash in the image — or (b) external-pool matches for finalized edges, which is P8/CP2b level-3 territory.
Either is a redesign of P6/cart output shapes, which the brief said to stop at. Recommend: land this switch (it is the plumbing, and it pays), and take “press compiles on the pool lane” as its own arc with the pool/section granularity question decided first.
5. Decisions I made (each one is a place John may want to overrule)
The seam is
boot_cart.pool_executable, notshop_build.prepare_executable.prepare_executableis shared by dev realize and the press; putting the switch there would have needed a discriminator and would have put the linker in the dev loop’s path.pool_executableis the press and only the press, so the dev/ship split is structural rather than conditional.One executable = one program.
pool_executableis called once for the root exec and once per resident; each call links its own module set. Two executables that share a module link it twice, independently. That is correct for granularity"program"— a program is an executable — but it does mean the shared modules of the fleet are streamlined N times per seed.A link failure REFUSES the press; there is no fallback to the old path. Project discipline (fail loudly, name the thing). The diagnostics are rendered into the error text. A silent fallback would make a linker regression invisible in the artifact.
stripping: {names: false, logs: []}. Name and log stripping are real size levers and P6 supports them here, but they are CP7 with behavioural consequences (producer information disappears from panics), and turning them on in the same landing would make the artifact delta unattributable. Ruling wanted, not assumed.imports: []on every link row. The honest covering for a statically compiled unit set — see §4. I did not fabricate covering decisions to makefinalized_sitesnon-zero.No new cache key, deliberately — and I believe the constraint is already satisfied. The brief asked for keys folding the link plan + member unit hashes. On this lane there is no derivation cache to poison:
- the pressed pool is addressed by
blake2of its own bytes (h = text(crypto.blake2(stone(window), 32), 'h')), andcementre-hashes every section it lays down and refuses a mismatch; mach_lower.press_unitdoes not consultcache_mach_result— only the dev lane’sfinish_unit_machdoes, and that lane is untouched;- the linked program itself is computed fresh per press and never stored.
Staleness across a code change is carried by the existing mechanism: the link plan is a constant inside
boot_cart.cm,boot_cart.cmis a member of the shop actor’s own closure, so changing the plan changes that unit’s source hash → the executable manifest → the seed derivation record. The Makefile’s.cm/.cesource-set fingerprint invalidatesseed-freshon top of that. Adding a key here would have guarded nothing and added a second thing to keep in agreement.Flag for review: the module row’s
mcode.hashnow names the unlinked unit while itsmachnames a pool pressed from the linked one. The image is self-consistent (cement re-hashes), but the row no longer states its own derivation. If you want the cart to be auditable unit→pool, the linked member needs storing and naming — that is a real, separate landing.- the pressed pool is addressed by
The FLOOR units are not linked.
engine/engine_liteandengine/boot_walkstill go throughmach_lower.press_floor_unitunchanged. A floor unit is compiled outside the realize lane, is a single unit with no closure, andmcode_lower.lowering_coderefuses it by construction (which is whypress_unittakescode = nullfor it). There is no program for it to be a member of.shop_actor.ce’s start-timemcode_lower.unit_blobis untouched. That is the shop lowering a realized mcode-payload executable so it can run it — a realization, not a press. The brief said dev realization stays as it is.The linker is now in
boot_cart.cm’s closure — and that turned out to cost more than the switch saves. I verified before wiring thatpit-compiler/*was already inboot/root.cartand concluded there was no new weight. That was right about the compiler and wrong about the linker:pit-linker/mcode_linkandpit-compiler/structuredwere not in the shop actor’s closure, and they are +292 KB against −45 KB of savings. See §2. This is the decision most likely to want overruling — the press arguably belongs in the builder worker, which is not in the cart.
6. Notes for whoever picks this up
- The press logs one line per executable on the
linkchannel:press: linked N unit(s), F finalized site(s), A->B instructions, C->D guards, E->F literal rows. That is the census, live, on every press. - A third
pit cementin one daemon lifetime hung with the daemon idle. Runs 1 (unlinked) and 2 (linked) both completed in 25–46 s; run 3 hung. Both code paths succeeded once each, so this looks like the known daemon-lifetime scratch-image cap (PLAN_IMAGE_MAX=256), not this change — but it is unconfirmed and it is why the byte-determinism check forpit cementis not in §3.make seed’s own two-press fixpoint covers the same property for the boot press. - The night’s machine was carrying 5 other agents (load average 10–15), so every wall-clock number here is contended and not a performance measurement.
Source: plans/archive/night-2026-08-04/press-switch.md