theory: EchoApprox composition rung — first slice (retract direction)#70
Merged
Merged
Conversation
Extends `proofs/agda/EchoApprox.agda` with the first slice of the axis-2 composition rung from the design note (§7 obligations 2 + 6, plus the canonical-split retract direction). Obligations landed: * `echo-strict→approx` (§7 #2) — general strict ⇒ zero-tolerance approximate. Generalises `echo-approx-intro` from own-fibre points (`f x`) to arbitrary `y` reached via a strict echo `(x, p : f x ≡ y)`. One extra `subst` along `p` over the existing `dist-self` path. * `echo-approx-comp-sound` (§7 #6) — sound RHS-to-LHS direction of the retract shape from `composition.md` §Q3 / axis-2 design note §5. Unpacks the existential and calls `echo-approx-compose`. * `echo-approx-comp-retract-to` — canonical-split LHS → RHS-Σ section of the retract: picks `b := f x`, `ε₁ := zero`, `ε₂ := ε`. Uses `echo-approx-intro` for the inner echo and the original bound for the outer. * `echo-approx-comp-retract-A` — A-component round-trip `proj₁ ∘ sound ∘ retract-to ≡ proj₁`, proved by `refl`. Witnesses the retraction direction holding definitionally on the A-component, as the design note (§5) predicts. Obligations deferred (out of scope for this rung): * §7 #7 zero-collapse under separation (`Separated → EchoR zero f y → Echo f y`) — needs a separation predicate on the pseudo-metric record that callers can opt into. * §7 #8 axis-1 shadow agreement — cross-axis classification, separate rung. * Full retract B-component and tolerance-budget round-trip — needs a `+`-left-identity axiom on `Tolerance` (`zero + ε ≡ ε`) which the current record does not supply. Adding it is a separate decision (it commits the carrier to a left-unital monoid, not just an ordered-+-monotone-monoid). * Lipschitz generalisation (`L_g ≠ 1`) — needs scalar multiplication on `Tol`. Docs updated: * `docs/echo-types/composition.md` §Q3 — promoted from "entirely speculative" to landed-retract-shape with the deferred items called out. * `docs/echo-types/roadmap.md` — new "landed" entry for the composition rung first slice. Invariants preserved: `--safe --without-K`, no postulates, no escape pragmas, funext untouched. `Smoke.agda` already pins `module Approx` following the existing convention (per-lemma pins inside parameterised modules require instantiation, which the project does not do for EchoApprox). Build: `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/All.agda` and `... Smoke.agda` both exit 0. Refs `docs/echo-types/roadmap.md` Axis 2 entry. Refs `docs/echo-types/composition.md` §Q3. 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
…dule (#71) ## Summary Closes a silent violation of the CLAUDE.md "Working rules" invariant — *"Every headline theorem must be pinned in `Smoke.agda` via `using` clause"* — for parameterised modules. `EchoApprox.Approx` lemmas could not be named in `Smoke.agda` until *some* `PseudoMetric` was supplied, so the invariant has been quietly skipped for every `echo-approx-*` and `echo-strict→approx` lemma. PR #70 (Lane C of the multi-lane swarm) added the retract-direction lemmas (`echo-approx-comp-sound`, `echo-approx-comp-retract-to`, `echo-approx-comp-retract-A`) but, following existing convention, left them unpinned for the same reason. This PR closes the gap with the smallest, most honest possible instance. **Instance chosen:** the trivial / collapse-to-strict pseudometric on the unit carrier `⊤`. - `Tol := ⊤`, `zero := tt`, `_+_ := λ _ _ → tt` - `_≤_ := λ _ _ → ⊤` - `dist := λ _ _ → tt` on `B := ⊤` Every order / monotonicity / triangle obligation discharges to `tt`. Every approximate echo collapses to `Σ A (λ _ → ⊤)`, so each pinned lemma is a proof-of-life sanity check that the parameterised module's term is well-typed at *some* instance — exactly the hygiene contract the invariant asks for. No new mathematical content. When a genuine metric instance lands in the repo, the per-lemma pins below can be re-pointed at it (this is option 1 of two candidates considered; option 2, a discrete metric over `Bool`, adds nothing for the pinning purpose). ## Headlines now pinned in `Smoke.agda` (9 names) | New top-level name | Underlying `Approx` term | |---|---| | `approx-EchoR` | `EchoR` | | `approx-intro` | `echo-approx-intro` | | `approx-strict→approx` | `echo-strict→approx` | | `approx-relax` | `echo-approx-relax` | | `approx-NonExpansive` | `NonExpansive` | | `approx-compose` | `echo-approx-compose` | | `approx-comp-sound` | `echo-approx-comp-sound` | | `approx-comp-retract-to` | `echo-approx-comp-retract-to` | | `approx-comp-retract-A` | `echo-approx-comp-retract-A` | Plus the instance constructors `trivialTolerance`, `trivialPseudoMetric`. ## Build status Verified in the parent session (a sandbox quirk in this worktree denied positional-argument `agda` invocations despite project `.claude/settings.json` allowing them; the call worked from the parent): ``` $ LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/All.agda exit: 0 $ LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/Smoke.agda exit: 0 ``` `--safe --without-K` invariants intact (Agda would have errored otherwise). No postulates, no funext, no path algebra — every field is `tt` or `refl`. ## Files - New: `proofs/agda/EchoApproxInstance.agda` (instance + 9 per-lemma re-bindings) - Modified: `proofs/agda/All.agda` (one `open import` line, keeps orphan-module-as-dead-code rule satisfied) - Modified: `proofs/agda/Smoke.agda` (per-lemma `using` clause adjacent to the existing `Approx` block) ## Refs - Refs #70 — Lane C surfaced the gap by landing retract-direction lemmas in a parameterised module. - Refs CLAUDE.md "Working rules" invariant: *"Every headline theorem must be pinned in `Smoke.agda` via `using` clause."* - Does **not** Close any issue. ## Test plan - [x] `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/All.agda` exits 0 under `--safe --without-K` (verified parent session) - [x] `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/Smoke.agda` exits 0 under `--safe --without-K` (verified parent session) - [x] No new postulates introduced - [x] No `--safe` weakening or escape pragmas - [ ] CI green on this branch Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
…tegration) (#73) ## Summary Brings the `harden/ci-flake-pin-2026-05-18` stack onto main, with three logical groupings: * **Harden foundation (P0/P1)** — closure-hole closure, external fibre triangulation against stdlib, reproducible CI-via-flake exact pin (additive verifier). These are the earlier commits on the branch; structural work, no Agda regressions. * **Pillar E expansion (commit `8a24530`)** — clears two `[EXPAND]` tags on `docs/echo-types/paper.adoc`: - **Background and notation** primer: 6 subsections (type-theoretic setting, Σ-types + identity, HoTT fibres, coeffect/graded-modality lineage, thin-poset reindexing modalities, notation summary) plus an 18-row notation table whose every symbol is sourced from a real Agda module. Explicit on the post-retraction framing. - **Related work**: 8 per-neighbour subsections (HoTT fibres, graded comonad/coeffect/QTT, lenses/optics, refinement types, setoid quotients, provenance semirings, IFC/modal type theories, synthesis). All `<<reframing-note>>` xrefs resolve. - `types-abstract.adoc`: per-neighbour related-work positioning block mirroring the paper. Abstract status remains "NOT submission-ready, pending re-review" — content alignment only. * **Licence sweep (commit `2e78761`)** — collapses the `PMPL-1.0-or-later` SPDX identifier to `MPL-2.0` per owner direction 2026-05-20. 29 source/config files swept; README badge updated; `stapeln.toml` + `arghda-core/Cargo.toml` license fields; new `docs/PMPL-NARRATIVE.adoc` records the cultural/discipline overlay PMPL represented (no legal effect change — MPL-2.0 was already the lawyer-confirmed operative legal effect). ## Reconciliation needed before merge `origin/main` has advanced by 7 PRs (#64–#70) since this branch's last merge from main: * #64–#66 bridge work (CNO Agda↔Coq↔Lean4 correspondence, EchoTropical correspondence appendix, EchoJanusBridge OpKind mirror — substantive `EchoJanusBridge.agda` +221 / `EchoApprox.agda` +132) * #67 docs: rule out 2-categorical shape + roadmap credits * #68 theory: Axis 8 graded access modality (new `EchoAccess.agda`, 262 lines) * #69 theory: AntiEcho thin slice (new `AntiEcho.agda`, 93 lines) * #70 theory: EchoApprox composition rung first slice **Expected conflicts** (deliberate, owner-resolved): * `paper.adoc` — this PR adds Background primer + Related work; parallel sessions may have edited adjacent sections * `types-abstract.adoc` — this PR adds a related-work block * `flake.nix` — this PR is the full harden-P1 flake; parallel sessions retained the simpler devShell flake * `.github/workflows/*.yml`, `.machine_readable/6a2/*.a2ml`, `contractiles/*.a2ml`, `stapeln.toml`, `README.md`, `arghda-core/Cargo.toml`, `Containerfile`, `EXPLAINME.adoc`, `QUICKSTART-*.adoc`, `TOPOLOGY.adoc`, `docs/echidna-design-search-2026-04-28.adoc`, `docs/echo-types/MAP.adoc`, `docs/echo-types/echo-kernel-note.adoc`, `scripts/kernel-guard.sh`, `tools/check-guardrails.sh` — licence sweep; conflicts with parallel sessions that kept PMPL headers (resolve by taking this PR's MPL-2.0) ## Test plan - [ ] CI green: governance + Agda + Hypatia scans + Scorecard - [ ] `flake.nix` `nix flake check` passes (additive verifier) - [ ] `agda proofs/agda/All.agda` and `agda proofs/agda/Smoke.agda` both exit 0 under `--safe --without-K`, zero postulates (no Agda was touched by this branch's recent commits, so this should be a verification-only step) - [ ] AsciiDoc render of `paper.adoc` — confirm all `<<reframing-note>>` xrefs resolve - [ ] `docs/PMPL-NARRATIVE.adoc` reads coherently - [ ] No remaining `PMPL`/`Palimpsest` strings outside `docs/PMPL-NARRATIVE.adoc` + the one intentional pointer in `ECOSYSTEM.a2ml` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
May 20, 2026
…dow (#74) ## 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 #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` ```agda record Tolerance ℓ : Set (suc ℓ) where field Tol : Set ℓ zero : 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: ```agda +-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 - PR #70 (retract direction) - `/tmp/echo-types-exploration/axis2-approximate.md` §7 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 - [x] `agda proofs/agda/All.agda` exits 0 - [x] `agda proofs/agda/Smoke.agda` exits 0 - [x] No postulates / escape pragmas / funext introduced - [x] 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](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
Extends
proofs/agda/EchoApprox.agdawith the first slice of theaxis-2 composition rung from the design note (drafted in
/tmp/echo-types-exploration/axis2-approximate.md, §7 obligations2 + 6, plus the canonical-split retract direction). Refs
docs/echo-types/roadmap.mdAxis 2 entry anddocs/echo-types/composition.md§Q3 — does not close either.
Obligations landed
echo-strict→approx(§7 Claude/add ordinal notation layer 9qh sf #2). General strict ⇒ zero-toleranceapproximate. Generalises
echo-approx-introfrom own-fibre pointsto arbitrary
yvia the codomain equationp : f x ≡ y. Oneextra
substalongp.echo-approx-comp-sound(§7 E5: make ν operational and add Buchholz example/smoke modules #6). Sound RHS-to-LHS directionof the retract shape from
composition.md§Q3 / design-note §5.Unpacks the existential and calls
echo-approx-compose.echo-approx-comp-retract-to. Canonical-split LHS → RHS-Σsection of the retract: picks
b := f x,ε₁ := zero,ε₂ := ε.Uses
echo-approx-introfor the inner echo, original bound forthe outer.
echo-approx-comp-retract-A. A-component round-tripproj₁ ∘ sound ∘ retract-to ≡ proj₁, proved byrefl. Theretraction direction holds definitionally on the A-component as
the design note (§5) predicts.
Obligations deferred (out of this rung)
the
PseudoMetricrecord.+-left-identity axiom onTolerance(zero + ε ≡ ε) not in thecurrent record. Adding it commits the carrier to a left-unital
monoid; deferred as a separate decision.
L_g ≠ 1) — needs scalar multiplicationon
Tol.Docs updated
docs/echo-types/composition.md§Q3 promoted from "entirelyspeculative" to landed-retract-shape with deferred items called out.
docs/echo-types/roadmap.mdadds a "landed" entry for thecomposition rung first slice.
Invariants preserved
--safe --without-KTest plan
LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/All.agdaexits 0LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/Smoke.agdaexits 0postulate, no escape pragmas, funext not importedSmoke.agdaalready pinsmodule Approxfollowing projectconvention (per-lemma pins inside parameterised modules require
instantiation, which the project does not do for
EchoApprox).