Repository navigation
release: 5.9.0 — three ways a program could be silently wrong - #708
Merged
Merged
Conversation
Two `severity:high` defects in this release share a failure mode, and it is the one this project treats most seriously: the program did the wrong thing and reported success. #691 a callback handed to an imported module's function. Inside a workflow step the step truncated at the call, nothing was raised, and the run reported `failed: []` with `steps: {}`. Five symptoms came out of one construct because a closure's address indexes the chunk it was compiled from, and the symptom is whatever sat at that address. #696 the same question in the other direction -- a closure a module RETURNS. No workflow needed; `let f = m.make_adder(3i)` at top level was enough, which made a factory function unusable. It could not share #691's fix: every context source that one uses records something a call is still INSIDE of, and a returned closure is called after all of them are gone. #704 the bytecode cache keyed on path and mtime and never on content, so an edit landing inside the platform's timestamp resolution ran the PREVIOUS program. Not a PyPy bug -- five rapid rewrites with different content produced 2 distinct cache keys out of 5 on CPython too. Added: #170 binary file I/O (`fs.read_bytes`, `fs.write_bytes`), which is what a Nodus program needs to write a compiled artifact -- a Stage 3 bootstrap gap the Runtime Readiness audit recorded. Performance: #702, ~9.6x recovered on PyPy. `VM.__init__` sat at 79 instance attributes and PyPy loses map-based storage above 80; a goal-budget feature made it 80 and cost ~9x for three releases with every gate green, because CPython is flat across that boundary and every gate here is CPython. Tooling: #412 phase 4 finishes the opcode audit -- all 49 now carry a semantic spec, verified by 52 mutations with 52 killed. New guards over the filesystem builtin surface, `BUILTIN_NAMES` checked against the live registry, and a test that counts the VM's instance attributes so the next crossing of the PyPy cliff fails on the PR that causes it. Release steps 1-4c: suite 3,353 passed, 8 skipped (was 3,132 at the 5.8.0 cut) ruff / mypy clean fmt --check clean keyword coverage 13 passed nodus_gate --all 9 phases green; closed-issues 6/6 --closed-issues --section 5.9.0 6/6 (re-run after the cut, not before) --versions 10 of 13 claims were stale and are fixed; now 13/13 llms.txt synced into the wheel copy Gate 10b probes written BEFORE the tag, per the rule that they are the only check reading the release's *claims* rather than its code: four behaviour probes and one prose probe added for 5.9.0, 88/88 passing. Each 5.9.0 probe runs in the position its documentation points at -- the #691 lesson, since that defect survived a full suite, nine gate phases and 83 probes that all ran in `fn main()`. The README's "Recent" paragraph is rewritten now rather than after the tag: `readme = "README.md"` makes it the permanent PyPI page. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EdYjdCRLuedehwRCdi2hXb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release PR for 5.9.0. Steps 1–4c of the sequence are done; this is step 5.
Why now
Two
severity:highdefects in this release share a failure mode, and it is the one this project treats most seriously: the program did the wrong thing and reported success. Both are fixed onmainand neither is on PyPI.failed: []withsteps: {}. Five symptoms from one construct, because a closure's address indexes the chunk it was compiled from and the symptom is whatever sat at that address.let f = m.make_adder(3i)at top level was enough, which made a factory function unusable. It could not share #691's fix: every context source that one uses records something a call is still inside of, and a returned closure is called after all of them are gone.Added: #170 binary file I/O (
fs.read_bytes/fs.write_bytes) — what a Nodus program needs to write a compiled artifact, a Stage 3 bootstrap gap the Runtime Readiness audit recorded. A feature, so a minor bump is the right shape.Performance: #702, ~9.6x recovered on PyPy.
VM.__init__sat at 79 instance attributes; PyPy loses map-based storage above 80. A goal-budget feature made it 80 and cost ~9x for three releases with every gate green — because CPython is flat across that boundary and every gate here is CPython.Tooling: #412 phase 4 finishes the opcode audit — all 49 carry a semantic spec, verified by 52 mutations, 52 killed. Plus guards over the filesystem builtin surface,
BUILTIN_NAMESchecked against the live registry, and a test counting the VM's instance attributes so the next crossing of the PyPy cliff fails on the PR that causes it.Release steps completed
fmt --checknodus_gate --allversion.pyandpyproject.tomlboth 5.9.0[Unreleased]→## [5.9.0] - 2026-08-31--closed-issues --section 5.9.0--versionsllms.txtHousekeeping done first:
[Unreleased]had 2×### Fixesand 3×### Tooling. Consolidated to one of each inAdded → Fixes → Performance → Toolingorder, with issue references verified identical before and after.Gate 10b probes, written before the tag
Four behaviour probes and one prose probe added for 5.9.0 — 88/88 passing. They are the only check that reads the release's claims rather than its code, and running them after the tag would make any correction impossible.
Each 5.9.0 probe runs in the position its documentation points at. That is #691's lesson rather than a preference:
retry.untilhad a full suite, nine gate phases and 83 probes behind it and did not work inside a step body, because every one of them ran infn main().Two of the new probes failed on first run — my own bug, absolute paths in an
import, then relative imports resolving against CWD rather than thefilenamelabel (#521's territory). Fixed by writing a realmain.ndand usingrun_file, which is the route the regression tests take for the same reason.Remaining after merge
Tag → wheel → Gate 10a dependent suites (before any upload) → Gate 10b against the built wheel from outside the repo with
--require-installed→ PyPI → Stage 5 → GitHub release → Stage 6 sweep, with the three eval documents.🤖 Generated with Claude Code
https://claude.ai/code/session_01EdYjdCRLuedehwRCdi2hXb