fix(loop): census_error surfacing + pr-rebase gh field/fail-closed fixes (issue #187) - #216
Open
robercano-ghbot wants to merge 2 commits into
Open
fix(loop): census_error surfacing + pr-rebase gh field/fail-closed fixes (issue #187)#216robercano-ghbot wants to merge 2 commits into
robercano-ghbot wants to merge 2 commits into
Conversation
Two defects let the autonomous loop fail silently: 1. pr-rebase.sh requested `baseRefOid` in a `gh pr list --json` field list. That field does not exist on `gh pr list` in gh 2.46.0 (it is a GraphQL PullRequest field, surfaced only via `gh pr view`), so gh printed "Unknown JSON field" and exited non-zero on EVERY invocation. loop-census.sh swallowed that via `| grep -c . || true`, pinning rebase_prs=0 forever: the whole #96-part-3 rebase feature was a permanent no-op, plus stderr garbage on every tick. Every PR in this query shares `--base "$base"`, so the PR-level baseRefOid GitHub would report is by definition that base branch's current tip; fetch it once via `gh api repos/OWNER/REPO/commits/BASE --jq .sha` instead. 2. Nothing distinguished "census failed" from "nothing to do". Census now emits a greppable `census_error=<stage>` stdout contract line whenever a gh/parse step genuinely fails or degrades, previously unguarded gh calls no longer abort the script mid-contract under `set -euo pipefail`, loop-tick.sh folds the stages into the tick record's `reason` field, and cockpit.sh renders `reason` in the loop-health panel. A healthy tick emits zero census_error lines and is byte-identical to before. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ion (issue #187) Follow-up hardening on top of 83dec48's census_error surfacing, addressing review-lens findings: - pr-rebase.sh: a failed base-branch-tip fetch now degrades FAIL-CLOSED (checked exit 1, no candidates emitted) instead of fail-open with an empty base_sha — the old behavior would silently re-emit every CONFLICTING PR as a fresh attempt=1 candidate on every tick of a fetch outage, defeating the anti-livelock budget. loop-census.sh's existing exit-code guard now surfaces census_error=rebase_prs for this case. - loop-census.sh: open_prs is now value-validated, not just exit-code checked — a gh SUCCESS with empty/non-numeric stdout (malformed --jq result) previously sailed past the guard and crashed the later `-eq 0` comparison with a bash "integer expression expected" error instead of a clean census_error. - pr-rebase.test.sh's gh stub now validates the --json field list against gh 2.46.0's real allowlist, so a regression that reintroduces the invalid `baseRefOid` field fails the suite instead of silently passing. - loop-daemon.test.sh: run_daemon_once_stripped_path now uses the same curated PATH as every other helper (previously a bare /usr/bin:/bin, which can resolve the host's real systemd-run/systemctl and hang when this suite runs from inside an active pr-loop-driver-* unit). - Test coverage: per-stage census_error fixtures for every remaining census stage (repo-derive, open_pr_branches, open_issue_set, feedback_prs, ci_fix_prs, comment_fix_prs, planned), the open_prs non-numeric-success case, and a ceiling-vs-census_error precedence regression guard (ceiling_reason always wins). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Collaborator
Author
|
fix(loop): census_error surfacing + pr-rebase gh field/fail-closed fixes (issue #187) (not yet reviewed) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #187 (narrowed scope — see below).
What this fixes
Two defects let the autonomous loop fail silently:
pr-rebase.shrequested an invalidgh pr list --jsonfield.baseRefOiddoesn't exist ongh pr listin gh 2.46.0 (GraphQL-only), so gh printed "Unknown JSON field" and exited non-zero on every invocation.loop-census.shsilently swallowed that, pinningrebase_prs=0forever — the Loop: react to post-open PR events — remote CI failure fixing, review-comment convergence, conflict-after-sibling-merge #96-part-3 rebase feature was a permanent no-op. Fixed by fetching the base branch's tip SHA once viagh api repos/OWNER/REPO/commits/BASE(every PR here shares the same base, so this is equivalent to the per-PR field). A failed fetch now degrades fail-closed (checkedexit 1, zero candidates) rather than fail-open with an emptybase_sha— the old fail-open shape would have silently re-emitted every CONFLICTING PR as a freshattempt=1candidate on every tick of an outage, defeating the anti-livelock budget.Nothing distinguished "census failed" from "nothing to do." Census now emits a greppable
census_error=<stage>line whenever a gh/parse step genuinely fails or degrades, for every stage (repo-derive,open_prs— both exit-code and value-validated,open_pr_branches,open_issue_set,feedback_prs,ci_fix_prs,comment_fix_prs,rebase_prs,planned). Previously-unguarded gh calls no longer abort the script mid-contract underset -euo pipefail.loop-tick.shfolds these into the tick record'sreasonfield (yielding to the existingceiling_reasonwhen both fire — verified by a dedicated precedence regression test), andcockpit.shrendersreasonin the loop-health panel. A healthy tick emits zerocensus_errorlines and is byte-identical to before.Scope note
The original issue's items 1–2 (stray
milestoneoutput, priority ordering on milestone-assigned issues) were already resolved by #174's milestone-scoping feature, which landed onmainafter this issue was filed — extensive milestone fixtures already exist inloop-census.test.sh. This PR covers the issue's remaining items (3: never die into a silentaction=none; 4: daemon-path validation) plus thepr-rebase.shbug found while implementing item 3.Validation
GATES_FILE=self/gates.json bash .claude/scripts/gate.sh build✅GATES_FILE=self/gates.json bash .claude/scripts/gate.sh lint✅self/smoke-fanout.sh(end-to-end fan-out scaffold) ✅*.test.shrun individually — all pass:loop-census.test.sh(147),pr-rebase.test.sh(17),loop-ceilings.test.sh(53),loop-daemon.test.sh(113),cockpit.test.sh(131),loop-tick.test.sh(95).gate.sh test(which loops over every*.test.shsequentially) hangs in this sandboxed environment when it reachesloop-daemon.test.sh— confirmed to reproduce identically on unmodifiedmain, i.e. a pre-existing environmental flake (resource contention under the full-suite sequential run), not something this PR introduces. Gates were verified by running build/lint/smoke-fanout plus every touched test file standalone instead (each passes cleanly in isolation).Daemon-path verification (issue's item 4)
Not independently re-verified end-to-end in this session (the daemon's own re-attach/reachability path is exactly what the sandboxed-hang note above is about — see caveat). The census_error contract itself is covered by the per-stage fixtures above; a live tick's dispatch behavior should be spot-checked via the cockpit after merge.
🤖 Generated with Claude Code