phase8: record cycles 1-2 and the two harness mechanisms
Control record updated with both verified cycles, the two per-region overrides that came out of worker findings (maspsx=off and gp=-NAME, with the byte evidence for each of the six anomaly-class regions), and the coordinator findings: the stale worklist caught before dispatch, the candidate-first merge that contained a bad cycle, Ghidra's COP2 pseudo-op collapsing, and the two $gp thunk halves. Also excludes 0x80108034 and 0x8010804C from the worklist: they are the two halves of a $gp-switch thunk and are not matchable as C regions. Milestone met at 109 distinct bodies (target 70).
This commit is contained in:
@@ -122,7 +122,8 @@ worklist: validate
|
||||
@test -f "$(DUPES)"
|
||||
@"$(TRIAGE_TOOL)" plan --exe "$(EXE)" --extents "$(EXTENTS)" --inventory "$(INVENTORY)" \
|
||||
--census "$(DUPES)" --regions "$(REGIONS)" \
|
||||
--exclude 0x8005DEF8 --exclude 0x800F3160 --out "$(WORKLIST)" --force
|
||||
--exclude 0x8005DEF8 --exclude 0x800F3160 \
|
||||
--exclude 0x80108034 --exclude 0x8010804C --out "$(WORKLIST)" --force
|
||||
|
||||
# Verification gates. `test` is synthetic-only and needs no game input;
|
||||
# `check` adds the extents check and the full-binary byte gate (which do).
|
||||
|
||||
+1817
-1893
File diff suppressed because it is too large
Load Diff
@@ -12,12 +12,12 @@ matched bodies** (from 34), every one verified by the coordinator's own gate.
|
||||
|
||||
## Progress
|
||||
|
||||
- [ ] **P8-T1 — Control records, baseline revalidation, and the intercom handshake** (in progress)
|
||||
- [ ] **P8-T2 — Claim-merge tooling and the protocol record**
|
||||
- [ ] **P8-T3 — Dispatch both charters and verify cycle 1**
|
||||
- [ ] **P8-T4 — Verification cycle 2 with re-partitioning**
|
||||
- [x] **P8-T1 — Control records, baseline revalidation, and the intercom handshake** (complete)
|
||||
- [x] **P8-T2 — Claim-merge tooling and the protocol record** (complete)
|
||||
- [x] **P8-T3 — Dispatch both charters and verify cycle 1** (complete: 18 claims verified, 57 regions)
|
||||
- [x] **P8-T4 — Verification cycle 2 with re-partitioning** (complete: 58 claims verified, 115 regions / 109 bodies — milestone met)
|
||||
- [ ] **Rules check**
|
||||
- [ ] **P8-T5 — The SDK-shape investigation, bounded**
|
||||
- [ ] **P8-T5 — The SDK-shape investigation, bounded** (worker C, in progress)
|
||||
- [ ] **P8-T6 — Verification cycle 3 and consolidation**
|
||||
- [ ] **P8-T7 — Cookbook, conventions, protocol record, and phase gate**
|
||||
|
||||
@@ -85,6 +85,99 @@ they need, and the hard rules.
|
||||
Worker B's charter was corrected immediately after the stale-worklist catch, because it quoted the old
|
||||
partition bounds; the correction is recorded rather than quietly resent.
|
||||
|
||||
## P8-T2 — Claim-merge tooling and the protocol record (2026-09-23)
|
||||
|
||||
**Delivered:**
|
||||
|
||||
- `tools/sf3_merge` (28 synthetic tests): merges worker claim files into the tracked registries,
|
||||
accepting a claim only if its extent exists in the derived extents table and is graded `exact` with
|
||||
exactly the claimed end, its source is a repo-relative `src/func_XXXXXXXX.c` that exists, and it
|
||||
overlaps neither the registry nor another worker's claim. Rejections are reported with reasons and
|
||||
nothing is written. `--skip-registered` treats an exact re-claim as a no-op, because a worker's claims
|
||||
file is naturally cumulative.
|
||||
- `docs/PHASE8_PROTOCOL.md` — roles, addressing, the hard rules, message types, staging formats, the
|
||||
partition command, the merge workflow and the per-cycle verification table.
|
||||
|
||||
**Refinement to the plan:** the plan said "merge, then gate". The tool takes an explicit destination, so
|
||||
in practice the coordinator merges to a **candidate** registry, gates the candidate, and promotes only on
|
||||
`MATCH`. The tracked registry therefore never contains an unverified claim — which is exactly what saved
|
||||
this phase's first cycle (see below).
|
||||
|
||||
## P8-T3 — Cycle 1 verified (2026-09-23)
|
||||
|
||||
| Worker | Claims | Result |
|
||||
|---|---|---|
|
||||
| A (`01a0d143`) | 10 (target 8) | `sf3_merge` 10/10 accepted; candidate gate `c_regions=49`, 0 differing, `MATCH`; promoted; `make check` green |
|
||||
| B (`01a0d145`) | 8 (7 bodies; `g0029` is a two-address group) | 8/8 accepted; candidate gate `c_regions=57`, 0 differing, `MATCH`; promoted; `make check` green |
|
||||
|
||||
Worker A also requested 9 `gp`-marked rows instead of editing the shared registry — the protocol working
|
||||
as designed. Worker B classified its whole 946-row partition and found 226 rows (24%) needing `gp`
|
||||
accesses, staging 335 distinct addresses. Those were verified before use: 335/335 arithmetically exact,
|
||||
four sampled against my own Ghidra disassembly, and a risk check for whether a new marker could change an
|
||||
already-matched region (it could only touch worker A's unclaimed files).
|
||||
|
||||
## P8-T4 — Cycle 2 verified, and the milestone (2026-09-23)
|
||||
|
||||
66 claims from A (28), B (32) and the coordinator (6 anomaly-class regions): **58 accepted, 8 skipped as
|
||||
already registered, 0 rejected.** Candidate gate `c_regions=115`, 0 differing bytes, SHA-1
|
||||
`e173426c157384ebf1b6caf8c6fea18a85a14af9`; promoted; `make check` green (199 tests,
|
||||
`regions=115 disagreements=0`).
|
||||
|
||||
**Distinct matched bodies: 34 → 51 → 109. The phase milestone of 70 is met.**
|
||||
|
||||
The first attempt at this merge **failed the candidate gate** (`differing_bytes=1117442`, rebuilt 4 bytes
|
||||
short). Because the merge had gone to a candidate, the tracked registry was never touched. Diagnosis:
|
||||
per-claim `range` runs against the candidate symbols isolated it to one region, `0x8002D288`, and the
|
||||
cause was a genuine model limit rather than a bad claim — see the gp-site finding below.
|
||||
|
||||
## Harness mechanisms added mid-phase
|
||||
|
||||
Both were found by workers and implemented by the coordinator; both are per-region overrides in the
|
||||
region registry's fourth field, and both are synthetic-tested.
|
||||
|
||||
### `maspsx=off` — the assembler-anomaly class
|
||||
|
||||
Worker A isolated the `$at`-macro-store-in-the-`jr`-delay-slot shape with a decisive experiment: cc1
|
||||
emits an empty delay slot, **maspsx fills it with a `nop`**, and GNU `as` in reorder mode fills it
|
||||
correctly by moving the last half of the expanded store. Worker B reverse-engineered the same mechanism
|
||||
independently from cc1's output.
|
||||
|
||||
| Address | Size | maspsx on | maspsx off |
|
||||
|---|---|---|---|
|
||||
| `0x80102B10` | 28 | 32, `LENGTH-MISMATCH` | **28, 0 differing** |
|
||||
| `0x800F8B6C` | 20 | 24, `LENGTH-MISMATCH` | **20, 0 differing** |
|
||||
| `0x800F8B58` | 20 | 24, `LENGTH-MISMATCH` | **20, 0 differing** |
|
||||
| `0x800F8FE4` | 20 | 24, `LENGTH-MISMATCH` | **20, 0 differing** |
|
||||
| `0x800F8AEC` | 12 | 16, `LENGTH-MISMATCH` | **12, 0 differing** |
|
||||
| `0x800F3160` | 12 | 16, `LENGTH-MISMATCH` | **12, 0 differing** |
|
||||
|
||||
`0x800F3160` was Phase 5's first recorded bounded negative — "no tested compiler + assembler pair
|
||||
reproduces its store-in-delay-slot scheduling" — and stood unresolved for three phases. It is now a
|
||||
registered match, as are the other five.
|
||||
|
||||
### `gp=-NAME` — the access form is per site, not per symbol
|
||||
|
||||
The gp marker is per symbol, but this executable accesses one address both ways:
|
||||
|
||||
- `0x80121F84` is read **gp-relative** at `0x800A80BC`–`0x800A8208` (six accesses at `d=0x64c`, found by
|
||||
scanning the payload), so worker B's census row is correct;
|
||||
- and written **absolutely** at `0x8002D288` (`lui at,0x8012` / `sw zero,0x1f84(at)`), so worker A's
|
||||
source is correct too.
|
||||
|
||||
The marker rewrote A's absolute store into a gp-relative one — 2 instructions instead of 1 — and the
|
||||
region came out 4 bytes short. `gp=-D_80121F84` on that one region row expresses both forms. **This makes
|
||||
cookbook finding 10 incomplete**: it says the choice is the object's size/section, but here it is the
|
||||
site.
|
||||
|
||||
## Coordinator findings
|
||||
|
||||
| Finding | Evidence |
|
||||
|---|---|
|
||||
| The tracked worklist was **stale** before dispatch | Generated in P7-T4 with 12 regions registered; still listed 23 candidates matched later in Phase 7. Regenerated (1,893 listed, 39 excluded as already registered), re-partitioned, and worker B's charter corrected. |
|
||||
| The candidate-first merge caught a bad cycle | The first cycle-2 candidate failed the gate (`differing_bytes=1117442`); the tracked registry was untouched, and per-claim `range` runs isolated the single culprit in minutes. |
|
||||
| Ghidra's PSX loader **collapses COP2 sequences** into one pseudo-op | Worker A found `0x8001AE3C` rendered as a single `ldbkdir a0,a1,a2`, so Ghidra's instruction count can be *lower* than reality. Never use it as a size; the extent table is authoritative. |
|
||||
| Two `$gp`-switch thunk halves are not C regions | `0x80108034`, `0x8010804C` (worker B). Added to the worklist's named exclusions. |
|
||||
|
||||
## Notes and limits
|
||||
|
||||
- Three sessions share one worktree. The safety property is that a worker's claim is never trusted: the
|
||||
|
||||
Reference in New Issue
Block a user