Release-candidate notes — 7a16a40 (Nazm v0.3.0: public-release readiness, R1)
Frozen evidence for one tested commit. This file records what was verified at
7a16a40640b44f93713f8209d714f1fd20f45420 and is not updated as the project moves. Current
implementation truth is ../capability-matrix.md; what is not done is
../limitations.md. The candidate before it is 82936f6.md, which
this file does not change.
Nothing has been pushed, tagged or published. This is a candidate for Nazm v0.3.0, the toolchain release of the executable language Nazm v0.3. Making it a release is a person’s decision, and the procedure for it is at the end of this file.
Relationship to N108
82936f6 was N108’s accepted core candidate: the language, compiler, runtime, backends and the
compiler written in Nazm closed under their declared scope, every class-A row VERIFIED. R1 is
public-release hygiene on top of it, and changed no language or runtime semantics intentionally:
| Commit | What |
|---|---|
f7e3b0f R1A | the public version settled — language v0.3, toolchain 0.3.0, tag v0.3.0 — and the specification’s status stated section by section (stability.md, spec.md’s header) |
06795a6 R1B | CI runs the host-safe subset and leaves out, by reading the guard, every target that needs containment; N108’s lifecycle “timing flake” was an inherited ignored SIGINT, and the test now restores the default itself |
a85f34a R1C | a public README, a getting-started page and a tour the suite executes as written, a support matrix checked against the compiler’s own table, SECURITY.md, CONTRIBUTING.md |
eae9ed2 R1D | no run date inside a candidate (SOURCE_DATE_EPOCH, the commit time), and a build-input-digest over every tracked file |
2eb2111 | a corpus audit the tour exposed: a captured name read as the binding it copies (test only) |
47daadf R1-C1 | the one semantic-tooling defect R1 found, fixed — below |
745e6a6 | the public-claims audit: current documents brought to the compiler they describe |
c730626 | three catalogue entries for R1B’s and R1D’s responsibilities |
7a16a40 | the grammar’s new production given the example its test requires |
R1-C1 — a function written as a value was missing from the reference index
Found when R1’s tour (examples/tour/closures.nz) entered the corpus the reference audits read:
in apply_twice(double, 5), double was in no entity’s set. The checker had recorded every named
function written as a value since N50, and lowering, MIR and effects read that record; the reference
index, built from Resolution::each_use, did not. So nazm references, LSP find-references, a
snapshot’s references and dependencies, and every plan read from the index left such uses out,
and rename refused such a function — its re-check found the name undefined — so nothing was ever
renamed wrongly. The fix is one shared path: each_use reports each recorded function value as
a use of the function it names, at the name’s span, so every consumer of the index sees it, nothing
re-resolves a name, and no occurrence is listed twice. Every form the language accepts is covered:
an argument, a let, a return, a field, a generic argument, an import and a re-export’s alias.
Two corpus audits were stale since N50 and N78 and were fixed with it — a capture is the binding it
copies, and x.m() in a variant’s shape is a method call when the checker says so — and structure
now states by test that it offers no member at a method’s name. Epoch 29, nazm.interface/11,
runtime ABI 14, nazm.resolved/1 and nazm.snapshot/3 are unchanged: the schemas now carry what
they always promised, so a snapshot of a program with a function value has different references
and dependencies digests than an earlier build gave. Caches written by unreleased 0.3.0 builds
before 47daadf share this checker identity and may hold a unit without those uses; none was
released, the repository’s own were deleted, and this candidate’s evidence was produced after the
fix from fresh caches. architecture.md §7.110. Mutation evidence below.
Identities
| Commit | 7a16a40640b44f93713f8209d714f1fd20f45420 — the records commit that adds this file changes documentation only |
| Release | Nazm v0.3.0 (toolchain 0.3.0, Cargo.toml); language v0.3; intended tag v0.3.0 |
| Toolchain | rustc 1.98.1, pinned in rust-toolchain.toml |
| Semantic epoch | 29 (crates/nazm-cache/src/identity.rs) |
| Interface schema | nazm.interface/11 |
| Runtime ABI revision | 14 (crates/nazm-runtime/src/lib.rs) |
| Other identities | nazm.package/1, nazm.lock/1, nazm.registry-index/1, standard library 1.0 (stability.md) |
| Binary | bin/nazm, Linux aarch64, SHA-256 efc435cedff41f7c0e501c5030eba0a1270c3d1b20d9d3bb92c9d044a73f50af; prints “Nazm language v0.3, toolchain 0.3.0” |
| Archive | nazm-release-candidate.tar.gz, 7.0 MB, SHA-256 a5e2ee974fa5810ed8dfaa2a0359c0ac6acab743dc93ba0e95de84500ebf1f5b |
Final support status
| Class | Status at this candidate |
|---|---|
| A — core | every row VERIFIED, as N108 left them (areas 1, 2, 2a, 3–9, 10, 10a, 10b, 11–15, 22–24, 29, 30’s mutation half, 31; selfhost parity 21 of 21) |
| B — ecosystem and domain | eight PARTIAL, each with its limitation stated: 21 AI/HPC, 25 LSP and MCP, 26 package and build tooling, 27 debugger and profiler, 28 performance measurement, 32 reproducibility and provenance, 33 platform and target matrix, 34 smart contracts; and 30’s fuzzing half. A release limitation, not core debt |
| C — external blockers | BLOCKED, each by a named cause: the in-process JIT (area 12: unsafe forbidden, no executable-memory crate offline); proofs of the formal core (no proof assistant or solver here); sBPF execution (area 34: no sBPF toolchain offline); a second GPU provider (area 21) |
| Compile-only | x86_64-unknown-linux-gnu: nazm build --target produces objects, nothing ran on amd64 here (support.md). R1 gained no x86_64 Linux run, so it stays compile-only |
| Non-goals | Windows, 32-bit hosted and big-endian targets, with reasons (support.md); macros, trait objects, effect handlers and the rest of roadmap.md’s post-release table are tracks or research, not defects |
Evidence
All contained runs are Docker, offline, nazm-contained:1.98.1, Linux aarch64, serial, from clean
worktrees, on 2026-10-07. The harness’s verification volumes were cleared before the final gate and
the candidate’s worktree was new, so no check, object or cargo cache from before 47daadf was used.
| Stage | Commit | Result |
|---|---|---|
Workspace suite (contained tests) | 47daadf | 2,492 passed, 0 failed, 47 ignored, 200 binaries |
Workspace suite, inside the release assembly (cargo test --workspace) | 7a16a40 | 2,492 passed, 0 failed, 47 ignored, 179 test binaries — twice, once per assembly (by crate below) |
Host-safe subset on macOS (workspace-tests --host-safe, CI’s command) | 7a16a40 | 178 binaries, one left out by its guard; every one passed — execution_boundary failed only because NAZM_REQUIRE_NONUTF8, the Linux job’s switch, was set on APFS, and passed 14 of 14 without it |
Self-hosting (contained selfhost) | 47daadf; c730626 | 43 of 43; 43 of 43 from cleared volumes |
| Bootstrap C1 → C2 → C3 | 47daadf; in both assemblies at 7a16a40 | C2 = C3 18481f2a…, byte-identical; 34 conformance cases (14 multi-module) and 29 refusals agree — self-reproduction, not correctness |
Lifecycle (xtask --test lifecycle --ignored) | 47daadf | 19 of 19; the SIGINT test 25 of 25 launched in the background (N108’s failing mode) and 5 of 5 in the foreground, the harness-death test 3 and 3; no outcome rests on a sleep, every wait is a polled condition with a deadline |
Fuzzing, every target, 300 s each (contained fuzz 300) | c730626 | five targets, 3,775,962 executions, 0 crashes; run’s 34 hangs are programs that block, as at N108 (Nazm does not promise deadlock freedom) |
Compiler benchmark (bench --check, inside the assembly) | 7a16a40 | passed |
xtask check, docs and claims gates | 7a16a40 | passed |
Release assembly (contained --profile p4t4 release), twice | 7a16a40 | passed, 1,715 s each; 220 files verified against MANIFEST.txt |
| Platform runs (QEMU, WebAssembly, EVM, GPU, debuggers) | — | not rerun: R1 changed no backend, runtime or target code; N108’s 15 of 15 at 82936f6 stand for them |
c730626 → 7a16a40 changes docs/grammar.ebnf and the guide generated from it, and 47daadf →
c730626 documentation, the capability report’s text, one example and the catalogue, so the stages
run at 47daadf and c730626 stand for this commit. An assembly at c730626 failed in the suite
— nazm-syntax’s grammar test, on the production that had no example — which is why 7a16a40
exists.
What GitHub CI establishes, and what only the contained gate does
.github/workflows/ci.yml runs, on an uncontained ubuntu-latest runner: formatting, lints,
cargo xtask check, the host-safe subset (cargo xtask workspace-tests --host-safe, every test
binary except those that call the containment guard — the selfhost and bootstrap stages), the
lifecycle tests and the benchmark harness’s self-test. It establishes that those pass on x86_64
Linux, and nothing about the compiler stages it leaves out. It is not the release gate, and no
green CI run has been recorded yet (area 33). Only the contained gate above — contained tests,
selfhost, bootstrap, fuzz, mutate and release — establishes this candidate; an ordinary
cargo test --workspace on an uncontained host is neither permitted for those stages nor equivalent
to them (runbook.md).
Mutation evidence
The catalogue holds 1,273 entries. Which campaign established each:
| Campaign | Commit | Entries | Result |
|---|---|---|---|
N108’s gate — every entry the catalogue then held (releases/82936f6.md) | fc509ce → 82936f6 | 1,268 | 1,268 caught |
R1-C1, responsibility-mapped (b90442992da24c7f): the two new reference-index entries and twelve historical ones on the index, captures, trait calls, rename’s re-check, snapshot references and resolved units | 47daadf | 14 (2 new) | 14 caught at tier 1, 14 of 14 killers verified |
R1 harness and release tooling (fee2785e528773a1): the three new entries — the host-safe subset recognising the guard, the build-input digest covering Cargo.lock and every file’s contents — and three historical ones on the suite runner | c730626 | 6 (3 new) | 6 caught at tier 1, 6 of 6 killers verified |
0 survived, 0 unusable, 0 not injected, 0 without a verdict in either R1 campaign. N108 caught all 1,268 catalogue entries present at its gate; R1-C1 added two reference-index mutants and R1 three tooling mutants, each caught in its own responsibility-mapped campaign. Every current entry has a verdict of caught, from one of these three campaigns — not from one campaign over 1,273.
Performance
R1-C1 reads one more table into the reference index: building it for the compiler written in Nazm took a median of 2.70 ms after against 2.69 ms before (release build, 30 runs), that compilation having no function values; the cost is linear in the number of function values. The release assembly’s benchmark check passed.
Reproducibility and provenance
Kept apart, as capability-matrix.md area 32 requires:
| Claim | At this candidate |
|---|---|
| Source identity | source-commit: 7a16a40…, source-tree-clean: yes (PROVENANCE) |
| Build-input identity | build-input-digest: 0c8a851b1ce220f4e46d6540969a97727bf7fc149a0b26dd0692b48b6c581860 — SHA-256 over scripts/source-digest.sh --list’s files, which is every file git tracks (equal to git ls-files in a clean checkout, xtask/tests/release.rs); .nazm/ caches and other ignored files excluded |
| Artifact manifest | MANIFEST.txt: 220 files with SHA-256, written by the assembly and checked by it; redigested independently below |
| Reproducibility | Two assemblies of 7a16a40, run one after the other in the same image on one host, gave byte-identical archives (a5e2ee97… both times), with identical MANIFEST.txt and PROVENANCE.txt. Every date inside is the commit’s (SOURCE_DATE_EPOCH, 2026-10-07T08:53:50Z). Nothing is claimed across hosts, images or toolchains |
| SBOM | sbom.json in the evidence bundle, nazm.sbom/1: the 261 crates Cargo.lock names and its BLAKE3 digest, rustc 1.98.1. What Cargo.lock claims; nothing checks a crate against its upstream. A program’s CycloneDX SBOM is nazm build --sbom (N94) |
| Signed attestation | none: signing needs a person’s key. nazm attest sign/verify exist (N94) and are step 6 of the procedure below |
Independent verification of the artifact
The archive was extracted on the host and every file’s SHA-256 recomputed with Python’s hashlib,
not with the tool that wrote the manifest: 221 files in the archive, 220 manifest entries, 220 of
220 match, none missing, and the only file not listed is MANIFEST.txt itself; bin/nazm is the
manifest’s binary-sha; the archive’s MANIFEST.txt and PROVENANCE.txt are the published ones.
The manifest names version: nazm 0.3.0, the binary’s own text is “Nazm language v0.3, toolchain
0.3.0”, and the README inside is the v0.3.0 page. The archive’s file name does not carry the
version; the publisher names the uploaded file (step 7).
Evidence index
target/gates/r1f/evidence-7a16a40/ — an evidence bundle (nazm.evidence/1), 23 files indexed by
BLAKE3, index.json SHA-256 550f1a963bb7aaa1cf32d7b5304deba4b1c79b2cb01cfcd6d560190c363e0123,
verified with cargo xtask evidence --verify: the release’s MANIFEST.txt and PROVENANCE.txt, both
archives’ SHA-256, the independent redigest, both assembly logs and the failed c730626 one, the
c730626 and 47daadf gate logs with both campaigns’ journals, the lifecycle runs and the host-safe
run. The archives are under target/gates/r1f/final-rc1/ and final-rc2/, build output and not
tracked.
Known limitations
limitations.md is the list. In the release’s terms: the eight class-B rows’ limitations; the
class-C blockers; x86_64-unknown-linux-gnu compile-only; reproducibility shown on one host and one
image only; no signed attestation of this candidate; the oracle runs the sequential subset only; the
interpreter, the compiler written in Nazm and a program that calls C keep a thread per task;
structure completion offers no methods, and at x.m() and x.m(1) it declines with two different
internal reasons (both “no answer”; no schema or protocol exposes the difference); the parser’s
help text for a refused construct still lists the v0.1 subset, and nazm capabilities’s types
line lists the eight built-in type names and not the five other capability types.
The human release procedure
Every step is a person’s, in this order, from a clean checkout of exactly this commit. Stop at the first step that does not pass.
- Check out the commit.
git checkout 7a16a40640b44f93713f8209d714f1fd20f45420;git status --porcelainmust print nothing. Delete any.nazm/directory a build before47daadfleft in the checkout. - Build the images (network here and nowhere after):
docker/contained.Dockerfile(nazm-contained:1.98.1), and for the platform runsnazm-qemu:n86,nazm-wasm:n64,nazm-evm:n70andnazm-debug:n58. - Run the gates, contained and offline, each exiting 0:
cargo xtask contained cache clear;cargo xtask contained tests;cargo xtask contained selfhost;cargo xtask contained bootstrap;cargo xtask contained fuzz 300;cargo test -p xtask --test lifecycle -- --ignored --test-threads 1;cargo xtask checkandcargo test -p nazm-cli --test docs; and, if a full campaign is wanted rather than this file’s composition,cargo xtask contained --profile p4t4 mutate --strategy targeted --verify-killers, resumed with--resumeuntil complete. - Run the platform tests on the host:
cargo test -p nazm-cli --test accel --test boards --test contract_property --test debugger --test debugger_v3 --test evm --test freestanding --test realtime --test wasm --test wasm_contract -- --ignored. - Assemble the candidate twice:
cargo xtask contained --profile p4t4 release, copyingtarget/release-candidate/aside after each; the twonazm-release-candidate.tar.gzmust be byte-identical (cmp), and their SHA-256 must be this file’sa5e2ee97…if the image is the same. It tags, pushes and uploads nothing. - Verify independently, and attest if wanted: extract the archive and compare every file’s
SHA-256 with
MANIFEST.txt, both ways;cargo xtask evidence --verifyover the gate’s evidence bundle; optionallynazm attest sign --key KEY PROVENANCE.txt nazm-release-candidate.tar.gzandnazm attest verifywith the signer’s allowed-signers file. - Decide. Only then, and only by a person: tag
v0.3.0at this commit, push the branch and the tag, and publish the archive — named for the release, for examplenazm-0.3.0-aarch64-unknown-linux-gnu.tar.gz(the bytes unchanged) — withMANIFEST.txt,PROVENANCE.txtand this file beside it. Enable GitHub private vulnerability reporting, whichSECURITY.mdnames first, and confirm the maintainer address it falls back to. None of this has been done.
Nothing has been pushed, tagged or published.
Appendix — the workspace suite by crate
The release assembly’s cargo test --workspace at 7a16a40, read from its log (final1.log in
the evidence bundle; final2.log is identical in every count), binary by binary, grouped by crate;
doc-tests are one row.
2492 passed, 0 failed, 47 ignored.
| Crate | Passed | Ignored |
|---|---|---|
nazm-agent-bench | 21 | 0 |
nazm-bench | 109 | 0 |
nazm-cache | 64 | 0 |
nazm-cir | 0 | 0 |
nazm-cli | 1158 | 22 |
nazm-codegen-clif | 1 | 0 |
nazm-core | 386 | 0 |
nazm-diag | 6 | 0 |
nazm-docs | 25 | 0 |
nazm-formal | 11 | 0 |
nazm-iface | 42 | 0 |
nazm-lir | 23 | 0 |
nazm-mcp | 33 | 2 |
nazm-mir | 1 | 0 |
nazm-package | 24 | 0 |
nazm-repo | 21 | 1 |
nazm-runtime | 8 | 0 |
nazm-sema | 30 | 0 |
nazm-service | 258 | 1 |
nazm-span | 14 | 0 |
nazm-syntax | 101 | 1 |
nazm-tokens | 16 | 1 |
xtask | 140 | 19 |
| doc-tests, every crate | 0 | 0 |