feat: echo-search-product — bounded product (sequential) search composition#254
Merged
Conversation
…sition
Closes the last "where next" gap in EchoSearch. The original sketch
(`EchoS … f b n₁ → EchoS … g y n₂ → EchoS … (g∘f) y (n₁*n₂)`) is ill-typed —
the second search's witness is not tied to the first's output — so the
well-typed form is the PRODUCT of two independent searches over `A₁ × A₂`
with budget `n₁ * n₂`:
productEnum n₂ enum₁ enum₂ k = (enum₁ (k / n₂) , enum₂ (k % n₂))
echo-search-product : EchoS enum₁ f₁ y₁ n₁ → EchoS enum₂ f₂ y₂ n₂ →
EchoS (productEnum n₂ enum₁ enum₂) (productMap f₁ f₂) (y₁,y₂) (n₁*n₂)
The witness pairs the two step indices row-major as `k₂ + k₁*n₂`, which stays
`< n₁*n₂` exactly when `k₁<n₁, k₂<n₂` (via `+-monoˡ-<` / `*-monoˡ-≤`), and
`/n₂` / `%n₂` recover `k₁` / `k₂` (`+-distrib-/-∣ʳ` + `m*n/n≡m` + `m<n⇒m/n≡0`;
`[m+kn]%n≡m%n` + `m<n⇒m%n≡m`). The `n₁*n₂` budget provably needs this
budget-dependent pairing — a global `ℕ×ℕ↔ℕ` cannot keep
`pair (n₁-1)(n₂-1) < n₁*n₂` — hence the `/n₂` scheme and `NonZero n₂`.
`--safe --without-K`, zero postulates, structural. 3 Smoke pins; the "where
next" note marked LANDED (with the ill-typed-sketch correction). EchoSearch +
Smoke.agda + All.agda exit 0; kernel-guard PASS.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018CaSgNjNURC7ocsyjYh9We
🔍 Hypatia Security ScanFindings: 6 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": "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": "Repository has 6 non-main remote branch(es). Policy: single main branch only.",
"type": "GS007",
"file": ".",
"action": "delete_remote_branches",
"rule_module": "git_state",
"severity": "medium"
},
{
"reason": "Code scanning (Scorecard): TokenPermissionsID -- Token-Permissions -- 18 day(s) old [STALE]",
"type": "CSA001",
"file": ".github/workflows/scorecard.yml",
"action": "escalate",
"rule_module": "code_scanning_alerts",
"severity": "high"
},
{
"reason": "Code-scanning alert TokenPermissionsID (high) at .github/workflows/scorecard.yml is 18 days old (threshold: 7 days) -- overdue for remediation",
"type": "CSA003",
"file": ".github/workflows/scorecard.yml",
"action": "escalate",
"rule_module": "code_scanning_alerts",
"severity": "high"
},
{
"reason": "Code-scanning alert hypatia/code_safety/agda_postulate dismissed as 'false positive' -- ensure dismissal is documented and justified",
"type": "CSA004",
"file": "proofs/agda/EchoImageFactorizationPropPostulated.agda",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
🔍 Hypatia Security ScanFindings: 6 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": "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": "Repository has 5 non-main remote branch(es). Policy: single main branch only.",
"type": "GS007",
"file": ".",
"action": "delete_remote_branches",
"rule_module": "git_state",
"severity": "medium"
},
{
"reason": "Code scanning (Scorecard): TokenPermissionsID -- Token-Permissions -- 18 day(s) old [STALE]",
"type": "CSA001",
"file": ".github/workflows/scorecard.yml",
"action": "escalate",
"rule_module": "code_scanning_alerts",
"severity": "high"
},
{
"reason": "Code-scanning alert TokenPermissionsID (high) at .github/workflows/scorecard.yml is 18 days old (threshold: 7 days) -- overdue for remediation",
"type": "CSA003",
"file": ".github/workflows/scorecard.yml",
"action": "escalate",
"rule_module": "code_scanning_alerts",
"severity": "high"
},
{
"reason": "Code-scanning alert hypatia/code_safety/agda_postulate dismissed as 'false positive' -- ensure dismissal is documented and justified",
"type": "CSA004",
"file": "proofs/agda/EchoImageFactorizationPropPostulated.agda",
"action": "review",
"rule_module": "code_scanning_alerts",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
pushed a commit
that referenced
this pull request
Jun 21, 2026
…rdinal-contradiction flag Catches the machine ledger up to the gap-closing proofs that landed without an arc (#249 EchoReversibilityBridge, #250 EchoResidueCell, #251/#254 EchoSearch decidable+product, #252 EchoApprox Lipschitz, #257 EchoLLEncoding universal gap, #258 proof-debt variance refresh), records the cross-repo (echo-types + 007) docs-completeness audit, and flags one unresolved owner decision: main carries ordinal BH climb rungs 7 & 8 (f89a3aa, a096764) dated 2026-06-21 — the same day as the D-2026-06-21 retirement — contradicting the retirement banner. The two ordinal wiki files are deliberately left un-fixed pending that reconciliation. Disposition: both repos clean/verified, push-nothing-else. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018CaSgNjNURC7ocsyjYh9We
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.
What
Closes the last "where next" gap in
EchoSearch— product (sequential) composition of bounded searches. This is gap 3-of-3 from the proof survey (decidability #251 and Lipschitz #252 already merged).The correction
The module's original sketch —
EchoS … f b n₁ → EchoS … g y n₂ → EchoS … (g ∘ f) y (n₁ * n₂)— is ill-typed: the second search produces ag-preimage ofyover its own enumerator, with no tie to the first search's outputb, sog (f x) ≡ ydoesn't follow. The well-typed composition is the product of two independent searches:How (the row-major pairing)
The witness pairs the two step indices as
k₂ + k₁ * n₂:< n₁ * n₂:k₂ + k₁*n₂ < n₂ + k₁*n₂ = suc k₁ * n₂ ≤ n₁ * n₂(+-monoˡ-<then*-monoˡ-≤);/ n₂ ≡ k₁(+-distrib-/-∣ʳ+m*n/n≡m+m<n⇒m/n≡0) and% n₂ ≡ k₂([m+kn]%n≡m%n+m<n⇒m%n≡m).The
n₁ * n₂budget provably requires this budget-dependent pairing — a globalℕ × ℕ ↔ ℕcannot keeppair (n₁-1) (n₂-1) < n₁ * n₂— which is exactly why it divides byn₂and carriesNonZero n₂(a zero-width second dimension admits no witness anyway). That's the bijection the module deferred "to the slice that wants it".Discipline
--safe --without-K, zero postulates, structural.productMap,productEnum,echo-search-product); the "where next" note marked LANDED with the ill-typed-sketch correction.main:EchoSearch,Smoke.agda,All.agdaall exit 0;kernel-guard.shPASS (existing module — no new module).Context
This is the final gap from the proof-surface survey. With it, the echo-types proof surface is gap-free apart from the deliberately parked ordinal/fidelity ladder and the author-driven Pillar E paper.
🤖 Generated with Claude Code
https://claude.ai/code/session_018CaSgNjNURC7ocsyjYh9We
Generated by Claude Code