Repository navigation
tests/test_value_pattern_line_break.py: ID_READERS says checked_value refuses a line feed in adopt-project.py's --id, which never calls it, and the docstrings say a fullmatch reader passes the guard when it must be listed (#1166 follow-up) #1229
Description
(lane openRepoShape-5, 2026-10-23)
Goal: tests/test_value_pattern_line_break.py says only what is true of the readers of PROJECT_ID_RE: no row of ID_READERS gives a reason that does not hold for the tool it names, and the guard test_every_reader_of_the_id_pattern_is_in_the_table tells the author of a new reader, in its docstrings and in its failure message, that the one way to pass is a row in ID_READERS, whichever method the reader calls.
Problem
This issue applies once #1166 (#1139) has landed. #1166 is open at 5102b4294 (read with gh pr view 1166 on 2026-10-23, updated 18:04:21Z), and its second commit adds the guard. Its body was corrected for the two wordings below that it repeated (it says that adopt-project.py never calls checked_value on --id, and that "ID_READERS still gives it the checked_value reason"), so only the test file is left. Line numbers are tests/test_value_pattern_line_break.py at 5102b4294.
- A false reason for
adopt-project.py's argv--id(rc1166b's NIT 2).- The module docstring's "LEFT AS THEY ARE" bullet (
:42-45) reads: "The argv readers ofPROJECT_ID_RE(--idinscaffold-project.py,family.py initandadopt-project.py): each holds the id tochecked_valueafter the pattern, which refuses a line feed asunsafe-valuenaming--id(tests/test_derived_id_refusals.py)." - The
ID_READERSrows forscripts/family.py(:158-159) andscaffold-project.py(:160-161) say "argv--id:checked_valuerefuses a line feed after it". Theadopt-project.pyrow (:162-166) begins "argv--id, as above", which is the same reason. - It holds for two of the three.
scaffold-project.py:2517callschecked_value("--id", project_id)andscripts/family.py:2626callschecked_value("--id", family_id);tests/test_derived_id_refusals.py'sTOOLS(:59) pins that answer forscaffoldandfamilyonly. adopt-project.pynever callschecked_valueon--id. Its calls (git grep 'checked_value(' 5102b4294 -- adopt-project.py) are for--project(:5401), the tracking branch,--pin-owner, the leg paths and--org, and for the plan's keys. Its reader of the idplantakes, passed or derived, isPROJECT_ID_RE.match(project_id)at:5140, which takesnorthwindfollowed by a line feed.- A line feed is still refused, by another door: the project's own
validate-manifest.py(measured below, forplan).
- The module docstring's "LEFT AS THEY ARE" bullet (
- The docstrings say
fullmatchis enough (rc1166b's NIT 1).- The module docstring (
:57-60): "A NEW READER ofPROJECT_ID_REis held to the same rule bytest_every_reader_of_the_id_pattern_is_in_the_table: it asks withfullmatch, or it is listed inID_READERSwith the reason a line feed cannot reach it." - The test's docstring (
:196-198): "A reader written later that asksPROJECT_ID_REwithmatch(orsearch) takes "atlas\n": it is read withfullmatch, or it is inID_READERSwith the reason a line feed cannot reach it, or this fails." - The guard is
assert id_pattern_calls() == expected(:200), a dict equality over every(module, method)of every call. It is exact in both directions, so a newfullmatchreader fails it too, and so does a listed reader taken away. The assert has no message, so the author of a sibling PR sees only a dict diff.
- The module docstring (
- The guard reads spellings, not meaning (rc1166b's NIT 4, optional).
_ID = PROJECT_ID_REfollowed by_ID.match(value)passes it, and by reading so doesfrom repo_shape import PROJECT_ID_RE as X.id_pattern_calls(:170-192) counts only a call whose receiver is the namePROJECT_ID_REor an attribute of that name. The body of validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166 claims only the two spellings, andid_pattern_calls's docstring names the same two, so nothing in either is false; an alias is simply outside the guard.
Measured
Lane 5's re-check of #1166 (#1139), rc1166b, NIT 1, NIT 2 and NIT 4 (#1166 issuecomment-6371408915), at 5102b4294:
- NIT 2.
adopt-project.py plan --id=northwind<LF>, from a local source through conftest'swrite_plan, exits 2 and writes no plan:REFUSED adopt-manifest-invalid: --id is 'northwind\n', which the project's own validate-manifest.py refuses: manifest-id: id is 'northwind\n'; it must match ^[a-z0-9][a-z0-9-]*$.Measured forplanonly;applyand the other adopt paths were not. - NIT 1.
def _rc_probe(value): return PROJECT_ID_RE.fullmatch(value)appended toupdate-shape.pyfails the guard withLeft contains 1 more item: {('update-shape.py', 'fullmatch'): 1}. Making oneadopt-project.pyreader unreachable (if False:in place of the plan-id:test at:6791) fails it too:{('adopt-project.py', 'match'): 2} != {('adopt-project.py', 'match'): 3}. Neither failure namesID_READERS. - NIT 4.
_ID = PROJECT_ID_REthen_ID.match(value)inupdate-shape.py: both guards,2 passed. APROJECT_ID_RE.match(...)inside a string or a comment is correctly not counted:2 passed. - The file on the head, through the review's
run9.sh(stub gh,GH_TOKEN=bogus,EMAILexported,dirty=0): 30 passed on git 2.43.0 (31.59s) and on 2.47.1 (29.43s).
The drafter re-read the three places and the checked_value calls at 5102b4294 (git show of the test file, adopt-project.py, scaffold-project.py, scripts/family.py and tests/test_derived_id_refusals.py).
Suggested fix
Wording and one message, in the test file only; no production file.
- Correct the reason. In the module docstring bullet (
:42-45), say that the first two hold the id tochecked_valueafter the pattern, and thatadopt-project.pydoes not:plantakes it withmatchand the project's ownvalidate-manifest.pyrefuses the line feed (adopt-manifest-invalid, inmanifest-id's words). In theadopt-project.pyrow (:162-166), replace "argv--id, as above" with that reason. Thescripts/family.pyandscaffold-project.pyrows can stay.- Optional, so the reason is true by test as the other two are by
TOOLS: one row that runsadopt-project.py plan --idwith a trailing line feed and asserts exit 2 andadopt-manifest-invalidnaming--id. The review measuredplanonly.
- Optional, so the reason is true by test as the other two are by
- Say "listed in
ID_READERS" for any new reader. In both docstrings (:57-60,:196-198), drop "it asks withfullmatch, or": a new reader,fullmatchincluded, needs a row, and a reader taken away loses its row, because the table is exact. A sibling that adds any reader must add one. The body of validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166 found none among the open PRs. - Give the assert a message that names
ID_READERSand what to do, for example that it lists every call of a method ofPROJECT_ID_REoutsidetests/,fullmatchincluded, and that the author adds, changes or drops the row of the module and method the diff shows. - Optional, NIT 4: make the guard see an alias, or say in the docstring that it reads spellings and stops there. To see one: an
ast.Assignwhose value is thePROJECT_ID_REname or an attribute of that name, and an importasthat renames it, each a failure that names the alias and the file. A match in a string or a comment must stay uncounted. Leaving it and saying so is a fair answer.
Verify
git grep -n 'checked_value' tests/test_value_pattern_line_break.pyshows thechecked_valuereason only againstscaffold-project.pyandscripts/family.py, and theadopt-project.pyrow and the module docstring namevalidate-manifest.pyandadopt-manifest-invalidfor it.- A scratch clone with one reader added to a tracked module outside
tests/, once per method (fullmatch,match,search) onupdate-shape.py: the guard fails each time, and its message namesID_READERS. Each plant is restored and the file's sha256 checked, as rc1166b did (restored=Trueeach time). - A listed reader made unreachable (
if False:atadopt-project.py:6791): fails, and the message namesID_READERS. - The file passes: 30 passed on git 2.43 and 2.47.1 as at
5102b4294(31 if the optionalplanrow is added), and the hygiene five (test_pinned_copy_text.py,test_path_guard_hygiene.py,test_repo_hygiene.py,test_agents_md_codes.py,test_cli_reference.py: 306 passed on git 2.43.0 at that head). - The diff touches only the test file, adds no non-ASCII line and no
assertthat joins conditions withandoror. - If NIT 4 is done: the alias plants (
_ID = PROJECT_ID_REthen_ID.match(value), andfrom repo_shape import PROJECT_ID_RE as X) fail the guard, and aPROJECT_ID_RE.match(...)in a string or a comment still passes it.
Found by lane 5's re-check of #1166 (#1139), rc1166b, NIT 1, NIT 2 and NIT 4 (#1166 issuecomment-6371408915), at 5102b4294; the three places and the checked_value calls were re-read at that head by the drafter.
Lane: openreposhape-5 (openRepoShape-5)
Activity
brettheap commentedon Oct 23, 2026
CLAIMED — lane openRepoShape-5, session 50cede29-ab82-4ca3-9f67-d98e1a58c8d2@Eagle, 2026-10-23T21:20:52Z, for #1229
Logged in
lanes/log/openRepoShape-5.mdat894023c9e4d4c26ba08f34f6a22fb363785b0740.The three reads (lane-collision-protocol Rule 1):