ж-box arc — stage A1 census report

STATUS: CENSUS — stage A1 of DESIGN-zh-box-reduction.md (§9), lane L3. Analysis only; zero emission change (CNR byte-identical is the gate). The verdict this report exists to deliver: the §3.6 projection is CONFIRMED on the recommended branch (§10.3’s hoisted-temp rule) — every site class the ~7k-residual projection zeroes is confirmed lowered/reverting by static census against the real corpus, the §3.3 emission-shape table covers the corpus with zero unclassifiable argument shapes at lowered positions, and the per-GOOS delta adds no new layout-L3 memberships. Findings that reprice details (not the branch) are in §6.

Toolchain caveat, stated first: these numbers were measured on go1.23.2 (lane machine laptop-1); the corpus is pinned to 1.23.1. Per the standing coordinator ruling, laptop re-measures are developmental until the repin — the durable deliverable is the INSTRUMENT, and re-derivation on the pinned machine is one command (§1). Every number in this report should be re-derived there at merge; deviations from the design’s 2026-08-10 pinned-machine inputs are reported in §5 and never forced into agreement.

1. The instrument, and the one-command re-derivation

The classification pass is src/go2cs/refLoweringAnalysisOperations.go (the design §8’s named file): a package-scope, whitelist-shaped D1/D1′/D2 vs X1–X5 classifier over every package-level function’s pointer parameters, the two-sided fixed point (§3.2 — forward strips AND caller-side emittability strips), the §3.3 per-call-site argument-shape census (rows 1–7 / defer-go / other-veto), and the §3.3 address-taken-local reversion census. It runs in all three conversion drivers (normal, -tests on production files only, hand-owned-sibling — §3.5’s three-driver rule), records its verdict on the package context (packageRefLoweringResult; nothing emission-side reads it at A1), and prints a per-package census block under -debug.

The corpus-scale instrument is -ref-census (src/go2cs/refLoweringCensus.go): with -stdlib, it loads the standard library once per -platforms target with full syntax (the same std pattern, GO111MODULE=off, GOOS/GOARCH environment and purego-default tags the -stdlib scanner uses), classifies every convert-set package, resolves the Phase-A and A′-world fixed points globally, cross-references candidates against the hand-owned file set (read-only), diffs classification across GOOS targets, and writes one JSON report plus a stdout summary. It emits nothing, anywhere — no seeded staging roots exist because no conversion runs; -go2cspath is read only to locate src/core for the hand-own scan.

The one-command re-derivation (run from a clone, pinned machine):

go2cs -stdlib -ref-census <out.json> -platforms windows/amd64,linux/amd64,darwin/amd64 -go2cspath <repo>\src

Wall time on laptop-1: ~10 s for all three targets (one std load each). Unit guards: refLoweringAnalysis_test.go (D/X families, both strip directions of the fixed point, the shape rows, the locals census, the §3.5 production-only determinism invariant with an export_test.go func-value alias, bodiless/linkname X5).

Rulings honored: §10.1 (Phase-A scope = unexported package-level functions; exported classified under the one A′ flag), §10.3 (row 5 = hoisted-temp rule; the projection below is priced on it), §10.4 (nil doctrine — shapes only at A1; row 7 counted), §10.5 (A before B — nothing golib-side was touched), §10.6 (started on the coordinator’s post-harvest go signal).

2. The census, per §9 items (a)–(f)

All numbers windows/amd64 (the primary corpus target) unless stated; linux/darwin in §2.6.

(a) How many params/locals lower

  corpus-wide nistec/fiat edwards25519 edwards25519/field nistec
package-level funcs 7,736 48 18 9 25
pointer params 2,819 96 24 10 32
lowered (Phase A) 564 96 (100 %) 22 6 0
address-taken locals 2,771 158 74 15 20
locals reverting 236 150 (95 %) 21 0 0

The corpus-wide picture is exactly the design’s claim (§3.6: “the count win is concentrated where the bill is”): 8.5 % of the corpus’s address-taken locals revert, but 95 % of fiat’s do, and the 8 fiat keeps are all in the wrapper file (Bytes’s &out into the bytes method — non-candidate position; SetBytes’s in, kept by the design’s own implicit-address predicate for in[:] — see §6.3). The method-side counts for B′ context: 1,609 method pointer-params corpus-wide; veto/kept tallies are in the JSON.

(b) Per-call-site argument shapes (§3.3 rows, at Phase-A-lowered positions)

Shape corpus fiat edwards25519 notes
row 1 &e.x field addr 281 56 16 the fiat op-argument class
row 2 &x local addr 286 154 22 the fiat64 CmovznzU64 feeds
row 3 pointer var 806 4 1 corpus-dominant; carries boxes, mints nothing
row 4 &s[i] elem addr 17  
row 5 pointer conversion 31 20 7 see below
row 6 temp (composite/new/call) 11  
row 7 literal nil 1 3 on darwin
defer-go (boxed carve-out) 13 gob 3, go/parser 5, fmt 2, net/http, runtime, text/template 1 each
other-veto (no emission row) 0 0 0 the §3.3 table covers the corpus

Zero other-veto shapes on every target is the completeness proof A1 existed to obtain: no call-site argument shape at any lowered position falls outside the seven rows plus the defer/go carve-out, so the caller-side strip of the two-sided fixed point never fired on the real corpus (it is unit-guarded synthetically). The 31 lowered-position row-5 sites decompose completely: 20 fiat + 7 edwards25519-scalar + 4 elsewherecrypto/internal/mlkem768.pkeEncrypt#2 (conv-of-value), os.newFileStatFromFileIDBothDirInfo#0/…FullDirInfo#0 (conv-of-value, dir_windows.go), and runtime.semawakeup#0 (conv-chain, lock_sema windows — moot: that function falls to the declared-in-hand-own X5 arm of §2 c). Sub-shapes to carry into A2: conv-of-address (the priced (*T2)(&v.x) fiat shape — all 20 fiat sites and 6 of 7 edwards25519 sites) and conv-of-value (4 sites — the temp rule hoists an already-computed value; same mechanics, listed so A2 prices them). The remaining syscall-seam conv-chain sites (WSAIoctl etc.) target X3-vetoed positions and are inert.

Row-5 count vs the panel’s: the panel priced “16 sites across the four curve files” (C-F1); the census measures 20 in fiat (per curve: Select 3 + ToBytes 1 + FromBytes 1) plus 7 in edwards25519’s scalar family. Favorable deviation — more conversion-shape sites are covered by the ruled temp rule than were priced.

(c) Hand-own + linkname cross-references

Marker census, re-measured (line-anchored ^\s*\[module:\s*(go\.)?GoManualConversion\], cross-checked against git grep -P — identical): 49 marked files, 41 *_impl.cs companions, 31 files in both lists, 59 distinct hand-owned files. The design’s §3.5 asserted “44 marked + 26 *_impl.cs” (r51b-era); the counts moved with r52–r60 and with framing (the 31-file overlap makes “marked” and “companion” non-disjoint categories). Full lists in the census JSON.

Cross-reference of every Phase-A-lowered candidate against same-package hand-owned files (word-anchored textual scan; same-package is the complete exposure set — a lowered candidate emits internal, foreign assemblies cannot bind it, and the linkname escape is already X5): 17 textual hits, resolved per instance:

Verdict Instances
REAL — resolve at A2 (4) hash/crc32.castagnoliShift (declared and called in the marked crc32_amd64.cs); hash/crc32.slicingUpdate (declared in a regenerated file, called from the frozen hand-own, line 371); runtime.getLockRank + runtime.lockWithRankMayAcquire (both called from marked mfinal.cs line 112: lockWithRankMayAcquire(Ꮡfinlock, getLockRank(Ꮡfinlock));)
Comment-only word collisions, dismissed (13) runtime.noteclear/full/open/semacreate/semawakeup (doc comments in runtime2.cs and the lock impls), internal/chacha8rand.setup, os.newFileStatFromFileFullDirInfo/…IDBothDirInfo, syscall.copyFindData (all comment lines)

The A2 remedy this resolves to (small and mechanizable): X5 gains one arm — “declared in a file whose emission target is hand-owned” — checkable at conversion time with the existing per-file containsManualConversionMarker probe (this alone closes castagnoliShift and the whole semacreate-class of frozen-declaration functions wholesale, on every GOOS via the L3 routing the probe already follows); plus a curated 3-function called-from-hand-own exclusion (slicingUpdate, getLockRank, lockWithRankMayAcquire). Zero hand-own edits are required for Phase A. Linkname exclusions ran inside the pass (X5-linkname: 177 params corpus-wide) — handles scanned per package, the curated forward/push registries consulted both sides.

(d) Per-GOOS classification deltas (the layout-L3 propagation)

25 positions across 5 packages differ in Phase-A verdict between targets that declare the function — and all five packages are ALREADY layout-L3 (runtime 14, net 7, os 2, internal/filepathlite 1, syscall 1): the L3-set delta is ZERO new packages. The variance is the expected OS-conditional-body class (net.fileConn lowered on windows only, os.sameFile lowered on unix only, runtime’s os-layer helpers, …; full table in the JSON). A2’s merge churn from classification is therefore bounded to within-package file movement in packages that already carry per-GOOS folders — priced, not discovered. Functions present on a single target were excluded from the delta by definition (platform-exclusive, no new variance).

(e) Both fiat families

(f) The exported-candidate classification (§10.1’s A′ decision input)

The strict A′ flag (exported package-level function, ≥1 param lowered under the A′-world global fixed point): 64 functions — with a corpus-wide call-site traffic of just 69 argument records (top: unicode.Is 9, internal/runtime/atomic.LoadAcq 8, image/internal/imageutil.DrawYCbCr 6; everything else ≤ 6). A′ widens lowered positions 564 → 632 (+68).

Against the design’s 2026-08-10 measurement (347: 115 internal/*, 80 sync, 46 syscall, 26 constructor-shaped/X2) — reported, not reconciled, at three strictness levels:

Level total internal/* sync syscall other
L0: exported, ≥1 pointer param 444 122 39 104 179
L1: minus func-level X5 (bodiless/linkname/func-value) 354 78 0 104 172
L2: strict A′ candidates 64 24 0 6 34
exported with an X2-return (constructor-shaped) veto 3        

L1’s total (354) sits near the design’s 347, and the design’s own annotations forecast the drops my stricter levels apply (sync “largely the hand-owned atomic surface” → all func-vetoed at L1; syscall “X3-dominated” → 104 → 6 at L2). The constructor-shaped bucket differs sharply (3 vs 26) — likely an instrument-definition difference (mine counts X2-return vetoes on exported functions; the design’s 26 may include store-shaped X2). Toolchain (1.23.2 vs 1.23.1) and instrument definitions both contribute; re-derive on the pinned machine before any A′ decision. On these numbers the census’s input to the checkpoint is plain: the A′ prize is small (+68 positions, 69 traffic records, no bucket concentration worth an arc).

§9 (a)–(f) per-target roll-up

  windows/amd64 linux/amd64 darwin/amd64
packages / funcs 304 / 7,736 302 / 7,774 303 / 8,028
pointer params / lowered A / A′ 2,819 / 564 / 632 2,532 / 558 / 623 2,590 / 568 / 634
locals address-taken / revert 2,771 / 236 2,687 / 233 2,783 / 237
exported candidates (A′) 64 61 62
other-veto shapes at lowered positions 0 0 0

3. The §3.6 projection, re-derived from the real corpus

A static census cannot re-run r56d’s dynamic counters; the honest re-derivation is per-class static coverage of the sites that generate the dynamic bill, priced against r56d’s measured per-run counts (P256):

Class dynamic bill (r56d) census coverage verdict
address-taken locals (box + slot) 153,026 fiat64’s CmovznzU64-fed locals revert (150/158 fiat-wide; the generated op locals ALL revert — the 8 keeps are wrapper-file sites whose phases are ≤ 1 % of the bill each) → ~0
field-ref boxes at plain lowered positions ~46,506 all 56 fiat row-1 + 154 row-2 sites sit at lowered positions (Sub/Mul/Add/Square arg feeds, &tmp/&in wrapper feeds) → ~0
conversion-shape boxes (3a) ~34,560 all 20 fiat row-5 sites classify conv-of-address at lowered positions; §10.3’s temp rule applies to every one → ~0
@new<T>() (3b) ~3,600 nistec’s point helpers unlowered by scope; new(…) sites are row-6/X2 — untouched, as designed unchanged ✓
array<T> backings (4) 3,386 untouched unchanged ✓
projected residual     ~7,000 (−97 %) — the recommended branch

BRANCH VERDICT: projection CONFIRMED; §10.3’s hoisted-temp branch stands. No argument-shape class is bigger than priced (row 5 measured larger in coverage, 27 vs 16, in the favorable direction), no unclassifiable shape exists at any lowered position, and the veto branch’s re-opening condition (a materially-below census) did not occur. The §7 unit-target statics all hold: every parameter of Mul/Add/Sub/Square/Select’s call chains lowers, Select’s conversion feeds classify row 5, and CmovznzU64’s class-2 sink lowers. One honest amendment to §7’s table: the SetBytes probe’s residual will include in’s kept box (the in[:] implicit address — §6.3) and the Bytes probe’s out box (method position) — small named terms, not projection movement.

4. Gate results (A1 gates per §9)

Recorded by the lane at commit time — see the lane report; the coordinator re-gates at merge:

5. Deviations from the design’s measured inputs (reported, never forced)

  1. Toolchain: census on go1.23.2, corpus pinned 1.23.1 — every number developmental until the pinned re-derivation (§1’s command).
  2. 347-split (§2 f): strict A′ = 64; nearest instrument-level L1 = 354 vs 347; buckets differ with forecastable causes; constructor-shaped 3 vs 26 (definition difference suspected).
  3. Row-5 site count: 27 lowered-position sites (20 fiat + 7 edwards25519) vs the panel’s 16 — favorable (more coverage than priced).
  4. Hand-own census: 49 marked / 41 *_impl.cs / 59 distinct vs the design’s “44 + 26” — r52–r60 growth plus overlap framing; per CLAUDE.md the count is re-measured, never carried.

6. Findings the design did not anticipate (A2 pricing notes; none re-open the branch)

  1. §3.2 text vs §3.3 carve-out on defer/go, resolved toward §3.3: §3.2’s parenthetical “(or sits in a defer/go statement)” reads as a position-strip; §3.3 (and guard 3) make defer/go sites boxed carve-outs of a still-lowered callee. Implemented per §3.3 — defer/go never strips the callee — with the parameter-side mirror the design implies but does not state: an address-carrying use (D1′/D2) of the CALLER’s own candidate parameter inside a defer/go argument frame vetoes that parameter (X2-defer-arg — the thunk stores a box a lowered parameter no longer has). 13 defer-go sites exist at lowered positions corpus-wide; the carve-out is load-bearing exactly there.
  2. The pointer-slice shape p[:] (19 params corpus-wide, edwards25519.copyFieldElement the fiat-family instance): not a §3.2 D row, so it vetoes — under its own tag (other-use-ptr-slice) so A2 can decide whether a D-row for it is worth having. It never solely blocks a projection-relevant site.
  3. SetBytes’s in keeps its box by the design’s own predicate (in[:] is an implicit address-take per §3.3’s reversion rule) — the §7 SetBytes/Bytes probe rows gain a small named residual term (§3 above).
  4. edwards25519/field’s carryPropagate strip (§2 e): the second fiat family’s field multiply keeps the boxed convention in Phase A because its core ends in a method call. Allocation-neutral for Phase A’s measured prize; a named constituent for B′.
  5. The whitelist’s default arm never decided an outcome alone: other-use fired only co-vetoed (darwin’s 16 pthread-seam params, all X3 alongside; linux 1; windows 0) — the classifier’s recognized-shape coverage is effectively total on this corpus.
  6. A2’s hand-own rule (§2 c): X5 gains the declared-in-hand-own arm + a 3-function curated exclusion; zero hand-own edits owed.

7. Census artifacts