fix-abandoned-dependency-readiness

Fix: abandoned prerequisites must fail closed, never authorize downstream work

Metadata

Statusdone
Assignedagent-931
Modelpi:openai-codex:gpt-5.6-sol
Created2026-07-28T14:06:57.315922489+00:00
Started2026-07-28T15:48:34.168245930+00:00
Completed2026-07-28T16:26:33.320628711+00:00
Tokens22052124 in / 33382 out

Description

User-reported safety bug

A historical production chain showed an abandoned prerequisite making an obsolete downstream packaging/launch task runnable. This remains current, explicit policy: Status::is_dep_satisfied() returns true for Done | Abandoned, ready_tasks tests pin that behavior, archived boundaries are accepted regardless of recorded status, and coordinator recovery has another missing/terminal shortcut.

Clean-room reproduction with the installed current binary:

before abandon: ready=[prerequisite]
after abandon:  ready=[downstream]
why-blocked: downstream is_ready=true, total_blockers=0

This is unsafe. after is a required-success edge. Abandonment means the prerequisite will not produce its promised artifact; it is terminal for liveness/retention only, never success evidence.

Normative semantics

  • Keep Abandoned terminal for lifecycle, cleanup, cycle membership, UI history, and no-retry semantics.
  • Separate terminality from dependency satisfaction. For ordinary required after edges, only exact successful completion (Done plus any applicable acceptance receipt/gate) satisfies. Abandoned, Failed, unresolved/missing, waiting, stale, and incomplete states block.
  • An ordinary dependent whose prerequisite is abandoned must never become dispatcher-ready, claimable, spawnable, auto-unblocked, completable by a worker, mergeable, or eligible for downstream finalization.
  • Canonical dependency_disposition is the single authority. Remove divergent shortcuts in ready/status/why-blocked/coordinator stuck-unblock/manual-done/federation/archive paths.
  • An ArchivedBoundary already records status: only a boundary whose recorded status is Done can satisfy. Archived Abandoned remains a visible failed-closed blocker. A truly missing dependency blocks; deletion/GC must not manufacture success.
  • Remote dependencies obey the same status semantics.
  • Preserve evaluation-system relation-aware exceptions only where necessary for an owning satellite to resolve a source soft state. Never generalize dot-prefix or terminal status into success.
  • Existing graphs upgrade fail closed without rewriting history. Open/Blocked dependents immediately remain non-ready. For any already-live attempt launched under the obsolete rule, stop acceptance/merge, preserve/fence the exact process safely, retain its work as evidence, and require operator review; never blindly kill a writer or retroactively mark success.
  • Already-Done historical descendants remain immutable history but are flagged by an audit/check diagnostic as completed-through-abandoned-prerequisite; do not reopen them automatically.

Explicit operator escape paths

  • wg abandon must report affected active ordinary dependents and state that they remain blocked.
  • --superseded-by remains provenance, not success. Diagnostics name replacements but do not silently treat them as done or rewrite ambiguous AND/OR dependency intent.
  • To proceed intentionally, the operator must perform an explicit graph mutation: retry/reopen the prerequisite, relink the dependent to a completed replacement, or remove/waive the edge with audited rationale. Existing wg rm-dep may serve if it records adequate provenance; otherwise add a narrowly-scoped audited dependency waiver. No reason string or ordinary message counts as a waiver.
  • wg why-blocked, wg show, stable JSON, TUI detail and Activity must say blocked: prerequisite X was abandoned and show supersession/repair commands. Do not misleadingly report zero blockers because abandoned is terminal.

Validation

  • Preserve a RED installed-binary/old-source regression proving before=[prerequisite], abandon, after=[downstream] today.
  • Unit/integration tests reverse the old assertions: local and remote Abandoned never satisfy ordinary dependencies; Done still does; Failed/missing remain blocked.
  • Credential-free installed-binary daemon smoke builds prerequisite -> packaging -> launch, abandons each upstream shape, and proves no dependent claim/spawn/PID/worktree/session/evaluation/merge or readiness event appears across repeated polls and restart.
  • Same smoke proves explicit audited edge removal/relink permits progress, while --superseded-by alone does not.
  • Archived Done boundary satisfies; archived Abandoned boundary blocks before/after daemon restart and archive undo.
  • Coordinator stale-block reconciliation delegates to canonical disposition and cannot treat missing/abandoned as success.
  • Worker wg_done cannot bypass an abandoned dependency; explicit operator waiver is content/edge-bound, attributable, idempotent and visible.
  • Upgrade audit catches already-running and already-Done descendants without destructive reset or historical mutation.
  • Cycles, evaluation satellites, archive/GC, federation, status/why-blocked, lifecycle and service readiness suites remain sound.
  • cargo fmt --check, cargo clippy, focused/full tests and owned smoke pass; commit/push and wg done finalize normally.

Depends on

Required by

Log