Skip to content

tests: six skips on a failed git call ask the system first, so a failed git call fails the test and an encoding that cannot spell U+202E skips the bidi test (#853, #854) - #869

Merged
brettheap merged 26 commits into
mainfrom
l3-853-854-test-skips
Oct 18, 2026
Merged

brettheap merged 26 commits into
mainfrom
l3-853-854-test-skips

Conversation

@brettheap

@brettheap brettheap commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

How to review

Closes #853.
Closes #854.

Tests only. No tool, template, pinned file or doc changes. Beyond the two issues' text, the PR also makes six more tests in tests/test_adopt_template_values.py skip under a C locale, where they raised UnicodeEncodeError (see "Beyond #853 and #854" below).

What changed

#853, line 1: three tests no longer skip when make_source_repo fails

refused_then_moved (tests/test_adopt_template_values.py), test_a_utf8_clone_of_a_source_whose_path_is_not_utf8_adopts (tests/test_adopt_git_reads.py) and test_a_source_directory_that_is_not_utf8_is_shown_spelled (tests/test_adopt_plan_escapes.py) each wrapped make_source_repo(parent / "Thing") in except AssertionError: pytest.skip("git will not work under ..."). All three try blocks are gone.

#853, line 2, and the sixth site: three branch helpers no longer skip when git fails

with_default_branch, moved_to_a_branch_that_is_not_utf8 and remembered_on (tests/test_adopt_git_reads.py) caught except (AssertionError, UnicodeError, OSError) around the git calls that make the branch.

  • remembered_on is the sixth site. adopt-project.py: _default_branch reads origin/HEAD and HEAD by full name and whole, and reads the source only at a branch of its own, so a git clone -b source is no longer git-failed with no remedy, and a HEAD on origin/x, on main<U+00A0> or beside a tag main no longer adopts another branch's commit (#797) #830 added it after the issue's scan of main at fc867207. The same AST scan, run on this branch after merge 2, found it at tests/test_adopt_git_reads.py:730. It is called with ma, U+2028 and in (text) and with caf and byte 0xE9 (not UTF-8).
  • Each helper now calls a new function, skip_where_no_ref_can_be_named(source, branch), before its first git call, and the except is gone. That function asks:
    • for a name that is not UTF-8: skip_where_a_name_cannot_be_not_utf_8(source.parent), as the issue says. That asks Windows' os.fsencode first, then macOS's EILSEQ, on the disk the ref files go to.
    • for a name that is text: only the file name encoding. This is one step past the issue's "for a UTF-8 name, ask nothing". subprocess puts every argument through os.fsencode, so under LC_ALL=C the git call for main plus U+00A0, or for U+2028, raised UnicodeEncodeError in the test. On the base those rows skipped through the broad except, as no branch here is named b'main\xc2\xa0': UnicodeEncodeError(...). Asking nothing would have turned those skips into failures under the C locale. Under UTF-8 the question never skips.
  • moved_to_a_branch_that_is_not_utf8 asks before it makes anything, so a skip costs no make_source_repo and no plan run.
  • The skip after git symbolic-ref, in with_default_branch, stays. Whether git gives the name back as it was written is the system's answer, and no exception is behind it.

#854: the U+202E test skips under an ASCII file name encoding

test_execute_refuses_a_local_source_directory_holding_a_bidi_control now calls skip_where_the_environment_cannot_carry(parent.name) before parent.mkdir(). Nothing else in the test is guarded.

Beyond #853 and #854: six more tests skip under a C locale (fix round 1)

Under PYTHONUTF8=0 LC_ALL=C PYTHONCOERCECLOCALE=0 LANG=C LC_CTYPE=C, six tests in tests/test_adopt_template_values.py raised UnicodeEncodeError in the test body. Neither issue names them: #854 names only the U+202E test, and #853 is about AssertionError skips. They are the same kind of failure as #854, in a file this PR already changes, so this PR takes them (the review's NIT 2) and they need no issue of their own.

  • Five raised at subprocess.run in adopted. In ASCII it cannot put the value on plan's command line. They are test_plan_refuses_a_flag_no_file_can_hold[--elected-by='Jos\\u2028e'], [--elected-by='\\u202eevil'], [--reference='ref \\u2066x\\u2069 y'], test_a_valid_non_ascii_elector_still_adopts[accented] and [zero-width-non-joiner]. Each now calls skip_where_the_environment_cannot_carry with its value (the elector, in the second test) as its first line, before make_source_repo and adopted.
  • The sixth, test_a_utf8_source_directory_still_adopts_with_local_remotes, raised at the mkdir of caf and U+00E9 in make_source_repo (tests/conftest.py:916). It now asks about that directory's name before make_source_repo.
  • Measured, under C.
    • At 40531e19, the six: 6 failed, 3 passed, 69 deselected. The 3 that pass are the flag test's surrogate and TAB rows, which ASCII with surrogateescape can carry.
    • The same six failed on the base 84a09c2e and on origin/main (RV869's runs 3 and 5).
    • At bcf6952e: 3 passed, 6 skipped. Each of the six skips on "this system's file name encoding (ascii) cannot spell ...".
  • Under UTF-8, all six run and pass. Nothing in the 11-file run below is skipped.
  • CI holds the six too (fix round 2). CI runs UTF-8, where a test that asked its question after make_source_repo or adopted still passed. Six emulated rows in tests/test_non_utf8_git_failures.py now hold them (see "Fix round 2" below).

New: tests/test_non_utf8_git_failures.py (42 tests)

Each place is called as a plain function, as tests/test_non_utf8_oserror_sites.py does. The tests reuse #845's GIT_FAILED, a_source_git_cannot_make, the_error_of and BIDI_TEST, and #806's fixtures, refusing and ascii_fsencode.

group what is emulated the caller must tests
line 1 make_source_repo raises AssertionError("... No space left on device") after the byte directory is made fail with that error 3
line 1, Windows os.fsencode gives a surrogate three bytes, and make_source_repo fails skip on os.fsencode before the mkdir or git, with nothing made under tmp_path 3
line 2, not UTF-8 the module's git raises it fail with it 4
line 2, text the same fail with it 2
macOS EILSEQ on the probe skip on the helper's reason before git, with nothing made under tmp_path 4
Windows os.fsencode gives a surrogate three bytes skip on os.fsencode before the disk or git, with nothing made 4
text asks nothing about the byte both of the above, with git failing fail with git's error, not skip 2
ASCII encoding, text branch os.fsencode is ASCII skip on "file name encoding" before git 2
#854 os.fsencode is ASCII, and os.mkdir raises UnicodeEncodeError as the real one does there skip on "this system's file name encoding ... cannot spell", with nothing made 1
#854, the six template-values tests (fix round 2) os.fsencode is ASCII, and make_source_repo fails skip on "file name encoding" before make_source_repo, with nothing made under tmp_path 6
the scan every tests/*.py, read as #853's scan reads it, and wider no except that catches an AssertionError holds a pytest.skip. That covers one that names AssertionError, Exception or BaseException (alone or in a tuple), and a bare except 1
the scan's own rows found: except AssertionError alone, in a tuple, or with the skip behind a raise; except Exception; except (OSError, BaseException); a bare except. Not found: except AssertionError or except Exception with no skip; one for another error; the symbolic-ref kind of skip as listed 10

The states the helper answers still skip for the three line-1 tests:

All of them pass in the runs below.

AST scan after the change. I re-ran #853's scan, an except that names AssertionError and holds a pytest.skip, over tests/*.py. It finds no site. Before the change it found 6 on the merged tree: the issue's 5 and remembered_on.

Fix round 1 widened the scan (the review's NIT 3).

  • skips_on_an_assertion_error is now skips_that_catch_an_assertion_error. It also finds a bare except, an except Exception or an except BaseException that holds a pytest.skip. Each of those catches a failed git call without naming it.
  • Before the widening, every open PR's head was scanned for such a handler (see "Merge checks"). None holds one, so the wider scan fails no later landing.

Tests

Linux, Python 3.12.3. Every run had a stub gh first on PATH (it exits 97), GH_TOKEN=bogus, an empty GH_CONFIG_DIR and /usr/bin/python3 -m pytest -q -p no:cacheprovider --basetemp=<scratch>/bt-<name> -o tmp_path_retention_policy=failed -rs <files>. The C locale adds PYTHONUTF8=0 LC_ALL=C PYTHONCOERCECLOCALE=0 LANG=C LC_CTYPE=C, and sys.getfilesystemencoding() printed ascii there.

UTF-8, on the change's files. The 11 files are tests/test_adopt_template_values.py, tests/test_adopt_git_reads.py, tests/test_adopt_plan_escapes.py, tests/test_non_utf8_name_helpers.py, tests/test_repo_hygiene.py, tests/test_non_utf8_oserror_sites.py, tests/test_non_utf8_name_callers.py, tests/test_non_utf8_git_reads.py, tests/test_non_utf8_git_failures.py, tests/test_family_init_asks_every_value.py (it imports test_non_utf8_git_reads.py) and tests/test_no_auto_maintenance.py (it scans every test file):

550 passed in 184.60s (0:03:04)

Nothing skipped. The new file alone: 36 passed in 9.36s. At 40531e19 the same 11 files gave 543 passed. The 7 new ones are the 3 line-1 Windows rows and the 4 new rows of the scan.

C locale, on the 8 changed files. These are files 1-4 and 6-9 of the 11 above: the 7 changed test files and tests/test_non_utf8_name_helpers.py. test_repo_hygiene.py is left out.

302 passed, 32 skipped in 121.47s (0:02:01)

The skip reasons of the C-locale run (-rs):

SKIPPED [1] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'Jos\u2028e'
SKIPPED [2] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell '\u202eevil'
SKIPPED [1] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'ref \u2066x\u2069 y'
SKIPPED [1] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell '\u202ecaf'
SKIPPED [3] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'Jos\xe9'
SKIPPED [1] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'Ali\u200cReza'
SKIPPED [1] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'caf\xe9'
SKIPPED [6] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'main\xa0'
SKIPPED [3] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'ma\u2028in'
SKIPPED [2] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell '\u202e'
SKIPPED [3] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'caf\xe9.yml'
SKIPPED [2] tests/test_non_utf8_git_reads.py:111: this system's file name encoding cannot spell 'caf\xe9.yml': 'ascii' codec can't encode character '\\xe9' in position 145: ordinal not in range(128)
SKIPPED [4] tests/test_non_utf8_git_reads.py:111: this system's file name encoding cannot spell 'caf\xe9.yml': 'ascii' codec can't encode character '\\xe9' in position 117: ordinal not in range(128)
SKIPPED [2] tests/conftest.py:1219: this system's file name encoding (ascii) cannot spell 'Mehr\u200cdad'

Mutants

Each mutant was applied alone in a scratch worktree, and tests/test_non_utf8_git_failures.py was run. All 13 are caught:

mutant result caught by
line 1: the try/skip back in refused_then_moved 2 failed, 27 passed test_a_failure_of_git_under_the_byte_directory_fails_the_test[adopt-template-values], the scan
the same in the git-reads test 2 failed, 27 passed [adopt-git-reads], the scan
the same in the plan-escapes test 2 failed, 27 passed [adopt-plan-escapes], the scan
line 2: the except back in with_default_branch 5 failed, 24 passed both not-UTF-8 rows, both NBSP rows, the scan
the same in moved_to_a_branch_that_is_not_utf8 2 failed, 27 passed its git-failure row, the scan
the same in remembered_on (the sixth site) 4 failed, 25 passed its not-UTF-8 row, both U+2028 rows, the scan
skip_where_no_ref_can_be_named asks nothing for a name that is not UTF-8 8 failed, 21 passed the 4 EILSEQ rows and the 4 Windows rows
it asks nothing for a name that is text 2 failed, 27 passed both ASCII-encoding rows
a text name asks the byte helper too 2 failed, 27 passed both "asks nothing of a byte" rows
moved_to_a_branch_that_is_not_utf8 asks after make_source_repo 2 failed, 27 passed its EILSEQ and Windows rows (tmp_path not empty)
#854: the encoding check dropped from the U+202E test 1 failed, 28 passed test_where_the_file_name_encoding_cannot_spell_u202e_the_bidi_test_skips
#854: the check after the mkdir 1 failed, 28 passed the same
the helper's reason back to "cannot carry" 1 failed, 28 passed the same

With a real git failure. A stub git first on PATH, in the scratch worktree only, failed one subcommand as a full disk does (error: unable to write file .git/objects/xx: No space left on device, exit 128) and ran /usr/bin/git for everything else:

  • git commit fails, test_execute_refuses_a_local_source_directory_that_is_not_utf8:
    • this branch: 1 failed in 0.39s (AssertionError: error: unable to write file ...);
    • the line-1 mutant: 1 skipped in 0.38s, SKIPPED [1] tests/test_adopt_template_values.py:266: git will not work under 'caf\udce9' here: error: unable to write file .git/objects/xx: No space left on device. This is the test that passes where it should fail.
  • git branch -m fails, test_check_finds_a_plans_branch_gone_for_one_that_is_not_utf8:
    • this branch: 1 failed in 0.98s;
    • the moved_to_a_branch_that_is_not_utf8 mutant: 1 skipped in 0.95s ("no branch here is named b'caf\xe9'").
  • git update-ref fails, test_the_way_through_spells_a_name_no_command_line_carries (the sixth site):
    • this branch: 2 failed in 0.63s;
    • the remembered_on mutant: 2 skipped in 0.79s.

#854 in the real C locale, test_execute_refuses_a_local_source_directory_holding_a_bidi_control:

  • this branch: 1 skipped in 0.15s, on the reason above;
  • the mutant without the check: 1 failed in 0.26s, with UnicodeEncodeError: 'ascii' codec can't encode character '\u202e' in position 115 at the mkdir, as on the base;
  • the same mutant under UTF-8: 1 passed.

Fix round 1. Each mutant was applied alone in a scratch worktree:

mutant run result caught by
RV869's survivor: the template-values byte test asks skip_where_a_name_cannot_be_not_utf_8 after its mkdir the four test_non_utf8_* files (git_failures, name_callers, oserror_sites, name_helpers), UTF-8 1 failed, 107 passed test_where_fsencode_makes_no_byte_the_byte_directory_test_skips_first[adopt-template-values]
test_a_valid_non_ascii_elector_still_adopts asks after adopted the test, C 2 failed (UnicodeEncodeError for U+00E9 and for U+200C) both of its rows
test_plan_refuses_a_flag_no_file_can_hold asks after adopted the test, C 3 failed, 3 passed its U+2028, U+202E and U+2066 rows
test_a_utf8_source_directory_still_adopts_with_local_remotes asks after make_source_repo the test, C 1 failed (UnicodeEncodeError at the mkdir) the test
RV869's own1: except Exception as exc: pytest.skip(...) around with_default_branch's git calls tests/test_non_utf8_git_failures.py, UTF-8 5 failed, 31 passed test_no_test_skips_on_an_assertion_error ({'test_adopt_git_reads.py': [567]}) and the 4 behaviour rows of with_default_branch. With the scan of 40531e19 in its place, the scan test passes on own1: 1 passed
  • How the first mutant fails. It fails because windows_fsencode takes no Path, at the test's own os.fsencode(tmp_path). I also made windows_fsencode take one (os.fspath, in the scratch tree only). Then the same row fails on assert list(tmp_path.iterdir()) == [], with the directory caf\udce9 left there. Either way the row fails.
  • The three C mutants pass under UTF-8, which is CI's locale (2 passed, 6 passed, 1 passed). At bcf6952e a C-locale run like the one above held those skips, and no emulated row did. Fix round 2 adds the rows (below).

Fix round 2 (2572a717): RV869b's two NITs

NIT 1: windows_fsencode takes a path (tests/conftest.py:1187). It calls os.fspath(text) first, as the real os.fsencode does, so a test that asks os.fsencode(tmp_path) under the emulation no longer raises AttributeError: 'PosixPath' object has no attribute 'encode' before the question it holds. A new row, test_windows_fsencode_takes_a_path_as_os_fsencode_does (tests/test_non_utf8_name_helpers.py:93), asserts windows_fsencode(Path("caf\udcff")) == b"caf\xed\xb3\xbf". Its non-ASCII is written as escapes.

NIT 2: six emulated rows for the six C-locale skips (tests/test_non_utf8_git_failures.py:299-347, WHERE_ASCII_CANNOT_SPELL and test_where_the_file_name_encoding_is_ascii_the_template_values_tests_skip). Each row sets os.fsencode to ascii_fsencode and make_source_repo to a_source_git_cannot_make, as the line-1 rows do. It then asserts that the test skips on "file name encoding" and that tmp_path is empty. The rows are flag-u2028, flag-u202e, flag-u2066, elector-accented, elector-zwnj and cafe-directory. A test that asked after make_source_repo fails on git's error under UTF-8, which is CI's locale.

Runs (stub gh first on PATH, as above):

  • UTF-8, the 7 files that use windows_fsencode or ascii_fsencode (tests/test_bootstrap_branch_bytes.py, tests/test_bootstrap_non_utf8_branch.py, tests/test_non_utf8_git_failures.py, tests/test_non_utf8_git_reads.py, tests/test_non_utf8_name_callers.py, tests/test_non_utf8_name_helpers.py, tests/test_non_utf8_oserror_sites.py), plus tests/test_adopt_template_values.py and tests/test_repo_hygiene.py: 411 passed in 111.76s (0:01:51), nothing skipped.
  • C locale, tests/test_non_utf8_git_failures.py and tests/test_adopt_template_values.py: 109 passed, 11 skipped in 44.32s. The 11 skips are the 6 template-values tests, the U+202E test and the 4 text-branch rows, each on "file name encoding ... cannot spell".

Mutants, under UTF-8, each alone in a scratch worktree, tests/test_non_utf8_git_failures.py:

mutant result caught by
RV869b's m2b: the flag test asks after adopted 3 failed, 39 passed [flag-u2028], [flag-u202e], [flag-u2066]
RV869b's m2c: the caf and U+00E9 test asks after make_source_repo 1 failed, 41 passed [cafe-directory]
the flag test asks about flag, not value 3 failed, 39 passed the same three flag rows
the elector test asks after make_source_repo 2 failed, 40 passed [elector-accented], [elector-zwnj]
NIT 1: os.fspath taken out of windows_fsencode 1 failed, 60 passed (with tests/test_non_utf8_name_helpers.py) test_windows_fsencode_takes_a_path_as_os_fsencode_does, by the AttributeError
RV869's m1: the template-values byte test asks after its mkdir 1 failed, 114 passed (the four test_non_utf8_* files) [adopt-template-values] of the byte-directory Windows rows, on assert list(tmp_path.iterdir()) == [] and no longer on an AttributeError

Merge checks

git merge-tree --write-tree of bcf6952e:

gh pr list --state open --limit 200 --json number,files shows 34 open PRs. Only #806, #845, #849 and #871 touch these 8 files.

The open PRs' tests/, for the widened scan.

  • Fix round 1 fetched every open PR's head (gh pr list --state open --limit 200 --json number,headRefOid, 34 open, this one included). It scanned each head's tests/ with the widened scan.
  • No head holds a bare except, an except Exception or an except BaseException that holds a pytest.skip.
  • Every other head holds only the known except AssertionError sites (5 or 6 a head), which it keeps from main before this PR.
  • The new head holds none, and neither does its merge with origin/main.

Left out

  • No Windows or macOS run. CI is Linux only (ci: run the test suite on Linux only #597). The Windows and macOS answers are emulated.
  • The six C-locale skips are held by emulated rows (fix round 2). The rows hold each test's question, which it asks through os.fsencode. They do not change what subprocess does with an argument, so make_source_repo is replaced by a function that fails: a test that went on past its question fails on git's error under UTF-8. A real C-locale run is still what finds a new test of this kind.

Lane: openreposhape-3 (openRepoShape-3)
🤖 Generated with Claude Code

Summary by Sourcery

Make non-UTF-8 test skips depend on explicit system capability checks while allowing unexpected Git and filesystem failures to fail the tests.

New Features:

  • Add coverage for failures and platform-specific encoding behavior in non-UTF-8 Git and template-value tests.

Bug Fixes:

  • Ensure genuine Git and filesystem failures fail tests instead of being incorrectly converted into skips.
  • Skip tests before filesystem or subprocess operations when the environment cannot encode the required names or values, including U+202E cases under ASCII locales.

Enhancements:

  • Centralize environment encoding checks and apply them consistently across affected test helpers.
  • Add static checks preventing exception handlers from hiding failed Git calls behind pytest skips.

Tests:

  • Add comprehensive emulated Windows, macOS, and C-locale coverage for encoding probes, Git failures, skip ordering, and exception-handler scanning.

Brett Heap and others added 17 commits October 16, 2026 14:05
… carry a name or branch that is not UTF-8, `os.fsencode` first and the disk's EILSEQ second, and two pins hold `bump-leg.py`'s UTF-8 decode and the leg finding's role, so a test no longer skips on the disk alone or passes under a decode as ASCII or a finding named by path (#663)

#461's five test lines, lane 2's L2-52 and lane 4's R423 N1 and N2 and R455 F1
and F3. Test only: no tool and no template changes, and `validate-manifest.py`,
a pinned copy, is read and not edited.

- `tests/conftest.py` holds `skip_where_a_name_cannot_be_not_utf_8`, which
  `tests/test_adopt_pins.py` and `tests/test_pin_source_unreadable.py` each
  had a copy of. It asks `skip_where_fsencode_gives_a_surrogate_no_byte`
  first (Windows' `os.fsencode` makes three bytes of U+DCFF, so no name that
  stands for a byte is carried there, though NTFS would take the file), then
  the disk (macOS answers EILSEQ); any other error is the test's own.
- `make_file` and the `--branch a\udcffb` test call it, so they skip on
  Windows too, where the disk takes the name and the child then refuses the
  branch. `test_a_branch_the_system_carries_has_no_fault` asks the same
  function instead of its own copy of the question.
- `test_a_name_that_is_utf8_under_quote_path_false_is_still_refused` asserts
  that the line naming `caf<e9>.yml` holds no literal `\x`, in any locale, so
  `bump-leg.py` decoding git's bytes as ASCII fails it.
- `_leg_branch_findings` is asked of a leg whose role is not its path, so
  naming the leg by `path` fails it.
- `tests/test_non_utf8_name_helpers.py` holds the helpers to this, with
  Windows' `os.fsencode` and macOS's EILSEQ emulated: CI is Linux only, and no
  Windows or macOS run was made.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…held by an emulation, so dropping the shared helper from it fails a test on Linux too (#663)

`test_a_branch_the_system_carries_has_no_fault` now asks
`skip_where_fsencode_gives_a_surrogate_no_byte` where it had its own copy of
the question. The new test calls it under Windows' `os.fsencode` (emulated):
a branch holding a byte-carrying surrogate is skipped, plain text and text
with an accent run. Removing the call fails the two skipped rows.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… fails where a skip escapes it, `windows_fsencode` passes bytes through as `os.fsencode` does, and the no-`\x` check skips where the file name encoding is not UTF-8, so a leaked skip, an emulation that breaks on bytes and a Latin-1 host no longer pass silently or fail on a tool that is right (#663)

The review of #723 (0b1d1dd) found no MUST and three things to take.

SHOULD-1: `skip_message` had no test of its own. A skip that escapes it ends
the test SKIPPED, and no run fails on a skip, so the mutant where one escapes
gave `10 passed, 3 skipped` on the helpers file and seven emulation tests
silently skipped. `tests/test_non_utf8_name_helpers.py` now holds it with
three tests: it returns the reason a call skips with, it returns None where
the call does not skip, and it lets any other exception go on. The first
catches the escape and fails it with `pytest.fail`, because a bare assert on
an escaped skip would end that test SKIPPED too.

NIT-2: `windows_fsencode` took `str` only. `os.fsencode` passes bytes through
on every system, so the emulation now does, and two tests hold it (the
surrogate and text, and the bytes, compared with `os.fsencode` itself).

NIT-1: on a Latin-1 file name encoding `make_file` writes `caf\xe9.yml` as
the single byte 0xE9, the tool prints `caf\xe9.yml`, and the new
`"\\x" not in shown` assertion would fail although the tool is right. It is
now `assert_shown_without_hex_escapes`, which skips where
`os.fsencode(UTF8) != UTF8.encode("utf-8")` and is called after the test's
other assertions, so a skip loses none of them. Two tests hold it under an
emulated Latin-1 `os.fsencode` (it skips) and Windows' (it asserts, and fails
a line that holds a `\x`).

Tests only; no tool and no template changes.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…_values.py, test_adopt_plan_escapes.py, test_clone_url_bytes.py and test_non_utf8_git_reads.py: the four tests and `directory_named` that made a directory named with a byte that is not UTF-8 ask `skip_where_a_name_cannot_be_not_utf_8` and skip on its two answers only, `directory_named` keeps its own Windows skip for a control character and no longer skips a bidi override there, and three tests of `test_non_utf8_git_reads.py` skip where an ASCII file name encoding cannot carry their text, so a full disk or a `tmp_path` nobody can write in fails the test instead of skipping it and a C locale shows no failure that is not a defect (#757)

The four tests (in `test_stdout_encoding.py`, `test_adopt_git_reads.py`,
`test_adopt_template_values.py` and `test_adopt_plan_escapes.py`) and
`directory_named` each made the
directory themselves and turned ANY `OSError` into `pytest.skip`, beside
the helper #663 added to `tests/conftest.py`. That helper skips on the two
answers that mean "this system cannot carry the name" (Windows'
`os.fsencode` first, macOS's EILSEQ second) and raises the rest. They now
call it, and each keeps its own second skip (git will not work under the
name; a listing that shows a rewritten name); the directory they make
after the probe is no longer guarded. The file twin in
`test_adopt_plan_escapes.py` asks the same question of a file name and
calls the helper too.

`directory_named` asks the helper for a name that is not UTF-8 and keeps
its own Windows skip for a control character, which Windows refuses in any
name. The `bidi-override` row, which NTFS holds, now runs on Windows
(reasoned; CI is Linux only, no Windows run was made).

Under `PYTHONUTF8=0 LC_ALL=C PYTHONCOERCECLOCALE=0` the file name encoding
is ASCII, and `tests/test_non_utf8_git_reads.py` failed six tests that hold
no defect: `test_make_file_writes_a_name_that_is_utf8_where_fsencode_makes_no_byte`
(the issue's line) and the five rows that put `Jos\u00E9`, a U+200C name or a
U+202E name into a child's environment, where `subprocess` raises
`UnicodeEncodeError` before the tool runs. The first now ends as its
neighbour does, on a skip that names the filesystem; the others skip where
`os.fsencode` cannot carry the value.

`tests/test_non_utf8_name_callers.py` calls each caller as a function with
the disk answering as macOS (EILSEQ on the probe: a skip), as a folder
nobody can write in (EACCES on the probe, and on the test's own
directory: a failure), and `directory_named` as Windows (a control
character skips, a bidi override does not), and holds the two C-locale
skips with an ASCII `os.fsencode` and a `write_bytes` that raises as it
would.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ke_file` test asks the file name encoding first and keeps its strict assert, the rows that let the probe through ask the real disk first, and each `pytest.raises` block holds one call, so a write the disk refuses fails the test and no skip is made of it, a disk that refuses the probe skips the rows and does not fail them, and the new file has no S5778 smell (#757)

A fix round for lane 1's review of #806 at 4184972 (three SHOULD FIX, one nit).

1. The `make_file` test skipped on `make_file`'s own "filesystem" reason,
   which `make_file` gives for ANY `OSError` of its write, so a write refused
   with EACCES or ENOSPC for the plain UTF-8 name `caf` and U+00E9 plus `.yml`
   ended the test SKIPPED, and the reason it gave was false. The test now
   calls `skip_where_the_environment_cannot_carry(UTF8)` first, before it
   swaps in the Windows `os.fsencode`, and keeps the strict
   `assert skip_message(make_file, ...) is None`: it skips for the file name
   encoding and for nothing else. The helper's reason loses " in an
   environment", which was wrong for a file name; the callers file reads
   "file name encoding". The ASCII row now patches `os.fsencode`, and two
   rows make `Path.write_bytes` raise EACCES and ENOSPC and expect the test
   to FAIL.
2. The own-directory rows let the probe through to the real disk, and
   their fixture asked only `os.fsencode`, so on macOS's APFS or a ZFS with
   `utf8only` the real probe answers EILSEQ, the helper skips, and the row
   failed. `a_disk_that_takes_the_probe` asks the real disk first and those
   rows alone use it; a row makes the disk answer EILSEQ and asks the
   fixture.
3. `fail_where_the_caller_ends` holds the `pytest.fail`, so each
   `pytest.raises` block holds one call (python:S5778, two places, and the
   new EACCES/ENOSPC rows).
4. The Windows rows for a byte and a control character now call
   `directory_named` itself, so its order (ask, then make) is held: a version
   that skipped after `os.mkdir` leaves a directory or fails on
   `os.fsencode` of a path. The bidi row asks `skip_where_this_system_cannot_name`
   and is named for it, because `directory_named` goes on to make a `Path`,
   and under an emulated `os.name` of `nt` that is a `WindowsPath`.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	tests/test_non_utf8_git_reads.py
…ile` skips on EILSEQ or a `UnicodeError` only and the U+202E directory has no guard, so a full disk or a read-only `tmp_path` fails the test, not SKIPPED (#834)

Five tests that make a directory or a file named with a byte that is not
UTF-8, or with U+202E, turned ANY `OSError` into `pytest.skip`, beside
`skip_where_a_name_cannot_be_not_utf_8` (#663). A disk that filled up, a
read-only `tmp_path` or a folder this user cannot write in read as SKIPPED,
and no run fails on a skip.

- `test_a_checkout_whose_path_is_not_utf8_is_a_checkout`
  (test_cli_reference.py) and
  `test_a_name_that_is_not_utf8_is_never_an_exception_quoted_as_a_finding`
  (test_doctor_validator_verdicts.py) ask the helper on `tmp_path` and make
  their directory with no `try`.
- `test_a_branch_whose_name_is_not_utf8_is_read_back_on_every_run`
  (test_bootstrap_leg_moves.py) asks the helper in place of its `write_bytes`
  probe, which skipped on `OSError` and `ValueError`.
- `make_file` (test_non_utf8_git_reads.py) keeps the `UnicodeError` skip (an
  ASCII file name encoding, #757) and skips an `OSError` only where its errno
  is EILSEQ (macOS); ENOSPC, EROFS and EACCES are raised, so each caller
  inherits a failure and no skip. #757's test of a refused write
  (test_non_utf8_name_callers.py) now expects that `OSError`, where it
  expected the AssertionError of the test's own "not a skip" assert.
- The U+202E directory (test_adopt_template_values.py) is valid text, which
  no system known here refuses, so its `mkdir` is unguarded. Read, not run, on
  macOS and Windows; Linux takes it.

tests/test_non_utf8_oserror_sites.py calls each as a function, with the disk
answering as it would on a system CI does not run (Linux only, #597): EILSEQ
on the probe (macOS) skips, EACCES, ENOSPC and EROFS on the probe or on the
test's own name raise, and an `os.fsencode` that gives a surrogate three bytes
(Windows) skips the three helper callers before the disk is touched. On the
base 30 of its 32 tests fail, and so do the 2 changed ones of
test_non_utf8_name_callers.py; the other 2 hold what both keep, the EILSEQ
skip and the `UnicodeError` skip of `make_file`. No Windows or macOS run was
made.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…gives its two skips their own reasons, and the U+202E test fails where git fails, so a guard that skips the rest or a full disk after the `mkdir` no longer passes (#834)

Fix round on #845, after lane 4's review of b18b243 (READY, no MUST).

SHOULD 1. `REFUSALS` held ENOSPC, EROFS and EACCES, so a guard that
re-raised those three and skipped every other error passed all of the
tests. The emulated disk now answers every errno `errno.errorcode` holds
but EILSEQ (129 of them), and each caller must raise it, as Python makes it
(`PermissionError` for EACCES). The sweep stops at the first errno that
fails and names it, so a caller that goes on past a refused name runs its
test once and not 129 times. The explicit three-row families are gone, as
the sweeps cover them; the new file has 18 tests where it had 32.

SHOULD 2. The U+202E test's docstring claimed more than
`refused_then_moved` did: its `make_source_repo` call still skipped on an
`AssertionError`, so a disk that filled after the `mkdir` read as SKIPPED.
Made true and not narrowed: `refused_then_moved` takes
`skip_where_git_fails` (default True, as #757 left it for the name that is
not UTF-8, which git may not work under), and the U+202E test passes False,
as the name is valid text and git failing there is the disk. Two new tests
hold it, and a third holds the kept skip for the byte name, which stays a
known limit.

NIT 3. `make_file` gives the two skips their own reasons: "this system's
file name encoding cannot spell ..." for a `UnicodeError`, and "this
filesystem refuses a file name that is not UTF-8 (EILSEQ)" for EILSEQ. The
controls pin both.

NIT 5. The new own-directory test is renamed for its sites, so a `-k`
selection no longer picks up #757's test of the same name.

NIT 6. The module docstring keeps `skip_where_a_name_cannot_be_not_utf_8`
on one line.

NIT 4 stays: moving the emulated disk and the two fixtures into conftest
would add hunks to a file #814 and #818 also edit.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…re and does not catch it, so a failing errno still names itself and the test has no `try` for python:S8714 (#834)

Fix round 2 on #845, after lane 4's re-check of efb1727 (READY, no MUST).
SonarCloud reported python:S8714 on the `except pytest.fail.Exception` of
`raised_for_every_errno`, which caught a failure only to fail again with
the errno's name in front.

`fail_where_the_caller_ends` takes a keyword `said`, put in front of its
message, and `the_error_of` threads it through; the loop passes
`said=f"errno {code} ({errno.errorcode[code]}): "`. The loop has no `try`.
The message a failing errno gives is the same as before, `errno 1 (EPERM):
the caller ended SKIPPED: ...`, and the sweep still stops at the first
errno that fails. The three other callers of `fail_where_the_caller_ends`
pass no `said` and are unchanged.

One test holds it: a caller that skips where it should raise fails at the
first errno with the label in front of the message, and is asked once.
It passes on efb1727 too, as the message is kept; it fails where the label
is dropped at any of the three places it is passed, and where the sweep
goes on past a failure.

The U+202E test under a C locale (the re-check's NIT 2) is #854 and is not
changed here.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…es` block, so the block holds one call and python:S5778 no longer reports it (#834)

Fix round 3 on #845, after lane 4's re-check of 9ba530a (READY, no MUST).
SonarCloud reported python:S5778 (MAJOR) on
`test_the_sweep_names_the_first_errno_that_fails_and_stops_there`: its
`pytest.raises(pytest.fail.Exception)` block held two calls that could
raise, `Disk(first)` and `raised_for_every_errno(...)`.

`disk = Disk(first)` is built before the block, and the block holds
`raised_for_every_errno(disk, hides_the_error, "a path")` alone. The
assertions after it read the same exception, `failed.value.msg`, and the
list of calls the caller was asked. Nothing else changes.

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s `appended_to_command_scope` import and #806's `skip_where_a_name_cannot_be_not_utf_8` import both stay in `tests/test_adopt_git_reads.py`'s `from conftest import` block, as the union of the two names, sorted as the file sorts them

main moved from `677f9bfa` to `e62b5e17`. #818 (`aec3b38f`) changed
`tests/test_adopt_git_reads.py` and `tests/test_non_utf8_git_reads.py`, as #806
does. `tests/test_non_utf8_git_reads.py` merged by itself. In
`tests/test_adopt_git_reads.py` the only conflict was the `from conftest import`
block: #806's side added `skip_where_a_name_cannot_be_not_utf_8`, #818's side
added `appended_to_command_scope` and took the block back to one line. The block
is now both names, the constant first and the rest in alphabetical order, wrapped
at 79 columns as the other test files wrap it. The rest of the file is #818's
change to `command_scope` and to
`test_the_user_name_given_is_appended_to_the_config_the_environment_holds`,
beside #806's use of the skip helper.

Conflicts:
	tests/test_adopt_git_reads.py

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…`from conftest import` block of `tests/test_adopt_git_reads.py` (#818's `appended_to_command_scope` beside #806's `skip_where_a_name_cannot_be_not_utf_8`), so main's #830 merges after it with no conflict

#845's head 8f6a38e is stacked on #806's older head 76ae641. A merge of
origin/main straight onto it conflicts in that one import line, which
#806's own merge of e62b5e1 already resolved as the union of the names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s `with_default_branch` and `remembered_on` (51414d2), which #853's second line edits

#853's second line waits for #797 (PR #830), which rewrote
`with_default_branch`, gave it a `branch` argument called with a UTF-8
name, and added `remembered_on`, the sixth site of the issue's scan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m first and let git's failure fail the test, and the U+202E test asks the file name encoding before its `mkdir`, so a full disk reads as a failure, not SKIPPED, and a C locale skips that test instead of erroring (#853, #854)

#853, line 1: `refused_then_moved`, `test_a_utf8_clone_of_a_source_whose_path_is_not_utf8_adopts`
and `test_a_source_directory_that_is_not_utf8_is_shown_spelled` no longer
wrap `make_source_repo` in `except AssertionError: pytest.skip(...)`. They
already ask `skip_where_a_name_cannot_be_not_utf_8` before the `mkdir`
(#757), and git works under any directory a system carries, so a git that
fails there (a disk that filled after the `mkdir`) fails the test.
`refused_then_moved` loses #834's `skip_where_git_fails`, which only the
byte-name test still used.

#853, line 2, and the sixth site: `with_default_branch`,
`moved_to_a_branch_that_is_not_utf8` and `remembered_on` (added by #830
after the issue's scan) ask `skip_where_no_ref_can_be_named` before their
first git call and drop their `except (AssertionError, UnicodeError,
OSError)`. A name that is not UTF-8 asks the helper of the directory the
source is in; a name that is text asks only whether the file name encoding
can spell it, since `subprocess` puts every argument through `os.fsencode`.
The skip after `git symbolic-ref` stays.

#854: the U+202E test asks `skip_where_the_environment_cannot_carry` before
its `mkdir`. The helper moves from `tests/test_non_utf8_git_reads.py` to
`tests/conftest.py` with its callers, and its reason now reads "this
system's file name encoding (...) cannot spell ...", as `make_file`'s does.

`tests/test_non_utf8_git_failures.py` (new) calls each place with git made
to fail, and with macOS, Windows and an ASCII encoding emulated. It also
scans every `tests/*.py` for an `except` that names `AssertionError` and
holds a `pytest.skip`. #845's control test that held the byte-name skip as
a known limit is gone, and its two U+202E tests skip under an ASCII
encoding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 18, 2026
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-18T03:55:44Z) Lane 3's independent review of its own #869 (#853, #854) at 40531e19, by RV869 (opus): READY. No MUST. One SHOULD: line 1 has no Windows (windows_fsencode) row at the caller level, so a mutant that asks after the mkdir survives. Four NITs. CI is green on all four checks. A fix round starts now (W869f). It takes the SHOULD and NITs 1, 3 and 4. It also takes NIT 2's six C-locale failures in tests/test_adopt_template_values.py, a file this PR already changes, so they need no issue of their own.


Verdict: READY. There is no MUST. There is one SHOULD and four NITs. The tests CI job finished green on 40531e19 while I reviewed, so nothing is still pending.

Review of #869, head 40531e19. The reviewed change is git diff 84a09c2e 40531e19: 8 files, +475/−110, one commit that touches exactly those 8 files. Every number below is my own run.

The checks the brief asked for

1. Both merges are exact and clean.

  • e387a3c2 (parents 8f6a38e3 and a1498632): merge-tree --write-tree exits 0 and gives 88a781dc, which is the commit's tree.
  • 84a09c2e (parents e387a3c2 and 3fb30a8f): exits 0 and gives f7147379, which is the commit's tree. 3fb30a8f is on origin/main.

2a. A text branch name asking the file name encoding is right.

2b. Moving the helper and rewording its reason breaks nothing.

2c. The control test's purpose is kept, the other way round.

3. The scan, with my own script, independent of the writer's.

Tree except naming AssertionError that holds a skip
base 84a09c2e 6: test_adopt_git_reads.py 472, 549, 569, 730; test_adopt_plan_escapes.py 408; test_adopt_template_values.py 265
head 0
head merged with origin/main 4dea85ee (tree b39ecb29) 0
origin/main 6
  • On the head there are also 0 bare, Exception or BaseException handlers holding a skip.
  • tests/ has no subfolders, so glob("*.py") covers every file.

4. remembered_on's skip is the narrowest one that is right.

  • For the byte name it asks os.fsencode (Windows), then the EILSEQ probe on source.parent (macOS).
  • That is the same disk as .git/refs, and it also works in the new rows, where source does not exist yet.
  • For U+2028 it asks only the encoding.
  • The old "or alters the name" in its docstring had no read-back behind it, so nothing is lost.

5. The 6 C-locale failures are unchanged and were already there.

7. Windows.

  • Windows' os.fsencode is UTF-8 with surrogatepass, so skip_where_the_environment_cannot_carry never skips there. That is correct: on Windows, subprocess and mkdir pass text as UTF-16.
  • skip_where_no_ref_can_be_named sends a name that is not UTF-8 through skip_where_fsencode_gives_a_surrogate_no_byte before the disk or git is touched.
  • Every new-file row that uses real git or a real probe carries a_system_that_carries_the_byte, so it skips on Windows.
  • The gap is line 1; see SHOULD 1.

8. SonarCloud analysed 40531e19:

  • quality gate OK, 0 issues, 0 hotspots;
  • 0 new duplicated lines and 0 code smells in each of test_non_utf8_git_failures.py (363 new lines), test_adopt_git_reads.py, conftest.py and test_non_utf8_oserror_sites.py;
  • no composite assert a and b among the added lines.

9. Merges. See the merge results below.

Other hygiene:

  • The diff adds no non-ASCII character, no tab and no line over 79 columns.
  • pyflakes shows only the noqa: F401 fixture-import patterns that the base also has.

SHOULD

SHOULD 1: line 1 has no Windows (windows_fsencode) row at the caller level.

NITs

  1. A stale docstring sentence. tests/test_non_utf8_oserror_sites.py:28-29 says "The U+202E test makes its directory, and its source repository, with no guard." The test now asks the file name encoding first (tests: under a C locale, test_execute_refuses_a_local_source_directory_holding_a_bidi_control errors at mkdir, because its except OSError does not catch the UnicodeEncodeError that U+202E raises there, where it should skip #854). Fix: add "but the file name encoding's question (tests: under a C locale, test_execute_refuses_a_local_source_directory_holding_a_bidi_control errors at mkdir, because its except OSError does not catch the UnicodeEncodeError that U+202E raises there, where it should skip #854)".
  2. Open a follow-up issue for the six C-locale failures listed under check 5. Fix: call skip_where_the_environment_cannot_carry(value) before adopted in the five, and before the make_source_repo of caf+U+00E9 in the sixth.
  3. The scan sees only an except that names AssertionError.
    • My mutant own1, except Exception: pytest.skip around with_default_branch's git calls, is invisible to the scan.
    • The behaviour rows catch it only at the six known sites.
    • Head has no such handlers today, so widening skips_on_an_assertion_error (tests/test_non_utf8_git_failures.py:293-300) to bare, Exception and BaseException handlers costs nothing.
    • This is optional: the Verify is met as written.
  4. The PR body's file list is slightly off. "The first 4 and the last 4 of the files above" is really files 1-4 and 6-9: the 7 changed test files plus test_non_utf8_name_helpers.py, 327 tests. The counts reproduce exactly.

Test runs

Every run had a stub gh first on PATH (exits 97), GH_TOKEN=bogus, an empty GH_CONFIG_DIR, and timeout 2400 /usr/bin/python3 -m pytest -q -p no:cacheprovider --basetemp=<scratch>/bt-RV869-<name> -o tmp_path_retention_policy=failed -rs <files>. "C" means PYTHONUTF8=0 LC_ALL=C PYTHONCOERCECLOCALE=0 LANG=C LC_CTYPE=C, where the file name encoding printed ascii.

# Tree, environment, files Result
1 head, UTF-8, the writer's 11 files 543 passed in 244.42s, 0 skipped
2 head, C, 8 files (7 changed + name_helpers) 6 failed, 295 passed, 26 skipped in 183.15s
3 base 84a09c2e, C, 7 files 7 failed, 272 passed, 20 skipped in 161.28s; only the U+202E test differs from run 2
4 head merged with origin/main, UTF-8, 8 files + test_repo_hygiene.py 405 passed in 199.56s
5 origin/main 4dea85ee, C, test_adopt_template_values.py 7 failed, 71 passed in 65.01s
6 head, a plugin that makes os.mkdir answer EILSEQ to a name that is not UTF-8 (new file + 3 adopt files) 183 passed, 20 skipped in 117.82s
7 real git failing commit with an ENOSPC message, the 3 line-1 tests head: each 1 failed with that AssertionError; base: each 1 skipped, "git will not work under ..."
8 real git failing switch, branch and update-ref, -k "default_branch or branch_gone or way_through" head 14 failed, 23 deselected in 6.67s; base 14 skipped, 23 deselected in 4.83s
9 #854's Verify, real U+202E test head under C: 1 skipped in 0.19s, reason "this system's file name encoding (ascii) cannot spell" U+202E+caf. Check removed: C 1 failed in 0.32s (UnicodeEncodeError at mkdir), UTF-8 1 passed in 6.82s
10 CI on 40531e19 tests success (02:46:47Z to 03:53:04Z), tests-git-bash success, package success, SonarCloud pass

Mutants

Each was run against tests/test_non_utf8_git_failures.py under UTF-8 unless noted.

Mutant Result Killed by
Writer's: the try/skip back in refused_then_moved 2 failed, 27 passed [adopt-template-values] and the scan (matches the writer)
Writer's: the except back in remembered_on, helper kept 4 failed, 25 passed its not-UTF-8 row, both U+2028 rows, the scan (matches). With the helper call also removed, as on the base: 7 failed
Writer's: moved_to_... asks after make_source_repo 2 failed, 27 passed its EILSEQ and Windows rows (matches)
Writer's: #854 check after the mkdir 1 failed, 28 passed the U+202E skip test (matches)
Writer's: a text name asks nothing 2 failed, 27 passed both ASCII rows (matches); under the real C locale, 5 real rows fail (check 2a)
Own own1: except Exception: pytest.skip in with_default_branch 4 failed the behaviour rows only; the scan cannot see it
Own own2: except Exception: pytest.skip in refused_then_moved 1 failed [adopt-template-values]
Own own3: a text name asks the byte probe instead of the encoding 4 failed both "asks nothing" rows and both ASCII rows
Own: line-1 byte test asks after its mkdir 101 passed survives; SHOULD 1

Merge results

Scratch paths

All under /workspace/projects/openRepoShape-worktrees/_lane3-scratch/:

  • clone: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869
  • worktrees:
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-head (40531e19)
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-base (84a09c2e)
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-mut (left clean)
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-mainmerge (tree b39ecb29)
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-main (4dea85ee)
  • logs: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-logs/
  • prototype row: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-logs/test_rv869_probe_row.py.txt
  • scripts:
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-run.sh
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-scan.py
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-mutate.py
  • git stubs:
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-failgit/git
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-failgit2/git
  • EILSEQ plugin: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/RV869-plugin/rv869_eilseq.py
  • basetemps: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869-scratch/bt-RV869-*
  • open PR heads: fetched into private refs refs/rv869/pr<N> in the clone.

No Windows or macOS run was possible here; those answers are emulated. Nothing was pushed or posted, and no git config was changed.

Lane: openreposhape-3 (openRepoShape-3)

Brett Heap and others added 3 commits October 18, 2026 04:03
…old them to asking before their `mkdir`, and the scan finds a `pytest.skip` in a bare, `Exception` or `BaseException` handler too (#853, review of #869)

- `test_where_fsencode_makes_no_byte_the_byte_directory_test_skips_first`
  (`tests/test_non_utf8_git_failures.py`), one row for each of the three
  tests over `UNDER_A_BYTE_DIRECTORY`: with `os.fsencode` as Windows has
  it, each test skips on the helper's reason and makes nothing under
  `tmp_path`. A test that asked after its `mkdir` passed every row before.
- `skips_on_an_assertion_error` is `skips_that_catch_an_assertion_error`:
  it finds an `except` that catches an `AssertionError` without naming it
  as well, so an `except Exception: pytest.skip(...)` around a git call
  fails the scan. No open pull request's `tests/` holds one.
- `tests/test_non_utf8_oserror_sites.py`'s docstring says the U+202E test
  asks the file name encoding before its `mkdir` (#854).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…under a C locale ask the file name encoding first and skip there, as #854's U+202E test does

Under `PYTHONUTF8=0 LC_ALL=C PYTHONCOERCECLOCALE=0` the file name
encoding is ASCII. Three rows of `test_plan_refuses_a_flag_no_file_can_hold`
(U+2028, U+202E, U+2066) and both rows of
`test_a_valid_non_ascii_elector_still_adopts` raised at `subprocess.run`
in `adopted`, which cannot put the value on `plan`'s command line there;
`test_a_utf8_source_directory_still_adopts_with_local_remotes` raised at
the `mkdir` of `caf` and U+00E9 in `make_source_repo`. Each now calls
`skip_where_the_environment_cannot_carry` first. Under UTF-8 none skips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-18T04:13:32Z) Fix round 1 (W869f) of lane 3's #869, answering RV869: pushed. The head is now bcf6952e (60836f5c and bcf6952e on top of 40531e19; the round alone is git diff 40531e19 bcf6952e, 3 test files, +101/-23). The body is updated. No merge was made: #806's head moved during the round, from a1498632 to 22238b47 (main d6475f96 merged in). #869 is clean with both, and with #845 8f6a38e3 and origin/main d6475f96. It restacks after #845 lands.

An independent re-check of this round (RV869b, opus) starts now.

Lane: openreposhape-3 (openRepoShape-3)

Brett Heap and others added 2 commits October 18, 2026 04:17
Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… for: tests/test_non_utf8_name_callers.py

Lane: openreposhape-5 (openRepoShape-5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-18T04:37:54Z) Lane 3's independent re-check of #869's fix round 1 (40531e19..bcf6952e), by RV869b (opus): READY. No MUST and no SHOULD. All five of RV869's items are fixed and measured, and all 33 open PR heads pass the wider scan, as do their predicted merges. Four optional NITs. Lane 3 takes NIT 1 (windows_fsencode takes a path, as the real os.fsencode does) and NIT 2 (emulated rows for the six C-locale skips, so CI holds them) in a small round 2 now. It leaves NIT 3 (scan edge cases that occur in no tree), and takes NIT 4 in the squash message. Restack: #806 landed as d6071c7, and lane 5 has merged it into #845 (fc3cb5e9). #869 merges clean with that head, and restacks after #845 lands.


RV869b: independent re-check of fix round 1 on lane 3's #869 (closes #853 and #854). Head bcf6952e: READY.

There is no MUST and no SHOULD, and there are four optional NITs. All five of RV869's items are fixed, and I measured each fix myself. All 33 open PR heads pass the wider scan, and so do their predicted merges. The head is clean with everything the brief named except a plain merge with current main (5 files). That conflict comes only from #806's squash landing at 04:17:02Z, after this round; merged through #845's new head it is clean (merge results below).

What moved while I worked (the PR head did not; ls-remote read bcf6952e again at 04:34:45Z):

On CI, bcf6952e has SonarCloud, package and tests-git-bash passing. tests was still pending at 04:34Z. SonarCloud's API for PR 869 shows commit bcf6952e, gate OK, 0 new issues, 0 code smells, 0 new duplicated lines and 0 hotspots. None of the added lines is a composite assert.

The checks

1. SHOULD 1: the Windows rows at tests/test_non_utf8_git_failures.py:128-141.

  • The writer's claim holds. Each row asserts three things: a skip happened, its reason contains os.fsencode, and tmp_path is empty.
    • On RV869's survivor (the template-values byte test asking after its mkdir), the first failure is AttributeError: 'PosixPath' object has no attribute 'encode'.
    • That error comes from the test's own os.fsencode(tmp_path) at tests/test_adopt_template_values.py:305. windows_fsencode (tests/conftest.py:1180-1188) takes only str | bytes.
    • The same happens for the other two tests (tests/test_adopt_git_reads.py:468, tests/test_adopt_plan_escapes.py:404).
  • Measured both ways, on the 4 test_non_utf8_* files for the template-values mutant and on test_non_utf8_git_failures.py for the other two:
    • windows_fsencode takes a path (text = os.fspath(text) first). All three mutants then fail on the row's own assert list(tmp_path.iterdir()) == [], with caf\udce9 left there: 1 failed, 107 passed, then 1 failed, 35 passed for each of the other two. The head is unchanged across all six files that use windows_fsencode: 221 passed in 52.94s.
    • The row wraps it (lambda value: windows_fsencode(os.fspath(value))). The same assertion fails: 1 failed, 107 passed.
    • The faithful emulation without the empty-tmp_path assertion. The mutant survives (108 passed). With the head's emulation and no assertion, it still dies, but only on the AttributeError.
  • Verdict on check 1: the row tests what it says. The empty-tmp_path assertion is the part that matters, and the AttributeError is a side effect of the emulation that hits first. That is NIT 1 below.

2. NIT 2, taken here: the six C-locale tests.

3. NIT 3: the wider scan.

4. NITs 1 and 4.

5. Every hunk read.

  • The round is exactly 3 files, +101/-23:
    • test_adopt_template_values.py: 3 hunks;
    • test_non_utf8_git_failures.py: docstring, the 3-row test, the wider scan, and 4 new scan rows (10 in all);
    • test_non_utf8_oserror_sites.py: 1 docstring line.
  • The new file has 36 tests: own1's run counts 5 failed, 31 passed.
  • The added lines have no non-ASCII character, no tab and no line over 79 columns. One raw é is removed (now \u00e9).
  • pyflakes shows only the known fixture-import patterns.
  • No doc or pinned file changes. No reference to the old name skips_on_an_assertion_error remains.
  • Windows: the six new calls never skip there, because os.fsencode is UTF-8 with surrogatepass.

NITs (all optional)

NIT 1: windows_fsencode takes no path, so the new rows kill on an emulation artifact first.

NIT 2: the body's "Left out" says the six C-locale skips cannot get an emulated row. They can.

  • Where: the body's "Left out", second bullet.
  • Scenario: an order mutant of the six passes in CI, which runs UTF-8.
  • Measured: my prototype /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-logs/test_rv869b_c_rows.py.txt has 6 rows. Each sets os.fsencode = ascii_fsencode and make_source_repo = a_source_git_cannot_make, as the line-1 rows do, then asserts a skip on "file name encoding" with tmp_path empty.
    • head, UTF-8: 6 passed in 5.40s; real C: 6 passed in 0.27s;
    • m2b: 3 failed, 3 passed; m2c: 1 failed, 5 passed; own-flag: 3 failed, 3 passed. All of these are under UTF-8.
  • Fix: add the rows, or reword the bullet to "not added".

NIT 3: the scan has one false positive and two misses.

  • Where: names_in (tests/test_non_utf8_git_failures.py:302) reads an attribute by its last name.
  • Scenario:
    • except pytest.skip.Exception: pytest.skip(...) is flagged as an Exception handler;
    • skip(...) imported with from pytest import skip is missed;
    • raise pytest.skip.Exception(...) inside except Exception is missed.
  • Measured: none occurs anywhere.
    • The head has no from pytest import, no import pytest as and no raise pytest.skip.Exception.
    • Its two except pytest.skip.Exception handlers (conftest.py:1199, test_non_utf8_name_helpers.py:60) hold no skip.
    • My scan of the PR heads found no such alias either.
  • Fix: count Exception and BaseException only as an ast.Name or builtins.<name>, or leave it as is.

NIT 4: the title does not name the six extra skips.

Test runs

All runs used a stub gh first on PATH (exits 97), GH_TOKEN=bogus, an empty GH_CONFIG_DIR, GIT_ALLOW_PROTOCOL unset, and /usr/bin/python3 -m pytest -q -p no:cacheprovider --basetemp=<scratch>/bt-RV869b-<name> -o tmp_path_retention_policy=failed -rs. "C" means PYTHONUTF8=0 LC_ALL=C PYTHONCOERCECLOCALE=0 LANG=C LC_CTYPE=C, where the file name encoding printed ascii.

# Tree, locale, files Result
1 head, UTF-8, the body's 11 files 550 passed in 165.42s, 0 skipped
2 head, C, the 8 files (1-4, 6-9) 302 passed, 32 skipped in 142.53s; skip reasons match the body's list
3 head, C, test_adopt_template_values.py -k the six tests' functions 3 passed, 6 skipped, 69 deselected in 1.86s; UTF-8 9 passed ... in 20.13s; 40531e19 C 6 failed, 3 passed ...
4 predicted restack 963aff8b (head + #845 fc3cb5e9), UTF-8, the 11 files + test_stdout_encoding.py 597 passed, 1 skipped in 256.09s; the skip is the Windows-only test at test_stdout_encoding.py:285
5 the same tree, C, the 8 files 302 passed, 32 skipped in 117.35s
6 head + windows_fsencode taking a path, the 6 files that use it 221 passed in 52.94s

Mutants

Under UTF-8 unless marked C.

Mutant Run Result Killed by
m1, the writer's: template-values byte test asks after mkdir 4 non_utf8 files 1 failed, 107 passed [adopt-template-values] row, by the AttributeError
m1 with windows_fsencode taking a path same 1 failed, 107 passed same row, by the empty-tmp_path assertion
m1 with the row wrapping os.fspath same 1 failed, 107 passed same, by the empty-tmp_path assertion
m1, path-taking emulation, row without its empty assertion same 108 passed survives (the assertion is the part that holds it)
m1, head emulation, row without its empty assertion same 1 failed, 107 passed AttributeError only
Own: git-reads test asks after mkdir (head emulation / path-taking) test_non_utf8_git_failures.py 1 failed, 35 passed each [adopt-git-reads]: AttributeError / empty assertion
Own: plan-escapes test asks after mkdir (head emulation / path-taking) same 1 failed, 35 passed each [adopt-plan-escapes]: AttributeError / empty assertion
own1, the writer's: except Exception as exc: pytest.skip in with_default_branch same 5 failed, 31 passed the 4 with_default_branch rows, and the scan {'test_adopt_git_reads.py': [567]}. With 40531e19's scan: 1 passed, 28 deselected (invisible), as the writer says
m2b, the writer's: flag test asks after adopted C 3 failed, 3 passed U+2028, U+202E and U+2066 rows (UnicodeEncodeError)
m2c, the writer's: caf+U+00E9 test asks after make_source_repo C / UTF-8 1 failed / 1 passed the test (UnicodeEncodeError at conftest.py:916 mkdir); passes under UTF-8 (CI)
Own: flag test asks about flag, not value C / UTF-8 3 failed, 3 passed / 6 passed the same 3 rows, under C only
Own: Exception dropped from CATCH_AN_ASSERTION_ERROR test_non_utf8_git_failures.py 1 failed, 35 passed scan row [exception]
Own: bare except dropped from catches_an_assertion_error same 1 failed, 35 passed scan row [bare]

Merge results

git merge-tree --write-tree of bcf6952e:

Scratch paths

  • Clone: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b
    • private refs: refs/rv869b/pr<N> (33 heads), refs/rv869b/sim-m1, sim-m2, sim-m3, m2x<N>.
  • Worktrees, all under /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/:
    • head: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-head (bcf6952e, clean)
    • previous head: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-prev (40531e19)
    • predicted restack: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-restack (tree 963aff8b)
    • mutants: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-mut-*, left mutated. RV869b-mut-wf holds a local-only scratch commit cf4bc0c1.
    • prototype rows: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-proto, /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-proto-m2b, /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-proto-m2c
  • Logs: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-logs/
    • test runs: run1-head-utf8-11.log, run2-head-c-8.log, run3-restack-utf8-12.log, run4-restack-c-8.log, and mut-*.log
    • scan and merge results: scan-pr-heads.txt, scan-merged.txt, merge-m2-prs.txt, open-prs.json
    • NIT 2 prototype: test_rv869b_c_rows.py.txt
  • Scripts:
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-run.sh
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-mutate.py
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-scan.py
    • /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-forms.py
  • Stub gh: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/RV869b-stubbin/gh
  • Basetemps: /workspace/projects/openRepoShape-worktrees/_lane3-scratch/RV869b-scratch/bt-RV869b-*

No Windows or macOS run was possible; those answers are emulated. Nothing was pushed or posted, no GitHub write was made, and no git config was changed. The scratch commits used env-var identities only.

Lane: openreposhape-3 (openRepoShape-3)

…s hold the C-locale skips of test_adopt_template_values.py in CI (#853, #854)

Fix round 2 of #869, RV869b's NIT 1 and NIT 2.

NIT 1: windows_fsencode now calls os.fspath first, so a test that asks
os.fsencode(tmp_path) under the emulation no longer fails with an
AttributeError before the question it holds; the rows of
test_non_utf8_git_failures.py that ask after a mkdir now fail on their own
empty-tmp_path assertion. A row in test_non_utf8_name_helpers.py holds it.

NIT 2: six emulated rows in test_non_utf8_git_failures.py (os.fsencode as
ASCII, make_source_repo failing) hold the six tests of
test_adopt_template_values.py that skip under LC_ALL=C: each must skip on
the file name encoding with nothing made under tmp_path. CI runs UTF-8, so
a test that asked after make_source_repo or adopted passed there before.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-18T04:48:33Z) Fix round 2 (W869g, sonnet-xhigh) (2572a717, a fast-forward from bcf6952e), for RV869b's two optional NITs. The commit touches 3 test files (+72/-4). Nothing was merged.

  • NIT 1, taken. windows_fsencode (tests/conftest.py:1187) now calls os.fspath(text) first. A new row, tests/test_non_utf8_name_helpers.py:93, asserts windows_fsencode(Path("caf\udcff")) == b"caf\xed\xb3\xbf". With os.fspath taken out, that row fails on AttributeError. RV869's m1 now fails on assert list(tmp_path.iterdir()) == [] and no longer on an AttributeError.
  • NIT 2, taken. Six emulated rows are in tests/test_non_utf8_git_failures.py:299-347: flag-u2028, flag-u202e, flag-u2066, elector-accented, elector-zwnj and cafe-directory. Each sets os.fsencode = ascii_fsencode and make_source_repo to the failing stub, and asserts a skip on "file name encoding" with tmp_path empty. Under UTF-8, m2b fails 3 failed, 39 passed and m2c fails 1 failed, 41 passed. Two more mutants die too: the flag test asking about flag, and the elector test asking after make_source_repo. The body's "Left out" bullet now says the rows exist, and I corrected three other lines that became false.
  • Runs. UTF-8 over the 7 windows_fsencode/ascii_fsencode files plus test_adopt_template_values.py and test_repo_hygiene.py: 411 passed in 111.76s. C locale over test_non_utf8_git_failures.py and test_adopt_template_values.py: 109 passed, 11 skipped in 44.32s.
  • Not taken, as ruled. NIT 3 is left, and NIT 4 goes in the squash message.

Lane 3's own check, not a reviewer's verdict: the round is tests only and takes two optional NITs, so it carries no opus re-check of its own. Lane 3 read every line of the diff (3 files, +72/-4, no non-ASCII added) and the writer's runs and mutants. The gate that runs before #869 lands covers the whole PR on its predicted squash tree, after #845 lands and #869 restacks.

Lane: openreposhape-3 (openRepoShape-3)

Brett Heap and others added 2 commits October 18, 2026 10:22
…that landed as 0f69339, so the squash merges after it with only #845's files to settle

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s/test_adopt_template_values.py, tests/test_non_utf8_name_callers.py and tests/test_non_utf8_oserror_sites.py, which are #845's files and equal its final head there; tests/conftest.py is #845's squash's text with this branch's two changes laid on it, so main's NOT_UTF_8_BRANCH, NOT_UTF_8_BRANCH_NAMED and git_answer_bytes stay

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-3, 2026-10-18T10:26:50Z) #869 is restacked onto main by lane 3's R869 (sonnet), now at ba2d7ab4. #845 landed as 0f69339, and GitHub moved the base to main when #845's branch was deleted.

Lane: openreposhape-3 (openRepoShape-3)

@sonarqubecloud

Copy link
Copy Markdown

@brettheap
brettheap marked this pull request as ready for review October 18, 2026 11:22
@sourcery-ai

sourcery-ai Bot commented Oct 18, 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 3 days and 8 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@brettheap
brettheap merged commit 87efa1b into main Oct 18, 2026
5 checks passed
@brettheap
brettheap deleted the l3-853-854-test-skips branch October 18, 2026 11:22
brettheap pushed a commit that referenced this pull request Oct 18, 2026
…ith #815, #770, #869 and #802 (#883)

Round 5 of #883, a refresh. Each line comes from its squash body and was
checked against the code at main 0d5d2b1:

- #815 (#764): a project's bootstrap ends a validator's exit 2 as
  `bootstrap REFUSED`, exit 2, takes an upstream path, cache or pin it
  cannot read as no answer, and leaves a reftable leg's cherry-pick or
  revert alone. A line in "What changed", one in "What 1.1.1 fixes", and
  a note under "What a script sees" on the direct run's exit code. Its
  body's leftovers, two tracebacks on Python 3.12 and 3.13 and two
  "failed" texts beneath a REFUSED line, are a new limit.
- #770 (#755) and #869 (#853, #854): tests, in the Tests line. The test
  limit for #853 and #854, and the skip #845 left, which #869 removes, are
  retired.
- #802 (#675): update-shape.py's `git show` lines are shell-quoted and its
  kept-copy readers read some Python as Python does. Its one-hop read and
  what it reads as running are a new limit.

67 pull requests; 69 of the milestone's 72 issues closed at 11:31Z, and
the open list is the 3 that read leaves: #707, #879 and #884. The
shape-copy lists stand: the assembly root's bootstrap.py, which #815
changes, is on them. No other file changes.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 18, 2026
… the release commit, #778's leg-clone sentence and #802's readers sentence, each checked against runs at v1.1.0 and main (#883 follow-up) (#893)

The v1.1.1 notes landed as the release commit `5017830` (#883), and RV883's round 5 held two SHOULDs and five NITs for after it (#883 issuecomment-6250558821). This applies them to `docs/release-notes/v1.1.1.md`, with two more sentences lane 1's review found:

1. **#778's leg-clone sentence** says what runs at `v1.1.0` and `5017830` show. A leg clone whose own `AGENTS.md` says so keeps its leg row and its Triad row over each fault, where v1.1.0 gave `FINDING the way in refused` over a tab line and a traceback, exit 1, over a pattern that does not compile or a policy that raised on its name. A leg known only by its name gets a repository's two `n/a` rows.
2. **"Is", not "stays", exit 2,** in the pattern case, which was exit 1 in v1.1.0.
3. **#802's clause is dropped:** v1.1.0's `_blocks_inside` already read a `try`'s handlers, `else` and `finally` outside its guard.
4. **"What 1.1.1 fixes"** names "or cannot be used", and `the other way in`.
5. **#815's leftover tracebacks** were measured on Python 3.12; 3.13 is read, not run.
6. **#871 lets `_` through for any owner,** an organisation's name included.
7. **#869 asks the disk** only about a name that is not UTF-8.
8. **#802's readers:** at v1.1.0 only the import reader skipped an `if TYPE_CHECKING:` body; the binding reader skips one now.
9. **A known limit names #940:** under the `C` or POSIX locale, the bash `openRepoShape` and `setup.sh`'s guards refuse a URL, path or ref with a letter past ASCII as "a control character", a regression from v1.1.0 in the launcher through #872 (#866); a UTF-8 locale takes such a URL or path.

The draft-time lines in the sections marked "remove at tag time" say main `2d372bb`, where #778 landed file for file as its reviewed head `8259ea1`, and that #879 moved to v1.2.0. The release body never carries those sections.

Review: lane 1's independent reviewer found `b795ef74` NOT READY, on the leg-clone sentence, and `ca49f125` READY, with each changed sentence checked against runs at `v1.1.0` and `5017830`. Lane 1's second reviewer found `6cdb5551`, which adds the #940 limit, READY, with each clause measured against the launcher at `64464d31` and at v1.1.0.

It lands by fast refresh (Brett Heap, 2026-10-15T22:48:35Z). Its reviewed head `6cdb5551` is green on Linux and SonarCloud. The branch merged main once and was never rebased; the last merge is update-branch's, clean, giving f60654e, which is green on SonarCloud and Git Bash. Lane 1's gate passed on its tree: the 5 test files that read the release notes or the workflows (`test_repo_hygiene.py`, `test_release_workflow.py`, `test_workflow_concurrency.py`, `test_agents_md_codes.py` and `test_cli_reference.py`), 221 passed and 0 skipped.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment