Skip to content

ADR-309: implement rebase mechanic (rebase_onto) - #80

Merged
jodavis merged 3 commits into
feature/ADR-296-concurrencyfrom
dev/claude/ADR-309
Jul 22, 2026
Merged

ADR-309: implement rebase mechanic (rebase_onto)#80
jodavis merged 3 commits into
feature/ADR-296-concurrencyfrom
dev/claude/ADR-309

Conversation

@jodavis-claude

Copy link
Copy Markdown
Collaborator

Work item: ADR-309

Implement the rebase mechanic: a standalone rebase_onto(working_branch, new_base, worktree) -> Literal["rebased", "conflict"] function that fetches, rebases a working branch onto an updated base, and force-pushes with lease on success. This is the first git-operation primitive that later Concurrent Development spec tasks (dev-team:watch-pr, resolve-rebase-conflict, the base-branch resolver) will build on.

Changes

  • Added plugins/dev-team/skills/workflow-orchestrate/scripts/rebase_mechanic.pyrebase_onto(working_branch, new_base, worktree). Fetches origin in worktree, checks out working_branch, rebases onto the freshly-fetched origin/<new_base>; on success force-pushes with lease (git push --force-with-lease origin <working_branch>) and returns "rebased"; on rebase failure, leaves the rebase in progress untouched (no --continue/--skip/--abort) and returns "conflict" without pushing.
  • All git subprocess calls go through a private _run_git() helper that always passes cwd=worktree, timeout=30, and check=True — no module-level REPO_ROOT, per the brief's explicit-worktree-parameter requirement.
  • Added plugins/dev-team/skills/workflow-orchestrate/scripts/test_rebase_mechanic.py — pytest suite building real local bare "origin" repos and working clones (no git mocking) covering: clean rebase, genuine conflict, freshly-fetched base overriding a stale local ref, self-checkout when the worktree starts on a different branch, and fetch failure propagating as subprocess.CalledProcessError.

Design decisions

  • Rebases onto origin/<new_base> (the freshly-fetched remote-tracking ref), not the bare local branch name, so a stale local new_base branch can't cause an outdated rebase target.
  • Any non-zero exit from the git rebase step is treated as "conflict" — no further disambiguation (e.g. dirty working tree vs. genuine content conflict) is attempted, since both exit-criteria scenarios are satisfied by this simpler behavior. The conflict-path test independently confirms a real rebase-in-progress marker (.git/rebase-merge/.git/rebase-apply) is left behind. Flagged as a known, non-blocking ambiguity for reviewers.
  • rebase_onto performs its own checkout of working_branch rather than assuming the caller's worktree is already on it, since it will later be invoked from a long-lived dev-team:watch-pr monitor whose current branch isn't guaranteed.
  • No main() CLI wrapper shipped — no current skill or script invokes the mechanic yet; deferred to whichever later task (dev-team:watch-pr) first needs to call it via Bash.

Testing completed

  • 5 new pytest tests, all passing, using real fixture git repos (bare "origin" + working clones), no git mocking.
  • Full plugins/dev-team/skills/workflow-orchestrate/scripts/ suite (165 tests) passes with no regressions.

…ed — clean rebase (returns "rebased", verified force-pushed-with-lease reaches origin), genuine conflict (returns "conflict", rebase-in-progress marker left in place, no push to origin), fetch making `origin/<new_base>` the rebase source of truth over a stale local ref, self-checkout of `working_branch` when the worktree starts on a different branch, and non-conflict git failures (fetch) propagating as `CalledProcessError` rather than being swallowed. No logging, no CLI wrapper, and no additional invalid-input branches in scope for this component.)
@github-actions

Copy link
Copy Markdown

build-and-test: Python test results

Status: ✅ Passed

Test log

@jodavis-claude jodavis-claude left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against the ADR-309 task brief and _spec_ConcurrentDevelopment.md. All five exit criteria are met: rebase_onto(working_branch, new_base, worktree) -> Literal["rebased", "conflict"] fetches, rebases onto the freshly-fetched origin/<new_base>, force-pushes with lease on success, and leaves a conflicted rebase untouched (no --continue/--skip/--abort) on failure. Tests build real fixture git repos (bare origin + working clone) covering clean rebase, genuine conflict, stale-local-base-vs-fresh-fetch, self-checkout onto a different starting branch, and fetch-failure propagation. Ran the suite locally: 5/5 new tests pass, and the full workflow-orchestrate scripts suite (165 tests) passes with no regressions. CONTRIBUTING.md guidelines are followed: timeout= is passed on every subprocess.run, CalledProcessError is never silently swallowed (fetch/checkout/push propagate; only the rebase step's failure is deliberately reinterpreted as the business outcome "conflict"), and test naming/AAA structure match convention. Two small non-blocking suggestions left inline below. Approving.

Comment thread plugins/dev-team/skills/workflow-orchestrate/scripts/rebase_mechanic.py Outdated
Comment thread plugins/dev-team/skills/workflow-orchestrate/scripts/test_rebase_mechanic.py Outdated
@jodavis-claude
jodavis-claude marked this pull request as ready for review July 22, 2026 02:12
@jodavis-claude
jodavis-claude requested a review from jodavis July 22, 2026 02:12
@jodavis
jodavis enabled auto-merge (squash) July 22, 2026 03:26
Review comment: the caught CalledProcessError from the rebase step had no
stderr/stdout to inspect, so a non-content rebase-start failure (e.g. a dirty
working tree) was indistinguishable from a genuine conflict. Capture the
rebase subprocess output and log e.stderr at debug level before returning
"conflict", giving a future caller something to diagnose with.
Review comment: the stale-local-base-vs-fresh-fetch test only checked for
tundra.txt's presence post-rebase, not the function's return value. Capture
and assert result == "rebased" for a stronger, self-documenting assertion.
@jodavis
jodavis merged commit 31d2675 into feature/ADR-296-concurrency Jul 22, 2026
3 checks passed
@jodavis
jodavis deleted the dev/claude/ADR-309 branch July 22, 2026 03:28
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.

3 participants