Skip to content

README.md, adopt-project.py and the handbook: a kept directory entry makefile/ is tested, README says make at the root reads a kept GNUmakefile or makefile instead, and a docstring says the shape's Makefile alone holds CONTRACTS_DIR (#1061) - #1123

Merged
brettheap merged 4 commits into
mainfrom
fix/1061-makefile-follow-ups
Nov 8, 2026

Conversation

@brettheap

@brettheap brettheap commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

The three follow-ups of #1046 (#977), which lane 1's review of that pull request (r1046) left for later as its NIT-C, NIT-D and NIT-E. None is a regression. Each is a test, a sentence or a docstring: adopt-project.py changes only in a docstring.

(a) Mutant R10: a kept directory entry makefile/ is tested. Dropping the rstrip("/") in twins, in _makefile_follow_up, left every test passing. With a kept makefile/, _root_keeps finds Makefile by its directory form, so folded is True. Without the rstrip, twins is empty and twins[0] raises in plan. The code is right; only the test was missing. ANSWERED in tests/test_adopt_make_reads_first.py gains a ("makefile/", "root") row, id makefile-directory, which expects the line a kept makefile file gets. GNU make 4.3 stops on a directory with makefile: Is a directory. (r1046's measure), so the case is contrived, and the comment above ANSWERED says so.

(b) README says that make at the root reads a kept GNUmakefile or makefile instead. Section "Adopting an existing repository":

  • Before: "...shape/Makefile, which holds the export until a person merges the two."
  • After: "...shape/Makefile, which holds the export until a person merges the two; make at the root reads a kept GNUmakefile or makefile instead."

README.md is at its cap, 1482 lines (1422 + the 60 in tests/readme-cap.d/), so the paragraph is tightened and stays at 12 lines, and README.md stays at 1482. Three phrasings are shorter. No fact is lost; the word "honest" is:

  • "the plan says so up front" for "the plan says so instead of letting it be discovered later";
  • a colon for "because" before the assistant-stubs clause;
  • "The tool names the edit and does not make it; making it silently would be the dangerous half." for "The tool does not make the edit — naming it is the honest half, making it silently would be the dangerous one."

The handbook's adopt section says nothing of CONTRACTS_DIR, as in #1046, so only its marker moves, to the section's new blob (a7154cc3, from readme_fingerprint over readme_segments). SENTENCE in the test follows the new text.

(c) The docstring of contracts_from_code_leg. It said "CONTRACTS_DIR is the root Makefile's alone", which predates #977. It now says the shape's Makefile's alone: the root's Makefile, or, where the source keeps a Makefile of its own, shape/Makefile.

Measured

Mutants of twins in _makefile_follow_up, each in a scratch git clone --shared of this head, restored by sha256 (e3f38a53...79f5c before and after each):

Mutant Test file on main Test file on this head
both rstrip("/") dropped (R10) 32 passed, 1 failed: README's sentence, which this head's README no longer matches, and nothing to do with the mutant 1 failed, 33 passed: [makefile-directory], IndexError: list index out of range
rstrip("/") dropped from the filter only not run 1 failed, 33 passed: the same IndexError
rstrip("/") dropped from the element only not run 1 failed, 33 passed: the line names makefile/ where it names makefile

So R10 survived the 32 rows on main and the new row kills it, and both halves of it.

Tests

  • tests/test_adopt_make_reads_first.py: 33 tests on main, 34 here.
  • Gate on the merge of this head with main at 6da757cb, named files only, one basetemp, a stub gh first on PATH, GH_TOKEN=bogus, GIT_SSH_COMMAND=false, GIT_CONFIG_GLOBAL=/dev/null:
    • test_adopt_make_reads_first, test_adopt_contracts_dir, test_adopt_printed_sentences: 122 passed (34, 34, 54).
    • test_repo_hygiene, test_readme_sections, test_readme_windows_quoting_sentence, test_family_docs_one_spelling, test_setup_by_hand_commands, test_update_add_codes_documented, test_doctor_plan_overrides, test_agents_md_codes, test_cli_reference, test_pinned_copy_text, test_scaffold_leg_path_collisions: 584 passed.
    • test_shape_doctor.py in 4 shards: 445 passed, 3 skipped (the PowerShell line, Windows only).

Merge with main

main moved to 6da757cb while this was made, and was merged here as 3d1c37a6. It touched adopt-project.py elsewhere, and neither README.md nor docs/handbook.html, so the cap and the re-wrap hold. Since then main has moved to 823624d9, and its #1101 added 7 README lines and tests/readme-cap.d/915.txt. r1123's independent review measured the merge with 823624d9 (tree a317e482):

  • README.md is 1489 lines, exactly at its cap of 1489.
  • The adopt handbook marker is unchanged, at a7154cc3.
  • The tests passed: 210 + 70 + 104; the doctor 445 passed and 3 skipped; groups A (122) and B (584).

Not in this PR

#1048 covers the same gap in collision_follow_up, AGENTS-shape.md and the NOTE in adopt-project.py. adopt_makefile_block's docstring in scripts/shape_materialize.py says the block is appended "to the assembly root's Makefile", the same older claim, and is left to it. It is filed as #1135, since #1048 and its PR #1105 do not hold it.

Closes #1061

Lane: openreposhape-1 (openRepoShape-1)

🤖 Generated with Claude Code

Summary by Sourcery

Clarify makefile ownership and root-level make behavior while covering retained makefile directory entries in adoption tests.

Enhancements:

  • Clarify which root-level makefiles are read when adopting an existing repository and which Makefile owns CONTRACTS_DIR.
  • Add coverage for a retained makefile/ directory entry to protect makefile discovery behavior.

Documentation:

  • Update the README and handbook reference marker to document root make behavior.

Tests:

  • Extend adoption tests to cover retained makefile directories and keep the documented README sentence synchronized.

Brett Heap and others added 3 commits October 21, 2026 10:58
…`("makefile/", "root")` row, so a kept directory entry `makefile/` is tested, for #1061's box (a); boxes (b) and (c) are not made yet

The row expects the line a kept `makefile` file gets. Run against the scratch
copy's `adopt-project.py`, the row fails on `twins[0]` raising IndexError when
`rstrip("/")` is dropped from `twins`' filter (mutant R10), and on the line
naming `makefile/` when dropped from its element. Not yet shown cleanly: the
scratch copy had no `.git`, so the end-to-end tests there failed for that
reason too; the mutant runs must be redone in a scratch copy that is a git
repository, restored by sha256.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… at the root reads a kept `GNUmakefile` or `makefile` instead, and the read-across docstring says `CONTRACTS_DIR` is the shape's Makefile's alone, the root's `Makefile` or `shape/Makefile`, no longer the root Makefile's (#1061)

Boxes (b) and (c) of #1061, on top of box (a) (the `makefile/` row).

(b) README.md, "Adopting an existing repository": the sentence that says
where the export lives now ends "; `make` at the root reads a kept
`GNUmakefile` or `makefile` instead." README is at its cap (1482), so the
paragraph is tightened to stay at 12 lines: "up front" for "instead of letting
it be discovered later", a colon for "because", and one sentence made
shorter without losing either half. The handbook's `adopt` section says
nothing of `CONTRACTS_DIR`, so only its marker moves, to the section's new
blob. `SENTENCE` in tests/test_adopt_make_reads_first.py follows.

(c) adopt-project.py, `contracts_from_code_leg`'s docstring: "`CONTRACTS_DIR`
is the root Makefile's alone" predates #977. It now says the shape's
Makefile's alone, the root's `Makefile` or, where the source keeps a
`Makefile` of its own, `shape/Makefile`.

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

sourcery-ai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Implementation

Update the contracts read-across docstring to describe CONTRACTS_DIR as belonging to the shape’s Makefile, which may be the root Makefile or shape/Makefile.

  • adopt-project.py L3721-3724

Documentation

Clarify that root-level make reads a kept GNUmakefile or makefile, and refresh the handbook’s README section fingerprint.

  • README.md L816-827
  • docs/handbook.html L1290

Tests

Add coverage for a kept makefile/ directory and update the README sentence expectation and test commentary for the clarified Makefile behavior.

  • tests/test_adopt_make_reads_first.py L132-139, L183-186 (+4 small edits)

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

@brettheap

Copy link
Copy Markdown
Contributor Author

(lane openRepoShape-1, 2026-10-21T15:35:44Z) r1123, lane 1's independent reviewer (not the writer), reviewed #1123 at 5c3908f8: READY on condition, a complete review. Lane 1 has now met the condition in the body. No MUST. The merge with main 823624d9 is green: README is 1489 lines at a cap of 1489, and the handbook marker is unchanged. The README sentence is true, measured with /usr/bin/make. The new row is the only one that kills R10. Lane 1 met S1 and S2 in the body: adopt_makefile_block's docstring is now filed as #1135, because #1048 and #1105 do not hold it, and the merge section names 823624d9. NIT-1 is softened in the body. NIT-2 and NIT-3 are left. The review follows in full.


r1123: review of PR #1123 (Closes #1061)

Verdict: READY on condition. Every check in the brief is finished, so this report is complete. It is not marked PARTIAL even though the checkpoint asked for an early send. The merged tree is green, the README sentence is true when measured with /usr/bin/make, and the new row kills R10 and both of its halves. The condition is the two SHOULDs below: one is a hand-off nobody holds, the other is a body section that has gone stale. Neither needs a code change.

Scratch mutants are restored. sha256 after restore: head clone adopt-project.py e3f38a53…79f5c, base clone 933d072e…d5bc4c. Both clones and the merged clone show a clean git status. My worktree is at 5c3908f8 and clean.

Merge with current main 823624d9

  • git merge-tree --write-tree 5c3908f8 823624d9 is clean and gives tree a317e482. I built it in the scratch clone /workspace/projects/openRepoShape-worktrees/_lane1-scratch/r1123/merged. Checking it out took a local commit-tree (4ebbcf10), which was never pushed.
  • README cap: README.md is 1489 lines. The test prints the cap is 1422 + 2 (460.txt) + 5 (550.txt) + 12 (563.txt) + 22 (564.txt) + 10 (606.txt) + 1 (683.txt) + 2 (711.txt) + 2 (785.txt) + 1 (786.txt) + 7 (915.txt) + 3 (921.txt) = 1489. It sits exactly at the cap, and the test passes.
  • Handbook marker: I recomputed readme_fingerprint of the § Adopting segment on the merged tree and got a7154cc3186677058edf16e13594e83d5907f6c5. It is the only adopt marker in docs/handbook.html, and it matches.
  • Results:
Files Result
test_repo_hygiene (100), test_readme_sections (76), test_adopt_make_reads_first (34) 210 passed
test_cli_reference (23), test_agents_md_codes (47) 70 passed
test_scaffold_leg_path_collisions 104 passed
test_shape_doctor, 4 shards of 112 112, 112, 112, then 109 passed with 3 skipped (PowerShell, Windows only) = 445 passed, 3 skipped
Writer's group A on the merged tree 122 passed (34, 34, 54)
Writer's 11-file group B on the merged tree 584 passed

Is the README sentence true? Yes.

I ran real adoptions with the test helper adopt_with_legs_mounted_away, then /usr/bin/make (GNU Make 4.3) at the root of each clone:

Kept at the root make which make contracts-dir -f <shape's> contracts-dir
none no which rule (only the shape's Makefile) exit 0, …/Northwind/legs/spec/contracts exit 0
makefile makefile exit 2, No rule to make target 'contracts-dir' exit 0
GNUmakefile GNUmakefile exit 2, No rule exit 0
Makefile Makefile exit 2, No rule shape/Makefile, exit 0
Makefile + makefile makefile exit 2, No rule shape/Makefile, exit 0
Makefile + GNUmakefile GNUmakefile exit 2, No rule shape/Makefile, exit 0
makefile + GNUmakefile GNUmakefile exit 2, No rule exit 0

A minimal probe with a directory named makefile/ gives make: *** makefile: Is a directory. Stop., which matches the body's quote.

The three trims, sentence by sentence (old against new):

  1. "says so instead of letting it be discovered later" became "says so up front". Same meaning.
  2. The sentence on plan, follow_ups: and CONTRACTS_DIR is unchanged up to "merges the two". The new clause is appended there.
  3. "does not make the edit — naming it is the honest half, making it silently would be the dangerous one" became "names the edit and does not make it; making it silently would be the dangerous half". Both facts are kept; the word "honest" is lost (NIT-1).
  4. "because" became a colon. Same meaning.

The paragraph stays at 12 lines (README.md:809-820 at 5c3908f8). No other file quotes the old phrases (git grep finds none), and the handbook's adopt section paraphrases none of them.

The docstring (c) is true

execute passes append={"Makefile": adopt_makefile_block(...)} (adopt-project.py:14868). The block is added to the shape's Makefile wherever place writes it: at the root, or at shape/Makefile when path.exists() (scripts/shape_materialize.py:4645-4676). Nothing else exports CONTRACTS_DIR. One small gap is NIT-2.

Findings

MUST: none.

SHOULD

NIT

  • NIT-1: README.md:817-818. The body says "none with a meaning lost", but the word "honest" is gone. Either soften the body's claim or leave the text as it is.
  • NIT-2: adopt-project.py:3634-3636, and the older README.md:814-816 clause. Both leave out the disk that ignores case: there a kept makefile (or MAKEFILE, or the directory makefile/) is the Makefile path, and place writes the shape's copy to shape/Makefile. The follow-up line itself says so. Optional fix: "(on a disk that ignores case, any name that folds to it)".
  • NIT-3: tests/test_adopt_make_reads_first.py:145-147 and :183-186.
    • The row pins a line that is not true for a directory: "GNU make at the root reads the source's makefile … until the two are merged". In fact make stops with "Is a directory".
    • The comment at :134-139 records that the case is contrived, so the row works as a crash guard.
    • Optional: the docstring's "as the one GNU make reads" could read "as the one the line says GNU make reads".

Body-claim table

Claim Measured Verdict
Closes #1061 is the only closing keyword closingIssuesReferences = [1061]; Sourcery's "Bug Fixes:" heading names no issue true
R10 left every test passing on main base: 121 passed (33 + 34 + 54) both unmutated and under R10 true
folded is True for makefile/; without rstrip, twins[0] raises head R10 gives IndexError: list index out of range at adopt-project.py:3766 true
GNU make 4.3: makefile: Is a directory. probe output above true
README before/after quotes; 12 lines; 1482 = 1422 + 60 head: 1482 lines, 10 cap files; the paragraph diff is 12/12 true at head (S2 for the current main)
Marker becomes a7154cc3… recomputed true
Docstring (c) quote matches the diff true (NIT-2)
Mutant table: R10 / filter / element each 1 failed, 33 passed same results; element mutant names `makefile/` true
sha256 e3f38a53…79f5c before and after each same true
33 tests on main, 34 here collected 33 (base) and 34 true
122 passed (34, 34, 54); 584 passed; 445 passed, 3 skipped the same numbers on the 823624d9 merge true
Main at 6da757cb touched neither README nor handbook was true; main has moved since stale (S2)
adopt_makefile_block docstring left to #1048 #1048 and #1105 do not hold it not held (S1)
Sonnet trailer present on both commits; correct, not flagged —

Mutants: 7 of 8 killed on head

Unfinished checks

None. All five checks in the brief were run.

Files

Everything is in /workspace/projects/openRepoShape-worktrees/_lane1-scratch/r1123/:

  • runpt.sh, bin/gh (the stub) and ghcfg/
  • merged/, head/ and base/ (the scratch clones)
  • mut/ (the mutants and batch.log)
  • doctor-shards.log
  • probes/ (the minimal probe, and probe_adopt_make.py with its adopt-150041/ output)

No GitHub write, commit to any branch, push, rm or git config was made.

Lane: openreposhape-1 (openRepoShape-1)

This was referenced Oct 21, 2026
@brettheap brettheap added this to the v1.2.1 milestone Oct 23, 2026
brettheap added a commit that referenced this pull request Nov 8, 2026
…eeps a `GNUmakefile` or a `makefile`, which GNU make reads first, the Makefile collision follow-up no longer says the shape's make targets arrive with the merge, and the pinned file says `make` reads the first of the three and the block reaches it only once that file holds it or includes a Makefile that does (#1048) (#1105)

Two sentences said a kept `Makefile` is what holds the shape's block back. GNU make reads the first of `GNUmakefile`, `makefile` and `Makefile` it finds, and only that one, so where the root also keeps `GNUmakefile` or `makefile`, `make` reads that file, and reaches the merged `Makefile` only where that file includes it.

**Measured** (a real `execute`, then `make -n` in the clone, for each kept name; r1046's NIT-B, repeated; the include rows are RV1105's SHOULD-1):

| the source keeps | file `make` reads | after `cat shape/Makefile >> Makefile`, `make -n bootstrap` |
|---|---|---|
| `Makefile` | `Makefile` | exit 0 |
| `Makefile` + `makefile` | `makefile` | exit 2, "No rule to make target 'bootstrap'" |
| `Makefile` + `GNUmakefile` | `GNUmakefile` | exit 2, same |
| all three | `GNUmakefile` | exit 2, same |
| `Makefile` + a `makefile` or `GNUmakefile` that ends in `include Makefile` | that file | exit 0, runs `python3 scripts/bootstrap.py` (exit 2 before the merge) |
| `makefile` or `GNUmakefile` alone | that file | no merge to make: the shape's `Makefile` is the root's, and `make contracts-dir` has no rule until that file holds the block or includes `Makefile` |

**What changed**
- `scripts/shape_materialize.py`, `collision_follow_up`: takes `reads_first`, the file GNU make reads before the shape's `Makefile`. Where it is set, the Makefile's follow-up says GNU make reads that file, the first of the three it finds, and that the shape's make targets reach `make` there only once that file has them, or includes a Makefile that does; until then `python3 scripts/bootstrap.py` is what the shape's `make bootstrap` runs. Where `scripts/bootstrap.py` went aside too, it says neither command runs the shape's bootstrap until the script is merged, and then `python3 scripts/bootstrap.py` runs it. Where the root keeps only the source's `Makefile`, the sentence is what it was, byte for byte. `GNU_MAKE_READS` joins `SHAPE_MAKE_TARGETS`.
- `adopt-project.py`, `_predict_collisions`: reads the file from the plan's root paths as `_makefile_follow_up` does, so the `CONTRACTS_DIR` line and the collision line of one plan name the same file.
- `templates/assembly-root/AGENTS-shape.md`: says `make contracts-dir` prints the block wherever `make` reads the shape's Makefile, names the three files in the order the code reads them, and says that where a `GNUmakefile` or `makefile` is kept, beside a `Makefile` or instead of one, `make` reads it, and not the shape's Makefile unless that file includes it. It is one verbatim copy: the digest in every project's `contracts/shape-pin.yaml` is rendered from its bytes at adopt and scaffold time, and no digest or `tree_sha256` of it is stored in this repository, so there is no pin to move here; each project re-pins through `update-shape.py` as for any template change.
- `tests/test_pinned_copy_text.py`: `ADOPTED_SENTENCES` holds the new text.
- `tests/test_adopt_collision_make_reads.py` (new, 31 rows): the follow-up per kept set, the two lines of one plan naming one file, no collision line where no `Makefile` is kept, the two name tuples equal, the pinned file naming every file the code reads first, the script-aside tail where `make` reads another file, and, in a real adoption's clone, `make -n` held to both sentences for each kept name and for a kept `GNUmakefile` or `makefile` that ends in `include Makefile`.

**Fix round 1** (RV1105's review, `b28f40de0` on top of `5a4de7f76`)
- **SHOULD-1:** the follow-up said the targets reach `make` "only once `X` holds them, or includes a Makefile that does, and not with that merge alone". The last clause is untrue where `X` already ends in `include Makefile`: the merge alone brings them. The clause is gone, and the docstring paragraph, the `SHAPE_MAKE_TARGETS` comment and the `ADOPTED_SENTENCES` comment now say the merge alone brings the targets only where that file includes `Makefile`.
- **NIT-1 (and RV1121's NIT-3):** the follow-up now uses the words of #1121's NOTE: "has them", and "is what the shape's `make bootstrap` runs". `_next_steps` is not touched.
- **NIT-2:** the script-aside tail, where `reads_first` is set, said "neither `make bootstrap` nor `python3 scripts/bootstrap.py` runs the shape's bootstrap before both merges are made", which reads as if `make bootstrap` runs it after them. It now says neither runs it until the script is merged, and then `python3 scripts/bootstrap.py` runs it. I did not keep "before both merges": where `X` is given the targets itself, as the sentence before invites, `make bootstrap` runs the shape's bootstrap once the script is merged, with no `Makefile` merge at all.
- **NIT-3:** the template's "and never the shape's Makefile" is now ", and not the shape's Makefile unless that file includes it". `ADOPTED_SENTENCES` changes with it. No other copy or regex in `tests/` pins that sentence (`git grep` for "never the shape" and "reads the first of them").
- **NIT-4:** the `collision_follow_up` docstring no longer says `execute` reports through it. It says `plan` predicts the follow-ups and stores them in `follow_ups:`, the split commit carries those, `execute` names its collisions by path only (its `beside` lines and the "WRITTEN BESIDE" list), and `Materialized.follow_ups()` has no caller. The method stays.
- NITs 5 to 8 are left to the lane.

**Rows of this round:** `tests/test_adopt_collision_make_reads.py` and `tests/test_pinned_copy_text.py`, 118 rows. With this round's test files on `5a4de7f76`'s code, 17 fail and 101 pass; on `b28f40de0` all 118 pass. The 17 fail for the right reason:

| rows | why they fail on `5a4de7f76` |
|---|---|
| 4 collision rows (`Makefile+makefile`, `Makefile+GNUmakefile`, all three, `Makefile+GNUmakefile+scripts`) | the line holds "not with that merge alone" |
| 2 new script-tail rows (`GNUmakefile`, `makefile`) | the line holds "before both merges are made" |
| 2 new include rows in a real clone (`GNUmakefile`, `makefile`) | `make -n bootstrap` exits 2 before the merge and 0 after it alone (both asserted first, and passing), then the split message holds "not with that merge alone" |
| 7 clone rows, the pinned-file row and `test_a_scaffolded_root_is_told_its_makefile_exports_none` | the pinned file still says "and never the shape's Makefile" |

**Mutants of this round**, each run against the 118 rows on `b28f40de0`, each file restored and its sha256 checked:

| id | mutant | rows failing | result |
|---|---|---|---|
| MA | ", and not with that merge alone" put back | 6 | killed |
| MB | the script-aside tail put back ("before both merges are made") | 3 | killed |
| MC | the template's "and never the shape's Makefile" put back | 9 | killed |
| MD1 | include rows: `not in message` inverted to `in message` | 2 | killed |
| MD2 | include rows: after the merge, `returncode == 0` inverted | 2 | killed |
| ME | "holds them" put back | 6 | killed |
| MF | "the shape's `bootstrap` target runs" put back | 5 | killed |

**Gate** on `b28f40de0`:

| files | passed | failed | skipped |
|---|---|---|---|
| `test_adopt_collision_make_reads`, `test_pinned_copy_text`, `test_adopt_make_reads_first`, `test_adopt_contracts_dir`, `test_adopt_printed_sentences`, `test_adopt_e2e`, `test_repo_hygiene`, `test_scaffold_leg_path_collisions` | 470 | 0 | 0 |
| `test_shape_doctor`, 8 shards (62 + 56 + 54 + 56 + 60 + 57 + 58 + 45 collected) | 445 | 0 | 3 (PowerShell rows, Windows host only) |
| **total** | **915** | **0** | **3** |

**Merge-tree:** `b28f40de0` against main `4ed7c7bf5` is clean, and so is it against each open PR that touches these files: #1104, #1106, #1118, #1119, #1120, #1121 (`1c5173758`), #1122, #1123 and #1125.

**Round 0** (`5a4de7f76`, main `6da757cbe` merged in): on main's code (plus the constant alone), 12 of the then 27 rows failed and 15 passed; the 30 test files that run the changed code or read the template gave 2109 passed, 0 failed and 4 skipped (3 PowerShell rows in `test_shape_doctor.py`, 1 MedxEHR row in `test_adopt_plan.py` that needs a clone `SHAPE_MEDXEHR_CLONE` names); nine mutants each failed 1 to 11 of the then 114 rows.

**Not here**
- The third box of #1048, the `_next_steps` NOTE in `adopt-project.py`, is covered by the change #1047 makes to it: see #1047 and #1121.
- `templates/assembly-root/AGENTS-shape.md` line 19 and the five-commands table say `make bootstrap` without this caveat. They say nothing about a kept file, so they are outside #1048's two sentences.

Closes #1048

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

sonarqubecloud Bot commented Nov 8, 2026

Copy link
Copy Markdown

@brettheap
brettheap marked this pull request as ready for review November 8, 2026 17:46
@sourcery-ai

sourcery-ai Bot commented Nov 8, 2026

Copy link
Copy Markdown

Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 6 days and 1 hour by commenting @sourcery-ai review. Upgrade to get a review now.

@brettheap
brettheap merged commit 9729315 into main Nov 8, 2026
5 checks passed
@brettheap
brettheap deleted the fix/1061-makefile-follow-ups branch November 8, 2026 17:47
brettheap pushed a commit that referenced this pull request Nov 8, 2026
main = 9729315, #1123's squash (#1061)
on top of #1118's squash 9ec0dc7.

Lane: openreposhape-1 (openRepoShape-1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap pushed a commit that referenced this pull request Nov 8, 2026
…`makefile-directory` row in `tests/test_adopt_make_reads_first.py` expects the line that says GNU make stops at a kept `makefile/`, and still guards `twins`

Lane 1's #1123 (#1061) landed after this branch merged main 46fe6ac, and
the merge with it is clean by text. By meaning it is not: #1123 adds a row,
`test_a_name_only_a_disk_that_ignores_case_takes_for_makefile[makefile-directory]`,
that expects the `CONTRACTS_DIR` line a kept `makefile` FILE gets for a kept
`makefile/` DIRECTORY ("only once `makefile` does"). #1123's own message says
that line is not true for a directory, since GNU make 4.3 stops there with
`makefile: Is a directory.`, and that the row works as a crash guard for
`twins` in `_makefile_follow_up`. This branch changes exactly that line
(#1132, RV1121's NIT-1): a kept directory is one GNU make stops at. On the
predicted merge the row was the one failure in 254 rows.

The row now expects `SHAPES + written_as("makefile")`, as #1123 wrote it,
which is what guards `twins`, followed by this branch's directory clause,
through a new `stops_at` helper beside `reads`. The comment above `ANSWERED`
and the row's docstring say so. Nothing else changes, and #1118's merge
(9ec0dc7, also in this main) is clean by text and by its rows.

Lane: openreposhape-5 (openRepoShape-5)
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

Labels

None yet

Projects

None yet

1 participant