fix(cassettes): say when the counts are unverified instead of reporting a guess

When the dispenser throws or the dispense times out there is no per-bay
report, so nothing is debited — not the cassette rows, not HAL's bays.
Bills may well have reached the customer, and both counters then read
high with nothing to indicate it. The machine went on treating a number
it had reason to doubt as measurement.

A dispense that ends with no report now latches a countsUncertainSince
flag, which rides along in the state document as counts_uncertain_since
so the operator can see the numbers need a recount. The field is
additive: a consumer reading positions ignores it, so this needs no
coordinated release. An operator config apply clears the flag inside the
same transaction, since asserting authoritative counts is precisely what
a recount is.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-09-22 22:14:06 +02:00
commit 474903c38b
7 changed files with 130 additions and 2 deletions

View file

@ -24,7 +24,9 @@ import {
markCommandExecuting,
completeCommand,
getLastKnownConfigCreatedAt,
getCountsUncertainSince,
getLastStatePublishedAt,
markCountsUncertain,
markStatePublished,
resetStatePublishWatermark,
resetForRepair,
@ -556,6 +558,10 @@ ipcMain.handle('state:get-last-known-config-created-at', (): number =>
getLastKnownConfigCreatedAt()
)
ipcMain.handle('state:get-last-state-published-at', (): number | null => getLastStatePublishedAt())
ipcMain.handle('state:get-counts-uncertain-since', (): number | null => getCountsUncertainSince())
ipcMain.handle('state:mark-counts-uncertain', (_event, unixTimestamp: number): void => {
markCountsUncertain(unixTimestamp)
})
ipcMain.handle('state:mark-state-published', (_event, unixTimestamp: number): void => {
markStatePublished(unixTimestamp)
})