← back to Ken
Ken (Cody gate c): add read-only reconciliation canary — verifies ken_portfolios rollup (returned/invested/balance) still equals the per-trade ledger within $2. Catches the bigint-string over-credit bug class forever. Exit 1 + ALERT on divergence. Coerces bigint-as-string (the very bug).
a33bc89d2685a4ad2205c1f7c95199f9abc09132 · 2026-08-03 10:21:21 -0700 · steve@designerwallcoverings.com
Files touched
A kalshi-dash/scripts/reconcile-canary.mjs
Diff
commit a33bc89d2685a4ad2205c1f7c95199f9abc09132
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date: Mon Aug 3 10:21:21 2026 -0700
Ken (Cody gate c): add read-only reconciliation canary — verifies ken_portfolios rollup (returned/invested/balance) still equals the per-trade ledger within $2. Catches the bigint-string over-credit bug class forever. Exit 1 + ALERT on divergence. Coerces bigint-as-string (the very bug).
---
kalshi-dash/scripts/reconcile-canary.mjs | 59 ++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/kalshi-dash/scripts/reconcile-canary.mjs b/kalshi-dash/scripts/reconcile-canary.mjs
new file mode 100644
index 0000000..919d674
--- /dev/null
+++ b/kalshi-dash/scripts/reconcile-canary.mjs
@@ -0,0 +1,59 @@
+#!/usr/bin/env node
+// Ken paper-sim RECONCILIATION CANARY (born 2026-08-03 after the bigint-string over-credit bug).
+// Read-only. Verifies the ken_portfolios rollup columns still equal the authoritative per-trade
+// ledger, and that balance = seed - invested + returned. Any divergence beyond a small rounding
+// tolerance means a credit/settle bug has crept back in (the exact class of the 441x over-credit
+// where node-postgres bigint-as-string made `cost_cents + pnl` concatenate).
+//
+// Exit 0 = reconciled (silent-ish). Exit 1 = DIVERGENCE (prints ALERT). Never writes anything.
+// Run: KEN_DATABASE_URL=... node scripts/reconcile-canary.mjs
+import pg from 'pg';
+
+const TOL_CENTS = 200; // $2 tolerance absorbs benign rounding; the bug produced 100x+ divergence
+const url = process.env.KEN_DATABASE_URL;
+if (!url) { console.error('reconcile-canary: KEN_DATABASE_URL not set'); process.exit(2); }
+
+const pool = new pg.Pool({ connectionString: url });
+try {
+ const { rows: [r] } = await pool.query(`
+ SELECT
+ (SELECT COALESCE(SUM(total_returned_cents),0) FROM ken_portfolios) AS rollup_returned,
+ (SELECT COALESCE(SUM(CASE WHEN pnl_cents>0 THEN cost_cents+pnl_cents
+ WHEN pnl_cents=0 AND resolved_at IS NOT NULL THEN cost_cents
+ ELSE 0 END),0) FROM ken_portfolio_trades) AS ledger_returned,
+ (SELECT COALESCE(SUM(total_invested_cents),0) FROM ken_portfolios) AS rollup_invested,
+ (SELECT COALESCE(SUM(cost_cents),0) FROM ken_portfolio_trades) AS ledger_invested,
+ (SELECT COALESCE(SUM(balance_cents),0) FROM ken_portfolios) AS balance,
+ (SELECT COALESCE(SUM(starting_balance_cents),0) FROM ken_portfolios) AS seed
+ `);
+
+ // pg returns bigint as string — coerce (the very bug this canary guards against).
+ const n = (v) => Number(v);
+ const rollupRet = n(r.rollup_returned), ledgerRet = n(r.ledger_returned);
+ const rollupInv = n(r.rollup_invested), ledgerInv = n(r.ledger_invested);
+ const balance = n(r.balance), seed = n(r.seed);
+ const expectedBalance = seed - rollupInv + rollupRet;
+
+ const checks = [
+ { name: 'returned (rollup vs ledger)', a: rollupRet, b: ledgerRet },
+ { name: 'invested (rollup vs ledger)', a: rollupInv, b: ledgerInv },
+ { name: 'balance (vs seed-inv+ret)', a: balance, b: expectedBalance },
+ ];
+ const fails = checks.filter(c => Math.abs(c.a - c.b) > TOL_CENTS);
+ const usd = (c) => '$' + (c / 100).toFixed(2);
+
+ if (fails.length === 0) {
+ console.log(`[reconcile-canary] OK — returned=${usd(rollupRet)} invested=${usd(rollupInv)} balance=${usd(balance)} (all reconcile within $${TOL_CENTS/100})`);
+ process.exit(0);
+ }
+ console.error('🚨 [reconcile-canary] DIVERGENCE — a credit/settle bug is back:');
+ for (const c of fails) {
+ console.error(` ${c.name}: ${usd(c.a)} vs ${usd(c.b)} (off by ${usd(Math.abs(c.a - c.b))}, ${(c.b !== 0 ? (c.a / c.b).toFixed(1) : '∞')}x)`);
+ }
+ process.exit(1);
+} catch (e) {
+ console.error('[reconcile-canary] error:', e.message);
+ process.exit(2);
+} finally {
+ await pool.end();
+}
← 2f7617c Ken (Cody gate b): independence gate on winner-consensus — e
·
back to Ken
·
Ken: reconcile-canary self-alerts to CNCP parking-lot on div 259b896 →