PE: close phase 3.39: RECAP, R123-R126, C0518-C0528, two skills

This commit is contained in:
Drew T
2026-10-02 23:15:20 -06:00
parent 7cbafd847b
commit b74b9cf86e
21 changed files with 209 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
---
name: d1-snapshot
description: D1 readability snapshot: census to newest P dir, snapshot, timeline, progress --readme
---
# D1 Snapshot
Captured 2026-10-02 from /home/musashi/bfm-decomp/.run/p339_close/skill_d1-snapshot.md.
## When to use
Recording a readability row (phase close, campaign batches)
## Steps
# d1-snapshot
## Steps
1. `PY tools/type_census.py -j 16 --out-dir .run/P<newest>/census` (mkdir -p first; not the cycle's P37).
2. `PY tools/readability_progress.py --snapshot "<label>"` (refuses a stale census).
3. `PY tools/timeline.py`, then `PY tools/progress.py --readme` (no --help: it runs and rewrites docs/progress.md).
4. Record `readability_progress --check` before the commit that records the row (STALE after it, by design).
5. Inside restruct cycles, a per-batch snapshot "refused (a stale census?)" is non-gating; the cycle continues.
Source: P3.39 tasks/T5.md:25, T11.md:23, T4.md:24, T12.md:22-23.
@@ -0,0 +1,21 @@
---
name: tools-edit-kit-corpus
description: After any tools/ edit: make kit-corpus, tool_dictionary row for new files, then make tools-health
---
# Tools Edit Kit Corpus
Captured 2026-10-02 from /home/musashi/bfm-decomp/.run/p339_close/skill_tools-edit-kit-corpus.md.
## When to use
Any edit under tools/ or a new harness tool
## Steps
# tools-edit-kit-corpus
## Steps
1. Edit the tool.
2. New file: add a `config/tool_dictionary.tsv` row.
3. `make kit-corpus` (refreshes the tracked copy under decomp-architect/corpus/tools/P10/).
4. `make tools-health` must say OK (`GAP corpus copy differs` = step 3 skipped).
5. Commit the tool and its corpus copy together; H7 line in docs/ops/ in the same task.
Source: P3.39 tasks/T1.md:35, T2.md:36, T9.md:28.
+2
View File
@@ -47,6 +47,8 @@ PY = /usr/bin/python3
- restruct-cycle-watch — Launch, find, wake on and stop a detached restruct_cycle.sh without racing inflight.json
- retire-doc-consumers — Grep and repoint tools, Makefile and docs that read a doc being retired, in the same task
- commit-task-autostage — Commit logs and research deliberately; force-add ignored tracked paths before commit_task.sh
- tools-edit-kit-corpus — After any tools/ edit: make kit-corpus, tool_dictionary row for new files, then make tools-health
- d1-snapshot — D1 readability snapshot: census to newest P dir, snapshot, timeline, progress --readme
## Paths <!-- roles: expert coder router planner review critic discuss auditor curator -->
- Oracles (the ground truth X3 names): <!-- TODO ORACLES: no source found -->
+8
View File
@@ -0,0 +1,8 @@
# C0518 — Freshness checks mask self-referential report cells
tags: reports,freshness,timeline,check · date: 2026-10-02 · phase/task: 39/T1 · origin: P3.39 T1 summary
# Freshness checks mask self-referential report cells
A generated report column such as "commits per date" moves with the report's own commit, so a byte-for-byte freshness check is red after every commit. Mask that cell on the newest row; compare everything else.
Source: P3.39 tasks/T1.md:34 (timeline.py --check).
+8
View File
@@ -0,0 +1,8 @@
# C0519 — Text censuses must exclude the registry's own #define lines by name
tags: census,macros,regex,gate · date: 2026-10-02 · phase/task: 39/T2 · origin: P3.39 T2 summary
# Text censuses must exclude the registry's own #define lines by name
A macro definition line that textually matches a site regex is counted as a site by a text census. A gate must drop the registry's own `#define` lines by macro name, not by file (other macros in that file still count).
Source: P3.39 tasks/T2.md:35 (type_census KEPT_MACROS).
+8
View File
@@ -0,0 +1,8 @@
# C0520 — Hash-named bbt types block a rung-S redraw; pin from ledger bases
tags: restruct,rung-S,structs,bbt · date: 2026-10-02 · phase/task: 39/T3 · origin: P3.39 T3 summary
# Hash-named bbt types block a rung-S redraw; pin from ledger bases
Hash-named types (Unkstruct_<8hex>) block a rung-S redraw. A scratch pin built from the ledger rows' `bases[].type` gets the sweep through.
Source: P3.39 tasks/T3.md:28 (T3.c6).
+8
View File
@@ -0,0 +1,8 @@
# C0521 — Later sweeps unback kept macros; match KEPT on a normalised base
tags: restruct,casts,kept,macros · date: 2026-10-02 · phase/task: 39/T3 · origin: P3.39 T3 summary
# Later sweeps unback kept macros; match KEPT on a normalised base
A later sweep batch that respells a nested base under an earlier kept macro silently unbacks it. Match carried KEPT entries on a normalised base: `*(T *)(X+k)` is the same site as `((S *)X)->unkK`.
Source: P3.39 tasks/T3.md:29.
+8
View File
@@ -0,0 +1,8 @@
# C0522 — Dead-kept canonical types go live when a sweep spells members
tags: structs,twins,check-structs · date: 2026-10-02 · phase/task: 39/T3 · origin: P3.39 T3 summary
# Dead-kept canonical types go live when a sweep spells members
A canonical type listed as dead-kept becomes live when a sweep spells members on it; `type_census --check-structs` then fails `twins_stale` until it leaves `## Dead kept`. Re-run struct_twins after such sweeps.
Source: P3.39 tasks/T3.md:30.
+8
View File
@@ -0,0 +1,8 @@
# C0523 — restruct --plan skips .h TUs unless --headers
tags: restruct,headers,globals,cycle · date: 2026-10-02 · phase/task: 39/T5 · origin: P3.39 T5 summary
# restruct --plan skips .h TUs unless --headers
`restruct --plan --rung S` skips `.h` TUs unless `--headers` is passed; global sites in headers need a HEADERS=1 cycle.
Source: P3.39 tasks/T5.md:24.
+8
View File
@@ -0,0 +1,8 @@
# C0524 — An 'unsigned' census class may mean 'cache never saw it'
tags: census,gte,inventory,planning · date: 2026-10-02 · phase/task: 39/T7.1 · origin: P3.39 T7.1 summary
# An 'unsigned' census class may mean 'cache never saw it'
A census's "unsigned" class can mean the tool's signature cache never saw the site, not a semantic class. Refresh the inventory before planning to respell such sites.
Source: P3.39 tasks/T7.1.md:27.
+8
View File
@@ -0,0 +1,8 @@
# C0525 — Give fleet-wide consolidation tools an explicit keep filter
tags: gte,gte_consolidate,ownership,fleet · date: 2026-10-02 · phase/task: 39/T7.1 · origin: P3.39 T7.1 summary
# Give fleet-wide consolidation tools an explicit keep filter
A consolidation tool that respells everything it can also respells sites another task owns. Give it an explicit keep filter before a fleet apply.
Source: P3.39 tasks/T7.1.md:28.
+8
View File
@@ -0,0 +1,8 @@
# C0526 — Read a gate's predicate before planning to zero its total
tags: census,planning,predicate,gate · date: 2026-10-02 · phase/task: 39/T7 · origin: P3.39 T7 summary
# Read a gate's predicate before planning to zero its total
A census that labels sites "via-macro" in its breakdown but counts them in a "direct" total makes a done-when written from the total unreachable. Read the predicate (retriever-code when the hook denies the source) before planning to zero it; P39 T7 was superseded by T7.1 for this.
Source: P3.39 tasks/T7.md:19.
+8
View File
@@ -0,0 +1,8 @@
# C0527 — Rung R recipes bank no-op brace wraps; filter '0 pin(s) gone'
tags: delever,rung-R,pins,recipes · date: 2026-10-02 · phase/task: 39/T8 · origin: P3.39 T8 summary
# Rung R recipes bank no-op brace wraps; filter '0 pin(s) gone'
Rung R recipes bank no-op brace wraps on bodies with no live sites. Filter banks reporting "0 pin(s) gone".
Source: P3.39 tasks/T8.md:25.
+8
View File
@@ -0,0 +1,8 @@
# C0528 — Residue coverage is per site; re-run after any respelling task
tags: residue,ledger,restruct,gate,casts · date: 2026-10-02 · phase/task: 39/T10 · origin: P3.39 T10 summary
# Residue coverage is per site; re-run after any respelling task
A coverage check keyed on "body has any ledger row" hides per-site gaps once later sweeps add rows for other reasons: match per site (form, normalised base, off). Merge new residue entries into the latest row rather than superseding it (a superseding row unbacks earlier KEPT entries). A per-site gate goes red again when a later task respells a covered body (new site keys): re-run `restruct --residue` per segment after any respelling task, before the milestone.
Source: P3.39 tasks/T10.md:37, T9.md:29.
+11
View File
@@ -967,3 +967,14 @@ C0514 | Run a repo-wide check on unedited HEAD first; mirrored edits need make k
C0515 | Global I/M casts to typed externs: R ladder and refusal causes | casts,globals,extern,restruct,recipes | 2026-10-02 | 39/T5 | P3.39 T5 summary
C0516 | Lying declarations: def + all callers; K&R-empty can be load-bearing | lying,decls,K&R,restruct,rung-D | 2026-10-02 | 39/T6 | P3.39 T6 summary
C0517 | GTE one spelling in gte_inline.h; clobber variants as header-level levers | gte,levers,delever,gte_consolidate | 2026-10-02 | 39/T7.1 | P3.39 T7.1/T8 summaries
C0518 | Freshness checks mask self-referential report cells | reports,freshness,timeline,check | 2026-10-02 | 39/T1 | P3.39 T1 summary
C0519 | Text censuses must exclude the registry's own #define lines by name | census,macros,regex,gate | 2026-10-02 | 39/T2 | P3.39 T2 summary
C0520 | Hash-named bbt types block a rung-S redraw; pin from ledger bases | restruct,rung-S,structs,bbt | 2026-10-02 | 39/T3 | P3.39 T3 summary
C0521 | Later sweeps unback kept macros; match KEPT on a normalised base | restruct,casts,kept,macros | 2026-10-02 | 39/T3 | P3.39 T3 summary
C0522 | Dead-kept canonical types go live when a sweep spells members | structs,twins,check-structs | 2026-10-02 | 39/T3 | P3.39 T3 summary
C0523 | restruct --plan skips .h TUs unless --headers | restruct,headers,globals,cycle | 2026-10-02 | 39/T5 | P3.39 T5 summary
C0524 | An 'unsigned' census class may mean 'cache never saw it' | census,gte,inventory,planning | 2026-10-02 | 39/T7.1 | P3.39 T7.1 summary
C0525 | Give fleet-wide consolidation tools an explicit keep filter | gte,gte_consolidate,ownership,fleet | 2026-10-02 | 39/T7.1 | P3.39 T7.1 summary
C0526 | Read a gate's predicate before planning to zero its total | census,planning,predicate,gate | 2026-10-02 | 39/T7 | P3.39 T7 summary
C0527 | Rung R recipes bank no-op brace wraps; filter '0 pin(s) gone' | delever,rung-R,pins,recipes | 2026-10-02 | 39/T8 | P3.39 T8 summary
C0528 | Residue coverage is per site; re-run after any respelling task | residue,ledger,restruct,gate,casts | 2026-10-02 | 39/T10 | P3.39 T10 summary
+30
View File
@@ -0,0 +1,30 @@
MILESTONE: green
## Recap
Phase 3.39 was the cast campaign: the decompiled C still read memory through raw pointer arithmetic such as `*(s16 *)(p + 0x10)`, and the goal was that every such "raw cast" either becomes a named struct member or global, or is kept on purpose with a written reason. Early on the sweep hit a wall: about 292,000 sites point into structs that have no single agreed definition yet, so the plan was changed (the "replan", reading A, 2026-10-02) to accept those sites as recorded residue, each one listed in the restruct ledger with its cause, and to leave giving those structs their canonical definitions to Phase 3.40. Under that reading the phase delivered: zero uncovered raw casts, every intentional cast spelled by one of five registered macros backed by a ledger row, lying function declarations cut from 229 to 11 (all ledgered), GTE (the PlayStation geometry coprocessor) instructions spelled one way through one header, and every remaining compiler-steering "lever" (pins and inline asm) listed in a lever residue file. All 218 game binaries still rebuild byte-identical. Raw cast counts fell from 503,016 to 336,219 overall.
Milestone verification, all at commit 78a8415257 from a clean source tree (only an unrelated discussion index line and an untracked agent file were dirty; gate outputs were restored after the run, not committed):
- `PY tools/type_census.py --check-casts --residue` exit 0: uncovered P=0 I=0 X=0 M=0, unbacked macros 0, lying 11 (ledgered 11) (.run/logs/p339_c1_casts.log).
- `PY tools/restruct.py --rung S --check-residue --only <seg>` exit 0 for `ov_*`, `md_*`, `main`, `src/shared/*`: uncovered 0 sites / 0 bodies each (.run/logs/p339_c2_resid.log).
- `PY tools/lever_census.py --check --strict --residue config/lever_residue.tsv` exit 0: residue 3528, residue-unused 0, direct GTE in bodies 0 (.run/logs/p339_c2_resid.log).
- `make clean && make extract-all JOBS=16 && make check-all JOBS=16` exit 0: `check-all: 218 passed, 0 failed of 218` (.run/logs/p339_c4_r22.log).
- `PY tools/phaseend_index.py verify` printed RED (0/1) (.run/logs/p339_close_verify.log): it parsed the whole multi-command `verified by` text as one clause and expected the check-all line in the first command's output. Its first command exited 0. Each clause was then run alone, and every one was green (above).
## Records
- T5's flagged commits: 3f547f1152 committed about 794k lines of `.run/P39/census` scratch to git, and 5201d28b19 untracked it again. History is unchanged (no rewrite). `restruct_cycle.sh:96` still stages `.run/P37/census` (tracked files only).
- Replan (reading A, REPLAN 2026-10-02): T4 hit the TYPE-NOT-CANONICAL wall and was left blocked. T10 added the per-site residue gate `--check-casts --residue`, and the milestone reads residue covered by a cause-named ledger row as closed. The literal lever `--strict` 0 also moves to 3.40 (reading A for levers, 2026-10-01).
- Critic's T7.1 ruling (2026-10-02): T7 was reopened as T7.1. Its done-when clauses are read the way lever_census's own docstring defines them ("direct" means not through a gte_inline.h macro; per-TU defs means those of kind gte), so T7's "direct GTE" total was not reachable as first written. T8's done-when gained the per-TU asm macro definitions (164, all ledgered).
- Two census dirs disagree by about 5 P sites (the gate's `.run/P37` has 257,470 and the series' `.run/P39` has 257,475). This was not investigated (T9, T11).
- H7 deviations: T2 changed `tools/type_census.py`, `tools/lever_census.py` and two `config/` ledgers without listing HOW_WE_WORK.md or docs/ops in its Files. T10 later added the "type_census casts" Tools row and T8 the lever-residue ops note. T11 changed `tools/progress.py` with no HOW_WE_WORK.md or docs/ops line.
- harness: `phaseend_index.py verify` does not split a Milestone `verified by` list joined by commas and "and". Its `--help` does not say how clauses are delimited.
## Decisions that still bind
- Kept casts and lying declarations stay only with a ledger row: rule R123 (rules_add).
- Raw cast residue is covered per site by a cause-named RESIDUAL row: rule R124.
- GTE asm in bodies is spelled only through include/gte_inline.h: rule R125.
- The lever gate is `--strict --residue config/lever_residue.tsv` until the literal 0 in 3.40, and asm-macro rows follow the T8 shape: rule R126.
- main's rung-S gate is the per-object oracle plus a clean R22, not gate_main.py (environment fact, already in docs/ops/gate-main-only-with-gate-main.md and the T4 ops note).
- `timeline.py --check` masks the newest row's Commits cell (environment fact, docs/ops/p39-t1-2026-10-01-restruct-stale-supersede-timeline-check.md).
- Next task needs: the 3.40 planner sizes the canonical-types campaign from residue_census (TYPE-NOT-CANONICAL 291,819 sites over about 13k map types, where the top 81 types cover half) and from config/lever_residue.tsv (2,433 rows, 3,528 sites, 70 tagged [3.40-agent]), which is the input for the literal `lever_census --check --strict` 0.
- Next task needs: the standing request (developer, 2026-10-02) for every phase close is to update the README graphs, story section 10 and retrospective section 7, and the wiki pages. The 3.40 planner gives it a task, as T12 did here.
- Promoted at this close: cookbook C0518-C0528, skills `tools-edit-kit-corpus` and `d1-snapshot`, rules R123-R126.
+8
View File
@@ -149,3 +149,11 @@ R120 | Issue reply drafts are never committed or mentioned in commit text | - |
R121 | Phases name the counts they move and publish them at close | - | active | developer 2026-09-30
R122 | Tier-2 struct twins are folded on evidence or listed with a cause | structs,census,twins | active | PhaseEnd_Phase3.38 binding (T5.1)
R123 | Kept casts and lying declarations stay only with a ledger row | casts,lying,ledger,macros | active | PhaseEnd_Phase3.39 binding
R124 | Raw cast residue is covered per site by a cause-named RESIDUAL row | casts,residue,ledger,restruct | active | PhaseEnd_Phase3.39 binding
R125 | GTE asm in bodies is spelled only through gte_inline.h | gte,asm,levers,headers | active | PhaseEnd_Phase3.39 binding
R126 | Lever residue is a ledger, gated by --strict --residue | levers,pins,asm,residue,ledger | active | PhaseEnd_Phase3.39 binding
+7
View File
@@ -0,0 +1,7 @@
# R123 — Kept casts and lying declarations stay only with a ledger row
id: R123 · group: - · status: active · tags: casts,lying,ledger,macros · origin: PhaseEnd_Phase3.39 binding · added: 2026-10-02
A kept cast is spelled only by a registered macro of include/common.h (CAST_WIDTH, CAST_SIGN, CAST_ALIAS, CAST_MISALIGNED, CAST_NONSTRUCT) and is honest only with its KEPT row in the restruct ledger. A lying declaration stays only with a config/lying_exceptions.tsv row whose cause is byte evidence from a real judgement (compile error or DIFFERS object), never untried. `type_census --check-casts` is the gate; `--check` stays the broader reading.
Why: P3.39 took lying decls 229 -> 11 and unbacked macros to 0; an unledgered exception is indistinguishable from unfinished work.
Evidence: phase-ends/phase-3.39 tasks/T2.md:20, T6.md:15.
+7
View File
@@ -0,0 +1,7 @@
# R124 — Raw cast residue is covered per site by a cause-named RESIDUAL row
id: R124 · group: - · status: active · tags: casts,residue,ledger,restruct · origin: PhaseEnd_Phase3.39 binding · added: 2026-10-02
A raw P/I/X/M site not respelled is covered only by the body's latest rung-S ledger row naming its cause, matched per site on (form, normalised base, off), never on line (`restruct.residue_match`). A `--residue` row for a body with an existing latest S row merges (keeps KEPT/MEMBER entries and verdict). TYPE-NOT-CANONICAL is residual for rung S; global I/M sites go through `--recipes --forms I,M` first and are residual only with the refusing recipe as cause (R2-*/R3-*).
Why: reading A of the P3.39 milestone (REPLAN 2026-10-02); the residue_census is the 3.40 canonical-types input.
Evidence: phase-ends/phase-3.39 tasks/T3.md:14, T5.md:13, T10.md:15-16.
+7
View File
@@ -0,0 +1,7 @@
# R125 — GTE asm in bodies is spelled only through gte_inline.h
id: R125 · group: - · status: active · tags: gte,asm,levers,headers · origin: PhaseEnd_Phase3.39 binding · added: 2026-10-02
GTE asm in a body is spelled only as a call of an include/gte_inline.h macro, except gte-lever statements on the lever ledger. New spellings enter the header through `gte_consolidate --inventory && --header`, never by hand; re-run gte_consolidate (--rejudge) after any delever pass.
Why: P3.39 brought direct GTE in bodies to 0.
Evidence: phase-ends/phase-3.39 tasks/T7.1.md:16, T8.md:24.
+7
View File
@@ -0,0 +1,7 @@
# R126 — Lever residue is a ledger, gated by --strict --residue
id: R126 · group: - · status: active · tags: levers,pins,asm,residue,ledger · origin: PhaseEnd_Phase3.39 binding · added: 2026-10-02
Until the literal `lever_census --check --strict` 0 (3.40), the lever gate is `--check --strict --residue config/lever_residue.tsv`: residue rows are excluded from failures and counted in every total; residue-unused must be 0. Per-TU asm macro definitions are ledgered as kind asm-macro rows, func = macro name, cause `asm-macro-def(<launder|instruction|barrier>)`; same-name defs in one TU share one row.
Why: reading A for levers (2026-10-01); 3,528 sites in 2,433 rows at the P3.39 close.
Evidence: phase-ends/phase-3.39 tasks/T2.md:21, T8.md:13.