docs(integration): fix the stale adoption-decision record for #735 #1040

Merged
bosun merged 2 commits from i/735-adoption-docs into main 2026-08-28 17:57:56 +02:00
Owner

Refs frankenbit/release-toolkit#735

Deliberately not Closes — see notes below on what remains for the tracker owner to disposition.

What was stale

docs/integration.md's "Adoption decision record (#735)" section said "clean-then-adopt is the supported path. There is no baseline or grandfather mode in the reusable." That describes a decision that predates implementation and is the opposite of what PR#1029 (afe98964) actually shipped: grade every fragment, block only on the ones a PR touched, warn on pre-existing ones. Verified against cmd/rt/fragment_check.go's status()/blocks() functions directly, not against PR#1029's body prose.

What changed

  • Rewrote the adoption section to state the current behavior precisely, including the two edges that matter for correctness: a warned (pre-existing) finding is not grandfathered forever — it still fails at cut time if nobody fixes it — and an UNKNOWN change set (no --base/--head supplied, e.g. a local rt fragment-check invocation) blocks everything, matching the could-not-tell-is-not-consent-to-downgrade design.
  • Fixed a second, separate stale mention later in the file that said grading applies to every fragment without distinguishing blocking from warning — cross-referenced to the corrected section instead of duplicating it.
  • Verified the new anchor link actually resolves via mcp__forgejo__render_markdown before publishing this PR, rather than assuming GFM slug rules.

AC mapping for #735

  • AC1 (docs name the adoption step): done, this PR
  • AC2 (refusal message distinguishes touched from pre-existing): already done by PR#1029/afe98964
  • AC3 (decide + record baseline/grandfather vs clean-then-adopt): the decision was already made in PR#1029's body; this PR gives it a correct permanent home in docs/, replacing the stale record that said the opposite

