Repository navigation
shape-doctor.py: a checkout of the standard whose own contracts/repository-naming.yaml does not load makes a compliant project INVALID (naming), exit 1, "the naming policy is not satisfied (exit 2)", so a person is failed for the checkout's fault, and the module's EXIT CODES list leaves out an unfinished merge #678
Copy link
Copy link
Closed
Closed
Copy link
Milestone
Description
Goal: a checkout of the standard that cannot read its own naming policy says CANNOT ANSWER about a project, never INVALID, and the doctor's EXIT CODES list names every kind of exit-1 finding it prints.
Filed by lane openRepoShape-3 on Brett Heap's word of 2026-10-16T12:24:41Z ("give #460 to lane 3").
Size: S. Lands after: nothing; no open pull request touches shape-doctor.py.
What happens (measured on main d4a7fab: a project scaffolded into local bare remotes, with a gh that exits 97):
- From a clean checkout, the project reads
COMPLIANT (exit 0). From a copy of the same checkout whosecontracts/repository-naming.yamlgained one tab-indented line, it reads:FINDING naming the naming policy is not satisfied (exit 2): REFUSED yaml-unparsable: <checkout>/contracts/repository-naming.yaml: line 508: tab used for indentation (every other row ok) INVALID (naming) (exit 1) - The refusal is about the standard's own file.
validate-repository-naming.pyrefuses before it reads the project whenNamingPolicy.loadfails (scripts/validate-repository-naming.py:956-960, exit 2).check_namingaskscrashed()(shape-doctor.py's twonamingrows read only the naming script's exit code, so a crash of the STANDARD's ownvalidate-repository-naming.pyis a FINDING about the project (INVALID (naming), exit 1, where #357 makes a crashed template CANNOT ANSWER), and a directory whose name is not UTF-8 getsnaming FINDING Atl?as: UnicodeEncodeError: ..., the script's traceback quoted as a fact about the name #410, shape-doctor.py: a validator's verdict is a printedFINDINGorREFUSEDand any other non-zero exit is a crash, so a gate killed by a signal, ended byos._exit(1), holding conflict markers or failing argparse no longer "reports a finding", a crash of the standard's own naming script is CANNOT ANSWER instead ofINVALID (naming), and a pass that printedWARNINGornotelines is anotequoting them while a red row quotes its finding and never a warning (#410, #448) #557), which answers None for any printedREFUSED, so the row becomes the generic FINDING about the project. - "is not satisfied" is the wrong verb for exit 2;
validator_rowsays "refuses" for 2 (shape-doctor.py:1852). check_not_a_root_namingquotes the same refusal as the directory name's finding. Its verdict stays NOT A SHAPE ROOT.- shape-doctor.py's two
namingrows read only the naming script's exit code, so a crash of the STANDARD's ownvalidate-repository-naming.pyis a FINDING about the project (INVALID (naming), exit 1, where #357 makes a crashed template CANNOT ANSWER), and a directory whose name is not UTF-8 getsnaming FINDING Atl?as: UnicodeEncodeError: ..., the script's traceback quoted as a fact about the name #410's rule is that the naming script is always this checkout's, so "nothing here is a statement about the project" (naming_crashed_row). A refusal of the checkout's own policy file is the same fact.docs/release-notes/v1.0.0.md:523lists this as a known limit. - Separately, the module docstring's EXIT CODES list never names an unfinished merge for exit 1. Its exit-1 line reads: "the shape is behind, a copy has drifted, a validator is red, a leg is off its pin, a manifest is there and does not load, or a tracked path sits in a leg ...". Yet the
mergerow (shape-doctor.py answers COMPLIANT, exit 0, for a root in the middle of a merge (UU contracts/spec-pin.yaml,UU spec, a MERGE_HEAD,git commitrefusing), because no row asks git for unmerged paths andrecorded_gitlinkanswers an unmerged gitlink from HEAD, so a root an agent cannot commit is reported compliant, including after thegit checkout --oursthat a conflicted pin's NEXT names #424, shape-doctor.py: a root whose index holds an unmerged path gets amergeFINDING naming the paths, withgit -C <root> statusas its NEXT, and the verdictINVALID (merge), exit 1, on a rung above every other but CANNOT ANSWER, so a mergegit commitrefuses no longer reads COMPLIANT, exit 0, oncecheckout --ourstakes the markers out, or DRIFTED about a leg that never moved (#424) #468) makesINVALID (merge), exit 1, as the paragraph above the list says.
Where it is (d4a7fab):
shape-doctor.py:279-289: the EXIT CODES list.:120-130: the merge paragraph.shape-doctor.py:2050-2092:check_naming, with its reason at :2090-2092.shape-doctor.py:2095-2124:naming_crashed_row.shape-doctor.py:7742-7788:check_not_a_root_naming.scripts/repo_shape.py:1806-1817:NamingPolicy.load. The doctor's ownrepo_shapeimport already carries it.
The change:
- Before running the naming script, ask whether this checkout's
contracts/repository-naming.yamlloads, withrepo_shape.NamingPolicy.load, the reader the script itself uses. Where it does not load, or where the script'sREFUSEDnames that file:- mark the row
detail.environmentand quote the refusal; - say, in
naming_crashed_row's words, that the file is this checkout's and not the project's, so nothing here is a statement about the project; - a project root is then CANNOT ANSWER, exit 3, and a directory that is not a root stays NOT A SHAPE ROOT.
- mark the row
- Word any other exit 2 as "refuses (exit 2)", and an exit 1 as the finding it is.
- In the docstring's EXIT CODES list, add the unfinished merge (
INVALID (merge)) to the exit-1 line, and this checkout's own naming policy to the exit-3 line.
Tests (tests/test_doctor_validator_verdicts.py, beside test_a_crashed_naming_script_cannot_answer_for_a_compliant_project, using standard_under):
- A copy of the standard whose policy has a tab line, over a compliant project: the row is a FINDING with
detail.environment, the verdict isCANNOT ANSWER (naming: ...), exit 3, and the reason names the file as this checkout's. - The same copy over a directory that is not a root: NOT A SHAPE ROOT, exit 2, and the row says the same.
- Control: a project whose leg name does not classify is still
INVALID (naming), exit 1.
From #460, #460 (L3) and #460 (comment) (L9).
🤖 Generated with Claude Code
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
brettheap commentedon Oct 16, 2026
CLAIMED — lane openRepoShape-3, session b30e8b49-f249-4668-adb1-1dbfa93c09e1@Eagle, 2026-10-16T13:01:36Z, for #678
Logged in
lanes/log/openRepoShape-3.mdata1aab39f1adef954a2b039e175e6d9baa09bd545.The three reads (lane-collision-protocol Rule 1):
shape-doctor.py: the `naming` policy row's `why` says "not to this di…
shape-doctor.py: a checkout whose own `contracts/repository-naming.ya…
Merge origin/main (66b230e) into l3-683-partial-clone
README.md, the handbook and the v1.1.0 notes: the doctor's exit 3 nam…
family.py: `add`'s refusal of a member's own gitlink held only under …