[object Object]

← back to Dw Sku Integrity

TK-10896: Cody-gate hardening — within-batch shared-candidate reporting + doc precision

2fb7252e1bf7ecf07f706921e9b5156c83a0c261 · 2026-08-30 09:39:18 -0700 · codex-10896

Cody flagged 2,552 rows as undetected collisions; VERIFIED false — they are same-
pattern sellable+sample pairs (identical title+handle) that correctly share one
canonical dw_sku (which is intentionally non-unique). Rejected the mislabel; instead:
(1) scanner now reports within_batch_shared_candidates (1,276 groups/2,552 rows,
benign) + per-row shared_pattern_candidate flag so a downstream apply upserts;
(2) README no-mint claim corrected to no-fabrication + guard-conditional no-mint;
(3) Bucket-A residue caveat quantified (4,084 rows in prefix, <=668 possibly minted,
needs mint ledger). 25 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 2fb7252e1bf7ecf07f706921e9b5156c83a0c261
Author: codex-10896 <steve@designerwallcoverings.com>
Date:   Sun Aug 30 09:39:18 2026 -0700

    TK-10896: Cody-gate hardening — within-batch shared-candidate reporting + doc precision
    
    Cody flagged 2,552 rows as undetected collisions; VERIFIED false — they are same-
    pattern sellable+sample pairs (identical title+handle) that correctly share one
    canonical dw_sku (which is intentionally non-unique). Rejected the mislabel; instead:
    (1) scanner now reports within_batch_shared_candidates (1,276 groups/2,552 rows,
    benign) + per-row shared_pattern_candidate flag so a downstream apply upserts;
    (2) README no-mint claim corrected to no-fabrication + guard-conditional no-mint;
    (3) Bucket-A residue caveat quantified (4,084 rows in prefix, <=668 possibly minted,
    needs mint ledger). 25 tests green.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 README.md                            | 16 +++++++++++++---
 dwsku-backlog-scan.mjs               | 23 ++++++++++++++++++++++-
 evidence/ANALYSIS-2026-08-30.md      | 26 +++++++++++++++++++-------
 evidence/mac2-mirror-2026-08-30.json |  5 +++++
 test/classify.test.mjs               | 13 +++++++++++++
 5 files changed, 72 insertions(+), 11 deletions(-)

diff --git a/README.md b/README.md
index b7a03c0..bf745dd 100644
--- a/README.md
+++ b/README.md
@@ -14,9 +14,19 @@ existing `sku`.
 
 - **Read-only.** The scanner issues only `SELECT`. It never `UPDATE`/`INSERT`/
   `DELETE`s, never writes the DB. Its only output is a local summary/plan file.
-- **No minting.** `classify.mjs` recovers codes by pure suffix-stripping; a unit
-  test (`INVARIANT: classifier never proposes a candidate absent from the row`)
-  enforces this.
+- **No fabrication.** `classify.mjs` recovers codes by pure suffix-stripping; a unit
+  test enforces that a proposed candidate is always a prefix of the row's existing
+  `sku` — it never invents a code absent from a DB field. NOTE this is a
+  *no-fabrication* guarantee, not an unconditional *no-mint* guarantee: a reverted
+  Phase-4 mint WROTE its code into `sku`, so residue is trivially "already in a
+  field." The **provenance guard** (greenfield-prefix routing) is what upgrades this
+  to no-mint — so the no-mint property holds *provided the guard catches all residue
+  prefixes*. Greenfield (Bucket B) is fully covered; a small Bucket-A subset (≤~668
+  rows minted into already-in-use prefixes) needs the exact reverted-mint ledger to
+  disambiguate and is flagged, not silently cleared (see `evidence/ANALYSIS`).
+- **dw_sku is intentionally non-unique.** A pattern's sellable + sample rows share one
+  canonical `dw_sku`. The scanner reports `within_batch_shared_candidates` (benign
+  same-pattern groups); an apply step MUST upsert, never assume per-row uniqueness.
 - Any actual `dw_sku` write is canonical + customer-facing → **gated** (drafted to
   `~/.claude/yolo-queue/pending-approval/`, ledgered, reversible). Not this repo's job.
 
diff --git a/dwsku-backlog-scan.mjs b/dwsku-backlog-scan.mjs
index 70b4147..bb3fc5b 100644
--- a/dwsku-backlog-scan.mjs
+++ b/dwsku-backlog-scan.mjs
@@ -67,8 +67,24 @@ const planLines = [];
 let selfCopyWithMfr = 0;
 let selfCopyNoMfr = 0;
 
+// First pass: count how many blank rows resolve to each self-copy candidate, so
+// we can distinguish a candidate shared by a pattern's own sellable+sample rows
+// (BENIGN — dw_sku is intentionally non-unique across a pattern's variants) from
+// a true cross-product collision (caught separately by the distinct-title test /
+// activeCodeSet check). A downstream apply MUST NOT treat dw_sku as a per-row
+// unique key; these shared groups are surfaced so it doesn't choke on them.
+const candCount = new Map();
 for (const [vendor, sku, mfr_sku, dw_sku, status] of rows) {
   const v = classifyRow({ vendor, sku, mfr_sku, dw_sku, status }, activeCodeSet);
+  if (v.candidate) candCount.set(v.candidate, (candCount.get(v.candidate) || 0) + 1);
+}
+let sharedGroupRows = 0;
+let sharedGroups = 0;
+for (const n of candCount.values()) if (n > 1) { sharedGroups++; sharedGroupRows += n; }
+
+for (const [vendor, sku, mfr_sku, dw_sku, status] of rows) {
+  const v = classifyRow({ vendor, sku, mfr_sku, dw_sku, status }, activeCodeSet);
+  const sharedCandidate = !!(v.candidate && candCount.get(v.candidate) > 1);
   byClass[v.class] = (byClass[v.class] || 0) + 1;
   const grp = RECOVERY_GROUP[v.class] || 'unknown';
   byGroup[grp] = (byGroup[grp] || 0) + 1;
@@ -79,7 +95,7 @@ for (const [vendor, sku, mfr_sku, dw_sku, status] of rows) {
   if (grp === 'rescrape_program_TK10900') {
     byVendorRescrape[vendor] = (byVendorRescrape[vendor] || 0) + 1;
   }
-  if (emitPlan) planLines.push(JSON.stringify({ vendor, sku, mfr_sku, class: v.class, candidate: v.candidate, collides: v.collides, group: grp }));
+  if (emitPlan) planLines.push(JSON.stringify({ vendor, sku, mfr_sku, class: v.class, candidate: v.candidate, collides: v.collides, shared_pattern_candidate: sharedCandidate, group: grp }));
 }
 
 const summary = {
@@ -95,6 +111,11 @@ const summary = {
     with_real_mfr_sku_cross_verifiable: selfCopyWithMfr,
     sku_only_no_independent_check: selfCopyNoMfr,
   },
+  within_batch_shared_candidates: {
+    note: 'BENIGN: same-pattern sellable+sample rows resolving to one shared dw_sku (dw_sku is intentionally non-unique per pattern). These are NOT collisions; an apply step must upsert, not assume per-row uniqueness. True cross-product collisions are counted under *_COLLISION classes.',
+    shared_candidate_groups: sharedGroups,
+    rows_in_shared_groups: sharedGroupRows,
+  },
   rescrape_cohorts_top: Object.fromEntries(Object.entries(byVendorRescrape).sort((a, b) => b[1] - a[1]).slice(0, 15)),
 };
 
diff --git a/evidence/ANALYSIS-2026-08-30.md b/evidence/ANALYSIS-2026-08-30.md
index 45bc921..3026ee8 100644
--- a/evidence/ANALYSIS-2026-08-30.md
+++ b/evidence/ANALYSIS-2026-08-30.md
@@ -56,8 +56,13 @@ specific way, and the guard makes the classifier robust to it either way.
 - Classifier + strip rule are correct and reproducible (24 tests green; validated on
   real sku shapes incl. `-Sample`, `-Yard`, `-Per Yard`, doubled `-Sample-Sample`,
   and non-numeric Elitis `DWEL-RM-…` cores).
-- Nothing was written to any database. No code was minted. Within-batch collision
-  check = 0 (no two distinct-title blanks collapse to one candidate).
+- Nothing was written to any database. No code was minted. Within-batch: 1,276
+  candidate groups (2,552 rows) share a code, but ALL are **same-pattern** (identical
+  title+handle: a pattern's sellable row + its `-Sample` row) → they *correctly* share
+  one canonical dw_sku. **True cross-product within-batch collisions = 0** (distinct-
+  title groups = 0). `dw_sku` is intentionally non-unique per pattern; a downstream
+  apply MUST upsert, not assume per-row uniqueness (scanner reports this under
+  `within_batch_shared_candidates`).
 - The 9 collisions match the memo's Phase-2 dedup class (Novasuede `DWCC-*-Per Yard`,
   Arte `DWKE-41415-Sample-Sample`) → TK-10649.
 - The re-scrape program is real (8,962 rows), dominated by Carnegie 5,921 — vindicating
@@ -67,9 +72,16 @@ specific way, and the guard makes the classifier robust to it either way.
 1. **Kamatera canonical run** — `DWSKU_PSQL='ssh <kam> psql' node dwsku-backlog-scan.mjs`
    for the authoritative segmentation (the guard means the mirror and canonical should
    now agree on routing even where `sku` residue differs).
-2. **Bucket A/C disambiguation** — greenfield (Bucket B) is unambiguous. For Bucket A
-   prefixes that were ALSO in scraper use (DWKN/DWTT/DWRW/DWJS/DWRO/DWCC, ~668 minted)
-   and the Romo `DWRO-30476..30966` reverted range, separating scraper-native from mint
-   requires the exact reverted-mint number list; until then those stay self-copy by
-   default (documented, low volume). Recommend sourcing the mint ledger to tighten this.
+2. **Bucket A/C disambiguation (Cody-flagged, quantified)** — greenfield (Bucket B) is
+   unambiguous and guarded. Bucket-A prefixes were ALSO in scraper use, so a blank row
+   carrying one is *usually* scraper-native — but the Phase-4 decision aid shows ~668
+   rows were minted into Bucket A (Knoll 505, Thibaut 64, RebelWalls 51, JS 12, Romo 11,
+   Nova 25) + the Romo `DWRO-30476..30966` reverted range. There are **4,084 blank rows
+   currently in Bucket-A prefixes** (DWJS 1,689, DWTT 1,517, DWKN 622, DWRW 203, DWCC 53);
+   at most ~668 of those could be mint residue, but WHICH ones needs the exact reverted-
+   mint number list to separate scraper-native from mint. **Until that ledger is sourced,
+   do NOT apply the Bucket-A self-copy subset** — treat those 4,084 as "verify against
+   mint ledger first." (Guarding all 4,084 outright would wrongly quarantine ~3,400
+   legitimate scraper-native rows, so this is a caveat + a per-vendor pre-apply check,
+   not a hard block.) Sourcing the mint ledger is the recommended next read-only step.
 3. Any `dw_sku` write is canonical + customer-facing → gated, per-vendor batch, ledgered.
