[object Object]

← back to Dw Signup Fulfillment

TK-11285: correct my own overclaim in the f9de58c write-up

534d1f633f0a2a13294596a02501d87ff013f95c · 2026-09-10 08:11:03 -0700 · Steve Abrams

Cody's re-gate returned FIX FIRST (narrowed): the bidirectional race fix is
genuine and it independently re-verified it, but I mischaracterized the
leftover link_status/link_error problem. Verified the correction myself.

f9de58c's message attributes the self-contradictory row (status:'approved' +
valid shopify_customer_id + link_status:'unlinked' + stale link_error) to the
clobber. That is overclaimed. The same shape appears with ZERO concurrency:
approve() resolves the customer through its findCustomerByEmail fallback and
stamps shopify_customer_id, but never reconciles link_status/link_error. It
needs no second writer and predates all TK-11285 work.

So the `self_contradictory` assertion in reverse-race.js was not a race
detector - it would have fired solo too. Renamed to
contradictory_shape_not_race_specific, explicitly documented as not evidence of
the race, and the harness gained a --solo control that demonstrates the
contradiction with no concurrent writer at all
(verification/tk11285/reverse-race-solo.json).

What actually IS the clobber, and what f9de58c genuinely fixes: a value that was
'linked' ON DISK being reverted to 'unlinked' by the service's stale row
snapshot. Those assertions are now gated on a second writer having run, so they
can no longer be satisfied by the solo gap. Race mode still reports CLAIM NOT
REPRODUCED after the fix.

The reconciliation gap is split to TK-11377 rather than folded in here - the
naive repair (set link_status='linked') would make already-approved designers
eligible for recover-stuck-apps.js --send-only's activation letter, which is a
product decision, not a mechanical fix. Non-blocking for this deploy.

No production code changed in this commit - evidence and wording only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEDp3MXiKVJ5GDKaQCHZon

Files touched

Diff

commit 534d1f633f0a2a13294596a02501d87ff013f95c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Sep 10 08:11:03 2026 -0700

    TK-11285: correct my own overclaim in the f9de58c write-up
    
    Cody's re-gate returned FIX FIRST (narrowed): the bidirectional race fix is
    genuine and it independently re-verified it, but I mischaracterized the
    leftover link_status/link_error problem. Verified the correction myself.
    
    f9de58c's message attributes the self-contradictory row (status:'approved' +
    valid shopify_customer_id + link_status:'unlinked' + stale link_error) to the
    clobber. That is overclaimed. The same shape appears with ZERO concurrency:
    approve() resolves the customer through its findCustomerByEmail fallback and
    stamps shopify_customer_id, but never reconciles link_status/link_error. It
    needs no second writer and predates all TK-11285 work.
    
    So the `self_contradictory` assertion in reverse-race.js was not a race
    detector - it would have fired solo too. Renamed to
    contradictory_shape_not_race_specific, explicitly documented as not evidence of
    the race, and the harness gained a --solo control that demonstrates the
    contradiction with no concurrent writer at all
    (verification/tk11285/reverse-race-solo.json).
    
    What actually IS the clobber, and what f9de58c genuinely fixes: a value that was
    'linked' ON DISK being reverted to 'unlinked' by the service's stale row
    snapshot. Those assertions are now gated on a second writer having run, so they
    can no longer be satisfied by the solo gap. Race mode still reports CLAIM NOT
    REPRODUCED after the fix.
    
    The reconciliation gap is split to TK-11377 rather than folded in here - the
    naive repair (set link_status='linked') would make already-approved designers
    eligible for recover-stuck-apps.js --send-only's activation letter, which is a
    product decision, not a mechanical fix. Non-blocking for this deploy.
    
    No production code changed in this commit - evidence and wording only.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01NEDp3MXiKVJ5GDKaQCHZon
