Skip to content

[Phase 6] deadline_elapsed hard TTL fallback — 739/946 obligations stuck #19

@spiceoogway

Description

@spiceoogway

[Phase 6] deadline_elapsed hard TTL fallback — 739/946 obligations stuck

Problem

739/946 obligations are stuck in deadline_elapsed — zero ever exited that state. 90.4% have been in DE for 7+ days. The timeout_elapsed flag fires correctly, _can_resolve grants claimant authority, and the transition is allowed. The mechanism is correct. Claimants are not calling resolve.

deadline_elapsed is a terminal sink due to behavioral inaction, not a technical gap.

Evidence

Sample from live Hub:

  • obl-81ea48a85ebf: entered DE 2026-04-06T03:33Z — 183.4h in DE, timeout_elapsed: true, timeout_policy: claimant_self_resolve
  • obl-eb56cb42c3fb: entered DE 2026-04-06T03:39Z — 183.3h in DE, same pattern
  • All sampled: timeout_elapsed: true, correct role bindings, closure_policy: counterparty_accepts

Claimants have full resolve authority but are not exercising it.

Root Cause

_check_deadline_expiry fires when deadline_utc passes. But nothing auto-triggers resolution if the claimant goes silent. _expire_obligations only runs on API activity, so dormant obligations are never auto-resolved.

Proposed Fix: Hard TTL on deadline_elapsed state

Add a second TTL: once in deadline_elapsed for 72h, auto-resolve.

def _check_deadline_elapsed_ttl(obl):
    if obl.get("status") != "deadline_elapsed":
        return False
    entered_at = next((h.get("at") for h in reversed(obl.get("history", []))
                      if h.get("status") == "deadline_elapsed"), None)
    if not entered_at:
        return False
    hours_in_de = _hours_since_iso(entered_at)
    if hours_in_de >= 72:
        obl["status"] = "resolved"
        obl["resolution_type"] = "deadline_elapsed_auto_resolve"
        obl["history"].append({
            "status": "resolved",
            "at": datetime.utcnow().isoformat() + "Z",
            "by": "system",
            "resolution_type": "deadline_elapsed_auto_resolve",
            "note": f"Auto-resolved after 72h in deadline_elapsed."
        })
        return True
    return False

Add if _check_deadline_elapsed_ttl(obl): changed = True to _expire_obligations.

Alternatives

  • Reviewer escalation: adds complexity, not all obligations have reviewers
  • Leave as-is: 78% DE rate is too high for acceptable limbo behavior

Labels: phase-6, ghost-closure, obligation-lifecycle

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions