Skip to content

feat(axi): add per-run PR base branch via --base-branch - #861

Open
lakshyads05 wants to merge 3 commits into
kunchenguid:mainfrom
lakshyads05:fm/nm-axi-run-base-branch-flag-b6
Open

feat(axi): add per-run PR base branch via --base-branch#861
lakshyads05 wants to merge 3 commits into
kunchenguid:mainfrom
lakshyads05:fm/nm-axi-run-base-branch-flag-b6

Conversation

@lakshyads05

Copy link
Copy Markdown
# Summary
- Add `no-mistakes axi run --base-branch <branch>` to open a PR against a named integration branch for one run only
- Persist the choice on the run record so rebase, PR creation, and CI honor it consistently across resume and rerun
- Validate branch names and remote existence before starting a run

# Changes

## CLI and daemon
- New `--base-branch` flag on `axi run` (and `rerun` for explicit override); value travels through git push options and IPC like intent/skip
- `runs.pr_base_branch` column stores the per-run override for the whole pipeline lifetime

## Pipeline
- `effectivePRBaseBranch` precedence: per-run flag > `pr.base_branch` > repository default
- PR step uses the shared resolver (including skip-when-branch-equals-base)
- Existing PR forge base still wins for CI/ci_fix repair paths (unchanged)

# Why
Teams working several tasks in one repository often need each validation run to target a different epic or feature branch. Repo-wide `pr.base_branch` cannot express that without committing config per task, and retargeting after the fact wastes CI and freezes the wrong PR body. A per-run operator flag extends the existing mechanism without changing default behavior when omitted.

## Precedence
1. Per-run `--base-branch` (operator CLI / push option)
2. Repo `pr.base_branch` (trusted default-branch config)
3. Repository forge default branch
4. For CI merge-conflict repair on an **existing** PR: live forge base from the open PR still wins (unchanged)

## Trust boundary
`pr.base_branch` stays trusted default-branch-only gate control. The new flag is operator-supplied at run start—the same trust path as `--intent` and `--skip`—and does not let pushed branch content choose the integration target.

# Test plan
- [x] `go test -race` on touched packages (`internal/cli`, `internal/daemon`, `internal/db`, `internal/pipeline/steps`) passes
- [x] `make lint` passes
- [ ] Full `go test -race ./...` on maintainer CI (local macOS run hit unrelated `internal/branchsync` git segfault flakes)
- [ ] `axi run --base-branch epic/foo` opens PR against `epic/foo` on a repo with concurrent epic branches

Let axi run target an integration branch for one run without changing
repo config, persisting the choice on the run record for rebase, PR, and CI.
@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (3): Last reviewed commit: "fix(pr): retarget Gitea PRs and fail clo..." | Re-trigger Greptile

Honor a per-run --base-branch on an already-open PR, and refuse
reattach when that flag would silently drop against an in-flight run.
@lakshyads05

Copy link
Copy Markdown
Author

Addressed both review notes in 2619601:

  1. Existing PR base. A per-run --base-branch that disagrees with an already-open PR now retargets that PR (gh pr edit --base / glab mr update --target-branch) before updating title and body. Repo-config pr.base_branch changes still do not retarget, so an existing PR is updated in place rather than duplicated.

  2. Reattach. axi run --base-branch against an in-flight run now refuses when the flag would be discarded. Matching (or omitted) --base-branch still reattaches.

Comment thread internal/pipeline/steps/pr.go
@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate:

First look at HEAD 26196012 (--base-branch CLI/IPC/DB, effectivePRBaseBranch, existing-PR retarget, reattach refuse-on-mismatch). First-time fork CI approved (CI / docs / Guard).

Diff review: opt-in operator flag on the same trust path as --intent/--skip; omitted = prior behavior. Pushed branch content cannot choose the base. Greptile's earlier notes on retarget + silent discard look addressed in this head. Not a default gate-pass change. Waiting on hosted CI + green Greptile on this SHA before merge.

VISION.md:

  • R1: aligns (opt-in per-run targeting; core pipeline order unchanged).
  • R2: aligns.
  • R3: aligns (operator judgment for integration target).
  • R4: aligns (trust boundary stated; forge base for existing-PR CI repair unchanged when no override).
  • R5: aligns.
  • R6: aligns.
  • R7: aligns.

An unknown live base on a provider that cannot retarget used to
succeed, so a per-run --base-branch left the forge PR on the old
target. Gitea now copies the listed base and PATCHes via tea api.
@lakshyads05

Copy link
Copy Markdown
Author

Addressed the Greptile P1 in 9d7ae7c:

  • Silent skip. A per-run --base-branch on a provider that cannot retarget now fails closed, including when the live forge base is unread. Title/body are no longer rewritten against a base the PR did not move to.
  • Gitea. FindPR copies the listed base, and SetPRBaseBranch PATCHes via tea api (tea pulls edit has no --base). GitHub and GitLab retarget paths are unchanged.

@kunchenguid

Copy link
Copy Markdown
Owner

Speaking as Kun's firstmate:

Re-triaged HEAD 9d7ae7c7 after your Gitea/fail-closed retarget follow-up. Greptile 5/5. Fork CI re-approved on this SHA (was action_required again). Opt-in --base-branch; providers that cannot retarget fail closed. Waiting on hosted CI before merge.

VISION.md:

  • R1–R7: aligns (unchanged vs prior; fail-closed retarget strengthens R5).

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