Skip to content

Stale teammate notifications keep interrupting the lead after team purge (split from #40, bug 4) #48

Open

Description

@hueyexe

Split out of #40 (bug 4), which is otherwise fixed in v0.20.0 — the other three bugs are closed there, this one is still untraced.

Original report (credit: @Its-Satyajit, from #40)

After team_cleanup archived the team and a second team_cleanup with purge deleted it, teammates that were already in shutdown state kept delivering notifications to the lead. The lead's turn showed [System: New team message from alpha] on repeat, and the body was never readable:

> team_results()
This session is not in a team.

team_message had zero rows afterwards, so the redelivery is not coming from the database. Likely suspects: in-flight/persisted wake deliveries (synthetic system messages) that reference a team that no longer exists, or the idle-flush backstop re-firing for a member row that was purged between scheduling and delivery. Whatever delivers the notification needs a guard: if the recipient's team no longer exists (or the member row is gone), drop the delivery instead of waking the lead.

Acceptance

  • After a purge, a lead session must receive zero further teammate notifications.
  • Any delivery path that runs after team deletion must no-op when the team/member row is missing.

Activity

  1. hueyexe commented on Oct 19, 2026

    @hueyexe
    OwnerAuthor

    First-hand reproduction just landed while dogfooding v0.20.0 — timeline and DB evidence below.

    Reproduction (v0.20.0, opencode 2.0.32, single lead + one member)

    1. Team dogfood-020 with members alpha and beta (GLM 5.3 flash teammates), both completed their tasks and reported
    2. alpha shut down gracefully; beta's graceful shutdown stalled (idle → shutdown_requested → idle), so the lead force-shut beta down
    3. Lead ran team_cleanup — team archived
    4. Minutes later, the lead's session received [System: New team message from beta] — with no body readable:
      > team_results()
      This session is not in a team.
      

    DB state at the time of the stale notification

    team:   team_mvf377ul_0000_icdz5j | dogfood-020 | status=archived
    
    team_message (latest, all for the lead):
      beta | lead | <task-result>... | delivered=1 | 10:23:06
      beta | lead | <task-result>... | delivered=1 | 10:22:10
      beta | lead | <task-result>... | delivered=1 | 10:17:15
      alpha | lead | <task-result>... | delivered=1 | 10:17:01
    

    Every message row is delivered=1 — the stale wake did not come from the database, exactly as the original #40 bug 4 reporter observed.

    Likely mechanism (now with concrete timing)

    The wake was an in-flight fire-and-forget promptAsync scheduled before cleanup (beta's final team_message/shutdown processing raced the force shutdown). The delivery path fires the lead wake unconditionally — nothing re-checks at delivery time whether the lead's team still exists. team_cleanup runs between schedule and delivery → the lead is woken into a team that no longer resolves.

    The acceptance criterion already written on this issue is confirmed as the right fix: every delivery path must no-op when the recipient's team/member row is missing at delivery time, and lead-bound wakes should resolve the team fresh from the registry rather than trusting the pre-schedule state.

    Note

    Beta also re-reported its task result three times (10:17, 10:22, 10:23) because of the repeated shutdown requests during the graceful-shutdown stall — the stall behavior that produced the extra wakes is itself worth looking at alongside the delivery guard: a member that has gone idle after processing the shutdown message should terminalize rather than cycle back to idle.

  2. hueyexe commented on Oct 19, 2026

    @hueyexe
    OwnerAuthor

    Update: the stale wakes repeat, one per lead turn. A second [System: New team message from beta] arrived on the lead's next turn, with the DB unchanged since the first (latest row still 10:23:06, all delivered=1, team still archived).

    This matches the original #40 report's 'on repeat' symptom and supports the in-flight-wake-queue theory: beta sent three lead-bound task results (10:17, 10:22, 10:23), each scheduling a fire-and-forget lead wake; after cleanup, those queued wakes drain into the lead's turns one at a time. Expect the count of stale notifications to roughly equal the number of lead-bound wakes scheduled before cleanup — and the lead can neither read nor dismiss them, because the team no longer resolves.

    Reinforces the fix direction: guard delivery against team/member existence at fire time, and consider draining or invalidating pending lead-bound wakes for a team during team_cleanup's archive step.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions