main.qml kept a `connected*CommandSource` string for usage, cost, sessions and
provider config beside the `activeUsageCommands` map, and routed every reply by
comparing the source name against them in turn. The map already knew: each entry
carries the `kind` those properties encode. The timeout handler checked both
halves at once, five times over:
if (descriptor.kind === "cost" && sourceName === connectedCostCommandSource)
Move the nonce, the descriptor, the deadline scan and the lookup behind
CommandLedger.js, and delete the four properties and their 56 references.
Replies now route on the ledger entry, and a reply the ledger no longer holds
returns before any parse runs.
That is the same staleness rule as before, stated once rather than four times.
Starting a newer command retires the older source name, so a late reply from the
retired run is absent from the ledger and cannot overwrite the fresher result.
Before this it depended on the routing chain and the shadow property agreeing.
tests/tst_command_ledger.qml adds 23 cases, including the retired-run drop that
had no behavioural test at all, the deadline boundary, and account commands
which are waited on without a clock and must not keep the timeout timer running.
The static checks that named the shadow properties now assert the ledger and
reject the properties by name. The updater keeps its own single-slot
`connectedUpdateCommandSource`: it runs on a separate DataSource and is out of
scope here.Simone committed on 8/19/2026, 12:50:54 PMparenta75a843
6 files changedLine totals unavailable