diff --git a/evidence/mac2-mirror-2026-08-30.json b/evidence/mac2-mirror-2026-08-30.json
index 2675229..f2bd2f8 100644
--- a/evidence/mac2-mirror-2026-08-30.json
+++ b/evidence/mac2-mirror-2026-08-30.json
@@ -25,6 +25,11 @@
     "with_real_mfr_sku_cross_verifiable": 9814,
     "sku_only_no_independent_check": 15809
   },
+  "within_batch_shared_candidates": {
+    "note": "BENIGN: same-pattern sellable+sample rows resolving to one shared dw_sku (dw_sku is intentionally non-unique per pattern). These are NOT collisions; an apply step must upsert, not assume per-row uniqueness. True cross-product collisions are counted under *_COLLISION classes.",
+    "shared_candidate_groups": 1276,
+    "rows_in_shared_groups": 2552
+  },
   "rescrape_cohorts_top": {
     "Carnegie": 5921,
     "Maharam": 1429,
diff --git a/test/classify.test.mjs b/test/classify.test.mjs
index 804ef0c..ec3cf74 100644
--- a/test/classify.test.mjs
+++ b/test/classify.test.mjs
@@ -147,6 +147,19 @@ test('PROVENANCE GUARD: greenfield set is configurable via opts', () => {
   assert.equal(classifyRow({ status: 'active', dw_sku: '', sku: 'DWAG-1-Sample' }, new Set(), opts).class, 'SELF_COPY_DW');
 });
 
+test('BENIGN SHARED CODE: a pattern sellable + its -Sample resolve to the SAME candidate and both stay SELF_COPY_DW (not a collision)', () => {
+  // Same pattern, two rows (sellable + sample). dw_sku is intentionally shared.
+  const bare = classifyRow({ status: 'active', dw_sku: '', sku: 'DWPP-206465' }, new Set());
+  const samp = classifyRow({ status: 'active', dw_sku: '', sku: 'DWPP-206465-Sample' }, new Set());
+  assert.equal(bare.candidate, 'DWPP-206465');
+  assert.equal(samp.candidate, 'DWPP-206465');
+  assert.equal(bare.class, 'SELF_COPY_DW');
+  assert.equal(samp.class, 'SELF_COPY_DW');
+  // Neither is flagged as a collision — they belong to the same pattern.
+  assert.equal(bare.collides, false);
+  assert.equal(samp.collides, false);
+});
+
 test('UNIT_SUFFIXES includes the observed vocabulary', () => {
   for (const w of ['Sample', 'Yard', 'Roll', 'Panel', 'Bolt', 'Per Yard']) {
     assert.ok(UNIT_SUFFIXES.includes(w), `${w} missing from UNIT_SUFFIXES`);

← 04762e2 TK-10896: record Claude-Codex no-mint comparison proof  ·  back to Dw Sku Integrity  ·  Revert "TK-10896: record Claude-Codex no-mint comparison pro 58d16de →