Skip to content

Commit a04c1d9

Browse files
fix(lol/abi): make the lol-abi Idris package typecheck (#389)
## Summary First unit of bringing **standards** toward proof/RSR compliance: **making the `lol-abi` Idris package typecheck** (it previously did not build at all). `lol/` is hyperpolymath's port of Ehsaneddin Asgari's *1000Langs*; the Idris ABI modules fixed here are estate-authored (`MPL-2.0`). `idris2 --build lol-abi.ipkg` now exits 0 (pre-existing shadowing warnings only). **No `believe_me`, no holes.** ## `Layout.idr` - Every `MkStructLayout` left its erased `aligned : Divides alignment totalSize` auto-implicit to proof search, which cannot guess the quotient `k`. Supplied explicitly per layout via `{aligned = DivideBy k Refl}` (32=4·8, 24=3·8, 56=7·8, 40=5·8, 16=4·4). - `paddingFor` used `-` on `Nat` (resolves to a nonexistent `Neg Nat`) → truncating `minus`. - Removed the **unused, unsound** `alignUpCorrect` lemma: its `Refl` body asserted `n = (n div a)·a`, true only for concrete args. A correct general proof needs the division theorem (absent from Idris2 `base`); the divisibility the real layouts need is discharged per-layout by the explicit `DivideBy` witnesses. Documented as future work. ## `I18nStore.idr` - `extractLanguage` used `Data.List1.split` (wants a `List`) on a `String` → `Data.String.split`. - `LookupError` used `data X = .. | ..` with per-constructor `|||` doc comments (only valid in GADT form) → `data LookupError : Type where`. - The `CorrectStore` interface ended with a **dangling `|||` doc comment** (no method after it), breaking the block's scope so the following top-level `data LookupError` failed to register → demoted to a plain comment. ## Flagged for owner (NOT touched — license guardrail) - **`lol/proofs/theories/information_theory.agda`** is third-party-attributed (`MIT AND LicenseRef-Palimpsest-0.8`, © Ehsaneddin Asgari). It has a trivial syntax bug (illegal `where` inside `postulate`), but editing a third-party-attributed file is owner-only — **left untouched, flagged**. - **`rhodium-standard-repositories/rsr-audit.sh`** hardcodes `MIT AND Palimpsest` as the required license, contradicting the estate's current MPL-2.0-for-sole-owner policy. Updating what license the standard mandates is owner-only — **flagged, not changed**. RSR format-brittleness fixes + real gaps (`.well-known`, Justfile `validate`) will follow on this branch. > Note: the branch history carries a pre-existing merge commit (`66271d3`) not introduced by this work. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019awZjBD1qx61tvmEuEKNpn --- _Generated by [Claude Code](https://claude.ai/code/session_019awZjBD1qx61tvmEuEKNpn)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent c43aafa commit a04c1d9

3 files changed

Lines changed: 38 additions & 21 deletions

File tree

.machine_readable/REGISTRY.a2ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ name = "Consent-Aware HTTP"
171171
stream = "protocol"
172172
home = "consent-aware-http/"
173173
canonical_doc = "consent-aware-http/README.adoc"
174-
source_hash = "sha256:dbfc1d464ac7e9098d8115dda332eff832276b643bcea787a5f9b3900f09142b"
174+
source_hash = "sha256:fb2611536673928bd3ac6ac6f6097b431e2a6a6114f609674c6e9287f0c1f1e1"
175175
route = "consent headers / AI-usage boundaries for HTTP"
176176

177177
[[spec]]

lol/src/Lol/ABI/I18nStore.idr

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import Lol.ABI.PluralForm
2626
import Data.So
2727
import Data.List
2828
import Data.List1
29+
import Data.String
2930

3031
%default total
3132

@@ -150,7 +151,7 @@ lookupWithFallback lookupFn strategy reqLocale defLocale key =
150151
||| "en-US" -> "en", "zh-Hans-CN" -> "zh"
151152
public export
152153
extractLanguage : String -> String
153-
extractLanguage s = let (lang ::: _) = split (== '-') s in lang
154+
extractLanguage s = let (lang ::: _) = Data.String.split (== '-') s in lang
154155

155156
||| Convert a plural category to its CLDR string suffix.
156157
public export
@@ -213,9 +214,11 @@ interface I18nStore store => CorrectStore (store : Type) where
213214
(prf : KeyExists locale key) ->
214215
lookup st locale key = Just (guaranteedLookup st prf)
215216

216-
||| The store is monotonic: adding translations never removes existing ones
217-
||| (expressed as: if a key exists, it continues to exist)
218-
||| This is an invariant the Zig store must maintain.
217+
-- The store is monotonic: adding translations never removes existing ones
218+
-- (expressed as: if a key exists, it continues to exist). Stated as a plain
219+
-- comment, not a `|||` doc comment: a trailing doc comment with no method
220+
-- following it is dangling and breaks the interface block's scope. This
221+
-- invariant is enforced on the Zig store side, not provable generically here.
219222

220223
--------------------------------------------------------------------------------
221224
-- Error Classification
@@ -224,15 +227,15 @@ interface I18nStore store => CorrectStore (store : Type) where
224227
||| Classification of lookup failures for error reporting.
225228
||| The Zig FFI maps these to the Result enum in Types.idr.
226229
public export
227-
data LookupError
228-
= ||| The requested locale is not in the corpus at all
229-
NoSuchLocale String
230-
| ||| The locale exists but the key is not defined
231-
NoSuchKey String String
232-
| ||| The plural form variant is missing (e.g. "items.few" missing)
233-
MissingPluralForm String String PluralCategory
234-
| ||| The entire fallback chain was exhausted without finding a translation
235-
FallbackExhausted String String (List String)
230+
data LookupError : Type where
231+
||| The requested locale is not in the corpus at all
232+
NoSuchLocale : String -> LookupError
233+
||| The locale exists but the key is not defined
234+
NoSuchKey : String -> String -> LookupError
235+
||| The plural form variant is missing (e.g. "items.few" missing)
236+
MissingPluralForm : String -> String -> PluralCategory -> LookupError
237+
||| The entire fallback chain was exhausted without finding a translation
238+
FallbackExhausted : String -> String -> List String -> LookupError
236239

237240
||| Map a lookup error to the appropriate Result code for FFI transport
238241
public export

lol/src/Lol/ABI/Layout.idr

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ paddingFor : (offset : Nat) -> (alignment : Nat) -> Nat
3232
paddingFor offset alignment =
3333
if offset `mod` alignment == 0
3434
then 0
35-
else alignment - (offset `mod` alignment)
35+
else alignment `minus` (offset `mod` alignment)
3636

3737
||| Proof that alignment divides aligned size
3838
public export
@@ -45,12 +45,21 @@ alignUp : (size : Nat) -> (alignment : Nat) -> Nat
4545
alignUp size alignment =
4646
size + paddingFor size alignment
4747

48-
||| Proof that alignUp produces an aligned result.
49-
||| For any positive alignment, (alignUp s a) is divisible by a.
50-
public export
51-
alignUpCorrect : (size : Nat) -> (align : Nat) -> (align > 0) -> Divides align (alignUp size align)
52-
alignUpCorrect size align prf =
53-
DivideBy ((size + paddingFor size align) `div` align) Refl
48+
-- NOTE (2026-06-18): a general lemma
49+
-- alignUpCorrect : (size, align : Nat) -> So (align > 0)
50+
-- -> Divides align (alignUp size align)
51+
-- was removed here. It was unused, and its body asserted
52+
-- alignUp size align = (alignUp size align `div` align) * align
53+
-- via `Refl`, which only holds definitionally for *concrete* arguments, not
54+
-- symbolic ones, so the lemma did not actually typecheck. A correct general
55+
-- proof needs the division theorem (n = d * (n `div` d) + n `mod` d), which
56+
-- Idris2 `base` does not export (only the `divNatNZ`/`modNatNZ`/`divmod'`
57+
-- functions exist, with no accompanying equational lemma), so it would have to
58+
-- be hand-proved from `Data.Nat.divmod'`. The divisibility that the concrete
59+
-- struct layouts actually rely on is discharged per-layout below by the
60+
-- explicit `{aligned = DivideBy k Refl}` witnesses (which compute, since the
61+
-- sizes/alignments there are concrete). Re-introducing the general lemma with a
62+
-- real proof is tracked as future work, not a `believe_me`.
5463

5564
--------------------------------------------------------------------------------
5665
-- Struct Field Layout
@@ -117,6 +126,7 @@ localeLayout =
117126
]
118127
32 -- Total size: 32 bytes
119128
8 -- Alignment: 8 bytes (pointer alignment)
129+
{aligned = DivideBy 4 Refl} -- 32 = 4 * 8
120130

121131
||| Layout of lol_translation_result_t.
122132
|||
@@ -138,6 +148,7 @@ translationResultLayout =
138148
]
139149
24 -- Total size: 24 bytes
140150
8 -- Alignment: 8 bytes
151+
{aligned = DivideBy 3 Refl} -- 24 = 3 * 8
141152

142153
||| Layout of lol_language_info_t.
143154
|||
@@ -167,6 +178,7 @@ languageInfoLayout =
167178
]
168179
56 -- Total size: 56 bytes
169180
8 -- Alignment: 8 bytes
181+
{aligned = DivideBy 7 Refl} -- 56 = 7 * 8
170182

171183
||| Layout of lol_plural_rule_t.
172184
|||
@@ -188,6 +200,7 @@ pluralRuleLayout =
188200
]
189201
40 -- Total size: 40 bytes
190202
8 -- Alignment: 8 bytes
203+
{aligned = DivideBy 5 Refl} -- 40 = 5 * 8
191204

192205
--------------------------------------------------------------------------------
193206
-- C ABI Compatibility Proofs
@@ -243,3 +256,4 @@ localeLayoutWasm32 =
243256
]
244257
16 -- Total size: 16 bytes on WASM32
245258
4 -- Alignment: 4 bytes
259+
{aligned = DivideBy 4 Refl} -- 16 = 4 * 4

0 commit comments

Comments
 (0)