Skip to content

fix(caller-drift): name WHICH read failed, not "repos that could not be read" - #242

Merged
LukasWodka merged 1 commit into
developfrom
fix/1885-watchdog-unreadable-decomposed
Aug 13, 2026
Merged

fix(caller-drift): name WHICH read failed, not "repos that could not be read"#242
LukasWodka merged 1 commit into
developfrom
fix/1885-watchdog-unreadable-decomposed

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Bugbot Medium on the staging promotion PR #238.

The mislabel

unreadable is the merged list — protection and ruleset read failures are folded into it (caller-drift.py:2000-2001). The watchdog headline read that count as repos that were never read, so a clean caller/copy/quality audit with one failed protection or ruleset read was announced as:

⚠️Could not evaluate — N repo(s) could not be read and are NOT known to comply.

A true count under a false name, sending the reader hunting for repos nobody had touched.

The split already existed

The script decomposes this correctly for its own report and issue body (caller_failed = len(unreadable) - protection - ruleset, at :2035 and :2152). Only the workflow consumed the merged number — so this exports the existing split rather than inventing one. Same move as remediation_failures, which got its own output for exactly this reason (#227).

Fixed in both places

The "Remediation failed" verdict carried the same wording. The phrase is now built once above the verdicts and quoted twice — fixing only the reported line would have left its sibling saying "repo(s) could not be read", which is the half-fix this repo keeps re-learning.

Verified by running the composed shell over every shape

inputsheadline
caller only3 repo(s) could not be read (caller/copy state UNKNOWN)
protection only2 branch-protection read(s) failed (protection state UNKNOWN)
ruleset only1 ruleset read(s) failed (ruleset state UNKNOWN)
all threethe three clauses, joined
split absent7 read(s) failed (fallback, so a future read type cannot produce an empty sentence)

caller-drift selftest 162 pass / 0 fail; actionlint clean; ruff clean.


Note

Low Risk
Reporting and workflow shell wording only; audit logic and exit codes are unchanged.

Overview
Caller-drift watchdog verdicts no longer treat the merged unreadable count as “repos that could not be read.” caller-drift.py now writes caller_unreadable, protection_unreadable, and ruleset_unreadable to step outputs (the script already separated these internally for its report).

The caller-drift.yml conformance-issue step builds one what phrase from those counts (caller/copy vs branch-protection vs ruleset, with a generic fallback) and reuses it for exit-code 2 “could not evaluate” and remediation failed headlines, so operators see which API layer failed instead of chasing repos that were actually audited.

Reviewed by Cursor Bugbot for commit f79e195. Bugbot is set up for automated code reviews on this repo. Configure here.

…be read"
Bugbot Medium on the staging promotion PR #238.
`unreadable` is the MERGED list -- protection and ruleset read failures are
folded into it (caller-drift.py:2000-2001). The watchdog headline read that count
as repos that were never read, so a clean caller/copy/quality audit with a single
failed protection or ruleset read was announced as "N repo(s) could not be read
and are NOT known to comply": a true count under a false name, sending the reader
to look for repos nobody had touched.
The script already decomposes this correctly for its own report and issue body
(the `caller_failed = len(unreadable) - protection - ruleset` split at :2035 and
:2152). Only the workflow consumed the merged number. So this exports the split
that already existed rather than inventing one -- same move as
`remediation_failures`, which got its own output for exactly this reason (#227).
Adds `caller_unreadable`, `protection_unreadable` and `ruleset_unreadable`
outputs; the watchdog composes them into one clause naming each failing read
type, falling back to the merged count so a future read type cannot produce an
empty sentence.
FIXED IN BOTH PLACES. The "Remediation failed" verdict carried the same wording,
so the phrase is now built ONCE above the verdicts and quoted twice -- fixing
only the reported line would have left its sibling saying "repo(s) could not be
read", which is the exact half-fix this repo keeps re-learning.
Verified by running the composed shell over every shape:
caller-only -> "3 repo(s) could not be read (caller/copy state UNKNOWN)"
protection-only -> "2 branch-protection read(s) failed (protection state UNKNOWN)"
ruleset-only -> "1 ruleset read(s) failed (ruleset state UNKNOWN)"
all three -> the three clauses, joined
split absent -> "7 read(s) failed" (fallback)
caller-drift selftest 162 pass / 0 fail; actionlint clean; ruff clean.

@saadqbalsaadqbal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clean, careful PR 👍 Fail-closed posture is fully intact — the exit-2/return paths in caller-drift.py (2163+) are byte-identical; this only adds three handle.write outputs and rewords two verdict strings. Attribution is right: caller_unreadable = len(unreadable) − len(protection_unreadable) − len(ruleset_unreadable) reads after the two extends at 2000-2001, so it recovers exactly the original repo-read count — same arithmetic already used/tested at 2034 and 2164. The [ … ] && what=… builder is set -e-safe, and I checked the protection-only and split-absent (fallback) branches both produce sane text. One tiny non-blocker: the new GHA outputs themselves aren't asserted by the selftest (no test change here), but the split state they derive from is (selftest 918-925), so it's thin plumbing over tested logic.

@LukasWodka
LukasWodka merged commit 91d4a0b into developAug 13, 2026
13 checks passed
@LukasWodka
LukasWodka deleted the fix/1885-watchdog-unreadable-decomposed branch August 14, 2026 13:53
Sign up for freeto 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.

2 participants

@LukasWodka@saadqbal