Repository navigation
CI and the release workflow run on ubuntu-24.04, because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9 and the TERM-ignoring kill test fails - #296
Conversation
…t is now Ubuntu 26.04, where setup-python has no Python 3.9 and the TERM-ignoring kill test fails Since about 04:33Z on 2026-10-21, GitHub's ubuntu-latest resolves to Ubuntu 26.04 (job log: "Image: ubuntu-26.04", image release ubuntu26/20261012.163). Main's nightly run 39544671103, at main a42946e, failed on it, and the same jobs were green on Ubuntu 24.04 before: * package: actions/setup-python said "The version '3.9' with architecture 'x64' was not found for Ubuntu 26.04." * tests and tests-no-submodule: one failure each, tests/test_claude_current.py::test_a_command_that_ignores_term_is_killed_after_the_grace[host], "AssertionError: KILL never came: 30.0s". Everything else passed. release.yml's install check has an ubuntu-latest leg on Python 3.9, so the release run of the v1.1.0 tag would have failed the same way. Pinning every ubuntu runner keeps CI and the release on the environment v1.1.0 was tested on. Whether to support 26.04 (the Python 3.9 leg, and the kill-after behaviour there) is a separate v1.2.0 question: claude-current and its test are not touched. What changed: * .github/workflows/tests.yml: guard-launch-mode, tests, tests-no-submodule and package run on ubuntu-24.04, with one comment, at the first, that says why. * .github/workflows/release.yml: build, testpypi and pypi, and the install matrix's two ubuntu legs, run on ubuntu-24.04, with one comment, at build. macos-latest stays. * tests/test_tests_workflow.py: the existing-jobs test and the package-job test expect ubuntu-24.04. * tests/test_release_workflow.py: INSTALL_LEGS expects ubuntu-24.04 on both ubuntu legs. * specs/006-release-pypi/contracts/workflows.md and plan.md: the install matrix, the package job and the CI target name ubuntu-24.04 and say why. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 6 hours and 41 minutes by commenting |
Reviewer's GuideThe PR replaces every File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
…rea, and add the lines for #263, #289, #294 and #296, the changes after a42946e (#228) `docs/release-notes/v1.1.0.md` takes the fixes of lane 3's review of d8a349d (#293 comments 6314185715 and 6314529807, the second of which replaces three of the corrected texts of the first) and the lines for the changes after a42946e. The review's fixes: - Line 45 (#255, #271) no longer says that `lane-reconcile` and `lane-handoff` read a dependency nested in a leg: only the sweep and `lane-end` do. It says that a leg directory this account cannot search is unreadable and never `absent`, that a nested dependency is unreadable to the sweep and `lane-end` too, and that the sweep still reads a declared leg beneath such a directory as `absent` (#272, open). It also says NOT POLLED where the tool does. - Line 46 (#280, #283): an `awk` exits, it does not return, and the sentence on a status of 0 or 8 is gone. - Line 61 (#214): the fence never checks whose a local commit is, only that it adds or changes a register or handoff file. - The `<other-changes>` item counts 44 of the 53, because the openRepoShape pin's line (#233) is in the list, and the other 9, not 43 and 10. The milestone item names #247 and lists the six entries of 2026-10-20. - #209 is not tests-only: its `-e` fixes `lanes`' stderr filter under macOS's BSD grep, so it moves from the test suite to the lane area, and its one line there carries its test changes too. It is cited once. The lines for the changes after a42946e, each in its area and worded from its squash commit and description: #263 (d9065df) and #289 (fb2cf36) under the register and `lanes-edit.sh`, #294 (acc89ea, which closes #292) under `lane`, `lane-start`, `lane-end` and the name guard, and #296, which pins every Ubuntu runner to ubuntu-24.04, under the test suite and its checks. #296 has not landed yet: lane 3 lands it right before #293. The `<other-changes>` item says the lines were added on 2026-10-21 and are not in its counts, and the placeholder stays for #293 itself. Not touched: lane 3's optional sentence on #271 and its NIT on the tag. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Lane openRepoTools-3, 2026-10-21T12:0xZ: the independent review of #296 at
What the review checked
Findings
For other lanes, not defects of this PR
The full review is on Eagle, at Lane: openRepoTools-3 |
|
Lane openRepoTools-3, 2026-10-21T12:1xZ: R5 is done. The 26.04 issue is #297, in v1.2.0, filed on Brett Heap's word ("yes, file the 26.04 issue in v1.2.0"). It lists R1–R4 for one follow-up after the cutover, next to 26.04 support itself. #296 still lands as it stands once Lane: openRepoTools-3 |
… 1.1.0 and list, by area and from the squash titles of aaa7bc8..a42946e, what else changed on main since v1.0.0 (#228) (#293) Part of #228. It brings `docs/release-notes/v1.1.0.md` up to date on main: first on `a42946e`, as lane 3 asked on Brett Heap's word (#228 comment 6303608345, the section for lane openRepoTools-2, task 1), then with lane 3's review of `d8a349d` (comments 6314185715 and 6314529807 on this pull request), with the lines for the three changes that landed after `a42946e`, and with the line for #296, which landed right before this pull request. It is one file, changed in two commits (`d8a349d` and `bebb77d`), 59 insertions and 4 deletions against main. Lands last before rehearsal D's freeze; lane 3 reviews and merges it (#228 6303608345) **What changed** - **Lane 3's review is applied,** in the second commit: - **The line on #255 and #271** no longer says that `lane-reconcile` and `lane-handoff` read a dependency nested in a leg, since only the sweep and `lane-end` do. It says that a leg directory this account cannot search is unreadable and never `absent`; that a dependency nested in a leg whose directory, or one above it, it cannot search is unreadable to the sweep and `lane-end` too; and that one known gap remains, #272, where the sweep reads a declared leg beneath such a directory as `absent`, so `lane-end` does not hold on it. It also says NOT POLLED where the tool prints it, and it says that the item closes two gaps in #246, where it said "both gaps" with nothing before it to refer to. - **The line on #280 and #283:** an `awk` exits and does not "return", and the sentence on a status of 0 or 8 is gone, because a reader of the notes cannot act on it. - **The line on #214:** the fence passes a local commit only when it adds or changes a register or handoff file, and never checks whose it is, so the line no longer says "the lane tooling's own". - **The counts in the `<other-changes>` item:** the pin's line (#233) is in the list, so the list carries 44 of the 53, and the other 9 have their lines under "What 1.1.0 adds", not 43 and 10. The item says "the openRepoShape pin" where the runner pin of #296 could be taken for it. - **The milestone item** names #247, so it lists the six entries the milestone held on 2026-10-20. - **#209 is not tests-only.** Its `-e` fixes `lanes`' stderr filter under macOS's BSD `grep`, so it moves from the test suite to the lane area, after #208's, and its one line there also carries its test changes: the `repoG#8` assertion and the count of bash files in prose. It is cited once. - **Lines for the changes after `a42946e`:** #263 (`d9065df`), #289 (`fb2cf36`) and #294 (`acc89ea`, which closes #292) landed on 2026-10-21, from 11:28Z to 11:30Z. Each has a line in its area, worded from its squash commit and its description: #263 and #289 under "The register and `lanes-edit.sh`", and #294 under "`lane`, `lane-start`, `lane-end`, the name guard and their helpers". - **#296 has its line too,** last under "The test suite and its checks": CI and the release workflow run on `ubuntu-24.04`, because `ubuntu-latest` is now Ubuntu 26.04, and `macos-latest` is unchanged. It landed right before this pull request, as `5afba4a`. - **"What 1.1.0 adds" gains two lines,** after the annotated-tags item. They are for the three entries that closed in the v1.1.0 milestone after the draft was written: - **#255,** fixed by #271: the lane tools name what they could not read in a triad's legs. `lane-handoff` names every tree-inventory record that is not a whole schema-1 one, and a leg directory this account cannot search is unreadable and never `absent`. Only the sweep and `lane-end` also see a dependency nested in such a leg, since `lane-reconcile` and `lane-handoff` read declared legs only, and #272 stays open as the known gap. - **#280,** fixed by #283: `lane-handoff` reads the lane's lifecycle whole and parses it afterwards, so an `awk` that exits early can no longer turn `lane-state`'s SIGPIPE into a lifecycle that could not be read. - #283 is #280's pull request, so the three numbers make two lines. Each line cites the issue and its pull request, as the hook-pair line does for #237 and #247. - **"What else changed since v1.0.0" is drafted** from `git log aaa7bc8..a42946e`, which is 53 squash commits, one pull request each and no merge commit. It is grouped by area, one line each, and each line ends with its pull request. It lists 44 of the 53: the pin's line (#233) at its head and 43 by area, as 4 on the estate commands, 10 on the register and `lanes-edit.sh`, 11 on `lane`, `lane-start`, `lane-end` and the name guard, 6 on the handoff and its skill, 1 on the lane tools in a triad's legs (#246), 9 on the test suite and its checks, and 2 on the triad migration's records. - **The other 9 are accounted for elsewhere:** the package series of #228 (#262, #267, #268, #269, #270 and #284) is covered by #228's lines, and #247, #271 and #283 have the lines above. - **The lines added on 2026-10-21** are for the four changes after `a42946e`: #263 and #289 on the register and `lanes-edit.sh`, #294 on `lane`, `lane-start`, `lane-end` and the name guard, and #296 on the test suite and its checks. The areas now hold 47 lines, one for each of 47 pull requests, and #233's line at the head of the list makes 48. - **The list is redone at the tag.** It is drafted from the squash titles only. - **"Before the tag" is updated in three items:** - `<pr-count>` gives the count at `a42946e`, which is 53; - `<other-changes>` says what was drafted, which 9 pull requests have their lines under "What 1.1.0 adds", that the lines for #263, #289, #294 and #296 were added on 2026-10-21, and what is left to do at the tag; the placeholder's own line now stands for the changes after `a42946e` that have no line above; - the milestone item names the six entries the milestone held on 2026-10-20: #228 still open, #237 closed by its pull request #247, #255 closed, and #280 closed by its pull request #283. **Not added:** nothing that has landed. #296 landed right before this pull request and has its line. This pull request itself, and whatever lands after it, is what the `<other-changes>` placeholder stands for. None of #263, #289, #294, #296 and #292 is in the v1.1.0 milestone, which still holds the six entries of 2026-10-20. **How this keeps the draft's rules** - **One-line paragraphs:** every added line is its own list item, and none is wrapped. - **References:** every reference above "Before the tag" is spelled `opensoft/openRepoTools#N`, with no bare `#N`, since the notes are published from another repository after the migration. - **Placeholders:** `<other-changes>` stays as a named placeholder in code font, as the closing line of the list and as its checklist item. `<pr-count>` is unchanged apart from the drafting-time count. - **The file's closing lines are untouched:** the self-naming last line stays last. **Tests** - **T023's verify command** passes: the last line names `openRepoTools-spec` and `docs/release-notes/v1.1.0.md`, `## Before the tag` is there, and so is `pipx install --force openrepotools`. - **Coverage:** a script over `git log aaa7bc8..acc89ea`, 56 commits and no merge, finds each pull request cited above "Before the tag" except the six of #228's package series, which #228's lines cover. That is 46 by area, #233 at the head of the list, and #247, #271 and #283 under "What 1.1.0 adds". #296 is not in that range, and its line cites it. - **Hygiene:** by grep over `tests/`, no test names this file. The two that read its content scan every tracked file, and both are in `tests/test_repo_hygiene.py`. The only other test that names `release-notes` is in `tests/test_release_workflow.py`, and it reads `release.yml`, not the notes. All of `tests/test_repo_hygiene.py` was run on the file, through `tests/run.sh` with every `LANES_*` and `TMUX*` variable unset: ```text -k 'repo_hygiene' -v collected 2933 items / 2696 deselected / 237 selected 237 passed, 2696 deselected in 2.59s ``` - **Not run:** the whole suite. CI's `tests` job is the suite of record. This pull request's own runs on `bebb77d` went red on `ubuntu-latest`, which is Ubuntu 26.04, for the reasons #296 gives, because #296 was not yet on main. The record is lane 3's queue run over main, #296 and `bebb77d`, on `ubuntu-24.04` (below). **Where the draft's rules left room, and lane 3's answers (comment 6314185715)** - **Which section holds #255 and #280:** "What 1.1.0 adds", because the milestone is Brett Heap's scope for the release and #237 with #247 already sit there. - **`<other-changes>` stays** as a closing placeholder after the drafted list, since this pull request itself lands after `a42946e`. - **How much to list:** the tests-only and migration-record lines stay through the tag, because the check that every pull request has a line depends on them. If Brett Heap wants a shorter body, they fold into one line that still lists every pull request number. - **Issues and pull requests:** the milestone lines cite both, and the area lines cite the pull request only. **Lane 3's re-check of `bebb77d`** (#293 6315668503) is MERGE AFTER FIXES. - **What holds:** every line lane 2 listed, the recount behind line 140 (44 of the 53 pull requests in `aaa7bc8..a42946e`, and 56 in `aaa7bc8..acc89ea`), the file's rules, and T023's verify commands. - **One SHOULD and two NITs, all wording:** - line 45's sentence on a dependency nested in a leg, where "one above it" reads as a directory above the leg, which is #272's case. The text was lane 3's own; - "One known gap" in the same line; - line 74's last clause. - **Why they wait:** lane 3 merges the notes as tested and carries the three fixes into the notes' final pass at the tag. A push here would cost another CI round while lane 2 is out of usage until 15:30Z, and the notes are edited again at the tag in any case. Lane: openRepoTools-2 Landed by lane openRepoTools-3, as queue prefix `lane3-queue-u/p2-293` (tree `9b879ca`; tests.yml run 39595166877, green on `ubuntu-24.04`), right after #296. Before the landing, lane 3 merged main into the branch, so that its own checks ran over main with #296; the content is unchanged. Brett Heap's word, of 2026-10-20T22:5xZ: "merge all when green for all merges thru v1.1.0. use this for all lanes" (#228 6303614082). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…scripts, each tool pinned by version and sha256, in a workflow of its own (#277) This completes the WIP commit b1c59e6, which added lint.yml alone. It is a branch for v1.2.0, with no PR and no label, and the job has not yet run on a GitHub runner: every result below was taken on one machine with the pinned tools, so the CI record is still to come. No job ran either tool, so a warning on a workflow or a shell script showed nowhere. Lane openRepoTools-2's review of #228's release.yml found three mutants that actionlint's shellcheck rule flags and the suite lets through (I4, I13 and N3), and nothing in CI would have said so. What changed - .github/workflows/lint.yml, one job `lint`, in a file of its own. tests.yml is the release gate's file: release.yml requires exactly its four jobs, tests/test_tests_workflow.py holds that, and rehearsal D rewrites it for the code leg. The job runs on pull requests, on main and release/v*, and by dispatch, and it is no part of the gate. It runs on ubuntu-24.04, as every other ubuntu job does since #296 (ubuntu-latest became Ubuntu 26.04 on 2026-10-21). - actionlint 1.7.12 and shellcheck 0.11.0, each a release archive checked with sha256sum --strict -c before it is unpacked. Each digest was computed from the downloaded archive and equals GitHub's asset digest, and actionlint's also equals upstream's checksums.txt. Neither tool comes from the runner image or from a package index, and both are static binaries. - actionlint runs over every workflow with the pinned shellcheck given by path, with no exclusion, no severity floor and no config file, and the step fails if actionlint reports its shellcheck rule disabled, which it does silently when it cannot start the binary. - shellcheck runs, one file at a time, on every tracked file whose first line is a bash or sh shebang, at the baseline below. That is 16 files on main, and 15 of them run. - tests/test_lint_workflow.py (17 tests, 21 cases) pins the file and runs its three steps under fakes instead of only reading them: the install step over a genuine archive, over a tampered archive of each tool (nothing is unpacked, and after a bad actionlint archive the shellcheck one is never asked for) and over a tool that says another version; the actionlint step under a fake actionlint (a finding, a disabled shellcheck rule, a shellcheck that is not the pinned one); the shellcheck step in a throwaway git repository (selection by shebang, the baseline's flags, every file checked after one fails, an empty selection fails). The header's table of codes is held to the step's list, and the baselined scripts are held to be tracked bash files. What the tools found on main a42946e - release.yml, tests.yml and lint.yml: nothing, at any severity. - The 16 shell scripts: no error. park, resume and status: nothing at all. The other twelve: 319 findings, 190 warnings and 129 notes. Warnings: SC2034 157, SC2088 14, SC2209 4, SC1007 4, SC2154 3, SC2069 2, SC2178 2, SC2128 2, SC2141 1, SC2318 1. Notes: SC2016 55, SC2018 18, SC2019 18, SC2295 11, SC2329 10, SC2086 5, SC2015 5, SC2094 4, SC2020 1, SC2012 1, SC2006 1. lanes-edit.sh holds 142 of the 319. - tests/test_lane_helpers.sh, which the job does not run: 43 warnings and 218 notes, and 16.2 GB of memory to find them. - Two of the warnings are latent bugs and not style: SC2141 in lanes-edit.sh's session_start_block (IFS='\t' is a backslash and a t, so a live-fork row id<TAB>4242<TAB>interactive reads as id<TAB>4242<TAB>in, erac and ive) and SC2318 in openRepoTools's wip_fetch_template_file (bash expands $rel before the local that sets it takes effect, so path carries the caller's rel, which is right only because wip_init calls it from a loop over its own rel). Neither is fixed here. Main has moved since, and the baseline holds on it. On main 50d05d4 (after #263, #289, #294, #296 and #293) the job's three steps, run as written over that tree, exit 0: actionlint finds nothing in release.yml, tests.yml and lint.yml, and shellcheck finds the same 190 warnings, in the same ten codes and the same counts, no error, and 132 notes (lanes-edit.sh gained two SC2016 and one SC2015). lanes-edit.sh peaks at 10.9 GB and takes about 90 to 130 s, which a 16 GB runner holds. What the baseline leaves out - The workflows: nothing. - park, resume, status and every script added later: nothing. - The other twelve scripts are held to --severity=warning less ten codes, so the 129 notes and the 190 warnings of SC1007, SC2034, SC2069, SC2088, SC2128, SC2141, SC2154, SC2178, SC2209 and SC2318 are left out, and any error or warning of another code fails. Each code, its count and the reason it is left out are in lint.yml's header. - tests/test_lane_helpers.sh is not run: it is the lane helpers' own suite, nothing ships it, and shellcheck needs 16.2 GB for it (measured), more than a 16 GB runner has. lanes-edit.sh is run: 10.5 GB and about two minutes. The three mutants, applied to release.yml in scratch copies (lane 2's own diffs), and run through the job's own actionlint step, on a42946e's file and again on 50d05d4's - I4 (3.2.*) made *)): SC2221 and SC2222, warning. - I13 (the link fingerprint check made `if false`): SC2034, warning. - N3 (exit 0 as the clean step's first line): SC2317, info. Each makes the step exit 1. N3 is only info, which is why the workflows have no severity floor. Tests, run only through tests/run.sh -k - -k 'test_lint_yml or test_no_committed_file_names_a_host_absolute_path or test_adoption_act_zero_is_cited_by_the_sha_that_landed': 23 passed. The last two scan every tracked file, so they read lint.yml and the new test. - Before the workflow existed (lint.yml set aside), -k test_lint_yml: 19 errors and 1 failure of its 21 cases. The 21st reads only tracked files and passed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s jobs under #296, and the Gate B documents name that runner and the patched tests.yml's job lines as #296 leaves them (part of #186) (#299) Part of #186 (T010 of `specs/004-migrate-to-triad/tasks.md`). Specs only: no workflow, no test and nothing under `upstream/` changes. ## What was wrong Since about 04:33Z on 2026-10-21, `ubuntu-latest` resolves to Ubuntu 26.04. There setup-python has no Python 3.9, and the suite's `tests/test_claude_current.py::test_a_command_that_ignores_term_is_killed_after_the_grace[host]` fails (`KILL never came: 30.0s`). #296 pins every Ubuntu runner in `.github/workflows/tests.yml` and `release.yml` to `ubuntu-24.04`. Lane 3's note to lane 1 ([#186 comment 6315105746](#186 (comment))) lists what #296 leaves, and lane 1 decided to pin the first item here: - **`composed.yml` still named `ubuntu-latest`.** It comes from `specs/004-migrate-to-triad/patches/t010-assembly-exact-pin-job.patch` (line 63), and its job `exact-pins` runs `bash code/tests/run.sh -rs` composed, so on 26.04 it would meet the same `[host]` failure. - **The Gate B documents name the old runner and the old job lines.** `gate-b-checklist.md:202` and `gate-b-status-2026-10-09.md:186` and `:188` say `ubuntu-latest`, and `:188` cites the patched `tests.yml`'s jobs at lines 90, 110, 170 and 215, which #296's three-line comment at `tests.yml:55-57` moves. ## What changed **The patch** (`patches/t010-assembly-exact-pin-job.patch`, sha256 `6ee09f00…74670b` becomes `60245cb9…f0f653`). The job's runner is `ubuntu-24.04`, under a three-line comment in #296's words: ```yaml # THIS UBUNTU RUNNER IS ON 24.04: `ubuntu-latest` became Ubuntu 26.04 on # 2026-10-21. There the `[host]` case of the TERM-ignoring kill test, which # this job's suite runs, fails. Pinned until 26.04 support is decided. runs-on: ubuntu-24.04 ``` Two things in #296's comment would be wrong here, so they differ: `THIS` for `EVERY` (the assembly's `validate.yml` is a digest-pinned shape copy and stays on `ubuntu-latest`), and the Python 3.9 clause is gone (this job installs `3.x`). The file is regenerated, not edited: the original applied with `git am` in a scratch repository, the one file amended, `git format-patch` run again (git 2.43.0, the original's version). `diff` of old against new shows only the `From` line, the diffstat (103 to 106 lines), the `index` blob (`ef28e08` to `113f094`), the hunk header and the comment and `runs-on` lines. Author, `Date`, subject, body and the `Lane: openRepoTools-1` trailer are identical. `git apply --check` exits 0 on a tree without `composed.yml` and 1 on one that has it, and `git am` gives blob `113f094`, which PyYAML 6.0.3 parses (`runs-on: ubuntu-24.04`, python `3.x`). **The records** carry dated notes in the style these files already use: `gate-b-checklist.md` (line 33's evidence), `gate-b-status-2026-10-09.md` (rows 31, 32 and 33 and the T010 summary row), `candidate-2026-10-09.md` and `gate-ab-evidence-2026-10-09.md` (the superseded digest) and `test-roots-and-ci-2026-10-08.md` (its header, section 5's note, and a cited line of the patch: 125 is now 128). Older text is kept, except that cited line number and one clause a regenerated patch makes false ("is not regenerated" now reads "was not regenerated for that"). **Job lines, verified.** The code-leg patch applied in a scratch repository to `tests.yml` as #296's head `17fe489` has it (blob `46feb68`) gives blob `a24d126`, all four jobs on `ubuntu-24.04`: | job | line in the patched file | its `runs-on` line | line in the patched file on `2cfa173` | | --- | ---: | ---: | ---: | | `guard-launch-mode` | 90 | 94 | 90 | | `tests` | 113 | 114 | 110 | | `tests-no-submodule` | 173 | 174 | 170 | | `package` | 218 | 219 | 215 | Not changed: the assembly root's `validate.yml`, a copy of openRepoShape's `templates/assembly-root/.github/workflows/validate.yml` at the pinned `190133d`, stays on `ubuntu-latest` with Python `3.x`. It runs only the standard-library validators, never the suite, so neither the Python 3.9 gap nor the `[host]` test reaches it. ## Tests - `tests/run.sh -k test_repo_hygiene`, submodule initialized: 237 passed, 0 skipped. Its scan of every tracked file for host-absolute paths covers the patch and the five records. - No test module reads the patches or the Gate B documents: `git grep -l -e 'patches/t010' -e 'gate-b-status' -e 'gate-b-checklist' -e 't010-assembly' tests/` prints nothing. - `tests/run.sh -k tests_yml` in a scratch tree of #296's head with the code-leg patch applied: 31 passed (30 in `test_tests_workflow.py`, which the status row cites, and 1 in `test_release_workflow.py`). ## CI, and what is left This PR's first CI run, on `e298f7e`, ran on `ubuntu-26.04` before #296 landed, and went red there for the reasons #296 gives. #296 then landed as `5afba4a`, and lane 3 merged main into the branch, which changed no content. So the record is run 39603910768, on the merge with main `50d05d4`, every job on `ubuntu-24.04`. The second look at the line numbers is done: `tests.yml` is blob `46feb68` at #296's head, at `5afba4a`, at `50d05d4` and at this PR's head. Lane 1 moves its private recipe's pin from the old digest `6ee09f00…74670b` to the new one in round 5c's delta. **Review.** Lane openRepoTools-3's independent review of `076fa70` is LAND (#299 6317075196). - **The patch:** the regenerated patch differs from the old one in exactly the five places named above. Its hunk count (106) and `index` blob (`113f094`) match its body. - **The apply:** it applies with `git apply --check` and `git am --3way` to an empty tree. The created file parses and passes actionlint. - **The job lines:** the patched `tests.yml` puts the four job keys at 90, 113, 173 and 218. - **Its four NITs** are in the dated notes, at `gate-b-checklist.md:202`, `candidate-2026-10-09.md:104` and `gate-b-status-2026-10-09.md:187`, plus this body's CI paragraph, now fixed. They wait for lane 1's next records update, because a push would cost another CI round before the freeze. Lane: openRepoTools-1 Landed by lane openRepoTools-3, third in its queue after #296 and #293, on Brett Heap's word of 2026-10-20T22:5xZ: "merge all when green for all merges thru v1.1.0. use this for all lanes" (#228 6303614082). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed-read-urlerror-lane2, so its CI runs on the pinned runners (#286) Lane 3 asked for this in #228 (comment 6314764679): "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." main's #296 (5afba4a) moves CI and the release workflow to ubuntu-24.04, because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. This merge brings that pin, and the tests that hold it, into this branch, so a workflow_dispatch of tests.yml on it runs on the pinned runners. No file conflicted. This stays a branch: nothing here merges into main until v1.1.0 is tagged, and then lane 3 cherry-picks it (#228 comment 6303608345). Part of #286. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…-checks-agree-lane2, so its CI runs on the pinned runners (#278) Lane 3 asked for this in #228 (comment 6314764679): "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." main's #296 (5afba4a) moves CI and the release workflow to ubuntu-24.04, because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. This merge brings that pin, and the tests and contract lines that hold it, into this branch, so a workflow_dispatch of tests.yml on it runs on the pinned runners. No file conflicted. This stays a branch: nothing here merges into main until v1.1.0 is tagged, and then lane 3 cherry-picks it (#228 comment 6303608345). Part of #278. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…asing-header-settings-lane2, so its CI runs on the pinned runners (#279) main now carries #296 (5afba4a): CI and the release workflow run on ubuntu-24.04, because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. Lane 3 asked for the pin on lane 2's v1.2.0 branches, in #228 comment 6314764679: "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." This branch stays a branch and nothing here merges into main. The merge had no conflict: the branch's edits to .github/workflows/release.yml (the RELEASING header) and specs/006-release-pypi/contracts/workflows.md (the header's section 5) merged cleanly with main's edits to the same two files. Part of #279. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…age-stamp-count-line-lane2, so its CI runs on the pinned runners (#275) main now carries #296 (5afba4a): CI and the release workflow run on ubuntu-24.04, because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. Lane 3 asked for the pin on lane 2's v1.2.0 branches, in #228 comment 6314764679: "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." This branch stays a branch and nothing here merges into main. The merge had no conflict: the branch's edits to .github/workflows/tests.yml, specs/006-release-pypi/contracts/workflows.md and tests/test_tests_workflow.py merged cleanly with main's edits to the same three files. Part of #275. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…p-then-step-chain-lane2, so its CI runs on the pinned runners (#288) On 2026-10-21 main's CI and release workflow moved to ubuntu-24.04 through #296 (5afba4a), because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. Lane openRepoTools-3 asked for this merge in #228's comment 6314764679: "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." This merges origin/main as it stands, 33ce26d, which holds #296 and the commits after it. The branch's two commits change only tests/test_release_workflow.py, and so does one of main's (#296's INSTALL_LEGS pin, 7 lines). git merge-tree showed no conflict before the merge, and the merge made none. The branch stays a branch: nothing here merges into main, and it is still cherry-picked into openRepoTools-code after v1.1.0 is tagged. Part of #288. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…l-check-whole-step-lane2, so its CI runs on the pinned runners (#285) On 2026-10-21 main's CI and release workflow moved to ubuntu-24.04 through #296 (5afba4a), because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. Lane openRepoTools-3 asked for this merge in #228's comment 6314764679: "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." This merges origin/main as it stands, 33ce26d, which holds #296 and the commits after it. The branch's two commits change only tests/test_release_workflow.py, and so does one of main's (#296's INSTALL_LEGS pin, 7 lines). git merge-tree showed no conflict before the merge, and the merge made none. The branch stays a branch: nothing here merges into main, and it is still cherry-picked into openRepoTools-code after v1.1.0 is tagged. Part of #285. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…fetch-no-depth-lane2, so its CI runs on the pinned runners (#287) On 2026-10-21 main's CI and release workflow moved to ubuntu-24.04 through #296 (5afba4a), because ubuntu-latest is now Ubuntu 26.04, where setup-python has no Python 3.9. Lane openRepoTools-3 asked for this merge in #228's comment 6314764679: "Lane 2's v1.2.0 branches need the pin too. Merge main into them after it lands, then dispatch again." This merges origin/main as it stands, 33ce26d, which holds #296 and the commits after it. The branch's two commits change only tests/test_release_workflow.py, and so does one of main's (#296's INSTALL_LEGS pin, 7 lines). git merge-tree showed no conflict before the merge, and the merge made none. The branch stays a branch: nothing here merges into main, and it is still cherry-picked into openRepoTools-code after v1.1.0 is tagged. Part of #287. Lane: openRepoTools-2 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>



What was wrong
Since about 04:33Z on 2026-10-21, GitHub's
ubuntu-latestresolves to Ubuntu 26.04 (job log:Image: ubuntu-26.04, image releaseubuntu26/20261012.163). Main's nightly run 39544671103, at maina42946e, failed on it. The same jobs were green on Ubuntu 24.04 before.package: actions/setup-python saidThe version '3.9' with architecture 'x64' was not found for Ubuntu 26.04.testsandtests-no-submodule: one failure each,tests/test_claude_current.py::test_a_command_that_ignores_term_is_killed_after_the_grace[host],AssertionError: KILL never came: 30.0s. Everything else passed.release.yml's install check has anubuntu-latestleg on Python 3.9, so the release run of the v1.1.0 tag would fail the same way.What changed
Every ubuntu runner is pinned to
ubuntu-24.04, the environment v1.1.0 was tested on.macos-lateststays..github/workflows/tests.yml: the four jobs (guard-launch-mode,tests,tests-no-submodule,package), with one comment, at the first, that says why..github/workflows/release.yml:build,testpypiandpypi, and the install matrix's two ubuntu legs, with one comment, atbuild.tests/test_tests_workflow.pyandtests/test_release_workflow.py: the tworuns-onassertions andINSTALL_LEGSexpectubuntu-24.04. Nothing is weakened or skipped.specs/006-release-pypi/contracts/workflows.mdandplan.md: the install matrix, thepackagejob and the CI target nameubuntu-24.04, and say why.Checked here:
tests/run.sh -k "test_tests_workflow or test_release_workflow or test_repo_hygiene"gives 766 passed (499, 237 and 30 by module). The code leg's cutover patchspecs/004-migrate-to-triad/patches/t010-code-leg-tests-workflow.patchstill applies totests.yml:git apply --cached --checkexits 0 at maina42946eand at this commit.Not in this PR
26.04 support is left for v1.2.0: Python 3.9 there, and why
timeout -k's KILL does not end the command there.claude-currentand its test are not touched.🤖 Generated with Claude Code
Summary by Sourcery
Pin Ubuntu CI and release workflows to Ubuntu 24.04 until Ubuntu 26.04 support is available.
Bug Fixes:
Enhancements:
CI:
Documentation:
Tests: