Skip to content

M6 design amendment 3g: marital projection domain law for sub-15-at-anchor persons (§2.8.2 pin correction, closes reg-5 crash) - #209

Merged
MaxGhenis merged 7 commits into
masterfrom
m6-amendment-3g
Jul 15, 2026
Merged

M6 design amendment 3g: marital projection domain law for sub-15-at-anchor persons (§2.8.2 pin correction, closes reg-5 crash)#209
MaxGhenis merged 7 commits into
masterfrom
m6-amendment-3g

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

M6 design amendment 3g — the marital projection domain law for sub-START_AGE-at-anchor persons

Docs-only design amendment (revision 13) adding §2.8.2g and correcting the §2.8.2 universe pin and the §2.8.9 "residual open decisions: none" claim. Closes the fifth-registration execution failure (gate_m6 candidate 1): ValueError: certified marital panel has no entry row at anchor. No code in this PR — the implementing patch is pinned in §2.8.2g and lands after ratification, as amendments 3d/3e did. No gates.yaml/runs/ contact.

Evidence base (both cited by path+field throughout §2.8.2g):

The defect

build_anchor_frame (m6_cells.py:122-140) admits every gated-start-wave person with no age filter, so minors are in the anchor. marital_panel_builder overrides start_exposure_year := anchor_wave (panel_builders.py:187) and demands the certified person_years entry row at that wave. But the certified marital person_years begin at birth_year + START_AGE (START_AGE = 15, transitions.py:111,260), so any person with anchor_wave < birth+15 has no anchor row and the builder raises (panel_builders.py:209-214). The raise prints missing[:10] (reg-5 listed 10 ids); on the realized anchor the identical mechanism trips a single uniform class of 2,850 sub-START_AGE-at-anchor children (verified read-only: 2,568/246/36 anchored 2015/2017/2019; ages 7–14; born 2001–2008).

Pin correction (uncontested)

The §2.8.2 pin claimed _valid_persons "resolves the missing-entry-row case by construction." It does not: _valid_persons (transitions.py:265-277) tests start_exposure_year ≤ censor_year on the certified start_exposure = birth+15, before the builder overrides start_exposure := anchor_wave. Person-years presence at the anchor requires anchor_wave ≥ birth_year + START_AGE. Corrected in place; §2.8.9's falsified "none" and item (iii) carry dated corrections.

The A-vs-B verdict — argued from the numbers (all verified read-only)

The 2,850 are not gated-neutral: 281 (all born 2001, age 14 at the 2015 anchor, reaching 18 by 2019) sit in the truth-side gated first_marriage.{18-29}@2019 at-risk person-years — 281 of 3,224 = 8.7 % of persons, 9.0 % of F6 weight. Zero appear in any gated event; 2,569 are gated-neutral.

frozen v3 floor (e931c886…) truth-side gated denominators projected universe report-only
A exclude-and-mark moves → dies: symmetric exclusion drops the 281 from the truth-side first_marriage.{18-29}@2019 denominator → σ + tolerance recompute → not byte-identical. Asymmetric (projected-only) preserves the bytes but scores a 2,943-person projected vs 3,224-person truth denominator → identity-guard-rejected (support.py:311-315) + rate-biasing moves (symmetric) 2,850 excluded 2,850
B seed-at-marital-entry (adopted) zero — builder is projected-side only; truth side untouched zero — 281 stay in the frozen denominator +2,638 seeded (212 born-2008 dropped by the existing start_exposure ≤ censor filter); the 281 enter the projected denominator symmetric with truth 2,357

B is adopted; A dies on the ratified-frozen v3 floor constraint. B's pin: replace the unconditional override with start_exposure_year = max(anchor_wave, birth_year + START_AGE) — byte-unchanged for the bulk, the certified risk-set entry for the gap class.

B's named leak, adjudicated empirically (not merely "structurally near-certain")

The certified entry row at birth+15 is never_married for all 2,850 (0 exceptions), with marriage_duration/years_since_dissolution null/zero; the earliest married person-year anywhere in the class is age 19; the 11 who marry (n_marriages > 0) marry at age ≥ 19, strictly after the seed. The seed is a structural constant carrying zero holdout informationB leaks nothing. B reads the certified entry row (the same pd.isna → never_married the core applies, marital.py:100-101), not an assumed state.

