Skip to content

fix(remote): say how many cycles have failed since the last success (#829) - #891

Draft
fujibee wants to merge 1 commit into
mainfrom
fix/829-status-tells-the-truth
Draft

fix(remote): say how many cycles have failed since the last success (#829)#891
fujibee wants to merge 1 commit into
mainfrom
fix/829-status-tells-the-truth

Conversation

@fujibee

@fujibee fujibee commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Declared reviewers: 1

Part of #829 — the first of the three it splits into, and the one that would
have shortened the other two.

Change class: user-visible output. One status line gains a clause. No
change to what syncs or when.

What went wrong

A Windows machine had not synced once since connecting on 2026-08-13. Every
push was refused with HTTP 400 and retried about every 75 seconds, for six
days. agmsg remote status said:

myteam	connected (engine running, pid 5140) since 2026-08-13T…
		cycles: last successful sync 2026-08-13T09:02:00.000Z
		refused: the server answered 400 … at 2026-08-19T00:00:00.000Z

The refusal line is there and shipped in v1.2.0 — I built the state and ran
status against it rather than reading the source, and both lines print. What
it does not say is that the timestamp above is not the present state. A
success from six days ago and a success from four seconds ago are the same
sentence. The person who found this found it because two rosters disagreed.

What it says now

		cycles: last successful sync 2026-08-13T09:02:00.000Z; 6842 have failed since

The engine records failures the way it already records successes — same file,
same lifetime, same best-effort promise that bookkeeping never takes down
syncing. Counted since the last success, because "one failed a moment ago" and
"nothing has worked in six days" are the two states this line has to separate.

Refusals count. They deliberately do not advance consecutiveFailures
that drives the backoff, and a refusal is not evidence the transport is
degrading — but six days of nothing but refusals is six days of nothing synced,
so a second counter answers the second question.

no successful cycle recorded splits the same way: an engine started a second
ago and one that has never completed a cycle said the same thing, and only the
second is a fault.

Measured

tests/test_remote_status_liveness.bats     34/34   (3 new)
tests/remote_sync_engine.test.mjs          96/96   (2 new)
tests/test_remote_sync.bats                31/31
check-enforced-assertions                  639, unchanged from origin/main *

* main is one over its baseline today; that is #890, not this branch.

mutation result
refusals stop being counted red — the engine case
a success no longer ends the run of failures red
the count guard stops rejecting a non-numeric value red — lots reaches the line
none (control) green

The status cases assert both directions: a working engine must not grow a
clause about failures it has not had, and a count it cannot parse is absent
rather than printed.

Not here

Quarantining the row that cannot be sent, and any repair of values already
stored, are the other two thirds of #829 and are deliberately separate. This one
is first because it is the part that makes the next failure — whatever causes
it — visible to the person it is happening to.

An engine that failed every cycle for six days kept the last success it ever
had, and status printed it with nothing beside it -- so a machine that had not
synced since the 13th reported 'last successful sync 2026-08-13' and read as
working. The person who found it found it because two rosters disagreed.

A success timestamp cannot say whether it is the present state, so the engine
now records the failures too, counted since the last success. Refusals count:
they do not advance the backoff counter, deliberately, but six days of nothing
but refusals is six days of nothing synced.

'No cycle recorded' likewise splits: a young engine and one that has never
completed a cycle said the same thing, and only the second is a fault.
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