diff --git a/.beads/formulas/mol-polecat-conflict-resolve.formula.toml b/.beads/formulas/mol-polecat-conflict-resolve.formula.toml new file mode 100644 index 00000000..127e5078 --- /dev/null +++ b/.beads/formulas/mol-polecat-conflict-resolve.formula.toml @@ -0,0 +1,385 @@ +description = """ +Conflict resolution workflow for polecats handling merge conflicts. + +This molecule guides a polecat through resolving merge conflicts for a previously +submitted MR that failed to rebase. The workflow uses the merge-slot gate to +serialize conflict resolution and prevent racing. + +## Task Recognition + +Conflict resolution tasks are created by the Refinery when a mechanical rebase +fails. They are identified by: +- Title prefix: "Resolve merge conflicts:" +- Metadata fields in description: Original MR, Branch, Conflict SHA + +## Key Differences from Regular Polecat Work + +| Aspect | Regular Work | Conflict Resolution | +|--------|--------------|---------------------| +| Branch source | Create new branch | Checkout existing MR branch | +| Merge path | Submit to queue via `gt done` | Push directly to main | +| Issue closure | Refinery closes after merge | Close MR bead yourself | +| Serialization | None | Merge-slot gate required | + +## Variables + +| Variable | Source | Description | +|----------|--------|-------------| +| task | hook_bead | The conflict-resolution task ID | +| original_mr | task metadata | The MR bead that had conflicts | +| branch | task metadata | The branch to rebase | +| conflict_sha | task metadata | Main SHA when conflict occurred | + +## Failure Modes + +| Situation | Action | +|-----------|--------| +| Merge slot held | Wait (--wait flag adds you to queue) | +| Complex conflicts | Use judgment; escalate if unsure | +| Tests fail after resolve | Fix them before pushing | +| Resolution unclear | Read original issue for context |""" +formula = "mol-polecat-conflict-resolve" +version = 1 + +[[steps]] +id = "load-task" +title = "Load task and extract metadata" +description = """ +Initialize your session and understand the conflict resolution task. + +**1. Prime your environment:** +```bash +gt prime # Load role context +bd prime # Load beads context +``` + +**2. Check your hook:** +```bash +gt hook # Shows your pinned molecule and hook_bead +``` + +**3. Read the conflict resolution task:** +```bash +bd show {{task}} +``` + +**4. Extract metadata from the task description:** + +The task description contains structured metadata: +``` +## Metadata +- Original MR: +- Branch: +- Conflict with: @ +- Original issue: +- Retry count: +``` + +Parse and note: +- **original_mr**: The MR bead ID (you'll close this after merge) +- **branch**: The branch to checkout and rebase +- **source_issue**: The original work issue (read for context if needed) +- **retry_count**: How many times this has been attempted + +**5. Understand the context:** + +If the conflict seems complex, read the original issue: +```bash +bd show # What was the original work? +``` + +**Exit criteria:** You have all metadata and understand the conflict context.""" + +[[steps]] +id = "acquire-slot" +title = "Acquire merge slot" +needs = ["load-task"] +description = """ +Acquire exclusive access to the merge slot before proceeding. + +The merge slot prevents multiple conflict-resolution polecats from racing +to push to main simultaneously (the "Monkey Knife Fight" problem). + +**1. Check slot availability:** +```bash +bd merge-slot check --json +``` + +**2. Acquire the slot:** +```bash +bd merge-slot acquire --holder=$(whoami) --wait --json +``` + +The `--wait` flag adds you to the waiters queue if the slot is held. +You'll proceed when the current holder releases. + +**3. Verify acquisition:** +The output should show: +```json +{"available": false, "holder": "your-name", ...} +``` + +If you're in the waiters list, wait for the holder to release. Check +periodically: +```bash +bd merge-slot check --json +``` + +**Important:** Once you have the slot, complete the workflow promptly. +Other polecats may be waiting. + +**Exit criteria:** You hold the merge slot exclusively.""" + +[[steps]] +id = "checkout-branch" +title = "Checkout and prepare the conflicting branch" +needs = ["acquire-slot"] +description = """ +Fetch and checkout the branch that needs conflict resolution. + +**1. Ensure clean workspace:** +```bash +git status # Should be clean +git stash list # Should be empty +``` + +If dirty, clean up first (stash or discard). + +**2. Fetch latest state:** +```bash +git fetch origin +git fetch origin {{branch}}:refs/remotes/origin/{{branch}} +``` + +**3. Checkout the branch:** +```bash +git checkout -b temp-resolve origin/{{branch}} +``` + +Using `temp-resolve` as the local branch name keeps things clear. + +**4. Verify the branch state:** +```bash +git log --oneline -5 # Recent commits +git log origin/main..HEAD # Commits not on main +``` + +**Exit criteria:** On temp-resolve branch, ready to rebase.""" + +[[steps]] +id = "rebase-resolve" +title = "Rebase onto main and resolve conflicts" +needs = ["checkout-branch"] +description = """ +Perform the rebase and resolve any conflicts. + +**1. Start the rebase:** +```bash +git rebase origin/main +``` + +**2. If conflicts occur:** + +For each conflicted file: +```bash +git status # See conflicted files +git diff # See conflict markers +``` + +**Resolve using your judgment:** +- Read both versions carefully +- Consider the original intent (from source issue) +- If the MR was adding a feature, preserve that addition +- If the MR was fixing a bug, ensure the fix remains + +**After resolving each file:** +```bash +git add +git rebase --continue +``` + +**3. If stuck on a conflict:** +- Read the original issue for context: `bd show ` +- If still unclear, escalate to Witness: + ```bash + gt mail send /witness -s "HELP: Complex conflict" -m "Task: {{task}} + File: + Issue: Cannot determine correct resolution" + ``` + +**4. Verify rebase success:** +```bash +git log --oneline origin/main..HEAD # Your commits rebased +git status # Clean working tree +``` + +**Exit criteria:** Branch successfully rebased onto origin/main.""" + +[[steps]] +id = "run-tests" +title = "Run tests to verify resolution" +needs = ["rebase-resolve"] +description = """ +Verify the resolution doesn't break anything. + +**1. Run the test suite:** +```bash +go test ./... # Or appropriate test command +``` + +**ALL TESTS MUST PASS.** Do not push with failures. + +**2. If tests fail:** +- Determine if it's a resolution error or pre-existing +- If your resolution broke something: fix it +- If pre-existing: file a bead, but still must fix before pushing + +```bash +# Quick check: does main pass? +git stash +git checkout origin/main +go test ./... +git checkout temp-resolve +git stash pop +``` + +**3. Run build check:** +```bash +go build ./... +``` + +**Exit criteria:** All tests pass, build succeeds.""" + +[[steps]] +id = "push-to-main" +title = "Push resolved changes directly to main" +needs = ["run-tests"] +description = """ +Push the resolved branch directly to main. + +**Important:** Unlike normal polecat work, conflict resolution pushes directly +to main. This is because: +1. The original MR was already reviewed/approved by being in the queue +2. We're just resolving conflicts, not adding new functionality +3. Going back through the queue would create an infinite loop + +**1. Rebase one more time (in case main moved):** +```bash +git fetch origin +git rebase origin/main +``` + +If new conflicts: resolve them (return to rebase-resolve step). + +**2. Push to main:** +```bash +git push origin temp-resolve:main +``` + +**3. Verify the push:** +```bash +git log origin/main --oneline -3 # Your commits should be there +``` + +**Exit criteria:** Changes are on origin/main.""" + +[[steps]] +id = "close-beads" +title = "Close the original MR bead and this task" +needs = ["push-to-main"] +description = """ +Close the beads to complete the work chain. + +**1. Close the original MR bead:** +```bash +bd close {{original_mr}} --reason="merged after conflict resolution" +``` + +This completes the MR that was blocked on conflicts. + +**2. Close the source issue (if not already closed):** +```bash +bd show # Check status +bd close --reason="merged via conflict resolution" +``` + +The Refinery normally closes issues after merge, but since we pushed +directly to main, we handle it here. + +**3. Sync beads:** +```bash +bd sync +``` + +**Exit criteria:** Original MR and source issue are closed.""" + +[[steps]] +id = "release-slot" +title = "Release merge slot" +needs = ["close-beads"] +description = """ +Release the merge slot so other polecats can proceed. + +**1. Release the slot:** +```bash +bd merge-slot release --holder=$(whoami) --json +``` + +**2. Verify release:** +```bash +bd merge-slot check --json +``` + +Should show either: +- `available: true` (no one waiting) +- `holder: ` (slot passed to next in queue) + +**Exit criteria:** Merge slot released.""" + +[[steps]] +id = "cleanup-and-exit" +title = "Clean up and close task" +needs = ["release-slot"] +description = """ +Clean up workspace and close the conflict resolution task. + +**1. Clean up local branch:** +```bash +git checkout main +git branch -D temp-resolve +git fetch origin +git reset --hard origin/main +``` + +**2. Verify clean state:** +```bash +git status # Clean +git stash list # Empty +``` + +**3. Close this task:** +```bash +bd close {{task}} --reason="Conflicts resolved and merged to main" +``` + +**4. Signal completion:** +```bash +gt done +``` + +You're now recyclable. The Witness knows you've completed conflict resolution. + +**Exit criteria:** Task closed, workspace clean, polecat recyclable.""" + +[vars] +[vars.task] +description = "The conflict resolution task ID assigned to this polecat" +required = true + +[vars.original_mr] +description = "The original MR bead ID (extracted from task metadata)" +required = true + +[vars.branch] +description = "The branch to rebase (extracted from task metadata)" +required = true