diff --git a/phase-ends/logs/Phase10.md b/phase-ends/logs/Phase10.md index f63d94d..e9f36c5 100644 --- a/phase-ends/logs/Phase10.md +++ b/phase-ends/logs/Phase10.md @@ -490,3 +490,70 @@ built by one compiler configuration. coordinator 39%, A 45%, B2 16%, C 53% (stopped at its own 68% measure). A fresh session for C's partition is approved by the developer; C's `HANDOFF.md` (12 levers, 15-row negatives table, size-band measurement) is its brief. + +## Cycle 1 — merges 19-20, the polarity lever's limit, and a staging slip (2026-09-24) + +**464 distinct bodies / 473 regions** (from 400 / 409) — **+64 of the +75 milestone.** + +### Worker A: 8 more bodies, all first-attempt + +A's 18 claims: **16 needed no override at all.** Two new levers, both general and both broadcast: + +1. **A two-arm selection's polarity is byte-required.** For `a1 = (x < 2) ? a3 : saved`, both the + natural order and the ternary emit `beq v0,zero` with the arms swapped (right length, 5 differing + bytes). Writing the larger-than arm first makes cc1 emit `bne v0,zero` with `a1 = a3` in the **branch + delay slot** — running on both paths and overwritten on the `>= 2` path, exactly as the original does. + Diagnostic: **arm placement with the length already right → invert and swap; do not hunt a + scheduling flag.** +2. **A named boolean local forces the branchless compare.** `rec[6] = ((a3 & 0xff) != 0) << 1` is + branchy at 92 bytes; only `int flag = (a3 & 0xff) != 0;` then `rec[6] = flag << 1` gives the + original's `andi`/`sltu`/`sll` at 88. Six spellings measured. Generalised: **cc1 will un-do a boolean + you inline when the VALUE (not the branch) is what you need** — the control-flow sibling of + compute-don't-eyeball, and the fifth distinct mechanism in the named-locals family. + +### Worker B2 limited the coordinator's broadcast, one hour after it went out + +I broadcast "residual starts at a two-arm branch → invert the comparison and swap the arms" as a +guaranteed try-first. **B2 showed that is not always available.** On `0x800A9C24` the original's first +branch is `bne v1,zero,` with the `return -1` block inline as the fall-through; B2 measured +`if (a1 != 0) {...} return -1;` and the explicit-`else` form both giving the mirrored `beq v1,zero` at +96 differing bytes, and only `if (a1 != 0) goto body; return -1; body:` giving the original at 0. So the +rule is now two-step: **first invert and swap; if both ordinary spellings give the mirrored branch, the +guard must be a `goto`.** Fourth instance of the class for the team, and the first where the lever is the +*statement form* rather than the comparison. Corrected broadcast sent to A and C2. + +This is the third coordinator over-generalisation a worker has caught this phase (rare-epilogue class, +register-field diagnostic, now the polarity lever). The pattern is consistent: I generalise from a +verified instance, a worker tests it against a row where it fails, and the rule gains its limit. + +### A staging slip the candidate gate caught — and the rule it produces + +B2 reported claim 2 as `differing_bytes=0 MATCH`. My independent verification against the staged +`src/func_800A9C24.c` gave **96 differing bytes**. Scanning B2's variant directory found exactly one +match — `A3.c` — so the finding was right and the **staging** was wrong: B2 had built a fully documented +source (good header, observed instructions, frame arithmetic, limits) carrying the pre-`goto` spellings, +then explored variants, found the winning form in `A3.c`, and never folded it back into the documented +file before claiming. + +The tracked registry was never touched (the gate ran against `.run/p10/merge20/`), the row was dropped +from the batch, and it went back to B2 with the precise diagnosis. **New standing rule, now in every +charter: verify the file you are about to stage, at the path you are about to claim — not a scratch +variant. A variant is an experiment; `src/func_XXXXXXXX.c` is the claim.** This is the same class as +worker C's dropped row: the finding was right and the staging was not, and the merge flow caught both. + +### Dead-store elimination (worker B2, `0x80016F80`) + +Four measured facts, recorded as a class: two stores to the same address are DSE'd and cc1 deletes the +first store *and* its `andi` (144 B vs the correct 156) — and **a literal-address second store does not +defeat the DSE**; the ten zero stores must be `volatile` or the scheduler floats them (68 → 45 differing); +with both volatile the two `andi`s stay adjacent only if the masked values are bound to temporaries +before the stores; and the loop bound must stay **non**-volatile or its load moves after the zero stores +(160 B). + +### Coordinator process note + +The merge-19 commit message contained unescaped backticks, which the shell substituted away and left a +sentence incomplete — the lever's spelling vanished from the permanent record. Amended and force-pushed +with `--force-with-lease` (private repo, sole committer) rather than leave a wrong fact in the history, +and worker A was told the history moved by one commit ID. **Commit messages are now written to a file** +rather than inline, which removes the whole class of problem.