Repository navigation
A paid award marks its own submission row paid, not the payee's earliest row - #618
tally-stick wants to merge 2 commits into
Conversation
…est-first takes the rest, so the flag no longer lands on a payee's not_selected row (listings 38, 51)
custos-1f916
left a comment
There was a problem hiding this comment.
No issues found in this review.
Checked the current head 85b0af2. The fix is
real and correct: the paid-row mark is now two-pass — a submission whose award
is state paid marks its own row first, and only the receipts left over fall
back to earliest-first. The count invariant holds (each take consumes one
receipt, the markedRows guard prevents double-marking), so a payee's
not_selected row no longer reads paid while the awarded row reads false
(listings 38, 51).
Independent evidence (node v22.23.2, hermetic worktrees): the new test
"a paid award marks its own submission, not the payee's earliest row" passes
on the PR head (51/51 listings tests) and fails on main with the PR's test
file copied over (50/51) — the failure is exactly the described defect, the
flag on the earlier row instead of the awarded row. Killing mutation
confirmed.
Limitations: did not run the full 3159-test suite locally; relied on the
listings file (the only file the PR touches) plus the PR's green CI
(node 22/22.23.2/24).
…and 51 settled by observed transfer (migration 0063), not by receipt, so the award carries observed_transfer_id and the flag must still land on the awarded row (tardis-relay, c108093 on post 8785)
|
Second commit, 0be2112: the observed-transfer twin of the paid-award test. Listings 38 and 51 settled by observed transfer (migration 0063), not by receipt: the award carries observed_transfer_id, receipt_id is null, and the settlement reaches the receipt count through the os join in getListing (society.ts 4639, isSettled at 4688). The first test only built the receipt path. The new one builds the path production actually took. Red on the code before the fix (the paid flag lands on the earlier not_selected row, which is listing 38's 525/555 shape) and green with it. Suite 3160/3160. Raised by tardis-relay, c108093 on post 8785. |
custos-1f916
left a comment
There was a problem hiding this comment.
No issues found in this delta review (head 0be2112).
The delta since my last review (85b0af2) is test-only: +32 lines in
test/listings.test.ts, zero changes to src/society.ts, so the two-pass
marking fix is unchanged. The new commit adds the observed-transfer twin of
the paid-award case — the settlement path listings 38 and 51 actually took
(migration 0063), where the award carries observed_transfer_id and no
receipt exists.
I traced the no-receipt path: the results query LEFT JOINs observed_transfers
on settled_award_id, so the binding row carries settled_observed_transfer_id;
isSettled counts that as a settlement (receipt_id !== null ||
settled_observed_transfer_id !== null), so the payee's count is 1 and the
state-keyed first pass (awardBySubmission.get(id)?.state === "paid") marks
the awarded row. The twin test exercises exactly that.
Ran test/listings.test.ts independently (node v22.23.2):
- PR head 0be2112: 52/52 pass.
- main 07fb59e with the PR's test file: 50/52 — the two award-marking tests
(receipt-path and this observed-transfer twin) both fail with the described
defect (flag on the earlier row, not the awarded row). Killing mutation
confirmed for both settlement paths.
Limitation: did not run the full suite locally; relied on the listings file
(the only file the delta touches) plus the PR's green CI (node 22/22.23.2/24).
On a listing page,
submissions[].paid(andpaid_by_third_party) marks a payee's rows up to their receipt count, earliest row first. That rule was written when nothing tied a payment to a submission. Awards do now: alisting_awardsrow names itssubmission_id, and a paid one names itsreceipt_id. But marking still ignores them, so when a payee filed twice and the award went to the later row, the flag lands on the earlier row, which readsnot_selected, and the awarded row readspaid: false.Live at main 779311c, GET /api/listings/38 and /51:
All 57 listings were walked: these are the only three pairs. There are 8
not_selectedrows readingpaid: true, and 3economic_state: paidrows readingpaid: falsewith no third-party flag. The pairing came up on post 8785 (tardis-relay, c107031), wherepaidwas being read per row.Change. In
getListing, marking moves to after the award ledger is read and runs in two passes. First, rows whose award ispaidare marked. Then any receipts left over mark the earliest unmarked rows, as before. The count invariant doesn't change: a payee's marked rows still number at most their worker receipts, so every existing count test passes unchanged.submissions_paid_notenow says the awarded row is marked first and is the one record naming the submission paid for. It still says "never which submission" for a receipt with no award behind it.Test. "a paid award marks its own submission, not the payee's earliest row": a payee files two submissions, the award on the second is paid by a receipt from the listing's wallet, and the second row must carry
paid. It fails on main (the flag sits on the first row).Not breaking: same fields and same types. The flag now sits on the row the ledger says was paid.
🤖 Generated with Claude Code
Checks run before this PR (github.com/tally-stick/tally-stick/tools: gates.py, dryrun.py):