Skip to content

Commit d87b459

Browse files
docs(L4): dyadic-mode scaffold — Phase A (no proof changes) (#197)
## Summary * **Phase A** of the post-slice-4 four-phase plan: L4 dyadic-mode scaffold. Per `formal/PRESERVATION-DESIGN.md §7`, L4 is *not a separate proof layer* — it is a labelling discipline at the program / module level. **No proofs change.** * New: `formal/L4-DYADIC.md` (design page) + `formal/L4.v` (Definitions only — `ProgramMode` enum + `program_mode_to_modality : ProgramMode -> Modality`). * Updated: `PROOF-NEEDS.md` (§2 row + §4 file-by-file table), `.machine_readable/6a2/{STATE,META}.a2ml`, `formal/_CoqProject` (adds `L4.v`). ## Why this is the right shape * L4 introduces **zero** new typing judgments, step relations, preservation theorems, or echo disciplines. * `formal/L4.v` carries Definitions only — no theorems, no admit, no axiom. * Imports only `Modality.v`. No coupling to L1 / L3 internals. * Downstream tools (Idris2 ABI, Rust borrow checker, surface parser) now have a citable Coq type to refer to (`ProgramMode`) instead of an unmechanised concept. ## Files ``` formal/L4-DYADIC.md 261 lines (new) formal/L4.v 66 lines (new) formal/_CoqProject +1 line PROOF-NEEDS.md +21 / -7 STATE.a2ml refreshed META.a2ml ADR-005 L4 line annotated ``` ## Build oracle Clean rebuild of all 10 `.v` files with `coqc 8.18.0` — zero errors. Admit/Qed counts unchanged from main: * `Semantics_L1.v`: 26 Qed / 3 outer Admitted (5 inner `admit.`) * `Semantics.v`: 1 sacrosanct Admitted (the legacy `Theorem preservation`; provably false per `Counterexample.v`) * Everywhere else: 0 admits, 0 axioms. ## Test plan - [x] `coqc 8.18.0` builds `L4.v` standalone - [x] `coqc 8.18.0` clean-rebuilds the full `formal/*.v` tree in dependency order - [x] GPG signature verified on the commit - [x] No new `Admitted` or `Axiom` in any `.v` file - [x] No edits to `Semantics.v`, `Typing.v`, or any L1/L2/L3 mechanisation ## Owner directive compliance Verified against `CLAUDE.md` 2026-05-27 owner directive: - ❌ does not close `Theorem preservation` in `Semantics.v` - ❌ does not extend `Semantics.v` with closure-support lemmas - ❌ does not close any `Admitted.` in `Semantics_L1.v` - ❌ does not patch the legacy `Typing.v` judgment - ❌ does not pattern-match on `Linear`/`Affine` inside `Echo.v` - ❌ does not add new `Axiom` declarations - ✅ derives from `PRESERVATION-DESIGN.md §7` (the canonical design source) ## Next phase Phase B — TEcho linearity / observation discipline. Wire `is_linear_ty (TEcho T) = ...` so a Linear unobserved echo fails typing, then cascade through every `is_linear_ty T = true` premise site. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8747d89 commit d87b459

6 files changed

Lines changed: 261 additions & 20 deletions

File tree

.machine_readable/6a2/META.a2ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ consequences = "Mechanised Coq + Idris2 chain. NOTE: as of 2026-05-26 the legacy
2828
status = "accepted"
2929
date = "2026-05-27"
3030
context = "On 2026-05-26 formal/Counterexample.v (5 Qed lemmas) demonstrated that preservation in the legacy single-layer judgment is provably false: region exit can invalidate sibling assumptions without the typing judgment tracking that dependency explicitly. The legacy judgment conflates four distinct concerns (structural discipline, region capabilities, dyadic interaction, echo residue)."
31-
decision = "Four-layer principled redesign with each layer's preservation theorem derived against its own explicit invariants. L1 = region capabilities (TypingL1.v + Semantics_L1.v, modality-indexed); L2 = structural modality Linear/Affine (Modality.v + m in has_type_l1); L3 = echo/residue (Echo.v, fiber-shaped, one type former, L2-mode dispatched at typing-rule boundary); L4 = dyadic interaction (designed only). Echo Types are orthogonal to structural discipline by construction — one Echo type former, Linear/Affine is a thin-poset of observation disciplines layered on top, not two separate echo types."
31+
decision = "Four-layer principled redesign with each layer's preservation theorem derived against its own explicit invariants. L1 = region capabilities (TypingL1.v + Semantics_L1.v, modality-indexed); L2 = structural modality Linear/Affine (Modality.v + m in has_type_l1); L3 = echo/residue (Echo.v + preservation_l3 in Semantics_L1.v, fiber-shaped, one type former, L2-mode dispatched at typing-rule boundary); L4 = dyadic interaction (labelling discipline only, no proofs change — Definitions in L4.v + design doc L4-DYADIC.md, Phase A landed 2026-05-28). Echo Types are orthogonal to structural discipline by construction — one Echo type former, Linear/Affine is a thin-poset of observation disciplines layered on top, not two separate echo types."
3232
consequences = "Preservation is re-derived per layer. Legacy formal/Semantics.v + formal/Typing.v are archaeology and must not be extended. Per-sublanguage proof debt tracked in PROOF-NEEDS.md. Past/present/future map in STATUS.adoc. Owner directive 2026-05-27 in CLAUDE.md is durable. Pre-2026-05-26 closure-plan PRs (#92, #102, #104, #106, #114, #116, #117, #121, #146) are archaeology, not instructions."
3333

3434
# ── Development Practices ──────────────────────────────────────────────────

.machine_readable/6a2/STATE.a2ml

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
@state(version="2.0"):
88
phase: "implementation"
9-
next_action: "Layered preservation work, NOT legacy patching. Per owner directive 2026-05-27 (see CLAUDE.md): do not attempt to close Theorem preservation in formal/Semantics.v (provably false via Counterexample.v); do not extend Semantics.v with closure-support lemmas (step_preserves_type_at_pre and similar are all in this anti-pattern class); do not close residual Semantics_L1.v axioms via ad-hoc proof tricks. Affirmative work: per-layer preservation derivation against the four-layer redesign in formal/PRESERVATION-DESIGN.md. L2 modality landed in-place (PRs #176 + #177); 6 L1 supporting lemmas regressed to Admitted post-L2-hybrid — bullet-rewrite needed for the 3 new Affine-only constructors of has_type_l1 in Semantics_L1.v."
10-
last_action: "Doc lockdown landed on main (PR TBD): CLAUDE.md adds owner-directive §, PRESERVATION-DESIGN.md + PRESERVATION-HANDOFF.md gain banners, ROADMAP.adoc §preservation-closure-plan obsoleted, this STATE.a2ml updated. The lockdown originated on the proof/l1-region-threading-design branch (PR #175 against that branch); replayed to main because the design branch is DIRTY+superseded by the L2 hybrid path (#176+#177). PR #153 to be closed as superseded."
11-
updated: 2026-05-27T11:30:00Z
9+
next_action: "Phase B — TEcho linearity / observation discipline. Wire `is_linear_ty (TEcho T) = ...` in TypingL1.v so a Linear unobserved echo fails typing, then cascade through every `is_linear_ty T = true` premise site. Phase C (L1 structural list-vs-multiset bridge) and Phase D (L2 effect-typed TFun) follow, per the saved 4-phase plan (project_ephapax_post_slice4_plan in user auto-memory). All work is layered per CLAUDE.md owner directive 2026-05-27: no patching of legacy Semantics.v/Typing.v, no new Admitted/Axiom, no ad-hoc cross-layer reasoning to close L1 admits."
10+
last_action: "Phase A — L4 dyadic scaffold (docs only, no proof changes). Added formal/L4-DYADIC.md design page extracting PRESERVATION-DESIGN.md §7 + formal/L4.v with [ProgramMode] enum and [program_mode_to_modality] mapping to L2's [Modality]. Wired into _CoqProject; full-tree coqc 8.18.0 clean rebuild passes. Slice 4 capstone (preservation_l3) landed on main 2026-05-27 as PR #196."
11+
updated: 2026-05-28T08:25:00Z
1212

1313
@directive(source="owner", date="2026-05-27", canonical="CLAUDE.md"):
1414
# Captured durable directive — preservation work is the four-layer redesign,
@@ -46,14 +46,20 @@ updated: 2026-05-27T11:30:00Z
4646
# and their at_pre helpers are Qed but support legacy-preservation
4747
# closure attempts that are now ruled out. Retained for diagnostic
4848
# value; no new lemmas in this class.
49-
# - formal/Semantics_L1.v `preservation_l1`: in progress; 6 supporting
50-
# lemmas regressed to Admitted post-L2-hybrid (PRs #176+#177).
51-
# Bullet-structure rewrite needed for 3 new Affine-only constructors.
52-
# - formal/TypingL1.v: now m-indexed (`has_type_l1 m R G e T R' G'`),
53-
# `linear_to_affine` Qed zero axioms.
54-
# - formal/Echo.v: K-free scaffold, no postulates, forward-looking
55-
# (not yet wired into has_type_l1).
49+
# - formal/Semantics_L1.v `preservation_l1`: stated `forall m`; body
50+
# Admitted (lambda-rigidity gap, closes at Phase D / L2 effect-typed
51+
# TFun per PRESERVATION-DESIGN.md §5.1). 5 inner `admit.` cases
52+
# (3 distinct structural blockers + 2 mechanical mirrors) covered
53+
# by 3 outer Admitted markers. Zero new debt introduced post-L2.
54+
# - formal/Semantics_L1.v `preservation_l3`: Qed, both modes, slice 4
55+
# of L3 wiring landed 2026-05-27 (PR #196).
56+
# - formal/TypingL1.v: m-indexed (`has_type_l1 m R G e T R' G'`),
57+
# `linear_to_affine` Qed zero axioms; T_Echo_L1 / T_Observe_L1 +
58+
# parallel T_*_Echo rules landed for L3 wiring.
59+
# - formal/Echo.v: K-free L3 calculus, no postulates, 12 Qed.
5660
# - formal/Modality.v: thin-poset Linear ≤ Affine, all Qed.
61+
# - formal/L4.v: ProgramMode labelling discipline, Definitions only,
62+
# no theorems. Phase A landed 2026-05-28.
5763
#
5864
# Other proof-debt items (out of preservation scope):
5965
# - src/abi/Ephapax/ABI/Invariants.idr E1-E6: E1 (preservation) OWED at
@@ -62,12 +68,15 @@ updated: 2026-05-27T11:30:00Z
6268
@end
6369

6470
@artifacts:
65-
# Layered files on main (post-L2-hybrid):
66-
# formal/Counterexample.v — 3 Qed lemmas; preservation FALSE
67-
# formal/Echo.v — L3 scaffold, K-free
71+
# Layered files on main (post-slice-4 + Phase A):
72+
# formal/Counterexample.v — 5 Qed lemmas; preservation FALSE
73+
# formal/Echo.v — L3 calculus, K-free, 12 Qed
6874
# formal/Modality.v — L2 thin poset, all Qed
69-
# formal/TypingL1.v — m-indexed has_type_l1 (post-#176)
70-
# formal/Semantics_L1.v — in progress; 6 supporting Admitted
75+
# formal/TypingL1.v — m-indexed has_type_l1 + Echo/Observe rules
76+
# formal/Semantics_L1.v — 26 Qed, 3 outer Admitted (5 inner admit.)
77+
# formal/TypingL2.v — thin wrapper through TypingL1.has_type_l1
78+
# formal/L4.v — ProgramMode labelling discipline (Phase A)
79+
# formal/L4-DYADIC.md — L4 design doc
7180
# Doc lockdown:
7281
# CLAUDE.md — owner directive §
7382
# formal/PRESERVATION-DESIGN.md — CANONICAL banner

PROOF-NEEDS.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,24 @@ enters the typing rules" and (for the diagram) in §6 (to be added).
111111
| ~~Thread `G` (echo context) alongside `R` (region context) through compound rules~~ | ~~New context parameter on every L1 compound rule~~ | **OBSOLETE 2026-05-27**: under the owner-approved parallel-rules design (slices 3a–3c), echoes are values of type `TEcho T` that flow through the existing `ctx` G. No separate echo-context parameter is needed. |
112112
| ✅ State and prove `preservation_l3` | Per-layer preservation theorem against the L3 invariants for the new echo-emitting step rules + echo-typed paths | done 2026-05-27 (L3 wiring slice 4 — capstone). Two per-case Qed lemmas (`preservation_l3_region_active_echo` for `S_Region_Exit_Echo` × `T_Region_Active_L1_Echo`, and `preservation_l3_drop_echo` for `S_Drop_Echo` × `T_Drop_L1_Echo`) plus an umbrella `preservation_l3` (their conjunction, Qed). Zero new admits or axioms. Per-case alignment forced by `T_Echo_L1`'s witness-type premise; non-deterministic crossover cases are non-preserving by design (typing derivation pins the path). Conditionally Qed under the pre-existing `region_shrink_preserves_typing_l1_gen_m` L1 structural admit per PRESERVATION-DESIGN.md §5.1. |
113113

114-
### Mid-term (L4 — not started)
114+
### Mid-term (L4 — scaffold landed 2026-05-28)
115115

116116
L4 covers dyadic interaction semantics (mother–child distinction).
117-
Design lives in `formal/PRESERVATION-DESIGN.md §7`. No file, no mechanisation
118-
yet. To be approached only after L3 wiring lands.
117+
Per `formal/PRESERVATION-DESIGN.md §7`, L4 is "not a separate proof
118+
layer. It is a labelling discipline at the program / module level...
119+
No proofs change."
120+
121+
Phase A scaffold landed 2026-05-28:
122+
123+
| Item | File | Status |
124+
|---|---|---|
125+
| ✅ L4 design page | `formal/L4-DYADIC.md` | done — extracts + extends design doc §7 |
126+
| ✅ Labelling enum `ProgramMode` + `program_mode_to_modality` mapping to L2 | `formal/L4.v` | done — Definitions only, no theorems, no admit, no axiom |
127+
128+
Future L4 work (post-Phase D, optional): surface-syntax wiring in
129+
the borrow checker so `#![ephapax_linear]` / `#![ephapax_affine]` /
130+
`#![module_boundary_mix]` parse and select the L2 modality. This is
131+
implementation, not proof debt.
119132

120133
### Value-prop directions (committed and speculative)
121134

@@ -218,7 +231,7 @@ to the owner**:
218231

219232
## §4. Counts + file-by-file map
220233

221-
### Per-file Qed / Admitted summary (as of 2026-05-27)
234+
### Per-file Qed / Admitted summary (as of 2026-05-28)
222235

223236
| File | Qed | Admitted | Disposition |
224237
|---|---:|---:|---|
@@ -230,6 +243,7 @@ to the owner**:
230243
| `formal/Modality.v` | **1** | 0 | ✅ active — L2 core, zero axioms |
231244
| `formal/Echo.v` | **12** | 0 | ✅ active — L3 calculus, not yet wired into L1 |
232245
| `formal/TypingL2.v` | (wrapper) | (wrapper) | ✅ thin re-indexing through `TypingL1.has_type_l1` |
246+
| `formal/L4.v` | (Definitions only) | 0 | ✅ active — L4 labelling discipline, no theorems (Phase A landed 2026-05-28) |
233247
| `src/abi/Ephapax/…` (Idris2) | n/a | n/a | ✅ active — ABI, Region linearity, no `believe_me` / `sorry` / `assert_total` |
234248

235249
### Seam audit (slice 4, 2026-05-27): every admit/axiom classified

formal/L4-DYADIC.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<!-- SPDX-License-Identifier: PMPL-1.0-or-later -->
2+
<!-- Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> -->
3+
4+
# Ephapax L4 — Dyadic mode (labelling discipline)
5+
6+
> Scope: project / module-level labelling. **No proof obligations.**
7+
> Companion mechanical scaffold: [`formal/L4.v`](L4.v).
8+
> Canonical design source: [`formal/PRESERVATION-DESIGN.md §7`](PRESERVATION-DESIGN.md).
9+
10+
## What L4 is
11+
12+
L4 is the outermost ring of the four-layer redesign. Where L1 / L2 / L3
13+
each carry a typing-layer judgment or per-layer proof obligation, L4
14+
carries **none of that**. It is a *labelling discipline* applied at the
15+
program / module boundary.
16+
17+
A closed Ephapax program declares one of three program modes:
18+
19+
| `ProgramMode` (L4) | Selects L2 modality | L3 echo discipline that follows |
20+
|---|---|---|
21+
| `EphapaxLinear` | `Linear` | Echoes must be **observed** before program end |
22+
| `EphapaxAffine` | `Affine` | Echoes may be observed or silently lowered |
23+
| `ModuleBoundaryMix` | per-module | Module's L2 modality determines its L3 echo discipline at each boundary crossing |
24+
25+
The declaration tells the type checker which L2 modality `m` to thread
26+
through `has_type_l1`. Once `m` is selected, L3's echo observation
27+
discipline follows from L2 with no further user input.
28+
29+
## Why L4 is not a separate proof layer
30+
31+
The four-layer redesign assigns proof obligations as follows:
32+
33+
| Layer | What it proves | Where the proof lives |
34+
|---|---|---|
35+
| **L1** | Region-capability soundness; preservation under R-threading | `formal/TypingL1.v` + `formal/Semantics_L1.v` |
36+
| **L2** | Modality lifting (Linear ⇒ Affine) | `formal/Modality.v` (`linear_to_affine` Qed) |
37+
| **L3** | Echo residue preservation under irreversible steps | `formal/Echo.v` + `preservation_l3` in `formal/Semantics_L1.v` |
38+
| **L4** | (nothing — labelling only) | `formal/L4.v` (Definitions only, no theorems) |
39+
40+
L4 is the *user-facing surface* through which L1–L3's proofs are
41+
applied to a concrete program. Selecting `EphapaxLinear` at L4 instructs
42+
the system to:
43+
44+
1. Choose `Linear : Modality` at L2.
45+
2. Enforce echo observation at L3.
46+
3. Apply L1's preservation theorem to the resulting derivation.
47+
48+
No new theorem is needed at L4 because no new judgment is introduced.
49+
50+
## The mother–child dyad
51+
52+
The dyadic framing (PRESERVATION-DESIGN.md §7) reads the Linear /
53+
Affine pair as an **asymmetric dyad**:
54+
55+
- **Linear** = the obligation-bearer (the *speaker* of the dyad).
56+
Linear-mode programs are responsible for discharging every echo
57+
before termination.
58+
- **Affine** = the obligation-relaxer (the *listener*).
59+
Affine-mode programs may accept, observe, or silently drop echoes —
60+
the listener has the option of not engaging.
61+
62+
Both sides are needed because real systems contain both
63+
obligation-bearing components (resource owners, audit trails, GDPR
64+
deletion receipts) and obligation-relaxing components (loggers, UI,
65+
diagnostics that may safely vanish).
66+
67+
The dyad **is not symmetric**: a Linear-mode component can call into
68+
an Affine-mode component (the listener silently relaxes), but an
69+
Affine-mode component cannot call into a Linear-mode component except
70+
through a designated obligation-handoff (a `ModuleBoundaryMix`
71+
declaration explicitly converts the obligation surface).
72+
73+
This asymmetry is exactly what L2's `linear_to_affine` lemma
74+
mechanises: every Linear derivation can be viewed as an Affine
75+
derivation, but not vice versa.
76+
77+
## Orthogonality to L1 / L2 / L3
78+
79+
L4 is orthogonal to the lower layers in the following sense:
80+
81+
- **L1 (region capabilities)** is the *same* in both Linear and
82+
Affine — both must track region exit precisely for soundness.
83+
Switching L4 program mode does not change L1's invariants.
84+
- **L2 (modality)** gives the *direction* of the dyad — which side
85+
is obligation-bearing. L4 selects which L2 modality the program
86+
inhabits.
87+
- **L3 (echo)** is the *protocol* of obligation discharge — what
88+
the observer must do with the residue. L4 selects the L3
89+
discipline indirectly through L2.
90+
91+
## What L4 declarations look like (illustrative)
92+
93+
L4 is currently a *design layer*. Surface syntax has not yet been
94+
wired into the parser or borrow checker. The intended shape:
95+
96+
```ephapax
97+
// Top of a closed program, before any imports
98+
#![ephapax_linear]
99+
100+
// — or —
101+
102+
#![ephapax_affine]
103+
104+
// — or, at the boundary of a multi-module project —
105+
106+
#![module_boundary_mix(default = "ephapax_affine")]
107+
mod critical_section {
108+
#![ephapax_linear]
109+
// every echo here must be observed before this module returns
110+
}
111+
```
112+
113+
The mechanical surface for downstream tools is in [`formal/L4.v`](L4.v):
114+
115+
- `ProgramMode` — three-constructor enum (`PModeLinear` /
116+
`PModeAffine` / `PModeBoundaryMix`).
117+
- `program_mode_to_modality` — total function `ProgramMode -> Modality`
118+
(with `PModeBoundaryMix` mapped to a default; per-module modality is
119+
read from the surrounding declaration).
120+
- No theorems; no admit; no axiom.
121+
122+
## What L4 does NOT do
123+
124+
L4 introduces **zero** new proof obligations. In particular:
125+
126+
- L4 does NOT introduce a new typing judgment.
127+
- L4 does NOT introduce a new step relation.
128+
- L4 does NOT introduce a new preservation theorem.
129+
- L4 does NOT introduce a new echo discipline.
130+
- L4 does NOT change the L1 region-threading invariants.
131+
- L4 does NOT change the L2 modality-lifting lemma.
132+
133+
If a question about L4 leads to a proof obligation, the question is
134+
not about L4 — it is about whichever lower layer the obligation lives
135+
in (probably L2 if it concerns modality lifting, or L3 if it concerns
136+
echo discipline).
137+
138+
## Cross-references
139+
140+
- [`formal/PRESERVATION-DESIGN.md §7`](PRESERVATION-DESIGN.md)
141+
canonical design source.
142+
- [`formal/PRESERVATION-DESIGN.md §8`](PRESERVATION-DESIGN.md)
143+
per-layer proof-need separation between Linear and Affine.
144+
- [`formal/L4.v`](L4.v) — the mechanical scaffold (Definitions only).
145+
- [`formal/Modality.v`](Modality.v) — L2 thin poset; selected by L4.
146+
- [`formal/Echo.v`](Echo.v) — L3 echo calculus; discipline selected
147+
by L2.
148+
- [`CLAUDE.md`](../CLAUDE.md) — agent guidance; owner directive
149+
2026-05-27 (no patching of legacy preservation).
150+
- [`PROOF-NEEDS.md`](../PROOF-NEEDS.md) — proof-debt accounting.

formal/L4.v

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
(* SPDX-License-Identifier: PMPL-1.0-or-later *)
2+
(* SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell *)
3+
4+
(**
5+
6+
*********************************************************************
7+
*** ✅ ACTIVE -- L4 dyadic mode (labelling discipline). ***
8+
*** ***
9+
*** L4 is NOT a separate proof layer. This file carries ***
10+
*** Definitions ONLY: ***
11+
*** - [ProgramMode]: three-constructor enum. ***
12+
*** - [program_mode_to_modality]: total mapping to L2. ***
13+
*** ***
14+
*** No theorems, no admit, no axiom. ***
15+
*** ***
16+
*** Canonical design: formal/PRESERVATION-DESIGN.md §7. ***
17+
*** Companion doc: formal/L4-DYADIC.md. ***
18+
*********************************************************************
19+
20+
*)
21+
22+
From Ephapax Require Import Modality.
23+
24+
(** * Ephapax L4 — Dyadic mode (program-level labelling)
25+
26+
L4 is the outermost ring of the four-layer redesign. Where L1, L2,
27+
and L3 each carry a typing-layer judgment or per-layer proof
28+
obligation, L4 carries **none of that**. It is a labelling
29+
discipline applied at the program / module boundary.
30+
31+
A closed Ephapax program declares one of three program modes; the
32+
declaration tells the type checker which L2 modality [m] to thread
33+
through [has_type_l1]. Once [m] is selected, L3's echo observation
34+
discipline follows from L2 with no further user input.
35+
36+
See [formal/L4-DYADIC.md] for the design discussion; this file is
37+
purely the mechanical scaffold so downstream tools (Idris2 ABI,
38+
Rust borrow checker, surface parser) can refer to a citable type. *)
39+
40+
Inductive ProgramMode : Type :=
41+
| PModeLinear : ProgramMode
42+
| PModeAffine : ProgramMode
43+
| PModeBoundaryMix : Modality -> ProgramMode.
44+
45+
(** [program_mode_to_modality] selects the L2 modality threaded
46+
through a program's typing derivation. For [PModeBoundaryMix d],
47+
[d] is the default modality used outside any module-local
48+
declaration; per-module modality is read from the surrounding
49+
declaration in the surface syntax and is not represented at this
50+
layer. *)
51+
52+
Definition program_mode_to_modality (p : ProgramMode) : Modality :=
53+
match p with
54+
| PModeLinear => Linear
55+
| PModeAffine => Affine
56+
| PModeBoundaryMix d => d
57+
end.
58+
59+
(** Sanity: the round-trip from the two pure program modes through
60+
[program_mode_to_modality] recovers the expected L2 modality.
61+
This is definitional, not a theorem about the system. *)
62+
63+
Definition program_mode_linear_selects_linear :
64+
program_mode_to_modality PModeLinear = Linear := eq_refl.
65+
66+
Definition program_mode_affine_selects_affine :
67+
program_mode_to_modality PModeAffine = Affine := eq_refl.

0 commit comments

Comments
 (0)