← back to Tk 10965 Zero Price Analysis
FINDINGS.md
73 lines
# TK-10965 — Zero-price-orderable canary FAIL: root-cause analysis (READ-ONLY)
**Ticket:** TK-10965 (analysis) · underlying alert **TK-10963** (`zero-price-orderable-canary` verdict FAIL)
**Analyst:** codex-10965 · **Date:** 2026-08-30 · **Method:** live Shopify Admin GraphQL reads + `dw_unified` mirror reads. **No Shopify or DB writes.**
**Store:** `designer-laboratory-sandbox.myshopify.com` (the LIVE production DW store).
---
## 1. The defect (what the canary caught)
`zero-price-orderable-canary` (`~/.claude/skills/zero-price-orderable-canary/check.mjs`) flags any **ACTIVE, `quote-only`-tagged** product whose **non-Sample variant** has `price == 0` **and** `availableForSale == true`. Such a variant can be added to cart and **checked out for $0**, bypassing the quote-only ("contact for price") flow.
Latest verdict: **FAIL — 1,281 of 1,455 quote-only-active products (88%)** have a $0 orderable non-sample variant. All flagged products are **Phillipe Romano** (the "Vienna It's Electric" contract-vinyl line and siblings). This is real, not a phantom — confirmed by independent live reads.
## 2. Quantified root cause — 100% uniform
Live inspection of **all 1,281** flagged variants (`evidence/tk10965_quant.mjs`):
| Signal | Value across flagged variants |
|---|---|
| `inventoryPolicy` | **DENY** — 1281/1281 (100%) |
| `inventoryQuantity` | **2026** — 1281/1281 (100%) |
| `inventoryItem.tracked` | **true** — 1281/1281 (100%) |
| `price` (non-sample "Per Yard") | **0.00** |
**Mechanism.** Shopify derives `availableForSale ≈ (tracked && quantity > 0) || policy == CONTINUE`. Here the variant is purchasable **purely because `quantity = 2026 > 0`**. `inventoryPolicy = DENY` is inert — DENY only blocks purchase when `quantity ≤ 0`. So the buyable-at-$0 state is driven entirely by the stamped quantity.
**`2026` is not a stock count — it is a hard-coded year-as-sentinel.** Provenance (`grep`, read-only):
- `Designer-Wallcoverings/DW-Programming/command54-shopify-push.js` and `justindavid-shopify-push.js` (both Phillipe-Romano private-label push scripts) contain **`setInventory2026()`**, which sets `on_hand = 2026` at the Ventura Blvd location on the **sellable (non-Sample) SKU**, plus `inventory_quantity: 2026` on product create. Header comment: *"All-channels publish + inventory-2026 on activation (Steve 2026-06-20, memory activation-all-channels-and-2026-inventory) … Cap-free."*
- The same `setInventory2026` / `quantity: 2026` convention appears in **~20 importer scripts**, including the canonical live importer `Designer-Wallcoverings/shopify/scripts/cadence/cadence-import.js` and the shared `.../templates/new-product-import-template.js`.
**So this is a design collision, not an accident.** An activation policy deliberately stamps a large arbitrary in-stock number (the year `2026`) on the sellable variant — intended to keep products from reading "out of stock" on sales channels (Google/GMC etc.). That policy collides head-on with **quote-only $0 pricing**: a sellable variant that is (a) priced $0 and (b) given positive tracked stock is, by Shopify's rules, **purchasable for $0**. `DENY` cannot save it.
Corroborating detail: on each flagged product the **Sample** variant is correctly `qty=0 → availableForSale=false`, i.e. the product's *own* Sample variant already demonstrates the non-orderable state the sellable variant should have.
## 3. Corrections to the prior analysis (TK-10963 / existing memo)
The earlier `vp-dw-commerce` pass and the drafted memo `pending-approval/zero-price-orderable-1281-quoteonly-REMEDIATION.md` state two things this investigation **disproves with live data**:
1. **"The bug is `inventory_policy=CONTINUE`."** — **False.** 0 of 1,281 are CONTINUE; all 1,281 are **DENY**. The cause is `quantity=2026`, not the policy. Therefore the memo's proposed remediation *"set inventory policy to DENY"* is a **no-op** — it is already DENY.
2. **"De Gournay proves the fix: identical setup but DENY+0 → not orderable."** — **Misread.** De Gournay's variants are also `DENY, qty=2026, availableForSale=true`. De Gournay is simply **not flagged because it has no $0 non-sample variant** (it is structurally sample-priced), *not* because it is guarded. It is not a valid reference for the fix.
The correct fix is **`quantity → 0`** on the sellable variant (keep DENY + tracked), which is exactly the state PR's own Sample variant already has.
## 4. True blast radius — the canary UNDERCOUNTS by 462
The canary searches only `tag:'quote-only'`. A vendor-scoped scan (`verify.mjs`) finds the **identical `qty=2026` defect on Fentucci Naturals**, which is tagged `quotes` / `Needs-Price` and carries **zero** `quote-only` tags — so the canary never sees it.
| Vendor | Active scanned | $0-orderable | qty==2026 | Seen by canary? |
|---|---|---|---|---|
| Phillipe Romano | 12,000 | **1,281** | 1,281 | yes (tagged quote-only) |
| Fentucci Naturals | 504 | **462** | 462 | **NO — canary blind spot** |
| De Gournay | 172 | 0 | 0 | n/a (no $0 variant) |
| Atomic 50 Ceilings | 2 | 0 | 0 | n/a |
| **TOTAL** | | **1,743** | **1,743 (100%)** | canary sees 1,281 = **73%** |
**26.5% of the true defect population is invisible to the standing canary.** Remediation must be scoped to **1,743**, and the canary itself must be broadened (see REMEDIATION.md §Prevention).
## 5. Impact
- **Revenue leak / free goods:** any customer can check out a contract wallcovering "Per Yard" variant for **$0** on 1,743 live products.
- **Quote-only bypass:** these lines have **no public retail price by design**; a $0 order also skips the intended "get a quote" commercial flow.
- **GMC exposure (secondary):** a $0-priced offer with positive stock is also disapproval-bait on Google Shopping — the very channel the `setInventory2026` policy was trying to serve.
## 6. Reproduction / evidence
- `verify.mjs` — re-runnable READ-ONLY acceptance test. `exit 0` = clean, `exit 1` = defect present. Also emits `evidence/verify-latest.json`.
- `evidence/tk10965_probe.mjs` — single-product variant dump (PR flagged / Fentucci / De Gournay).
- `evidence/tk10965_quant.mjs` — full flagged-set mechanism tabulation (policy/qty/tracked).
- `evidence/tk10965_vendors.mjs` — bounded per-vendor blast-radius scan.
- `evidence/verify-latest.json` — machine-readable snapshot from the latest `verify.mjs` run.