Skip to content

Commit e6b8dc4

Browse files
committed
P-037 A18-1F: pre-register the final population-decomposition re-plan (no code)
Final budget re-plan after the A18-1R STOP (#377, 192/180, not run), per the owner ruling. Split, prospectively frozen budget: measurement <= 145, falsifier module <= 60, total <= 200; any cap reached unfinished kills the population-decomposition approach. Document-wide canonicalization independent of L_actual; broken canonicalization propagates through the forward closure; non-EQUAL reasons need exactly one witnessed mechanism; EQUAL split into equal_identity / equal_after_rewrite. F0 (A->B->C) must kill the old local-honesty rule first. Rows: the 36 of the #376 snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiyfrkaG9sJruTcshM2oq
1 parent ca14336 commit e6b8dc4

1 file changed

Lines changed: 268 additions & 0 deletions

File tree

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
# P-037 A18-1F: population decomposition, final re-plan (pre-registered)
2+
3+
> Status: **PRE-REGISTERED.** This file is committed before any executable
4+
> change of this gate. The boundaries below do not move after this SHA.
5+
>
6+
> - Base: `ca1433661cf6b62f10dfc4701fc9067647f2b612`, the exact head of #376
7+
> (B1 evidence completion). It is **not** the over-budget #377.
8+
> - Branch: `research/p037-a18-1f`.
9+
>
10+
> `F` means **final attempt**. It is the last budget re-plan for the A18
11+
> population-decomposition hypothesis. If this gate reaches any of its three
12+
> caps unfinished, the approach is **killed**. There will be no A18-1G.
13+
14+
## 0. Owner decision (OWNER RULING, 2026-09-28, recorded in meaning)
15+
16+
- **#377 (A18-1R)** stays unchanged as a STOP research artifact:
17+
`STATE: STOP — 192 / 180`, `RUN: NONE`. It is not run, its cap is not
18+
edited, and it is not minified down to 180.
19+
- **#376** is accepted as case-4 evidence infrastructure. Its scope is exact:
20+
- Its 36-row snapshot is a **new supplemental per-row baseline** for A18.
21+
- It reproduces B1's aggregates and the 8 rows B1 committed individually.
22+
- It proves nothing historical, row by row, about the other 28 rows,
23+
because B1 never committed them per row.
24+
- The differing extractor DLL sha stays disclosed.
25+
- **Why a re-plan is allowed once.** The #377 STOP showed the cost
26+
structure. About 140 lines are measurement, coverage and reporting; about
27+
52 are the kill harness. The decomposition itself does not grow into a new
28+
solver. So the premise is alive; the executable falsifiers were mispriced.
29+
- **Why the budget is split.** A new, prospectively frozen, split budget is
30+
allowed. Moving the falsifiers into another file does **not** make their
31+
lines free: the test module has its own cap *and* counts toward the total.
32+
The split is architectural, not a tax shelter.
33+
34+
## A. Question
35+
36+
Unchanged from A18-1 and A18-1R. On the frozen population `571669e`, is the
37+
already-registered two-seam model sufficient with **only** the known
38+
normalization reasons?
39+
40+
```text
41+
G <-> L_canonical semantic_class: EQUAL | SUMMARY_REFINEMENT | LEGACY_HONESTY | UNEXPLAINED
42+
L_canonical <-> L_actual normalization_reason: EQUAL | CONSUMES_PARAM_FOLD | ARGUMENT_SHAPE_LOSS | UNEXPLAINED
43+
```
44+
45+
A third normalization mechanism, however understandable, is
46+
`RESULT: FAIL — A18-1F NORMALIZATION MODEL INCOMPLETE`. It is never an
47+
invitation to extend the enum.
48+
49+
## B. Rows
50+
51+
- The rows are exactly the **36** comparable rows of the #376 snapshot
52+
`docs/evidence/p037-b1/comparable-summary-rows.json`: 28 `EQUAL` and 8
53+
`UNEXPLAINED`. Each is a B1 summary coordinate with both `G` and
54+
`L_actual`.
55+
- They are recomputed from the frozen population with the unchanged B1
56+
instrument, one row per coordinate whose class is not
57+
`NO_GUARDED_EVIDENCE`. The row key is `(document, method, index)`.
58+
- The 68 `NO_GUARDED_EVIDENCE` rows and all application-level rows are
59+
outside this gate.
60+
61+
## C. Definitions (fixed before measuring)
62+
63+
For each document, the frozen facts are extracted with the unchanged B1
64+
instrument. `L_actual`, `G` and B1's class come from `own-guarded-report` on
65+
those facts as emitted.
66+
67+
### C.1 Forward sites and eligibility
68+
69+
- **Coordinate:** a summary row `(method, index)` of the document's report
70+
whose function is in the document's facts.
71+
- **Forward site of a coordinate:** a sidecar (`guarded_facts.calls`) call in
72+
that function in which the coordinate's parameter (by `ordinal`) fills a
73+
`param` slot.
74+
- **Eligibility** is decided from frozen facts only. A site is **eligible**
75+
(canonicalized) when all of these hold:
76+
- **E1:** the parameter fills exactly one slot of that call;
77+
- **E2:** exactly one legacy body op names the parameter at the call's
78+
`statement_line`, and no other site already canonicalized that op;
79+
- **E3:** the callee coordinate resolves to exactly one report summary row
80+
`(callee, ordinal = slot)`, which gives the callee `index`.
81+
- A site that fails E1–E3 is **broken**.
82+
- **Eligibility never reads `L_actual`.** The #375 rule "rewrite only if the
83+
callee's `L_actual` disagrees" is forbidden. It is kept only as the
84+
test-only `local` mode that F0 must kill.
85+
86+
### C.2 L_canonical and semantic_class
87+
88+
- **`L_canonical`:** the unchanged production MOS, run once per document over
89+
facts in which **every** eligible forward site of **every** coordinate is
90+
represented as the canonical legacy `call`. That is A18-0's positional form:
91+
`{"op":"call","callee":…,"sig":…,"line":statement_line,"args":["_"]*callee_index+[param]}`.
92+
This applies whatever the site's current op is, and a site that is already
93+
a `call` is rewritten to the same form.
94+
- **`semantic_class`:** the class `own-guarded-report` assigns to the row on
95+
the canonical facts, which is the existing rule `G <-> L_canonical`.
96+
- **`G` must not move:** the row's `G` on the canonical facts must equal its
97+
`G` on the original facts.
98+
99+
### C.3 Forward closure and broken propagation
100+
101+
- **Forward closure of a row:** its own coordinate, plus every coordinate
102+
reachable through the callee coordinates of eligible sites, transitively.
103+
- **Broken closure:** the closure contains a broken site, or a coordinate
104+
with no entry (for example, its function is absent from the facts). A row
105+
whose closure is broken is normalization **`UNEXPLAINED`**, whatever its own
106+
site looks like, and even when `L_actual == L_canonical`. A canonical
107+
surface that could not be built honestly proves nothing.
108+
109+
### C.4 Site mechanism and local witness
110+
111+
The mechanism comes from the site's actual op.
112+
113+
| actual op | mechanism | local witness |
114+
|------------|-----------------------|---------------|
115+
| `call` | `EQUAL` | not needed |
116+
| `release` | `CONSUMES_PARAM_FOLD` | the actual representation at this honest-forward site is `release`, and this site was replaced by the canonical forward in the canonical facts |
117+
| `use` | `ARGUMENT_SHAPE_LOSS` | the fold witness above, plus the already-registered wrapper probe: the frozen source with only `(T)x` / `x!` removed on that line re-extracts to `release` there |
118+
| other | `UNKNOWN` | none |
119+
120+
- A `use` site whose wrapper probe fails is `UNKNOWN`.
121+
- The probe is evaluated wherever it can decide a reason, which means at
122+
every `use` site in the closure of a row with `L_actual != L_canonical`.
123+
- In the closure of an `EQUAL` row, mechanisms are reported only as
124+
metadata.
125+
126+
### C.5 normalization_reason
127+
128+
The rules apply in this order:
129+
1. **Broken closure** gives `UNEXPLAINED`.
130+
2. **`L_actual == L_canonical`** gives `EQUAL`, even if canonicalization
131+
physically rewrote sites. It is counted separately:
132+
- `equal_identity`: every site in the closure already was a `call`, or
133+
there is no site;
134+
- `equal_after_rewrite`: at least one site in the closure had a non-`call`
135+
op. This is the hidden, currently value-neutral normalization debt.
136+
3. **`L_actual != L_canonical`** gives the non-`EQUAL` reason `R` only if
137+
all of these hold:
138+
1. the closure contains exactly one non-`EQUAL` mechanism kind, and it is
139+
`R`;
140+
2. `R` is `CONSUMES_PARAM_FOLD` or `ARGUMENT_SHAPE_LOSS`;
141+
3. every site of `R` in the closure satisfies its local witness (C.4);
142+
4. there is no `UNKNOWN` and no broken site in the closure.
143+
144+
Otherwise the reason is `UNEXPLAINED`. A closure with both a fold and a
145+
shape loss is `UNEXPLAINED`, even though the composition is intuitively
146+
understood. The hypothesis promises one reason per non-equal row.
147+
148+
## D. Necessary conditions
149+
150+
- **N1: coverage.** Every snapshot row is decomposed exactly once, with no
151+
missing, extra or duplicated `(document, method, index)`.
152+
- **N2: no drift.** For every row, `L_actual`, `G` and the B1 class equal the
153+
snapshot. Any drift makes the gate **VOID**.
154+
- **N3:** semantic `UNEXPLAINED = 0`.
155+
- **N4:** normalization `UNEXPLAINED = 0`, and no broken closure.
156+
- **N5:** every non-`EQUAL` reason satisfies C.5.3, including the executable
157+
per-site witnesses.
158+
- **N6:** `G` moved by canonicalization `= 0`.
159+
- **N7:** A18-0 consistency. The 8 A18-0 rows reproduce A18-0's committed
160+
`L_canonical` (`docs/evidence/p037-a18/eight-rows.json`), with eight-row
161+
drift `= 0`.
162+
163+
## E. Falsifiers (run first; the population runs only if all fire)
164+
165+
The falsifiers live in a separate, non-auto-discovered test module,
166+
`tests/p037_a18_1f_falsifiers.py`. It is not named `test_*.py`: `run_tests.py`
167+
auto-discovers those, and CI has no frozen-population extractor build. Its
168+
output is committed as evidence before the population run, and the
169+
population is run only if it exits 0.
170+
171+
- **F0 (first): transitive A → B → C.** The fixture is built from the frozen
172+
facts of `guard-forward-bare`:
173+
- B = `ShapeForwardBare.Outer` forwards to C = `ShapeForwardBare.Inner`.
174+
- A test-only caller A forwards to B with a legacy `release`, which agrees
175+
with `B_actual = must`. A is never population.
176+
177+
Both halves must hold:
178+
- the **new rule passes**: `A_canonical == B_canonical != B_actual`, and
179+
A's reason is `CONSUMES_PARAM_FOLD`;
180+
- the **old #375 local-honesty rule fails**: `A_canonical == B_actual`.
181+
182+
If the old rule is not killed by this fixture, F0 is built wrongly: the
183+
gate STOPs and does not run the population.
184+
- **F1:** a fold row with canonicalization disabled is no longer
185+
`CONSUMES_PARAM_FOLD`.
186+
- **F2: broken links give `UNEXPLAINED`.**
187+
- F2a: in a cast/bang row whose own sidecar-to-forward link is broken
188+
(the site's `statement_line` shifted off the legacy op), the reason is
189+
`UNEXPLAINED`, not a fold.
190+
- F2b, closure propagation: in the F0 fixture, only B's site is broken. A
191+
must be `UNEXPLAINED`, although A's own site is intact.
192+
- **F3:** the pure rule (C.5) gives `UNEXPLAINED` in three cases:
193+
- `actual = unknown`, `canonical = must`, and no mechanism;
194+
- a closure holding both a fold and a shape loss;
195+
- a broken closure with `actual == canonical`.
196+
- **F4:** a `G` / `L_canonical` pair outside the three semantic cases is
197+
semantic `UNEXPLAINED`. This uses the cast row with canonicalization
198+
disabled (`may` vs `no`) and the real Rust classifier.
199+
- **F5 / F6:** coverage on the complete document passes. Deleting one row
200+
(F5), or duplicating one (F6), fails it.
201+
202+
## F. Hard KILL: `RESULT: FAIL — A18-1F …`
203+
204+
The gate fails on any of these:
205+
- F0 does not kill the old local-honesty rule, or any falsifier misses. The
206+
population is then not run.
207+
- semantic `UNEXPLAINED > 0`;
208+
- normalization `UNEXPLAINED > 0`;
209+
- a broken canonicalization in any closure;
210+
- a new normalization mechanism is needed;
211+
- a snapshot coverage problem (missing, extra or duplicate) or drift (VOID);
212+
- `G` changes under the canonical rewrite;
213+
- A18-0 eight-row drift;
214+
- information beyond the frozen facts is needed, other than the registered
215+
wrapper probe;
216+
- production semantics, `ConsumesParam`, the extractor, OwnIR or facts have
217+
to change;
218+
- **budget:** measurement `> 145`, tests `> 60`, or total `> 200`.
219+
220+
Reaching any cap unfinished gives
221+
`RESULT: KILL — A18 POPULATION-DECOMPOSITION APPROACH (BUDGET)`. No further
222+
budget re-plan follows.
223+
224+
## G. PASS: `RESULT: PASS — A18 POPULATION DECOMPOSITION HOLDS`
225+
226+
PASS requires all of:
227+
- `covered = 36`, `missing = 0`, `duplicates = 0`, `extra = 0`, snapshot
228+
drift `= 0`;
229+
- semantic `UNEXPLAINED = 0`, normalization `UNEXPLAINED = 0`, broken
230+
closures `= 0`;
231+
- A18-0 eight-row drift `= 0`, and `G` changed by canonicalization `= 0`.
232+
233+
For every row, the result reports `L_actual`, `L_canonical`, `G`,
234+
`semantic_class`, `normalization_reason`, the closure mechanisms and the
235+
witnesses. The aggregates are the semantic counts, the normalization counts,
236+
`equal_identity`, `equal_after_rewrite` and the
237+
`semantic_class × normalization_reason` cross-tab.
238+
239+
A PASS does not make B1 pass. It establishes only this: "B1's original gate
240+
failed, and the A18 decomposition explains that failure population-wide."
241+
A B1 reconciliation gate needs its own authorization.
242+
243+
## H. Budget (all three caps are binding)
244+
245+
```text
246+
measurement / decomposition / report code: <= 145 lines (scripts/p037_a18_decompose.py, delta vs ca14336)
247+
falsifier test module: <= 60 lines (tests/p037_a18_1f_falsifiers.py, new file)
248+
-----------------------------------------------------------------------------------------------------
249+
TOTAL executable handwritten delta: <= 200 lines
250+
```
251+
252+
- The counting rule is the same as in A18-0 and A18-1R: added or changed
253+
lines in `git diff ca14336`, excluding blank lines and lines whose stripped
254+
text starts with `#`. Docstrings count.
255+
- Test-module lines count toward the total; they are not an exclusion.
256+
- No minification: the code is written in the repository's ordinary style.
257+
- This note and the evidence JSON are not code.
258+
259+
## I. Non-goals
260+
261+
This gate does not touch any of these:
262+
- B1: #373 and its evidence, and the #376 snapshot;
263+
- #375 and #377;
264+
- production MOS and verdicts, and `ConsumesParam`;
265+
- extractor facts and semantics, OwnIR, R, A14, #368, Phase C;
266+
- the three P-037 classes, `own-guarded`, and the application level.
267+
268+
It adds no normalization reason.

0 commit comments

Comments
 (0)