Skip to content

Commit ca84cb1

Browse files
committed
docs(p037): amend Phase B conditionality evidence contract
Fourth semantic difference class (CONDITIONALITY_HONESTY), the call-site witness contract that explains it, the verdict-snapshot consumer that verifies it via observation binding against a real captured before/after SARIF pair, the preregistered future SARIF-properties producer boundary (verdict.rs: struct Finding/impl Finding/fn transfer_note; render.rs: struct Properties/fn sarif_result -- item-level, not whole-file), the matching treatment carve-out correction in scripts/p037_evidence_b.py, and instrument-supersession preregistration. Zero production semantics: rust/, frontend/, and ownlang/ are byte-identical to e4199ec. Proven end to end with a real compiled own-cli binary emitting a schema-shaped witness that classifies as CONDITIONALITY_HONESTY through the unmodified reader chain, then fully reverted before this commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AN6xHbpovxrmZ4AMjS7WQA
1 parent e4199ec commit ca84cb1

7 files changed

Lines changed: 1438 additions & 41 deletions

File tree

‎docs/evidence/p037-b-epoch.json‎

Lines changed: 40 additions & 6 deletions
Large diffs are not rendered by default.

‎docs/notes/p037-formal-kernel.md‎

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3650,3 +3650,174 @@ the same kind of retake B1-F1/B1-F2/B1-F2-F2/B1-F2-F4/B1-F2-F4-R1 each
36503650
already forced. Only once this corrected head is terminal-green does the
36513651
fresh `T_B`/`R_B` retake proceed, and only after THAT retake is itself
36523652
terminal-green does B2.1a become the next authorized task — not before.
3653+
3654+
## 11. Phase B / B2.1b/c-R1: the CONDITIONALITY_HONESTY case-5 amendment
3655+
3656+
The held B2.1b/c-R1 treatment (the guarded-effect summary engine actually
3657+
wired into `mos.rs`/`lower.rs`/`dump.rs`, uncommitted on its own branch)
3658+
gave the B1 classifier (`scripts/p037_b_classifier.py`) its first REAL
3659+
`guarded` representation to measure real documents against. Doing exactly
3660+
what B1-F2-F4's own `derive_document_witnesses`/`explain_divergence`
3661+
adapter was built for — classify a REAL structural divergence, not a
3662+
hand-built one — surfaced a §10.1 case 5: a real, user-visible verdict/
3663+
advisory movement that fits none of the three declared classes in the
3664+
P-037 proposal's G-T2b (§7) or this note's own §10.8 framing of them.
3665+
3666+
**The measurement.** Three fixtures, built deliberately around a NON-
3667+
static, non-literal `bool` guard argument (a direct call to a genuinely
3668+
conditional callee, the same callee reached through a bare-forward
3669+
wrapper, and that wrapper followed by a defensive dispose), run through
3670+
the real pipeline at three states: a scratch worktree at the pre-B2.1a
3671+
instrument head (this section's own commit lineage), the current
3672+
instrument head's own extractor/`mos.rs` (post-B2.1a, still guard-
3673+
unaware — `mos.rs`/`lower.rs`/`dump.rs` are byte-identical between these
3674+
two states; only `frontend/roslyn/OwnSharp.Extractor/Program.cs` moved
3675+
under B2.1a), and the held R1 treatment. Measured, not assumed (§10's own
3676+
discipline throughout): the wrapper's own summary transfer walks `must`
3677+
(state A — the pre-B2.1a extractor fabricates an unconditional release
3678+
at the delegating call site) -> `no` (state B — B2.1a's own EmitFlowExpr
3679+
change degrades that fabrication to a bare `use`, and legacy's `no` is
3680+
frozen there today, since `ownlang/ownir.py`'s own derivation is
3681+
byte-identical across all three states) -> a real `Split(no,must)`/
3682+
`Split(must,no)` collapsing to `may` (state C, R1's own guarded solver).
3683+
The verdict moves in lockstep: a real `OWN001` (states A and B) becomes a
3684+
`0 findings + OWN051` advisory (state C) — `own-cli`'s own SARIF marks
3685+
`OWN001` `warning` and `OWN051` `note`, so this is visible even at
3686+
`p037_verdict_snapshot.py`'s default `--level verdict` filter, not only
3687+
under `--level all`. The direct-call fixture additionally proved the
3688+
existing (method,param) WITNESS schema cannot even represent the
3689+
divergence at its own call site: the caller acquires its resource as a
3690+
LOCAL, never receives it as a parameter, so no `dump_summaries` row for
3691+
that method exists at all — the movement is real (the same verdict
3692+
transition, same three states) but structurally invisible to
3693+
`derive_document_witnesses`, which walks `summaries[].params[]`.
3694+
3695+
**Kernel theorem vs. composed pipeline — kept as two separate claims, on
3696+
purpose.** G-T2a/G-T2b (proposal §7) are proofs about the relationship
3697+
between the guarded lfp system and `_build_skeletons`'s derivation FROM
3698+
WHATEVER RAW BODY OPS IT IS HANDED. Nothing about this finding moves
3699+
K11/K11' or their `formal/p037-kernel` mechanization, and no hand-derived
3700+
row in the proposal's §8 stops holding — the kernel theorem is not
3701+
rewritten, because its premises still hold exactly where it states them.
3702+
What was false is a SEPARATE, later claim layered on top of it: that
3703+
diffing the collapsed view against the real, composed pipeline's golden
3704+
dumps — extractor facts as B2.1a actually changed them, feeding both
3705+
derivations — lands in exactly those three classes and nothing else.
3706+
B2.1a's own EmitFlowExpr change is precisely a movement in WHICH raw body
3707+
op `_build_skeletons` is handed for a delegating call, for both engines at
3708+
once — a variable the kernel theorem's own statement, quantified over
3709+
"today's derivation" reading whatever op the extractor already produced,
3710+
never modeled. This is the same distinction `docs/evidence/
3711+
p037-b-epoch.json`'s own `b1_f2_f3b_delegation_architecture` note already
3712+
draws between the raw-fact layer's authorization (`facts_expectation`) and
3713+
the semantic classification layered on top of an authorized fact move
3714+
(APPLICATION_REFINEMENT/SUMMARY_REFINEMENT/LEGACY_HONESTY/UNCLASSIFIED) —
3715+
extended here to name the fourth, newly-authorized member of that second
3716+
list.
3717+
3718+
**CONDITIONALITY_HONESTY, the fourth declared class.** Legacy collapsed a
3719+
genuinely conditional callee to one lattice extreme (`no` or `must`,
3720+
whichever the raw fact handed to it implied); the guarded solver now
3721+
honestly recovers the real `Split(no,must)` (either orientation); an
3722+
unselected call site collapses it to `may` because the branch outcome is
3723+
genuinely unresolved there. `may` is `<= no` in neither direction and
3724+
`<= must` in neither direction (the lattice of §3), so this is provably,
3725+
structurally never SUMMARY_REFINEMENT (which requires the guarded value
3726+
strictly below legacy) regardless of which lattice extreme legacy happened
3727+
to pick — checked both ways in `scripts/p037_b_classifier.py`'s own
3728+
selftest (`conditionality-honesty-positive-legacy-no` and its
3729+
`-legacy-must-twin`). It carries no static selection (`kind:"param"`/
3730+
`"var"` in the real extracted `guarded_facts`, never `bool_const`, so
3731+
`classify_guard_call_arg` never produces `ConstPos`/`ConstNeg` for it),
3732+
so it is never APPLICATION_REFINEMENT; `collapsed` is `may`, never
3733+
`unknown`, so class 3's own shape does not match. The precision LOSS
3734+
relative to whichever extreme legacy chose is a conditionality-HONESTY
3735+
GAIN, the same "narrower claim, more honest" shape class 3 already
3736+
established for `unknown`, landing at a different, previously
3737+
unrepresentable point of the lattice. A SEPARATE, distinctly-typed
3738+
CALL-SITE witness (not a variant of the (method,param) SUMMARY witness)
3739+
represents the direct-call shape a real caller-local resource produces,
3740+
classified into the identical four-class vocabulary.
3741+
3742+
**Case-5 discipline followed, not shortcut.** Per §10.1, this is
3743+
unambiguously case 5 ("requires new semantics ... STOP: explicit contract
3744+
amendment before implementation continues"), never cases 1-4: it is not an
3745+
implementation defect (the R1 solver's Cells/Selection/apply() machinery
3746+
was independently proven correct for exactly this shape before this
3747+
finding, and stays byte-identical throughout this amendment); not a proof-
3748+
boundary gap (no unrecorded Kani assumption is implicated); not a shape-
3749+
census gap (the raw fact shape — a `kind:"param"`, non-const boolean
3750+
guard argument — was already known vocabulary); not a missing test alone
3751+
(the gap is in the declared semantic contract itself, not merely in
3752+
coverage of it). The amendment therefore lands as: (1) the fourth class in
3753+
`scripts/p037_b_classifier.py`, with the narrow structural predicate above
3754+
and hostile negatives proving it cannot be reached by an uncond shape, a
3755+
non-`{no,must}` cell pair, a statically-selected site, or the pre-existing
3756+
class-3 shape; (2) the call-site witness kind, frozen (schema, validator,
3757+
classifier branch, synthetic and real-measured tests) with no production
3758+
emitter wired yet — the same "contract before implementation" B1 already
3759+
used for the original three classes; (3) `p037_verdict_snapshot.py`'s
3760+
comparison contract extended to consume a frozen, optional
3761+
`call_site_witnesses` field (present on no snapshot recorded before this
3762+
amendment), reclassifying every witness itself rather than trusting a
3763+
recorded verdict, excusing exactly the `(line, code, level)` keys a
3764+
CLOSED-classified witness names and never the rest of a file's own diff.
3765+
Zero bytes of `mos.rs`/`lower.rs`/`dump.rs`/the extractor/`ownlang/` move
3766+
under this amendment; `p037_b_production_diff_gate.py` and the extractor's
3767+
own diff gate both report IDENTICAL against this section's own commit.
3768+
3769+
**Instrument consequence, the same rule §10.8's own corrections already
3770+
established.** `scripts/p037_b_classifier.py`, `scripts/p037_mos_snapshot.
3771+
py`, `scripts/p037_verdict_snapshot.py` and `scripts/p037_evidence_b.py`
3772+
are `INSTRUMENT_PATHS` entries with no carve-out (`scripts/
3773+
p037_evidence_b.py`'s own `INSTRUMENT_CARVE_OUTS` names only `mos.rs`/
3774+
`lower.rs`/`dump.rs`/the extractor). This amendment touches three of the
3775+
four, so `instrument_identity` moves, exactly like every prior B1-F1/
3776+
B1-F2/B1-F2-F2/B1-F2-F4/B1-F2-F4-R1/B1-F2-F4-R2 correction already forced.
3777+
The prior `T_B`/`R_B` are SUPERSEDED, not rewritten or invalidated
3778+
retroactively — they were honest evidence of what the instrument, as it
3779+
stood, actually measured. Built on the pre-B2.1a instrument head named in
3780+
this amendment's own commit (never on top of B2.1a, so the eventual
3781+
after-measurement still exercises B2.1a as its own, separately-authorized
3782+
treatment step, per the order this section's own title states), so that
3783+
after a fresh T_B/R_B retake, the sequence resumes as: new instrument/R_B
3784+
-> B2.1a extractor treatment (replayed) -> the held B2.1b/c-R1 treatment
3785+
(replayed, not reimplemented from memory — the working diff is preserved
3786+
separately) -> B_after. The held R1 treatment is not discarded by this
3787+
finding; the measurement in this section is, if anything, a working proof
3788+
of its own honesty — at every one of the three states above, the engine
3789+
either claimed a definite consume/borrow it could not support or genuinely
3790+
lost track of the obligation; only the R1 state declines to claim more
3791+
than it knows and says so via `OWN051`, the load-bearing distinction
3792+
`docs/evidence/p037-b-epoch.json`'s own class-3 framing already drew for
3793+
`unknown`, now shown to hold one lattice point further out.
3794+
3795+
**Pre-T_B instrument-closure gate (owner review).** Naming T_B on the
3796+
amendment above alone would have frozen an instrument with no real capture
3797+
path for the call-site witness -- a thermometer with no wire attached, and
3798+
any future B2.1b/c-R1 replay would have had to edit the just-frozen
3799+
instrument again to attach one, exactly the instrument/treatment collision
3800+
B1-F2/B1-F2-F2/B1-F2-F4/B1-F2-F4-R2 each already found and fixed in other
3801+
shapes. Closed before T_B, not after: the transport is SARIF
3802+
`properties.p037_call_site_witness` (own-cli's own qualified,
3803+
already-consumed SARIF surface -- `own-shadow-engine` is explicitly excluded,
3804+
being #260's dev oracle, never wired into production); `p037_verdict_
3805+
snapshot.py` reads/validates/stores it unconditionally today (schema bumped
3806+
to `/4`, fail-closed on absence/bad version/malformed witness); populating
3807+
it for real needs `verdict.rs`/`render.rs` (both still frozen) to gain a
3808+
call-site-carrying field, PREREGISTERED here as a separate, later boundary
3809+
amendment, not assumed or implemented now. A second review finding, in the
3810+
same pass: the original design let a witness NAME the diagnostic key(s) it
3811+
explained, trusted at face value -- a small permission system that could
3812+
let a structurally valid witness excuse an unrelated diagnostic merely by
3813+
naming it. Replaced with observation binding: the expected signature is
3814+
DERIVED from the witness's own semantic fields (`lowered=="plain"` implies
3815+
`OWN051`/`note` at exactly its own `site.line`) and independently confirmed
3816+
against the REAL captured SARIF message text, never against a claim; the
3817+
before-side key is derived and confirmed the same way at
3818+
`resource_acquire_site`. `docs/evidence/p037-b-epoch.json`'s own amendment
3819+
entry carries the full transport schema, the frozen-file finding, and an
3820+
explicitly un-resolved open question this same review raised: G-V4's
3821+
mutated-guard fixture (`Guarded.Outer`, uncond shape, correctly outside this
3822+
class's predicate) still needs its own resolution before any B_after take
3823+
that includes it -- flagged, not deferred.

‎docs/proposals/P-037-guarded-effect-summaries.md‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,65 @@ branch-sensitive machinery D1/D7 already built (`_definite_release`,
495495
implementation or of this contract, never a fourth class by fiat; and a
496496
class-3 difference that changes a verdict is a defect, not a refinement.
497497

498+
- **Amendment (post-B1, the CONDITIONALITY_HONESTY finding) — this last
499+
claim was FALSE, and the falsification does not touch G-T2a/G-T2b's own
500+
proofs.** Measured directly (three fixtures built around a non-static,
501+
non-literal `bool` guard argument — a direct call, a bare-forward wrapper,
502+
and the same wrapper with a defensive dispose after it — run through the
503+
real pipeline at three states: pre-B2.1a, post-B2.1a-pre-B2.1b/c, and the
504+
B2.1b/c-R1 treatment): a real, user-visible verdict/advisory movement
505+
exists that fits none of the three classes above. Two levels, kept
506+
separate on purpose:
507+
- **The kernel theorem itself is untouched.** G-T2a/G-T2b are proofs about
508+
the relationship between the guarded lfp system and `_build_skeletons`'s
509+
derivation FROM WHATEVER RAW BODY OPS IT IS HANDED — they say nothing
510+
about where those ops come from, and nothing in K11/K11′ or their formal-
511+
kernel mechanization moves. Every hand-derived row in §8 is still exactly
512+
as proven.
513+
- **The "exactly the three classes, and nothing else" claim above is a
514+
claim about the COMPOSED, real pipeline — extractor raw facts as
515+
actually produced today feeding both derivations — and THAT is what the
516+
counterexample falsifies.** #304's own later B2.1a step (EmitFlowExpr:
517+
an interprocedural call recognized as consuming its argument now emits
518+
`use(var, line)` where it used to emit an unconditional `release(var,
519+
line)`, so a plain flow-insensitive fabrication cannot misreport a
520+
conditional callee as an unconditional one) changes WHICH raw body op
521+
`_build_skeletons` is handed for a delegating call site, for BOTH
522+
engines — a transformation this proposal's own G-T2b proof, stated
523+
against "today's derivation" reading whatever op the extractor already
524+
produced, never modeled as a variable at all. Composed with the guarded
525+
solver genuinely reconstructing the delegating call's real
526+
`Split(no,must)`/`Split(must,no)` shape, an UNSELECTED call site collapses
527+
that recovered split to `may` (G-A1: plain, OWN051) — and legacy (which
528+
now sees only a bare `use`, or, before B2.1a, a body op that was itself
529+
already fabricated to a single extreme) collapsed the SAME conditional
530+
callee to `no` or `must`. `may` is `≰ no` and `≰ must` in this proposal's
531+
own lattice (§3), so this is provably never summary refinement (which
532+
requires the guarded value strictly *below* legacy); it carries no
533+
static selection, so it is not application refinement; and `collapsed`
534+
is `may`, not `unknown`, so class 3's own shape does not match either.
535+
- **CONDITIONALITY_HONESTY, a fourth declared class**, added by amendment,
536+
not by classifier fiat (`scripts/p037_b_classifier.py`'s own comment on
537+
`CLOSED_CLASSES` carries the same reasoning as here): legacy collapsed a
538+
genuinely conditional callee to one lattice extreme (`no` or `must`,
539+
whichever the raw fact it was handed implied); the guarded solver now
540+
honestly recovers the real `Split(no,must)` (either orientation); an
541+
unselected site collapses it to `may` because the branch outcome is
542+
genuinely unresolved there — a precision LOSS relative to either
543+
extreme that is a conditionality-HONESTY gain, exactly the same
544+
"narrower claim, more honest" shape class 3 already established for
545+
`unknown`, at a different point in the lattice. A call site with no
546+
(method,param) summary coordinate of its own (the direct-call fixture:
547+
the resource is a caller-local, never a parameter) cannot even be
548+
represented by the SUMMARY diffing this section describes at all —
549+
the classifier's separate call-site witness kind exists for exactly
550+
that shape; see its own module docstring point 5.
551+
- The corrected claim: diffing the collapsed view against today's golden
552+
dumps isolates the differences into exactly the **four** declared
553+
classes above, and nothing else — an implementation difference outside
554+
all four remains a defect, never a fifth class by fiat, and this
555+
amendment does not reopen that discipline.
556+
498557
## 8. Worked adversarial cases (hand-derived; the conformance seeds for #304)
499558

500559
Notation: `S = Split(g, pos, neg)`; call-site column shows the applied effect.
@@ -599,3 +658,12 @@ Acceptance for this proposal (design review, no code):
599658
**legacy-honesty difference** (guarded `unknown` for today's `may`, never
600659
verdict-changing) — entered into the #304 conformance matrix;
601660
- the walls of §9 accepted as walls.
661+
662+
This list records what THIS design review accepted, at the time it accepted
663+
it, and is not rewritten by the amendment §7 now carries: a **fourth**
664+
declared verdict-change class, **conditionality honesty** (guarded `may`
665+
recovered from a legacy `no` or `must` that had collapsed a genuinely
666+
conditional callee to one extreme, no static selection), entered the #304
667+
conformance matrix separately, by its own review (see
668+
`docs/evidence/p037-b-epoch.json`'s appended supersession entry for that
669+
review's own record) — it is not retroactively folded into this bullet list.

0 commit comments

Comments
 (0)