Skip to content

A mirror cut short at a size or time cap reported Success - #163

Merged
xroche merged 2 commits into
masterfrom
fix/capstop
Aug 24, 2026
Merged

A mirror cut short at a size or time cap reported Success#163
xroche merged 2 commits into
masterfrom
fix/capstop

Conversation

@xroche

@xroche xroche commented Aug 24, 2026

Copy link
Copy Markdown
Owner

A mirror the engine cut short at a size or time cap still reported "Success!". back_checkmirror() asks for a smooth stop when maxsite or maxtime is reached. That sets the engine's stop flag but no abort flag, and the user tapped nothing, so the pane saw a clean run. The line above it disagreed: pendingWork already counted the run as resumable and offered to continue it.

The stop source is read once now, as MirrorOutcome.Stop, and feeds both the pane and the resume offer. A cap reports "Stopped!" and says a limit was reached. A user stop and a real abort still outrank it, because reaching a cap also makes the engine report itself stopped. Reading the source once closes a second gap: interrupted is volatile and was read twice, so a stop landing between the two reads could leave the pane and the resume offer disagreeing.

InterruptedLockTest pinned the old expression verbatim, so a behaviour-preserving rewrite failed it. It pins the property instead: the resume offer must read the run's verdict, without narrowing it to one kind of stop.

xroche and others added 2 commits August 24, 2026 11:27
back_checkmirror() asks for a smooth stop when maxsite or maxtime is
reached (htsback.c:4841-4853). That sets state.stop and no abort flag, and
the user tapped nothing, so the pane saw a clean run and said so. The line
above it disagreed: pendingWork already counted the run as resumable and
offered to continue it.

The stop source is read once now, as MirrorOutcome.Stop, and feeds both
the pane and the resume offer, so they cannot contradict each other again.
A user stop and a real abort still outrank a cap, because reaching a cap
also makes the engine report itself stopped.

InterruptedLockTest pinned the old expression verbatim, which made a
behaviour-preserving rewrite fail it. It pins the property instead: the
resume offer must not read the user's stop alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
The review found the assertion I wrote to replace #158's guard was
strictly weaker than the one it replaced. Rewriting the production line
was fair, since stop != NONE is equivalent to the old expression, but
contains("engine.wasStopped()") is satisfied by the ternary anywhere in
runInternal, so leavesPendingWork(stop == Stop.USER, code) brought #158
back with both assertions green. The argument is now taken with balanced
parentheses instead of up to the first comma, and it must read the run's
verdict without narrowing it to one kind of stop.

Changing false to Stop.ENGINE in two existing rows also left no row
pairing Stop.NONE with a live abort code, so an abort that never set the
stop flag could read as a success. Those rows are back alongside the new
ones.

Three more the same pass found: transposing the ternary's branches was
invisible, so each branch is pinned to its source; the pane's first
argument is pinned by position rather than by a four-character substring
a comment could satisfy; and the new Stopped! wording was pinned to
nothing.

STOPPED_AT_LIMIT moves after the aborts, because declaration order read
as a precedence and of() ranks it last. Stop.ENGINE's comment claimed the
cap, which is only what of() decides later.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche merged commit 2f3b6a2 into master Aug 24, 2026
6 checks passed
@xroche
xroche deleted the fix/capstop branch August 24, 2026 16:46
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