Skip to content

wip init refuses an adopted checkout ahead of origin's main by anything but its own seed, before a byte is written (#64) - #139

Merged
brettheap merged 4 commits into
mainfrom
fix/wip-init-refuses-unreviewed-history-ahead-of-main
Oct 3, 2026
Merged

brettheap merged 4 commits into
mainfrom
fix/wip-init-refuses-unreviewed-history-ahead-of-main

Conversation

@brettheap

@brettheap brettheap commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Builds #64 as Brett Heap ruled it on 2026-10-02, verbatim: "go with option 1 on #64".

What step 6a now refuses

Step 6a already refused an ADOPTED checkout whose worktree or index carries anything the template does not name. It never looked at history, and step 8 pushes HEAD:main wherever HEAD is not what origin's main already carries. So a clean adopted checkout with a person's own unpushed commits (a register edit made here and never pushed, a note committed on the wrong clone) had every one of them published to the main of their workspace repository. The command that published them came only to place a template.

Step 6a now asks the remote before step 7 writes a byte, lists git rev-list <origin main>..HEAD, and refuses with exit 2 unless every commit in that range is this command's own seed. Where the remote has no main yet, the range is all of HEAD. The refusal:

  • names every commit in the range with git log --oneline, indented like the other refusals, and says which main it compared against (<target>'s main (abc1234), or (it has none yet));
  • says that this command ends by pushing HEAD to that main, so it would publish them unreviewed;
  • says that NOTHING was written into the checkout on this run and nothing was staged;
  • gives the remedy: push those commits yourself, or discard them, then re-run openRepoTools wip init.

What it exempts, and why

This command's own seed. If the PR-only ruleset rejects the first run's push, that run leaves a clean worktree and exactly one commit ahead of main: the seed. Step 8's refusal promises that "a re-run after that has only to push". wip_is_own_seed recognises a seed by all of what makes step 8's commit its own:

  1. one parent or none. Step 8 never merges, and diff-tree names no path for a merge unless asked for a combined diff, so without this check a merge would pass the tree test by naming nothing;
  2. a subject starting Seed this workspace repository from ;
  3. a body carrying Written by `openRepoTools wip init` ;
  4. a tree that differs from its parent's (the empty tree, for a root commit, via --root) at one or more template paths and at no other. Step 8 commits only template paths by pathspec, and never makes an empty commit.

Every read that fails counts as "not a seed". The seed's bytes are not compared with the template: that run may have pinned a different template commit, and the ruling names the subject, the trailer and the tree. The comment block says so.

The shared remote read

git ls-remote origin main is asked once, at step 6a. Step 8 reads the same remote_head, so the range checked and the push decided are one reading of main. Step 8's own ls-remote is gone, and its local_head != remote_head gate is unchanged. Two changes come with moving the read:

  • The line read is refs/heads/main by name, not NR==1. A pattern of main matches every ref whose name ends in it, and refs/heads/backup/main sorts first. Step 8 used to read that branch's tip as main, and would then say that main "already carries this commit" without pushing to it. With the new gate the same misreading would have let the branch's commits through. Pinned by a test.
  • "Could not ask" is kept as the ruling keeps it. The check is skipped, one line on stdout says so, and the run goes on to the push, which is still the probe. remote_asked is kept separate from remote_head so that an unanswered question is never read as "no main yet", which would put every commit ahead and refuse the seed re-run. The comment names the remaining window: a remote that refuses the question but accepts the push a moment later.

Two refusals and one flag that come with the gate

  • A range that cannot be listed is refused, never read as empty (wip init step 6a's git-status safety gate masks a failure as clean (|| :) #49's lesson, applied to history). The usual cause is a main this checkout has never fetched. Before this change, that case wrote the template, committed, and then died at a non-fast-forward push with the ruleset message. Now the refusal names the fetch, includes git's own words, and nothing has been written.
  • --no-show-signature on every git log the recognizer runs. log.showSignature prints the signature report on stdout, ahead of --format. On a machine with commit.gpgSign set, the command's own signed seed would read back with No signature / Good "git" signature … as its first line and be refused. Measured with an SSH-signed commit; pinned by a test.

Left unchanged: step 1's idempotence (the pointer-file test), the seed commit's message, and the push itself.

How it was tested

New tests in tests/test_wip_init_command.py:

  • test_an_adopted_checkout_ahead_of_main_by_a_persons_commit_is_refused: clean by the old gate, one commit of the person's own ahead. Checks exit 2, the commit's sha and subject in stderr, no template byte written, nothing staged, nothing pushed, no pointer file.
  • test_a_seed_a_refused_push_left_on_an_adopted_main_is_pushed_by_the_rerun: the ruleset is switched on for an existing repository, and the first run leaves one seed on top of a non-empty main. Once the ruleset is lifted, the re-run recognises the seed, pushes it and exits 0. The existing test_the_rerun_after_the_administrator_acts_has_only_to_push now asserts the same for a root seed.
  • test_a_remote_that_cannot_be_asked_skips_the_history_check_for_the_probe: origin points at a path where nothing answers, with a person's commit ahead. The check is skipped with its line, and the run reaches step 8's ruleset refusal, not 6a's.
  • test_a_commit_wearing_the_seeds_message_is_not_taken_for_the_seed[non-template-path|no-trailer|merge|empty]: the tree test has teeth, and so does each other part.
  • test_an_empty_main_with_a_persons_local_commit_is_refused
  • test_a_main_this_checkout_never_fetched_is_refused_not_read_as_nothing_ahead
  • test_a_branch_whose_name_ends_in_main_is_not_read_as_main
  • test_a_signed_seed_is_still_known_where_log_shows_signatures (skipped without ssh-keygen or git ≥ 2.34)

Local runs used tests/run.sh scoped to the wip-init and hygiene modules. On the branch: 220 passed, 40 skipped, 0 failed. Against main's openRepoTools, all 12 targeted tests fail. With --no-show-signature removed, the signed-seed test fails. Details are in this comment.

CI

Copilot round 1 (b5e80d5) reported no findings, with "Approval recommended". It did not fire on the later pushes, and re-requesting it was a no-op.

Filed while building this: #140. Step 8 reads every refused push as the PR-only ruleset, so a checkout that is merely behind main is sent to an administrator. This predates the PR, and step 8's push is outside it.

README and its cap

One sentence in the wip init seed paragraph: a checkout ahead of that repository's main by anything but an earlier run's unpushed seed is refused, and it names the commits. That adds two lines, so the hygiene cap moves 472 → 474, with a dated 2026-10-02 entry naming #64. #103 raises the same cap to 484 and is expected to land first; the lane owner reconciles the cap after it lands (per the cap's own rule, the cap counts what merged).

Closes #64

Lane: openRepoTools-1

🤖 Generated with Claude Code

Summary by Sourcery

Refuse to initialize adopted checkouts with unpushed history that would be published to main, while safely permitting and validating earlier seed reruns.

New Features:

  • Prevent wip init from adopting clean checkouts with unpushed commits that would be published to the workspace repository’s main, while allowing previously created seed commits to be pushed on rerun.
  • Share a single, exact remote main lookup between the history safety check and the final push decision, including correct handling of missing or unreachable remote branches.

Bug Fixes:

  • Avoid misidentifying similarly named remote branches as main and avoid treating failures to enumerate commit history as an empty range.
  • Ensure seed recognition remains reliable for root, signed, malformed, merge, and empty commits.

Enhancements:

  • Add clear pre-write refusal messages that identify affected commits, explain the publication risk, preserve checkout state, and provide remediation guidance.

Documentation:

  • Document the new history-based adoption refusal in the wip init README guidance.

Tests:

  • Add comprehensive coverage for unpushed local history, seed reruns, unavailable or empty remotes, unfetched remote history, branch-name matching, seed recognition, and signed commits.

Chores:

  • Update the README hygiene line-count cap and its corresponding enforcement test.

…n` by any commit but its own seed, before a byte is written, and step 6a and step 8 read origin's `main` once between them (#64)

Brett Heap ruled on 2026-10-02, verbatim "go with option 1 on #64". Step 6a
asked about the worktree and the index and never about history, so a clean
adopted checkout holding a person's own unpushed commits had them pushed to
the `main` of their workspace repository by step 8's `push origin HEAD:main`.
Step 6a now asks `git ls-remote origin main` before step 7 writes anything,
lists `<origin main>..HEAD` (all of HEAD where the remote has no `main`), and
refuses with exit 2, naming every commit in that range, unless each one is this
command's own seed. A seed is recognised by its subject, its `Written by` line,
one parent or none, and a tree that differs from its parent's only at template
paths, with at least one changed. The exemption keeps step 8's promise that a
re-run after a ruleset-rejected push only has to push.

The remote is asked once, and step 8 reads that same answer, so the range
checked and the push decided are one reading of `main`. The line it reads is
`refs/heads/main` by name. The first line of a `main` pattern can belong to a
branch such as `backup/main`. Where the remote cannot be asked, the check is
skipped with one line saying so and the push stays the probe, as the ruling
keeps it. A range that cannot be listed, usually because `main` has moved and
this checkout has not fetched it, is a refusal and never counts as an empty
range. The recognizer passes `--no-show-signature` because `log.showSignature`
writes the signature report on stdout ahead of the subject.

Tests cover a person's commit ahead, a seed left by a refused push on an adopted
`main`, a remote that cannot be asked, a commit that copies the seed's message
(four ways), an empty `main`, a `main` this checkout has not fetched, a
`backup/main` branch, and a signed seed. The README's seed paragraph gains one
sentence, and its cap moves 472 -> 474 with a dated entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 3, 2026 00:10

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 21 hours and 20 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduces a shared, exact remote-main history check before wip init writes anything, preventing accidental publication of user commits while allowing only valid prior seed commits to be re-pushed; the change also hardens seed recognition and adds extensive regression coverage and documentation.

Sequence diagram for wip init remote-main history check

sequenceDiagram
    participant W as wip init
    participant R as origin
    participant G as Git history
    participant T as Checkout

    W->>R: git ls-remote origin refs/heads/main
    alt remote main is available
        W->>G: git rev-list remote_head..HEAD
        G-->>W: commits ahead of main
        W->>G: git log --no-show-signature --oneline
        W->>G: wip_is_own_seed(commit)
        alt any commit is not an own seed
            W-->>T: Refuse before writing
        else all commits are valid seeds
            W->>T: Write template and create seed
            W->>R: Push HEAD:main using remote_head
        end
    else remote cannot be asked
        W-->>W: Skip history check
        W->>T: Write template and create seed
        W->>R: Push HEAD:main as probe
    end
Loading

Flow diagram for wip init history safety gate

flowchart TD
    A["wip init"] --> B["Step 1: pointer-file idempotence check"]
    B -->|already initialized| Z["Exit without network call"]
    B -->|adopted checkout| C["Existing worktree and index checks"]
    C --> D["git ls-remote origin refs/heads/main"]
    D -->|remote cannot be asked| E["Skip history check; continue to push probe"]
    D -->|remote main available| F["git rev-list remote_head..HEAD"]
    F -->|cannot list range| R["Refuse: nothing written or staged"]
    F -->|user commits in range| R
    F -->|only valid prior seed commits| G["Write template and create seed if needed"]
    E --> G
    G --> H["Push HEAD:main using shared remote_head"]
    H -->|ruleset refusal| I["Leave clean unpushed seed for rerun"]
    H -->|success| J["Complete"]
Loading

File-Level Changes

Change Details Files
Adds a pre-write history safety gate for adopted checkouts so wip init cannot publish unpushed user commits to the workspace repository's main branch.
  • Reads origin's exact refs/heads/main once during step 6a and shares that result with the push decision.
  • Lists the remote-main-to-HEAD range and refuses unless every ahead commit is the command's recognized seed.
  • Handles a missing remote main by treating all of HEAD as ahead, while distinguishing an unanswered remote query from no main.
  • Refuses safely when the range cannot be listed, preserving git diagnostics and suggesting a fetch.
  • Reports the compared main, every offending commit, publication risk, and the no-write/no-stage guarantee with remediation guidance.
openRepoTools
README.md
Defines strict recognition rules for an earlier wip init seed and hardens the history inspection against repository and user configuration edge cases.
  • Recognizes only single-parent or root commits with the expected subject, trailer, and template-only non-empty tree change.
  • Uses the empty tree for root-seed comparison and rejects merges, empty commits, missing trailers, and commits touching non-template paths.
  • Suppresses commit signature reports during log parsing so signed seeds remain recognizable.
  • Preserves the existing push behavior and the distinction between skipped remote probing and an empty main.
openRepoTools
Adds comprehensive regression coverage for history refusals, seed re-runs, remote-query behavior, ref selection, and signature handling.
  • Verifies user commits are refused before template bytes, index changes, pointer creation, or pushes occur.
  • Covers adopted and root seeds left by a rejected push, including successful administrator-enabled re-runs.
  • Covers missing main, an unfetched main, an unreachable remote, and a branch whose name merely ends in main.
  • Tests each seed-recognition invariant and signed-seed compatibility.
tests/test_wip_init_command.py
Documents the new refusal behavior and updates the README hygiene line budget.
  • Explains that adopted checkouts ahead of main by anything other than an unpushed seed must be pushed or discarded by the user.
  • Raises the enforced README cap from 472 to 474 with a dated rationale for the two added lines.
README.md
tests/test_repo_hygiene.py

Assessment against linked issues

Issue Objective Addressed Explanation
#64 Prevent wip init from publishing unreviewed commits already present in an adopted checkout's local HEAD, by checking its history relative to the remote main before writing or staging anything. ✅
#64 Allow an adopted checkout to be rerun when its only commits ahead of main are an earlier wip init seed, while rejecting unrelated, malformed, merge, empty, or otherwise unrecognized commits. ✅
#64 Document the new adopted-checkout history safety behavior and provide coverage for remote-read failures, missing or stale main, exact ref selection, and preservation of the no-write guarantee. ✅

Possibly linked issues


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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The safety gate matches the stated requirements and is thoroughly covered by focused tests.

Review effort: Balanced
Findings: None

What changed in this PR

Prevents wip init from publishing unreviewed local commits when adopting an existing workspace checkout.

Changes:

  • Validates commits ahead of remote main, allowing only recognized seed commits.
  • Reuses an exact remote-main lookup for validation and pushing.
  • Adds documentation and comprehensive regression coverage.
File Description
openRepoTools Adds the pre-write history gate and seed recognizer.
tests/​test_wip_init_command.py Covers refusal, recovery, remote, signature, and seed edge cases.
README.md Documents the new refusal behavior.
tests/​test_repo_hygiene.py Adjusts the documented README line budget.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

…this run and nothing was staged." on one line, as every other step 6a refusal does

Rewrapping the refusal to shorten its lines split that sentence between
"NOTHING was" and "written". Every test of the history gate asserts the
sentence's own words, so seven of them failed on CI's Linux job at b5e80d5
("7 failed, 697 passed"), all on that one assertion. The sentence is now a
line of its own, so a person reading the refusal, or a test of it, finds it
whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 3, 2026 00:33
@brettheap

Copy link
Copy Markdown
Contributor Author

Local verification on Eagle. Every run went through tests/run.sh (the workstation lock).

After: this branch @ 73bba01. Scoped to the wip-init and hygiene modules (every other module passed with --ignore=): 220 passed, 40 skipped, 0 failed, exit 0.

Before: the same tests, openRepoTools from main @ cbb5981. I ran a scratch copy of this branch with only openRepoTools replaced, so the new tests were run against the old command. All 12 targeted tests fail:

test before (main)
…ahead_of_main_by_a_persons_commit_is_refused assert 0 == 2: exit 0, the commit published
…wearing_the_seeds_message…[non-template-path / no-trailer / merge / empty] assert 0 == 2 in all four
…empty_main_with_a_persons_local_commit_is_refused assert 0 == 2
…branch_whose_name_ends_in_main_is_not_read_as_main assert 0 == 2: NR==1 read backup/main as main
…main_this_checkout_never_fetched… got step 8's "THAT IS THE RULESET" after writing the template, not the pre-write refusal
…remote_that_cannot_be_asked… the skip line is absent
…refused_push_left_on_an_adopted_main…, …administrator_acts_has_only_to_push, …signed_seed… pushed as before; they fail only on the new "one seed an earlier run committed…" line. These three pin the exemption, so they guard against over-refusal and pass on both behaviours apart from that line

Without --no-show-signature. In a scratch copy of this branch with the flag removed from the recognizer, test_a_signed_seed_is_still_known_where_log_shows_signatures fails assert 2 == 0. The command refuses its own SSH-signed seed (427c863 Seed this workspace repository from …) as "not every one of them is this command's own seed".

CI on b5e80d5. It failed 7 tests on one assertion: my rewrap had split "NOTHING was / written". 73bba01 fixes that.

Filed rather than fixed here: #140. Step 8 reads every refused push as the PR-only ruleset, so a checkout that is merely behind main is sent to an administrator. This predates the PR. It was reproduced on main and on this branch.

brettheap and others added 2 commits October 3, 2026 01:33
…Copilot capped at two rounds, CI the suite of record) into the #64 branch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cap carries both dated entries, 472 -> 484 for #57 and 484 -> 486 for #64

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@brettheap brettheap added the ready landing gate: runs tests-macos once before the squash label Oct 3, 2026
@sonarqubecloud

sonarqubecloud Bot commented Oct 3, 2026

Copy link
Copy Markdown

@brettheap

Copy link
Copy Markdown
Contributor Author

Landing note from lane openRepoTools-1 (2026-10-03). CI on c587c4f (this branch + main a44a4ed): tests (Linux, the suite of record by #119 ruling 3), tests-no-submodule, tests-windows, parse-macos, guard-launch-mode and SonarCloud pass. The ready gate's tests-macos fails 21 cases, every one in the lane picker and liveness sections of tests/test_lane_helpers.sh; 14 are red on main's own last macOS run and the other 7 are the same family. This PR touches wip init, its tests, the README and the README cap only — no lane helper and no line of that suite — so it cannot have introduced them. Filed as a follow-up per #119 ruling (1)(d) rather than blocking the landing. Copilot: one round, no findings (ruling 2's cap unused).

@brettheap
brettheap merged commit 795016e into main Oct 3, 2026
12 of 14 checks passed
brettheap added a commit that referenced this pull request Oct 3, 2026
…e-listing

#139 (wip init refuses an adopted checkout ahead of origin's main) landed
after #83. It touches `openRepoTools`, its own tests, README.md and a
different docstring of tests/test_repo_hygiene.py than this branch does;
the merge is clean and nothing of it is resolved by hand.

Lane: openRepoTools-3
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
brettheap added a commit that referenced this pull request Oct 3, 2026
Bring in #119, #103, #83, #139 and #93 so #61 lands last in the queue
on the main it will actually land on. One textual conflict:

- lanes-edit.sh, the `*)` arm's unknown-subcommand list: main added
  `binding`, `request-handoff`, `register-row-local`, `retired-identity`
  (#83) and `retire-rows`, `archive-rows` (#93); this branch added
  `duplicate-holder`. Every name is kept, in main's order with
  `duplicate-holder` after `forks` as before, and the list still equals
  the dispatcher's arms exactly (test_repo_hygiene's derived check).

Checked against #61's code, nothing else needed a change: the suite's
fake-command block (tmux, claude, pgrep, ps, gh) is intact and no new
main code calls pgrep or ps; #93's columns 14-17 and #83's column 13
are in the `lanes` listing rows, which #61 never reads; LOG_AWK's
fields, live_holder's, transcript_holders' and lane_forks' output
formats are unchanged; #83's HANDOFF-REQUESTED is a lane-kind verb that
changes no state and holder_is_dead's five-verb whitelist skips it as
every last-line reader must; and lane-end's --retire-dormant sweep is
refused beside --retire and exits before the fork/duplicate retire path.

Lane: openRepoTools-3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brettheap
brettheap deleted the fix/wip-init-refuses-unreviewed-history-ahead-of-main branch October 3, 2026 18:49
brettheap added a commit that referenced this pull request Oct 4, 2026
Bring #97 onto a current base before the seam rework Brett Heap ruled on
2026-10-04 ("managed ledger owns enrolled lanes; #97 owns legacy — rework
both"). Main moved 14 commits past 957a26f, to daed209: #81 lane-rename,
#83 Amendment 18, #93 Amendment 19, #61 claim --force takeover, #146,
#119, #101-#103, #129, #131, #133, #135, #136, #139 and #134.

Four files conflicted, and in every one both intents survive:

- lanes-edit.sh, the function sections: both sides appended after
  migrate_state_cells. Main's Amendment 19(c)/(d) sweep and archive stay
  directly under it, because its header says "the shape
  `migrate-state-cells` has one screen up"; #97's lifecycle and
  inventory section follows them.
- lanes-edit.sh, the unknown-subcommand refusal: the union of both lists,
  56 names, the same set as the dispatcher's 56 arms.
- lanes-edit.sh, the exit-code table, and the manual's copy of it: #97's
  7 row ("another act got there first", in three verbs) is kept, and exit
  9 now has two meanings, one per verb. #61 spent 9 on `claim --force`'s
  abandoned takeover and #97 spent it on `lane-state`'s unreadable
  snapshot, and each PR took it as unused. Neither verb can return the
  other's 9, so the table names both and nothing is renumbered in a
  merge. The manual's 9 row said "(`claim` only)", which the merge would
  have made false; its 7 row now names #97's two fenced writers too, as
  the code table already did. The next commit moves #97's 9 to 10.
- lane-handoff, the late-record restart line: #129's
  `$lane_profile_word` (lclaude) with #97's lifecycle line under it.
- docs/README-lanes.md: Amendment 19's section, then #97's #91 section,
  so the amendment sections stay in number order.
- tests/test_lane_helpers.sh: main's Amendment 19 and Amendment 18
  sections run first, in main's order (A18's restores its fixtures), and
  #97's self-contained #91 section follows them, before the
  workstation-seam section, as it did on #97's branch.

lane-start auto-merged around #134's rewrite. #97's section 4a still
prints the reconciliation after Amendment 18's binding gate and before
section 5 and the STARTED/RESUMED write in 5b. AGENTS.md, README.md,
tests/test_repo_hygiene.py and skills/ are byte-identical to main, so
the 316- and 486-line caps already match the merged counts.

Locally, tests/run.sh -k 'lane_helpers_suite or repo_hygiene or
lane_start_claude_current or guard_launch_mode or install_skill_and_hook':
274 passed, 600 deselected, in 1560 s.

Lane: openRepoTools-3
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

ready landing gate: runs tests-macos once before the squash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wip init pushes an adopted checkout's local HEAD verbatim, unreviewed, even when this run wrote nothing

2 participants