Skip to content

feat: @safe-gated verified resource checking + n-ary/global session runtimes#127

Merged
hyperpolymath merged 2 commits into
mainfrom
claude/dreamy-hypatia-O8XHo
Jun 27, 2026
Merged

feat: @safe-gated verified resource checking + n-ary/global session runtimes#127
hyperpolymath merged 2 commits into
mainfrom
claude/dreamy-hypatia-O8XHo

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

What

Two follow-ups requested after the coupling work merged (#121):

1. Wire the verified QTT checker in as the compiler default (#[safe]-gated)

crates/my-lang/src/checker.rs now runs the machine-checked QTT core (my_qtt::check, the faithful R5 port) by default — no flag — on every function annotated #[safe]. Checker::check_qtt_safe_fn models the function as |params| body, lowers it via qtt_bridge, and a parameter dropped/duplicated within the resource fragment becomes CheckError::ResourceViolation. Out-of-fragment bodies (arithmetic, records, AI exprs, return, calls to globals) can't be lowered and are skipped — unverifiable ≠ unsafe.

Gated on #[safe] (per the maintainer's choice) because my-lang isn't linear-by-default — blanket enforcement would reject normal code. End-to-end via typecheck:

#[safe] fn id(x: Int)  { x; }      -> OK
#[safe] fn drp(x: Int) { 0; }      -> ResourceViolation   (x dropped)
        fn drp(x: Int) { 0; }      -> OK   (not #[safe])
#[safe] fn add1(x: Int){ x + 1; }  -> OK   (arithmetic out-of-fragment, skipped)

Closes the docs/STATUS.adoc "make the resource axis the default in checker.rs" item. 4 new tests; all 153 my-lang tests green.

2. The n-ary nstep + global gstep session runtimes (coupling #4, remaining layers)

SessionEval.v adds a functional stepper for the other two layers of the SessionPi metatheory, both nondeterministic relations, proved adequate and axiom-free (CI-gated):

Stepper Layer Theorems
gstep1 : gty -> option gty global type gstep1_sound + gstep1_complete (progress)
nstep1 : role_assignment -> option role_assignment n-ary located nstep1_sound + nstep1_complete (progress)

For nondeterministic relations the honest adequacy is soundness + progress (step1 = None iff stuck), not functional determinism — gstep1 commits to the head branch, nstep1 to the first communicating pair (find_recv/find_bra, parties always re-fetched via ra_get so duplicate role entries never act on a stale party).

Rust runtime my_qtt::session gains faithful Gty/Vty/gstep1 and RoleAssignment + the lookup/search chain + nstep1 (+5 unit tests). Both are extracted and differentially conformance-tested: one conformance/run.sh now drives 6 query classes90,000 results across 5 seeds agree ({check, one-step, normal-form, cstep, gstep, nstep} × 3000 × 5).

Verification

  • coqc suite (incl. SessionEval.v) builds; all new theorems Print Assumptions → closed (axiom-free).
  • cargo test -p my-qtt (25) + -p my-lang (153) green.
  • conformance/run.sh 90k/90k agree across 5 seeds.

Scope / honesty

Refinement-by-conformance against the extracted verified steppers, not a full Rust-in-Coq proof. The #[safe] resource check only bites where the body is in the lowerable fragment. The AI-surface interpreter.rs remains a separate unverified frontend.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV


Generated by Claude Code

claude added 2 commits June 27, 2026 04:42
…] fns

Wires the machine-checked QTT core (my_qtt::check, the faithful R5 port) into
the compiler's default check path — closing the docs/STATUS.adoc "make the
resource axis the default in checker.rs" item.

`Checker::check_function` now, for every function annotated `#[safe]`, models
it as `|params| body` and runs `qtt_bridge::check_expr` (→ verified
`my_qtt::check`). A parameter dropped or used more than once WITHIN the
resource-relevant fragment is reported as `CheckError::ResourceViolation`; a
body using constructs outside that fragment (arithmetic, records, AI exprs,
calls to globals, `return`) cannot be lowered and is skipped — unverifiable is
not unsafe. Runs by default (no flag); gated on `#[safe]` so the rest of the
language (which is not linear-by-default) is unaffected.

End-to-end via `typecheck`:
  #[safe] fn id(x: Int)  { x; }      -> OK   (x used once)
  #[safe] fn drp(x: Int) { 0; }      -> ResourceViolation (x dropped)
          fn drp(x: Int) { 0; }      -> OK   (not #[safe], not enforced)
  #[safe] fn add1(x: Int){ x + 1; }  -> OK   (arithmetic out-of-fragment, skipped)

4 new checker tests; all 153 my-lang tests green. STATUS docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV
Extends the session coupling from the binary `cstep` to the remaining two
layers of the SessionPi metatheory, both nondeterministic relations:

SessionEval.v (axiom-free, in _CoqProject / CI-gated):
- gstep1 : gty -> option gty   — sound (gstep1_sound) + PROGRESS (gstep1_complete:
  gstep G G' -> exists G'', gstep1 G = Some G''). Commits to the head branch;
  progress not determinism because gstep is nondeterministic at GBra.
- nstep1 : role_assignment -> option role_assignment — sound (nstep1_sound) +
  PROGRESS (nstep1_complete). Scans for the first communicating pair
  (find_recv/find_bra), parties always re-fetched via ra_get so duplicate role
  entries never act on a stale party. Soundness via per-search inversion lemmas;
  progress via the dual membership lemmas + ra_get_in.

For the two nondeterministic relations the honest adequacy is soundness +
progress (`step1 = None` iff stuck), not functional determinism.

Rust runtime (my_qtt::session): faithful Gty/Vty + gstep1, and
RoleAssignment/ra_get/ra_set/find_recv/find_bra/try_role/nstep1, mirroring Coq;
+5 unit tests.

Conformance: gstep1/nstep1 extracted (Extract.v); the harness gains
(gstep GTY) and (nstep RA) queries (oracle parse/show for gty + role_assignment;
generators in conformance_gen). One run.sh now drives 6 query classes:
90,000 results across 5 seeds agree (3000 cases x {check, one-step, normal-form,
cstep, gstep, nstep}).

STATUS.md: #4 row -> all three layers conformance-checked; two new
mechanised-cores rows for gstep1/nstep1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV
@hyperpolymath hyperpolymath marked this pull request as ready for review June 27, 2026 10:06
@hyperpolymath hyperpolymath merged commit caf3b81 into main Jun 27, 2026
21 of 28 checks passed
@hyperpolymath hyperpolymath deleted the claude/dreamy-hypatia-O8XHo branch June 27, 2026 10:06
hyperpolymath added a commit that referenced this pull request Jun 27, 2026
…lures at source (#129)

## What

Deals with the pre-existing CI failures **at source**, in scope order.
Summary of every red and its disposition:

| Failure | Root cause | Fix |
|---|---|---|
| `llvm-cov` "no profraw" | **My regression from #127** —
`CheckError::ResourceViolation` made a `match` in `my-lsp`
non-exhaustive, so `cargo --workspace` couldn't build → no tests ran →
no profraw | ✅ Added the missing match arm; `cargo test --workspace
--exclude my-llvm` green |
| `governance / Licence consistency` | repo-root `LICENSE` had no SPDX
header | ✅ Added `SPDX-License-Identifier: MPL-2.0` |
| `PR (address)` / `PR (undefined)` (ClusterFuzzLite) |
`.clusterfuzzlite/Containerfile` was **conflict-broken** and misnamed
(the action builds from `Dockerfile`) | ✅ Clean `Dockerfile` + corrected
`build.sh`; removed broken `Containerfile` |
| stale merge-conflict markers | unresolved
`<<<<<<<`/`=======`/`>>>>>>>` in `CONTRIBUTING.md`,
`.clusterfuzzlite/{Containerfile,build.sh}` | ✅ Resolved (kept the
`my-lang` side; HEAD's `my-lang-archive` is a stale name) |
| `scan / Hypatia` + `Validate Hypatia Baseline` | **Upstream** — the
Hypatia analyzer itself fails to compile: `undefined variable
"real_subdirs"` at `lib/rules/structural_drift.ex:1019` in
`hyperpolymath/standards` | ⛔ Out of my push scope — must be fixed in
`standards`; nothing in my-lang triggers it |

## Honesty notes

- **I mis-diagnosed `llvm-cov` earlier as "not caused by this PR."** It
*was* — the "no profraw" was a downstream symptom of `my-lsp` failing to
build under `--workspace`. My local `-p my-lang`/`-p my-qtt` runs never
built `my-lsp`, so they missed it. This PR fixes it and I've verified
the full workspace build + tests.
- The ClusterFuzzLite Dockerfile/build.sh follow the documented OSS-Fuzz
Rust pattern and are syntax-checked, but the full image build needs the
OSS-Fuzz base image (not runnable locally) — so that one is "root cause
removed, correct by inspection," not locally executed.
- **Hypatia is the only remaining red and it's upstream.** Exact fix for
whoever owns `standards`: bind/define `real_subdirs` before its use at
`structural_drift.ex:1019` (looks like a variable that was
renamed/dropped).

## Verification
- `cargo test --workspace --exclude my-llvm` → all crates green (my-lsp
5, my-lang 153, my-qtt 25, …).
- No conflict markers remain repo-wide; `bash -n
.clusterfuzzlite/build.sh` OK; LICENSE SPDX header present.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV

---
_Generated by [Claude
Code](https://claude.ai/code/session_01BwV2DWsjkBiNP3oscimMLV)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants