|
Important
|
This document is the single source of truth for the status of AffineScript’s
known soundness holes. If any other document — It is test-anchored: every row names the fixture or test that proves its
claim, and |
Ground-truthed at d55e22c on 2026-06-21 by source
inspection at the cited file:line anchors, with dune build and
dune runtest green. The status words below are deliberate; read them
precisely.
Soundness status used to live in ~6 places that drifted independently — the
capability matrix, a survey block in .claude/CLAUDE.md, dated STATE-
snapshots, session handoffs, the wiki. A reader (human or agent) who happened
to open the stale one got a stale answer, in the *dangerous direction:
"this hole is still open" long after it was fixed, or — worse in principle —
the reverse. This file is the structural fix:
-
One surface. Soundness-hole status is stated here and nowhere else. Other docs may summarise and then link here; they may not maintain a competing per-issue ledger. The gate enforces the back-link.
-
Anchored to tests. Each claim cites the executable artefact that proves it. Prose detached from tests is what rots; prose nailed to a fixture cannot drift without the fixture (and the gate) noticing.
-
Stamped. The freshness attributes above record the commit and date this was last reconciled against the running compiler.
| Term | Meaning |
|---|---|
fixed |
The previously-unsound behaviour is gone. The program that used to be wrongly accepted is now rejected, or the wrong result is now the right one. |
loud-fail |
The construct is not implementable on this path, but it errors at compile-time or run-time — it never silently emits a plausible-wrong value. "Fail loud, never silent" is the governing rule. |
removed |
The feature whose surface could not be honestly enforced was withdrawn from the language, so there is no unenforced surface left to mislead anyone. |
residual (pinned) |
A known-incorrect behaviour still exists, but an executable test pins it, so it cannot regress unnoticed and will alarm (the test flips to failing) the day it is fixed. |
open (tracked) |
A known gap with no fix yet, tracked by an issue. Stated here so it cannot be mistaken for a guarantee. |
partial |
Implemented and load-bearing for common cases; the named residual is the gap. |
| Issue | Soundness claim (current behaviour) | Status | Proven in code |
|---|---|---|---|
#554 / #177 |
Use-after-move through a callee-returned borrow is rejected.
|
fixed |
|
#555 (codegen) |
|
loud-fail |
|
#555 (interp, multi-shot) |
Calling |
loud-fail |
|
#555 (interp, non-tail single-shot) |
|
residual (pinned) |
|
#556 |
Async CPS table-miss fails loud instead of silently lowering synchronously. |
loud-fail |
|
#558 |
Refinement / dependent types were removed in v1 (2026-04-10). There is no
|
removed |
|
#559 |
Overlapping trait impls whose self types unify are rejected as a coherence violation, before the check pass, so an ambiguous instance base is reported up front. |
fixed |
|
#559 (generic subsumption) |
Generic-subsumption overlap — |
open (tracked) |
Documented in the coherence test block in |
#553 (Polonius) |
The Polonius extractor (ADR-022) is implemented through M3 but is
TEST-ONLY / unwired — it gates no production verdict. The lexical
|
partial |
|
The implementation holes above are closed, but honesty requires naming what is not a guarantee:
-
Interpreter non-tail resume (#555 residual, pinned; tracked as #623) — see the ledger row.
-
Stub backends drop
return. The Lean and Why3 experimental code generators dropreturnstatements wholesale — a broader codegen-honesty gap than #555, flagged but not yet fenced (tracked as #624). Treat all non-reference backends as experimental (seedocs/CAPABILITY-MATRIX.adoc). -
Generic-subsumption coherence (#559 follow-up) — see the ledger row.
Closing an implementation hole is not the same as having metatheory. The
soundness arguments for the holes above (docs/academic/proofs/.adoc, the
comments in lib/borrow.ml) remain prose, and the Solo core fragment’s
progress / preservation are still ?todo. Mechanisation has *started — an
axiom-free Coq/Rocq formal/ track (codegen-preservation: K-1
K1_CodegenPreservation.v, K-1-with-let K1Let_CodegenPreservation.v, and
the F-1 transformer-preservation composition; #620/#621) — but it does not yet
cover any hole in this ledger. The proof obligations, their rigour tiers, and
their (mostly prose / absent) status are catalogued in
docs/PROOF-NEEDS.adoc (umbrella issue #513). The one-line distinction:
The compiler now fails loud on these shapes and the residuals are pinned by tests — but the soundness arguments are still paper proofs, not machine-checked.
The v1 release-readiness ledger is issue #563.
-
Ground-truth by running the tool. Reproduce the behaviour against the built compiler (
dune build && dune runtest,dune exec affinescript — …). Never edit a status here from another doc — that is how drift starts. -
Change the row, change the anchor. If you fix or break a hole, update the status word and its anchoring fixture/test in the same change. The gate (
tools/check-soundness-ledger.sh) fails if a namedtest/e2e/fixtures/*.affineanchor no longer exists. -
Bump the stamp. Update
:ground-truth-sha:and:ground-truth-date:above to the commit you verified against. -
Do not fork the ledger. If another doc needs to mention soundness status, it links here; it does not copy the table. The gate checks the back-links from
README.adoc,docs/CAPABILITY-MATRIX.adoc,docs/PROOF-NEEDS.adoc,docs/NAVIGATION.adoc, and.claude/CLAUDE.md.
-
CAPABILITY-MATRIX.adoc — authoritative feature readiness (this ledger owns soundness-hole status; the matrix links here).
-
PROOF-NEEDS.adoc — what must be proven, at what rigour, with what (mostly unmechanised) status.
-
reports/HANDOFF-2026-06-17-soundness.adoc, reports/TIDY-UP-LEDGER-2026-06-16.adoc — the dated session reports this ledger consolidates (historical inputs).