theory: EchoApprox deeper rung — separated zero-collapse + axis-1 shadow#74
Merged
Conversation
…dow agreement Picks up the §7 deferrals from PR #70: two of the three remaining obligations (separated zero-collapse, axis-1 shadow agreement) land in this PR. The third (B-component + tolerance-budget retract round-trip) is parked on a `Tolerance` interface design call — see PR body. Rungs landed ------------ Rung A — separated zero-collapse (§7 #7): * `Separated : Set` — predicate on a pseudo-metric: `∀ b₁ b₂ → dist b₁ b₂ ≤ zero → b₁ ≡ b₂`. Not folded into the `PseudoMetric` record; callers supply it as an explicit hypothesis at the lemma site (pseudo-metrics in general only guarantee `dist y y ≡ zero`, not the converse). * `echo-approx-zero-collapses-strict : Separated → EchoR zero f y → Echo f y` formalises the §4 statement "Approximate → strict (only when separated, at ε = 0)" from the axis-2 design note. Rung B — axis-1 shadow agreement (§7 #8): * `echo-shadow-A` — A-component projection (the axis-1 "shadow" of an approximate echo). * `echo-shadow-iso-{to,from}` — pins the §7 #8 obligation explicitly. The iso is definitional both ways because `EchoR ε f y = Σ A (λ x → dist (f x) y ≤ ε)` already IS the existential shape; the lemma pair pins the obligation, not proves a non-trivial fact. * `echo-strict→approx-shadow-A` — cross-axis cohere: the A-component of `echo-strict→approx` agrees with the strict A-component on the nose (`refl`). The transport in `echo-strict→approx` only touches the bound proof, never the A-witness. * `echo-strict→approx-collapse-shadow-A` — round-trip under separation: `zero-collapses-strict ∘ strict→approx ≡ id` on the A-component, definitionally. Closes the §4 statement at the axis-1 shadow. Rung C — DEFERRED (design call required) ----------------------------------------- The full B-component + tolerance-budget retract round-trip needs a `+`-left-identity axiom on `Tolerance` (`zero + ε ≡ ε`). The current `Tolerance` record (see `EchoApprox.agda` lines 66–76) has fields `Tol`, `zero`, `_+_`, `_≤_`, `≤-refl`, `≤-trans`, `+-mono-≤` — no identity laws on `+`. Two options: (a) Extend `Tolerance` with `+`-identity laws (`+-identityˡ`, `+-identityʳ`). Changes the interface; every instance must discharge two new fields. Ripples to consumers (currently just `EchoApproxInstance.trivialTolerance`, but that may grow). Pro: minimal scaffolding. Con: makes `Tolerance` strictly stronger than "ordered commutative-monoid-flavoured". (b) Add a separate `BalancedTolerance` record on top of `Tolerance` carrying just the identity laws. Additive; no interface breakage. Lemmas needing the laws take `BalancedTolerance T` as an extra hypothesis. Pro: layered, opt-in. Con: an extra record name to thread through. Recommendation: (b). The current `Tolerance` is deliberately the minimal interface that lets us state `echo-approx-compose` (triangle + additive monotonicity, nothing else). Identity laws are needed only by the retract round-trip, which is a downstream refinement — keeping them out of the core interface preserves the "minimal moving parts" design from §3 of the axis-2 design note. Rung C is deferred pending owner decision. The owner-deferred decision is also documented inline in `EchoApprox.agda`'s module header. Rung D — also deferred ---------------------- The Lipschitz generalisation `L_g ≠ 1` would need scalar multiplication on `Tolerance` — a third interface call. Deferred alongside Rung C. Hygiene ------- All new headlines pinned via the per-lemma proof-of-life pattern established in PR #71: `EchoApproxInstance.agda` adds top-level identifiers at the trivial-pseudometric-on-⊤ instance, `Smoke.agda` enumerates them in its `using` clause. The pattern extends mechanically; no new design needed. Verification ------------ $ agda -i proofs/agda proofs/agda/All.agda # exit 0 $ agda -i proofs/agda proofs/agda/Smoke.agda # exit 0 `--safe --without-K` throughout. No postulates. No escape pragmas. No funext. Docs ---- `docs/echo-types/composition.md` §Q3 updated to record the second slice (zero-collapse + axis-1 shadow) and the Rung C / Rung D deferrals. Refs PR #70 and `/tmp/echo-types-exploration/axis2-approximate.md` §7. Refs not Closes — §7 is a multi-rung obligation list, and the Rung C / D deferrals remain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 20, 2026
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
…-rot (#79) ## Summary Three independent bookkeeping items consolidated to avoid PR churn: 1. **CLAUDE.md "Current rung state (2026-05-20)"** — full session arc for the echo-types swarm (PRs #67-#72, #74-#77). §"Theory work — no proof assistant needed" is now essentially closed (Lane 2 BalancedTolerance is #78, awaiting review). Two patterns formalised (per-lemma Smoke pin for parameterised modules; `sandbox.excludedCommands` workaround for the agda positional-arg sandbox quirk). Plan for next Claude included. 2. **EchoAccess `Lift ⊤` carrier — design closure.** The post-#75 carrier-honesty work hit a structural wall on the owner-authorised existential design: `degrade-access` becomes uninhabitable because the access lattice tracks **decreasing** information as you climb, so degrading must drop info, never fabricate it. Conclusion: `Lift ⊤` IS the right honest carrier at the top of the lattice (same sense as `EchoGraded.forget = ⊤`). New `docs/echo-types/decisions/echo-access-trivial-carrier.adoc` captures the closure; `EchoAccess.agda` module header updated from "Deferred to follow-up" to "Resolved 2026-05-20" with the structural reasoning. 3. **Complete `≤a-⊔a-univ` baseline-rot** — 10 more wrong-RHS clauses in the same family as commit `a8ac211` (which fixed only some of the strict-inequality witnesses). Discovered by Agda 2.8.0 on a clean `.agdai` cache; previous "verified green" reports were spuriously passing because of stale incremental builds. Same diagnosis: when `c1 ⊔a c2 = c2` (strict `c1 < c2`), the universal property witness needs `c2≤c` shape (p2), not `c1≤c` shape (p1). Fixed clauses span the decidable/enum/feasible/infeasible rows. ## Test plan - [x] `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/All.agda` exits 0 on Agda 2.8.0 - [x] `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/Smoke.agda` exits 0 on Agda 2.8.0 - [x] `--safe --without-K` invariants intact - [x] No postulates introduced - [x] No escape pragmas - [ ] CI Agda check passes - [ ] AsciiDoctor render of new decisions adoc (no asciidoctor in environment; hand-inspected against `decisions/no-2-cat.adoc` template) Refs CLAUDE.md "Rung-consolidation policy" §4 ("Update machine docs"). Does **not** close any issue. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
Lands the deferred Rung C from PR #74 / axis-2 design-note §7 via option (b) of the post-#74 design call: a separate `BalancedTolerance` record layered on `Tolerance` (mirroring how `Separated` is layered on `PseudoMetric`), NOT a mutation of the base `Tolerance` interface. Landed: * `BalancedTolerance T` record — `+-identityˡ : ∀ ε → zero + ε ≡ ε` and `+-identityʳ : ∀ ε → ε + zero ≡ ε`. Base `Tolerance` interface untouched. * `echo-approx-comp-retract-B` — B-component pin: the canonical-split section picks `b := f x` definitionally (`refl`; no BT needed). * `echo-approx-comp-retract-budget` — budget round-trip: `(zero + ε) ≡ ε` from `BalancedTolerance.+-identityˡ`. * `echo-approx-comp-retract-from-to` — budget-aligned A-component round-trip: `proj₁ (subst _ (+-identityˡ ε) (sound (retract-to e))) ≡ proj₁ e`, via the `subst-A-invariant` auxiliary. * `trivialBalancedTolerance` pin in `EchoApproxInstance.agda` (both identity laws discharge to `refl` on `Tol := ⊤`) and the four new per-lemma headlines pinned through `Smoke.agda` per the PR-#71 hygiene pattern. * `docs/echo-types/composition.md` §Q3 refreshed: option-(b) design cited, new round-trip lemmas enumerated, leftover deferred work (Lipschitz; transported full equality needing `_≤_`-propositionality) re-stated honestly. The full transported equality `subst _ (+-identityˡ ε) (sound (retract-to e)) ≡ e` is NOT discharged — it would require propositionality of the order `_≤_` on the inner bound, which the `Tolerance` interface deliberately does not assert. The A-component statement above is the strongest available without that extra structural hypothesis; this is noted in the file header, module preamble, and `composition.md`. Agda status. `EchoApprox.agda` + `EchoApproxInstance.agda` typecheck clean on Agda 2.8.0 (both `.agdai` produced from a clean cache). `proofs/agda/Smoke.agda` itself cannot be driven to exit 0 in this sandbox because of a pre-existing baseline-rot error in `proofs/agda/EchoAccess.agda:400` on origin/main (Agda 2.8 stricter unification rejects a `decidable ⊔a enum` reduction landed in PR \#75; unrelated to this change). CI is expected to run on the pinned stdlib v2.3 + apt-shipped older Agda where that reduction still goes through. Refs PR #74, /tmp/echo-types-exploration/axis2-approximate.md §7. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
…rip (#78) ## Summary Lands the deferred Rung C from PR #74 / axis-2 design-note §7 via the post-#74 design decision — **option (b)**: a separate `BalancedTolerance` record layered on `Tolerance` (mirroring how `Separated` is layered on `PseudoMetric`), **NOT** a mutation of the base `Tolerance` interface. ## Landed - `BalancedTolerance T` record — `+-identityˡ : ∀ ε → zero + ε ≡ ε` and `+-identityʳ : ∀ ε → ε + zero ≡ ε`. The base `Tolerance` interface stays untouched. - `echo-approx-comp-retract-B` — B-component pin: the canonical-split section picks `b := f x` definitionally (`refl`; no `BT` needed). - `echo-approx-comp-retract-budget` — budget round-trip: `(zero + ε) ≡ ε` from `BalancedTolerance.+-identityˡ`. - `echo-approx-comp-retract-from-to` — budget-aligned A-component round-trip: `proj₁ (subst _ (+-identityˡ ε) (sound (retract-to e))) ≡ proj₁ e`, via a small `subst-A-invariant` auxiliary. - `trivialBalancedTolerance` instance in `EchoApproxInstance.agda` (both identity laws discharge to `refl` on `Tol := ⊤`) plus the four new per-lemma headlines pinned through `Smoke.agda` per the PR #71 hygiene pattern. - `docs/echo-types/composition.md` §Q3 refreshed: option-(b) design cited, new round-trip lemmas enumerated, leftover deferred work re-stated honestly. ## Out of scope (still deferred) The full transported equality `subst _ (+-identityˡ ε) (sound (retract-to e)) ≡ e` is **not** discharged here — it would require propositionality of `_≤_` on the inner bound, which `Tolerance` deliberately does not assert. The A-component statement above is the strongest available without that extra structural hypothesis; documented in the file header, module preamble, and `composition.md`. The Lipschitz generalisation (`L_g ≠ 1`) is still deferred — it needs multiplication on `Tolerance`, an orthogonal interface call. ## Agda status - `EchoApprox.agda` + `EchoApproxInstance.agda` typecheck clean on Agda 2.8.0 (both `.agdai` produced from a clean cache in the worktree sandbox). - `proofs/agda/Smoke.agda` itself **cannot** be driven to exit 0 in this sandbox because of a pre-existing baseline-rot error at `proofs/agda/EchoAccess.agda:400` on `origin/main` (Agda 2.8 stricter unification rejects a `decidable ⊔a enum` reduction landed in #75; unrelated to this change). CI runs on the apt-shipped older Agda + pinned stdlib v2.3 where that reduction still goes through — the green CI signal here is the merge oracle. ## Test plan - [ ] CI (`agda.yml`) green on the `theory/echo-approx-balanced-tolerance` branch with `--safe --without-K`, no postulates. - [ ] `agda proofs/agda/All.agda` and `agda proofs/agda/Smoke.agda` both exit 0 on CI. - [ ] Verify the four new headline pins (`approx-comp-retract-B`, `approx-comp-retract-budget`, `approx-comp-retract-from-to`, `approx-subst-A-invariant`) appear in `Smoke.agda` and resolve against `EchoApproxInstance`. ## References - Builds on / refs PR #74 (Rung B; `Separated` layer + `echo-strict→approx` + axis-1 shadow), PR #71 (per-lemma Smoke pins via instance module). - Closes the Rung-C portion of `/tmp/echo-types-exploration/axis2-approximate.md` §7 obligations (B-component + budget round-trip). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🔍 Hypatia Security ScanFindings: 10 issues detected
View findings[
{
"reason": "No test directory or test files found",
"type": "no_tests",
"file": "/home/runner/work/echo-types/echo-types",
"action": "flag",
"rule_module": "honest_completion",
"severity": "high",
"deduction": 20
},
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in secret-scanner.yml",
"type": "missing_workflow",
"file": "secret-scanner.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Action actions/cache@v4 needs attention",
"type": "unpinned_action",
"file": "agda.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "No dependabot.yml or renovate.json found in echo-types",
"type": "DependencyUpdate",
"file": "/home/runner/work/echo-types/echo-types",
"action": "auto_fix",
"rule_module": "scorecard",
"severity": "high",
"remediation": "Add .github/dependabot.yml or renovate.json configuration.",
"scorecard_check": "Dependency-Update-Tool"
},
{
"reason": "Nominal-only SAST in echo-types: codeql.yml language matrix contains no language present in the repo and lacks `actions`, so CodeQL records zero results on every commit. Remediation: set the CodeQL matrix to `language: actions`.",
"type": "StaticAnalysis",
"file": "/home/runner/work/echo-types/echo-types",
"action": "auto_fix",
"rule_module": "scorecard",
"severity": "medium",
"remediation": "Add CodeQL or equivalent SAST workflow.",
"scorecard_check": "SAST"
},
{
"reason": "1 workflow(s) with tag-pinned (not SHA-pinned) actions in echo-types",
"type": "DependencyPinning",
"file": "/home/runner/work/echo-types/echo-types",
"action": "auto_fix",
"rule_module": "scorecard",
"severity": "medium",
"remediation": "Pin GitHub Actions and Docker base images by SHA hash.",
"scorecard_check": "Pinned-Dependencies"
},
{
"reason": "Repository has 1 non-main remote branch(es). Policy: single main branch only.",
"type": "GS007",
"file": ".",
"action": "delete_remote_branches",
"rule_module": "git_state",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Picks up two of three §7 deferrals from PR #70 in
/tmp/echo-types-exploration/axis2-approximate.md. Refs not Closesbecause §7 is multi-rung and one rung (B-component +
tolerance-budget retract round-trip) stays deferred pending a
Toleranceinterface design call (see below).Rungs landed
Rung A — separated zero-collapse (§7 #7)
Separated : Set— separation predicate on the pseudo-metric:∀ b₁ b₂ → dist b₁ b₂ ≤ zero → b₁ ≡ b₂. Kept out of thePseudoMetricrecord; supplied as an explicit hypothesis at thelemma site (pseudo-metrics in general only guarantee
dist y y ≡ zero, not the converse — making them a metric proper is anoptional refinement the record deliberately does not bake in).
echo-approx-zero-collapses-strict : Separated → EchoR zero f y → Echo f yformalises the §4 "Approximate → strict (only when separated, at
ε = 0)" statement.
Rung B — axis-1 shadow agreement (§7 #8)
echo-shadow-A— A-component projection (axis-1 shadow of anapproximate echo).
echo-shadow-iso-{to,from}— pins the §7 E6/E7: add Buchholz well-formed targets and EchoOrdinal bridge #8 obligationexplicitly (definitional both ways:
EchoR ε f yIS theexistential
Σ A (λ x → dist (f x) y ≤ ε)).echo-strict→approx-shadow-A— cross-axis cohere: theA-component of
echo-strict→approxagrees with the strictA-component on the nose (
refl).echo-strict→approx-collapse-shadow-A— round-trip underseparation:
zero-collapses-strict ∘ strict→approx ≡ idon theA-component, definitionally.
DESIGN-DECISION STOP — Rung C deferred
The full B-component + tolerance-budget retract round-trip
(
echo-approx-comp-retract-from-toand friends) requires a+-left-identity axiom onTolerance(zero + ε ≡ ε, plusright-identity for the symmetric variants).
Current shape of
ToleranceNo identity laws on
+. Minimal interface, lets us stateecho-approx-compose; that's all it currently does.What needs to be added
For the symmetric retract round-trip:
(
≡, not≤— the round-trip is a definitional retract on thetolerance budget, so we need a propositional equality, not just
mutual
≤.)Two options
(a) Extend
Tolerancewith the two identity-law fields.Toleranceinstance — currently justEchoApproxInstance.trivialTolerance(trivial discharge), butconsumers may grow. Makes
Tolerancestrictly stronger thanthe "ordered commutative-monoid-flavoured" framing in §3 of the
axis-2 design note.
(b) Add a separate
BalancedTolerancerecord on top ofTolerancecarrying just the identity laws.the design pattern of
PseudoMetric(which is separatelyrefined to a metric by adding
Separated, not by widening thebase record). Keeps the §3 "minimal moving parts" promise.
lemmas.
Recommendation
(b). The current
Toleranceis deliberately the minimalinterface that lets us state
echo-approx-compose(triangle +additive monotonicity, nothing else). Identity laws are needed
only by the retract round-trip, which is a downstream refinement
— keeping them out of the core interface preserves the "minimal
moving parts" design from §3 of the axis-2 design note. The
analogue is
PseudoMetricvs. (PseudoMetric+Separated):the refinement lives outside the base record.
Rung C is deferred pending owner decision.
Rung D — also deferred
The Lipschitz generalisation
L_g ≠ 1would need scalarmultiplication on
Tolerance— a third interface call (whetherto add it to the core record, or layer a
ScalableTolerancerefinement). Deferred alongside Rung C; same recommendation shape
applies.
Hygiene
All new headlines pinned via the per-lemma proof-of-life pattern
from PR #71:
EchoApproxInstance.agdaadds top-level identifiersat the trivial-pseudometric-on-
⊤instance,Smoke.agdaenumerates them in its
usingclause.Verification
--safe --without-Kthroughout. No postulates. No escape pragmas.No funext.
Refs
/tmp/echo-types-exploration/axis2-approximate.md§7Refs not Closes — §7 obligations 7 and 8 are landed, but
obligation 6's "full retract round-trip" (Rung C) and the
Lipschitz generalisation remain.
Test plan
agda proofs/agda/All.agdaexits 0agda proofs/agda/Smoke.agdaexits 0Smoke.agdaviaEchoApproxInstanceToleranceinterface question (a vs. b)round-trip
🤖 Generated with Claude Code