Files
gastown/.beads/formulas/mol-polecat-conflict-resolve.formula.toml
nux e663928564 feat(formulas): Add conflict resolution workflow for polecats (gt-si8rq.5)
New molecule formula mol-polecat-conflict-resolve defines the workflow for
polecats handling merge conflict resolution tasks:

1. Load task and extract metadata from conflict-resolution bead
2. Acquire merge slot (prevents racing via "Monkey Knife Fight" prevention)
3. Checkout the conflicting branch
4. Rebase onto main and resolve conflicts
5. Run tests to verify resolution
6. Push resolved changes directly to main (bypasses queue)
7. Close original MR bead and source issue
8. Release merge slot for next waiter
9. Clean up and close the conflict-resolution task

This completes the polecat side of the ephemeral merge workflow architecture.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 18:57:34 -08:00

386 lines
9.5 KiB
TOML

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: <mr-id>
- Branch: <branch>
- Conflict with: <target>@<main-sha>
- Original issue: <source-issue>
- Retry count: <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 <source-issue> # 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 <resolved-file>
git rebase --continue
```
**3. If stuck on a conflict:**
- Read the original issue for context: `bd show <source-issue>`
- If still unclear, escalate to Witness:
```bash
gt mail send <rig>/witness -s "HELP: Complex conflict" -m "Task: {{task}}
File: <conflicted-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 <source-issue> # Check status
bd close <source-issue> --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: <next-waiter>` (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