Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/silent-revert-canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ name: silent-revert-canary
# another recently-merged commit had just added.
#
# On 2026-08-15 three squash merges each landed a tree that dropped work a
# sibling PR had merged minutes earlier (#2633 dropped #2632, #2639 dropped
# #2635, #2641 dropped #2639). Every check stayed green through all three,
# because each reverting squash removed the code AND its tests in the same
# commit -- no suite can fail for a behavior whose tests are gone. Two issues
# sat CLOSED as COMPLETED with their fixes absent from main.
# sibling PR had merged minutes earlier (#2633 dropped both #2644 and #2642,
# #2639 dropped #2635, #2641 dropped #2639). Every check stayed green through
# all three, because each reverting squash removed the code AND its tests in
# the same commit -- no suite can fail for a behavior whose tests are gone.
# Two issues sat CLOSED as COMPLETED with their fixes absent from main.
#
# DETECTION, NOT PREVENTION -- and deliberately so.
#
Expand Down
40 changes: 27 additions & 13 deletions scripts/check-silent-revert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,19 @@
# WHY THIS EXISTS (#2691)
# ----------------------
# On 2026-08-15, three squash merges each landed a tree that dropped work a
# sibling PR had merged minutes earlier. #2633 dropped #2632's rollups (853
# lines); #2639 dropped #2635's report-ordering fix (346); #2641 dropped
# #2639's guard work (451) -- destructive_guard.py went 1643 -> 1424 lines.
# sibling PR had merged minutes earlier. #2633 dropped #2644's finding rollups
# (853 lines) AND #2642's aliased GraphQL merge evidence (301) in one squash --
# plugins/repo-fleet-hygiene/skills/audit/scripts/audit-fleet.sh went 2178 ->
# 1700 lines with every `rollup` and `graphql` marker at zero; #2639 dropped
# #2635's report-ordering fix (346); #2641 dropped #2639's guard work (451) --
# destructive_guard.py went 1643 -> 1424 lines.
#
# Every PARENTHESIZED line count above is a blame attribution: the number of
# lines the reverting squash deleted that `git blame` credits to that one
# culprit commit. It is not the squash's diffstat (cc58cbc53 removed 1165
# lines in total) and not the number of lines the culprit added. The bare
# `2178 -> 1700` and `1643 -> 1424` figures are a different measurement --
# whole-file line counts before and after.
#
# Every check stayed green through all three, and that is the point: each
# reverting squash removed the code AND the tests covering it in the same
Expand Down Expand Up @@ -49,10 +59,10 @@
# chosen.
#
# Curated marker strings (#2691's own suggestion 3). Catches only what
# somebody pre-registered. Nobody had registered #2632, #2635 or #2639 --
# registration happens after you already know a fix matters, which is exactly
# the knowledge the incident destroys. It also decays: the list is only as
# fresh as the last person who remembered to append to it.
# somebody pre-registered. Nobody had registered #2644, #2642, #2635 or
# #2639 -- registration happens after you already know a fix matters, which
# is exactly the knowledge the incident destroys. It also decays: the list is
# only as fresh as the last person who remembered to append to it.
#
# Merge-base staleness (the PR's branch point vs. what landed since).
# Tested and REJECTED on evidence: it exonerates all three real incidents,
Expand All @@ -65,10 +75,12 @@
# open, so it fires on almost everything.
#
# What is left is content: blame the lines a merge deleted and see who had just
# added them. Measured over the last 500 first-parent commits of main, the three
# known incidents score 853 / 451 / 346 lines against a single recent commit,
# and the highest verified-legitimate commit scores well below the threshold
# below. The separation is what makes the canary livable.
# added them. Measured over the last 500 first-parent commits of main, the
# three known incidents score 853 / 451 / 346 lines against a single recent
# commit -- plus a fourth attribution of 301 lines on the SAME #2633 squash,
# whose deletions trace to two different culprits and are reported separately.
# The highest verified-legitimate commit scores well below the threshold below.
# The separation is what makes the canary livable.
#
# FALSE-POSITIVE STRATEGY (the whole design rests on this)
# -------------------------------------------------------
Expand Down Expand Up @@ -101,8 +113,10 @@
# THE RESIDUAL FALSE POSITIVE, MEASURED RATHER THAN ASSUMED
# ---------------------------------------------------------
# At these settings, over the last 500 first-parent commits of main, the canary
# fires 5 times -- 1%. Three are the confirmed incidents. The other two are both
# real, and neither is a bug in the detector:
# fires on 5 commits -- 1%. (Six findings, not five: #2633's squash deleted
# content from two different culprits and each attribution is reported on its
# own.) Three of the five commits are the confirmed incidents. The other two
# are both real, and neither is a bug in the detector:
#
# 6f0a31109 (#2640, 390 lines) is the manual RESTORE of #2633's revert. To
# put back what #2633 dropped it had to delete what #2633 had added, so a
Expand Down
7 changes: 4 additions & 3 deletions scripts/silent-revert-acknowledged.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@
# the canary's first fire is a NEW event rather than known backlog.