Implementing patch (pinned; not in this PR)

  • engine/panel_builders.py marital_panel_builder: one-line clamp at :187 (birth_year already on attrs).
  • assembly.marital_step/m6_runner unchanged (identical builder signature/return).
  • The discriminating test: test_m6_panel_builders.py gains a sub-START_AGE-at-anchor fixture (born 2001 anchored 2015 — the class the current born-1980–1982 fixtures lack) asserting pre-patch raise / post-patch 2016 never_married seed + holdout_ids membership, plus a born-2008 censor-drop case.
  • No schema-audit/manifest/gates.yaml/runs/ delta (clamp reads only existing attrs columns).

What this does NOT change

Frozen floors byte-identical (runs/m6_holdout_floors_v{1,2,3}.json untouched; v3 sha e931c886… remains the gated contract). No gated cell definition moves. The certified engine invariant is preserved — the raise (panel_builders.py:209-214) stays; amendment 3g removes the cause (the sub-START_AGE anchor override) so the invariant holds by construction, mirroring §2.8.3a. Harness/universe-side only.

Tests

  • tests/test_gate_m6_floors.py (the doc-bound test): 23 passed — all asserted design-doc strings preserved.
  • tests/test_m6_panel_builders.py: 7 passed — confirms docs-only (no code changed; the current fixtures do not exercise the crash class, the §2.8.2g gap this amendment names).

Docs-only: 187 insertions, 9 deletions, one file.

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits July 15, 2026 06:47
…sing-entry-row)

The pin claimed _valid_persons resolves the missing-entry-row case by
construction; it tests the certified start_exposure=birth+START_AGE <= censor
BEFORE the builder overrides start_exposure:=anchor_wave, so person-years
presence at the anchor actually requires anchor_wave >= birth+START_AGE. Points
to the new §2.8.2g domain law. Closes reg-5 crash (forensics #42 4979437110).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nd item (iii)

§2.8.9's 'Residual open decisions: none' is falsified: the marital projection had
no domain law for the sub-START_AGE-at-anchor class build_anchor_frame admits.
Dated correction points to §2.8.2g. Item (iii)'s 'children fall outside holdout_ids
and every gated band' holds for synthetic fertility newborns but was falsified for
anchor-present minors (in holdout_ids, aging into first_marriage.18-29) — clarified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…judication)

The reg-5 crash class = 2850 sub-START_AGE-at-anchor children (build_anchor_frame
has no age filter; certified marital person_years start at birth+15). Adjudicates
option B (seed-at-marital-entry, start_exposure=max(anchor_wave, birth+START_AGE))
over A (exclude-and-mark): A perturbs the frozen v3 first_marriage.18-29@2019
denominator (281/3224 = 8.7% persons / 9.0% weight, verified read-only) -> floor
not byte-identical -> dies; B is projected-side-only -> floor byte-identical. Leak
adjudicated empirically: certified entry row never_married for all 2850, earliest
married age 19 -> seed is a structural constant -> leaks nothing. Pins the patch,
discriminating test, and scope. Closes reg-5 (graded 4979269487, forensics
4979437110).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…evision 13)

Adds the revision-log finding->section entry; bumps the design-parameters JSON
revision 12->13; adds amendment_3g_section; corrects builders.marital_universe
(the false 'resolves the missing-entry-row case' claim) and
scored_run_harness.residual_open_decisions ('none' -> one, closed by 3g); extends
next with the reg-4 abort / reg-5 crash / amendment-3g chain. JSON validated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
social-security-model Ready Ready Preview, Comment Jul 15, 2026 11:49am

Request Review

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Adversarial design referee — PR #209 (amendment 3g, §2.8.2g marital projection domain law)

Verdict: SPEC SOUND (ratifiable after listed fixes). 0 BLOCKING · 2 SHOULD-FIX · 3 NOTE.

