DONE evidence — intake fe05735a (CLI gap: receive-payment / link-payment should create dependent "Mark invoice paid in Finom" task)
Verdict: already implemented and merged on origin/main; verification-only session — no product code changes needed. This session verified the behavior end to end, re-ran the targeted tests on current main, and confirmed the handoff's acceptance criteria are each covered by an existing test.
backend/src/sponsorFinance/finomPaidTask.ts(introduced 4524ec57, extended 36028078):finomPaidTaskActionsleaves exactly one open "Mark invoice <number> paid in Finom" Task per deal (finomPaidTaskDescription), an ordinary cardless Task withsubject: sponsor-deal,source: sponsor-finom,tags: [finom-invoice-paid],instructionDocId: sop.finance.bookkeeping.marking-invoice-as-paid-in-finom, duedate= today (Berlin),dependsOn: [payment/receipt sourceId], andassigneeIdresolved byresolveDealOwnerId(deal owner → organization owner → deal/organization creation actor → workspace assignment policy;createdBystays the payment actor).backend/src/sponsorFinance/repository.tslinkPayment(): callsfinomPaidTaskActionsand puts...finom.actionsinside the sameTransactWritethat commits the payment link, so the Task exists if and only if the payment commits (or the deal's open one is adopted);details: { finomTaskId, finomTaskCreated }is recorded on thepayment-linkedhistory event.receivePayment()delegates tolinkPayment()with the prepared receipt source, so every CLI entry that records cash rides the same transaction:dataops sponsors receive-payment(POST/api/sponsor-crm/deals/:id/finance/receipts),dataops sponsors link-payment(POST/finance/payments),dataops reconcile confirm(posts the same two endpoints,cli/src/commands/reconcile.mjs:268,279) anddataops sponsors payment-mail confirm(POST/finance/receipts).backend/src/db/taskDependencies.ts: a committed receipt satisfies the Task's payment prerequisite; unlinking the payment makes it unmet and blocks completing the Task with409 prerequisites-incomplete.cli/skill/SKILL.mddocuments the payment follow-through (thank-you SOP step 10).
Idempotency, per criterion 3: a second payment on the same deal does not create a parallel Task —
finomPaidTaskActions adopts the deal's open Finom Task (appends the new sourceId to dependsOn,
version-checked update); a fresh Task row is keyed by finance-<digest({dealId, sourceId, finom: 'invoice-paid'})> so the next receipt after a resolved Task gets its own row; identical
retries with the same Idempotency-Key replay via replayMutation; concurrent receipts converge on
one Task (one 200, one 409).
The prior agent attempt origin/agent/fe05735a-73645e3e (commit 793ec5e2, "Link Finom paid Task
dependsOn to payment step and assign deal owner") has git patch-id
0c95739dcbe948c2128342df8c6d17bfda2a0073, identical to origin/main commit 36028078 — it was
merged verbatim. The base feature (creation/adoption + first tests) landed as 4524ec57. Nothing was
left to implement.
| Criterion | Evidence |
|---|---|
| 1. Verify first; implement only the gap | Inspected cli/src/commands/sponsors.mjs (receivePayment, linkPayment, sibling followUp), the sibling task-creation convention (paymentFollowUp.ts), and git log. Gap = none; see merge evidence above. |
| 2. Task auto-created on receive-payment / link-payment, linked, owner-assigned, dated | ddb test "creates the single Finom Task with instruction, owner, due date and payment dependency on receive-payment" (asserts description, instructionDocId, assigneeId = deal owner, dependsOn = receipt sourceId, date = today, subject) and "link-payment creates the same Finom Task for a ledger row linked after the fact" (org-owner fallback; unlink blocks completion). |
| 3. No duplicate on second call (reuse/adopt open task with the same link) | ddb tests "replays a retried receive-payment to the same single Task", "a second receipt adopts the open Task instead of creating parallel work" (dependsOn grows to [firstSourceId, secondSourceId]), "concurrent receipts converge on exactly one open Finom Task". |
| 4. Targeted tests only | No new tests needed — the existing suite already pins every criterion; this session re-ran them (below) and changed no test files. |
Tests re-run 2026-11-04 (worktree of branch fix/receive-payment-dependent-task = origin/main d213cf9b)
backend/tests/sponsor-finance-finom-task.ddb.ts against real DynamoDB Local
(docker run amazon/dynamodb-local -inMemory -sharedDb, the same gate
backend/scripts/test-sponsor-finance-transaction.sh uses):
7/7 pass, 0 fail —
- creates the single Finom Task with instruction, owner, due date and payment dependency on receive-payment
- replays a retried receive-payment to the same single Task
- a second receipt adopts the open Task instead of creating parallel work
- a resolved Task lets the next receipt create a fresh one
- link-payment creates the same Finom Task for a ledger row linked after the fact
- concurrent receipts converge on exactly one open Finom Task
- an unrelated open deal Task is never adopted as the Finom Task
backend/tests/sponsor-finance.test.ts (unit, includes finomPaidTaskDescription /
finomPaidTaskActions): 16/16 pass, 0 fail.
hub intake show fe05735a→Intake HTTP 503: request_failed(service unavailable during the session), so the live task record could not be read; verification is from git, source and tests.- Read-only
GET /api/tasks, fully paginated: 532 todo + 88 waiting + 1406 done = 2024 Tasks scanned, 0 withsource: sponsor-finomor tagfinom-invoice-paid. No open Finom Task exists (no payment has been recorded through the new path since it merged 2026-11-03) and no duplicate rows exist anywhere in the pool.
- None against the acceptance criteria.
- Observation, not a criterion: the CLI's
receive-payment/link-paymentstdout does not print the created/adopted Finom Task id (the route result carriesfinanceVersion/recordIdonly; the id lives in the server-side history event). The Task surfaces throughdataops sponsors show deals <id>openTasks anddataops sponsors finance <deal-id>(paymentFollowUp.existingTasks). Left untouched to avoid unrelated churn.