Summary
In multi-rig towns, the refinery agent tries to pull branches from the wrong rig's repo. This causes escalations like "can't find branch gt/toast/abc123" because the branch only exists in rig B's remote but the refinery was dispatched into rig A's worktree.
There are four compounding bugs in the dispatch chain.
Parent: #204
Bug 1: Singleton refinery reuse ignores rig_id
File: src/dos/town/agents.ts:345-350
const singletonRoles = ['witness', 'refinery', 'mayor'];
if (singletonRoles.includes(role)) {
const existing = listAgents(sql, { role });
if (existing.length > 0) return existing[0]; // ← ignores rigId argument
}
When getOrCreateAgent(sql, 'refinery', rigId) is called, the singleton lookup filters only by role, not by rig_id. If a refinery was created for rig A, it's returned for rig B's dispatch. The polecat path correctly checks rig_id (line 353-354 even has a comment explaining why), but this was never applied to refineries.
Fix: Refinery should be per-rig, not a town-wide singleton. Change the singleton lookup to include rig_id in the filter, or remove refinery from singletonRoles and treat it like polecats (one per rig, reusable within a rig).
Bug 2: processReviewQueue hardcodes rigList[0]
File: src/dos/Town.do.ts:1433-1434
const rigList = rigs.listRigs(this.sql);
const rigId = rigList[0]?.id ?? ''; // ← always picks first rig
When the alarm pops a review entry, it resolves the rig by taking the first rig in the list, not by looking at which rig the merge_request bead belongs to.
Fix: Resolve rigId from the merge_request bead's rig_id column (requires Bug 3 to be fixed first).
Bug 3: merge_request beads created with rig_id = null
File: src/dos/town/review-queue.ts:92
[id, 'merge_request', 'open', title, summary, null, /* ← rig_id */ ...]
submitToReviewQueue hardcodes rig_id to null on the merge_request bead. The ReviewQueueInput type doesn't include rig_id at all.
Fix: Add rig_id to ReviewQueueInput. Populate it from the source bead's rig_id (available via input.bead_id lookup) or pass it explicitly from agentDone.
Bug 4: ReviewQueueInput type has no rig_id field
File: src/types.ts:130-136
The ReviewQueueInput type doesn't carry rig context, making it impossible to propagate rig information through the review queue.
Fix: Add rig_id: string to the type.
The full bug chain
Given rig A (created first) and rig B (created second):
- Polecat on rig B finishes work →
submitToReviewQueue
- MR bead created with
rig_id = null (Bug 3)
- Alarm fires →
processReviewQueue pops the entry
- Rig resolved via
rigList[0] → gets rig A (Bug 2)
getOrCreateAgent('refinery') returns the existing refinery for rig A (Bug 1)
- Container dispatched with rig A's git URL, default branch, credentials
- Container clones rig A's repo
- Refinery tries to find rig B's branch → doesn't exist → escalation
Acceptance criteria
Summary
In multi-rig towns, the refinery agent tries to pull branches from the wrong rig's repo. This causes escalations like "can't find branch gt/toast/abc123" because the branch only exists in rig B's remote but the refinery was dispatched into rig A's worktree.
There are four compounding bugs in the dispatch chain.
Parent: #204
Bug 1: Singleton refinery reuse ignores rig_id
File:
src/dos/town/agents.ts:345-350When
getOrCreateAgent(sql, 'refinery', rigId)is called, the singleton lookup filters only by role, not byrig_id. If a refinery was created for rig A, it's returned for rig B's dispatch. The polecat path correctly checksrig_id(line 353-354 even has a comment explaining why), but this was never applied to refineries.Fix: Refinery should be per-rig, not a town-wide singleton. Change the singleton lookup to include
rig_idin the filter, or removerefineryfromsingletonRolesand treat it like polecats (one per rig, reusable within a rig).Bug 2: processReviewQueue hardcodes rigList[0]
File:
src/dos/Town.do.ts:1433-1434When the alarm pops a review entry, it resolves the rig by taking the first rig in the list, not by looking at which rig the merge_request bead belongs to.
Fix: Resolve
rigIdfrom the merge_request bead'srig_idcolumn (requires Bug 3 to be fixed first).Bug 3: merge_request beads created with rig_id = null
File:
src/dos/town/review-queue.ts:92submitToReviewQueuehardcodesrig_idtonullon the merge_request bead. TheReviewQueueInputtype doesn't includerig_idat all.Fix: Add
rig_idtoReviewQueueInput. Populate it from the source bead'srig_id(available viainput.bead_idlookup) or pass it explicitly fromagentDone.Bug 4: ReviewQueueInput type has no rig_id field
File:
src/types.ts:130-136The
ReviewQueueInputtype doesn't carry rig context, making it impossible to propagate rig information through the review queue.Fix: Add
rig_id: stringto the type.The full bug chain
Given rig A (created first) and rig B (created second):
submitToReviewQueuerig_id = null(Bug 3)processReviewQueuepops the entryrigList[0]→ gets rig A (Bug 2)getOrCreateAgent('refinery')returns the existing refinery for rig A (Bug 1)Acceptance criteria
ReviewQueueInputincludesrig_idsubmitToReviewQueuepopulatesrig_idon the merge_request beadprocessReviewQueueresolves rig from the merge_request bead, notrigList[0]getOrCreateAgentfor refinery filters byrig_id