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>
386 lines
9.5 KiB
TOML
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
|