Commit fdde0a0
committed
P-037 Phase B / B1-F2-F2: the extractor seam itself was still too narrow
Owner review of B1-F2 (5579d80/f8ffd42), while deriving the concrete
B2.1a implementation, found the repaired boundary mechanically
insufficient before any production byte moved -- a second, deeper freeze
needed on top of B1-F2-F1's record-only wording fix.
Finding A (proven, not assumed): ConsumeReleaseArgs's answer drives BOTH
EmitFlowExpr's release fabrication AND a separate escape/tracking
admission check (Program.cs's consumedArg). A scratch, never-committed
edit forcing ConsumeReleaseArgs to always abstain was run against all 8
named acceptance fixtures plus the full corpus/p036-bakeoff and
corpus/p037-shapes populations (own-check.sh --emit-facts, before/after
diffed byte-for-byte, reverted via git checkout before every next step):
7 of 8 canonical callers were dropped from functions[] entirely into a
body-less guarded_functions[] orphan (every acquire/release/use for the
local gone, not just the fabricated release); the 8th silently lost
tracking of a SEPARATE, honest, unconditional dispose in the same
method. Across the two populations: 9 functions newly orphaned, 4 more
corrupted, out of 94 (~14%); 0 new findings, 3 lost (false positives
erased by accident, not by correct reasoning). corpus/real-world (66
files) and corpus/wpf (56 files): zero impact, confirming the mechanism
is inert outside the guarded-consume shape. ANSWER: the existing
3-method seam cannot remove the fabricated release without destroying
caller obligation tracking -- NO. This same measurement doubles as the
hostile "broad retirement" control: REJECTED, not narrow within the
population it actually touches.
Finding B (proven from source and a real fixture): G-V4-rejected guard
candidates are invisible in the emitted sidecar by design ("not
eligible: no entry" -- confirmed on gv4-control-aliased-self-null:
Close's functions[] record carries no guarded_facts key at all, same
shape as genuinely unguarded). A rule keyed on "callee's guards[]
non-empty" cannot cover this. The raw guard-candidate shape match
already exists inside BuildGuardedFacts's own loop but only as inline
logic; extracting it into a shared helper is the likely resolution, NOT
yet proven by a scratch measurement the way Finding A is -- left
deliberately open for B2.1a, BuildGuardedFacts NOT authorized here.
Finding C: difference_policy.note referenced a first_semantic_
hypothesis.facts_expectation field that did not exist while still
asserting B1's now-stale pre-treatment "unchanged, full stop" claim.
Fix (record + gate, no Program.cs byte moves -- verified byte-identical
to f8ffd42 throughout):
- treatment.extractor_seam.mutable_methods gains EmitFlowExpr;
authorized_change_shape rewritten around the two decoupled roles
(ConsumeReleaseArgs/ConsumesParam keep answering TRACKING unchanged;
EmitFlowExpr alone decides RELEASE EMISSION, degrading to `use` rather
than dropping the op).
- new b1_f2_f2_seam_investigation section carries the findings/numbers.
- new, closed first_semantic_hypothesis.facts_expectation (allowed/never
raw-fact surface, machine-readable, not prose).
- difference_policy.note corrected in place; raw-fact layer now
explicitly separated from the semantic MOS/verdict classifier layer.
- new ci_transition_plan section preregisters the staged CI shape B2.1a
will use, without editing expected.json or p037_controls.py.
- scripts/p037_b_extractor_diff_gate.py: MUTABLE_METHODS gains
EmitFlowExpr; new dedicated hostile test proving it may move (its own
void-returning, multi-parameter shape); existing live-source/policy-
drift/violation checks extend automatically (they iterate the tuple,
not the three original names).
- docs/notes/p037-formal-kernel.md #10.8f documents both findings.
Verified: Program.cs byte-identical to f8ffd42; p037_controls.py --engine
both still matches current exactly; --post-a1 still fully RED on both
engines; extractor gate selftest (21 checks, including the new one) and
p037_evidence_b.py selftest green; ruff, mypy, full tests/run_tests.py,
fact-shape census all clean.
Widening scripts/p037_b_extractor_diff_gate.py (a tracked Phase-B
instrument path) moves instrument_identity -- the same consequence B1-F1
and B1-F2 each already had. named_later.T_B/R_B will be retaken fresh
once this head is terminal-green, same order as before. B_treatment_head
and B_after_evidence stay null: B2.1a remains separate, later, and not
yet authorized.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AN6xHbpovxrmZ4AMjS7WQA1 parent f8ffd42 commit fdde0a0
3 files changed
Lines changed: 273 additions & 27 deletions
File tree
- docs
- evidence
- notes
- scripts
0 commit comments