I re-derived every load-bearing number independently on the real PSID panel (run-5 venv, read-only through the harness loaders — nothing written to any held worktree, runs/, or gates.yaml), and re-ran the two kills and the leak from the data rather than from the PR text. The A-kill survives on both branches and the B-leak verdict holds — the sub-START_AGE-at-anchor class reproduces exactly, symmetric-A moves the frozen tolerance 0.356 → 0.355 (byte-identity dies), the §2.8.4 identity guard fires on asymmetric-A, and all 2,850 class entry rows are never_married. The two SHOULD-FIX items are factual corrections to supporting numbers in §2.8.2g; neither revives A nor opens a leak, so they do not change the adjudicated B-over-A outcome or the pinned patch.

Independently re-derived class counts (real data)

quantity doc re-derived
class size 2,850 2,850
anchor split 2015/2017/2019 2,568 / 246 / 36 2,568 / 246 / 36
birth range / age@anchor 2001–2008 / 7–14, μ10.8 2001–2008 / 7–14, μ10.8
py_year_min == birth+15 (all) yes yes, 0 violations
rows at anchor wave 0 0
reg-5 crash ids = missing[:10] (seed-0 hh side) exact match on seed-0 household side
truth first_marriage 18-29 @2019 281 / 3,224 281 / 3,224, all born 2001
person / weight share of that slice 8.7% / 9.0% 8.72% / 8.97%
gated events in class 0 0 (also 0 shock)
born-2008 censor-drop 212 212 (only born-2008)
net seeded (281 gated + 2,357 RO) 2,638 2,638

The A-kill — survives (both branches)

  • (i) symmetric exclusion. I reproduced the frozen v3 first_marriage.18-29|female cell byte-exact (mean 0.10667990746937188, sd 0.08307374839960044, σ 0.13521039283588324, tol 0.356), then re-ran the 100-seed household floor with the class excluded: mean/sd/σ all move and the derived tolerance shifts 0.356 → 0.355. So symmetric-A is genuinely not byte-identical → dies on the ratified-frozen v3 lock. The floor-arithmetic dependence is real and I consumed it end-to-end.
  • (ii) asymmetric exclusion. The §2.8.4 identity guard (support.py:311-315) fires on real frames when the projection drops the class rows truth still carries (ValueError: symmetric presence-conditioning requires identical projection and truth person-period support); the symmetric case passes and the 281 class 2019 keys survive conditioning. Guard genuinely rejects unlike denominators.

The B-leak — verdict holds

All 2,850 certified entry rows at birth+15 are never_married (0 exceptions), marriage_duration/years_since_dissolution null/zero. Adversarial probes the PR did not run:

  • Pre-15 marriages. The MH file does contain 121 pre-15 marriage-episode start ages (age hist: 14→92, 13→18, 12→6, 11→3, 10→1, 3→1), and 23 fall in the certified attrs∩anchor universe — all carried as married at their birth+15 entry. None are in the class (they are born 1928–1988), so the class's uniform never_married is real, not a coincidence, and B reads the certified row (not an assumed state) either way. No leak.
  • marital.py:100-101 pd.isna semantics agree with the seed coding (never_married → state 0), consistent with the truth side.

Findings

