The ABI package typechecks end-to-end (all modules %default total, no
postulate / believe_me / assert_total), and the hand-written Idris layout
constants are now cross-checked against the real C layout the Zig compiler emits
(see Cross-language ABI below):
cd src/interface/abi && idris2 --typecheck gsa-abi.ipkg
# 1/3: Building Types (Types.idr)
# 2/3: Building Layout (Layout.idr)
# 3/3: Building Foreign (Foreign.idr)Toolchain: Idris2 0.7.0, Chez backend (.tool-versions pins idris2 0.7.0).
For every one of the 8 ABI structs — ServerHandle, ProbeResult, ConfigField, A2MLConfig, GameProfile, ServerOctad, Fingerprint, DriftReport — all four layout properties are proven:
| Property | Meaning |
|---|---|
NoOverlap |
no two fields' [offset, offset+size) ranges overlap |
AllFieldsAligned |
every field offset is a multiple of its alignment |
SizeAligned |
total struct size is a multiple of the struct alignment |
SizeCoversFields |
total size ≥ sum of field sizes (padding accounted) |
Discharged by decision procedures (decNoOverlap, decAllAligned,
decSizeAligned, decSizeCovers) extracted via getYes; each proof
typechecks only because its Dec reduces to Yes for that concrete layout —
i.e. a malformed layout would fail to compile.
Also still proven: the per-type size/alignment Refl proofs, the
SizeOf↔layout agreement (LayoutMatchesSizeOf), and cross-platform
x86_64 ≡ aarch64 equivalence.
alignUpCeil offset a = ceilDiv offset a * a(via an in-module totalceilDiv).alignUpCeilIsMultiple— constructiveReflproof that the result isk * a.
Correction to the prior version of this file: the earlier
alignUpCeilIsMultipledid not typecheck (thecaseform left the goal stuck). It was rewritten viaceilDivso the witness is a directRefl. There is no remainingalignUpEquivpostulate — the proven path usesalignUpCeil/ceilDivdirectly, so that obligation is moot.
Decidable portInRange, nonEmptyId, configFieldCountPositive,
allPortsValid, the Valid* smart constructors, and the linear
ServerHandle with its erased non-null witness.
The Idris proofs above show the model is internally consistent; the Zig side now checks that model against reality and makes it a live runtime contract.
- Layout cross-check (was the open HIGH item). Each of the 8 structs is
declared as a Zig
extern struct(abi_layout.zig). A comptime block asserts@offsetOf/@sizeOf/@alignOfof every field equals the proven Idris constant — lifted verbatim fromLayout.idrintoabi_layout_expected.zigbyscripts/gen_abi_expected.zig. Any divergence is a compile error, so the library cannot build against a layout the proofs do not describe. A negative test (perturbing one offset) confirms the guard bites; the check also runs underzig build test. - Live offset contract. The previously-unimplemented FFI readers that
GSA.ABI.Foreignbinds are now real (abi_serde.zig):read_int/read_double/read_ptrdecode fields at a byte offset;read_string,array_len,array_get_string,is_null,freehandle strings/arrays;apply_config/close_handleround out the surface. Emitters (serializeDriftReport/serializeFingerprint/serializeStringArray) write the wire structs, andgossamer_gsa_drift_structexports one. Round-trip tests read each field back at its provenLayout.idroffset, standing in for the Idris reader — so agreement is an end-to-end cross-language guarantee. - Idris consumer.
Foreign.getDriftnow decodes aDriftReportat offsets taken fromoffsetOf … driftReportLayout(not the previous, wrong hand-tuned0/4/12/20/28), viaprim__driftStruct+prim__readPtr/readInt/readDouble.
Regenerate the expected table whenever
Layout.idrchanges:zig run scripts/gen_abi_expected.zig(then the Zig cross-check re-validates).
- Server probe safety (MEDIUM). Prove probes cause no side effects on targets. Needs a specification first.
- Configuration drift-detection completeness (LOW). Needs a richer spec.
- Access control for admin panels (LOW). Needs a specification.
Foreign.idr's linearServerHandlewrappers now typecheck: each handle is consumed by a pattern match and rebuilt for the borrow-return, so linearity is respected (previously they used the handle twice and did not compile).