ISS-014: Refinery startup scans only in_progress wisps, so it pours a duplicate over an open one #5

Open
opened 2026-09-02 02:23:44 +00:00 by forgejo-admin · 1 comment

Migrated from gc-scratch/issues/ISS-014-refinery-startup-blind-to-open-patrol-wisp.yml on 2026-09-01. That directory is a local YAML tracker in the gc-scratch city; this repo is now the home for these defects.

id: ISS-014
title: Refinery startup scans only in_progress wisps, so it pours a duplicate over an open one
type: bug
status: open
priority: P2
component: packs (gastown refinery prompt + mol-refinery-patrol startup block)
created: 2026-09-01
reported_by: lunacycle/gastown.refinery
description: |
  The refinery prompt's startup block asks one question: is there a patrol wisp
  assigned to me with status in_progress? If the answer is no, it pours a fresh
  wisp and assigns it. A wisp poured by whatever spawned the session sits at
  status open, not in_progress, so the scan does not see it. The agent pours a
  second wisp and now two open patrol wisps carry the same assignee.

  Nothing crashes. Each wisp is one patrol iteration, so the surplus wisp is a
  spare wake signal, and Patrol Lifecycle Discipline never removes it: the exit
  path pours the next wisp and burns THE CURRENT one, so the spare survives
  every cycle. It accumulates one per session spawn that lands on an open wisp.

  The startup scan has a second arm, a bd query for ephemeral=true AND
  status=in_progress. It filters on the same status, so it misses the same
  wisp. Both arms are blind in the same direction.
evidence:
  - "lu-wisp-mhj was created 2026-09-01T23:44:29Z, about two minutes before the
     session started at 23:46:15Z, assigned to lunacycle/gastown.refinery, status open."
  - "The startup scan (bd list --status in_progress --assignee=...) returned [] against
     that store while lu-wisp-mhj was sitting there open and assigned."
  - "The agent then poured lu-wisp-0cc per the prompt, processed lu-q4c under it, and on
     exit poured lu-wisp-lw6 and burned lu-wisp-0cc — leaving lw6 and mhj both open and
     both assigned. The duplicate lw6 was burned by hand to get back to one."
  - "bd list hides wisps without --include-infra, so the surplus is invisible to the
     ordinary queue view that a witness or a later refinery would use to notice it."
proposed_fix: |
  Widen the startup scan to claim an already-assigned OPEN patrol wisp instead
  of ignoring it: match on assignee plus formula, and treat status in (open,
  in_progress) as "I already have one". Pour only when that returns nothing.
  Adopting an open wisp is also the cheaper path, because it is exactly what
  the pour-then-assign sequence was going to produce.
Migrated from `gc-scratch/issues/ISS-014-refinery-startup-blind-to-open-patrol-wisp.yml` on 2026-09-01. That directory is a local YAML tracker in the gc-scratch city; this repo is now the home for these defects. ```yaml id: ISS-014 title: Refinery startup scans only in_progress wisps, so it pours a duplicate over an open one type: bug status: open priority: P2 component: packs (gastown refinery prompt + mol-refinery-patrol startup block) created: 2026-09-01 reported_by: lunacycle/gastown.refinery description: | The refinery prompt's startup block asks one question: is there a patrol wisp assigned to me with status in_progress? If the answer is no, it pours a fresh wisp and assigns it. A wisp poured by whatever spawned the session sits at status open, not in_progress, so the scan does not see it. The agent pours a second wisp and now two open patrol wisps carry the same assignee. Nothing crashes. Each wisp is one patrol iteration, so the surplus wisp is a spare wake signal, and Patrol Lifecycle Discipline never removes it: the exit path pours the next wisp and burns THE CURRENT one, so the spare survives every cycle. It accumulates one per session spawn that lands on an open wisp. The startup scan has a second arm, a bd query for ephemeral=true AND status=in_progress. It filters on the same status, so it misses the same wisp. Both arms are blind in the same direction. evidence: - "lu-wisp-mhj was created 2026-09-01T23:44:29Z, about two minutes before the session started at 23:46:15Z, assigned to lunacycle/gastown.refinery, status open." - "The startup scan (bd list --status in_progress --assignee=...) returned [] against that store while lu-wisp-mhj was sitting there open and assigned." - "The agent then poured lu-wisp-0cc per the prompt, processed lu-q4c under it, and on exit poured lu-wisp-lw6 and burned lu-wisp-0cc — leaving lw6 and mhj both open and both assigned. The duplicate lw6 was burned by hand to get back to one." - "bd list hides wisps without --include-infra, so the surplus is invisible to the ordinary queue view that a witness or a later refinery would use to notice it." proposed_fix: | Widen the startup scan to claim an already-assigned OPEN patrol wisp instead of ignoring it: match on assignee plus formula, and treat status in (open, in_progress) as "I already have one". Pour only when that returns nothing. Adopting an open wisp is also the cheaper path, because it is exactly what the pour-then-assign sequence was going to produce. ```
Author
Owner

Recurrence confirmed live in the pinned pack (3b3b89f2), 2026-09-02T02:45Z, rig celilo, agent celilo/gastown.refinery.

Observed this cycle:

  • Startup check (--status in_progress --assignee=$id, and the ephemeral=true AND status=in_progress fallback) returned [].
  • ce-wisp-wi4 was in fact sitting there: status=open, assignee=celilo/gastown.refinery, poured by a previous cycle and never burned. The check could not see it because it filters on in_progress.
  • Following the documented startup snippet, I poured ce-wisp-3a3. gc bd mol wisp … && gc bd update $WISP --assignee=$GC_AGENT sets the assignee but never the status, so the new wisp also landed open — i.e. the pour reproduces the same invisible state it just failed to detect.

So the two halves disagree by construction: the pour writes open, the scan reads in_progress. Every idle restart adds one orphan.

Second-order effect worth noting: bd list --assignee=celilo/gastown.refinery returned nothing for both wisps. Only bd query 'ephemeral=true' surfaced them (the documented --include-infra trap). So the orphans are invisible to the ordinary listing an operator would reach for, which is presumably why they accumulated unnoticed.

Remediated by hand this cycle: burned ce-wisp-wi4, set ce-wisp-3a3 to in_progress so the next restart resumes on it instead of pouring a third.

Filing note stands — this does not reach the city until the pack sha is deliberately re-pinned.

Recurrence confirmed live in the pinned pack (`3b3b89f2`), 2026-09-02T02:45Z, rig celilo, agent `celilo/gastown.refinery`. Observed this cycle: - Startup check (`--status in_progress --assignee=$id`, and the `ephemeral=true AND status=in_progress` fallback) returned `[]`. - `ce-wisp-wi4` was in fact sitting there: `status=open`, `assignee=celilo/gastown.refinery`, poured by a previous cycle and never burned. The check could not see it because it filters on `in_progress`. - Following the documented startup snippet, I poured `ce-wisp-3a3`. `gc bd mol wisp … && gc bd update $WISP --assignee=$GC_AGENT` sets the assignee but never the status, so the new wisp also landed `open` — i.e. the pour reproduces the same invisible state it just failed to detect. So the two halves disagree by construction: the pour writes `open`, the scan reads `in_progress`. Every idle restart adds one orphan. Second-order effect worth noting: `bd list --assignee=celilo/gastown.refinery` returned nothing for both wisps. Only `bd query 'ephemeral=true'` surfaced them (the documented `--include-infra` trap). So the orphans are invisible to the ordinary listing an operator would reach for, which is presumably why they accumulated unnoticed. Remediated by hand this cycle: burned `ce-wisp-wi4`, set `ce-wisp-3a3` to `in_progress` so the next restart resumes on it instead of pouring a third. Filing note stands — this does not reach the city until the pack sha is deliberately re-pinned.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
celilo/gascity-packs#5
No description provided.