Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions openadapt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1350,12 +1350,23 @@ def verify_ledger() -> None:
@verify_ledger.command("list")
@_LEDGER_OPTION
def verify_ledger_list(ledger_dir: Optional[str]) -> None:
"""Show held and open writes: key, state, when it began, outcome."""
"""Show held and open writes: key, state, when it began, outcome.

Also each provisional CONFIRMED whose recheck is still owed, with its due
time, so a recheck isn't lost when the server that holds it restarts.
"""
ledger = _write_ledger(ledger_dir)
rows = ledger.unresolved()
if not rows:
click.echo("No held or open writes.")
owed = ledger.rechecks_owed()
if not rows and not owed:
click.echo("No held or open writes. No rechecks owed.")
return
for key, attempt in owed:
click.echo(
f"{key} recheck-owed began {attempt.begun.get('at')} "
f"due {attempt.recheck_owed} by {attempt.begun.get('actor_kind')}:"
f"{attempt.begun.get('actor_id')}"
)
for key, attempt in rows:
outcome = (attempt.resolved or {}).get("outcome", "-")
state = "review" if attempt.review else ledger.state(attempt)
Expand Down
27 changes: 27 additions & 0 deletions tests/test_verify_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,30 @@ def test_verify_ledger_lists_and_releases_a_held_write(tmp_path) -> None:
assert released.exit_code == 0, released.output
listed = runner.invoke(main, ["verify", "ledger", "list", "--ledger", str(folder)])
assert "No held or open writes." in listed.output


def test_verify_ledger_lists_a_recheck_owed_until_it_runs(tmp_path) -> None:
ledger_mod = pytest.importorskip("openadapt_flow.write_ledger")
folder = tmp_path / "ledger"
ledger = ledger_mod.Ledger(ledger_mod.FileLedger(folder))
key = "d" * 64
due = "2026-01-01T00:02:00Z"
ledger.begun(key, "write-2", contract="c" * 64, actor_kind="agent", actor_id="bot")
ledger.resolved(
key,
"write-2",
outcome="CONFIRMED",
retry_safe=False,
delivered=True,
result={"outcome": "CONFIRMED", "provisional": True, "recheck_due_at": due},
)
runner = CliRunner()
listed = runner.invoke(main, ["verify", "ledger", "list", "--ledger", str(folder)])
assert listed.exit_code == 0, listed.output
assert key in listed.output and "recheck-owed" in listed.output
assert f"due {due}" in listed.output

ledger.rechecked(key, "write-2", outcome="CONFIRMED")
listed = runner.invoke(main, ["verify", "ledger", "list", "--ledger", str(folder)])
assert "recheck-owed" not in listed.output
assert "No rechecks owed." in listed.output
Loading