Skip to content

Commit db46298

Browse files
hyperpolymathclaude
andcommitted
characteristic/EI: discharge abstract loss-only obligation via sharpened proper-strict criterion
The obligation flagged open in RecipeNonTriviality.agda was `Mode-is-loss-only : ¬ NonLossOnly ModeAxis`. That literal claim is FALSE: the un-refined NonLossOnly counts reflexive identity steps, so it is vacuously satisfied by every multi-inhabitant axis. This proves the vacuity explicitly (NonLossOnly-holds-vacuously-for-Mode), then sharpens the criterion to the intended irreflexive reading (ProperNonLossOnly) and discharges the obligation in its defensible form: * ChoreoAxis-proper-non-loss-only -- positive case retained * Mode-is-not-proper-non-loss-only -- Mode loss-only, discharged All --safe --without-K, zero postulates, zero escape pragmas; full characteristic lane typechecks. EI-2 remains [CLOSED-NEG] (terminated-negative) -- verdict unchanged. Replanted onto true origin/main (2ca3122); prior push had drifted onto PR #54's base and bundled README/MAP.adoc. This commit is the proof change only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 2ca3122 commit db46298

1 file changed

Lines changed: 140 additions & 34 deletions

File tree

proofs/agda/characteristic/RecipeNonTriviality.agda

