docs: the M15 milestone record — the field fixes, v2.0.1 and the first blog post (#321) - #322
Conversation
…t blog post (#321) docs/milestones/15-v2-0-1-what-the-fleet-migration-taught.md, synthesized from #305's trail: seven requirements, seven delivery tasks, twenty-five Decision and six Deviation records, fourteen review submissions, and one QA round in which every requirement came back satisfied. Every count is re-derived from the source and every citation resolves. The M15 row is added to ROADMAP.md, already Done. The introduction's verb summary names what M15 added to task finish and status; nothing else there or in the README was stale, because M15-R6's own flip had already moved both version claims to v2.0.1. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_017Zu94NTC5DJskcpMTSofzr
There was a problem hiding this comment.
Changes requested. The document is the best-sourced record this project has produced — I re-derived every count in its opening paragraph from the API and all but one of them came back exact — but three claims are wrong on the branch as it stands, and one of them is wrong in a way that only got worse while the PR sat open. Reviewed as the reviewer seat (radiusred-checky), a distinct App from the author (radiusred-wordy).
Finding 1 (blocking) — the record's counts are already false at merge time, and the gap it names has since been filled
Two records landed on the milestone's trail after the record's commit (889db9d, authored 02:06:04Z) and before this review:
radiusred/gh-codecrew#306comment5564002686, 02:09:01Z, operator:**Decision (operator, after the merge):** the reviewer's non-blocking round-two note on PR #315 … is declined, not merely left.radiusred/gh-codecrew#305comment5564026934, 02:11:36Z, operator:**Deviation:** the same harness failure again on the record PR #322's first round …
Both parse as records under tracker.ExtractRecords' own rule, which is the rule the record says it counts by. Six statements in docs/milestones/15-v2-0-1-what-the-fleet-migration-taught.md are now false:
- Opening paragraph: "its three comments, carrying one Deviation record, the operator's verification of the release, and one QA comment" — #305 now has four comments and two Deviation records.
- Opening paragraph: "the twenty-five Decision records and six Deviation records across the milestone issue and those task issues" — now twenty-six and seven.
- Merge-order list, the
#306 / PR #315bullet: "Four Decisions" — now five. ## Decisions, first paragraph: "twenty-two on the six task issues in this hub" — now twenty-three. And in the same paragraph: "None carries a parenthetical qualifier: every record in this milestone is a bare**Decision:**or**Deviation:**label, which is not true of M14's, where two qualified labels were invisible to a plain search."**Decision (operator, after the merge):**is precisely that qualified form, so the sentence now says the opposite of the truth about its own milestone.## Deviations, first line: "Six Deviation records: one by the operator on #305, three on #309 and one each on #310 and #311" — now seven, two on #305.## What the record does not contain, third bullet: "It is still there. The review left it explicitly to the author — 'take it or leave it, and either is defensible' — and no Decision records the leaving. A blessing and a deferral are both decisions, and this is recorded as neither." Comment5564002686is exactly that Decision: it declines the third passage, gives the reason (the**What it writes.**bullet describes what the 2.0.0 binary wrote, which is true of 2.0.0, where the two marked passages are the adopter's steps and had to change), a Trade-off: and a Rejected:. The gap this bullet is about has been closed, and the bullet is the one place in the document that would have to say so.
The standard here is the house one, not mine: M14's record opens "#269's eight comments", and #269 carries nine today — but the ninth is milestone close 14's own closing comment at 23:34:56Z, after PR #304 merged at 23:32:50Z. Nothing landed on M14's trail between synthesis and merge, so that record was true when it merged. This one would not be.
The fix is small and is the implementer's call in shape: either re-derive the six lines above against the trail as it stands and fold the operator's #306 Decision into ### A migrated spoke, and a released changelog section edited to describe it and the third What the record does not contain bullet; or keep the snapshot and say so explicitly, naming the two comments and their ids as landing after synthesis. What it cannot do is ship the counts as written. Note that the second one is a Deviation about this PR's own review round, so a record that counts it is recording its own review — the same self-reference M14's record navigated by leaving its own task's rounds out; either treatment is defensible if it is stated.
Finding 2 — capture #316's provenance runs backwards
radiusred/gh-codecrew#316 was created at 2026-09-07T00:06:27Z. PR #313's only review (5127113957) was submitted at 00:10:17Z — three minutes and fifty seconds later. Two sentences assert the reverse:
## Protocol-discipline observationsregion,### An App is not an assignee…— "The reviewer confirmed the reading in round one — '…' — and #316 is that capture." This one is fine as written: it claims confirmation, not causation.- The captures section: "#316 … comes from the implementer's third Decision on #307 and the reviewer's confirmation of it". The capture cannot come from a review that did not exist yet.
## The review rounds, the PR #313 bullet: "and a third is the reading that became capture #316" — same inversion.
The record gets the other two right and it is worth keeping them right by contrast: #318 (review round one 00:17:38Z → capture 00:18:47Z) and #319 (round two 00:33:43Z → capture 00:34:24Z) both follow their reviews. The remedy is one clause each: #316 came from the Decision on #307, and the review independently reached the same reading four minutes later.
Finding 3 — the blog post has five sections, not six
## The release, and the blog post: "in six sections that follow the adopted capture's shape: why a protocol major, what changed, what an adopter does, what deliberately did not change, and what the fleet migration taught, ending on the seven captures v2.0.1 answers."
docs/blog/posts/2026-09-07-protocol-2-0-and-the-migration.md in radiusred/codecrew-www carries five headings and no others: ## Why a protocol major, ## What changed, ## What an adopter does, ## What deliberately did not change, ## What the migration taught. The clause about the seven captures is the closing part of the fifth, not a sixth. The record's own list names five. Either "five sections" or "an unheaded opening and five sections", whichever the author meant.
What I re-derived, and what held
Every count in the opening paragraph except those in Finding 1 checks out against the API, and I ran the sources rather than reading them.
- Seven requirements, unedited.
userContentEditson #305 returnstotalCount: 0; the body carries M15-R1…R7 and the Gates section is the scaffold placeholder, verbatim as quoted. - Seven delivery tasks plus #321. #305's
subIssuestotals 8: #306–#311 CLOSED,radiusred/codecrew-www#27CLOSED, #321 OPEN. - Seven merged PRs, twenty-four commits. Per-PR commit counts from the API are 3/2/4/6/6/2 for #313/#312/#315/#314/#317/#320 and 1 for
codecrew-www#28— 24, and each matches the per-task figure in the merge-order list. Merge SHAs8f9d9e9,55a04ee,9e225d9,7610047,9c322e0,2dc147a,9931d40and every merge timestamp match to the second. - Fourteen review submissions. 1/2/2/3/3/2/1 across the seven PRs, all by
radiusred-checky[bot]: fourCHANGES_REQUESTED, ten approvals submitted, seven standing and threeDISMISSED. The three dismissal events are at 00:13:31Z, 00:31:42Z and 00:42:12Z, giving standing times of 2m13s, 2m00s and 8m29s — the record's figures exactly. Every review id it links resolves to the round it names. - Force-pushes. 0 on #313, 1 on #312, 2 on #315, 3 on #314, 3 on #317, 0 on #320 — as stated. The four CHANGELOG quotations are verbatim and attributed to the right rounds.
- Timings. #305 opened 23:51:44Z; last delivery merged 01:25:44Z — one hour thirty-four minutes to the second. First
task start(#308) 23:59:09Z. The five parallel PRs opened 00:03:50Z–00:09:02Z, 5m12s apart. #311's Deviation 00:56:23Z → the operator's Decision 00:57:29Z, one minute six seconds. - The release, read from git/releases/actions. Tag ref → tag object
fabdc17eba781a98af792e5542d730fab0285be9, messagev2.0.1 (protocol 2.0), taggerradiusred-cody[bot]at 01:08:33Z, pointing at2dc147ac7fa5539e7f1b171f72aa8d984840b2a2. Run 34072047784 (.github/workflows/release.yml) created 01:08:40Z on that SHA, conclusionsuccess. Releasegh-codecrew 2.0.1published 01:09:55Z, neither draft nor prerelease, five assets with exactly the names given. - QA cells, verbatim against comment
5563791131. All seven verdicts aresatisfiedand the table's status column carries the word unqualified. Every quotation in the notes column and in## QA: one round, seven verdictsis verbatim: "Main build/test/vet/gofmt are clean", "highest issue comment count is #119 with 69", "the paging tests drive 101 comments and 150-row listings so dropping--paginatetruncates", "backlog captures #316, #318 and #319 remain open and outside the adopted set", "apart from recorded #306 correction notes", "refusesCLOSEDand printsdry run: nothing written", the R7 sentence aboutcodecrew-www#29. - Captures. All eight adopted (#287, #264, #301, #296, #297, #295, #303,
codecrew-www#26) are closed and carry exactly two comments each. All four filed-and-open (#316, #318, #319,codecrew-www#29) are open and were filed by the operator. All seven adopted hub/spoke captures were created 2026-09-06 between 11:24:17Z and 22:30:41Z, with #301 and #303 after v2.0.0 published at 18:47:47Z. - Gates. Neither repository has an issue labelled
cc:needs-decision(0 and 0). All seven delivery-task Ask-the-human sections resolve to none, and the six quoted fragments are verbatim; PR #312's and PR #315's bodies each say "No deviations from the plan". - Documented commands, executed.
gh codecrew milestone evidence 15built from this branch prints, byte for byte, the two lines the record quotes:requirements counted: M15-R1, … (7)andall 20 cited links resolve across 9 issues — evidence is reachable.milestone close 15 --dry-runreproduces the quoted gate block, differing only in#321 (in review)where the record shows(ready)— the same before-the-PR capture M10–M14's records all carry, so not a finding. - Links. All 112 links in the document resolve: 90 github.com URLs fetched through the API,
https://codecrew.worksand the live post 200, and all 21 relative links into the sibling records exist with their heading anchors present. - Claims about the code. SPEC §10's table still has 43 rows.
--paginateis onComments,SubIssues,listIssuesandOpenPRsForBranch; the two deliberate single-page reads each carry the comment the record describes, andTestMilestoneIssuesPaginateAndRecentIssuesDoesNotis the test holding one of them there.
Record and mechanics
- Plan before the first commit. #321's body was edited with the plan at 01:48:08Z by
radiusred-wordy; the sole commit is authored 02:06:04Z. - Decisions as comments, not only in the body. Three on #321 (
5563874552,5563874676,5563874789) at 01:49:38–40Z, matching the three the PR body claims. - Closing references.
closingIssuesReferenceslists #321 alone. The body's only close-family word is the leadingCloses #321, so capture #303's defect and the stricter dispatch rule are both satisfied. - Commit. One, conventional, lowercase after the type, 87 characters, referencing
(#321), authored asradiusred-wordy[bot]. - CHANGELOG.
### The M15 recordat the top of the fresh## [Unreleased], ending(#321). - ROADMAP. The M15 row is appended after M14's, already Done, and its document link matches the file added.
docs/introduction.md. The refresh is contract-mandated, not optional — the doc-synthesizer contract requires the introduction's verb claims to be true at every milestone boundary, and the old sentence enumerated three thingstask finishdoes where SPEC §6 now has four and said nothing aboutstatus's holder line or its stale-branch report. Both new clauses read true against SPEC §6'sstatusandtask finishrows.README.mduntouched, with the reasoning recorded.- Boundary check on a docs-only change.
gofmt -l .clean,go vet ./...clean,go test ./...all green.
One nit, not a finding
"the sharpest statement of what a dry run is for in this codebase" (### A migrated spoke…) is a superlative reaching past the milestone with nothing cited behind it, where every other comparative in the document links the record it compares against. Scoping it to this milestone, as its neighbours are, would keep the document's own rule intact. Take it or leave it.
Findings 2 and 3 are one clause each. Finding 1 is the one that has to be answered before this merges: the record's whole claim on a reader is that its counts are re-derivable from the trail, and two of them stopped being so at 02:09:01Z.
Two records landed on the milestone between this record's first commit and its review — the operator's Decision on #306 at 02:09:01Z and a second Deviation on #305 at 02:11:36Z — so every count they touch is re-derived as of 2026-09-07T02:26:50Z and the record names that instant; the trail is frozen from there, this document's own task included. Also from the review: capture #316's provenance no longer runs ahead of the review that confirmed it, the blog post is five sections and an unheaded opening, and the dry-run superlative is scoped to this milestone. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_017Zu94NTC5DJskcpMTSofzr
|
Round one answered at Finding 1 — re-derived at 2026-09-07T02:26:50Z, against a trail the coordination layer has frozen. The two records the review names are both folded in, and a third is mine: a Finding 2 — #316's provenance no longer runs backwards. The captures paragraph now says the capture was "filed at 00:06:27Z from the seat's own report and four minutes before the review that independently reached the same reading", and the PR #313 bullet says the review's third finding "reaches the same reading as capture #316, which the operator had already filed four minutes earlier from the implementer's own report". The observation sentence claimed confirmation rather than causation and is unchanged. Finding 3 — five sections. Now "an unheaded opening and five sections", and the fifth is named as the one ending on the seven captures. Nit — taken. "the sharpest statement of what a dry run is for in this codebase" is now "this milestone's clearest statement of what a dry run is for", scoped like its neighbours. One thing I added beyond the findings. The Re-verified at the new head. |
There was a problem hiding this comment.
Approved. Round two. Every count round one listed is now exact against the API as of the commit under review, the three other findings are answered, and gh codecrew milestone evidence 15 passes from this branch. Reviewed as the reviewer seat (radiusred-checky), a distinct App from the author (radiusred-wordy).
Finding 1 (blocking, round one) — resolved: the counts are re-derivable
I re-derived every figure round one named by replaying tracker.ExtractRecords' own rule (^\*\*(Decision|Deviation|Gate resolved)(\s*\(…\))?:\*\* at a paragraph start, on NormalizeLineEndings'd bodies) over the paginated comments of all nine M15 issues. The trail is unchanged since round one except the one **Deviation:** on #321 at 02:26:40Z, and nothing on any M15 issue is later than that — so the record's "counted at 2026-09-07T02:26:50Z, against a trail that is frozen from there" is true as of this review.
Per issue: #305 0/2, #306 5/0, #307 3/0, #308 3/0, #309 4/3, #310 4/1, #311 4/1, #321 3/1, codecrew-www#27 3/0 (Decisions/Deviations). Totals 29 Decisions, 8 Deviations; excluding #321, 26 and 7. Each of the six broken statements now checks out:
- Opening paragraph — "its four comments, carrying two Deviation records, the operator's verification of the release, and one QA comment holding all seven verdicts": #305 returns exactly four comments — the two
**Deviation:**records at 00:46:06Z and 02:11:36Z, the operator record for M15-R6 at 01:21:41Z, andradiusred-testy[bot]'s comment at 01:36:41Z carrying M15-R1…R7 allsatisfied. - Opening paragraph — "twenty-nine Decision records and eight Deviation records … of which twenty-six and seven are on the milestone issue and the seven delivery tasks": exact, both figures.
- Merge-order list,
#306 / PR #315— "Five Decisions, the fifth the operator's and recorded after the merge": five, and5564002686is at 02:09:01Z against PR #315's merge at 00:29:53Z. ## Decisions— "twenty-three on the six task issues in this hub, three on the spoke's task, and three on this document's own — the milestone issue itself carries none": 5+3+3+4+4+4 = 23, 3, 3, 0. "Two of the twenty-nine are the operator's":davisonwrote exactly two Decisions (5564002686on #306,5563544774on #311); the other twenty-seven splitradiusred-cody[bot]21 /radiusred-wordy[bot]6, as stated. And the parenthetical-qualifier claim is now the right way round and is the only one:**Decision (operator, after the merge):**on #306 is the sole non-bare label in the milestone — Decisions or Deviations — and the other twenty-eight Decisions are bare.## Deviations— "Eight Deviation records. Seven are on the milestone issue and the delivery tasks — two by the operator on #305, three on #309 and one each on #310 and #311, those five by the implementer seat — and the eighth is on this document's own task": exact, including the authorship split (davison×2,radiusred-cody[bot]×5,radiusred-wordy[bot]×1) and "None is recorded on #306, #307, #308 or the spoke's task".## What the record does not contain, third bullet: rewritten to say the gap was closed after the list was written, and its paraphrase of5564002686is faithful — the quoted grounds ("describes what the 2.0.0 binary wrote", the adopter's steps, the**Trade-off:**and**Rejected:**clauses) are verbatim against the comment. The same Decision is now also folded into### A migrated spoke…as a fifth Decision, quoted verbatim there too.
The self-reference is stated rather than silently resolved — both figures given, the instant named, and the **Deviation:** on #321 that records the recount counted in and cited. The ## Deviations and observations sections each carry it. That is the treatment round one said was defensible if stated.
I also re-checked the two claims the recount could have disturbed and did not: the **Deviation:** on #305 at 02:11:36Z is quoted verbatim (the 28 GiB clause and the withdrawal of the page-cache explanation included), and "the only harness attribution anywhere in the milestone" is now correctly narrowed to "the milestone's delivery".
Finding 2 (round one) — resolved: #316's provenance reads forward
radiusred/gh-codecrew#316 was created 00:06:27Z by the operator; PR #313's only review 5127113957 was submitted 00:10:17Z. Both sentences now run in that order: the captures section has "filed at 00:06:27Z from the seat's own report and four minutes before the review that independently reached the same reading", and the ## The review rounds PR #313 bullet has "a third reaches the same reading as capture #316, which the operator had already filed four minutes earlier from the implementer's own report". No remaining sentence claims the capture came from the review.
Finding 3 (round one) — resolved: five sections
docs/blog/posts/2026-09-07-protocol-2-0-and-the-migration.md in radiusred/codecrew-www carries exactly five headings — ## Why a protocol major, ## What changed, ## What an adopter does, ## What deliberately did not change, ## What the migration taught — preceded by an unheaded opening paragraph. The record now says "an unheaded opening and five sections", and its list of five matches the headings verbatim, including the heading's own wording ("what the migration taught", not "the fleet migration").
The nit (round one) — taken
"the sharpest statement of what a dry run is for in this codebase" is now "it is this milestone's clearest statement of what a dry run is for" — scoped to material the record itself enumerates, which is the document's own rule for comparatives.
What I ran
gh codecrew milestone evidence 15, built from this branch (go build ./cmd/codecrew) and run against the live milestone: exit 0, printingrequirements counted: M15-R1, … (7)andall 20 cited links resolve across 9 issues — evidence is reachable— byte for byte the block the record quotes.gh codecrew milestone close 15 --dry-runfrom this branch reproduces the quoted gate block withradiusred/gh-codecrew#321 (in review), which is exactly what the record's new sentence says it would show with this pull request open. The disclaimer is accurate.- Boundary check, docs-only change:
gofmt -l .clean,go vet ./...clean,go test ./...green acrossinternal/cli,internal/config,internal/gh,internal/tracker. - Mechanics. New commit
bc12d1fis conventional, lowercase after the type, subject 72 characters, references(#321), and no body line exceeds 100. It touches one file —docs/milestones/15-v2-0-1-what-the-fleet-migration-taught.md, +141/−44 — so round one's checks onCHANGELOG.md(### The M15 recordunder a fresh## [Unreleased], ending(#321)),ROADMAP.mdanddocs/introduction.mdstand unchanged.closingIssuesReferencesstill lists #321 alone, and the body's only close-family word remains the leadingCloses #321. The two relative links added both resolve, and the## Protocol-discipline observationscount went 8 → 9 to match the nine bullets that are actually there.
Two nits, neither a finding
## Deviations, line 807: "the operator's #306 Decision landed three minutes later and the second #305 Deviation five minutes after that". Read against the commit at 02:06:04Z both offsets are right; read with "that" as the #306 Decision the second is 2m35s. The observations bullet states the same thing with absolute timestamps and is unambiguous, so this is a wording preference only.- Line 1218: "the review that found them opened on the observation that '…'". That sentence is the round-one review's closing line rather than its opening; the quotation itself is verbatim, and Finding 1 was the review's first and blocking finding, so the sense is right.
Neither blocks. The record is honest about its own moving target, and the counts in it are re-derivable by anyone who runs the same rule against the frozen trail.
Closes #321.
The M15 milestone record:
docs/milestones/15-v2-0-1-what-the-fleet-migration-taught.md, written under the doc-synthesizer contract from the milestone's own trail — #305's body and comments, the seven delivery task issues and their pull requests with every review submission, and the release artefacts read back through the git, releases and actions APIs rather than quoted from the evidence comment.What it records. Seven requirements as opened, with no edit to the milestone body at all — its
userContentEditsquery returns a total count of zero. Seven delivery tasks, six here and one in radiusred/codecrew-www, in merge order with their rounds. Twenty-five Decision records and six Deviation records, grouped by the question each task had to settle. Fourteen review submissions — four change requests, ten approvals submitted, seven standing and three dismissed by a rebase. One QA round, in which every requirement came backsatisfied. The release, from the tag object through to the operator's own verification. The blog post, and the three Decisions about what a public page may say. Eight adopted backlog captures and four the milestone filed and left open. Eight protocol-discipline observations, and a "What the record does not contain" section with eight gaps in the trail.Counts. Every one is re-derived from the source rather than carried across, which is the standard PR #304's two rounds set on the M14 record. Records are counted by
tracker.ExtractRecords' own rule, which in this milestone reads one paragraph recording no deviation as a Deviation record, and one paragraph that reads like a Deviation label as none. Both are named in the record and in a Decision on the task: a count nobody can reproduce from the source is worse than one that needs explaining.Also in this pull request. The M15 row appended to
ROADMAP.md, already Done. A### The M15 recordsection at the top of the fresh## [Unreleased]inCHANGELOG.md, ending(#321). And the doc-synthesizer refresh: two clauses added todocs/introduction.md's verb summary —task finishnames any issue its merge would take besides the task, andstatusnames a task's holder from its start record and reports the repository's stale task branches. Nothing on either page was false, and the record says what was run to establish that: M15-R6's own flip had already moved both version claims to v2.0.1, the installed extension printsv2.0.1 (protocol 2.0), and SPEC §10's catalogue still counts forty-three refusal codes because this milestone added none.README.mdis unchanged, and the Decision on the task says why.Checks.
gh codecrew milestone evidence 15from the installed v2.0.1, run against this branch's milestone: seven requirements counted, every cited link reachable. Every github.com URL in the record — ninety of them — was opened through the API by hand as well; every relative link and heading anchor into the sibling milestone records checked to exist.gofmt -l .,go vet ./...andgo test ./...clean, as the boundary check on a docs-only change. One commit, conventional, lowercase after the type, 87 characters,(#321), authored asradiusred-wordy[bot].Decisions recorded on the task — three, and all three are mine to make: the scope of the introduction and README refresh, with what was run to justify it; attributing the reviewer seat's harness only for the four rounds the trail names, and declaring the other ten unattributed rather than inferring a harness from how a review reads; and counting the two record-grammar edge cases the way the scanner counts them rather than the way the prose reads. No deviations from the plan, and no ask-the-human point was reached.
For the reviewer. This dispatch stops at the open pull request: the review and
gh codecrew task finishfollow from the coordination layer. The two claims most worth a second opinion are the counts — every one is stated in the record's opening paragraph and each is re-derivable — and the harness attribution, where the record deliberately leaves ten of the fourteen rounds unattributed.