ADR-312: add resolve-rebase-conflict skill and fixture dry-run harness - #83
Merged
Merged
Conversation
…rness resolve-rebase-conflict is agent-skill prose (Testable per component-taxonomy, not a pure function): given a rebase already left in progress with conflicts and the task's own brief/spec context, it reads each conflicted file's hunks, resolves only what the context makes unambiguous, stages them, and drives git rebase --continue to completion. Reports "resolved" or "unresolved"; never runs git push or git rebase --abort itself (the caller, dev-team:watch-pr, does both as appropriate). Verification follows the taxonomy's "whatever mechanism actually fits" for prose Testable components (same precedent as ADR-319's harvest-playbook): a scripted fixture-scenario harness at plugins/dev-team/fixtures/resolve-rebase-conflict/ builds three real git repos with a genuine rebase conflict already in progress (via rebase_mechanic.rebase_onto(), following test_rebase_mechanic.py's bare-origin-plus-clone construction pattern): - single-file: one CHANGELOG.md hunk, resolvable from task context - multi-file: CHANGELOG.md + a JSON settings file conflict together (same commit), both resolvable from task context - unresolvable: a numeric setting both branches changed to different, equally-plausible values with no stated target — must decline to guess build_fixture.py builds each scenario; test_build_fixture.py (18 tests, all passing) confirms each one produces exactly the conflict it claims to. RUN.md documents the on-demand (non-CI) run/grade procedure for the judgment-shaped part of this check. Dry-ran the finished skill against all three scenarios via a fresh subagent blind to this authoring context: single-file and multi-file both correctly merged both sides' content and reported "resolved" with a clean working tree; unresolvable correctly stopped without editing anything and reported "unresolved", citing the missing target value as the reason it couldn't proceed. No production Python file changes needed — rebase_mechanic.py is untouched per the task brief.
build-and-test: Python test resultsStatus: ✅ Passed Test log |
jodavis-claude
commented
Jul 23, 2026
jodavis-claude
left a comment
Collaborator
Author
There was a problem hiding this comment.
Reviewed against the ADR-312 task brief and _spec_ConcurrentDevelopment.md (lines 503-526, 881-899). All five exit criteria are met:
SKILL.mdimplements the read-hunks / resolve-from-context / stage /git rebase --continueloop, stopping and reporting"unresolved"without partial edits when confidence is lacking (steps 1-6).- Never runs
git pushorgit rebase --abortitself — explicitly deferred to the caller. - The three-scenario fixture harness (
build_fixture.py,test_build_fixture.py,RUN.md) matches the spec's objective bar (single-file/single-hunk, multi-file, and a genuinely-unresolvable case), modeled closely onfixtures/playbook-harvestingandtest_rebase_mechanic.py's real-git-repo construction pattern. - Ran
test_build_fixture.pylocally: all 18 tests pass. - The prose correctly classifies as
Testableagent-skill-prose percomponent-taxonomy, and the direct-implementation-plus-dry-run-harness approach (bypassingimplement-tdd) follows the ADR-319 precedent as flagged in the brief's own known-ambiguity note.
No Priority 1-4 issues found. One minor style suggestion posted inline. Also noting (non-blocking): _run_git is now duplicated with near-identical bodies across rebase_mechanic.py, test_rebase_mechanic.py, and this PR's build_fixture.py/test_build_fixture.py — all test/fixture-infra code so not required by component-taxonomy, but could be worth consolidating into a shared test-helper module if a fourth copy shows up.
Approving.
jodavis-claude
marked this pull request as ready for review
July 23, 2026 06:12
jodavis
approved these changes
Jul 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Work item
ADR-312: Build the
resolve-rebase-conflictskill — given a rebase already left in progress with conflicts, it reads the conflicting hunks using the task's brief/spec context, resolves them, stages them (git add), and repeatsgit rebase --continueuntil the rebase completes cleanly or it hits a conflict it cannot resolve with confidence, reporting"resolved"or"unresolved", and never pushing itself.Changes
plugins/dev-team/skills/resolve-rebase-conflict/SKILL.md(new) — the skill itself: agent-skill prose (Testable percomponent-taxonomy, not a pure function) invoked by the Developer agent in the current worktree oncerebase_onto()has already left a rebase in progress with conflicts. Steps: (1) confirm a rebase is in progress; (2) enumerate every conflicted file (git status --porcelain=v1); (3) read each conflicted file's<<<<<<</=======/>>>>>>>regions; (4) resolve each region only when the task's brief/spec context makes the final content unambiguous, otherwise stop immediately and report"unresolved"; (5)git add+GIT_EDITOR=true git rebase --continue, looping back to step 2 if the next commit also conflicts; (6) report"resolved"(clean tree, no rebase in progress) or"unresolved"— never runsgit pushorgit rebase --abortitself.plugins/dev-team/fixtures/resolve-rebase-conflict/build_fixture.py(new) — fixture builder for the dry-run harness. Builds one of three named scenarios (single-file,multi-file,unresolvable) into a fresh throwaway git working clone, left mid-rebase with a real conflict already in progress, reusingrebase_mechanic.rebase_onto()against two real diverging branches.plugins/dev-team/fixtures/resolve-rebase-conflict/test_build_fixture.py(new) — 18 pytest tests confirming each scenario builder produces exactly the conflict state it claims to.plugins/dev-team/fixtures/resolve-rebase-conflict/RUN.md(new) — run procedure: fixture contents, invocation model (on-demand, not CI), materialize/run/grade steps for each of the three scenarios.No production Python files were modified —
rebase_mechanic.pyandrebase_onto()are untouched, as neither needed changes for this task.Design decisions
implement-tdd, per the ADR-319 (harvest-playbook) precedent:implement-tdd's tester/implementer/refactorer loop is built around AAA pytest assertions, which doesn't fit prose that makes judgment calls. Instead followed the same red/green stand-in — author the fixture harness first, then the prose, then grade the prose against the harness.single-file/multi-file's shared file, a JSONmax_retriesvalue conflict (brief states an explicit final target) formulti-file's second file, and a JSONbackoff_multipliervalue conflict where the brief states only intent, never a target value, forunresolvable.multi-file's two files conflict from a single commit on each side (not two separate commits), since git auto-merges non-overlapping single-line edits across separate commits during a rebase — both files had to be touched in the same commit on both branches to guarantee a simultaneous conflict.Testing completed
plugins/dev-team/fixtures/resolve-rebase-conflict/test_build_fixture.py— all 18 pytest tests pass, confirming each fixture scenario builder produces the exact conflict state (files, rebase-in-progress state, expected outcome, task-brief content) it claims to.SKILL.mdtext, the materialized worktree, and the scenario's task-brief text. All three passed:single-fileandmulti-filemerged correctly and reported"resolved"with a clean tree;unresolvablemade no edits and reported"unresolved", explicitly citing the missing target value as the reason it stopped rather than guessing.Wrapper/Orchestratorcomponent and no new externally-observable entry point — every component in scope isTestable, so verification followed the fixture-scenario harness instead.