Lines changed: 140 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ open import EchoLinear using
114114
; linear≤linear
115115
; linear≤affine
116116
; affine≤affine
117+
; LEcho
118+
; degradeMode
119+
; affine-all-equal
117120
)
118121
open import EchoGraded using
119122
( Grade
@@ -128,7 +131,12 @@ open import EchoGraded using
128131
; residue≤forget
129132
; forget≤forget
130133
)
131-
open import EchoCharacteristic using (collapse)
134+
open import EchoCharacteristic using
135+
( collapse
136+
; echo-true
137+
; echo-false
138+
; echo-true≢echo-false
139+
)
132140
open import characteristic.RoleGraded using
133141
( RoleGEcho
134142
; applyRole
@@ -349,7 +357,14 @@ recipe-non-triviality-concrete =
349357
--
350358
-- Status of the generic form:
351359
-- * Axis record: defined.
352-
-- * NonLossOnly predicate: defined.
360+
-- * NonLossOnly predicate: defined (and shown vacuous — see
361+
-- `NonLossOnly-holds-vacuously-for-Mode`).
362+
-- * ProperNonLossOnly predicate (sharpened, irreflexive): defined.
363+
-- * Choreo certified under the sharpened predicate
364+
-- (`ChoreoAxis-proper-non-loss-only`).
365+
-- * Mode loss-only under the sharpened predicate: DISCHARGED
366+
-- (`Mode-is-not-proper-non-loss-only`). This is the abstract
367+
-- obligation previously flagged open.
353368
-- * Generic 2D family: requires decidable equality and a live
354369
-- decoration; partial scaffolding below.
355370
-- * Generic forward direction: not yet proved.
@@ -423,40 +438,131 @@ ChoreoAxis-non-loss-only =
423438
Client , Server , c⊑s , choreo-c⊑s-strict
424439

425440
------------------------------------------------------------------------
426-
-- Mode is loss-only at the abstract level.
427-
--
428-
-- The strict step linear≤affine has transport `weaken` =
429-
-- collapse-to-residue, which collapses Echo collapse tt (multiple
430-
-- inhabitants) to EchoR ⊤ TrivialCert tt (one inhabitant up to
431-
-- TrivialCert structure). All inputs map to the same output, so
432-
-- the step has no distinguishing pair.
433-
--
434-
-- Formalising "no distinguishing pair" requires showing that
435-
-- distinct inputs map to equal outputs, which is the
436-
-- collapse-residue-same property. EchoLinear has
437-
-- weaken-collapses-distinction : weaken echo-true ≡ weaken echo-false
438-
-- as the formal certificate. We can lift this to "Mode is not
439-
-- non-loss-only" — i.e., Mode does not satisfy NonLossOnly.
440-
--
441-
-- However: NonLossOnly only requires the EXISTENCE of *some* strict
442-
-- step with a distinguishing pair. Mode has only one strict step
443-
-- (linear≤affine), and we need to show it has no distinguishing
444-
-- pair. This requires examining all pairs of inputs in
445-
-- LEcho linear and showing they all map to equal outputs under
446-
-- weaken — which involves the universal property of LEcho linear.
447-
--
448-
-- This is straightforward but requires more machinery (LEcho's
449-
-- definition unfolds to Echo collapse tt; collapse-to-residue's
450-
-- behaviour on all such inputs; uniqueness of the residue).
451-
--
452-
-- Left as an open obligation in the abstract section. The concrete
453-
-- forward direction above (rolegraded-cell-action,
454-
-- rolemode-cell-action) does not depend on this abstract
455-
-- formalisation.
441+
-- Why `Mode-is-loss-only : ¬ NonLossOnly ModeAxis` cannot be proved
442+
-- as literally stated — and the sharpening that discharges it.
443+
--
444+
-- The flagged obligation was `¬ NonLossOnly ModeAxis`. That claim is
445+
-- FALSE under the `NonLossOnly` predicate above, and the file below
446+
-- proves it false rather than papering over the gap.
447+
--
448+
-- The defect is in `IsStrict`/`NonLossOnly`: a step counts as
449+
-- "strict" merely if it carries a distinguishing pair. But the
450+
-- *reflexive* steps `m ≤m m` transport by the identity
451+
-- (`degradeMode linear≤linear e = e` definitionally), and the
452+
-- identity trivially preserves distinguishability whenever the
453+
-- decoration has ≥2 separable inhabitants. So *every* axis with a
454+
-- multi-inhabitant decoration satisfies `NonLossOnly` via a
455+
-- reflexive step — the predicate is vacuously true and does not
456+
-- discriminate loss-only axes at all. `Mode` is no exception:
457+
-- `NonLossOnly-holds-vacuously-for-Mode` below exhibits the witness
458+
-- explicitly, which is exactly why `¬ NonLossOnly ModeAxis` is
459+
-- unprovable.
460+
--
461+
-- The rigorous fix is to SHARPEN the criterion to the intended
462+
-- reading (cf. ChoreoInjective.agda: "at least one of its strict
463+
-- (non-reflexive) steps"): a *proper* strict step must move between
464+
-- DISTINCT decorations. Under that sharpened predicate
465+
-- (`ProperNonLossOnly`):
466+
--
467+
-- * Choreo still certifies (c⊑s : Client ≢ Server, distinguishing
468+
-- transport) — the positive case is not lost.
469+
-- * Mode does NOT certify: its only inter-decoration step is
470+
-- linear≤affine, whose transport `weaken` lands in `LEcho affine`
471+
-- where `affine-all-equal` forces ALL outputs equal, so no
472+
-- distinguishing pair can exist. The reflexive steps are now
473+
-- excluded by the `distinct` requirement.
474+
--
475+
-- This discharges the abstract obligation in its defensible form:
476+
-- `Mode-is-not-proper-non-loss-only`. It does NOT affect the
477+
-- terminated-negative EI-2 verdict (see TERMINATION NOTICE / the
478+
-- EI-2 STATUS banners and docs/EI2_REPORT.adoc); it removes a
479+
-- residual proof-debt comment from the abstract section and
480+
-- sharpens the underlying criterion.
481+
------------------------------------------------------------------------
482+
483+
-- The original predicate is vacuously satisfied by Mode via the
484+
-- reflexive linear step. This is the concrete reason
485+
-- `¬ NonLossOnly ModeAxis` is FALSE (not merely "hard").
486+
ModeAxis : Axis
487+
ModeAxis = record
488+
{ D = Mode
489+
; _≤_ = _≤m_
490+
; F = LEcho
491+
; t = degradeMode
492+
}
493+
494+
mode-linear-reflexive-strict : IsStrict ModeAxis linear≤linear
495+
mode-linear-reflexive-strict = record
496+
{ x = echo-true
497+
; y = echo-false
498+
; x≢y = echo-true≢echo-false
499+
; tx≢ty = echo-true≢echo-false
500+
}
501+
502+
NonLossOnly-holds-vacuously-for-Mode : NonLossOnly ModeAxis
503+
NonLossOnly-holds-vacuously-for-Mode =
504+
linear , linear , linear≤linear , mode-linear-reflexive-strict
505+
506+
------------------------------------------------------------------------
507+
-- Sharpened criterion: a *proper* strict step moves between DISTINCT
508+
-- decorations. This excludes reflexive identity steps, which carry
509+
-- no information-preserving transport content of their own.
510+
------------------------------------------------------------------------
511+
512+
record ProperlyStrict (a : Axis) {d1 d2 : Axis.D a}
513+
(le : Axis._≤_ a d1 d2) : Set where
514+
open Axis a
515+
field
516+
distinct : d1 ≢ d2
517+
x y : F d1
518+
x≢y : x ≢ y
519+
tx≢ty : t le x ≢ t le y
520+
521+
ProperNonLossOnly : Axis Set
522+
ProperNonLossOnly a =
523+
Σ (Axis.D a) (λ d1
524+
Σ (Axis.D a) (λ d2
525+
Σ (Axis._≤_ a d1 d2) (λ le
526+
ProperlyStrict a le)))
527+
528+
------------------------------------------------------------------------
529+
-- The sharpening keeps the positive case: Choreo still certifies,
530+
-- now via the genuinely proper step c⊑s (Client ≢ Server).
531+
------------------------------------------------------------------------
532+
533+
ChoreoAxis-proper-non-loss-only : ProperNonLossOnly ChoreoAxis
534+
ChoreoAxis-proper-non-loss-only =
535+
Client , Server , c⊑s , record
536+
{ distinct = λ ()
537+
; x = rg-input₁
538+
; y = rg-input₂
539+
; x≢y = rg-inputs-distinct
540+
; tx≢ty = rg-images-distinct
541+
}
542+
543+
------------------------------------------------------------------------
544+
-- The discharged obligation: Mode is loss-only under the sharpened
545+
-- (proper-step) criterion. Case analysis on the mode order:
546+
--
547+
-- * linear≤linear / affine≤affine — reflexive; `distinct` is
548+
-- `m ≡ m → ⊥`, refuted by `refl`.
549+
-- * linear≤affine — the unique inter-decoration step; its
550+
-- transport `degradeMode linear≤affine = weaken` lands in
551+
-- `LEcho affine`, where `affine-all-equal` makes every pair of
552+
-- outputs equal, contradicting `tx≢ty`.
456553
------------------------------------------------------------------------
457554

458-
-- Mode-is-loss-only : ¬ NonLossOnly ModeAxis
459-
-- ^^^ open obligation; requires more LEcho machinery.
555+
Mode-is-not-proper-non-loss-only : ProperNonLossOnly ModeAxis
556+
Mode-is-not-proper-non-loss-only
557+
(linear , linear , linear≤linear , ps) = ProperlyStrict.distinct ps refl
558+
Mode-is-not-proper-non-loss-only
559+
(affine , affine , affine≤affine , ps) = ProperlyStrict.distinct ps refl
560+
Mode-is-not-proper-non-loss-only
561+
(linear , affine , linear≤affine , ps) =
562+
ProperlyStrict.tx≢ty ps
563+
(affine-all-equal
564+
(degradeMode linear≤affine (ProperlyStrict.x ps))
565+
(degradeMode linear≤affine (ProperlyStrict.y ps)))
460566

461567
------------------------------------------------------------------------
462568
-- Summary (prose; the formal content is above)

0 commit comments

Comments
 (0)