Visitar URL original
docs/methodology: pre-port-audit-checklist (3-category cascade-audit) · SonicField/cpython@0efc0e1 · GitHub
Skip to content

Commit 0efc0e1

Browse files
committed
docs/methodology: pre-port-audit-checklist (3-category cascade-audit)
Authored per supervisor 00:51:18Z (B) + pythia python#368 audit-completeness gap. Closes the chat→structural gap for the cascade-audit-3-category discipline (feedback_cascade_audit_3category) by codifying the explicit checklist into the corpus. Files: NEW docs/methodology/pre-port-audit-checklist.md (+118 LOC) Specifies: - Motivation (c14 a6500318e0 SIGSEGV: audit cited only sizeof, missed offsetof + literal-offset categories; +8-byte offset corruption from frame_asm_c_frame_header_size +sizeof(void*) asymmetry vs C++ frameHeaderSize) - 3 categories explicit: (a) Sizeof equivalence (per touched C++ struct/class) (b) Offsetof equivalence per accessed field (NOT optional even if sizeof matches — empty-base-optimization can shift offsets symmetrically) (c) Hardcoded literal-offset equivalents (verify C-side substitute has same semantics as C++ original; cite both file:line; identify asymmetries: asm-helper vs LIR-generation, version conditionals, arithmetic adjustments) - Pre-audit procedure (4 steps: enumerate a, enumerate b, enumerate c, compose audit post) - Pre-audit example using c14 retrospective (what the audit SHOULD have said — calibration anchor) - Enforcement chain (author cite + gatekeeper APPROVE checklist + medic flag + supervisor dispose) - Out-of-scope (routine, docs, test, single-language refactors) - Non-coverage caveat (catches structural layout, NOT algorithmic differences / side effects / threading) - Self-falsifying disclaimer (calibration: any audit citing 3 categories at this detail level that still misses c14-class bug = checklist incomplete, not author failure) NOT a v2.x amendment per moratorium (D-1778554524) — operational discipline / methodology document. Companion to synthetic_falsifier_at_gate.md (1546c43). PRE-COMMIT BUILD: doc-only; pre-commit hook docs-path-skip per a2e8808 self-config.
1 parent 1fc473a commit 0efc0e1

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Pre-Port Audit Checklist (Layout-Pinned C++ Struct Ports)
2+
3+
**Authored:** theologian, 2026-05-13 (per supervisor 00:51:18Z (B), pythia #368 audit-completeness gap)
4+
5+
**Scope:** Mandatory checklist for any C++→C port commit that touches a C++ struct or class with C-side layout-pinned representation (HirInstrLayout, HirBeginInlinedFunction, HirFrameStateLayout, LirOperand, LirBasicBlock, LirFunction, LirInstruction, etc.). Supplements `synthetic_falsifier_at_gate.md` (1546c4330e) with a structural pre-commit audit specifically targeting the cascade-audit-3-category failure class (`feedback_cascade_audit_3category`).
6+
7+
## Motivation
8+
9+
c14 (a6500318e0, 2026-05-13 00:06:50Z) shipped after a "single-pass audit" that cited only category (a) — `sizeof(HirBeginInlinedFunction) == sizeof(BeginInlinedFunction)`. The audit missed:
10+
11+
- (b) field-offset cross-validation for HirBeginInlinedFunction `func` and `caller_state_ptr` (only `fullname` was offsetof-validated)
12+
- (c) hardcoded literal-offset assumption: the port called `frame_asm_c_frame_header_size` (the asm-helper variant that adds `+sizeof(void*)` when `ENABLE_SHADOW_FRAMES` undef) instead of the LIR-generation-equivalent `jit_frame_header_size` direct call. The asm-helper variant produces +8-byte offsets at runtime, crashing JIT in `test_phoenix_benchmark_correctness::test_fibonacci`.
13+
14+
The audit metric measured velocity (~20s dispatch→auth) and missed completeness. This checklist makes completeness auditable structurally, not by author judgment.
15+
16+
## The 3 Categories (per `feedback_cascade_audit_3category`)
17+
18+
Every port commit touching layout-pinned C++ structs MUST cite all three categories explicitly in the audit (chat or commit body), with specific C-side equivalents named:
19+
20+
### (a) Sizeof equivalence
21+
22+
For each C++ struct/class touched by the port (including via `reinterpret_cast`, field access, or method dispatch):
23+
24+
- Locate the `static_assert(sizeof(HirX) == sizeof(CppY))` line in the appropriate verifier file (e.g., `hir_instr_c_verify.cpp`, `lir_instr_c_verify.cpp`).
25+
- Cite the file:line.
26+
- If MISSING, ADD the static_assert as part of the port commit OR a precursor commit (do NOT proceed without one — the c14 SIGSEGV class).
27+
28+
### (b) Offsetof equivalence per field
29+
30+
For each C++ field accessed by the port via `instr->field` or equivalent C-side cast:
31+
32+
- Locate the `static_assert(offsetof(HirX, c_field) == offsetof(CppY, cpp_field_))` line in the verifier file.
33+
- Cite the file:line per field.
34+
- If MISSING for any accessed field, ADD the offsetof asserts BEFORE the port commit (precursor) OR in the same commit as part of the verifier-extension scope.
35+
- NOTE: sizeof equivalence (a) is NECESSARY but NOT SUFFICIENT; an empty base class subobject (e.g., `InlineBase`) can shift derived-class field offsets without changing total sizeof if the shift is symmetric on both sides — an offsetof per-field check catches asymmetric layouts.
36+
37+
### (c) Hardcoded literal-offset equivalents
38+
39+
For each C-side function or constant the port calls/uses as a substitute for a C++ method or constant:
40+
41+
- Verify the SUBSTITUTE has the SAME semantic behavior as the C++ original. Common asymmetries:
42+
- asm-helper variants vs LIR-generation variants (c14's `frame_asm_c_frame_header_size` vs `jit_frame_header_size` direct call)
43+
- Constants with version-conditional adjustments (`ENABLE_SHADOW_FRAMES`, `PY_VERSION_HEX`)
44+
- C-side fields that look identical-named but encode different shifts (e.g., `caller_state_ptr` vs `caller_state_` — same field, but the question is what the *value* means; if C++ wraps it via accessor with extra logic, the raw field read may differ)
45+
- If the substitute's semantics differ in any way, EITHER:
46+
- Construct the C++-equivalent expression manually in the C port (matching the args the C++ wrapper passes — c14's amend used `jit_frame_header_size(code, lightweight, sizeof(void*), sizeof(PyObject*))` to match `frameHeaderSize`'s exact behavior)
47+
- Add a static_assert proving the substitute produces the same value for the relevant inputs (e.g., for c14: `static_assert(JIT_FRAME_HEADER_SIZE_AS_USED_IN_C_HELPER == sizeof(jit::FrameHeader))`)
48+
- Document the asymmetry in the port comment AND the commit body, with a falsifier test if runtime behavior differs.
49+
50+
## Pre-Audit Procedure
51+
52+
Before posting the c-series scope-confirmation request to chat:
53+
54+
1. **Enumerate (a):** list every C++ struct/class the port touches; for each, file:line of the sizeof static_assert. If any are missing, decide whether to (i) add the assert as part of port commit OR (ii) add as precursor commit. Document the decision in the audit post.
55+
56+
2. **Enumerate (b):** list every C++ field the port accesses (directly or via accessor); for each, file:line of the offsetof static_assert. If missing, same decision tree as (a). Specifically: when the C++ class uses MULTIPLE INHERITANCE (even from an empty base), per-field offsetof asserts are NECESSARY because empty-base-optimization is implementation-defined.
57+
58+
3. **Enumerate (c):** list every C-side function and constant the port uses as a substitute for C++. For each substitute, locate the C-side definition (file:line) AND the C++ original (file:line); compare them line-by-line for asymmetries (extra args, version conditionals, extra arithmetic). If any asymmetry, document the resolution.
59+
60+
4. **Compose audit post:** include all three category enumerations explicitly. Failure to cite all three categories is a `feedback_cascade_audit_3category` violation (medic-flaggable).
61+
62+
## Pre-Audit Procedure Example (c14 retrospective)
63+
64+
What c14 audit SHOULD have said:
65+
66+
> (a) Sizeof equivalence:
67+
> - HirBeginInlinedFunction: sizeof matched at hir_instr_c_verify.cpp:281 ✓
68+
> - HirFrameStateLayout: sizeof matched at hir_instr_c_verify.cpp:106 ✓
69+
>
70+
> (b) Offsetof equivalence per field:
71+
> - HirBeginInlinedFunction.func — UNVERIFIED ⚠ (only .fullname offset asserted at line 268). Multiple inheritance from InlineBase (empty class) may cause subtle layout shift. ACTION: ADD offsetof(HirBeginInlinedFunction, func) == offsetof(BeginInlinedFunction, func_) static_assert as part of c14 commit.
72+
> - HirBeginInlinedFunction.caller_state_ptr — UNVERIFIED ⚠. Same. ACTION: ADD.
73+
> - HirFrameStateLayout.parent — VERIFIED at hir_instr_c_verify.cpp:120 ✓
74+
> - HirFrameStateLayout.code — VERIFIED at hir_instr_c_verify.cpp:113 ✓
75+
>
76+
> (c) Hardcoded literal-offset equivalents:
77+
> - C++ `frameHeaderSize(PyCodeObject*)` (frame_header.h:67) calls `jit_frame_header_size(code, lightweight, sizeof(FrameHeader), sizeof(PyObject*))` with sizeof(FrameHeader)=sizeof(void*) on 3.12+.
78+
> - C-side candidate `frame_asm_c_frame_header_size(PyCodeObject*)` (frame_asm_c.c:351) calls jit_frame_header_size with hardcoded JIT_FRAME_HEADER_SIZE=sizeof(void*) BUT THEN ADDS `+sizeof(void*)` when ENABLE_SHADOW_FRAMES is undef. ⚠ ASYMMETRIC. ACTION: do NOT use frame_asm_c_frame_header_size; call jit_frame_header_size directly with C++-equivalent args.
79+
80+
If c14 audit had cited (b) and (c) at this level of detail, the SIGSEGV would have been caught at audit time, not at gate.
81+
82+
## Enforcement
83+
84+
- **Author-side:** every port commit's audit post (chat or commit body) MUST include all three category enumerations.
85+
- **Gatekeeper:** APPROVE checklist for layout-pinned-port-class commits MUST verify all three category citations are present and concrete (file:line, not "verified").
86+
- **Medic:** [MEDIC-WARNING] on any port commit landing without 3-category audit citation.
87+
- **Supervisor:** disposes flags from medic.
88+
89+
## Out-of-scope
90+
91+
- Routine code commits that don't touch layout-pinned C++ structs (no audit needed).
92+
- Documentation-only commits.
93+
- Test-only commits.
94+
- Refactors within a single language (e.g., C++ method extraction without C interop).
95+
96+
## Non-coverage caveat
97+
98+
This checklist catches structural layout asymmetry. It does NOT catch:
99+
100+
- Algorithmic differences between C and C++ implementations (the C-port body could compute the wrong thing even if all layout is correct).
101+
- Side effects (e.g., reference counting, exception state) that C++ handles implicitly via destructors but C must handle explicitly.
102+
- Threading/synchronization assumptions.
103+
104+
These remain the author's responsibility to verify via runtime tests (gate Tier 1, force_compile, ABBA). The 3-category audit is a NECESSARY but NOT SUFFICIENT condition.
105+
106+
## Self-falsifying disclaimer
107+
108+
If a future port commit cites the 3 categories at this level of detail and STILL produces a runtime bug at gate, this checklist is incomplete and needs extension. The c14 retrospective example above is the calibration anchor: any pre-port audit that would NOT have caught c14's frame_asm_c asymmetry given this checklist is a checklist failure, not an author failure.

0 commit comments

Comments
 (0)