Skip to content

CI shepherd: ci_digest (triage + error lines + local repro) and ci_shepherd (merge / rerun / one note per head) (Part of #4790) - #4819

Merged
squid-protocol merged 2 commits into
mainfrom
feat/4790-ci-digest
Oct 9, 2026
Merged

squid-protocol merged 2 commits into
mainfrom
feat/4790-ci-digest

Conversation

@squid-protocol

@squid-protocol squid-protocol commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Steps 1–2 of #4790. Nobody (person or model) should read a raw CI log, wait on CI, or re-push to find out whether a fix works.

1. tests/tools/ci_digest.py N (also pr_check.py N --digest). Per failed check on the PR head:

2. tests/tools/box/ci_shepherd.py replaces handoffs/tools/merge_watch.sh + merge_train.sh. It keeps one queue, run by one process (an flock run lock, so it never matches itself in pgrep like the old watchers did). Each pass:

  • a merged or closed PR leaves the queue;
  • --after waits for a stacked PR's base;
  • green + mergeable → merge (pr_check.merge, pinned to the head; crucible pin synced);
  • pending → wait;
  • infra/flake → gh run rerun --failed once per (head, check);
  • dirty → one note per head;
  • real → one comment per head with the digest, and $CI_SHEPHERD_FIXER N digest.json if set.
    A new push resets the once-per-head memory. Census history stays out (it writes a committed file, so it is the evidence bot's job).

Live: the digest on #4818 triaged its action_required as dirty (it was real before the fix). The shepherd is running for the current queue (#4811 → #4780/#4810/#4818, #4819) from this branch.

Tests: test_ci_digest (6) + test_ci_shepherd (7, fake gh) + test_pr_check: 21 passed. Ruff and mypy audits clean; pr_gates --fast 5/5. No ledger, evidence or golden files touched.

Next (#4790 step 3): a fixer hook that runs agy or Claude on the digest's repro; auto re-merge when only generated files conflict.

🤖 Generated with Claude Code

… pr_check --digest (Part of #4790)

Step 1 of the CI shepherd. Nobody -- person or model -- should read a raw CI log or wait on CI to learn whether a fix
works. `ci_digest.py N` (and `pr_check.py N --digest`) gives, per failed check on the PR head:
- triage: dirty (action_required on a conflicting PR: merge main, regenerate generated files), infra (cancelled,
  startup failure, lost runner, disk, rate limit: rerun once), flake (only #4477's wall-clock tests failed: rerun
  once), real (a fixer's job);
- the job log's error lines and last 40 lines, ANSI codes and timestamps stripped;
- the local repro: pr_gates' own gate / ratchet names where one exists, the failing pytest node ids, the det cases
  not proven; checks with no local equivalent say so.
Tried live on #4818: its one "failure" was action_required on a dirty PR, now triaged dirty, not real.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread tests/tools/ci_digest.py
from typing import Any

sys.path.insert(0, str(Path(__file__).resolve().parent))
import pr_check # noqa: E402
Comment thread tests/tools/pr_check.py
res = check(args.number, api)
print(json.dumps(res, indent=1) if args.json else report(res))
if args.digest and res["checks"]["failed"]:
import ci_digest # noqa: PLC0415 -- fetches job logs; only when asked
…flakes once, one note per head (Part of #4790)

Step 2 of #4790, replacing handoffs/tools/merge_watch.sh + merge_train.sh. Per queued PR each pass:
merged/closed leaves; --after waits for its base; green + mergeable is merged (pr_check.merge, pinned to the head,
crucible pin synced); pending waits; infra/flake failures are rerun ONCE per (head SHA, check); a dirty PR gets one
note; a real failure gets one comment with ci_digest's digest (error lines, log tail, local repro), and
$CI_SHEPHERD_FIXER, if set, is started with the PR and the digest file. A new push resets the once-per-head memory.
One shepherd at a time via flock on a run lock (never a pgrep that matches itself); add/drop edit the queue between
passes under a state lock. Census history stays out (it writes a committed file: the evidence bot's job).
ci_digest entries now carry run_id / job_id. Tests: fake gh, 7 cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@squid-protocol squid-protocol changed the title ci_digest: per failed check, triage + error lines + local repro; pr_check --digest (Part of #4790) CI shepherd: ci_digest (triage + error lines + local repro) and ci_shepherd (merge / rerun / one note per head) (Part of #4790) Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

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.

2 participants