Read a failed read-back again once CMO answered the write #132

Manually merged
vinny merged 0 commits from vinny/readback-retry into master 2026-10-16 14:15:00 -04:00 AGit
Owner

Fixes #131.

In laboratory trial tpl-surface-defensive-escort, CMO answered an assignment and a deactivation, but their read-backs ran over the proxy's time budget while the game was busy. Both stayed outcome_unknown for good, with their missions and units reserved: verify_due only took accepted_in_progress actions. Also, a read-back that the proxy let expire unread carries execution_proven_absent, so the coordinator recorded the write as refused ("No effect was sent") and released its reservation, though CMO had run it.

Changes:

  • ActionCoordinator.execute marks the write answered once its receipt is recorded. After that, any failure (other than a changed timeline) is a read failure, and _unknown(..., reread=True) handles it.
  • The action stays outcome_unknown and its read-back is due again after 15 s, then 30, 60, 120, 240 and 480 s (capped at 600). That is READBACK_FAILURE_RETRIES = 6 re-reads, about 16 minutes. After the last one it is left for reconciliation as before.
  • verify_due re-reads these actions the same way, and ActionLedger.next_verification now also takes outcome_unknown actions that have a due time. Only these re-reads set one.
  • The write is never sent again. A write whose reply was lost is still left for reconciliation and is not read again by itself.
  • docs/TOOL_LIBRARY.md describes this.

Tests (tests/stage3/test_execution.py, synthetic port with a read-back failure):

  • a failed read-back read again and completed, with the reservation released, both for a budget overrun and for a read the proxy let expire;
  • read-backs that keep failing stop after their budget, keeping the reservation;
  • a lost write reply is not read again by itself.

The first three fail without the change. The expired-read case was recorded as rejected.

🤖 Generated with Claude Code

Fixes #131. In laboratory trial tpl-surface-defensive-escort, CMO answered an assignment and a deactivation, but their read-backs ran over the proxy's time budget while the game was busy. Both stayed `outcome_unknown` for good, with their missions and units reserved: `verify_due` only took `accepted_in_progress` actions. Also, a read-back that the proxy let expire unread carries `execution_proven_absent`, so the coordinator recorded the write as refused ("No effect was sent") and released its reservation, though CMO had run it. Changes: - `ActionCoordinator.execute` marks the write answered once its receipt is recorded. After that, any failure (other than a changed timeline) is a read failure, and `_unknown(..., reread=True)` handles it. - The action stays `outcome_unknown` and its read-back is due again after 15 s, then 30, 60, 120, 240 and 480 s (capped at 600). That is `READBACK_FAILURE_RETRIES` = 6 re-reads, about 16 minutes. After the last one it is left for reconciliation as before. - `verify_due` re-reads these actions the same way, and `ActionLedger.next_verification` now also takes `outcome_unknown` actions that have a due time. Only these re-reads set one. - The write is never sent again. A write whose reply was lost is still left for reconciliation and is not read again by itself. - `docs/TOOL_LIBRARY.md` describes this. Tests (`tests/stage3/test_execution.py`, synthetic port with a read-back failure): - a failed read-back read again and completed, with the reservation released, both for a budget overrun and for a read the proxy let expire; - read-backs that keep failing stop after their budget, keeping the reservation; - a lost write reply is not read again by itself. The first three fail without the change. The expired-read case was recorded as rejected. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Fixes #131. When CMO answered a library write and its read-back failed (a busy
game over the proxy's time budget), the action stayed outcome_unknown for good,
its units and mission reserved, since only accepted_in_progress actions came
due again. And a read-back the proxy let expire unread made the coordinator
record the write as refused and release its reservation, though CMO ran it.

Once the write is answered, a failure is a read failure: the action stays
outcome_unknown with its read-back due again after 15 s, 30 s and so on up to
600 s, READBACK_FAILURE_RETRIES (6) times. The write is never sent again, and
a write whose reply was lost is still left for reconciliation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Version 0.7.81 (readback-retry)
Some checks failed
check / check (ubuntu-latest) (push) Has been cancelled
check / check (windows-latest) (push) Has been cancelled
check / check (windows-latest) (pull_request) Has been cancelled
check / check (ubuntu-latest) (pull_request) Has been cancelled
54d24ae8cc
vinny manually merged commit 54d24ae8cc into master 2026-10-16 14:15:00 -04:00
Sign in to join this conversation.
No reviewers
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
vinny/CMOnet!132
No description provided.