Skip to content

feat: brain-autofix reusable workflows (auto-rebase + auto-fix-tests)#2

Merged
rabble merged 2 commits into
mainfrom
feat/auto-rebase-and-autofix-workflows
May 8, 2026
Merged

feat: brain-autofix reusable workflows (auto-rebase + auto-fix-tests)#2
rabble merged 2 commits into
mainfrom
feat/auto-rebase-and-autofix-workflows

Conversation

@rabble
Copy link
Copy Markdown
Member

@rabble rabble commented May 8, 2026

Summary

Two opt-in reusable workflows that solve the two pain points from chat: tests failing on PRs, and PRs not merging cleanly with origin/main.

`auto-rebase` — pure git, no LLM

On every `pull_request.synchronize`/`labeled`/`opened`, updates the PR branch from base. Resolves trivial conflicts automatically:

  • Lockfiles (pnpm/npm/yarn/cargo/go.sum) → regenerated via the relevant tool
  • Generated artifacts (`dist/`, `build/`, `.next/`, `.turbo/`, `node_modules/`) → PR-side wins, rebuilt next CI

Any non-trivial conflict aborts cleanly with a PR comment listing files needing human help.

`auto-fix-tests` — Claude Code in runner, opt-in via label

Triggered by:

  • PR `auto-fix` label, OR
  • comment `/brain-fix` on a PR, OR
  • `workflow_run` failure on a PR carrying the `auto-fix` label

Spins up Claude Code in the runner with a tight prompt + the failing test output, lets it make ONE focused fix, re-runs tests once to verify, only pushes if they pass.

Four guardrails (per the agreed list)

  1. Loop-break. Every brain-autofix commit carries `[skip-autofix]`. The workflow bails out when it sees that trailer on the last commit, so it never reacts to its own pushes.
  2. Wrong fix masking real bug. Explicit `fix: [brain-autofix] ...` commit + PR comment saying "human review still required."
  3. Secret exfiltration. `ANTHROPIC_API_KEY` flows via `secrets:` not `env:`, never echoed. Repos with sensitive secrets opt out via `.brain-autofix.disabled` at repo root.
  4. Cost. Auto-rebase is cheap (no LLM); auto-fix-tests is opt-in only via the `auto-fix` label.

Plus defense-in-depth:

  • `do-not-touch` / `wip` PR labels skip both workflows
  • `.brain-autofix.disabled` repo file skips both workflows
  • Idempotency tag (auto-fix-tests) skips re-fires for the same `head_sha`
  • Workflows refuse to push to the default branch
  • `--force-with-lease` only in rebase mode; merge mode is fast-forward (default)

Caller usage

See README — each repo adds ~10 lines.

Test plan

  • Merge this; opt one repo (probably divine-brain itself) into both workflows; observe behavior on a real PR
  • Confirm `.brain-autofix.disabled` opt-out works
  • Confirm the `[skip-autofix]` trailer breaks the loop after a brain-autofix commit

rabble added 2 commits May 8, 2026 19:08
Two opt-in reusable workflows that complement the divine-brain
pipeline. Each repo opts in by adding ~10 lines of caller workflow;
opts out per-PR via label or per-repo via a `.brain-autofix.disabled`
file.

auto-rebase.yml — pure-git, no LLM. On pull_request synchronize /
labeled / opened / reopened / ready_for_review:
  - skip if PR labeled do-not-touch or wip
  - skip if .brain-autofix.disabled at repo root
  - skip if last commit carries [skip-autofix] (loop-break)
  - merge or rebase from base; auto-resolve trivial conflicts:
      lockfiles (pnpm/npm/yarn/cargo/go) regenerated via the relevant
      tool; generated artifacts (dist/, build/, .next/, .turbo/) kept
      PR-side and rebuilt on next CI
  - any non-trivial conflict aborts cleanly with a PR comment listing
    files that need human help
  - push back to PR branch with [brain-autofix][skip-autofix] trailer
  - --force-with-lease only in rebase mode; merge mode is fast-forward
  - explicit refusal to push to the repo default branch

auto-fix-tests.yml — Claude Code in runner. Triggered by:
  - pull_request labeled (label = `auto-fix`), OR
  - issue_comment containing `/brain-fix` from a maintainer, OR
  - workflow_run completed=failure on a PR carrying the `auto-fix` label
  Then:
  - all the same skip checks as auto-rebase plus an idempotency tag
    keyed by head_sha (max 1 attempt per push)
  - install deps, capture failing test output (last 8KB), hand to
    Claude Code with --max-turns and a tight system prompt
  - re-run tests; ONLY push if they now pass
  - commit with [brain-autofix][skip-autofix] trailer + a note saying
    human review still required (auto-fix may have masked a real bug)
  - posts a PR comment with the agent's run log on success / failure /
    no-changes paths

ANTHROPIC_API_KEY flows via `secrets:` not `env:` and is never echoed.

README documents opt-in for both, including the caller-workflow
snippets and the four guardrail mechanisms (loop-break trailer,
disable file, label opt-out, idempotency tag).
Found four bugs reviewing the previous commit with fresh eyes:

1. Lockfile regen could commit a broken file. If the repo's package
   manager (pnpm/yarn/cargo/go) wasn't on the runner, the regen would
   silently fail, but my code still `git add`ed the file with
   conflict markers in it. Fixed via a `regen()` helper that:
     - early-returns "unresolved" when the tool isn't on PATH
     - sanity-checks the regenerated file for `<<<<<<<` / `=======`
       markers and treats their presence as failure
     - captures regen output to /tmp/regen.log for the PR comment

2. Fork PR push-back fails silently. `secrets.GITHUB_TOKEN` can't
   write to a fork branch. Both workflows now skip cleanly with a
   "PR is from a fork, cannot push back" reason. Documented in README.

3. Missing concurrency. Two close webhooks (labeled right after
   synchronize) raced. Both workflows now have a `concurrency:` group
   keyed on the PR number with `cancel-in-progress: true` — the
   later event has fresher info anyway.

4. README caller example mentioned `push: branches: [main]`, but the
   v0 job filter only accepts pull_request events. Removed the
   misleading example and added a "Note on triggers" callout.
@rabble rabble merged commit eb1cebf into main May 8, 2026
2 checks passed
@rabble rabble deleted the feat/auto-rebase-and-autofix-workflows branch May 8, 2026 07:23
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.

1 participant