Skip to content

theory: EchoApprox deeper rung — separated zero-collapse + axis-1 shadow#74

Merged
hyperpolymath merged 2 commits into
mainfrom
theory/echo-approx-deeper-rung
May 20, 2026
Merged

theory: EchoApprox deeper rung — separated zero-collapse + axis-1 shadow#74
hyperpolymath merged 2 commits into
mainfrom
theory/echo-approx-deeper-rung

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Picks up two of three §7 deferrals from PR #70 in
/tmp/echo-types-exploration/axis2-approximate.md. Refs not Closes
because §7 is multi-rung and one rung (B-component +
tolerance-budget retract round-trip) stays deferred pending a
Tolerance interface 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 the
    PseudoMetric record; supplied as an explicit hypothesis at the
    lemma site (pseudo-metrics in general only guarantee dist y y ≡ zero, not the converse — making them a metric proper is an
    optional refinement the record deliberately does not bake in).
  • echo-approx-zero-collapses-strict : Separated → EchoR zero f y → Echo f y
    formalises 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 an
    approximate echo).
  • echo-shadow-iso-{to,from} — pins the §7 E6/E7: add Buchholz well-formed targets and EchoOrdinal bridge #8 obligation
    explicitly (definitional both ways: EchoR ε f y IS the
    existential Σ A (λ x → dist (f x) y ≤ ε)).
  • 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).
  • echo-strict→approx-collapse-shadow-A — round-trip under
    separation: zero-collapses-strict ∘ strict→approx ≡ id on the
    A-component, definitionally.

DESIGN-DECISION STOP — Rung C deferred

The full B-component + tolerance-budget retract round-trip
(echo-approx-comp-retract-from-to and friends) requires a
+-left-identity axiom on Tolerance (zero + ε ≡ ε, plus
right-identity for the symmetric variants).

Current shape of Tolerance

record Tolerance: Set (suc ℓ) where
  field
    Tol      : Setzero     : Tol
    _+_      : Tol  Tol  Tol
    _≤_      : Tol  Tol  Set≤-refl   :  {ε}              ε ≤ ε
    ≤-trans  :  {ε₁ ε₂ ε₃}       ε₁ ≤ ε₂  ε₂ ≤ ε₃  ε₁ ≤ ε₃
    +-mono-≤ :  {a b c d}        a ≤ b  c ≤ d  (a + c) ≤ (b + d)

No identity laws on +. Minimal interface, lets us state
echo-approx-compose; that's all it currently does.

What needs to be added

For the symmetric retract round-trip:

+-identityˡ :  {ε}  (zero + ε) ≡ ε
+-identityʳ :  {ε}  (ε + zero) ≡ ε

(, not — the round-trip is a definitional retract on the
tolerance budget, so we need a propositional equality, not just
mutual .)

Two options

(a) Extend Tolerance with the two identity-law fields.

  • Pro: minimal scaffolding; one type to thread through.
  • Con: ripples to every Tolerance instance — currently just
    EchoApproxInstance.trivialTolerance (trivial discharge), but
    consumers may grow. Makes Tolerance strictly stronger than
    the "ordered commutative-monoid-flavoured" framing in §3 of the
    axis-2 design note.

(b) Add a separate BalancedTolerance record on top of
Tolerance carrying just the identity laws.

  • Pro: additive; no interface breakage; layered/opt-in. Matches
    the design pattern of PseudoMetric (which is separately
    refined to a metric by adding Separated, not by widening the
    base record). Keeps the §3 "minimal moving parts" promise.
  • Con: an extra record name to thread through retract-round-trip
    lemmas.

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. The
analogue is PseudoMetric vs. (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 ≠ 1 would need scalar
multiplication on Tolerance — a third interface call (whether
to add it to the core record, or layer a ScalableTolerance
refinement). 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.agda adds top-level identifiers
at the trivial-pseudometric-on- instance, Smoke.agda
enumerates them in its using clause.

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.

Refs

Refs 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.agda exits 0
  • agda proofs/agda/Smoke.agda exits 0
  • No postulates / escape pragmas / funext introduced
  • All new headlines pinned in Smoke.agda via EchoApproxInstance
  • Owner decides Rung C Tolerance interface question (a vs. b)
  • After decision: implement chosen option, land full retract
    round-trip

🤖 Generated with Claude Code

hyperpolymath and others added 2 commits May 20, 2026 15:26
…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>
@hyperpolymath hyperpolymath marked this pull request as ready for review May 20, 2026 14:28
@hyperpolymath hyperpolymath merged commit 9a1a908 into main May 20, 2026
7 of 10 checks passed
@hyperpolymath hyperpolymath deleted the theory/echo-approx-deeper-rung branch May 20, 2026 14:29
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>
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 10 issues detected

Severity Count
🔴 Critical 0
🟠 High 5
🟡 Medium 5
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant