Skip to content

fix(gastown): closed escalation beads re-broadcast as phantom Re-Escalation messages #2123

@jrf0110

Description

@jrf0110

Bug Description

Stale, already-closed escalation beads are being re-injected into the Mayor's chat feed as [Re-Escalation:high] or [Escalation:medium] messages. This occurs when the user navigates around the dashboard or rapidly opens rig views.

Root Cause

Location: services/gastown/src/dos/Town.do.ts, line 4533 — the re-escalation query.

const candidates = [
  ...query(
    this.sql,
    /* sql */ `${ESCALATION_JOIN} WHERE ${escalation_metadata.acknowledged} = 0 AND ${escalation_metadata.re_escalation_count} < ?`,
    [MAX_RE_ESCALATIONS]
  ),
].map(r => toEscalation(EscalationBeadRecord.parse(r)));

The ESCALATION_JOIN (defined at line 226) joins beads with escalation_metadata, but the re-escalation query does not filter by ${beads.status}. Specifically, it is missing:

  • No status != 'closed' filter — closed beads are eligible candidates
  • No acknowledged = 0 filter — acknowledged (and thus closed) beads are still queried

When an escalation is acknowledged via acknowledgeEscalation (line 3186), the bead status IS set to 'closed'. However, on the next _alarm tick, the re-escalation logic queries for candidates without checking that the bead is still open. The closed bead passes all filters (acknowledged was set to 1 but the query at line 4533 doesn't check that) and the age check at line 4542 may pass, causing a phantom re-escalation to be sent to the Mayor at line 4561.

Escalation Message Origins

Message pattern Location When emitted
[Escalation:{severity}] Line 3326 (routeEscalation) When a new escalation bead is created
[Re-Escalation:{severity}] Line 4561 (_alarm re-escalation loop) On alarm tick for stale unacknowledged escalations

The phantom issue specifically affects the Re-Escalation path (line 4561).

The Flow (buggy path)

  1. Escalation bead created → status = 'open'
  2. Mayor notified via sendMayorMessage (line 3326)
  3. Escalation acknowledged → acknowledged = 1 AND status = 'closed' (line 3186)
  4. _alarm tick fires
  5. Bug: Re-escalation query (line 4533) does NOT filter by status or acknowledged = 0
  6. Closed bead is selected as a candidate
  7. Age check (line 4542) may pass
  8. Mayor receives phantom [Re-Escalation:...] message (line 4561)

Fix

Add a status filter to the re-escalation query at line 4533:

WHERE ${beads.status} != 'closed'
  AND ${escalation_metadata.acknowledged} = 0
  AND ${escalation_metadata.re_escalation_count} < ?

Or equivalently, rely on the acknowledged flag since acknowledgeEscalation already sets it to 1:

WHERE ${escalation_metadata.acknowledged} = 0
  AND ${escalation_metadata.re_escalation_count} < ?

Impact

  • Noise in Mayor chat context degrading LLM response quality
  • Confusion from the LLM seeing stale escalation messages
  • Decreased trust in escalation signals

Severity

Medium — functional incorrectness affecting LLM context integrity

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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