@@ -4874,11 +4874,31 @@ export class ApprovalService implements IApprovalService {
48744874 // fallback (#4414) warns and evaluates every out-edge, so the flow
48754875 // proceeds with `{decision:'revise'}` where `{resubmitted:true}` was owed.
48764876 //
4877- // The discriminator is exact and structural: `action: 'resubmit'` has
4878- // exactly ONE writer in this file (`resubmit`), it is inserted before
4879- // that resume, and a resubmit opens the next round as a NEW row — so at
4880- // most one such action row exists per request, and its presence means
4877+ // The discriminator's first two clauses are exact and structural:
4878+ // `action: 'resubmit'` has exactly ONE writer in this file (`resubmit`),
4879+ // and it is inserted before that resume. Its presence therefore means
48814880 // the last continuation this row issued was the resubmit.
4881+ //
4882+ // ⚠️ What does NOT hold is the third clause this comment used to claim —
4883+ // "a resubmit opens the next round as a NEW row, so at most one such
4884+ // action row exists per request". A resubmit whose own resume STRANDS
4885+ // opens no next round at all, so the row stays `returned`; once an
4886+ // operator re-arms the pause with `restoreConsumedSuspension`, a second
4887+ // `resubmit` by the same submitter passes every door guard and writes a
4888+ // SECOND `action: 'resubmit'` row. ⇒ MORE THAN ONE such row CAN exist
4889+ // for one request. Measured guard by guard, on that very row in that
4890+ // very state, in `stranded-resubmit-second-door.test.ts` (#17601 probe,
4891+ // PR #17613) — read it there rather than re-deriving it from here.
4892+ //
4893+ // The read below is correct anyway, for a reason that clause never
4894+ // needed: it is a PRESENCE check (`limit: 1`), so it decides identically
4895+ // on one row or two — the pin's MEASUREMENT C drives this resolver on
4896+ // the doubled row and it still answers `resubmit`. What the doubling
4897+ // costs is the audit trail's one-row-per-advancement shape, ⛔ not the
4898+ // edge picked here, and that cost is ACCEPTED RESIDUE under the #17601
4899+ // ruling of 2026-09-11 (option B: scope this prose to what was measured,
4900+ // narrow no door). Requiring one row per advancement is a new card, ⛔
4901+ // not a local fix here.
48824902 const resubmitted = await this . engine . find ( 'sys_approval_action' , {
48834903 where : { request_id : requestId , action : 'resubmit' } , limit : 1 , context : SYSTEM_CTX ,
48844904 } ) ;
0 commit comments