Skip to content

fix(claude-code-review): drop the callee's checks: read that startup-fails every caller without it (closes #831) - #832

Merged
d-morrison merged 22 commits into
mainfrom
fix/831-v2-checks-read-outage
Sep 7, 2026
Merged

fix(claude-code-review): drop the callee's checks: read that startup-fails every caller without it (closes #831)#832
d-morrison merged 22 commits into
mainfrom
fix/831-v2-checks-read-outage

Conversation

@d-morrison

@d-morrison d-morrison commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Important

Live outage. Review dispatch has been dead in most consumers since the v2 slide to c07f7d4 (#830). Merging this does not fix them -- v2 must then be slid onto the merge commit.

Closes #831.

Cause

A reusable workflow's job cannot request a permission its caller lacks: the run ends in startup_failure before any job starts. #830 added checks: read to the claude-review job of the reusable claude-code-review.yml, and sliding v2 onto it broke every caller without that grant.

This repo already documents the rule -- README's Widening permissions is a breaking change -- with the identical prior incident measured in #685. It was not consulted. That, rather than the mechanism, is the durable lesson.

Blast radius, derived

18 repositories pin this workflow at @v2. At the slide (2026-09-06T00:58Z) only Morrison-Lab/gha granted checks: read, because #830 updated the dogfood caller in the same PR -- so the one repo anyone would check first was immunized against the regression it shipped.

17 of 18 broke. 15 still lack the grant as of 2026-09-06 22:27 PDT; ucdavis/bcs (bcs#966, merged 19:14Z, ~18h after the slide) and Morrison-Lab/ai-config (2026-09-07T05:01Z) have since added it.

Fix

Drop checks: read from the callee only. Caller-side grants stay everywhere -- they are what keeps callers working until the slide, and what makes the v3 (#833) cost nothing after it.

Guard

The parity test pins the model job's permission set, so any future addition fails offline. Mutation-verified: adding checks: read, packages: read, or id-token: write, and removing issues: read, each turn it red; a reflow or reorder does not.

CLAUDE.md's tag-slide policy now defers to README's section and adds the pre-slide check that makes it fire, verified to flag the real incident (898a3e2e..c07f7d45) and stay clean on the current tree.

Tradeoff

Reinstates #829 (reopened, rescoped): the reviewer 403s on check-runs and can misreport a clean PR as blocked. A degraded review beats a total outage, and #829's real remedy -- not reading a 403 as "blocked" -- never needed the permission.

Follow-ups: #833 (v3), #836 (instrumented gate), #829 (403 handling).

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d-morrison and others added 2 commits September 6, 2026 21:35
…fails callers

A reusable workflow's job cannot request a permission its caller lacks: the
run ends in startup_failure before any job starts. #830 added checks: read to
the claude-review job, and the v2 slide onto c07f7d4 killed review dispatch
in every consumer that had not granted it.

The parity test now pins the model job's permission SET rather than one key,
so the next addition of any name fails offline instead of at a consumer's
next PR.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ested at v2

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
F1 The comment claimed the outage ended 'until the tag moved back'. v2 is
   still c07f7d4; the rollback never happened. Says so, and says plainly
   that merging fixes nothing until v2 is slid onto the merge commit.
F2 '18 consumers' was the count of repos pinning @v2, not the count that
   broke. Derived: 16 of 18. gha and ucdavis/bcs already had the grant.
F3 CLAUDE.md's tag-slide readiness bar still said green-and-none-pending,
   which c07f7d4 satisfied -- the policy that permitted the incident was
   the one site not updated. Adds the permission-addition gate, with a
   command verified to flag the real incident (898a3e2..c07f7d4).
F4 The example stub and dogfood caller comments, and a test message, still
   said the model job reads check runs. It no longer can.
F5 The workflows.qmd needle could not show the list 'ends' -- appending the
   grant left it green. Anchored on the closing paren; mutation-confirmed.
   Also adds the missing self-test case for an ADDED scope, which nothing
   in the suite demonstrated; confirmed non-vacuous by weakening the
   assertion.
F6 'the v3 that will request it' now cites #833 at all five sites.
F7 Rewrapped the header sentence at a clause boundary.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
d-morrison and others added 14 commits September 6, 2026 22:10
R2-F1 The '18 consumer repositories' the round-1 sweep missed, in the test
      file's own comment -- invisible to a line-based grep because it spans
      a line break. Swept by joining comment continuations instead.
R2-F2 CLAUDE.md said consumers 'lost review dispatch until gha#832'. That PR
      is unmerged and merging it is not what ends the outage; the same diff
      says so twelve lines away. Claim removed.
R2-F3 '16 broke' was the count STILL broken. bcs#966 merged 19:14Z, hours
      after the slide, so bcs broke and was then repaired: 17 broke, 16
      remain. Corrected at all six sites.
R2-F4 The gate command resolved the tag from a LOCAL ref, which this same
      file documents as stale after a slide. Now resolves via ls-remote and
      diffs against FETCH_HEAD.
R2-F5 The gate flagged this very PR: a caller's comment-only change on an
      unchanged key. Now scoped to workflow_call callees, and labelled a
      prompt rather than a gate, with its residual imprecision stated and
      #836 filed for the parsed instrument.
R2-F6 'the one breaking change CI cannot see' was a false universal; it is
      a family, and the siblings are named.
R2-F7 The round-1 rewrap produced a 128-char header line. Rewrapped.
R2-F8 'recommended but not yet used: ... so the reads fail' read as though
      granting stops the 403. Says plainly that at @v2 the reads fail either
      way, because the model job does not request the scope.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R3-F1 The residual count decayed while the PR was being written --
      ai-config granted checks: read 15 minutes before the review, making
      '16 still broken, only bcs has added it' false on both halves. The
      consumer docs and changelog now carry only the fixed historical fact
      (17 of 18 broke) and point at #831 for the number that moves; the
      workflow comment dates its figure. #833's own '18' corrected too.
R3-F2 website/workflows.qmd was the one doc that never got round 2's F8
      correction, so it still implied a caller's grant fixes the 403.
R3-F3 The gate globbed *.yml only -- the exact drift workflow_discovery.py
      exists for, and untestable here since the tree has no *.yaml
      workflow -- and enumerated callees from the working tree while
      diffing FETCH_HEAD. Both fixed or disclosed, and the limitation list
      now says it is partial.
R3-F4 'changing a required input's default' cannot break a caller: the
      default is unreachable. Replaced with the two that do break --
      changing an OPTIONAL input's default, and making an optional input
      required.
R3-F5 checks: read sat in a must-grant list while the prose below called it
      inert; marked '(recommended, see below)'. The reference page's
      example stub was the third copy and lacked the comment the other two
      gained.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R4-F1 The docs asserted present-tense that the 403 happens whether or not
      the caller grants the scope. v2 still points at the commit that DOES
      request it, so until the slide a grant is exactly what makes a caller
      work -- bcs has been green since 19:15Z on the strength of it. As
      written a repaired consumer could read the page and remove the grant.
      Now states what holds before the slide, after it, and at the v3.
R4-F2 Three docs named #831 as the live tracker of the remaining count,
      and this PR closes #831. Retargeted to #833, which stays open and is
      where consumer adoption is the v3 precondition.
R4-F3 '18 repositories pin @v2' names a strictly larger population than the
      one measured -- ucdavis/hac.sap pins quarto-publish@v2 and was never
      affected. Says 'this workflow at @v2' at all six sites.
R4-F4 The closing-paren anchor guarded only workflows.qmd; the identical
      parenthetical in three other docs was unguarded. Now looped over all
      four, mutation-confirmed red in each.
R4-F5 perm_block tolerated a trailing comment on the target line but not on
      the intermediate ones, so a pure reorder of two correct grants turned
      the suite red. Fixed; reorder now passes.
R4-F6 'gha#836 carries the full list' was backwards -- CLAUDE.md's list is
      a superset. Reworded to 'carries the reasoning'.
R4-F7 The CI-invisible family omitted renaming or removing a JOB, which is
      the one this repo's own reference pages expose consumers to by
      telling them to gate branch protection on job names.
R4-F8 '(recommended, see below)' was a forward reference. Replaced with a
      self-contained qualifier.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R5-F4 is the substantive one. README already carries 'Widening permissions
is a breaking change', with the identical prior incident measured (#685,
when #638 added issues: read to ai-code-review.yml and the v2 slide
delivered it). My CLAUDE.md addition re-derived that rule without citing
it, and prescribed a WEAKER remedy: grep the diff, where README says sweep
REVDEPS.md and PR the caller grants BEFORE sliding. An operator following
CLAUDE.md alone would have shipped #830 exactly as it shipped.

I found this by grepping for 'checks: read' rather than for the concept --
the corpus-gap-from-a-grep trap. CLAUDE.md now defers to README as the
authority, adds only the check that makes it fire, and records the actual
lesson: the rule was written down with a worked precedent and was not
consulted, so the check belongs at the readiness bar that made it feel safe.

R5-F1 Four sites still said checks: read is 'not yet used by @v2'. v2 points
      at the commit that DOES request it, so the grant is currently the only
      thing keeping a caller alive -- and one of the four is gha's own
      caller, whose grant is why this repo is the 1-of-18 still working. A
      maintainer trimming an 'unused' permission would have broken it.
R5-F2 The workflow comment still named #831 as the live tracker of a moving
      count, and this PR closes #831. Retargeted to #833; #831's frozen
      figure is labelled as frozen and dated.
R5-F3 '@v2' meant the tag as it resolves today in one sentence and the tag
      after the slide six lines later, unmarked. Both now say which.
R5-F5 'currently points at' and 'required by the currently-tagged @v2' were
      undated volatile claims that go false at the slide. Dated.
R5-F6 The same point was made three times and #833 linked twice in one
      paragraph. Duplicate sentence dropped.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R6-F1 The four-doc parity needle was a whitespace-intolerant substring, so
      a semantic-line-break reflow -- the edit this repo's own review item 7
      asks for -- turned it red claiming the model job holds checks: read.
      Regex now tolerates the reflow; still red on an appended grant.
R6-F2 The gate flagged every permission line of a callee ADDED since the
      tag, which has no callers to break (measured on
      check-code-similarity.yml, new in #728). --diff-filter=M drops those;
      the rename consequence is disclosed.
R6-F3 'the model job stops requesting it' was stated twice, six lines apart,
      in three files. Merged, with the rationale attached to the first.
R6-F4 workflows.qmd was the one prose site left undated, and the three
      consumer-copied stubs justified the grant by a fact that goes false at
      the slide -- and then lives forever in every repo that copied them.
      Reason is now durable: the v3 reinstates it on the callee.
R6-F5 The exact-set assertion fires on a REMOVAL too but reported it as an
      addition needing a v3, contradicting CLAUDE.md.
R6-F6 Breaks fell mid-noun-phrase ('a called' / 'workflow').
R6-F7 The PR body still said 16 and called bcs unaffected -- written before
      17 was derived. bcs broke for ~18h. Body rewritten.
R6-F8 'gha#831 ... freezes at 15' made the issue the subject; and the
      population count was undated while the figure it counts was dated.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R7-F1 is the substantive one. My bullet's stop action was 'go do the REVDEPS
sweep', and REVDEPS.md lists 4 repos of which 1 names this workflow, while
its owner-scoped fallback omits Morrison-Lab and Lacaedemon -- the org this
repo now lives in. A sweep run during the outage would have found 1 of 18
consumers and reported the rest safe, so the remedy I pointed at would have
reproduced the incident. REVDEPS.md now leads with the unscoped per-workflow
search that actually worked, records why the scoped list is a fallback, and
adds the two missing owners; CLAUDE.md carries the derivation inline rather
than delegating it.

R7-F2 'only additions break callers' missed value escalation: contents: read
      to contents: write adds no key and startup-fails every read-only
      caller. The grep surfaces it and the prose said to dismiss it.
R7-F4 The workflow comment attributed the figure 15 to #831, whose body says
      18 and whose comment said 16; #833 and #829 still said 18. Derivation
      posted to all three.
R7-F5 perm_block tolerated trailing comments and reflows but not a full-line
      comment inside the block -- which the sibling stub this PR touches
      already uses. Mutation-confirmed both ways.
R7-F6 workflows.qmd kept the duplication fixed in the other three files, and
      an 'It' whose nearest antecedent was the wrong noun.
R7-F7 'all three phases:' enumerated two; the middle one is now named.
R7-F8 The stub comment gave only the post-slide reason, so it omitted that
      the tagged @v2 makes the grant mandatory today -- the mirror of the
      round-6 error.

R7-F3 (branch unpushed) resolves with this push; the pre-push guard held it
until a clean verdict.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R8-F1 and R8-F2 are both on my own REVDEPS edit, and F1 is the same class
this PR keeps fixing: I asserted the old owner-scoped sweep would have found
'1 of the 18' without deriving it. Measured, it returns 10 of 18 -- the
figure 1 belonged to the consumer table, a different list. Both figures are
now derived and dated.

R8-F2 The fallback queries could never work: GitHub code search reads a
      leading 'uses:' as a qualifier and drops the term, so both returned 0
      hits under every owner list -- indistinguishable from no consumers.
      Measured 0 with the prefix, 30 without. Prefix dropped.
R8-F3 The tag-slide section's closing Do/Don't still presented green CI as
      the whole gate, which is what the new bullet exists to deny.
R8-F4 The consumer-search snippet hard-coded @v2 while the same section says
      to derive the major -- and #833 cuts a v3 that would be missed.
R8-F5 CLAUDE.md's enumeration of what run-review-job-split-tests.py pins
      omitted this change's central guard, describing the suite as weaker
      than it is.
R8-F6 README and website/versioning.qmd -- the sections the new bullet calls
      the authority -- still prescribed the REVDEPS sweep this PR documents
      as having missed most affected repos.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every finding this round was on a numeric claim I wrote into documentation
without deriving it -- the third round running where that is the dominant
class, and the same failure the PR itself is about.

R9-F1 'the 6 under Morrison-Lab and Lacaedemon plus 2 more' invented a
      residual category. Derived: the old five-owner list misses exactly 8,
      all under those two owners (Morrison-Lab 7, Lacaedemon 1), and the
      corrected list returns all 18.
R9-F2 README and versioning.qmd said 'its owner-scoped fallback returned 10',
      dropping REVDEPS.md's own 'pre-2026-09-06' qualifier, so they
      discredited the fallback this PR had just fixed. Both now attribute
      the 10 to the retired list and say the current one returns 18.
R9-F3 CLAUDE.md still summarized README's remedy as 'sweep REVDEPS.md',
      which this PR removed from README -- and contradicted its own text 35
      lines later.
R9-F4 The search snippet interpolated $major before the block that assigns
      it. Run verbatim it does not error: it drops to an unpinned query,
      measured 34 hits against 29, silently widening a blast-radius check.
      The assignment moved into the same block.
R9-F6 The --diff-filter=M rationale cited a false positive that cannot be
      observed: check-code-similarity.yml predates the current tag, and the
      v2..main range adds no workflow at all (11 M, 0 A). The comment now
      says the filter drops nothing today and names a range that shows the
      shape.
R9-F5 The owner-scoped fallbacks omitted --limit, so gh's default of 30
      truncates silently -- the exact failure the surrounding note warns
      about.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R10-F1 'The list below ... returns all 18' pointed at the BROAD fallback,
       not the pinned query the 18 was derived from. Measured 2026-09-07:
       that fallback returns 100 hits across 4 repositories at --limit 100,
       and 304 across 28 at --limit 1000 -- so it was truncating exactly as
       silently as the default 30, in the block whose own comment claimed
       --limit fixed that. Cap raised, the measurement recorded, the
       sentence scoped to the pinned query, and a re-raise instruction added
       for when the hit count equals the cap.
R10-F2 The pre-slide grep matched only the values read and write, so a block
       collapsing to permissions: write-all -- a widening that startup-fails
       every narrower caller, and a spelling the suite's own fixture uses --
       was invisible. Pattern and prose both widened; verified against a
       synthetic write-all line, and confirmed still clean on the live range
       and still red on the incident range.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R11-F1 The 'permissions: (read|write)-all' alternative I added last round was
       dead code: the value pattern is unanchored, so 'write' already matches
       the prefix of 'write-all'. Verified -- the full pattern and the first
       alternative alone match an identical set. Removed, and the caveat list
       now records what the pattern really does: an INDENTED write-all is
       caught, a workflow-level one at column 0 is not, and that gap is
       unreachable today because every callee job declares its own block.
R11-F2 'the pre-2026-09-06 owner list' asserted a supersession that never
       happened -- git says the OWNERS line last changed 2026-07-28 and the
       names 2026-06-18, and the list is replaced by THIS commit. Three
       sites now say 'the list this change replaces' and date it from
       history. README and versioning.qmd additionally narrated this diff's
       own edit in the past tense, which is false on main.
R11-F3 The pre-slide caller search carried --limit 100 with no truncation
       caveat, on the one surface where truncation costs an outage. REVDEPS
       spells the hazard out; CLAUDE.md now does too, with the measured
       busiest count (claude.yml, 29) so the cap is checkable.
R11-F4 REVDEPS's note still framed itself around moving @v1 and cutting @v2.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R12-F1 is the one that matters, and it inverts my own recommendation. The
unscoped per-workflow search I had been telling operators to prefer returns
17 of the 18 consumers: reproduced across three runs, it omits
d-morrison/rme, a public non-archived repo whose caller does pin this
workflow at @v2. The owner-scoped form finds it. Neither form is complete,
neither reports dropping anything, and the --limit guard cannot see it
because 28 never equals the cap.

Following my own instructions before the next slide would therefore have
PRed 17 callers, slid the tag, and startup-failed the eighteenth -- the
gha#831 outage reproduced by the procedure written to prevent it. Every site
now says to run both forms and union them, with the measurement recorded.

R12-F2 'the busiest workflow was claude.yml at 29 hits' was wrong on both
       identity and count -- 29 is claude.yml's UNPINNED figure, while
       claude-code-review.yml measures 28 pinned and 34 unpinned. The
       adjacent 34-against-29 pair mixed a scoped and an unscoped count. The
       specific ceiling is dropped in favour of the mechanical check, since
       a remembered ceiling is the same defect one level down.

Also refreshes the dated consumer figure from the union query: 14 of 18 lack
the grant as of 2026-09-07 02:24 PDT (rme added it since the last reading).

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Round 12's headline finding was my own, and it was wrong. I claimed the
unscoped per-workflow search structurally omits a consumer, on three
repeated runs. Re-measured: d-morrison/rme's caller was pushed at 01:55 PDT
(rme#1143), my readings were at ~02:24, and by 02:53 the same query returns
29 hits across 18 with rme present, stable over four runs. The omission was
code-search INDEX LAG, and my three repetitions were three samples of one
stale index inside a ~30-minute window -- repetition is not independent
sampling when the thing sampled is a cache.

All four sites now carry the true lesson instead: the index lags a recent
push, so union the two query forms, treat any count as a floor, and re-run
after a delay when a caller may have changed recently. The owner-list half
of the evidence was solid and is kept.

R13-F2 'Measured 2026-09-06: 0 with the prefix, 30 without' cited 30, which
       is gh's default cap -- the exact truncation the next code block in
       the same file warns about. Re-measured at --limit 1000: 0 and 304
       across 28 repositories. The artifact is now named as one.
       The adjacent '28 pinned' figure was stale at 29; the comment no
       longer depends on either number.

Also corrects a prose overclaim the reviewer raised as non-blocking:
CLAUDE.md said the model job requests those four keys 'at read and nothing
more', but the exact-set assertion is over KEYS, with values pinned
separately against write. Mutation-confirmed: pull-requests: none passes.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
R14-F1 The union instruction referenced ${OWNERS[@]} three lines before the
array was assigned, under a header introducing a different sweep. Followed
in order, bash expands an unset array to zero words, so the 'owner-scoped'
per-workflow query is byte-identical to the unscoped one already run and the
union silently collapses to a single form -- the exact failure the
surrounding note exists to prevent, reproduced inside the instrument written
to prevent it.

The block is reordered so OWNERS is assigned first (both sweeps use it), the
two per-workflow forms are spelled out as real adjacent commands rather than
one command and a comment, and the reason for the ordering is stated so a
later edit does not undo it. Run verbatim in order, both forms now execute:
29 hits / 18 repos each.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
'returns all 18 -- under the PINNED per-workflow query, not under the broad
fallback beside it' reads as saying the broad sweep would miss consumers the
pinned query finds. Measured twice on 2026-09-07: the broad sweep returns
304 hits across 28 repositories, and that set is a strict superset of the 18
(pin - broad is empty).

The true distinction is not coverage but specificity: the broad form cannot
say WHICH callers pin the workflow being changed. Only the truncated
--limit 100 run omits any of the 18, and the truncation note beside it
already covers that. Reworded to say what actually separates the two forms.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@d-morrison
d-morrison marked this pull request as ready for review September 7, 2026 11:31
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

The @claude review's one finding, non-blocking but real and reproduced: the
snippet resolved $tagsha with git ls-remote, which reads the remote without
fetching anything, then diffed against that sha after fetching only main. On
a shallow clone -- what actions/checkout gives by default, and what the
review job itself runs in -- every loop iteration dies with 'fatal: bad
object'.

Reproduced on a --depth 1 clone and fixed by fetching the tag OBJECT
(git fetch --tags --force) and diffing against the tag ref rather than a
bare sha. Verified on both a shallow and a full clone: the loop completes,
stays clean on v2..main, and still fires on the incident range.

--force because a slide moves the tag, which this file already documents
elsewhere.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@d-morrison

Copy link
Copy Markdown
Collaborator Author

Addressed the shallow-clone finding — thank you, it was real and I reproduced it.

The block resolved tagsha with git ls-remote, which reads the remote without fetching anything, then diffed against that bare SHA having fetched only main. On a --depth 1 clone every loop iteration died with fatal: bad object c07f7d45..., exactly as reported.

Fixed by fetching the tag object and diffing against the ref rather than the SHA:

git fetch -q --tags --force origin main
tagsha="refs/tags/$major"

--force because a slide moves the tag, which the same file documents elsewhere. Verified on a fresh --depth 1 clone and on a full clone: the loop completes, stays clean over v2..main, and still fires on the incident range 898a3e2e..c07f7d45.

Posted by Claude Code (AI agent) --- not written by a human.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

d-morrison and others added 2 commits September 7, 2026 05:29
'required by the tagged @v2 now' dates itself with a word rather than a
date, and becomes false the moment v2 is slid onto this merge -- which this
PR's own body says must happen immediately. These three files are the ones
consumers copy verbatim and then keep indefinitely, so a reason that expires
is the worst place to put one.

The reviewer's failure scenario is the outage this PR exists to prevent: a
maintainer auditing unused permissions weeks later checks the stated reason,
finds it false, drops the grant, and gets startup-failed by the v3.

Reworded to a reason that holds through all three phases.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
I attributed the rme observation to 'a caller edited minutes ago may not be
indexed yet'. The measurement rules that out: rme#1143 added only a comment
and a checks: read line, leaving the uses: line the query matches on
byte-identical since 2026-07-28 (verified from the commit's own patch --
the uses: line appears in neither the + nor the - side). So the document had
matched for six weeks and was dropped anyway.

That is a reindex DROP of an already-indexed file, not a not-yet-indexed new
one, and the difference changes what a reader concludes. Under the old
wording, a count that FELL between two readings reads as a consumer having
removed its pin, because the stated hazard only covers new callers. All four
sites now say a push to any caller's file can drop it until reindexed, and
name the falling-count reading explicitly.

The remedy was already right -- union the forms, treat counts as a floor,
re-run after a delay -- so only the cause and its scope change.

Refs #831

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@d-morrison
d-morrison requested a lite review from Copilot September 7, 2026 13:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.

2026-09-07 13:19 UTC

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Claude finished reviewView run


The most recent prior review comment is confirmed at that URL. I now have everything needed to write the final review.

Code Review — #832

What changed since the last review round

The prior round reviewed commit 855b984289ece3bdffb74234d9c129cabf862d7a. This checkout's head is 6ec1a62f. Per the workflow-computed range (855b9842..6ec1a62f), there are two substantive commits from this PR branch plus one merge:

  • 433d1a0 and the merge 0a65640 are not new PR content — they're an unrelated, already-merged main-branch PR (fix(summary): pin actions/ai-inference back to v2 and ignore its majors (refs #834) #837, pinning actions/ai-inference back to @v2) that arrived via git merge origin/main into fix/831-v2-checks-read-outage. Verified via git show --stat 0a65640 and git show --stat 433d1a0.
  • 5df7ab2 — "make the stub comment's reason durable": rewords the checks: read comment in three consumer-facing files (.github/workflows/claude-review.yml, examples/claude-code-review.yml, website/reference/claude-code-review.qmd) from a self-dating phrase ("required by the tagged @v2 now") to one that stays true through all three phases (current outage, post-slide over-provisioning, future v3 reinstatement).
  • e7f189e — "correct the code-search index mechanism": corrects the causal explanation for the d-morrison/rme code-search flake in four prose sites (CLAUDE.md, README.md, REVDEPS.md, website/versioning.qmd) from "a caller edited minutes ago may not be indexed yet" (new-file-not-yet-indexed) to "a push to a file can drop it from the index until reindexed" (already-indexed-file dropped), since the matched line was unchanged for six weeks.

Verification performed

  • Confirmed 433d1a0/0a65640 are pre-existing main-branch content, not new PR work, via git show --stat.
  • Confirmed 5df7ab2's new wording ("keep: required by @v2 until the slide, and again at the v3 (gha#833)") lands identically across all three sites and grepped the tree for the old, self-dating phrase — no remaining instances.
  • Independently fact-checked e7f189e's central factual claim against the live d-morrison/rme repo via the public GitHub API (not by trusting the commit message):
    • d-morrison/rme#1143 exists, is merged, merged_at: 2026-09-07T08:55:08Z = 01:55:08 PDT, matching the commit message's and REVDEPS.md's stated push time exactly.
    • The PR's diff shows only a comment block and a checks: read line added; the uses: Morrison-Lab/gha/...@v2 line is unchanged context (appears in neither + nor -), confirming the "byte-identical" claim.
    • git log on that file's history in d-morrison/rme shows its next-most-recent change before #1143 was 2026-07-28T22:28:25Z ("Repoint gha reusable workflows to Morrison-Lab/gha"), exactly matching the "byte-identical since 2026-07-28" / "unchanged for six weeks" claim.
    • This is a genuinely accurate correction, not merely a plausible-sounding one — every checkable figure in it holds up against the primary source.
  • Read the full surrounding paragraphs in CLAUDE.md, README.md, REVDEPS.md, and website/versioning.qmd (not just the diff hunks) to confirm the reworded sentences are grammatically coherent and logically consistent with the surrounding "union both search forms, treat any count as a floor, re-run after a delay" guidance — no dangling references to the old "not-yet-indexed" framing remain anywhere in the tree.
  • Grepped for the specific old phrases removed by both commits (required by the tagged @v2 now, a caller edited minutes ago may not be indexed, caller edited.*may not be indexed) — zero hits.

Findings

None. Both commits are narrowly scoped, prose-only fixes that directly and correctly address the two non-blocking findings/self-corrections from prior review rounds (the "keep:" comment durability and the code-search index causal explanation), and both factual claims independently verify against the live external repository referenced.

The prior round's verdict (comment, posted 2026-09-07T12:12:33Z) was Ready for merge with no findings. That verdict stands — this round adds two accurate, well-scoped prose corrections and introduces no regressions.

Verdict

Ready for merge

Structured Review Data (JSON)
{
  "schema_version": "1.1",
  "reviewer": "claude",
  "commit_sha": "6ec1a62fc907af494ffce718d753a082c6de2fd",
  "verdict": "CLEAN",
  "findings": [],
  "detailed_assessment": "The two new commits since the last round (5df7ab2 rewording the checks: read comment, e7f189e correcting the code-search index causal explanation) are prose-only edits across CLAUDE.md, README.md, REVDEPS.md, website/versioning.qmd, website/reference/claude-code-review.qmd, examples/claude-code-review.yml, and claude-review.yml, verified consistent and free of stale leftover wording.",
  "holistic_assessment": "Both new commits directly resolve prior review findings, their central factual claim about d-morrison/rme#1143 was independently confirmed against the live GitHub API rather than trusted, and no regression, scope creep, or integration risk was introduced relative to the already-approved core permission fix."
}

Reviewed commit: e7f189e

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

💰 Cost: $1.3190 (review) — run

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v2 slide to c07f7d45 (#830) breaks review dispatch in every consumer lacking checks: read

2 participants