← back to Sanderson Onboard
tk10873/cross_validate_feed.mjs
111 lines
#!/usr/bin/env node
// cross_validate_feed.mjs — TK-10873 cycle 4. Cross-validate the Option-A REPRICE
// proposed prices (sourced from zoffany_catalog.price_retail) against the INDEPENDENT
// SDG S1 feed harvest (pilot/zoffany_feed_harvest.jsonl, from TK-10877 — a different
// price source), keyed by mfr_sku.
//
// READ-ONLY. NO SHOPIFY/DB WRITES, NO http/fetch. Reads two local files only.
//
// Why: the sanity gate could only "legibility-check" 238/328 retail-only prices with no
// independent cost floor (Cody cycle-3). The feed harvest is that missing 2nd source.
//
// FINDING (cycle 4): the two sources are cleanly BIMODAL — ~30 agree (ratio ~1.0) and
// a large cohort disagree by a near-constant ~2.543x (== 2 * 1.27, i.e. a double-roll x
// GBP->USD unit/currency transform). Where the feed price is ~2.54x the draft price, the
// draft (zoffany_catalog) value is potentially a ~2.5x UNDERPRICE. This does NOT auto-
// resolve which source is canonical — it FLAGS the discrepancy for Steve/pricing-owner.
import fs from 'node:fs';
const DIR = new URL('.', import.meta.url).pathname;
const DRAFT_IN = `${DIR}zoffany_optionA_draft.json`;
const FEED_IN = '/Users/macstudio3/Projects/sanderson-onboard/pilot/zoffany_feed_harvest.jsonl';
const JSON_OUT = `${DIR}cross_validate_feed.json`;
const MD_OUT = `${DIR}cross_validate_feed.md`;
// classification thresholds
const AGREE_TOL = 0.02; // |ratio-1| < 2% => sources agree
const UNIT_LO = 2.3, UNIT_HI = 2.8; // ratio in this band => the ~2.54x unit/currency discrepancy
export function classifyVsFeed(proposed, feedRetail) {
const p = Number(proposed), f = Number(feedRetail);
if (!Number.isFinite(f) || f <= 0) return { klass: 'UNVERIFIABLE', ratio: null };
if (!Number.isFinite(p) || p <= 0) return { klass: 'BAD_PROPOSED', ratio: null };
const ratio = f / p;
if (Math.abs(ratio - 1) < AGREE_TOL) return { klass: 'CONFIRMED', ratio };
if (ratio >= UNIT_LO && ratio <= UNIT_HI) return { klass: 'DISCREPANT_UNIT_2_5X', ratio };
return { klass: 'DISCREPANT_OTHER', ratio };
}
function loadFeed() {
const map = new Map();
for (const line of fs.readFileSync(FEED_IN, 'utf8').trim().split('\n')) {
const r = JSON.parse(line);
if (r.mfr_sku && Number(r.retail_usd) > 0) map.set(r.mfr_sku, Number(r.retail_usd));
}
return map;
}
function main() {
const draft = JSON.parse(fs.readFileSync(DRAFT_IN, 'utf8'));
const reprice = draft.filter(p => p.action === 'REPRICE');
const feed = loadFeed();
const buckets = { CONFIRMED: [], DISCREPANT_UNIT_2_5X: [], DISCREPANT_OTHER: [], UNVERIFIABLE: [], BAD_PROPOSED: [] };
for (const r of reprice) {
const { klass, ratio } = classifyVsFeed(r.proposed_sellable_price, feed.get(r.mfr_sku));
buckets[klass].push({
mfr_sku: r.mfr_sku, dw_sku: r.live_dw_sku || r.staged_dw_sku,
proposed: r.proposed_sellable_price, feed_retail: feed.get(r.mfr_sku) ?? null,
ratio: ratio == null ? null : Number(ratio.toFixed(3)),
});
}
const report = {
ticket: 'TK-10873', cycle: 4, generated_at: new Date().toISOString(), read_only: true,
source_a: 'zoffany_catalog.price_retail (used by the Option-A draft)',
source_b: 'SDG S1 feed harvest retail_usd (TK-10877, independent)',
reprice_total: reprice.length,
counts: Object.fromEntries(Object.entries(buckets).map(([k, v]) => [k, v.length])),
// headline: how many are 2nd-source CONFIRMED vs flagged discrepant vs unverifiable
verdict: buckets.DISCREPANT_UNIT_2_5X.length > 0 ? 'FAIL' : 'PASS',
status: buckets.DISCREPANT_UNIT_2_5X.length > 0 ? 'FAIL' : 'PASS',
finding: buckets.DISCREPANT_UNIT_2_5X.length > 0
? `${buckets.DISCREPANT_UNIT_2_5X.length} REPRICE prices are ~2.54x BELOW the independent S1 feed (systematic unit/currency mismatch). Which source is canonical is a Steve/pricing-owner decision — reprice of these is BLOCKED until resolved.`
: 'no systematic discrepancy vs the S1 feed',
buckets,
};
fs.writeFileSync(JSON_OUT, JSON.stringify(report, null, 2));
const c = report.counts;
const md = [
`# TK-10873 cycle 4 — REPRICE vs independent S1 feed cross-validation`, '',
`- **Verdict:** ${report.verdict}`,
`- Source A (draft): \`zoffany_catalog.price_retail\``,
`- Source B (independent): SDG S1 feed harvest \`retail_usd\` (TK-10877)`,
`- REPRICE rows: ${report.reprice_total}`, '',
`## Cross-validation buckets`,
`| bucket | count | meaning |`,
`|---|---|---|`,
`| CONFIRMED | ${c.CONFIRMED} | feed agrees with draft (ratio ~1.0) — 2nd-source verified |`,
`| DISCREPANT_UNIT_2_5X | ${c.DISCREPANT_UNIT_2_5X} | feed ~2.54x the draft price — systematic unit/currency mismatch, draft may be a ~2.5x UNDERPRICE |`,
`| DISCREPANT_OTHER | ${c.DISCREPANT_OTHER} | feed disagrees by some other factor |`,
`| UNVERIFIABLE | ${c.UNVERIFIABLE} | feed has no retail for this mfr_sku — cannot 2nd-source check |`,
`| BAD_PROPOSED | ${c.BAD_PROPOSED} | proposed price nonpositive (should be 0) |`, '',
`## What this means`,
`The ~2.54x factor (= 2 × ~1.27) is consistent with a double-roll × GBP→USD transform applied by one source and not the other. **This tool does NOT decide which is right** — it surfaces the discrepancy. The Option-A reprice of the DISCREPANT_UNIT_2_5X cohort is BLOCKED pending a Steve/pricing-owner ruling on the canonical price source (the epic TK-10874 says S1/feed is authoritative, which would make the draft's zoffany_catalog values wrong-low).`, '',
`Safe-to-reprice now = CONFIRMED (${c.CONFIRMED}). Everything else holds.`, '',
];
fs.writeFileSync(MD_OUT, md.join('\n') + '\n');
console.log('=== REPRICE vs S1 feed cross-validation (READ-ONLY) ===');
console.log(`reprice=${report.reprice_total} ${JSON.stringify(c)}`);
console.log(`verdict=${report.verdict}`);
console.log(report.finding);
console.log(`\nartifacts:\n ${JSON_OUT}\n ${MD_OUT}`);
// Exit nonzero on the systematic discrepancy so this is a real gate.
process.exit(report.verdict === 'FAIL' ? 1 : 0);
}
// run only if invoked directly (so tests can import classifyVsFeed)
if (import.meta.url === `file://${process.argv[1]}`) main();