diff --git a/.run/P34/c11/audit_cdecl_after_fix.log b/.run/P34/c11/audit_cdecl_after_fix.log new file mode 100644 index 000000000..94716a43d --- /dev/null +++ b/.run/P34/c11/audit_cdecl_after_fix.log @@ -0,0 +1,26 @@ +.venv/bin/python tools/cdecl.py --audit --gcc --limit 60 +[coverage] 60 TUs (cpp-derived) + 600 drafts (raw) +[coverage] depth-0 statements: 175222 declarators parsed: 166814 +[coverage] unparsed: 4 -> PARSER DEFECTS (gcc accepts, cdecl does not): 0 NOT-C (gcc rejects it too — corrupt input): 4 + NOT-C in 1 dir(s) (all scratch, none in src/): ['.run/drafts-T6-recanon'] + e.g. 'extern if ((func_80029178(0x119) & 0xFF) != 0);' -> expected ')', got '!=' in 'extern if ((func_800 + +[differential] expanded 5147 DEFINE_ macros through cpp -> 7430 names +[differential] engine_core.h — D_ symbols (raw-text scan vs cpp-expanded file scope) + incumbent theirs cdecl cdecl-only MY DEFECT their block-scope error + gen_harvest_targets.DATA_DECL_RE 2238 2319 601 0 520 + they count BLOCK-scope externs as file-scope canonicals: ['D_800636C8', 'D_80078EAF', 'D_800A5E8C', 'D_800A5E90'] + sig_unify.DATA_DECL_RE 2238 2319 601 0 520 + they count BLOCK-scope externs as file-scope canonicals: ['D_800636C8', 'D_80078EAF', 'D_800A5E8C', 'D_800A5E90'] + the audit's named blind symbols (engine_core.h), now resolved WITH THEIR KIND: + D_80127530 kind=array (expected array) [ok] s32 [4] + D_80127088 kind=fnptr (expected fnptr) [ok] void (*)(void) + D_8011DB28 kind=fnptr (expected fnptr) [ok] void (*)(s32) + D_801274D0 kind=fnptr (expected fnptr) [ok] s32 (*)(s32) + D_8018E858 kind=fnptr_array (expected fnptr_array) [ok] void (*[])(void) + +[gcc] 4777 distinct declarations -> the real cross-compiler +[gcc] adjudicated: 4777 env-skipped (gcc cannot compile the original out of its TU): 0 +[gcc] accepted: 4777 REJECTED (my reconstruction is a DIFFERENT TYPE): 0 + +cdecl: ALL ORACLES GREEN diff --git a/decomp-architect/corpus/record/docs/accelerators.md b/decomp-architect/corpus/record/docs/accelerators.md index dd20dd6c4..e34800120 100644 --- a/decomp-architect/corpus/record/docs/accelerators.md +++ b/decomp-architect/corpus/record/docs/accelerators.md @@ -892,3 +892,17 @@ lessons that were fixed but never generalised; on this project one in five candi ~4.3M tokens, ~13 min wall each in two batches; the coordinator's cost was the brief, the harvest script, the clustering and the provenance generation. +## P34 S93 (2026-09-08) — the flip day: a third-party step proven through the third party's toolchain, and the public-tree decisions + +The one failure of the flip day was a browser step nobody could have exercised while the repository was private: `docs/decompme-preset.md` +told the owner to paste the regenerated target listing into decomp.me, and decomp.me's assembler refused it (`invalid operands 'li a2,2'`). +The listing is the project's word oracle — nothing on our side assembles it; its bare register names resolve only through `macro.inc` and +its branch targets are absolute addresses — and the replica that had "proven the preset" compared words from the listing's comments, +never the listing itself. **Accelerator: a step that hands a file to a third party is proven through that party's own toolchain, on the +file itself, before the owner's browser session — and the tool that proves it writes the paste** (`verbatim_target_s.py --gas`; +`decompme_replica.sh` steps D and E; the retry matched 100% first time). Two smaller ones from the same day. **A calendar gate is read +the morning after the ticket, not "daily for a week":** the Support purge took one day; the probe passed during the previous sub-phase and +the flip could have opened a day earlier. **Decide what a public tree carries before the flip:** the sent outreach drafts and the +document archive were always going to leave (the owner removed both within hours of going public), and deciding at the consolidation +sub-phase would have spared two untrack commits on a public history; the Archive-index rule that made the removal harmless — name +archived files as paths, never links — held. diff --git a/decomp-architect/corpus/record/docs/decision-log.md b/decomp-architect/corpus/record/docs/decision-log.md index 8c883fb82..b05b45a2e 100644 --- a/decomp-architect/corpus/record/docs/decision-log.md +++ b/decomp-architect/corpus/record/docs/decision-log.md @@ -3645,3 +3645,41 @@ register lever (accelerators (16)), and treat "PROVED" as "proved against this l above any mid-campaign harvest's. Both are now the kit's own rules: the coverage check is in the kit's health target, and the record's front page tells the next project that its logs deserve one final read. +## P34 S93 (2026-09-08) — the flip: a calendar gate that opened early, and what a public tree carries + +- **Context and belief.** Phase 33 closed re-chartered because the flip waited on GitHub Support purging the old objects (the Activity + view served every pre-force-push tip). The seed planned a daily probe "until PASS, ~a week", with a delete-and-recreate fallback. The + probe passed on 2026-09-07, during Phase 33.5 — the purge took a day, not a week — so Phase 34 opened with its gate already open and the + fallback never needed. Gate 1 (plan mode, Max) ratified the twelve Phase-33.5 candidates as R84–R95 and added three things the seed did + not have: repository metadata and a `protect-main` ruleset (no force-push, no deletion, no bypass actors) set by Claude on the owner's + word, a GitHub Release for v2.0.0, and the finding that a Phase-1 relic clone of the OLD history still existed on the Windows + filesystem — deleted by Drew during planning, so C11's clone-reset step became "not applicable, with evidence". +- **What failed, once.** The decomp.me browser step failed on its first try: the doc told Drew to paste the regenerated target listing, + which is the project's WORD ORACLE (nothing on our side assembles it — bare register names that resolve only through `macro.inc`, + branch targets as absolute addresses). decomp.me's assembler refused it (`invalid operands 'li a2,2'`). The step had been written for a + private repo and never exercised (R14). The fix went into the tools, not the doc alone: `verbatim_target_s.py --gas` (the assemblable + form), the replica's step D (the paste itself through decomp.me's own `as` wrapper, 26/26 words) and step E (the bundle written from + the proven run); the retry matched 100% first time. Lesson, the same as P33's: a step that talks to a third party is proven through + that party's own toolchain before the owner sits down in the browser. +- **The outward day.** Public at 11:2x MDT; the after-flip probe 33/33 gone; both workflows green on the public repo; decomp.dev + registered (100.00% / 100.00%, hero image); the wiki pushed (32 pages; Claude ran the push on Drew's explicit one-off R6 waiver, the + P33 xsig precedent); the preset request (decompme/decomp.me#2106); the Archipelago note (AegeusEvander/…#1); xsig topics + homepage; + the tools post and Drew's own `#ai` reply in the decomp.me Discord; two Decompedia rows. frogress skipped on measurement: alive, 38 + projects, admin-created, and at 100% with generated badges and decomp.dev live it would add a list row only — pending by name. +- **Two owner decisions about the public tree (the pivot in this entry).** After the notes were sent, Drew took `docs/outreach/` out of + the tree ("just gitignore"), and then the document archive `docs/sunset/` ("remove sunset from the pushed repo … keep the old tools in + the sunset folder for the index, but not the other stuff"). The 33.5 design had anticipated exactly this: nothing ever linked into the + archive, the Archive index names each file as a path, so the removal broke no link — but the folder was still cited as PRESENT in four + wiki pages, and a trial "untrack both" pass measured that the tool census `--check` needs the retired files (a fresh clone would have + gone red), which is why the tools half stayed. Convention going forward (on the conventions page): a retired document gets its + Archive-index row and is deleted in the same commit; history keeps it. No rewrite for either — the drafts and the archive are in the + published history and contain nothing ROM-derived. +- **Scratch.** The untracked `.run/` campaign scratch that the frontier's emptying made worthless — per-function draft trees, permuter + work dirs, wave shards, resolver and rtu shadow trees, the P29/P32 crack scratch — was pruned after sampling each tree (≈9 GB; disk + 46 → 37 GB used); `.run/public_rewrite/` kept only the probe's two inputs (1.1 GB → 352 KB) so the probe stays runnable; every + tracked `.run` file (952) and the keep-set (`obj40`, the sigs, `decompme`, `wiki`, `verbatim_targets`, `ghidra_export`) untouched. +- **Hindsight — the better path.** (1) Exercise every third-party step through that party's own toolchain before the owner's browser + session, and let the tool write the paste (done now for decomp.me; the same rule would have caught it in P33). (2) Decide what a + public tree carries BEFORE the flip, not after: the outreach drafts and the archive were always going to leave; deciding at 33.5 would + have spared two untrack commits on a public history. (3) A "daily probe for a week" should start the day the ticket is filed and be + read the next morning — it passed in one day and the phase could have opened a day earlier. diff --git a/decomp-architect/corpus/record/phase-ends/DIGEST.md b/decomp-architect/corpus/record/phase-ends/DIGEST.md index fdc61cf34..5a1e5d565 100644 --- a/decomp-architect/corpus/record/phase-ends/DIGEST.md +++ b/decomp-architect/corpus/record/phase-ends/DIGEST.md @@ -19,8 +19,9 @@ database regenerable from `config/ghidra/`). The whole history was rewritten wit no license asserted over `src/`, NOTICE, THIRD_PARTY, badges, ROM-free CI), the releases (gcc-2.7.2 map, xsig, the permuter driver — offered upstream and declined, the drafter write-up, the decomp.me preset proven through decomp.me's own toolchain), the outreach notes, story, retrospective, wiki (13 pages) + how-to (13 chapters), and the **Gen3 charter** (`docs/gen3-handoff.md`, `docs/gen3-standards.md`) -are written. **The repository is still PRIVATE:** GitHub Support must purge the old objects first (ticket #4736982; the Activity view -publishes every pre-force-push tip, so a clean tree is not enough). **Phase 33.5 CLOSED 2026-09-08 (v1.32.1; `PhaseEnd_Phase33.5.md`):** the docs sub-phase before the flip — the wiki is the single +are written. **The repository went PUBLIC on 2026-09-08 (Phase 34 task 1, Drew)** after the purge probe passed twice — 2026-09-07 and +again immediately before the flip (33 of 33 sampled old hashes gone; Support ticket #4736982 had done its work) — with the `protect-main` +ruleset (no force-push, no deletion) guarding the published history. **Phase 33.5 CLOSED 2026-09-08 (v1.32.1; `PhaseEnd_Phase33.5.md`):** the docs sub-phase before the flip — the wiki is the single source of truth (six new pages incl. the Reference index and the Archive index; 59 documents and 34 tools retired into indexed sunset folders; `doc_links` with six checks), the tracked `.run/` is flip-ready (1,086 → 868 + the phase's own evidence; the two ROM listings untracked under an audit-only rule + a content check), the memory store reconciled (80 == 80; an 18-file seed), and **the day-one decomp @@ -30,8 +31,9 @@ kit-corpus`, asserted equal in tools-health), `tools/kit_coverage.py` (every rul its first run found 26 + 21 uncited, three genuine gaps), and the worklog mining pass (777 candidates / 634 banked / 143 new → DK-69–80). R74–R83 ratified at its gate 1; candidates (i)–(xii) proposed for Phase 34 gate 1. **Phase 34's gate is OPEN: the purge probe PASSED 2026-09-07.** **Phase 34 = the flip + the outward actions + C11 + the v2.0.0 PhaseEnd = Gen2 EXIT** (`docs/phase34-seed.md`). -**Phase 34 OPENED 2026-09-08 (S93; gate 1 in plan mode at Max; R84–R95 ratified; the plan and the live state are in -`phase-ends/CURRENT_PHASE.md`).** **Gen3 opens at Phase 35** — its seed now includes the S91-b types doctrine (R95, the canonical +**Phase 34 IN PROGRESS (opened 2026-09-08, S93; gate 1 in plan mode at Max; R84–R95 ratified; the plan and the live state are in +`phase-ends/CURRENT_PHASE.md`): the flip done, decomp.dev live, the wiki live (32 pages), the decomp.me preset requested, the +Archipelago note sent, the tools announced; `docs/outreach/` and `docs/sunset/` left the tree on the owner's decision.** **Gen3 opens at Phase 35** — its seed now includes the S91-b types doctrine (R95, the canonical type layer). ## 1. Corrections and supersessions of PROJECT_CONTEXT.md recorded in PhaseEnds (P1: the constitution is never edited) @@ -42,7 +44,7 @@ type layer). backups → today: **one commit per completed task after CURRENT_PHASE.md is updated; a bank commits the moment it exists (R42)**. Claude commits; **Drew pushes** (R6); the PhaseEnd + archived log are left uncommitted for Drew's milestone-close commit; no `Co-Authored-By` (R5). -- **H1** was relaxed while private (R1, 2026-06-10 → 2026-09-06) and is **IN FORCE again since Phase 33 C3 (2026-09-06)**: the ROM-derived and proprietary paths left the index and were purged from the whole history before the public flip (`docs/public-flip-runbook.md`); R1 is historical. **R20's backup home** is now the text export `config/ghidra/` (+ `tools/ghidra_rebuild.sh --proof`), `dumps/CHECKSUMS.sha1`, `tools/psyq_CHECKSUMS.sha256`, and the private archive repo `Druthulu/BFM-decomp-archive` (the pre-rewrite history); **never `git clean -x`** (CLAUDE.md fail-safe). +- **H1** was relaxed while private (R1, 2026-06-10 → 2026-09-06) and is **IN FORCE again since Phase 33 C3 (2026-09-06)**: the ROM-derived and proprietary paths left the index and were purged from the whole history before the public flip (`docs/public-flip-runbook.md`); R1 is historical. **The flip itself happened on 2026-09-08 (Phase 34 task 1).** **R20's backup home** is now the text export `config/ghidra/` (+ `tools/ghidra_rebuild.sh --proof`), `dumps/CHECKSUMS.sha1`, `tools/psyq_CHECKSUMS.sha256`, and the private archive repo `Druthulu/BFM-decomp-archive` (the pre-rewrite history); **never `git clean -x`** (CLAUDE.md fail-safe). - **Environment:** all-in-WSL (R2); Ghidra runs **headless** (MCP server via `tools/ghidra_mcp_start.sh` / the SessionStart hook; symbols persist only via `tools/ghidra_apply_symbols.sh`, MCP renames do not); PCSX-Redux is Windows-native bridged over the web API (R11); no `/tmp`, scratch under `.run/` (R12). @@ -355,8 +357,8 @@ the binding text. R44–R63 one-liners are the P31 table, ratified at P32 gate 1 ## 4. Where things live (the doc map a session needs) **The wiki is the source of truth for documentation (Phase 33.5):** `docs/wiki/Reference-index.md` lists every live reference and generated file with how to read it — start there; `docs/wiki/Docs-and-scratch-conventions.md` says where each kind of knowledge goes; -`docs/wiki/The-ROM-firewall.md` is the no-ROM policy; `docs/wiki/Archive-index.md` records every document retired to `docs/sunset/` -(kept for the owner's review; nothing links into it). The files a session touches most: `docs/SETUP.md` (environment, every tool's +`docs/wiki/The-ROM-firewall.md` is the no-ROM policy; `docs/wiki/Archive-index.md` records every document retired at Phase 33.5 +(the archive folder itself left the tree at Phase 34, 2026-09-08 — the rows are the record; nothing ever linked into it). The files a session touches most: `docs/SETUP.md` (environment, every tool's row, commands) · `docs/matching-cookbook.md` §1–§500 (idioms; 3.5 MB — grep by §, never read whole) + `docs/cookbook-index.md` (symptom-keyed, derived, 566 KB — grep) · `docs/gcc-2.7.2-map/` (the compiler map) · `docs/wave-playbook.md` (THE wave procedure; the OpenRouter-era `automation-runbook.md` is archived) · `docs/effort-map.md` · `docs/phase34-seed.md` (the next phase's seed; diff --git a/decomp-architect/corpus/tools/P6/cdecl.py b/decomp-architect/corpus/tools/P6/cdecl.py index 32f7e7944..2a615f64f 100644 --- a/decomp-architect/corpus/tools/P6/cdecl.py +++ b/decomp-architect/corpus/tools/P6/cdecl.py @@ -1004,15 +1004,19 @@ def audit_coverage(limit=None, verbose=False): defects, notc = [], [] for p, e in bad: stmt = e.split(' -> ')[0].strip("'\"") + # The scratch dir is created here (P34 S93): it lived under .run/audit/, which a scratch prune removed, and the + # write raised — the bare `except` below then counted every unparsed line as a parser DEFECT (the last close had + # read the same four lines as NOT-C). An adjudication that cannot run is a REFUSAL, never a verdict (R43/R57). + src = os.path.join(REPO, '.run/audit/cdecl/adj.c') + os.makedirs(os.path.dirname(src), exist_ok=True) try: - src = os.path.join(REPO, '.run/audit/cdecl/adj.c') open(src, 'w').write(_PROBE_HDR + stmt.encode().decode('unicode_escape') + '\n') r = subprocess.run([CC, '-fsyntax-only', '-w', '-I' + os.path.join(REPO, 'include'), '-I' + os.path.join(REPO, 'src'), src], capture_output=True, text=True, cwd=REPO) - (notc if r.returncode else defects).append((p, e)) - except Exception: - defects.append((p, e)) + except Exception as ex: + sys.exit(f'cdecl --audit: cannot adjudicate an unparsed statement with gcc ({ex}); refusing to grade it either way (R43)') + (notc if r.returncode else defects).append((p, e)) print(f'[coverage] {len(tus)} TUs (cpp-derived) + {len(drafts)} drafts (raw)') print(f'[coverage] depth-0 statements: {stmts} declarators parsed: {decls}') diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index 6cf4db836..db929593d 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -242,7 +242,22 @@ output) · `.run/P34/c11/` (the prune listing with sizes, `git worktree list`, t `master` = `be8a6cc`, the live Archive-index page (200) carries "removed from the tree at Phase 34" (`.run/P34/outward/wiki_push_c11.log`). `gh auth logout` stays Drew's last command after the close push. **Task 7 CLOSED.** -## 🛑 SESSION CHECKPOINT — PHASE 34 OPEN (S93, 2026-09-08): tasks 0a, 0–7 ✓; task 8 IN PROGRESS (Tier 1, Max confirmed by Drew "ready for task 8"): the close tools-health ran and FAILED at audit-cdecl — under diagnosis (R40: the instrument first); then the P7 walk, gate 2, the PhaseEnd v2.0.0 +### 2026-09-08 — Task 8 (part 1) — the close health chain: one instrument defect, exposed by the prune and fixed (Max; S93) +- The first `make tools-health` of the close (`.run/P34/tools_health_close.log`, 3,416 lines) went **red at `audit-cdecl`**: "PARSER + DEFECTS (gcc accepts, cdecl does not): 4", all four the same non-C line `extern if (...)` in `.run/drafts-T6-recanon/` drafts. At the + 33.5 close the SAME four lines were "NOT-C (gcc rejects it too): 4 → ALL ORACLES GREEN" on an unchanged sample (the sorted glob of + `.run/drafts*/*.c`; no draft dir was pruned). **Root cause (R40 → the instrument, R57 → its write path):** the gcc adjudication writes + its probe to `.run/audit/cdecl/adj.c`; task 7's prune removed `.run/audit/`; the write raised; the bare `except Exception` counted every + unparsed line as a DEFECT. A refusal reported as a verdict. +- **Fix (`tools/cdecl.py`):** `os.makedirs` for the scratch dir (the other two `.run/audit/cdecl` users already had it); an adjudication + that cannot run now `sys.exit`s with a refusal (R43) instead of grading either way. `make audit-cdecl` alone → **unparsed 4 → DEFECTS 0, + NOT-C 4 (`.run/drafts-T6-recanon`), gcc accepted 4,777 / REJECTED 0, "cdecl: ALL ORACLES GREEN"** (`.run/P34/c11/audit_cdecl_after_fix.log`). + `make kit-corpus` regenerated (cdecl.py is in the corpus); `tool_census --check` OK. The full chain relaunched detached (its log + overwrites the red one; the red run's verdict is quoted here). +- Lesson for the ledger: a scratch prune is an instrument change — every tool that writes under a pruned tree must be re-run before the + prune is called done (a candidate rule for the PhaseEnd). + +## 🛑 SESSION CHECKPOINT — PHASE 34 OPEN (S93, 2026-09-08): tasks 0a, 0–7 ✓; task 8 IN PROGRESS (Tier 1, Max): the cdecl instrument fixed, the full tools-health re-running detached (`.run/P34/tools_health_close.log`); then the P7 walk, gate 2, the PhaseEnd v2.0.0 ### 0. How to use this block A fresh session reads CLAUDE.md's load order, replays THIS block verbatim, and resumes at the first unchecked task above. Everything diff --git a/tools/cdecl.py b/tools/cdecl.py index 32f7e7944..2a615f64f 100644 --- a/tools/cdecl.py +++ b/tools/cdecl.py @@ -1004,15 +1004,19 @@ def audit_coverage(limit=None, verbose=False): defects, notc = [], [] for p, e in bad: stmt = e.split(' -> ')[0].strip("'\"") + # The scratch dir is created here (P34 S93): it lived under .run/audit/, which a scratch prune removed, and the + # write raised — the bare `except` below then counted every unparsed line as a parser DEFECT (the last close had + # read the same four lines as NOT-C). An adjudication that cannot run is a REFUSAL, never a verdict (R43/R57). + src = os.path.join(REPO, '.run/audit/cdecl/adj.c') + os.makedirs(os.path.dirname(src), exist_ok=True) try: - src = os.path.join(REPO, '.run/audit/cdecl/adj.c') open(src, 'w').write(_PROBE_HDR + stmt.encode().decode('unicode_escape') + '\n') r = subprocess.run([CC, '-fsyntax-only', '-w', '-I' + os.path.join(REPO, 'include'), '-I' + os.path.join(REPO, 'src'), src], capture_output=True, text=True, cwd=REPO) - (notc if r.returncode else defects).append((p, e)) - except Exception: - defects.append((p, e)) + except Exception as ex: + sys.exit(f'cdecl --audit: cannot adjudicate an unparsed statement with gcc ({ex}); refusing to grade it either way (R43)') + (notc if r.returncode else defects).append((p, e)) print(f'[coverage] {len(tus)} TUs (cpp-derived) + {len(drafts)} drafts (raw)') print(f'[coverage] depth-0 statements: {stmts} declarators parsed: {decls}')