Skip to content

Guard value reads, hold back emptied places, run once an hour - #4

Merged
timlichtenberg merged 3 commits into
mainfrom
tl/run-guards
Oct 22, 2026
Merged

timlichtenberg merged 3 commits into
mainfrom
tl/run-guards

Conversation

@timlichtenberg

Copy link
Copy Markdown
Member

Summary

The board read now guards the items, but the value lists inside an item still trust hasNextPage alone. If the API returns an empty value list for one item, the run reads every field of that item as cleared and clears it at the other places. This change makes those reads detect short lists, holds back a place whose values vanish without a sign of a clear, and limits the sync to one writing run per hour.

Changes

  • Board read: an issue item with no field values, or a number of values other than its totalCount, makes the board read short, so it is read again like a short item page. Every item holds at least its title.
  • Issue field values: a batch that returns another number of issues than asked for, or an issue with a number of values other than its totalCount, is read again (up to 6 reads, 10 seconds apart), then the run stops before any write. Null lists and null entries count as short. An issue that lacks the value of a synced field whose latest event set it counts as unread.
  • A board place of an issue whose synced fields held 2 or more values and all read empty is held back for the run. The issue fields of an issue are held back when a synced field that held a value reads empty without a removal event. A held place clears nothing and is listed in report.txt; if it reads the same in the next run, it receives the agreed values. A hand clear of all synced fields of an issue on one board is therefore undone.
  • A run with apply that starts less than 50 minutes after the start of the last run that tried a write stops before the read with exit code 5. A scheduled run shows that as a notice, a run started by hand fails. Only a run that tries a write stores its start time, so a run without writes still makes no commit in the state repository. A stored time more than 5 minutes ahead of the run is a state error.
  • The workflow runs once an hour at minute 11.
  • README: the new rules.

Validation

  • python -m pytest -q: 197 passed.
  • coverage run -m pytest -q && coverage report: 99% total; __main__.py and github.py 100% of lines and branches, core.py 99% (the 2 partial branches are also on main).
  • ruff check . and ruff format --check .: clean.
  • I changed each new condition in turn (30 changes in all, for example != to <, the WIPE_MIN value, the removal-time test, the stamp rule, the clock check, the null handling); every change makes at least 1 test fail.
  • The Sync step script with the run replaced by a fixed exit code: exit 5 gives 0 with a notice on schedule and 5 with an error on workflow_dispatch; exit 0, 2 and 4 are unchanged.
  • python -m board_sync without --apply against the 3 boards and a copy of the stored state, with a personal token: all reads full, no place held back, no unread issue, state file unchanged.

Not checked

  • An item with one synced value on a board can still lose it to a read that looks complete; the count rule needs 2 values, and a board gives no clear time.
  • The new checks were not run with the App token the workflow uses.

A board read now also counts as short when an issue item has no field values or fewer than its total, since every item holds at least its title. A read of issue field values is short when it returns fewer issues than asked for, or fewer values than the issue's total; it is read again like a board. An issue that lacks the value of a synced field whose latest event set it counts as unread.

An issue place whose synced fields held 2 or more values and now all read empty is held back for the run and listed in the report, so a lost read of one item clears nothing at the other places.

A run with apply stops before the read, with exit code 5, when it starts less than 50 minutes after the last run with apply. The workflow runs once an hour at minute 11 and shows that stop as a notice.
The issue fields of an issue are held back when one synced field that held a value reads empty with no removal event, since a clear of an issue field always has one; the count rule applies to boards only, so a hand clear on the issue still reaches the other places. Null value lists and null entries count as short reads.

Only a run that tries a write stores its start time, so a run without writes leaves the state as it was and makes no commit. A stored start time more than 5 minutes after the run's own start is a state error. A run started by hand that is too soon fails instead of showing a notice, so a bulk approval is not lost without a sign.
An issue field that comes back to the sync after a hold and was cleared after the agreed value now counts as a clear, since its removal event has a time; before, the agreed value was written back. A board clear has no time, so an empty board place still receives.

The start time is stored as soon as a write is sent, so a run stopped by a signal during its first write still starts the interval. A stored time in the future names applied_at in the error, and the README says how to recover. The workflow notices no longer repeat the interval, and the README states which short reads the hold does not catch.
@timlichtenberg
timlichtenberg merged commit 9d60a1a into main Oct 22, 2026
1 check passed
@timlichtenberg
timlichtenberg deleted the tl/run-guards branch October 22, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant