Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/breaking/1938-upgrading-from-0-46.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Upgrading from 0.46.0:** four announced changes need code changes in some programs: the `rm` builtin is removed (use `remove_file`, #1884); removing a missing file raises `io` (#1668); tape format v7 records loaded module source as `load_file_source`/`load_file_source_chunk`, so a check that a tape holds only argv must allow them; and the observer predicates `improving` (#1771) and `equilibrium` (#1891) changed. The per-consumer table is in `docs/release-reviews/v0.47.0.md` (#1938).
65 changes: 54 additions & 11 deletions docs/release-reviews/v0.47.0.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# v0.47.0 release legibility review

Range: v0.46.0..b089b22ba7363ec4cb91b6a6fc91bab28f56c45c
Range: v0.46.0..6352151b44982fe3f4eab0b777de1792418e3f27

The range holds 62 commits; `git diff --stat v0.46.0 dde78c5c` reports 256 files changed, +12,916/−1,361. The review covered the five categories in [README.md](README.md), over the range's changes and the docs and config they touch. The fixes are three commits on `release-0.47.0-review`, one per category fixed. Anything that needs a decision or a non-trivial change is filed as a labelled issue.

Expand Down Expand Up @@ -38,24 +38,24 @@ The instruments cannot see the rest, so one-off scans (not committed) covered it
| Docs drift | `src/builtins_host.c:1565-1567` (`write_text`) and `:1890-1892` (`write_bytes`): the `fs:ANSWER` comments called the NULL `FILE*` branch the documented 0 answer. Since #1668 that branch raises `io`. | FIXED #1951 |
| Docs drift | `docs/CONCURRENCY.md:700-708`: said a nondeterministic builtin on a worker raises under `EIGS_REPLAY` "until per-thread N streams exist (#1142)". Since #1566 it replays from the worker's own stream: two workers, 200 `N` records, 3 of 3 replays byte-identical. | FIXED #1951 |
| Docs drift | `docs/TRACE.md:750-751`, with the same premise: the coverage note called `tests/test_trace_mt.sh`'s replay-workers check "fail-loud". Since #1566 that check asserts that two worker streams replay, and that a malformed stream tag exits 3. | FIXED #1951 |
| Docs drift | `src/lsp_builtin_index.h:146`, `:235`, `:236`, `:278-280`, `:285`, `:306`: the hover for `is_dir`, `secure_equals`, `seed_random`, `stream_open`/`_write`/`_close`, `task_alive` and `try_parse` says 1/0, and each returns a bool. The range did not touch these comments. | FLAGGED #1945 |
| Docs drift | `src/lsp_builtin_index.h:146`, `:235`, `:236`, `:278-280`, `:285`, `:306`: the hover for `is_dir`, `secure_equals`, `seed_random`, `stream_open`/`_write`/`_close`, `task_alive` and `try_parse` says 1/0, and each returns a bool. The range did not touch these comments. | FIXED #1957 (flagged #1945, fixed before the cut) |
| Stale reference | `docs/CONCURRENCY.md:623`, written in this range: "Closing that waits on per-thread tape streams (#1142)". #1142 closed on 2026-09-14, and the streams exist (#1566). | FIXED #1951 |
| Stale reference | `.claude/rules/c-runtime-memory.md:133-135`: names "still-unfixed" members "ledgered on #1035/#1036". Both closed on 2026-09-02, and each named member is fixed in the tree. | FIXED #1951 |
| Stale reference | `docs/TRACE.md:98`, with its twin `docs/DEBUGGING.md:91` outside the range: the anchor `#observer-configuration-1044-1045` is dead. The heading's slug is `#observer-configuration-10441045`. | FIXED #1951 |
| Stale reference | `docs/TRACE.md:92`: the example header `V 7 0.46.0`. v0.46.0 wrote format 6, and v0.47.0 writes `V 7 0.47.0`. | FIXED #1951 |
| Stale reference | `.github/workflows/ci.yml:1006`: `download-artifact@9000827c` was annotated `# v8.0.1`. That SHA is v8.0.2; v8.0.1 is `3e5f45b2`, the SHA #1892 replaced. | FIXED #1951 |
| Stale reference | `tools/selftests.txt:11`: `[99c]`/`[99d]` stay "until the runner is split (#1275 plan, step 3)". #1275 closed on 2026-09-26, and no open issue tracks the split. | FLAGGED #1946 |
| Duplicated logic | `.github/workflows/nightly.yml:108-126` keeps its own Valgrind install loop beside the shared `.github/actions/install-valgrind` and `tools/install_valgrind.sh` (#1923). The copies already differ: `libc6-dbg`, apt sources, the archive cache. | FLAGGED #1942 |
| Duplicated logic | `src/ext_db.c:14-19`: `db_replay_blocks` (#1901) copies `replay_blocks` (`src/builtins.c:2463`) with a different boundary label. | FLAGGED #1943 |
| Duplicated logic | `src/builtins_host.c:1125-1130`: `file_io_error_message` re-lists the taped filesystem builtins that `k_tape_kinds` (`src/trace.c`) owns. | FLAGGED #1943 |
| Duplicated logic | `tools/docs_claims_check.sh:292-358`: `stale_builtin_calls` (#1747) rebuilds the vocabulary of `names()` (`:249-290`) with a different call regex. | FLAGGED #1944 |
| Stale reference | `tools/selftests.txt:11`: `[99c]`/`[99d]` stay "until the runner is split (#1275 plan, step 3)". #1275 closed on 2026-09-26, and no open issue tracks the split. | FIXED #1956 (flagged #1946, fixed before the cut) |
| Duplicated logic | `.github/workflows/nightly.yml:108-126` keeps its own Valgrind install loop beside the shared `.github/actions/install-valgrind` and `tools/install_valgrind.sh` (#1923). The copies already differ: `libc6-dbg`, apt sources, the archive cache. | FIXED #1959 (flagged #1942, fixed before the cut) |
| Duplicated logic | `src/ext_db.c:14-19`: `db_replay_blocks` (#1901) copies `replay_blocks` (`src/builtins.c:2463`) with a different boundary label. | FIXED #1960 (flagged #1943, fixed before the cut) |
| Duplicated logic | `src/builtins_host.c:1125-1130`: `file_io_error_message` re-lists the taped filesystem builtins that `k_tape_kinds` (`src/trace.c`) owns. | FIXED #1960 (flagged #1943, fixed before the cut) |
| Duplicated logic | `tools/docs_claims_check.sh:292-358`: `stale_builtin_calls` (#1747) rebuilds the vocabulary of `names()` (`:249-290`) with a different call regex. | FIXED #1961 (flagged #1944, fixed before the cut) |
| Dead code | `src/fsutil.c:253-258` and `src/fsutil.h:37-39`: `eigs_file_resolve_error` has had no caller since #1901 moved both of its callers to `eigs_file_resolve_message`. | FIXED #1951 |
| Dead code | `tools/install_valgrind.sh:41-42`: `VALGRIND_APT_OPTIONS` and `VALGRIND_APT_FIRST_OPTIONS` are read, and nothing in the tree sets them. | FLAGGED #1942 |
| Dead code | `tools/docs_claims_check.sh:296-304`: `registered`, parsed from `register_builtins`, is computed and guarded, but no verdict reads it; only the summary count does. | FLAGGED #1944 |
| Dead code | `tools/install_valgrind.sh:41-42`: `VALGRIND_APT_OPTIONS` and `VALGRIND_APT_FIRST_OPTIONS` are read, and nothing in the tree sets them. | FIXED #1959 (flagged #1942, fixed before the cut) |
| Dead code | `tools/docs_claims_check.sh:296-304`: `registered`, parsed from `register_builtins`, is computed and guarded, but no verdict reads it; only the summary count does. | FIXED #1961 (flagged #1944, fixed before the cut) |
| Dead code | The `O cfg`/`O win` and scheduler-trace machinery, with its residual comments (for example `src/eigenscript.h:2366`, `src/vm.h:672`). #1688 schedules its removal for "the tape-bump release", and this range bumped the tape to format 7 (#1885) without it. | FLAGGED #1688 |
| Docs drift | `docs/BUILTINS.md:913` (`task_detach`, changed in the range): it gave a reaped task's `task_alive` as `0`. It returns `false`, and `false == 0` raises. Found by the blind critic. The same claim outside the range, at `:910` (`task_send`) and `:912` (`task_kill`), was fixed with it; all three return `false` (measured) | FIXED #1953 |

Verdict: 11 fixed, 10 flagged (#1688, #1942, #1943, #1944, #1945, #1946, #1952) over v0.46.0..b089b22b; no unflagged mismatch in the range
Verdict: 20 fixed, 1 flagged (#1688) over v0.46.0..6352151b; no unflagged mismatch in the range

## Seen outside the range

Expand Down Expand Up @@ -103,10 +103,53 @@ The instruments ran again on `b089b22b`, with this addendum's doc fix applied:

| category | location | disposition |
|---|---|---|
| Duplicated logic | `tools/tree_lock.sh` and `tools/stop_gate.sh` (#1941): two implementations of the tree lock, each naming `.make.lock` | FLAGGED #1952 |
| Duplicated logic | `tools/tree_lock.sh` and `tools/stop_gate.sh` (#1941): two implementations of the tree lock, each naming `.make.lock` | FIXED #1955 (flagged #1952, fixed before the cut) |

The other four categories were checked over the two commits:
- **Docs drift:** none. The Makefile header documents the lock, and `.claude/settings.json`'s stop-gate status text stays accurate.
- **Stale references:** none. The new comments cite #1940 as provenance, not as pending work.
- **Config drift:** none. The new `tools/selftests.txt` row is enrolled, and every trigger path it names exists.
- **Dead code:** none. The Makefile calls `tools/tree_lock.sh`; the selftest row runs `tools/make_lock_check.sh`; the test uses the `tree-lock-smoke` target.

## Addendum 2: b089b22b..6352151b, and the consumer preflight

Eight PRs merged after addendum 1. Seven fix rows this review flagged, and #1954 fixes a line it saw outside the range (#1947):
- `0392a5e3` (#1954): the shared-store builtins raise on a wrong-typed argument (#1947);
- `296a3948` (#1955): the tree lock has one implementation (#1952);
- `bdd90028` (#1956): stale issue states and a wrong path (#1948, #1946);
- `3190db91` (#1957): bool results say `true`/`false`, with a gate (#1945);
- `8316aeb6` (#1958): the release embed smoke runs on code-changing PRs (#1935);
- `a8e09cd5` (#1959): nightly's Valgrind job uses the shared install action (#1942);
- `a63824c6` (#1961): one docs call-claim vocabulary and matcher (#1944);
- `6352151b` (#1960): one replay-refusal helper; the taped-filesystem rule reads `k_tape_kinds` (#1943).

Each was reviewed against the five categories when it merged, and none adds a finding. The instruments ran again on `6352151b`:

| instrument | result |
|---|---|
| `make` | rc 0, no `warning:` line |
| `bash tools/docs_claims_check.sh` | `docs-claims: OK — PATHS 262, FLAGS 47, MAKE TARGETS 52, NAMES 427, DOC ENROLMENT 12`; `BOOL RESULT WORDING: 32 constructor-derived bool builtin(s), 60 documented row/hover entrie(s), 0 hit(s)`. NAMES moved from 426 to 427 because #1961 fixed an under-match. |
| `bash tools/stdlib_index_check.sh` | `stdlib index OK: 181 builtins + 78 modules all documented` |
| `python3 tests/test_doc_examples.py` (suite [89]'s twelve documents, from `src/`) | `Doc examples: 195 checked, 195 passed, 0 failed, 5 skipped, 0 unreadable fence(s)` |
| `bash tools/workflow_yaml_check.sh` | OK |
| `bash tools/ci_tier_check.sh` | OK |
| `bash tools/enrolment_check.sh` | `PASS: test-enrolment: examined=128 enrolled=127 exempt=1` |
| `bash tools/codspeed_targets_check.sh` | `codspeed targets: 13 declared == found; consumer rows present; DMG pinned by SHA` |
| `bash tools/selftests.sh --list` | rc 0, 45 rows |

### Consumer preflight (`tools/consumer_acceptance.sh run`, candidate `6352151b`)

All 16 consumers were run against the candidate, then each non-PASS consumer against v0.46.0 with the same harness. Each regression is bisected or reduced to its cause. **No runtime blocker:** every regression is an announced change, and each consumer pins v0.46.0, so its fix ships with its bump PR.

| consumer | class | cause | consumer change at bump |
|---|---|---|---|
| DeslanStudio | intended | `0277d7a9` (#1668): removing a missing file raises `io` | guard pre-test cleanup with `file_exists`, or catch `io` |
| liferaft, eddy | intended | tape format v7 records module source (`load_file_source`, `load_file_source_chunk`); record and replay outputs are byte-identical | an "argv-only" tape check must exclude module-source records |
| phugoid | intended | #1771 (directional `improving`) and #1891 (equilibrium), each shown by a minimal differential probe | update its plant red-set expectations |
| ouroboros | intended | `e63a3f29` (#1884): the `rm` builtin is removed | `src/frontend.eigs:2428`: `rm` becomes `remove_file` |
| EigenLua | pre-existing | the same 1800 s HANG on v0.46.0; every runtime call succeeds | none for this release; the cap is #1963 |
| DMG, EigenMiniSat | environment | the sandbox's X11 shared memory, and `drat-trim` hidden by PATH; both PASS on both versions once fixed | none |

The other eight consumers (dynamics, eigen-edit, EigenGauntlet, EigenRegex, eigen-sheet, polymethod, tidelog, Tidepool) pass.

Two release PRs follow `6352151b`, and neither changes code. The first adds the `changes/breaking` upgrading note and this addendum. The second is the cut: `tools/changelog_fragments.sh cut 0.47.0 2026-10-25` assembles the CHANGELOG and bumps VERSION.
Loading