Create the Branches Before the Standup Writes Permanent History - #614
Conversation
STANDUP.md tells an agent to verify signing before the first commit, and to hand the maintainer prerequisites over before step 1, then goes straight to classification. Nothing in it says how `main` and `develop` come into being, so an agent commits onto whichever branch `git init` produced and writes the exploratory standup into the repository's permanent history. ## What section 0B says Create `main` empty, create `develop` from it, create the first feature branch from `develop`, run the whole standup there through the audit, add the repository and apply the configuration while still on that branch, and open a normal pull request into `develop` at the end. Carrying nothing means exactly one signed empty root commit, since a git branch cannot exist without a commit, and section 0's signing window applies to it like any other. ## Why the cleanup is unavailable afterwards Committing onto `develop` and squashing later is rejected, because `non_fast_forward` is set on both `develop` payloads and that squash is the rewrite the rule blocks. The protection is uneven. `repo-config/develop.json` carries a `pull_request` rule that blocks a direct commit outright, while `repo-config/operational/develop.json` carries `deletion`, `non_fast_forward` and `required_signatures`, and none of them stops one. A conformant operational repository therefore accepts the commit this step exists to prevent, and reports nothing wrong afterwards. On a public repository the squash is the one chance to leave a wrong secret value, a throwaway credential and a run of noise commits out of what gets published. ## Scope STANDUP.md is hub machinery and deliberately not carried, per `spec/section-model.md`, so this owes no re-vendor. #490 covered the human-gated half and is closed, which left this half. TODO.md drops the shipped cluster per its own selection procedure, and the issue-490 link definition it was the only user of. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds explicit guidance to STANDUP.md for creating main/develop before any standup work is committed, so exploratory onboarding work lands only via a feature branch PR, and removes the now-shipped backlog cluster from TODO.md.
Changes:
- Add
STANDUP.mdsection 0B describing the branch bootstrap sequence (emptymain, emptydevelop, standup on a feature branch, then PR intodevelop). - Document why post-hoc cleanup (commit-on-
developthen squash) fails undernon_fast_forward, and why operational repos are especially vulnerable. - Remove the shipped “Branch Bootstrap in the Standup” cluster and its unused issue link definition from
TODO.md.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| STANDUP.md | Adds section 0B documenting when/how to create main/develop and why the sequence matters for irreversible history. |
| TODO.md | Removes the shipped backlog cluster and the now-unused issue-490 link definition. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The sequence was prose only, so the ordering it exists to fix was left to inference, which is the review finding. Section 0 and step 4 both carry command blocks for the same reason. Adds the four local commands, and two ordering facts they do not carry on their own: section 0 checks fall between init and the empty root commit, and the two branches are pushed before step 4 applies the rulesets, since repo-config/main.json carries a pull_request rule and no bypass actors, so an applied ruleset blocks the push that seeds the branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:66
- The command block uses
git switch --create, but the repository does not document a minimum Git version andgit switchis only available in relatively recent Git releases. Usinggit checkout -bhere (or explicitly stating the Git version requirement) would make the standup instructions more broadly copy/paste compatible.
git init --initial-branch main # Rather than relying on the host's init.defaultBranch.
git commit --allow-empty --message "Initial commit" # The one signed empty root commit.
git branch develop # From main, so the two start level.
git switch --create "<feature-branch>" develop # Every step below runs here.
The suppressed round-2 finding named git switch, which arrived in 2.23. The binding constraint was git init --initial-branch at 2.28, so swapping only switch would have lowered nothing. Every command in the block now predates both, and docs/host-setup.md checks that git is present while stating no floor, so the block asks for nothing that file guarantees. The unconditional rename replaces the initial-branch flag and is correct on either host default, verified in a scratch repository through the feature checkout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering the round 2 suppressed finding here, since a suppressed comment has no thread to resolve.
Accepted, and the premise checks out: One correction to the diagnosis, which changes the fix. Fixed in d5c00d6 by removing both, so the block asks for nothing git init # The host default may be master, which the rename below corrects.
git commit --allow-empty --message "Initial commit" # The one signed empty root commit.
git branch --move --force main # Idempotent, so it is correct on either default.
git branch develop # From main, so the two start level.
git checkout -b "<feature-branch>" develop # Every step below runs here.The unconditional |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (2)
STANDUP.md:52
- This sentence claims nothing reaches
main/developwithout review, but section 0B immediately instructs creating (and later pushing) an empty root commit on those branches. Reword to clarify that the standup work stays off long-lived branches until a PR, rather than implying absolutely no direct commits ever land there.
**Create both long-lived branches empty and do the whole standup on a feature branch off `develop`.** An agent that starts committing onto whichever branch `git init` produced is writing the repo's permanent history, and every step below is exploratory work that has no business being permanent. Doing this first means nothing ever has to be cleaned off `main` or `develop`, because nothing reaches either without review.
STANDUP.md:60
- The text says "four commands", but the fenced block contains five commands (
git init, empty commit, branch rename, create develop, create feature branch). This mismatch makes the procedure harder to follow and audit.
The three local steps are four commands, run before the repository exists on GitHub:
Two round-3 findings, both correct. The opening claimed nothing reaches main or develop without review, four lines above an instruction to put an empty root commit on both and push them. It now says the only commit either carries is the empty one it starts from, which is the claim the rest of the section actually supports. The command count said four and the block had grown to five, because the previous commit added the rename and left the count behind it. The count is gone rather than corrected, since a number restating what the block shows has to be swept every time the block changes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering both round 3 suppressed findings here, since a suppressed comment has no thread to resolve. Both are accepted, and both are fixed in 4adc9dd.
Correct, and the contradiction sat four lines above the instruction that falsifies it. The opening now reads that the only commit either branch carries is the empty one it starts from, and that every change after it arrives by pull request, which is the claim the rest of the section supports rather than a wider one it does not. Worth recording that the wording came in verbatim from the backlog entry this pull request ships, so the imprecision was carried rather than introduced here. The entry is deleted by this same change, so there is nothing left to correct in it.
Correct, and mine: d5c00d6 added the rename to the block and left the count in the sentence above it. The count is removed rather than corrected, which is the durable half of the fix. A number restating what the block already shows has to be swept every time the block changes, and this is the first change that could have got it wrong doing so. The line now reads that steps 1 through 3 are the block below. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:68
- The command block for steps 1-3 omits the
git config --local --get user.email || truecheck that section 0 requires to run aftergit initand before the first commit (and the paragraph below this block explicitly says it belongs between the first and second lines). Including it in the block makes the copy/paste sequence mechanically correct and consistent with the earlier step ordering.
git init # The host default may be master, which the rename below corrects.
git commit --allow-empty --message "Initial commit" # The one signed empty root commit.
git branch --move --force main # Idempotent, so it is correct on either default.
git branch develop # From main, so the two start level.
git checkout -b "<feature-branch>" develop # Every step below runs here.
</details>
The round-4 finding is that the block presented itself as the copy-paste sequence while the paragraph under it said a check belonged between two of its lines. A reader following the block alone skipped it, and a reader following the prose had to interpolate it. The check is now the second line, and the prose says how section 0 reads it rather than where it goes, since an unset key prints nothing and exits non-zero, which is the passing case and not the failing one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering the round 4 suppressed finding here, since a suppressed comment has no thread to resolve. Accepted, fixed in 9c138f7.
Correct, and the two halves disagreed in a way that hurt either reader. Someone following the block alone skipped the check, and someone following the prose had to interpolate a line into a block that presented itself as complete. The check is now the second line of the block. The paragraph under it no longer says where the check goes, and says instead how section 0 reads it, because that is the part a reader still needs and the part the placement cannot convey: an unset key prints nothing and exits non-zero, so the passing case is empty output over a non-zero exit, and reading the exit status as failure inverts the check. That is section 0's own rule, applied here rather than restated. The three earlier suppressed findings this round re-listed were answered above, on the rounds that raised them. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:66
- The inline comment says this rename is "Idempotent", but with
--forceit can overwrite an existingmainbranch if someone runs the block in a non-empty repo. Since this procedure is for a freshgit init, it would be clearer (and more accurate) to state that assumption instead of claiming general idempotence.
git branch --move --force main # Idempotent, so it is correct on either default.
The round-5 finding is that the comment claimed idempotence while the line carries --force, which overwrites an existing main in a repository that already has one. The claim was true only under the block's own assumption, and the comment stated none. The comment now says what the line does and where, and the prose says what makes the force safe, a repository holding one branch and one commit, so the rename has nothing to collide with. It also says what the same line does in a repository that already carries main, since that is the case the word idempotent was quietly excluding. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering the round 5 suppressed finding here, since a suppressed comment has no thread to resolve. Accepted, fixed in 4f08872.
Correct. The word was accurate only inside the assumption the comment did not state, which is the shape worth fixing rather than the word. What I verified before writing it, and what it was hiding: the rename is safe here because the repository holds one branch and one commit, so So the comment now says what the line does and where, the prose says what bounds the force, and it names the repair case explicitly as the one this block is not for. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:68
- The step 0B command block creates the empty root commit but does not include section 0's required post-commit verification (
git log -1 --format=...). Because that verification appears earlier in the document (before the 0B commands that create the commit), it is easy to miss or run out of order. Including the verification command directly in this block keeps the sequence linear and makes it harder to skip the signing/identity check for the empty root commit.
git init # The host default may be master, which the rename below corrects.
git config --local --get user.email || true # Section 0's check, whose passing case is no output.
git commit --allow-empty --message "Initial commit" # The one signed empty root commit.
git branch --move --force main # Renames whichever branch git init produced, in a repo holding only it.
git branch develop # From main, so the two start level.
The round-6 finding is the pair of the round-4 one. The block created the empty root commit and left section 0's post-commit verification behind, so a reader running the block linearly created the commit the signing window exists for and never verified it. The verification is now the fourth line, copied from section 0 rather than paraphrased, so the two cannot drift into two different commands. The prose under the block stops naming a position for either check and says how each is read instead, which is the half the placement cannot carry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:60
- Section 0 already instructs running a
git config --local --get user.emailcheck aftergit init, and section 0B now includes a fullgit initblock as well. As written, a reader following section 0 literally may rungit initto satisfy the earlier check, then reach 0B and rungit initagain, which is confusing and makes the intended "one init" flow unclear. Consider clarifying here that thegit initin the block is the one section 0 expects, so there is no separate init step before 0B.
Steps 1 through 3 are the block below, run before the repository exists on GitHub:
The round-9 finding is that section 0 refers to git init twice as something already done, while 0B now carries the command itself, so a reader following both literally inits twice. The lead-in now says the block holds the only one, and how section 0 reads against it: the --global checks run ahead of the block and the two repository-scoped checks sit inside it. Section 0 is left alone. Its two references are correct as written once the reader knows which init they name, and rewording a section this change does not otherwise touch would carry into every downstream copy for a clarification that belongs here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering the round 9 suppressed finding here, since a suppressed comment has no thread to resolve. Accepted, fixed in c567ac6.
Correct, and this is the last of the seam the previous three rounds opened. Moving section 0's checks into the block was right, and it left section 0 referring to an init that now happens later in the document than the text describing it. The lead-in now says the block carries the procedure's only Section 0 itself is left alone deliberately. Its two references are correct once a reader knows which init they name, and rewording a section this change does not otherwise touch would land in every downstream copy of a carried file for a clarification that belongs to the new section. If a later change reworks section 0 for its own reasons, that is the moment to fold this in. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:72
- Line 64 in the shell block includes
|| true, so the command's actual exit status is always 0. The surrounding prose says the passing case is a non-zero exit with empty output, which is true of the underlyinggit config --getbut not of the full command as written, and can confuse readers who check$?while following the procedure.
The rename runs unconditionally rather than behind a test of `init.defaultBranch`, because forcing it is correct whether the host produced `master` or `main` and a conditional is one more thing to get wrong. What makes the force safe is where the block runs, in a repository holding one branch and one commit, so it is a rename with nothing to collide with rather than a general-purpose one. In a repository that already carries a `main` the same line overwrites that branch, which is why this block belongs to a fresh `git init` and never to a repair. Every command here predates `git switch` and `git init --initial-branch`, so the block needs no minimum version, which matters because [`docs/host-setup.md`][host-setup] checks that `git` is present and states no floor. The placeholder is quoted for the reason step 4 gives, that an unquoted `<` is input redirection. Both of section 0's checks sit in the block rather than beside it, placed where that section requires them rather than left to a reader to interpolate, and each is read as section 0 reads it. On the second line the finding is the printed value, so a non-zero exit over empty output is the passing case. On the fourth the passing result is `G` beside the noreply address in the author and the committer both, which reads the empty root commit as the first commit the signing window covers rather than as an exception to it. Push `main` and `develop` once the repository exists and **before** step 4 applies the rulesets, since [`repo-config/main.json`][repo-config-main] carries a `pull_request` rule, so an applied ruleset blocks the direct push that would otherwise seed the branch. Ordering it this way rather than relying on a bypass is deliberate, because who may bypass a ruleset is a human decision no payload declares, and `repo-config/configure.sh` reads the live list and preserves it rather than asserting one, so an agent cannot know from the payload whether a bypass exists.
The round-10 finding is that the prose called a non-zero exit the passing case while the line it describes ends in a tolerant tail, so its actual status is always zero. Measured both: the bare git config --get exits 1 on an unset key, and the same line with the tail exits 0. Both places that said it are fixed, section 0B's summary and section 0's own rule, since the imprecision came from the second and the first inherited it. Each now says the passing result is empty output, that the exit status answers nothing, and why the tail is there. Section 0 is edited here after declining to touch it last round. The reason given then was that it would reach downstream copies, which is wrong: this file is hub machinery and carried nowhere, as the pull request body says. The scope reason still held for a wording change that was only about the new section, and does not hold for the same defect the finding names. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering the round 10 suppressed finding here, since a suppressed comment has no thread to resolve. Accepted, fixed in 83a519d.
Correct, and measured rather than reasoned about: the bare Fixed in both places that said it, section 0B's summary and section 0's own rule, since the wording originated in section 0 and the new section inherited it. Each now says the passing result is empty output, that reading Correcting my own reasoning from the previous round. I declined to touch section 0 in the round 9 answer above and gave as the reason that rewording it would land in every downstream copy of a carried file. That is wrong. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:33
- Section 0 now has its only
git initinside 0B, but this paragraph sits immediately after the repo-local override check and can be read as prompting agit initbefore 0B. Adding an explicit reference to 0B here would prevent readers from initializing (and potentially committing) too early, which would make the 0B bootstrap block unsafe to apply.
**The finding is a printed value, never the exit code.** An unset key prints nothing and makes `git config --get` exit `1`, so reading that as failure inverts the check, and the tolerant tail turns it into a zero exit in any case, which leaves empty output as the whole of the passing result. The tail is in the snippet above so a copy into a `set -e` script does not abort on the expected case.
The round-11 finding is that section 0 documents a check that runs after git init while the init itself now lives in 0B, so the paragraph reads as a prompt to init early, which is the state 0B exists to prevent. Both of section 0's check paragraphs now say where the command runs, not only the flagged one. The two are the same defect and the reviewer named the first, so fixing that one alone would leave the second to a later round. The commands stay in section 0. It is where the reader learns what each check means and how to read its result, and 0B is where they run, which is the split both paragraphs now state. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Answering the round 11 suppressed finding here, since a suppressed comment has no thread to resolve. Accepted, fixed in b5c739e.
Accepted. Section 0 documents a check that happens after Fixed in both of section 0's check paragraphs rather than the one flagged. The The commands stay in section 0, since that is where a reader learns what each check means and how to read its result. 0B is where they run. Both paragraphs now state that split rather than implying a step of their own. On the shape of this loop, recorded because it is measurable rather than as a complaint. Rounds 4, 6, 9, 10 and 11 were each caused by the previous fix, which is one section's content moving and the text around it not moving with it. Every one of them was a real defect at the moment it was raised. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:25
- Subject/verb agreement: "The agent check branches" should be "The agent checks branches".
The agent check branches rather than listing both forms, because they are alternatives and running the wrong one fails on a correctly configured host: an SSH host need not have `gpg` installed at all. Signing is **SSH or GPG**, so judge the format and its agent together rather than requiring `ssh`: what matters is that the configured format has a matching agent holding the key, which is the check [GOVERNANCE.md "Git and Commit Rules"][governance-git-and-commit-rules] prescribes. Any of these wrong or absent is a **host** misconfiguration to surface to the maintainer ([`docs/host-setup.md`][host-setup] is the setup procedure), not something to patch per repo. Patching it locally hides a broken host that then produces wrong identities in every other repo on that machine.
|
Answering the round 12 suppressed finding here, since a suppressed comment has no thread to resolve. Declined, with the reading that makes the sentence correct as it stands.
The subject is the noun phrase "the agent check", meaning the check for the signing agent, and "branches" is its verb. The sentence says that this check branches rather than listing both forms, which is exactly what the snippet it describes does: if [ "$(git config --global --get gpg.format)" = ssh ]; then ssh-add -L; else gpg --list-secret-keys; fiThe suggested reading parses "the agent" as the subject and "check" as the verb, which leaves "branches" as a plural noun and turns the sentence into a claim that an agent inspects branches. There are no branches in that paragraph. It is section 0, before any repository exists, and the sentence's own subordinate clause names what the alternatives are, the SSH and GPG forms, not refs. The line is also not this pull request's. It landed in 77be3a3 under #481 on 2026-07-31 and appears in the diff only as context beside the nearby edit in b5c739e. I am leaving it as written rather than rewording correct prose the change does not otherwise touch. If the sentence is worth making harder to misparse, that is a separate observation about a garden-path noun phrase rather than a grammar defect, and it belongs in a change that has a reason to be in section 0. |
The round-12 finding claimed a subject-verb disagreement in STANDUP.md section 0. The subject is the noun phrase "the agent check" and "branches" is its verb, describing the if/else that selects ssh-add or gpg by the configured format, so the sentence is correct as written and the finding is declined. A decline that lives only in a pull request comment is re-derived the next time the line is read, which is what the Disproved Claims record exists to prevent, so the entry goes in with the reading, the revision it was proved against, and what ends it. The sentence itself is untouched. It landed in 77be3a3 under #481 and this change reaches it only as diff context. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixes a finding Copilot raised on the promotion pull request [#615](#615), against the command block [#614](#614) added. A promotion's head is `develop`, so the fix lands here rather than there. ## The finding > The branch rename uses long options (`--move --force`), but the paragraph below explicitly says the block "needs no minimum version". Using the long options may impose a newer Git requirement than the short form, so this can undermine the compatibility claim. Prefer the traditional `-M` form here to keep the bootstrap as version-agnostic as possible. ## What the source says Checked against git's own option tables rather than taken on faith, since the claim is about when a spelling became available: | Tag | `git branch` option table | | --- | --- | | `v1.5.4` | `OPT_BIT('m', NULL, ...)`, `OPT_BIT('M', NULL, ...)`, `OPT_BOOLEAN('f', NULL, ...)` | | `v2.0.0` | `OPT_BIT('m', "move", ...)`, `OPT_BIT('M', NULL, ...)`, `OPT__FORCE(...)` | So `--move` and `--force` did not exist in 1.5.4 and did by 2.0.0, and `-M` has no long equivalent in either. The finding has the direction right. It also bounds how wrong the block was. The long forms are far older than `git switch` at 2.23 and `git init --initial-branch` at 2.28, which is what the prose named, so nothing here was going to break on a plausible host. The claim was **no floor at all** rather than a floor earlier than those two, and the long forms do carry one. ## The change The line reads `git branch -M main`, and the paragraph says the short form is deliberate rather than terse, so a later edit does not restore the long form for consistency with the rest of the block. ## Verification `prose_lint.py` both invocations plus `sentence-split`, `editorconfig-checker` exit 0, `markdownlint-cli2` 0 issues across 44 files, and `STANDUP.md` at 206 of 206 CRLF lines. The block's comment column is unchanged at 65.
…-coverage remedy (#615) Promotes `develop` to `main`, carrying five merged pull requests. ## What is being promoted - **[#617](#617 `8515666`, the branch rename written `-M` rather than `--move --force`, which git gained later, checked against git's own option tables at `v1.5.4` and `v2.0.0`. - **[#616](#616 `08cf819`, the partial-coverage status line counting the unread files rather than asserting there is one. - **[#614](#614 `f39e0c0`, the branch bootstrap step in [`STANDUP.md`](./STANDUP.md). Section 0B states the sequence that keeps the exploratory standup off `main` and `develop`, carries the procedure's only `git init` alongside both of section 0's identity checks, and records why the post-hoc cleanup is unavailable. It also carries one Disproved Claims entry and the removal of the shipped backlog cluster. - **[#613](#613 `676a2bd`, the partial-coverage remedy in `scripts/pr_review.py` and its two documentation mirrors, corrected to what the record supports after measuring 4 pull requests and 7 rounds with 0 recoveries. - **[#612](#612 `1892d6f`, a Dependabot group bump of four actions. #616 and #617 both answer findings raised by the review **on this promotion**. A promotion's head is `develop`, so neither could be fixed here, and each took its own pull request into `develop` and its own review rounds before merging. ## Review state Each of the five was reviewed and merged on its own pull request, so this promotion carries no unreviewed change. #614 ran 13 rounds, 12 findings accepted and 1 declined and recorded under Disproved Claims. #616 ran 3 rounds and #617 ran 2, all findings accepted. ## Merge shape This is a promotion, so it merges as a **merge commit** rather than a squash, per [`GOVERNANCE.md`](./GOVERNANCE.md) "Branching Model". Its head is `develop` itself, so it must **not** be merged with `--delete-branch`.
…request sweep (#619) Promotes `develop` to `main`, carrying two merged pull requests. ## What is being promoted - **[#591](#591 `07ed74a`, reading why a merge is blocked instead of reporting one word. `scripts/pr_review.py` gains the check rollup, the four stuck shapes it tells apart, and exit `44` for a review loop that closed against a check no waiting clears, plus the [`GOVERNANCE.md`](./GOVERNANCE.md) and runbook wording that says `BLOCKED` never names its own cause. - **[#618](#618 `dd5fc90`, the open pull request sweep in [`TODO.md`](./TODO.md)'s selection procedure, plus an amendment recording the upstream ask for a machine-readable Copilot review schema. ## The exit code, since it changed meaning between branches #591 was authored before the outage of 2026-08-06 and defined exit `42` for its check reading. #607, #608 and #613 took `42` for a round that read fewer files than the pull request changed, and `43` for a shape the reader does not know, while it sat. The forward-merge renumbered the check reading to **44** and ranked it under both: `43` says no field can be believed, `42` says part of the diff has no review, and only once those are clear is a wedged required check the thing worth reporting. `wait` returns the coverage and shape verdict where it has one and reads the checks only where it does not. ## Review state Both were reviewed and merged on their own pull requests, so this promotion carries no unreviewed change. #591 ran 18 rounds across its life, 5 of them after the revival, and #618 ran 5. Every finding was accepted except one on #614, which was declined with evidence and recorded under "Disproved Claims" in [`.github/copilot-instructions.md`](./.github/copilot-instructions.md). ## Why #591 was open long enough to need reviving It was parked correctly during the GitHub Actions major outage, with the reason written on the pull request, and the reason then expired quietly. Three days later it was 20 commits behind `develop`, conflicting in six regions, and carrying an exit code that meant something else. #618 is the procedural answer to that, and it is in this same promotion. ## Merge shape This is a promotion, so it merges as a **merge commit** rather than a squash, per [`GOVERNANCE.md`](./GOVERNANCE.md) "Branching Model". Its head is `develop` itself, so it must **not** be merged with `--delete-branch`.
Ships the
Branch Bootstrap in the Standupcluster fromTODO.md, selected by that file's ownHow to Select the Next Itemprocedure.The gap
STANDUP.mdsection 0 requires signing to be live before the first commit, and section 0A hands the maintainer prerequisites over before step 1. Then it goes straight to classification. Nothing in the file says howmainanddevelopcome into being, so an agent commits onto whichever branchgit initproduced, and the exploratory standup becomes the repository's permanent history.Verified on
developat676a2bd:git initappears twice, both inside section 0 about the signing window, and a search forcheckout -b,git branch,feature branch,branch fromandroot commitreturns nothing.What section 0B says
Create
mainempty, createdevelopfrom it, create the first feature branch fromdevelop, run the whole standup there through the audit in step 5, add the repository and apply the configuration while still on that branch, then open a normal pull request intodevelop.Carrying nothing means exactly one signed empty root commit, since a git branch cannot exist without a commit, and section 0's signing window applies to it like any other.
Why the cleanup is unavailable afterwards
Committing onto
developand squashing later is rejected, becausenon_fast_forwardis set on bothdeveloppayloads and that squash is the rewrite the rule blocks.The protection is uneven, which is the part worth stating in the file:
repo-config/develop.jsondeletion,non_fast_forward,required_linear_history,required_signatures,pull_request,required_status_checks,copilot_code_reviewpull_requestrepo-config/operational/develop.jsondeletion,non_fast_forward,required_signaturesSo a conformant operational repository accepts the commit this step exists to prevent, and reports nothing wrong afterwards. On a public repository the squash is the one chance to leave a wrong secret value, a throwaway credential and a run of noise commits out of what gets published.
Scope
STANDUP.mdis hub machinery and deliberately not carried, perspec/section-model.md, so this owes no re-vendor and adds nothing to the outstanding sweep. #490 covered the human-gated half and is closed, which left this half, so there is no issue to close here.TODO.mddrops the shipped cluster per step 9 of its own procedure, and theissue-490link definition it was the only user of.One departure from the cluster text, stated so it is a decision rather than an omission: the cluster names Blog as the repository that was blocked, and the section describes the case without naming it. The evidence is the mechanism, and
STANDUP.mdis read by agents standing up unrelated repositories.Verification
prose_lint.py, both CI invocations plussentence-splitby name, which is in neither. Confirmed with--list-filesthat both files were actually read, rather than passing on an empty set.editorconfig-checker, exit 0. Line endings checked independently too, since a scripted rewrite converts them silently:STANDUP.mdis 191 of 191 CRLF lines andTODO.md494 of 494.markdownlint-cli2, 0 issues across 44 files.cspellreadsREADME.mdandHISTORY.mdonly, neither of which this touches.