@@ -124,6 +124,9 @@ open import EchoLinear using
124124 ; linear≤linear
125125 ; linear≤affine
126126 ; affine≤affine
127+ ; LEcho
128+ ; degradeMode
129+ ; affine-all-equal
127130 )
128131open import EchoGraded using
129132 ( Grade
@@ -138,7 +141,12 @@ open import EchoGraded using
138141 ; residue≤forget
139142 ; forget≤forget
140143 )
141- open import EchoCharacteristic using (collapse)
144+ open import EchoCharacteristic using
145+ ( collapse
146+ ; echo-true
147+ ; echo-false
148+ ; echo-true≢echo-false
149+ )
142150open import characteristic.RoleGraded using
143151 ( RoleGEcho
144152 ; applyRole
@@ -158,6 +166,10 @@ open import characteristic.ModeGraded using
158166 ( MGEcho to ModeGEcho
159167 ; applyGrade to applyGradeM
160168 )
169+ open import characteristic.RoleModeGrade using
170+ ( applyAll
171+ ; trace-non-trivial-cell
172+ )
161173
162174------------------------------------------------------------------------
163175-- Definitions of "non-trivial" for the formal theorem
@@ -301,6 +313,45 @@ ModeGrade-no-non-identity-cell :
301313 NonIdentity modegrade-cell-action → ⊥
302314ModeGrade-no-non-identity-cell (x , px) = px refl
303315
316+ ------------------------------------------------------------------------
317+ -- n=3 — RoleModeGrade (EI-2 obligation 4, formal enumeration form)
318+ --
319+ -- The 3D construction's pairwise/triple commutations are already
320+ -- discharged in characteristic.RoleModeGrade (all by `refl`). What
321+ -- was only stated there as a prose tracker entry — that the 3D
322+ -- construction has its non-trivial cell *because* it contains the
323+ -- non-loss-only axis Role — is here promoted to the SAME formal
324+ -- shape as the n=2 exhibits above. This is the mechanical extension
325+ -- of the concrete enumeration from n=2 to n=3 (obligation 4); it
326+ -- adds no new mathematical content over RoleModeGrade, only the
327+ -- formal `PreservesDistinct` certificate and an enumeration entry.
328+ --
329+ -- The unique live triple cell is (c⊑s, linear≤linear, keep≤keep);
330+ -- `applyAll` at that cell computes to `client-to-server` (proved in
331+ -- RoleModeGrade as `trace-non-trivial-cell`), so the n=3 cell action
332+ -- preserves distinctness via the same Choreo distinguishing pair.
333+ ------------------------------------------------------------------------
334+
335+ rmg-cell-action : RoleEcho Client true → RoleEcho Server true
336+ rmg-cell-action e = applyAll c⊑s linear≤linear keep≤keep e
337+
338+ rmg-cell-action-equals-c2s :
339+ ∀ (e : RoleEcho Client true) →
340+ rmg-cell-action e ≡ client-to-server e
341+ rmg-cell-action-equals-c2s = trace-non-trivial-cell
342+
343+ RoleModeGrade-has-non-trivial-cell :
344+ PreservesDistinct rmg-cell-action
345+ RoleModeGrade-has-non-trivial-cell =
346+ rg-input₁ , rg-input₂ , rg-inputs-distinct , rmg-images-distinct
347+ where
348+ rmg-images-distinct :
349+ rmg-cell-action rg-input₁ ≢ rmg-cell-action rg-input₂
350+ rmg-images-distinct p =
351+ rg-images-distinct
352+ (trans (sym (rmg-cell-action-equals-c2s rg-input₁))
353+ (trans p (rmg-cell-action-equals-c2s rg-input₂)))
354+
304355------------------------------------------------------------------------
305356-- The recipe-non-triviality theorem (concrete form)
306357--
@@ -329,6 +380,8 @@ data ConstructionWithStatus : Set where
329380 ConstructionWithStatus
330381 mg-trivial : (NonIdentity modegrade-cell-action → ⊥) →
331382 ConstructionWithStatus
383+ rmg-non-trivial : PreservesDistinct rmg-cell-action →
384+ ConstructionWithStatus
332385
333386-- The recipe-non-triviality theorem (concrete enumeration form):
334387-- each of the three 2D constructions has the non-triviality status
@@ -342,6 +395,23 @@ recipe-non-triviality-concrete =
342395 , rm-non-trivial RoleMode-has-non-trivial-cell
343396 , mg-trivial ModeGrade-no-non-identity-cell
344397
398+ -- The recipe-non-triviality theorem extended to n=3: the three n=2
399+ -- constructions plus the 3D RoleModeGrade construction, each with
400+ -- the non-triviality status predicted by the hypothesis (non-trivial
401+ -- iff the tuple contains a non-loss-only axis; RoleModeGrade is
402+ -- non-trivial because it contains Role). This discharges EI-2
403+ -- obligation 4 in the same formal enumeration shape as the n=2 case.
404+ recipe-non-triviality-concrete-n3 :
405+ ConstructionWithStatus
406+ × ConstructionWithStatus
407+ × ConstructionWithStatus
408+ × ConstructionWithStatus
409+ recipe-non-triviality-concrete-n3 =
410+ rg-non-trivial RoleGraded-has-non-trivial-cell
411+ , rm-non-trivial RoleMode-has-non-trivial-cell
412+ , mg-trivial ModeGrade-no-non-identity-cell
413+ , rmg-non-trivial RoleModeGrade-has-non-trivial-cell
414+
345415------------------------------------------------------------------------
346416-- §<<abstract>> — Generic abstract axis machinery (partial)
347417--
@@ -359,7 +429,14 @@ recipe-non-triviality-concrete =
359429--
360430-- Status of the generic form:
361431-- * Axis record: defined.
362- -- * NonLossOnly predicate: defined.
432+ -- * NonLossOnly predicate: defined (and shown vacuous — see
433+ -- `NonLossOnly-holds-vacuously-for-Mode`).
434+ -- * ProperNonLossOnly predicate (sharpened, irreflexive): defined.
435+ -- * Choreo certified under the sharpened predicate
436+ -- (`ChoreoAxis-proper-non-loss-only`).
437+ -- * Mode loss-only under the sharpened predicate: DISCHARGED
438+ -- (`Mode-is-not-proper-non-loss-only`). This is the abstract
439+ -- obligation previously flagged open.
363440-- * Generic 2D family: requires decidable equality and a live
364441-- decoration; partial scaffolding below.
365442-- * Generic forward direction: not yet proved.
@@ -433,40 +510,209 @@ ChoreoAxis-non-loss-only =
433510 Client , Server , c⊑s , choreo-c⊑s-strict
434511
435512------------------------------------------------------------------------
436- -- Mode is loss-only at the abstract level.
437- --
438- -- The strict step linear≤affine has transport `weaken` =
439- -- collapse-to-residue, which collapses Echo collapse tt (multiple
440- -- inhabitants) to EchoR ⊤ TrivialCert tt (one inhabitant up to
441- -- TrivialCert structure). All inputs map to the same output, so
442- -- the step has no distinguishing pair.
443- --
444- -- Formalising "no distinguishing pair" requires showing that
445- -- distinct inputs map to equal outputs, which is the
446- -- collapse-residue-same property. EchoLinear has
447- -- weaken-collapses-distinction : weaken echo-true ≡ weaken echo-false
448- -- as the formal certificate. We can lift this to "Mode is not
449- -- non-loss-only" — i.e., Mode does not satisfy NonLossOnly.
450- --
451- -- However: NonLossOnly only requires the EXISTENCE of *some* strict
452- -- step with a distinguishing pair. Mode has only one strict step
453- -- (linear≤affine), and we need to show it has no distinguishing
454- -- pair. This requires examining all pairs of inputs in
455- -- LEcho linear and showing they all map to equal outputs under
456- -- weaken — which involves the universal property of LEcho linear.
457- --
458- -- This is straightforward but requires more machinery (LEcho's
459- -- definition unfolds to Echo collapse tt; collapse-to-residue's
460- -- behaviour on all such inputs; uniqueness of the residue).
461- --
462- -- Left as an open obligation in the abstract section. The concrete
463- -- forward direction above (rolegraded-cell-action,
464- -- rolemode-cell-action) does not depend on this abstract
465- -- formalisation.
513+ -- Why `Mode-is-loss-only : ¬ NonLossOnly ModeAxis` cannot be proved
514+ -- as literally stated — and the sharpening that discharges it.
515+ --
516+ -- The flagged obligation was `¬ NonLossOnly ModeAxis`. That claim is
517+ -- FALSE under the `NonLossOnly` predicate above, and the file below
518+ -- proves it false rather than papering over the gap.
519+ --
520+ -- The defect is in `IsStrict`/`NonLossOnly`: a step counts as
521+ -- "strict" merely if it carries a distinguishing pair. But the
522+ -- *reflexive* steps `m ≤m m` transport by the identity
523+ -- (`degradeMode linear≤linear e = e` definitionally), and the
524+ -- identity trivially preserves distinguishability whenever the
525+ -- decoration has ≥2 separable inhabitants. So *every* axis with a
526+ -- multi-inhabitant decoration satisfies `NonLossOnly` via a
527+ -- reflexive step — the predicate is vacuously true and does not
528+ -- discriminate loss-only axes at all. `Mode` is no exception:
529+ -- `NonLossOnly-holds-vacuously-for-Mode` below exhibits the witness
530+ -- explicitly, which is exactly why `¬ NonLossOnly ModeAxis` is
531+ -- unprovable.
532+ --
533+ -- The rigorous fix is to SHARPEN the criterion to the intended
534+ -- reading (cf. ChoreoInjective.agda: "at least one of its strict
535+ -- (non-reflexive) steps"): a *proper* strict step must move between
536+ -- DISTINCT decorations. Under that sharpened predicate
537+ -- (`ProperNonLossOnly`):
538+ --
539+ -- * Choreo still certifies (c⊑s : Client ≢ Server, distinguishing
540+ -- transport) — the positive case is not lost.
541+ -- * Mode does NOT certify: its only inter-decoration step is
542+ -- linear≤affine, whose transport `weaken` lands in `LEcho affine`
543+ -- where `affine-all-equal` forces ALL outputs equal, so no
544+ -- distinguishing pair can exist. The reflexive steps are now
545+ -- excluded by the `distinct` requirement.
546+ --
547+ -- This discharges the abstract obligation in its defensible form:
548+ -- `Mode-is-not-proper-non-loss-only`. It does NOT affect the
549+ -- terminated-negative EI-2 verdict (see TERMINATION NOTICE / the
550+ -- EI-2 STATUS banners and docs/EI2_REPORT.adoc); it removes a
551+ -- residual proof-debt comment from the abstract section and
552+ -- sharpens the underlying criterion.
553+ ------------------------------------------------------------------------
554+
555+ -- The original predicate is vacuously satisfied by Mode via the
556+ -- reflexive linear step. This is the concrete reason
557+ -- `¬ NonLossOnly ModeAxis` is FALSE (not merely "hard").
558+ ModeAxis : Axis
559+ ModeAxis = record
560+ { D = Mode
561+ ; _≤_ = _≤m_
562+ ; F = LEcho
563+ ; t = degradeMode
564+ }
565+
566+ mode-linear-reflexive-strict : IsStrict ModeAxis linear≤linear
567+ mode-linear-reflexive-strict = record
568+ { x = echo-true
569+ ; y = echo-false
570+ ; x≢y = echo-true≢echo-false
571+ ; tx≢ty = echo-true≢echo-false
572+ }
573+
574+ NonLossOnly-holds-vacuously-for-Mode : NonLossOnly ModeAxis
575+ NonLossOnly-holds-vacuously-for-Mode =
576+ linear , linear , linear≤linear , mode-linear-reflexive-strict
577+
578+ ------------------------------------------------------------------------
579+ -- Sharpened criterion: a *proper* strict step moves between DISTINCT
580+ -- decorations. This excludes reflexive identity steps, which carry
581+ -- no information-preserving transport content of their own.
466582------------------------------------------------------------------------
467583
468- -- Mode-is-loss-only : ¬ NonLossOnly ModeAxis
469- -- ^^^ open obligation; requires more LEcho machinery.
584+ record ProperlyStrict (a : Axis) {d1 d2 : Axis.D a}
585+ (le : Axis._≤_ a d1 d2) : Set where
586+ open Axis a
587+ field
588+ distinct : d1 ≢ d2
589+ x y : F d1
590+ x≢y : x ≢ y
591+ tx≢ty : t le x ≢ t le y
592+
593+ ProperNonLossOnly : Axis → Set
594+ ProperNonLossOnly a =
595+ Σ (Axis.D a) (λ d1 →
596+ Σ (Axis.D a) (λ d2 →
597+ Σ (Axis._≤_ a d1 d2) (λ le →
598+ ProperlyStrict a le)))
599+
600+ ------------------------------------------------------------------------
601+ -- The sharpening keeps the positive case: Choreo still certifies,
602+ -- now via the genuinely proper step c⊑s (Client ≢ Server).
603+ ------------------------------------------------------------------------
604+
605+ ChoreoAxis-proper-non-loss-only : ProperNonLossOnly ChoreoAxis
606+ ChoreoAxis-proper-non-loss-only =
607+ Client , Server , c⊑s , record
608+ { distinct = λ ()
609+ ; x = rg-input₁
610+ ; y = rg-input₂
611+ ; x≢y = rg-inputs-distinct
612+ ; tx≢ty = rg-images-distinct
613+ }
614+
615+ ------------------------------------------------------------------------
616+ -- The discharged obligation: Mode is loss-only under the sharpened
617+ -- (proper-step) criterion. Case analysis on the mode order:
618+ --
619+ -- * linear≤linear / affine≤affine — reflexive; `distinct` is
620+ -- `m ≡ m → ⊥`, refuted by `refl`.
621+ -- * linear≤affine — the unique inter-decoration step; its
622+ -- transport `degradeMode linear≤affine = weaken` lands in
623+ -- `LEcho affine`, where `affine-all-equal` makes every pair of
624+ -- outputs equal, contradicting `tx≢ty`.
625+ ------------------------------------------------------------------------
626+
627+ Mode-is-not-proper-non-loss-only : ProperNonLossOnly ModeAxis → ⊥
628+ Mode-is-not-proper-non-loss-only
629+ (linear , linear , linear≤linear , ps) = ProperlyStrict.distinct ps refl
630+ Mode-is-not-proper-non-loss-only
631+ (affine , affine , affine≤affine , ps) = ProperlyStrict.distinct ps refl
632+ Mode-is-not-proper-non-loss-only
633+ (linear , affine , linear≤affine , ps) =
634+ ProperlyStrict.tx≢ty ps
635+ (affine-all-equal
636+ (degradeMode linear≤affine (ProperlyStrict.x ps))
637+ (degradeMode linear≤affine (ProperlyStrict.y ps)))
638+
639+ ------------------------------------------------------------------------
640+ -- Generic forward direction (EI-2 obligation 5, FORWARD half)
641+ --
642+ -- The §<<abstract>> header above speculated that the generic forward
643+ -- direction needs decidable equality on D plus a designated "live"
644+ -- decoration. That over-estimates the requirement: once the
645+ -- criterion is stated in its sharpened (proper-step) form, the
646+ -- forward direction follows directly from `ProperlyStrict`. A
647+ -- properly-non-loss-only axis exhibits a step whose transport is a
648+ -- distinctness-preserving (hence non-identity-acting) map. No
649+ -- decidable equality and no live decoration are needed; this is a
650+ -- sharpening of the file's own meta-claim about the requirement.
651+ --
652+ -- This discharges the FORWARD half of obligation 5 generically. The
653+ -- REVERSE half (no-NLO ⇒ every cell trivial) is unaffected and
654+ -- remains walled off by needing extensionality under --safe (see the
655+ -- §<<abstract>> note and PATH A/B below). The EI-2 verdict is
656+ -- UNCHANGED: this neither reopens nor terminates EI-2 (cf. the
657+ -- TERMINATION NOTICE and docs/EI2_REPORT.adoc); it discharges a
658+ -- residual obligation in its defensible form, exactly as the
659+ -- proper-strict sharpening did for the loss-only obligation.
660+ ------------------------------------------------------------------------
661+
662+ -- Forward, bare form: a properly-non-loss-only axis has a step whose
663+ -- transport preserves distinctness (is non-trivial).
664+ ProperNonLossOnly⇒distinguishing-step :
665+ ∀ (a : Axis) → ProperNonLossOnly a →
666+ Σ (Axis.D a) (λ d1 →
667+ Σ (Axis.D a) (λ d2 →
668+ Σ (Axis._≤_ a d1 d2) (λ le →
669+ PreservesDistinct (Axis.t a le))))
670+ ProperNonLossOnly⇒distinguishing-step a (d1 , d2 , le , ps) =
671+ d1 , d2 , le ,
672+ ( ProperlyStrict.x ps
673+ , ProperlyStrict.y ps
674+ , ProperlyStrict.x≢y ps
675+ , ProperlyStrict.tx≢ty ps )
676+
677+ -- Forward, 2D-cell form: composing that distinguishing step with ANY
678+ -- second-axis step whose action on the codomain is the identity
679+ -- still yields a cell whose composed action preserves distinctness.
680+ -- The identity hypothesis is supplied POINTWISE (∀ z → gB z ≡ z) —
681+ -- which every concrete reflexive second-axis step satisfies by
682+ -- `refl` — so the proof never invokes function extensionality.
683+ generic-2cell-forward :
684+ ∀ (a : Axis) {d1 d2 : Axis.D a} (le : Axis._≤_ a d1 d2)
685+ (ps : ProperlyStrict a le)
686+ (gB : Axis.F a d2 → Axis.F a d2) →
687+ (∀ z → gB z ≡ z) →
688+ PreservesDistinct (λ w → gB (Axis.t a le w))
689+ generic-2cell-forward a le ps gB gB-id =
690+ ProperlyStrict.x ps
691+ , ProperlyStrict.y ps
692+ , ProperlyStrict.x≢y ps
693+ , λ eq → ProperlyStrict.tx≢ty ps
694+ (trans (sym (gB-id (Axis.t a le (ProperlyStrict.x ps))))
695+ (trans eq
696+ (gB-id (Axis.t a le (ProperlyStrict.y ps)))))
697+
698+ -- The concrete cells are instances of the generic forward direction:
699+ -- ChoreoAxis is properly-non-loss-only via c⊑s, and the second-axis
700+ -- contribution in the concrete n=2/n=3 cells is pointwise-identity
701+ -- (`applyGrade keep≤keep` / `applyMode linear≤linear`, both `refl`).
702+ -- This is the link between the concrete enumeration above and the
703+ -- generic statement (non-vacuity witness; no duplication of content).
704+ choreo-instantiates-generic-forward :
705+ PreservesDistinct (λ w → (λ z → z) (Axis.t ChoreoAxis c⊑s w))
706+ choreo-instantiates-generic-forward =
707+ generic-2cell-forward ChoreoAxis c⊑s
708+ (record
709+ { distinct = λ ()
710+ ; x = rg-input₁
711+ ; y = rg-input₂
712+ ; x≢y = rg-inputs-distinct
713+ ; tx≢ty = rg-images-distinct
714+ })
715+ (λ z → z) (λ z → refl)
470716
471717------------------------------------------------------------------------
472718-- Summary (prose; the formal content is above)
0 commit comments