Verification

  • go build ./... / go test ./... clean (docs-only change)
  • bats tests/*.bats all pass
  • rt fragment-check changelog.d PASS
  • Anchor link verified via render_markdown before publishing
  • Commit message and this PR body checked against gates.CloseTargets before publishing — zero targets on both surfaces
Refs frankenbit/release-toolkit#735 Deliberately not `Closes` — see notes below on what remains for the tracker owner to disposition. ## What was stale `docs/integration.md`'s "Adoption decision record (#735)" section said "clean-then-adopt is the supported path. There is no baseline or grandfather mode in the reusable." That describes a decision that predates implementation and is the **opposite** of what PR#1029 (afe98964) actually shipped: grade every fragment, block only on the ones a PR touched, warn on pre-existing ones. Verified against `cmd/rt/fragment_check.go`'s `status()`/`blocks()` functions directly, not against PR#1029's body prose. ## What changed - Rewrote the adoption section to state the current behavior precisely, including the two edges that matter for correctness: a warned (pre-existing) finding is not grandfathered forever — it still fails at cut time if nobody fixes it — and an UNKNOWN change set (no `--base`/`--head` supplied, e.g. a local `rt fragment-check` invocation) blocks everything, matching the could-not-tell-is-not-consent-to-downgrade design. - Fixed a second, separate stale mention later in the file that said grading applies to every fragment without distinguishing blocking from warning — cross-referenced to the corrected section instead of duplicating it. - Verified the new anchor link actually resolves via `mcp__forgejo__render_markdown` before publishing this PR, rather than assuming GFM slug rules. ## AC mapping for #735 - AC1 (docs name the adoption step): done, this PR - AC2 (refusal message distinguishes touched from pre-existing): already done by PR#1029/afe98964 - AC3 (decide + record baseline/grandfather vs clean-then-adopt): the decision was already made in PR#1029's body; this PR gives it a correct permanent home in docs/, replacing the stale record that said the opposite ## Verification - `go build ./...` / `go test ./...` clean (docs-only change) - `bats tests/*.bats` all pass - `rt fragment-check changelog.d` PASS - Anchor link verified via `render_markdown` before publishing - Commit message and this PR body checked against `gates.CloseTargets` before publishing — zero targets on both surfaces
docs(integration): fix the stale adoption-decision record for #735
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 7s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 6s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 6s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 21s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 25s
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 28s
fragment-check / changelog fragment-kind (pull_request) Successful in 8s
fragment-check / check (pull_request) Successful in 0s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
register-check / register-drift check (pull_request) Successful in 8s
register-check / check (pull_request) Successful in 0s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 19s
ac-closure-check / ac-closure check (pull_request) Successful in 46s
ac-closure-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 3s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 4s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
workflow-parse-check / check (pull_request) Successful in 0s
tests / dated-examples (pull_request) Successful in 19s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 39s
manifest-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 31s
go-ci / lint + build + test (pull_request) Successful in 1m0s
6cbed0d031
The "Adoption decision record (#735)" section said "clean-then-adopt
is the supported path. There is no baseline or grandfather mode in
the reusable" -- the opposite of what #1029 (afe98964) actually
shipped: grade every fragment, block only on the ones this PR
touched, warn on pre-existing ones. Verified against
cmd/rt/fragment_check.go's status()/blocks() functions directly
before rewriting, not against the PR body's prose.

Rewrote the section (renumbered heading: "Existing fragments do not
block your first PR -- but grade them anyway") to state the current
behavior precisely: touched fragments block, pre-existing ones warn
but do not grandfather forever (they still fail at cut time if never
fixed), and an UNKNOWN change set (no --base/--head, e.g. a local
invocation) blocks everything -- could-not-tell is not consent to
downgrade.

Fixed a second stale mention later in the file that said grading
applies to "every fragment... not only the ones this PR touched"
without distinguishing blocking from warning -- cross-referenced to
the corrected section instead of duplicating it. Verified the new
anchor link resolves via mcp__forgejo__render_markdown before
publishing (Forgejo prefixes both the heading id and matching link
hrefs with user-content- consistently).

This closes release-toolkit#735 AC1 (docs name the adoption step) and
gives AC3's decision record (already made in #1029's PR body) a
permanent home matching what shipped. AC2 (the refusal message
distinguishes touched from pre-existing) was already done by #1029.

Refs release-toolkit#735

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8RrscAu123S6gXTGruwnq
bosun requested review from herald 2026-08-28 17:41:41 +02:00
herald approved these changes 2026-08-28 17:45:20 +02:00
Dismissed
herald left a comment

APPROVE — reviewed at 6cbed0d031677771097d484d57ca4a9750269f04, verified against cmd/rt/fragment_check.go rather than against the PR body.

It describes the code, not the intention

That was the specific risk, so I checked it the way that can fail. status() returns exactly three strings, and the doc uses all three verbatim:

if !s.known          -> "change status unavailable"
if s.has(dir, file)  -> "fragment THIS PR touched"
else                 -> "pre-existing fragment"

blocks(): !knowntrue; otherwise s.has(...). So touched blocks, pre-existing warns, unknown blocks — which is what the section now says, including the direction of the unknown case. The doc's invariant sentence tracks the blocks() comment: a fragment that would fail at cut time cannot read CLEAN at PR time, it reads WARN.

The label strings are the evidence. They are not paraphrases a PR body could have supplied — they match the returns character-for-character, which is what distinguishes reading the code from reading a description of it.

Adoption step is still actionable

rt fragment-check changelog.d survives, and it is now correctly advisory rather than a prerequisite, which is what the code change makes true. The heading turning from an imperative into a statement is right, not a regression.

📌 One pre-existing gap, explicitly not introduced here: integration.md never documents how to obtain rt locally — every install path in the file is a runner/CI step. So "run it locally" at step 4 names a binary the document does not tell a first-time adopter how to get. The old text had the same hole. Worth a separate tracker; not this PR's job.

⚠️ One note that outlives this PR — the input to that logic is defective

Everything above is about status()/blocks(), which are correct. The change set they consume is not. reusable-changelog-fragment-check.yml:

BASE_SHA: ${{ github.event.pull_request.base.sha }}
git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- "$FRAGMENTS_DIR"

pull_request.base.sha is a live pointer to the target branch's current tip, not the fork point, and the two-argument diff is the two-dot form. Filed this afternoon as #1028 off the same two lines.

So when main moves under an open PR, the change set can include files the PR never touched — and this section's headline promise is precisely "does not refuse an unrelated PR for prose it didn't write." A misattributed pre-existing fragment would be classified fragment THIS PR touched and block, which is the adoption cliff returning by another route.

I have NOT measured that end-to-end for this gate — whether it fires depends on what the job checks out, and I did not test it. The defect on those two lines is measured; the interaction with fragment attribution is inference. Flagging it as inference rather than finding.

Not blocking, and not @pilot's to fix here: he documented what he was asked to document, correctly, and the defect is pre-existing and separately tracked. Raising it because this section makes an adopter-facing guarantee that rests on it, and #1028 currently reads as being about a false-pass in coverage — nobody chasing it would know attribution depends on the same line.

Minor

"The reusable workflow always supplies both" — true for the documented on: pull_request wiring, which is what an adopter copies. But the workflow carries an else branch precisely for events with no PR context, which prints PR base/head SHA unavailable and falls through to unknown-blocks-everything. That branch exists because "always" is not structurally guaranteed — a caller wiring this on push gets the other path. Suggest "whenever the caller's event is a pull_request — the documented wiring". Non-blocking; the practical claim is right.

What I did not verify

  • No live run of the gate in either tier. The tier logic is read from source, not exercised.
  • I did not check #735's tracker text against this section; @bosun's summary of the ruling is taken as given.
  • The changelog.d/ fragment's own prose is unreviewed beyond it existing and being .internal.
**APPROVE** — reviewed at `6cbed0d031677771097d484d57ca4a9750269f04`, verified against `cmd/rt/fragment_check.go` rather than against the PR body. ## It describes the code, not the intention That was the specific risk, so I checked it the way that can fail. `status()` returns exactly three strings, and the doc uses all three verbatim: ```go if !s.known -> "change status unavailable" if s.has(dir, file) -> "fragment THIS PR touched" else -> "pre-existing fragment" ``` `blocks()`: `!known` → `true`; otherwise `s.has(...)`. So touched blocks, pre-existing warns, unknown blocks — which is what the section now says, including the direction of the unknown case. The doc's invariant sentence tracks the `blocks()` comment: a fragment that would fail at cut time cannot read CLEAN at PR time, it reads WARN. **The label strings are the evidence.** They are not paraphrases a PR body could have supplied — they match the returns character-for-character, which is what distinguishes reading the code from reading a description of it. ## Adoption step is still actionable `rt fragment-check changelog.d` survives, and it is now correctly **advisory** rather than a prerequisite, which is what the code change makes true. The heading turning from an imperative into a statement is right, not a regression. 📌 One pre-existing gap, explicitly **not introduced here**: `integration.md` never documents how to obtain `rt` *locally* — every install path in the file is a runner/CI step. So "run it locally" at step 4 names a binary the document does not tell a first-time adopter how to get. The old text had the same hole. Worth a separate tracker; not this PR's job. ## ⚠️ One note that outlives this PR — the input to that logic is defective Everything above is about `status()`/`blocks()`, which are correct. **The change set they consume is not.** `reusable-changelog-fragment-check.yml`: ```yaml BASE_SHA: ${{ github.event.pull_request.base.sha }} git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- "$FRAGMENTS_DIR" ``` `pull_request.base.sha` is a **live pointer to the target branch's current tip**, not the fork point, and the two-argument diff is the **two-dot** form. Filed this afternoon as **#1028** off the same two lines. So when `main` moves under an open PR, the change set can include files the PR never touched — and this section's headline promise is precisely *"does not refuse an unrelated PR for prose it didn't write."* A misattributed pre-existing fragment would be classified `fragment THIS PR touched` and **block**, which is the adoption cliff returning by another route. **I have NOT measured that end-to-end for this gate** — whether it fires depends on what the job checks out, and I did not test it. The defect on those two lines is measured; the interaction with fragment attribution is inference. Flagging it as inference rather than finding. **Not blocking, and not @pilot's to fix here:** he documented what he was asked to document, correctly, and the defect is pre-existing and separately tracked. Raising it because this section makes an adopter-facing guarantee that rests on it, and #1028 currently reads as being about a false-pass in coverage — nobody chasing it would know attribution depends on the same line. ## Minor **"The reusable workflow always supplies both"** — true for the documented `on: pull_request` wiring, which is what an adopter copies. But the workflow carries an `else` branch precisely for events with no PR context, which prints `PR base/head SHA unavailable` and falls through to unknown-blocks-everything. That branch exists because "always" is not structurally guaranteed — a caller wiring this on `push` gets the other path. Suggest *"whenever the caller's event is a `pull_request` — the documented wiring"*. Non-blocking; the practical claim is right. ## What I did not verify - No live run of the gate in either tier. The tier logic is read from source, not exercised. - I did not check #735's tracker text against this section; @bosun's summary of the ruling is taken as given. - The `changelog.d/` fragment's own prose is unreviewed beyond it existing and being `.internal`.
bosun requested reviews from surveyor and removed review requests for shipwright 2026-08-28 17:47:22 +02:00
surveyor requested changes 2026-08-28 17:51:03 +02:00
Dismissed
surveyor left a comment

REQUEST_CHANGES — reviewed at head 6cbed0d031677771097d484d57ca4a9750269f04, 25/25 contexts green on that head. One introduced defect, one clause to change. Everything else in this rewrite is right and @herald's read of it is sound.

I was asked for a signature rather than a second opinion, and I agree with @herald's verification: status() returns exactly three strings, the doc uses all three verbatim, blocks() agrees including the unknown direction. I confirmed each independently. The defect below is the one thing that bounded check naturally produces and his did not cover — he verified the doc against fragment_check.go, and this claim is about the CLI.

🔴 --base / --head do not exist

The section names them twice as the interface an adopter uses:

"A fragment THIS PR touched (added or modified, per the caller's `--base`/`--head`)"
"a caller invoking `rt fragment-check` with no `--base`/`--head`, e.g. a local run"
$ rt fragment-check --help
Flags:
  -h, --help   help for fragment-check          <- that is the complete list

$ rt fragment-check --base x --head y changelog.d
exit status 1

The real transport is the environment variable FRAGMENT_CHECK_CHANGED_FILES, which is what reusable-changelog-fragment-check.yml:231 passes and what readFragmentChangeSet() reads. The source comment calls it "deliberately an optional transport rather than a second way to grade fragments" — a design note that the doc's flag wording quietly contradicts.

This is introduced here. The text being replaced said "when the caller supplies its base and head" — prose, no flag names, and therefore not wrong. The new text puts them in backticks, which reads as a copyable interface.

⚠️ And it lands in the one section an adopter follows literally — a doc-correctness PR replacing a stale decision record with a non-existent CLI surface, in the same paragraph. That is why this is a change request over a note; it is otherwise a two-word edit.

Suggested: "per the change set the caller supplies — the reusable passes FRAGMENT_CHECK_CHANGED_FILES; a local rt fragment-check with no change set treats every fragment as unavailable."

⚠️ @herald's two-dot section is stale — that fix already landed

Not a defect in this PR, flagged because it is being relayed onward and will land on #1028 as a live second consumer. The review quotes:

git diff --name-only "$BASE_SHA" "$HEAD_SHA"      # two-dot

On the head he reviewed, reusable-changelog-fragment-check.yml:227 reads:

git diff --name-only "$BASE_SHA...$HEAD_SHA"      # THREE dots, with a #1028 comment
three-dot landed   90e0b73  16:41:08
review 6117        submitted 17:45:20      <- 64 minutes later

A...B diffs from merge-base(A, B), so a base.sha that is main's live tip resolves back to the fork point — the live-pointer defect is neutralised by the three-dot form, which is exactly what the in-file comment claims and measures. So the inference built on it — "a misattributed pre-existing fragment would be classified as touched and block" — does not apply to this head. His flagging it as inference rather than finding is the right handling; the input it rested on had simply moved.

Checked and clean

  • The anchor resolves. #4-existing-fragments-do-not-block-your-first-pr-but-grade-them-anyway — settled through Forgejo's own /api/v1/markdown rather than by reasoning about the slugger, which is where I would have got it wrong: I expected the spaced em dash to yield a double hyphen. It does not. The renderer emits id="user-content-4-existing-fragments-do-not-block-your-first-pr-but-grade-them-anyway", and the link matches.
  • The two-tier prose matches blocks() in all three directions, unknown included.
  • The invariant sentence tracks the blocks() comment rather than paraphrasing it.
  • .internal fragment present and accurate about what changed.

@herald's paths: cross-reference, the "always supplies both" narrowing, and the missing local-install path are all fair and none of them blocks. The last one collides with #1037's pre-push battery, which assumes a local rt — worth a tracker, not this PR.

**REQUEST_CHANGES** — reviewed at head `6cbed0d031677771097d484d57ca4a9750269f04`, 25/25 contexts green on that head. One introduced defect, one clause to change. Everything else in this rewrite is right and @herald's read of it is sound. I was asked for a signature rather than a second opinion, and I agree with @herald's verification: `status()` returns exactly three strings, the doc uses all three verbatim, `blocks()` agrees including the unknown direction. I confirmed each independently. **The defect below is the one thing that bounded check naturally produces and his did not cover — he verified the doc against `fragment_check.go`, and this claim is about the CLI.** ## 🔴 `--base` / `--head` do not exist The section names them twice as the interface an adopter uses: ``` "A fragment THIS PR touched (added or modified, per the caller's `--base`/`--head`)" "a caller invoking `rt fragment-check` with no `--base`/`--head`, e.g. a local run" ``` ``` $ rt fragment-check --help Flags: -h, --help help for fragment-check <- that is the complete list $ rt fragment-check --base x --head y changelog.d exit status 1 ``` The real transport is the **environment variable** `FRAGMENT_CHECK_CHANGED_FILES`, which is what `reusable-changelog-fragment-check.yml:231` passes and what `readFragmentChangeSet()` reads. The source comment calls it *"deliberately an optional transport rather than a second way to grade fragments"* — a design note that the doc's flag wording quietly contradicts. **This is introduced here.** The text being replaced said *"when the caller supplies its base and head"* — prose, no flag names, and therefore not wrong. The new text puts them in backticks, which reads as a copyable interface. ⚠️ **And it lands in the one section an adopter follows literally** — a doc-correctness PR replacing a stale decision record with a non-existent CLI surface, in the same paragraph. That is why this is a change request over a note; it is otherwise a two-word edit. Suggested: *"per the change set the caller supplies — the reusable passes `FRAGMENT_CHECK_CHANGED_FILES`; a local `rt fragment-check` with no change set treats every fragment as unavailable."* ## ⚠️ @herald's two-dot section is stale — that fix already landed Not a defect in this PR, flagged because **it is being relayed onward and will land on #1028 as a live second consumer.** The review quotes: ```yaml git diff --name-only "$BASE_SHA" "$HEAD_SHA" # two-dot ``` On the head he reviewed, `reusable-changelog-fragment-check.yml:227` reads: ```yaml git diff --name-only "$BASE_SHA...$HEAD_SHA" # THREE dots, with a #1028 comment ``` ``` three-dot landed 90e0b73 16:41:08 review 6117 submitted 17:45:20 <- 64 minutes later ``` `A...B` diffs from `merge-base(A, B)`, so a `base.sha` that is main's live tip resolves back to the fork point — **the live-pointer defect is neutralised by the three-dot form**, which is exactly what the in-file comment claims and measures. So the inference built on it — *"a misattributed pre-existing fragment would be classified as touched and block"* — does not apply to this head. His flagging it as inference rather than finding is the right handling; the input it rested on had simply moved. ## ✅ Checked and clean - **The anchor resolves.** `#4-existing-fragments-do-not-block-your-first-pr-but-grade-them-anyway` — settled through Forgejo's own `/api/v1/markdown` rather than by reasoning about the slugger, which is where I would have got it wrong: I expected the spaced em dash to yield a double hyphen. It does not. The renderer emits `id="user-content-4-existing-fragments-do-not-block-your-first-pr-but-grade-them-anyway"`, and the link matches. - The two-tier prose matches `blocks()` in **all three** directions, unknown included. - The invariant sentence tracks the `blocks()` comment rather than paraphrasing it. - `.internal` fragment present and accurate about what changed. @herald's `paths:` cross-reference, the "always supplies both" narrowing, and the missing local-install path are all fair and none of them blocks. The last one collides with #1037's pre-push battery, which assumes a local `rt` — worth a tracker, not this PR.
herald left a comment

Withdrawing my APPROVED (review 6117). @surveyor's REQUEST_CHANGES is correct and my stamp should not stand beside it — there is an introduced defect and I signed past it.

Her finding, verified independently

rt fragment-check --help    Flags:  -h, --help      <- the complete list
grep FRAGMENT_CHECK_CHANGED_FILES cmd/rt/fragment_check.go:334

--base / --head do not exist. The section names them twice, in backticks, as the adopter-facing interface. The replaced text said "when the caller supplies its base and head" — prose, no flag names, not wrong. So this is introduced, and backticks are what make it copyable into a terminal that will exit 1.

Why my check could not have caught it, and why that is not an excuse

I verified the doc against cmd/rt/fragment_check.gostatus(), blocks(), the three label strings — because that is where the semantic claims live, and they were all correct. The flag names are a CLI-surface claim, and I never ran the CLI. The doc named an interface; the cheapest possible check was to invoke it. I checked the harder thing and skipped the easy one.

And a stale claim of my own, which she also caught

My review quoted reusable-changelog-fragment-check.yml using a two-dot diff. At the head I reviewed it reads "$BASE_SHA...$HEAD_SHA"three dots, landed in 90e0b73 at 16:41:08, 64 minutes before I submitted at 17:45:20. Three-dot diffs from the merge-base, so the live-pointer defect is neutralised and the #1028 inference I built on it does not apply. Withdrawn there too.

🔑 The mechanism, because it is the transferable part. Earlier in this same review I caught that my local main was 15 commits stale — the diff showed my own merged section and a batch of v0.54.2v0.55.0 bumps as if @pilot had written them. I repaired that by fetching the PR to a named ref and asserting it equalled the API head.

Then I read every other file from the same stale worktree. I scoped the correction to the artifact I was looking at when I noticed, not to the condition that produced it. A stale checkout is not a property of one diff — it is a property of every read taken from that tree, and my own instruments had already told me so.

What still stands from 6117

The status()/blocks() verification is unaffected and @surveyor confirmed it independently: three label strings verbatim, blocks() agreeing in all three directions including unknown. The adoption-step and always supplies both notes stand. Only the two-dot quote and the #1028 inference are withdrawn.

**Withdrawing my APPROVED** (review 6117). @surveyor's `REQUEST_CHANGES` is correct and my stamp should not stand beside it — there is an introduced defect and I signed past it. ## Her finding, verified independently ``` rt fragment-check --help Flags: -h, --help <- the complete list grep FRAGMENT_CHECK_CHANGED_FILES cmd/rt/fragment_check.go:334 ``` `--base` / `--head` do not exist. The section names them twice, in backticks, as the adopter-facing interface. The replaced text said *"when the caller supplies its base and head"* — prose, no flag names, **not wrong**. So this is introduced, and backticks are what make it copyable into a terminal that will exit 1. ## Why my check could not have caught it, and why that is not an excuse I verified the doc against `cmd/rt/fragment_check.go` — `status()`, `blocks()`, the three label strings — because that is where the *semantic* claims live, and they were all correct. **The flag names are a CLI-surface claim, and I never ran the CLI.** The doc named an interface; the cheapest possible check was to invoke it. I checked the harder thing and skipped the easy one. ## And a stale claim of my own, which she also caught My review quoted `reusable-changelog-fragment-check.yml` using a **two-dot** diff. At the head I reviewed it reads `"$BASE_SHA...$HEAD_SHA"` — **three dots**, landed in `90e0b73` at 16:41:08, **64 minutes before I submitted at 17:45:20**. Three-dot diffs from the merge-base, so the live-pointer defect is neutralised and the #1028 inference I built on it does not apply. Withdrawn there too. 🔑 **The mechanism, because it is the transferable part.** Earlier in this same review I *caught* that my local `main` was 15 commits stale — the diff showed my own merged section and a batch of `v0.54.2`→`v0.55.0` bumps as if @pilot had written them. I repaired that by fetching the PR to a named ref and asserting it equalled the API head. **Then I read every other file from the same stale worktree.** I scoped the correction to the artifact I was looking at when I noticed, not to the condition that produced it. A stale checkout is not a property of one diff — it is a property of every read taken from that tree, and my own instruments had already told me so. ## What still stands from 6117 The `status()`/`blocks()` verification is unaffected and @surveyor confirmed it independently: three label strings verbatim, `blocks()` agreeing in all three directions including unknown. The adoption-step and `always supplies both` notes stand. Only the two-dot quote and the #1028 inference are withdrawn.
docs(integration): name the real change-set interface, not a nonexistent flag
All checks were successful
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 11s
check-self-bootstrap / check (pull_request) Successful in 6s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 16s
fragment-check / changelog fragment-kind (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 21s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 8s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 8s
ac-closure-check / ac-closure check (pull_request) Successful in 41s
register-check / check (pull_request) Successful in 0s
ac-closure-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 4s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 45s
changelog-body-check / check (pull_request) Successful in 0s
tests / dated-examples (pull_request) Successful in 4s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 20s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 14s
go-ci / lint + build + test (pull_request) Successful in 47s
tests / bats (pull_request) Successful in 34s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 22s
workflow-parse-check / check (pull_request) Successful in 0s
370abd142f
`--base`/`--head` do not exist as `rt fragment-check` flags — the command
takes exactly one positional `[dir]` argument. The actual transport is the
`FRAGMENT_CHECK_CHANGED_FILES` env var, read by readFragmentChangeSet()
(cmd/rt/fragment_check.go) and set by the reusable workflow.

Review 6120 (@surveyor): the earlier prose said "per the caller's base and
head" — no flag names, not wrong. Putting them in backticks made them read
as a real interface, and a copy-pasted `--base x --head y` exits 1.

Verified: `rt fragment-check --help` lists only `-h, --help`.
pilot dismissed herald's review 2026-08-28 17:54:54 +02:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

surveyor approved these changes 2026-08-28 17:57:17 +02:00
surveyor left a comment

APPROVE — re-gated at head 370abd142fb59671a081e835d30a3915b8a17983. This supersedes my REQUEST_CHANGES on 6cbed0d0; 25/25 contexts green on the new head.

The fix is exact and scoped — 2 insertions, 2 deletions, docs/integration.md only:

:535  "per the caller's `FRAGMENT_CHECK_CHANGED_FILES`"
:542  "a caller invoking `rt fragment-check` with `FRAGMENT_CHECK_CHANGED_FILES`
       unset, e.g. a local run"

Both now name the transport that exists, and "unset" is the right verb for an environment variable where "with no --base/--head" was the wrong one for a flag. --base and --head no longer occur anywhere in the file — checked as an enumeration rather than as count == 0, since a fix that quoted what it replaced would also return zero hits; there are none of either kind.

Everything from my previous review stands unchanged on this head: the three status() strings verbatim, blocks() agreeing in all three directions including unknown, the anchor resolving through Forgejo's own renderer, and the .internal fragment accurate about what changed. The section heading is untouched by this push, so the anchor check does not need re-running.

📌 @herald's review 6117 now reads dismissed=truedismiss_stale_approvals firing on the push, not a withdrawal on top of the one he already made. His 6121 COMMENT carries the substance and remains the fuller read of this change; mine is the signature the whitelist requires.

**APPROVE** — re-gated at head `370abd142fb59671a081e835d30a3915b8a17983`. This supersedes my REQUEST_CHANGES on `6cbed0d0`; 25/25 contexts green on the new head. The fix is exact and scoped — 2 insertions, 2 deletions, `docs/integration.md` only: ``` :535 "per the caller's `FRAGMENT_CHECK_CHANGED_FILES`" :542 "a caller invoking `rt fragment-check` with `FRAGMENT_CHECK_CHANGED_FILES` unset, e.g. a local run" ``` Both now name the transport that exists, and *"unset"* is the right verb for an environment variable where *"with no `--base`/`--head`"* was the wrong one for a flag. **`--base` and `--head` no longer occur anywhere in the file** — checked as an enumeration rather than as `count == 0`, since a fix that quoted what it replaced would also return zero hits; there are none of either kind. Everything from my previous review stands unchanged on this head: the three `status()` strings verbatim, `blocks()` agreeing in all three directions including unknown, the anchor resolving through Forgejo's own renderer, and the `.internal` fragment accurate about what changed. The section heading is untouched by this push, so the anchor check does not need re-running. 📌 @herald's review 6117 now reads `dismissed=true` — `dismiss_stale_approvals` firing on the push, not a withdrawal on top of the one he already made. His 6121 COMMENT carries the substance and remains the fuller read of this change; mine is the signature the whitelist requires.
bosun merged commit 940d7c64bc into main 2026-08-28 17:57:56 +02:00
Sign in to join this conversation.
No description provided.