---
 verification/tk11285/reverse-race-solo.json | 19 +++++++++++++++++++
 verification/tk11285/reverse-race.js        | 19 ++++++++++++++-----
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/verification/tk11285/reverse-race-solo.json b/verification/tk11285/reverse-race-solo.json
new file mode 100644
index 0000000..a5e61d4
--- /dev/null
+++ b/verification/tk11285/reverse-race-solo.json
@@ -0,0 +1,19 @@
+{
+  "claim": "service (checkpointApproval) clobbers recover-owned fields with a pre-await row snapshot",
+  "approve_ok": true,
+  "recover_wrote": {
+    "link_status": "linked",
+    "recovery_emailed": true,
+    "recovered_at": "2026-09-10T00:00:00.000Z"
+  },
+  "final_row": {
+    "status": "approved",
+    "shopify_customer_id": "5551111",
+    "link_status": "unlinked",
+    "link_error": "shopify_create_failed"
+  },
+  "link_status_clobbered": false,
+  "receipt_clobbered": false,
+  "contradictory_shape_not_race_specific": true,
+  "VERDICT": "SOLO: contradictory row with NO concurrency (separate approve() gap)"
+}
diff --git a/verification/tk11285/reverse-race.js b/verification/tk11285/reverse-race.js
index 6902236..017349e 100644
--- a/verification/tk11285/reverse-race.js
+++ b/verification/tk11285/reverse-race.js
@@ -15,11 +15,12 @@ fs.writeFileSync(APPS, JSON.stringify({
   shopify_customer_id: null, link_status: 'unlinked', link_error: 'shopify_create_failed',
 }) + '\n');
 
+const SOLO = process.argv.includes('--solo'); // control: no second writer at all
 let injected = false;
 // Interleave the recover script's OWN commitRows, from a separate process, during
 // the service's first await.
 global.__inject = () => {
-  if (injected) return; injected = true;
+  if (SOLO || injected) return; injected = true;
   execFileSync(process.execPath, ['-e', `
     const p=require(${JSON.stringify(path.join(ROOT, 'scripts', 'recover-stuck-apps.js'))});
     const rows=p.readRows();
@@ -43,10 +44,18 @@ global.__inject = () => {
       link_status: after.link_status, link_error: after.link_error,
       recovery_emailed: after.recovery_emailed, recovered_at: after.recovered_at,
     },
-    link_status_clobbered: after.link_status !== 'linked',
-    receipt_clobbered: after.recovery_emailed !== true,
-    self_contradictory: after.status === 'approved' && !!after.shopify_customer_id && after.link_status !== 'linked',
+    // The CLOBBER is: a value that was 'linked' ON DISK got reverted to 'unlinked'.
+    // Only meaningful when a second writer actually wrote 'linked' first.
+    link_status_clobbered: !SOLO && after.link_status !== 'linked',
+    receipt_clobbered: !SOLO && after.recovery_emailed !== true,
+    // NOT a race detector. approve() resolves the customer via the email_lookup
+    // fallback but never reconciles link_status/link_error, so this same
+    // contradictory shape appears with ZERO concurrency - run with --solo to see it.
+    // Tracked separately; do not read it as evidence of the race.
+    contradictory_shape_not_race_specific: after.status === 'approved' && !!after.shopify_customer_id && after.link_status !== 'linked',
   };
-  out.VERDICT = (out.link_status_clobbered || out.receipt_clobbered) ? 'CLAIM CONFIRMED — service clobbers' : 'CLAIM NOT REPRODUCED';
+  out.VERDICT = SOLO
+    ? (out.contradictory_shape_not_race_specific ? 'SOLO: contradictory row with NO concurrency (separate approve() gap)' : 'SOLO: clean')
+    : ((out.link_status_clobbered || out.receipt_clobbered) ? 'CLAIM CONFIRMED — service clobbers' : 'CLAIM NOT REPRODUCED');
   console.log(JSON.stringify(out, null, 2));
 })();

← f9de58c TK-11285: the race was bidirectional — stop the service clob  ·  back to Dw Signup Fulfillment  ·  TK-11285: stop the deploy itself from destroying the live ap a95eaa2 →