# #2640 is the manual restore of the content #2633's squash dropped. Putting
# #2632's rollups back required deleting what #2633 had put in their place, so
# a large removal of very recent content is precisely what this commit is.
6f0a3110942375fb292112f5df5e2c39bbf56cb0 #2640 restores #2632's rollups; the removal undoes #2633's revert
# #2644's finding rollups and #2642's aliased GraphQL merge evidence back
# required deleting what #2633 had put in their place, so a large removal of
# very recent content is precisely what this commit is.
6f0a3110942375fb292112f5df5e2c39bbf56cb0 #2640 restores #2644's rollups and #2642's GraphQL merge evidence; the removal undoes #2633's revert

# #2135's author noticed main move under the PR, merged origin/main into the
# branch rather than force-pushing, and argued the disposition explicitly in the
Expand Down
29 changes: 24 additions & 5 deletions scripts/silent-revert-incidents.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,30 @@ fires f603880dad4003477ec7cac27654fce92c75eec8 #2639 dropped #2635 (346 lines),
# went to zero occurrences. #2618 was left CLOSED as COMPLETED.
fires 9239f1541b1b15a2a183ad6b4067e577f931e3f1 #2641 dropped #2639 (451 lines), 10 minutes later

# Found by this canary's own calibration run, NOT by the #2691 audit: the same
# night, #2633's squash dropped #2632's finding rollups (853 lines). #2640 had
# to restore them by hand. Nobody had filed it, which is the clearest argument
# for automating the detection.
fires cc58cbc53fbbb2cca68e071507b82d3e3ff896ff #2633 dropped #2632's rollups (853 lines) -- unfiled until now
# The third merge from the same night, surfaced by this canary's own
# calibration run rather than by the #2691 audit. #2633's squash dropped work
# from TWO siblings at once, and the canary reports each culprit separately:
#
# 853 lines traced to bfb66beb8 (#2644, finding rollups and handoff plans)
# 301 lines traced to eda5ae5ed (#2642, aliased GraphQL merge evidence)
#
# Both numbers are blame attributions -- the count of lines cc58cbc53 deleted
# that `git blame` credits to that one culprit. Neither is the squash's
# diffstat (it removed 1165 lines in total) and neither is what the culprit
# itself added. plugins/repo-fleet-hygiene/skills/audit/scripts/audit-fleet.sh
# went 2178 -> 1700 lines with every `rollup` and `graphql` marker at zero;
# #2640 restored both surfaces by hand.
#
# This event was NOT unfiled. Issue #2656 recorded it, pinned to the same
# commits, roughly 23 hours before this canary merged -- from the test-coverage
# angle (the hand restore left `bare-repo-with-working-tree` uncovered) rather
# than as a silent revert. What the canary adds is detection speed and
# automation, not discovery.
#
# An earlier version of this row named #2632 as the victim. That was wrong:
# #2632 never merged (closed unmerged, no merge commit, not an ancestor of
# main) and its diff contains no rollup work at all.
fires cc58cbc53fbbb2cca68e071507b82d3e3ff896ff #2633 dropped #2644's rollups (853 blamed lines) and #2642's GraphQL merge evidence (301); already recorded in #2656
Comment thread
kyle-sexton marked this conversation as resolved.

# --- Verified-legitimate commits that must stay quiet -------------------------
# The closest sub-threshold miss in 500 commits: 129 lines of a doc section that
Expand Down