Skip to content

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

Merged
brettheap merged 1 commit into
mainfrom
fix/ci-pin-ubuntu-24.04
Oct 21, 2026
Merged

brettheap merged 1 commit into
mainfrom
fix/ci-pin-ubuntu-24.04

Conversation

@brettheap

@brettheap brettheap commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What was wrong

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. 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 fail the same way.

What changed

Every ubuntu runner is pinned to ubuntu-24.04, the environment v1.1.0 was tested on. macos-latest stays.

  • .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, testpypi and pypi, and the install matrix's two ubuntu legs, with one comment, at build.
  • tests/test_tests_workflow.py and tests/test_release_workflow.py: the two runs-on assertions and INSTALL_LEGS expect ubuntu-24.04. Nothing is weakened or skipped.
  • 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.

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 patch specs/004-migrate-to-triad/patches/t010-code-leg-tests-workflow.patch still applies to tests.yml: git apply --cached --check exits 0 at main a42946e and 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-current and 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:

  • Pin Ubuntu-based CI and release jobs to Ubuntu 24.04 to restore Python 3.9 availability and avoid failures in the TERM-ignoring process termination test.

Enhancements:

  • Update workflow tests and release documentation to enforce and document the Ubuntu 24.04 runner requirement while leaving macOS coverage unchanged.

CI:

  • Run all Ubuntu CI and release workflow jobs on ubuntu-24.04 instead of ubuntu-latest.

Documentation:

  • Document the Ubuntu runner pin and the Ubuntu 26.04 compatibility rationale in the release workflow specifications.

Tests:

  • Update workflow assertions and release install-matrix expectations for Ubuntu 24.04.

…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>
@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown

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 @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR replaces every ubuntu-latest runner used by CI and release workflows with ubuntu-24.04, preserving macOS coverage, and updates the workflow assertions and release documentation to enforce and explain the pin until Ubuntu 26.04 support is addressed.

File-Level Changes

Change Details Files
Pin all Ubuntu-based CI and release jobs to Ubuntu 24.04 while retaining the existing macOS runner.
  • Updated the four test workflow jobs, release build and publishing jobs, and both Ubuntu install-matrix legs.
  • Added comments documenting the Ubuntu 26.04 compatibility issue and the temporary pin.
  • Kept macOS on macos-latest.
.github/workflows/tests.yml
.github/workflows/release.yml
Align workflow contract tests with the new Ubuntu runner requirement.
  • Changed test-workflow runner assertions to require ubuntu-24.04.
  • Updated release install-matrix expectations for both Ubuntu legs.
tests/test_tests_workflow.py
tests/test_release_workflow.py
Update release documentation to describe the pinned CI target and its rationale.
  • Changed documented CI, package, and install-matrix Ubuntu targets to ubuntu-24.04.
  • Recorded that the pin avoids missing Python 3.9 support on Ubuntu 26.04.
specs/006-release-pypi/contracts/workflows.md
specs/006-release-pypi/plan.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sonarqubecloud

Copy link
Copy Markdown

brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
@brettheap

Copy link
Copy Markdown
Contributor Author

Lane openRepoTools-3, 2026-10-21T12:0xZ: the independent review of #296 at 17fe489 is LAND. This change touches governed workflow files, and this review is its independent read (specs/006-release-pypi/plan.md, G6).

What the review checked

  • No live ubuntu-latest is left. It parsed both files with PyYAML 6.0.3 and with the pinned load_yaml:
    • all four tests.yml jobs, and release.yml's build, testpypi and pypi, are on ubuntu-24.04;
    • the install matrix is ubuntu-24.04/3.x, macos-latest/3.x and ubuntu-24.04/3.9.
  • Nothing keyed on the old label changes meaning.
    • The only name built from matrix.os is the install job's display name, and nothing reads it: the rulesets require no status checks, and pypi needs install by its id.
    • runner.os == 'macOS' and matrix.python == '3.9' are unaffected.
    • No artifact name, cache key or concurrency group is built from the OS.
  • The tests: 766 passed, 0 skipped (test_release_workflow 499, test_repo_hygiene 237, test_tests_workflow 30).
    • Nothing is weakened: three literals change.
    • Mutants, each put back to ubuntu-latest: the tests job, the package job and the 3.9 install leg are each killed. build, testpypi and pypi survive; that is R2.
  • Lane 1's T010 code-leg patch: git apply --cached --check exits 0 at a42946e, 17fe489, acc89ea and 6d16f66, and a real apply is clean.
  • The facts in the commit and the body match run 39544671103, and nothing is overclaimed beyond R3.
  • CI so far: guard-launch-mode and package ran on Image: ubuntu-24.04 (ubuntu24/20261018.339). package set up CPython 3.9.25 and passed 285.

Findings

  • R1 · SHOULD, follow-up: three lines still say the existing jobs are unchanged.
    • The lines:
      • specs/006-release-pypi/contracts/workflows.md:40 says they "stay byte for byte";
      • :360 says they "keep today's runs-on";
      • the docstring at tests/test_tests_workflow.py:852-853 says the same.
    • The contract also contradicts its own :364.
    • The fix: ":40, byte for byte but for runs-on, ubuntu-24.04 on every job", and ":360, run on ubuntu-24.04, and keep their checkout options, Python version and run: commands". Adjust the docstring to match.
  • R2 · SHOULD, follow-up: no test pins the runs-on of release.yml's build (:272), testpypi (:1038) or pypi (:1563).
    • Why it matters: openRepoShape's model at 190133d still has ubuntu-latest at its :162, :686 and :1128, so a re-adaptation could bring it back unseen. The build would then lose release.yml:61-63's same-runner condition.
    • The fix: one test_release_upload_ test asserting all three are ubuntu-24.04.
  • R3 · NIT: "became Ubuntu 26.04 on 2026-10-21" is this repository's first run on 26.04, not GitHub's date. It appears at six places. GitHub's notice, [Ubuntu] ubuntu-latest label will use Ubuntu 26.04 in November 2026 actions/runner-images#14748, rolls the change out from 2026-10-19 to 2026-11-19.
    • The fix: cite it, and give 10-21 as this repository's first run on 26.04.
  • R4 · NIT: release.yml:269-271 copies tests.yml's reasons, but release.yml runs no test suite.
    • Its own reasons are the 3.9 install leg, and keeping the build on the image its gate and rc1 ran on.
    • Without them, whoever fixes the kill test could unpin both files, and the 3.9 leg would break.
  • R5 · NIT: "until 26.04 support is decided" has no tracking issue.
  • R6 · NIT, for the squash body: it should carry a Lane: openRepoTools-3 line, as lane 3's other squashes do. It should also say that this review is G6's independent read, because the commit was written on sonnet-xhigh and governed files are [O] work. Lane 3's squash body adds both.

For other lanes, not defects of this PR

The full review is on Eagle, at /workspace/projects/.lane-worktrees/openRepoTools-3/briefs/ci-pin-work/REPORT-review-reply-20261021T1203Z.md.

Lane: openRepoTools-3

@brettheap

Copy link
Copy Markdown
Contributor Author

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 tests and tests-no-submodule pass.

Lane: openRepoTools-3

@brettheap
brettheap merged commit 5afba4a into main Oct 21, 2026
6 checks passed
@brettheap
brettheap deleted the fix/ci-pin-ubuntu-24.04 branch October 21, 2026 12:53
brettheap added a commit that referenced this pull request Oct 21, 2026
… 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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap added a commit that referenced this pull request Oct 21, 2026
…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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…-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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
brettheap pushed a commit that referenced this pull request Oct 21, 2026
…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>
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.

1 participant