Skip to content

scripts/repo_shape.py: NamingPolicy reads a name with fullmatch at four sites, so a name that ends in a line feed matches no family and validate-repository-naming.py refuses it, and repository-naming.yaml says a pattern is read whole (#1202) - #1266

Draft
brettheap wants to merge 1 commit into
mainfrom
fix/1202-naming-fullmatch

Conversation

@brettheap

@brettheap brettheap commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Goal

#1202: a repository name that ends in a line feed is the name of no family of the naming policy, and validate-repository-naming.py refuses it as naming-unclassified, by name, over a manifest's leg repository: and over an argument, where main classified Atlas\n as Atlas and exited 0.

This is a DRAFT on main (be21751c3, the landing for #1243). It is the follow-up lane 5 filed as #1202 from its independent review of #1166 (#1139), finding 1 (pull/1166 issuecomment-6352173084). #1166 ended the seven module-level patterns of the validators in \Z and read the three ids with fullmatch, and left NamingPolicy, whose patterns come from contracts/repository-naming.yaml, every one ^...$, read with .match. The change is one commit, 09697e9c5: 3 files, +255 and -4 (git diff --shortstat origin/main...HEAD): scripts/repo_shape.py (+5 -4), contracts/repository-naming.yaml (+8), and the new tests/test_naming_policy_line_break.py (+242, 77 rows).

What held on main

Measured on main be21751c3 (production code equal to 5926cccab, where the branch was cut), Python 3.12.3, git 2.43.0, a stub gh and no network.

NamingPolicy read a name with .match at four sites of scripts/repo_shape.py: descendant_referents (the family's _re, then its _split_re) and matches (a role's _re, then a family's). In Python $ also matches just before a trailing line feed, and the YAML reader reads a double-quoted "...\n" as the text and a line feed. So matches, classify and descendant_referents gave a name with a trailing line feed the answers of the name without it (NamingPolicy.load(contracts/repository-naming.yaml), in process):

Name, with and without \n classify on main On this branch, with \n
Atlas, Atlas-spec, Atlas-code ('project-leg', 'assembly' / 'spec' / 'code') matches == [], classify is None
openFoo ('neutral-product', None), also project-leg/assembly matches == [], classify is None
Thing-Install ('install', None) matches == [], classify is None
user-wip ('workspace', None) matches == [], classify is None
InkxRouter, MedxScribe ('project-leg', 'assembly'), with descendant_referents ('openRouter', 'openxRouter') and ('openScribe', 'openxScribe') matches == [], classify is None, and descendant_referents == ()

Atlas-Spec (a capital S) is None with and without the line feed, on both. topic_pattern.match('xf-project-atlas\n') is a match on main; no tool reads topic_pattern (see Limits).

The gate (validate-repository-naming.py, run by the root template at Makefile:48 and validate.yml:310), measured by the new rows run on main's code:

What changed

  • scripts/repo_shape.py: the four sites read fullmatch. NamingPolicy is the only code that matches a name against the data's patterns (grep of the tracked *.py; scaffold-project.py:1535 prints the neutral-product pattern's text in a remedy and matches nothing). A one-line note beside topic_pattern says that a reader must use fullmatch, because $ takes a final line feed.
  • contracts/repository-naming.yaml: a paragraph at the end of the header, "A PATTERN IS READ AGAINST THE WHOLE NAME", for a fork's pattern. A pattern with no $ was read as a prefix under .match and is read as the whole name now, so a fork writes the pattern for the entire name. I took this of the two ways the issue offers (the other is to keep .match and refuse a name that holds a line feed at the entry of matches, classify and descendant_referents) as the shorter. Every shipped pattern begins with ^ and ends with $, and the measured sweep below shows fullmatch changes no answer except a trailing line feed.
  • tests/test_naming_policy_line_break.py (new, 77 rows):
    • the names are read from the data (families[].examples, roles[].examples, the descendant family's claim_without_referent_examples), so a family or a role added to the contract is covered without a line here; a declared_only family is asked under its own id;
    • a baseline row per name (the name without the line feed is matched as it was) and, per name with the line feed, matches == [], classify is None and descendant_referents == ();
    • rows over a fork's policy (NamingPolicy built from the shipped data with ONE pattern written without $) for each of the four sites;
    • the gate rows: validate-repository-naming.py --project over a scaffolded root for each of the three roles, a double-quoted baseline, and an argv name for each, with its baseline.
  • Nothing else. No refusal code is added, changed or renamed, no sentence of a refusal changes, no command or flag is added, so AGENTS.md, README.md, docs/ and the handbook mirror stay as they are. Before the change I grepped tests/, README.md, docs/ (the handbook), AGENTS.md and contracts/ for text that pins the header's wording or a prefix reading of a policy pattern: nothing reads the contract's comments, and the only patterns a test writes into a policy are tests/test_naming_policy.py:2498's fork form ^~[a-z]+$, which has a $, and tests/test_doctor_validator_verdicts.py:324's corrupted (^open(?:, which does not compile.
  • What pins scripts/repo_shape.py. This repository holds no copy of it and no digest of it. A project's copy is pinned by the shape pin's tree digest (sorted-ls-tree-r-v1, computed over the shape's tree at the pinned commit), and update-shape.py reaches it as an upstream-changed scripts/repo_shape.py row; contracts/repository-naming.yaml is in the copy lists of scripts/shape_materialize.py (lines 444 and 652) and reaches a project the same way. fullmatch needs no import, so no pinned script meets a name it lacks; tests/test_pinned_copy_text.py passes (hygiene five below).

The rows failing on main

tests/test_naming_policy_line_break.py run on main's production code (n1202-mut, a detached tree at be21751c3 with the new file copied in; sha256 of the file equal to the branch's): 40 failed, 37 passed (run-new-main-be21751c3.log). The 37 that pass are the baselines (21 family names, 6 role names, 6 descendant names, the double-quoted leg, 3 argv names). The 40 that fail, and why:

Row (function) Failing on main Because
test_a_name_that_ends_in_a_line_feed_matches_no_family 24: neutral-product- openxFactory, openXwallet, openChart, openDox, openXdox; install- xFactory-Hermes-Install, Hermes-Install, Keycloak-Install; domain-descendant- MedxChart, LedgerxWallet, codexFactory, MedxGlass, codexDox; project-leg- Atlas, Atlas-spec, Atlas-code, Northwind, Northwind-spec, Northwind-code; family- InkRouter, Northwind; workspace- brett-wip, scott-wip, a1-wip matches(name + "\n") was the answer for the name
test_a_descendant_name_that_ends_in_a_line_feed_has_no_referent 6: MedxChart, LedgerxWallet, codexFactory, MedxGlass, codexDox, MedxScribe descendant_referents gave openChart and openxChart, and so on
test_a_forks_descendant_pattern_with_no_dollar_is_read_as_the_whole_name 2: family-pattern, split-pattern a prefix pattern took MedxScribe
test_a_forks_leg_pattern_with_no_dollar_is_read_as_the_whole_name 2: role-pattern, family-pattern a prefix pattern took Atlas_x
test_the_naming_gate_refuses_a_leg_repository_that_ends_in_a_line_feed 3: assembly, spec, code exit 0 where 1 is expected
test_the_naming_gate_refuses_an_argv_name_that_ends_in_a_line_feed 3: Atlas, Atlas-spec, Atlas-code exit 0 where 1 is expected

On the branch all 77 pass. The refusal is, for each: exit 1 and the line FINDING naming-unclassified: <name>.

No name without a line feed changes its answer (measured, not argued): matches, classify and descendant_referents over 66,688 names (every string of up to 5 characters over A a x X - 1 _, a space and a line feed, and 11 stems with 12 suffixes, with and without open) under 5 declared roles (none, assembly, spec, code, family), on main and on the branch: 333,440 rows, 3,225 differ and every one is a name that ends in a line feed; none that does not; and no name that ends in a line feed matches anything on the branch (probe_inproc.py and sweep.py in lane 5's work/n1202/). tests/test_naming_policy.py passes unchanged.

Mutants

Each applied alone to scripts/repo_shape.py on the branch's copy in n1202-mut, run against the new file, and restored with a sha256 check (restored True, and at the end the file is main's bytes again, blob 00759f1e6):

Mutant Result Killed by
M1: descendant_referents, the family's _re.fullmatch put back to .match 1 failed, 76 passed test_a_forks_descendant_pattern...[family-pattern]
M2: descendant_referents, _split_re.fullmatch put back to .match 1 failed, 76 passed test_a_forks_descendant_pattern...[split-pattern]
M3: matches, a role's _re.fullmatch put back to .match 25 failed, 52 passed 18 of the every-name rows, test_a_forks_leg_pattern...[role-pattern], and the 3 leg and 3 argv gate rows
M4: matches, a family's _re.fullmatch put back to .match 31 failed, 46 passed all 24 every-name rows, test_a_forks_leg_pattern...[family-pattern], and the 3 leg and 3 argv gate rows
M5: M1 and M2 together 14 failed, 63 passed 6 every-name rows, the 6 descendant rows, both fork descendant rows
M6: all four sites 40 failed, 37 passed the same 40 as on main

No survivor. M1 and M2 are killed only by the fork rows, and that is the shape of the code, not a gap in the rows: the two sites of descendant_referents stand in series, and the shipped split_pattern takes the family pattern's language, so on the shipped data either alone makes the other redundant (M5 is what the shipped-data rows kill). A fork's policy whose one pattern has no $ is what asks each by itself; it is also the case the contract's new paragraph is written for.

Runs

Python 3.12.3 (CI runs 3.14; the rows assert lists, tuples and finding lines, nothing that depends on a repr or an ast.dump), through lane 5's run10.sh (gh stub first on PATH, bogus token, empty GH_CONFIG_DIR, blank git identity, GIT_SSH_COMMAND=false, GIT_CONFIG_GLOBAL=/dev/null), git-filter-repo 2.47.0 (CI's pin; git filter-repo --version prints a40bce548d2c), at head 09697e9c5, dirty=0:

Run git Result
the new file, tests/test_value_pattern_line_break.py (the sibling it imports two helpers from), tests/test_naming_policy.py, and the hygiene five: test_path_guard_hygiene, test_repo_hygiene, test_agents_md_codes, test_cli_reference, test_pinned_copy_text 2.43.0 751 passed in 131.18s
the same files 2.47.1 (tools/git247/bin/git, built from kernel.org's tarball) 751 passed in 120.02s
the neighbours that name NamingPolicy or run the naming gate: test_manifest_validator, test_scaffold_referent_chain_links, test_chain_pin_sources, test_github_name_limits, test_adopt_manifest_values, test_scaffold_manifest_values, test_reader_refusals_named, test_pin_source_env_collisions, test_family_init_values 2.43.0 750 passed, 19 skipped in 383.95s (all 19 are template skips in tests/test_family_init_values.py: 16 at :229, "this template quotes the placeholder", and 3 at :301, "this template quotes id:", as rv1266 printed them with -rs)

Before the rebase onto be21751c3 the same files (without the sibling) passed at the then head f552017f1: 720 on 2.43.0 and 720 on 2.47.1. Not run: the full suite, a real Windows host and macOS, and test_shape_doctor.py (it reads the naming validator through the doctor and no name in it ends in a line feed).

Merges

Read again by rv1266 at 2026-11-08T17:10Z: main 46fe6ac19 gives tree 251537e4, clean, and main 12122952b gives c46cbe55, clean. The new file, test_value_pattern_line_break, test_naming_policy and the hygiene five passed on that predicted merge (751, git 2.43.0), since 12122952b changed tests/test_pinned_copy_text.py.

git merge-tree --write-tree <other> 09697e9c5 (git 2.43.0) at 2026-11-08T16:29Z, against main and every open PR that touches one of this PR's files (50 open):

Against Head Tree
main be21751c3 836cb7fec (clean)
#1249 (scripts/repo_shape.py) 3146c3ca5 f41cf1dca (clean)
#1171 (scripts/repo_shape.py) 8162b874e 29eee887f (clean)
#1236 (scripts/validate-repository-naming.py, which the new rows run) 352dcbc96 64990151d (clean)

The later lander takes the refresh.

Limits

  • topic_pattern has no row. Nothing outside tests/test_naming_policy.py:422 reads it at main, and the data's topic.pattern and topic.id_pattern are read by no tool, so a row cannot fail on main for it. The note beside it, and the contract's paragraph, say a reader must use fullmatch.
  • A project's own copy reaches this through update-shape.py. Until a project takes the new scripts/repo_shape.py its validate-repository-naming.py and validate-manifest.py run the old .match. The root's validate-manifest.py already refuses a leg repository: that ends in a line feed since validate-manifest.py, validate-family.py, family.py and update-shape.py: an id:, a date or a repository: ending in a line feed is refused by name, and a pin's source_repository: that is no path or owner/repo name is named as the pin's (#1139) #1166.
  • The refusal prints the name raw. naming-unclassified names the name as typed, so Atlas\n ends the finding's first line and the existing text ("These names match none of the families ...") follows after a blank line; a name holding an ESC prints raw there on main too. Not changed: the issue asks that the name be refused by name, and no wording or code moves.
  • A fork's data that relied on a prefix reading. A fork's pattern with no $ is read as the whole name now, as the contract's header says. The shipped data has none, and no test writes one.
  • Not touched, read at their call sites: scaffold-project.py, setup-project.py, family.py and shape_materialize.py take a name from argv, which checked_value refuses first; validate-family.py strips it.

Closes #1202

Lane: openreposhape-5 (openRepoShape-5)

🤖 Generated with Claude Code

Summary by Sourcery

Ensure repository naming policy evaluation uses whole-name matching so names ending in a line feed are rejected consistently.

Bug Fixes:

  • Reject repository names ending in a line feed as unclassified instead of treating them as their newline-free equivalent.

Enhancements:

  • Make all repository naming policy patterns match the entire name, including custom patterns without an explicit end anchor.
  • Document whole-name pattern matching and the corresponding requirement for future readers of topic patterns.

Documentation:

  • Document that repository naming policy patterns are evaluated against the whole name.

Tests:

  • Add coverage for trailing-line-feed handling across naming classification, descendant referents, custom patterns, manifest repositories, and command-line names.

…t four sites, so a name that ends in a line feed matches no family and `validate-repository-naming.py` refuses it, and `repository-naming.yaml` says a pattern is read whole (#1202)

Every pattern of `contracts/repository-naming.yaml` is `^...$`, and
`NamingPolicy` read a name against it with `.match` in
`descendant_referents` (the family's pattern, then its `split_pattern`) and
in `matches` (a role's pattern, then a family's). In Python `$` also matches
just before a trailing line feed, so `Atlas\n` was classified as `Atlas`, and
`validate-repository-naming.py --project project.yaml` over a leg
`repository: "testorg/Atlas\n"`, or over the argument `$'Atlas\n'`, exited 0.
The four sites ask `fullmatch` now. Every shipped pattern begins with `^` and
ends with `$`, so no name without a line feed changes its answer. A fork's
pattern with no `$` read as a prefix of the name under `.match`; the contract's
header now says a pattern is read against the whole name, which is the
shorter of the two ways the issue offers. `topic_pattern` has no reader
outside `tests/test_naming_policy.py`, so a note beside it says a reader must
use `fullmatch`, and no row can fail on main for it.

`tests/test_naming_policy_line_break.py` reads its names from the data, so a
family or a role added to the contract is covered, and holds a fork's policy
whose one pattern has no `$` for each site: the two sites of
`descendant_referents` stand in series, and the shipped `split_pattern` takes
the family pattern's language, so on the shipped data either alone makes the
other redundant.

Closes #1202

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

sourcery-ai Bot commented Nov 8, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implementation

Switch all four NamingPolicy checks to fullmatch so names must match the entire pattern, and document the same requirement beside topic_pattern.

  • scripts/repo_shape.py L2231, L2268-2270, L2436-2439

Configuration

Clarify in the naming-policy contract that patterns are matched against the whole name, including patterns without a trailing dollar anchor.

  • contracts/repository-naming.yaml L119-126

Tests

Add regression coverage for trailing-line-feed names, whole-name matching of fork patterns, and rejection by the naming validator.

  • tests/test_naming_policy_line_break.py L1-242

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

sonarqubecloud Bot commented Nov 8, 2026

Copy link
Copy Markdown

@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-5, 2026-11-08T17:11:37Z) Independent review of #1266 (#1202) for lane openRepoShape-5, by rv1266 (opus), at 09697e9: READY

There are no MUST or SHOULD findings. The four sites are the only change in behaviour, and only for a name that ends in a line feed. Every row, mutant and gate the body claims reproduces. There are 7 NITs, none blocking. CI's tests job (the full suite on 3.14) was still pending at 17:10Z, so the landing needs it green.

Scope: one commit, 09697e9c52f35c9aadbafdebb88e47950105f474, on main be21751c3. It is 3 files, +255/-4. The head equals refs/heads/fix/1202-naming-fullmatch and refs/pull/1266/head by ls-remote at 16:45Z and again at 17:10Z. I reviewed in detached worktrees /workspace/projects/openRepoShape-worktrees/rv1266-review and rv1266-mut. Both are clean at the head (porcelain 0).

What held (measured)

  1. The four sites, and nothing else.

    • git grep finds no other reader of a policy pattern. The only readers of _re, _split_re and topic_pattern are repo_shape.py:2268, :2270, :2436 and :2439, plus the compile lines. Elsewhere, scaffold-project.py:1535 and validate-repository-naming.py:795/919 only print a pattern's text.
    • probes/patterns.py checked all 17 compiled patterns (6 families, 3 roles, the split patterns, topic.pattern and id_pattern):
      • every one begins with ^ and ends with $;
      • none is a top-level alternation (the positive control ^a|b$ parses as one BRANCH);
      • no character class admits \n.
    • So fullmatch and .match can differ only on a name that ends in a line feed.
  2. My own sweep confirms it. probes/sweep2.py loads main's and the head's repo_shape.py in one process. It compares matches, classify (with and without declared pins) and descendant_referents.

    • Inputs: every string of up to 5 characters over B b x X - 0 . \n \r \u2028, plus 14 stems x 19 suffixes, with and without a leading or trailing LF. That is 112,091 names under 6 roles.
    • Result: 672,546 rows; 4,200 differ, every one a name that ends in a line feed, and 0 otherwise. At the head, no name that ends in a line feed matches anything.
  3. The writer's sweep reproduces exactly. I re-ran sweep.py against main's bytes and the head's: 333,440 rows, 3,225 differ, all ending in a line feed, 0 otherwise. That is the body's number.

  4. The rows.

    • At the head, 77 of 77 pass (inside gates A and B).
    • I swapped main's scripts/repo_shape.py (blob 00759f1e6, sha256 623af121...) into rv1266-mut. The new file gave 40 failed, 37 passed (logs/rows-on-main.log). Afterwards I restored the head's copy and checked it: sha256 009c249e..., restored=True.
    • The 40 split as 24 every-name + 6 descendant + 2 + 2 fork + 3 leg-gate + 3 argv-gate. The 24 names are exactly the body's list.
    • All 6 gate rows fail as assert 0 == 1, printing ' Atlas' and then project-leg/assembly on the next line.
    • Table-driven: the rows read families[].examples, roles[].examples and claim_without_referent_examples from the data, and a declared_only family is asked under its own id. test_naming_policy.py's FAMILY_IDS is also read from the data and indexes family["examples"], so a family added without examples already fails there.
    • The gate rows: they exit 1 with exactly FINDING naming-unclassified: <name> for assembly, spec and code over --project, and for each argv name.
  5. Mutants. Each was applied alone in rv1266-mut, run against the new file, and restored with a sha256 check (restored True after every one; porcelain 0 at the end). All are killed:

    Mutant Result Killed by
    M1 descendant_referents _re back to .match 1 failed / 76 passed fork [family-pattern]
    M2 _split_re back to .match 1 failed fork [split-pattern]
    M3 role _re back to .match 25 failed 18 every-name rows, leg fork [role-pattern], 3 leg and 3 argv gate rows
    M4 family _re in matches back to .match 31 failed 24 every-name rows, leg fork [family-pattern], the 6 gate rows
    M5 = M1+M2 14 failed 6 every-name, 6 descendant, 2 fork rows
    M6 = all four sites 40 failed the same 40 as main
    X1 (mine) role site fullmatch(name.rstrip("\n")) 24 failed every-name and gate rows
    X2 (mine) family site in matches, the same strip 30 failed every-name and gate rows
    X3 (mine) both descendant sites strip 12 failed 6 descendant + 6 every-name rows
    X4 (mine) validate-repository-naming.py:1097 strips the leg name 3 failed the leg gate rows
    X5 (mine) :1465 strips the argv name 3 failed the argv gate rows
    X6 (mine) M6 plus an LF guard at classify's entry 34 failed every-name rows (matches, descendant_referents), descendant and fork rows
    X7 (mine) _split_re.search 1 failed fork [split-pattern]

    M1 and M2 are killed only by the fork rows. That is the code's shape (the two sites stand in series), as the body says. X3 shows the shipped-data rows do hold the descendant path.

  6. The contract header.

    • The contract reaches a project verbatim through shape_materialize.py's COPIED_FROM_SHAPE (line 444), and a family root through FAMILY_COPIED_FROM_SHAPE (line 652).
    • Main's and the head's contracts load to equal data (data equal: True).
    • Nothing pins its bytes, so the memory note's risk (a byte change breaking another file's regex) does not apply here. The rewrite targets that tests use still count 1 each at the head:
      • kind: repository-naming-policy\n (test_shape_doctor.py:1651, test_doctor_next_is_a_command.py:535);
      • pattern: "\^open\(\?: and - id: assembly(?=\r?\n) (test_doctor_validator_verdicts.py POLICY_EDITS, which asserts count 1).
    • The header adds one textual split_pattern: (1 to 2), but no test or tool reads that text; YAML reads the key.
    • No doc, handbook mirror or digest quotes the header, and no test holds a 64-hex digest of it. The new lines are ASCII.
  7. No legitimate caller passes such a name.

    • git_out strips stdout, and the advisory's other name is a directory name.
    • adopt-project.py, scaffold, setup and family.py take names from argv or a plan, which checked_value refuses first.
    • validate-family.py:615 strips.
    • validate-manifest.py returns at manifest-leg-repository (:1139-1143) before it classifies, so none of its output changes. test_value_pattern_line_break.py[leg-repository], which asserts exactly one finding, passes.
    • No other test feeds a line-feed name to the policy, the gate, or a block scalar (grep).
  8. The body's claims and counts hold.

    • +255/-4; 77 rows; 40/37; M1-M6 counts; the sweep numbers; 751 passed on each git; 750 passed and 19 skipped for the neighbours; the merge trees.
    • Its citations hold: test_naming_policy.py:422 and :2498, test_doctor_validator_verdicts.py:324, scaffold-project.py:1535 (CHAIN_LINK_FORM = "neutral-product"), and shape_materialize.py 444/652.
    • Commit: identity Brett Heap <service@opensoft.dev>; subject 249 characters; one Closes #1202; the Lane line and Co-Authored-By: Claude Sonnet 5.5; ASCII; no assert joins conditions with and or or.

NITs

  1. The body's Runs row guesses the 19 skips wrong. It says they "need another OS or a host" and that "the reasons were not printed". My runs print them (-rs), and they are all template skips in tests/test_family_init_values.py:
    • :229, 16 rows: "this template quotes the placeholder: the run is fine, and test_a_quoted_value_is_held_as_typed runs it";
    • :301, 3 rows: "this template quotes id:: the derived id reads back".
  2. The name is printed raw, and Limits covers only half of it. Probe at the head: validate-repository-naming.py $'Atlas\n' exits 1.
  3. Line length. The new topic_pattern comment at repo_shape.py:2231 is 108 characters, the only line in the file over 100 (main's longest is 93). No linter enforces a limit. Optional wrap.
  4. The Merges section is stale. main is now 46fe6ac19, and it is clean (table below).
  5. No milestone. The PR has none, and repo_shape.py: NamingPolicy reads a name with .match against patterns that end in $, so a name that ends in a line feed is classified as the name without it, and validate-repository-naming.py exits 0 over such a leg repository (#1166 follow-up) #1202 is on v1.2.1. The coordinator should set it before landing.
  6. One unclear cell. In "What held on main", the "the same" cells for openFoo, Thing-Install and user-wip read as "the same as main". They mean the first row's matches == [], classify is None. Wording only.
  7. CI tests was pending at 17:10Z (SonarCloud, package and tests-git-bash pass). Watch it before landing.

Gates

All ran through run10.sh (gh stub, bogus token, blank identity, GIT_SSH_COMMAND=false, GIT_CONFIG_GLOBAL=/dev/null), on Python 3.12.3 with git-filter-repo 2.47.0 (a40bce548d2c), each with rc=0. Gates A-D ran at the head with dirty=0.

Gate Git Files Result Log
A 2.43.0 new file, test_value_pattern_line_break, test_naming_policy, hygiene five 751 passed, 141.06s, 0 skips logs/gateA-core-243.log
B 2.47.1 (tools/git247/bin/git) same 751 passed, 120.31s, 0 skips logs/gateB-core-2471.log
C 2.43.0 the writer's 9 neighbours 750 passed, 19 skipped, 417.13s logs/gateC-neigh-243.log
D 2.47.1 the 9 neighbours 750 passed, 19 skipped, 419.77s logs/gateD-neigh-2471.log
E 2.43.0 gate A's set, on the predicted merge c46cbe55 (main 12122952b + this PR) 751 passed, 125.56s logs/gateE-merge-core-243.log

Every skip in C and D is one of the two template skips in NIT 1. I ran gate E because 12122952b changed tests/test_pinned_copy_text.py. I did not run the full suite, test_shape_doctor.py, Windows or macOS.

Merge-trees

git merge-tree --write-tree <other> 09697e9c5 (git 2.43.0), with heads fetched fresh at 16:51Z and 17:10Z. Of 51 open PRs, only #1249 and #1171 touch repo_shape.py, and #1236 touches the validator the new rows run.

Against Head Tree
main 46fe6ac19 (17:10Z; it touches shape_advisory.py, shape-doctor.py, test_doctor_unsearchable_links.py) 251537e4 clean
main 12122952b (16:51Z) c46cbe55 clean
#1249 3146c3ca5 f41cf1dc clean
#1171 8162b874e 29eee887 clean
#1236 352dcbc96 64990151 clean

The trees for #1249, #1171 and #1236 equal the writer's.

Everything is in /workspace/projects/.lane-worktrees/openRepoShape-5/work/rv1266/: STATE.md, logs/, merge-trees.txt, rows-on-main-failed.txt, and in probes/ the scripts patterns.py, sweep2.py, mutate.py, run-mutants.sh and contract_counts.py. I made no commits, pushes or GitHub writes.

Lane: openreposhape-5 (openRepoShape-5)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant