Skip to content

sweep: a triage.json reload failure on resume orphans a re-armed bundle #94

Description

@pbean

Summary

On resume of a paused sweep run, a re-armed (resolved) bundle is re-driven only because _ensure_triage reloads the cached triage.json and re-materializes the same bundle under the same _bundle_key, letting _run_bundle find the existing PENDING task. If that reload fails, the re-armed bundle can be silently orphaned and its resolved escalation stranded — the re-drive never runs.

Details

SweepEngine._ensure_triage (src/bmad_loop/sweep.py, ~line 676) short-circuits to the persisted plan on resume:

if triage_path.is_file():
    plan, errors = validate_triage(_read_json(triage_path), None)
    if plan is not None:
        return plan
    self.journal.append("sweep-triage-reload-failed", errors=errors)
# ...falls through to running a FRESH triage session

When triage.json is missing/corrupt or fails validate_triage, sweep runs a fresh triage session. That new plan may partition the open ids into differently-named bundles, so a re-armed PENDING task keyed dw-<oldname> (or dw<cycle>-<oldname>) is:

  • not re-materialized under a matching _bundle_key, and
  • not picked up by _materialize_bundles (it filters DEFERRED/ESCALATED, but a re-armed task is PENDING, so it isn't re-driven from that path either).

Net effect: the human resolved the escalation (via bmad-loop resolve, incl. --restore-patch), but the re-drive silently never happens and the bundle's dw ids stay open.

Severity

Low / pre-existing. Not introduced by the #75 patch-restore work (PR #93) — that work relies on the happy reload path, which is the normal case. This is the failure tail.

Possible fixes

  • On resume, drive a re-armed escalated bundle directly by state.paused_story_key (reconstructing its Bundle from the persisted task's dw_ids + key), independent of triage re-materialization — mirroring how the base engine's _finish_inflight re-drives the specific in-flight task.
  • Or, at minimum, when a re-armed bundle task exists but the reloaded/fresh plan does not contain it, log()/journal a loud warning instead of silently dropping it (no-silent-caps).

Context

Surfaced during the #75 pressure-test (finding "e"). See PR #93.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

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