Skip to content

fix(reusables): survive large PRs (gh pr diff 406) and symlinked prettier targets#106

Merged
topcoder1 merged 2 commits into
mainfrom
fix/large-pr-file-listing-and-symlink-targets
Jul 3, 2026
Merged

fix(reusables): survive large PRs (gh pr diff 406) and symlinked prettier targets#106
topcoder1 merged 2 commits into
mainfrom
fix/large-pr-file-listing-and-symlink-targets

Conversation

@topcoder1

Copy link
Copy Markdown
Owner

What broke

Two mechanical failure modes surfaced on dotclaude#121 (23,448 insertions / 161 files):

  1. gh pr diff --name-only HTTP-406s past 20k diff lines ("Sorry, the diff exceeded the maximum number of lines (20000)"), killing every reusable that used it as its changed-file source. Failing run: 28676286316.
  2. prettier hard-errors on explicitly specified symlinks ("Explicitly specified pattern 'skills/checkpoint/SKILL.md' is a symbolic link.") — dotclaude tracks symlinked SKILL.md files by convention. Failing run: 28676286301.

What changed

Failure mode 1 — all four consumers of gh pr diff --name-only now list changed files via the paginated files API (gh api repos/{o}/{r}/pulls/{n}/files --paginate), the idiom lint.yml/prettier-autofix.yml already used:

  • claude-author-automerge.yml — risk-tier path scan (the reported failure); also updates the Option-A bypass-label comment, which documented the 406 as unfixable
  • safe-paths-automerge.yml — safe-path classify (same one-liner, was set to 406 on any >20k-line docs PR)
  • pr-classify.yml — its risk:* label is load-bearing for automerge, so fixing automerge alone wouldn't unbrick large PRs
  • codex-review.yml — file list from the API; diff line count from PR additions + deletions (identical to the old gh pr diff | awk count) instead of fetching the diff body

The files-listing endpoint caps at 3000 files. Each gating workflow now handles that cap explicitly instead of silently under-classifying: automerge risk scan fails closed (bypass label remains the human override), safe-paths defers (all_safe=0, like its empty-diff branch), pr-classify and the codex cost gate stay red.

Failure mode 2lint.yml and prettier-autofix.yml (kept-in-sync duplicates) drop symlinks from the explicit target list before invoking prettier. Link targets still get formatted when they appear in the diff themselves; glob-fallback mode is unaffected (prettier skips glob-expanded symlinks on its own). The empty-array assignment is guarded so the block also runs on bash 3.2 (macOS), where the selftest executes it.

Selftests

  • selftest/test_pr_files_listing.sh — bans executable gh pr diff in the reusables and pins the paginated files-API idiom in all six changed-file consumers
  • selftest/test_prettier_symlink_filter.sh — extracts the shipped filter block from the YAML, runs it against a fixture tree (regular file, symlink, dangling symlink), and asserts lint/prettier-autofix haven't drifted
  • selftest/test_workflow_guards.py — wires the host-independent .sh selftests into the pytest self-test path (tests-runner.yml runs uv run pytest -q on this repo's PRs), so these guards are CI-enforced rather than run-manually-only. test_bb_automerge_risk_patterns.sh stays manual-only (needs the local ~/.claude/templates checkout + requests)

Local validation: all four .sh selftests pass, uv run pytest -q 6/6, YAML parse clean on all six edited workflows.

Auto-merge rationale: manual-merge category — PRs to topcoder1/ci-workflows are always manual merge, and this touches .github/workflows/**.
Codex rounds: 3 (round 1: one P2 — codex cost gate could be silently fooled by a truncated 3000+-file listing — fixed; rounds 2–3 clean).

HUMAN_READABLE_SUMMARY: Large PRs (>20k diff lines) were killing the automerge/risk/prettier CI jobs because GitHub refuses to serve huge diffs; the workflows now ask for the file list page-by-page instead, and prettier no longer chokes on symlinked markdown files. New selftests keep both fixes from regressing.

🤖 Generated with Claude Code

topcoder1 and others added 2 commits July 3, 2026 11:46
Two mechanical failure modes observed on topcoder1/dotclaude#121
(23,448 insertions / 161 files):

1. `gh pr diff --name-only` HTTP-406s past 20k diff lines, killing
   every workflow that used it as its changed-file source. Switch
   claude-author-automerge, safe-paths-automerge, pr-classify, and
   codex-review to the paginated files API (the idiom lint.yml /
   prettier-autofix.yml already used). The gating workflows fail
   closed at the API's 3000-file listing cap instead of silently
   under-classifying; codex-review takes its line count from the PR's
   additions+deletions instead of fetching the diff body.

2. prettier hard-errors on explicitly specified symlinks (dotclaude
   tracks symlinked SKILL.md files by convention). lint.yml and
   prettier-autofix.yml now drop symlinks from the explicit target
   list; the guarded empty-array assignment keeps the block bash-3.2
   safe so the selftest can execute it on macOS.

Selftests: test_pr_files_listing.sh bans executable `gh pr diff` in
the reusables and pins the files-API idiom; test_prettier_symlink_filter.sh
extracts the shipped filter block, runs it against a fixture tree, and
guards lint/prettier-autofix drift; test_workflow_guards.py wires the
host-independent .sh selftests into the pytest self-test path so CI
enforces them.

Failing runs: dotclaude runs 28676286316 (automerge) and 28676286301
(prettier-autofix).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex round-1 finding: a truncated file list could hide an
always_review path from codex-gate.mjs and silently skip a required
review. Same guard as the other gating workflows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the risk:blocked Risk class: blocked label Jul 3, 2026
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Risk class: blocked — manual merge required.

This PR touches one of the blocked path categories from .github/risk-paths.yml (Dockerfiles, docker-compose, .github/workflows/**, **/.env*, **/secrets*, infra/, terraform/, k8s/, or the classifier config itself).

Auto-merge is refused by claude-author-automerge.yml. A maintainer should review the diff and click "Squash and merge" themselves.

(This is a policy notice, not a code-quality failure. The classify job itself does not fail — required CI checks remain authoritative for "is the code green.")

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Coverage Floor — mode: enforce

metric value
measured 100.0%
floor (current) 99.0%
target 100.0%
last bumped 2026-05-12

@claude

claude Bot commented Jul 3, 2026

Copy link
Copy Markdown

No issues found. Files-API migration and symlink filter are correctly guarded (3000-cap fail-closed, bash 3.2 empty-array handling), env/repo refs are right, and the new selftests execute the shipped YAML.

@topcoder1 topcoder1 merged commit 530c55c into main Jul 3, 2026
13 checks passed
@topcoder1 topcoder1 deleted the fix/large-pr-file-listing-and-symlink-targets branch July 3, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:blocked Risk class: blocked

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant