Skip to content

Bug: Refinery agent dispatched to wrong rig in multi-rig towns #657

@jrf0110

Description

@jrf0110

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):

  1. Polecat on rig B finishes work → submitToReviewQueue
  2. MR bead created with rig_id = null (Bug 3)
  3. Alarm fires → processReviewQueue pops the entry
  4. Rig resolved via rigList[0] → gets rig A (Bug 2)
  5. getOrCreateAgent('refinery') returns the existing refinery for rig A (Bug 1)
  6. Container dispatched with rig A's git URL, default branch, credentials
  7. Container clones rig A's repo
  8. Refinery tries to find rig B's branch → doesn't exist → escalation

Acceptance criteria

  • ReviewQueueInput includes rig_id
  • submitToReviewQueue populates rig_id on the merge_request bead
  • processReviewQueue resolves rig from the merge_request bead, not rigList[0]
  • Refinery agents are per-rig (one per rig, not a town-wide singleton)
  • getOrCreateAgent for refinery filters by rig_id
  • Multi-rig town: rig B's polecat work is reviewed by a refinery dispatched into rig B's repo

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingkilo-auto-fixAuto-generated label by Kilokilo-triagedAuto-generated label by Kilo

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions