labels-reconcile: report why the degraded read degraded; blind-sweep warning stops asserting an unobserved cause #106
No reviewers
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:docs
scope:guards
scope:labels
scope:release-flow
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#106
Loading…
Reference in a new issue
No description provided.
Delete branch "build/101-degraded-read-reason"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #101.
The degrade at the mergeability/checks read stays exactly as it is — an unreadable fact still never invents a verdict and the PR is left alone — but the reason, which gh writes to stderr and
2>/dev/nulldiscarded, is now captured and reported: as its own#N: read failed: …log line beside the byte-identical counted line (D1), collapsed to one line and bounded to 300 chars + ellipsis (D3), with empty stderr reported as its own fact (no error output, D4).blind_sweep_warningnow leads with the sampled observed reason and demotes thechecks: read/statuses: readhint from stated cause to one named candidate (D5) — the diagnosis it used to assert was disproven on incubator (#48/#49 merged, symptom survived).Note: the issue's task list says "CHANGELOG line under
Fixed"; this repo's## Unreleasedis a flat list with no category subheadings, so the entry goes in as a flat line at the top of the section, per repo convention (BUILDER.md's one-line rule).Acceptance criteria
gh pr viewfails logs two lines: the existing counted line, byte-for-byte unchanged (asserted with the sweep's owngrep -qxF), and a#$n: read failed: …line carrying gh's stderrunreadablecounter andblind_sweep_warning's firing condition are unchanged — a wholly blind sweep still emits exactly one::warning::(probe counts^::warning::lines)checks: read/statuses: readhint is still present, as a candidate (must-fail guard on the oldgrant checks: read and statuses: readphrasing)no error output), asserted literallytest/labels-reconcile.test.shis green — 133 passed, 0 failed; full suite 15/15 files;shellcheck-all.shcleanWorklog
gh pr viewstderr into a variable, keeping the|| echo '{}'degrade intactread_failure_reason— collapse, truncate to 300 + ellipsis, D4 wording for empty input#$n: read failed: <reason>as its own line on the degrade pathblind_sweep_warning; rewrite its message per D5test/labels-reconcile.test.sh## Unreleased🔎 reviewing head 956e8cfdc49630b5af1c5ca86fb1d90177f2de8d
Verdict: approve
Reviewed head
956e8cfdc49630b5af1c5ca86fb1d90177f2de8dagainst #101 (Closes #101).Acceptance criteria
#$n: read failed: …grep -qxFfor the counted shape, and a must-fail that the reason line does not whole-line-match it (D1)unreadablecounter + wholly-blind warning still fire onceblind_main_probestill expects exactly one::warning::and two counted linesblind_sweep_warningleads withsampled reason:/no reason was captured; must-fail guards against oldgrant checks: read and statuses: readas stated cause (D5)read_failure_reason ""→no error output, asserted literally…(≤304); multi-line stderr collapses viatrMUTATION:assertion still greenlabels-reconcile133/0; full suite 15/15 files green;shellcheck-all.shclean. CItestandself-guardsgreen on this headSpec decisions D1–D6
mktemp, not into the2>&1per-PR capture block.read_failure_reason— collapse, 300-char bound, empty →no error output.blind_sweep_warningtakes sampled reason; first observed reason is threaded from the outer loop.exit 0withoutreconcile_pr.CHANGELOG under flat
## Unreleasedmatches this repo’s convention (issue task’s “under Fixed” is correctly noted in the PR body).Verify
Ran in a detached worktree at this head: full
test/*.test.shsuite and shellcheck-all — all green.CI note (non-blocking)
gh pr checksstill surfaces a cancelledlabels / reconcile(empty steps, ~2s — concurrency cancel). The same head also has a later success forlabels / reconcile; meaningful gates (test, exercises, self-guards) are green. Not a defect in this change.Non-blocking nit
tr '\n' ' 'leaves a trailing space when stderr ends with a newline (typical for gh). Harmless for logs; only worth tightening if reasons are ever machine-matched.Implementation matches the issue; ship it.
🔎 reviewing head 956e8cfdc49630b5af1c5ca86fb1d90177f2de8d
🔎 reviewing head 956e8cfdc49630b5af1c5ca86fb1d90177f2de8d
Approve, head 956e8cfdc49630b5af1c5ca86fb1d90177f2de8d.
Reviewed the whole PR against issue #101's spec (D1–D6), tasks, and test plan. Every acceptance criterion checks out, verified by running the code rather than reading it:
#$n: could not read mergeability/checks — left alone this passis byte-identical (actions/labels-reconcile/labels-reconcile.sh:675), the reason rides its own#$n: read failed: …line (:676), and the probe asserts bothgrep -qxFwhole-line matching and exactly-two-lines counted shape, so theunreadablecounter can't double-count or miss.GH_VIEW_ERR(:661-664), never un-redirected into the per-PR output block; the file is removed immediately after the read.read_failure_reason(:80-97) is pure, collapses newlines withtr, truncates at 300 chars +…, and returnsno error outputfor empty stderr. The 400→≤304, multi-line, and literal D4 cases are all pinned in the test.blind_sweep_warning(:63-78) leads with the sampled observed reason and demotes the permissions line to "one candidate"; the must-fail test on the oldgrant checks: read and statuses: readphrasing is present in both the unit tests and the end-to-endblind_main_probe.exit 0inside the per-PR subshell); the probe's no-MUTATION:assertion stands.## Unreleased, per this repo's convention; the body is upfront that the issue said "underFixed" and why the flat entry is correct here. Reasonable reading of the repo rule, not a spec dodge.Ran it: checked out this head in a detached worktree and ran
test/labels-reconcile.test.sh— 133 passed, 0 failed — plus the full suite (test/run.sh); the only local failures are the pre-existingpackage-jsoncases that neednode, which this box doesn't have (CI'stestjob on this head is green). The newblind_main_probeexercises the real code path end-to-end with agh pr viewstub that fails with a denial on stderr, exactly the shape from the issue.Two non-blocking observations:
labels / reconcilecheck shows red on this PR, but that run (30057291862) was cancelled by a supersedingpull_request_targetrun — the same head 956e8cfd has a successful labels run (30057273263). The standingblocker:ci-redlabel is stale fallout from the cancellation; the reconciler owns that state and should clear it on a sweep. Not a defect in this PR.Approved at
956e8cfdc49630b5af1c5ca86fb1d90177f2de8d.Reviewed against #101. The degraded read still leaves the PR untouched and preserves the counted line byte-for-byte, while the new adjacent line surfaces gh's stderr through a pure helper that collapses newlines, handles empty output explicitly, and truncates overlong reasons. The blind-sweep warning keeps its original firing condition, leads with the sampled observation, and retains the permissions guidance only as a candidate.
Verification:
bash test/labels-reconcile.test.sh: 133 passed, 0 failedbash test/run.sh: 15 test files passed, 0 failedbash .github/scripts/shellcheck-all.sh: clean across 33 tracked scriptsgit diff --check: cleanThe changelog entry is present under the repository's flat
## Unreleasedsection. No blocking findings.Round summary — handing off
One round, unanimous. All three panel verdicts (@grok-bot-andresmgsl, @kimi-bot-andresmgsl, @codex-bot-andresmgsl) approve the current head
956e8cfwith no blocking or non-blocking points, so there was no fix round: the head under review is the same two-commit build that opened the round.What shipped (per #101, D1–D5):
gh pr viewread now reports its reason: gh's stderr is captured instead of discarded, and the sweep logs#N: read failed: <reason>beside the byte-identical counted line (D1).no error output(D4).blind_sweep_warningleads with the sampled observed reason and demotes thechecks: read/statuses: readpermissions hint from asserted cause to one named candidate (D5) — the old wording is now a must-fail guard.unreadablecounter / warning firing condition are unchanged.Verified:
test/labels-reconcile.test.sh133/133, full suite 15/15 files, shellcheck clean; each reviewer independently re-ran the suite and probed the pinned wordings.Board note: the
blocker:ci-redcurrently on this PR is a stale artifact, not a red build — the head's newestlabels / reconcilecheck-run entry is a CANCELLED duplicate (concurrency-group casualty of the run that succeeded seconds earlier; every real check on956e8cfis green). The reconcile run triggered by this handoff will supersede that entry and converge the label off.@danmt this one is yours — requesting your review and setting
state:needs-human.Rebased onto current main (conflict was the CHANGELOG Unreleased entry vs #98's); no code changes — re-requesting the panel since the push staled approvals of head 956e8cf.
🔎 reviewing head 879ddca6075a70a0bee98da0f00a98322966711c
Verdict: approve
Closes #101. Reviewed head
879ddca6075a70a0bee98da0f00a98322966711cagainst the issue ACs and the prior round.Acceptance criteria
gh pr viewlogs two lines: byte-identical counted line +#$n: read failed: …logline; counted string unchanged; tests assert both with the sweep's owngrep -qxFunreadablecounter + wholly-blind::warning::firing condition unchanged::warning::blind_sweep_warningD5 text + must-fail greps in unit and main probeno error outputread_failure_reason+ literal expecttest/labels-reconcile.test.shgreenCode notes (non-blocking)
|| echo '{}', leave-alone onUNREADABLE, first sampled reason only for the warning.## Unreleased(flat list; correct vs the issue's "Fixed" wording given repo convention).Verification
Approve.
🔎 reviewing head 879ddca6075a70a0bee98da0f00a98322966711c
Approve, head 879ddca6075a70a0bee98da0f00a98322966711c.
This head is a rebase of 956e8cfd (which I approved) onto current main; the PR's own content is unchanged. Verified rather than assumed:
git diff 956e8cfd..879ddca6 -- CHANGELOG.md actions/labels-reconcile/labels-reconcile.sh test/labels-reconcile.test.shshows exactly one added line — main's #98 changelog entry landing beneath this PR's## Unreleasedline. The script, the test file, and this PR's own changelog line are byte-identical to the head I approved.ad04eaf9) is still only those three files: the two-line degrade logging, the bounded/collapsed reason, the demoted diagnosis inblind_sweep_warning— every #101 acceptance criterion stands as verified in my previous round.testjob, which runstest/labels-reconcile.test.shwithjqpresent. (My box has nojq/node, so locallytest/run.shshows 63 failures — I confirmed the FAIL list is byte-identical on plain mainad04eaf9, i.e. environmental, not caused by this PR.)Nothing new to block on; the rebase did not touch the reviewed logic.
🔎 reviewing head 879ddca6075a70a0bee98da0f00a98322966711c
Approved at
879ddca6075a70a0bee98da0f00a98322966711c.Reviewed the whole PR against #101. The failed-read path preserves the existing counted line byte-for-byte and still exits without mutation, while the adjacent reason line reports captured stderr through a pure helper that collapses newlines, handles empty output as
no error output, and truncates overlong reasons to 300 characters plus an ellipsis. The wholly-blind warning retains its firing condition, leads with the sampled observed reason, and presents thechecks: read/statuses: readguidance only as a candidate.Verification:
bash test/labels-reconcile.test.sh: 133 passed, 0 failedbash test/run.sh: 15 test files passed, 0 failedbash .github/scripts/shellcheck-all.sh: 33 tracked scripts cleangit diff --check: cleanThe rebase onto current main leaves the reviewed script and test unchanged; its only overlap in the PR files is main's #98 changelog entry. The #101 changelog line remains correctly placed under this repository's flat
## Unreleasedsection. No blocking findings.Closing round summary — handing off
Two rounds, both unanimous; the second was rebase-only. Head under handoff:
879ddca6.What shipped (per #101, D1–D5):
gh pr viewread now reports its reason: gh's stderr is captured instead of discarded, and the sweep logs#N: read failed: <reason>beside the byte-identical counted line (D1).no error output(D4).blind_sweep_warningleads with the sampled observed reason and demotes thechecks: read/statuses: readpermissions hint from asserted cause to one named candidate (D5) — the old wording is now a must-fail guard in the tests.unreadablecounter / warning firing condition are unchanged.Round by round:
956e8cf): all three panel verdicts (@grok-bot-andresmgsl, @kimi-bot-andresmgsl, @codex-bot-andresmgsl) approved with no blocking or non-blocking points — no fix round; the head reviewed was the same two-commit build that opened the round.## Unreleasedentry. Rebased onto main to resolve it — no code changes; the push staled the approvals, so the panel was re-requested.879ddca6): unanimous again. @kimi-bot-andresmgsl verified the head is a content-identical rebase of the approved956e8cf; the other two re-reviewed the full diff against #101's ACs.Verified at
879ddca6:test/labels-reconcile.test.sh133/133, full suite 15/15 files, shellcheck clean — run independently by the reviewers, not just asserted by the builder. Every CI check on the head is green (mergeStateStatus: CLEAN); the staleblocker:ci-rednoted at the round-1 handoff has since converged off.Post-merge residue: the fix lands in
## Unreleased, so incubator (where the blind-sweep symptom lives, #48/#49) only gets the new degrade reporting once the next release is cut and adopted. When its first blind sweep runs on this build, the loggedread failed:reason is exactly the data #101's disproven-permissions mystery was missing — expect that observation to seed the follow-up diagnosis issue.@danmt this one is yours — requesting your review and setting
state:needs-human.Rebased onto current main (changelog-only conflict with #109's entry); content unchanged, new head
09d2ea7.🔎 reviewing head
09d2ea764fVerdict: approve
Reviewed head
09d2ea764f627623bc18755783408832a04bcd9cagainst #101.Acceptance criteria
gh pr viewlogs two lines: counted line byte-identical +#$n: read failed: …grep -qxFunreadablecounter + wholly-blind firing condition unchanged (exactly one::warning::)^::warning::blind_sweep_warningreworded; tests pin both sampled and empty-reason shapes and fail on the old phrasingno error outputread_failure_reason+ unit assertiontest/labels-reconcile.test.shgreenSpec / decisions
grant checks: read and statuses: readlocks the disproven #95 inference out.UNREADABLEstill exits the per-PR subshell withoutreconcile_pr.Verification
bash test/run.shin a detached worktree at this head: 15/15 files green..github/scripts/shellcheck-all.sh: clean.No blocking issues. Optional nit (non-blocking): whitespace-only stderr becomes spaces rather than
no error outputaftertr '\n' ' '— not in the ACs and not a realghshape I've seen.Approve.
🔎 reviewing head
09d2ea764fApproved at
09d2ea764f627623bc18755783408832a04bcd9c.Reviewed the whole PR against #101. The failed-read path preserves the existing counted line byte-for-byte and still exits without mutation. Its adjacent reason line reports captured stderr through a pure helper that collapses newlines, emits
no error outputfor empty stderr, and truncates overlong reasons to 300 characters plus an ellipsis. The wholly blind warning retains its firing condition, leads with the sampled observed reason, and presentschecks: read/statuses: readonly as a candidate.Verification:
bash test/labels-reconcile.test.sh: 133 passed, 0 failedbash test/run.sh: 15 test files passed, 0 failedbash .github/scripts/shellcheck-all.sh: 33 tracked scripts cleangit diff --check: cleanSince my prior approval at
879ddca6075a70a0bee98da0f00a98322966711c, the reviewed script and test are byte-identical; the head only incorporates main's #109BUILDER.mdand changelog changes. The #101 changelog entry remains correctly placed under the repository's flat## Unreleasedsection. No blocking findings.🔎 reviewing head
09d2ea764fFrozen by directive. danmt ruled on ceremony#111 that every PR unrelated to the changelog change is
blockeduntil fragments reach every repo. This PR is unrelated, so it holds exactly where it is: nothing to rebase, nothing to address, no new round to start. A round already open may finish; its verdicts keep.What it waits on: heavy-duty/ceremony#112 landing in all five repos — the last link for this one is ceremony#118, the 0.2.0 release.
Your claim on #101 is parked, not abandoned. Do not unassign, do not close this PR, and do not rebase it to keep it mergeable — a rebase now burns the round it costs and buys nothing while the freeze stands. Declare the park in a comment on #101.
What to pick up instead: the epic's children. ceremony#113 and ceremony#114 are
readynow; #115 and #116 unblock when #114 lands.Triage lifts this label — nobody else.
Approve head
09d2ea764f.Verified against every acceptance criterion of #101, not just read:
labels: #N: could not read mergeability/checks — left alone this pass), and the reason rides its own#N: read failed: …line. The new test asserts the counted line with the sweep's owngrep -qxFfor both fixture PRs — ran green.blind_sweep_warningstill fires only whenunreadable == total > 0; the wholly-blind probe emits exactly one::warning::(asserted bygrep -c '^::warning::').sampled reason: …and demotes the permissions hint toone candidate is missing checks: read and statuses: read. The must-fail guard on the oldgrant checks: read and statuses: readphrasing is present and would go red on a regression.read_failure_reasonis pure: empty stderr →no error output; multi-line collapses viatr; 400 chars → 300 +…(tested at exactly the 300/304-byte boundary).mktemp, never interleaved into the per-PR output block;|| echo '{}'degrade and the no-mutation path untouched (the "leaves every PR untouched" assertion survives).Verification:
test/labels-reconcile.test.sh(the only test file this PR touches) passes at this head. The full suite shows 4 failing files locally (changelog-armed,drill-recorded,facts,version) — all fail identically on cleanmainbecause this box lacksnpm(I suppliedjqlocally to run the suite at all); none are touched by this diff. GitHub CI at this head: all checks pass (test,self-guards,labels / reconcile, …).The CHANGELOG deviation (flat line instead of
Fixed— this repo's## Unreleasedhas no category headings) is correctly called out in the PR body and matches repo convention. Fine as-is.