SHOULD-FIX 1 — the "marry at age ≥19" claim is false.
§2.8.2g and the JSON amendment_3g_section state: "the 11 with n_marriages > 0 marry at age ≥ 19 (strictly after the seed)." On real data the earliest first-marriage event in the class is age 18person_id 2852062 (born 2004, first_marriage in 2022). Age 19 is correct only for the earliest married person-year (a consequence of _assign_state's allow_exact_matches=False, which shifts the married state to the year after the event). Also only 9 of the 11 n_marriages>0 have a dated first-marriage episode (2 are undated MH records → no changepoint → no event). The B-leaks-nothing verdict is unaffected (every event at age ≥18 is strictly after the age-15 seed; all entry states are never_married), but correct the wording to "marry at age ≥ 18 (earliest married person-year age 19); the 9 with a dated first marriage marry strictly after the seed."

SHOULD-FIX 2 — 281/3,224 = 8.7% mislabels the floor-cell perturbation.
The 3,224 (and 2,943 = 3,224−281, and 8.7% persons / 9.0% weight) is the 2019 sex-pooled at-risk slice. The actually-gated floor cell is first_marriage.18-29|female, whose denominator pools 2015–2019 and is female-only: 7,832 at-risk person-years, of which the class contributes 157 (all at 2019) = ~2.0% by rows / 2.25% by weight, not 8.7%. The A-kill is unaffected — I reproduced the frozen tolerance 0.356 and its shift to 0.355 under symmetric exclusion, so any nonzero move breaks byte-identity regardless of magnitude — but the doc overstates the gated-cell denominator move ≈4×. Recommend labeling 3,224 / 8.7% explicitly as the 2019 sex-pooled slice and citing the ~2% gated-cell (first_marriage.18-29|female, pooled) denominator move (or just "nonzero → byte-identity broken").

NOTE 1 — asymmetric-A bias direction is inverted.
"…biases the first_marriage rate downward on the projection" (line ~1066): dropping zero-event never_married at-risk person-years raises the rate. Truth-side check: excluding the class lifts the pooled female first_marriage rate 0.04847 → 0.04959 (+2.3%; events unchanged at 339, at-risk 7,832 → 7,675). Moot for the adjudication (the identity guard fires on the key mismatch first — verified), but the prose should read "upward" or drop the direction word.

NOTE 2 — missing[:10] provenance.
The reg-5 ids [6035, 7053, 10187, 23032, 23033, 39033, 39034, 40044, 40045, 41035] are missing[:10] of the seed-0 household-split side (verified identical), not of the full class — whose lowest-10 are [6035, 6038, 7050, 7051, 7052, 7053, 7054, 7055, 7214, 10036]. The doc/forensics are technically correct (the crash was in the first gate seed's household side), but "the raise reports missing[:10]" could mislead a reader into expecting the full-class lowest ids. Optional one-clause clarification.

NOTE 3 — data-quality aside (out of 3g scope). The MH file's pre-15 marriage-episode start ages include an age-3 record; 23 pre-15 persons land in-universe and are carried married at birth+15. None touch the class, so 3g is sound — worth a separate look, not a 3g blocker.

Mechanics & patch pin — all clean

  • Pin correction excised. The §2.8.2 universe row no longer claims _valid_persons "resolves the missing-entry-row case by construction"; it now states the true condition (anchor_wave ≥ birth+START_AGE) and that the certified-span test runs before the anchor override. JSON builders.marital_universe carries the same correction ("CORRECTED by amendment 3g"; no residual false claim). §2.8.9 "residual open decisions: none" → "one, now closed"; item (iii) correctly distinguishes synthetic newborns (outside holdout_ids) from anchor-present minors (inside, do age into the gated band) — matches the 281 I measured.
  • Patch byte-neutrality (real data). Replaying the pinned start_exposure_year = max(anchor_wave, birth+START_AGE): bulk attrs and entry person_years are byte-identical to the unpatched builder (assert_frame_equal, check_dtype=True); max() == anchor_wave for every bulk row; the class is seeded at birth+15 never_married (2,638), and the 212 born-2008 are dropped by the existing start_exposure ≤ censor filter. birth_year is on attrs (transitions.py:239-243), START_AGE from data.transitions. The certified raise (panel_builders.py:209-214) stays; callers (assembly.marital_step:279, runner) unchanged. Blast radius checked — the only other start_exposure_year consumers are marital.py:68/302 (core + fertility); the clamp moves the class's start from age 14→15, which is inert (no marital risk or fertility below 15) and gated-cell-inert.
  • Discriminating-test spec accurately covers pre-patch-raise / post-patch born-2001→2016 never_married seed + holdout_ids + entry row at 2016 / born-2008 censor-drop. Confirmed the current fixtures are all born 1980–1982 (start_exposure 1995–1997) → none exercise the crash class.
  • Docs-only: 1 file, +187/−9. No runs/, gates.yaml, or .py touched. Frozen floors byte-identical (v3 sha e931c886 at head). JSON block parses (single fence, revision 13). §2.8.2g header/placement mirror §2.8.3f. test_gate_m6_floors.py (23) + test_m6_panel_builders.py (7) = 30 passed at head. CI green (build, lint, pytest 3.11/3.13, Vercel); MERGEABLE / CLEAN.

Referee verification: read-only via the harness loaders on the run-5 venv; scratch confined to my own dir; my worktree removed after posting.

S1: earliest first-marriage EVENT in the class is age 18 (pid 2852062, born 2004,
2022); earliest married person-year age 19 (allow_exact_matches=False); 9 of 11
n_marriages>0 have dated events. Leak conclusion unchanged (every event strictly
after the age-15 seed). S2: relabel 281/3224=8.7% as the 2019 sex-pooled slice; the
gated cell first_marriage.18-29|female pools 2015-2019 female-only (7832 at-risk),
class contributes 157 = 2.0% rows / 2.25% weight; A-kill unchanged (any nonzero move
breaks byte-identity; referee reproduced tol 0.356->0.355). N1: asymmetric-A biases
the rate UPWARD not downward (verified). N2: missing[:10] is the seed-0 household
side. N3: out-of-scope MH pre-15 aside (23 in-universe married-at-birth+15, born
1928-1988, none in class). All numbers independently re-derived read-only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirror the prose corrections in the amendment-history JSON: S1 (age-18 event, 9 of
11 dated, age-19 married person-year); S2 (281/3224 = sex-pooled 2019 slice; gated
cell first_marriage.18-29|female = 7832 at-risk pooled 2015-2019, class 157 = 2.0%
rows / 2.25% weight); N1 (asymmetric-A biases rate UPWARD; tol 0.356->0.355, any
nonzero move breaks byte-identity). JSON re-validated (json.loads OK, revision 13).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Referee fixes applied (SPEC SOUND → all 2 SHOULD-FIX + 3 NOTE addressed)

Thanks for the independent re-derivation. Every number was re-verified read-only against the run-5 venv before editing; the B-over-A adjudication, the pinned patch, and the frozen-floor byte-identity are unchanged. Fixes on m6-amendment-3g (PR stays draft for the verification round):

finding resolution commit
S1 — "marry at age ≥19" false Earliest first-marriage event in the class is age 18 (person_id 2852062, born 2004, 2022); the age-19 figure is the earliest married person-year (the _assign_state allow_exact_matches=False shift). Only 9 of 11 n_marriages>0 have a dated episode. Leak conclusion unchanged — every event is strictly after the age-15 seed. 86e9354 (prose), 63f9ca3 (JSON)
S2281/3,224 = 8.7% mislabels the gated cell Relabeled as the 2019 sex-pooled slice. The gated floor cell is `first_marriage.18-29 female(female-only, pooled 2015–2019): **7,832** at-risk person-years, class contributes **157 = 2.0% rows / 2.25% weight** (all at 2019). A-kill unchanged — I state the referee-reproduced0.356 → 0.355` and that any nonzero move breaks byte-identity.
N1 — asymmetric-A bias direction "downward" → "upward" (dropping zero-event never_married at-risk person-years raises the rate; independently confirmed the direction). Moot behind the identity guard, now stated correctly. 86e9354, 63f9ca3
N2missing[:10] provenance Clarified: the 10 reg-5 ids are the lowest-id members of the crash's seed-0 household-split side, not the full class's lowest ids. 86e9354, 63f9ca3 (defect para + next-chain wording)
N3 — pre-15 MH data-quality aside Added a one-clause out-of-scope parenthetical: the MH file carries pre-START_AGE episodes (23 land in attrs ∩ anchor, entering married at birth+15, all born 1928–1988, none in the class) — which is exactly why B reads the certified entry row rather than assuming never_married. Flagged as out of 3g scope. 86e9354

Independently re-derived, matching the referee's table: class 2,850 (2,568/246/36); event age 18 / married-py age 19 / 9-of-11 dated; female-pooled cell 7,832 with class 157 = 2.0%/2.25%; asymmetric-A direction up. JSON re-validates (revision 13, single fence); test_gate_m6_floors.py 23 + test_m6_panel_builders.py 7 = 30 passed. Docs-only; frozen floors byte-identical (v3 e931c886); no runs//gates.yaml/.py touched. Ready for the verification referee.

The S2 fix (gated cell = first_marriage.18-29|female, class move 157/2.0%, not the
281/8.7% sex-pooled 2019 slice) was applied to the Step-2 prose; propagate it to the
A-vs-B table rows A/B, the 'Symmetric floor-inert' pin, the JSON B-description, and
the JSON next-chain so no residual pre-S2 framing remains. Sweep: only the two
explicitly-labeled 'sex-pooled 2019 slice' references keep 281/3224/8.7%. JSON
re-validated (revision 13).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

S2 propagation (follow-up to the fixes above). Completed the S2 relabel across the whole subsection so no residual pre-S2 framing remains: the A-vs-B table rows A/B, the "Symmetric, floor-inert" pin, the JSON B-description, and the JSON next-chain now all state the gated cell as first_marriage.18-29|female with the class move 157 / 2.0 % (tol 0.356 → 0.355; any nonzero move breaks byte-identity). A consistency sweep confirms the only remaining 281 / 3,224 / 8.7 % uses are the two explicitly-labeled sex-pooled 2019 slice references (which are correct). Commit 225eaa0. JSON re-validates (revision 13); test_gate_m6_floors.py 23 passed.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Referee verification round — commits 86e9354 / 63f9ca3 / 225eaa0 (head 225eaa0)

Verdict: VERIFIED — ratifiable. All five findings resolved, not renamed. Re-derived every number myself on the real panel (run-5 venv, read-only); re-ran the floor at this round.

finding status check
S1 event-vs-person-year RESOLVED Prose + JSON now state: earliest first-marriage event age 18 (pid 2852062, born 2004, married 2022); earliest married person-year age 19 (named as the allow_exact_matches=False shift); 9 of 11 n_marriages>0 dated; "every such event strictly after the age-15 seed → B leaks nothing." Re-derived: min event age 18, age-18 pid = [2852062], born 2004, dated 9/11, earliest married person-year 19. ✓
S2 8.7% relabeled everywhere RESOLVED 8.7%/3,224 now labeled "sex-pooled 2019 slice" in all 6 sites (Step-2 prose, A-vs-B rows A+B, "B is adopted" para, Pins(B), JSON amendment_3g_section, JSON next). Gated cell correctly stated as first_marriage.18-29|female, 7,832 at-risk, class 157 = 2.0% rows / 2.25% weight. Re-derived exactly: 7,832 / 157 / 2.0% / 2.25%; the 2019 sex-pooled slice 3,224 / 281 / 8.72% / 8.97%. ✓
N1 bias direction RESOLVED "biases the rate upward … (dropping zero-event at-risk person-years raises the rate)" in prose + JSON. ✓
N2 missing[:10] framing RESOLVED "the 10 ids reg-5 listed are the lowest-id members of the crash's seed-0 household-split side, not the full class's lowest ids." ✓
N3 23 married-at-15 note RESOLVED "23 land in attrs ∩ anchor and enter married at their birth+15 — but none is in this class (born 1928–1988); out of scope for 3g." Re-derived: 23 in-universe, entry states {married: 23}, 0 in class, births 1928–1988. ✓

A-kill re-reproduced this round: the frozen v3 first_marriage.18-29\|female cell reproduces byte-exact (mean 0.10667990746937188, sd 0.08307374839960044, σ 0.13521039283588324); symmetric exclusion of the class shifts the derived tolerance 0.356 → 0.355 — the doc's stated numbers, confirmed. "Magnitude immaterial; any nonzero move breaks byte-identity" is the right framing.

Residual-framing sweep: clean. No bare 2,943, {18-29}, or @2019 remain; the only 8.7%/3,224 occurrences are the two correctly-labeled sex-pooled references (prose §2.8.2g + JSON) — the 8.7-pattern hits on lines 840/1516/1577 are §2.8.7 section refs, not S2 framing. marital_universe still carries the pin correction ("CORRECTED by amendment 3g"); residual_open_decisions = "one, closed by amendment 3g".

Mechanics at head 225eaa0: docs-only (1 file, +201/−9); frozen floors byte-identical (v3 sha e931c886); JSON block parses (single fence, revision 13); test_gate_m6_floors.py (23) + test_m6_panel_builders.py (7) = 30 passed; CI green (build, lint, pytest 3.11 + 3.13, Vercel); MERGEABLE (PR remains draft — not merging).

No new findings. The referee round is closed from my side; ratifiable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant