How to read this
KEEP — works, leave it
FIX — a bug or stale value, small change
RETHINK — the presentation itself is the problem
LIVE real feed
STATIC baked into HTML
MIXED live + hardcoded
BROKEN feed dead / wrong
The one-line finding: the portal's plumbing is real — Plaid cash, the queue, calendar, Hospitable and MIS quotes all answered live this morning. The problem is presentation: the home page opens as a wall of 20+ launchers and 6 data tiles, so the ONE thing that matters today is buried, and a few tiles show hardcoded or mis-computed numbers that read as fact. Fix the honesty bugs, then re-lead the page with today's single move.
A · The stat strip + top banners
Stat strip — 4 live numbersKeep
cash now · p0/p1 open · forced today · next 7 days · LIVE
- Does
- Four tap-to-jump numbers under the hero. Each scrolls to its parent tile.
- Fetches
- No own fetch — reuses the tile loaders (one source of truth). Good pattern.
- Verdict
- Honest and cheap. Keep it. Carry this "one loader, many displays" pattern into the rebuild.
Today banner + "What's New" stripFix
two stacked full-width links above the fold · STATIC
- Does
- "📋 Today →" links to today.html; a gold "NEW" strip links to everything.html.
- Issue
- The NEW strip text is hardcoded ("Today page, Week view, MIS cockpit… just shipped") and dated from the Jun-25 build — it will read "just shipped" forever. This is the everything.html hand-maintained problem leaking onto home.
- Verdict
- Fold both into the proposed single "today's goal" strip; kill the frozen NEW copy or drive it off the auto-index.
"Your next move" cardFix
client-side ranker picks #1 + #2 from the queue · LIVE
- Does
- Scores every card by priority + $-at-stake + waiting-on-others + age, shows the top one with Done / Defer / Skip and a slim "Then:" second move.
- Good
- This is already the seed of the "lead with the ONE thing" rethink — the logic exists and is honest about its ranking.
- Issue
- It sits fourth on the page (under stat strip, Today banner, NEW strip). The best asset is buried. It answers "what to do" but not "what's the goal / rest of my day" — Sam's A-to-Z ask.
- Verdict
- Promote to the top of the page and widen its job: one move + today's goal + the timed rest-of-day. See mockup right column.
B · The six data tiles
Cash · on handFix
/plaid/balances (KV-cached, cron-warmed) · MIXED (live Plaid + hand-entered block)
- Fetches
- LIVE — probed 12:16 PM: 9 institutions, 18 accounts,
total $1,992.09, cache_hit, zero failed. Real.
- Live loans now in Plaid
- Fifth Third mortgage ···1858 ($380,468) and USALLIANCE HELOC ···2650 ($217,000) are in the feed — render under "Loans · live".
- "Manual obligations"
- Hand-entered block = Shellpoint 9332 /mo $3,161.51 · Selene 9312 /mo $3,379.91 · Affirm total $4,105.02 (tagged "as of Apr 28 — verify"). These are the loans Fable found that Plaid can't see. Naming is wrong: it mixes monthly mortgage payments with a total Affirm balance under one "obligations" header, and Affirm is 2+ months stale.
- Chase gap
- Confirmed — no Chase account anywhere in the 9 Plaid institutions. Chase 5609 (the inflow hub) and 5007 are invisible to "cash on hand." Sam's instinct to add Chase back is correct; it's a genuine completeness hole, not a display bug.
- Verdict
- Rename the block "Mortgages & loans (not in Plaid)"; split monthly-payment rows from balance rows; date-stamp Affirm and flag it stale; add Chase (re-link via link.html or hand-enter with an "as of" date). The tile's data-honesty framing (⚠ on incomplete totals) is excellent — keep it.
Open loops · liveRethink label
/inbox QUEUE_JSON via ops-api · LIVE
- The 228 vs 92 confusion
- Both numbers are real and measure different things. The tile's big number (~228) = everything open that isn't forced-today or overdue (the backlog). The stat-strip 92 = P0 + P1 only (the cash-now/high-priority subset). Neither is wrong; they're just unlabeled, so they look contradictory.
- How it splits
- Cards are bucketed: forced today (P0 or due exactly today) → the Today tile; overdue → its own red bucket pointing at Rethink; the rest → this tile's count. Honest logic, but the raw scale (228 open) signals a backlog that needs a triage pass, not a display fix.
- Verdict
- Label every number with its scope on the tile ("228 open backlog · 92 are P0/P1 · N forced today"). The deeper fix is the 263→sane data pass the code itself flags — dedupe/triage the queue so the backlog number stops scaring.
Markets · MISRethink
/mis/peek?sym=NVDA · BROKEN (hardcoded ticker + wrong % + blank verdict)
- Hardcoded NVDA
- Confirmed — the fetch is literally
/mis/peek?sym=NVDA and the tile hardcodes the string "NVDA". It is not Sam's real top holding; it's a pinned bellwether. Sam's ask: show the real top holding (or the market), not a fixed name.
- The % is a real bug
- peek returns
day_pct:-1.76 and day_change:-3.48 (dollars). The tile reads q.day_change_pct||q.day_change — but day_change_pct doesn't exist, so it falls through to day_change (−3.48) and prints it as "↓3.48%". The true move was −1.76%. It's showing the dollar change as a percent.
- Verdict blank
- The verdict/SACS/basis rows depend on
d.universe, which the live peek isn't returning (and /health shows schwab_set:false — the live-holdings link is off), so "verdict mark" renders "—". Sam asked what the verdict mark even is: it's the MIS ADD/STARTER/WATCH/TRIM call for that ticker — currently unfed here.
- Missing
- No VIX, no gold, no market index. Sam wants the market + VIX + gold always visible. (The mis-cockpit page does show VIX — home doesn't.)
- Verdict
- Replace with a real "truth tile": market/regime + VIX + gold + your top holding by weight (from /mis/brief, which the cockpit already uses), correct the pct field name, and define "verdict" inline. This is a rethink, not a patch.
Groceries · open listKeep
/inbox GLIST + GROCERY + BOUGHT · LIVE
- Does
- Live list, aisle auto-categorization, mark-bought-by-name (not position), on-device "regulars" learning with Thu/Fri Shabbos staples.
- Verdict
- Mature and well-built. Per the per-surface-personality memory, its home-portal look is deliberately distinct from the kids' kiosk — keep both. No change.
Calendar · today + weekFix
HS.calendar('business') + ('family') merge + queue overlay · MIXED
- Fetches
- LIVE — merges business (Airbnb 9312/9332 + TripIt) and family scopes, then overlays dated queue cards onto their due-day. Probed live: business scope returns real 9312/9332 reservation spans. The Monsey event Sam saw is the wiring working.
- Static remnant
- A
KNOWN_PERSONAL[] array hardcodes late-June personal events (yahrzeit, farbrengen) because the iCal feed didn't carry them — all now past, harmless but dead weight.
- The consolidation question
- Sam's confusion is real: "Today" pill (calendar count) vs "next 7 days" (stat strip) vs the Today tile (forced tasks) vs the P0-due-today footer are four different day/week presentations. They don't conflict but they aren't unified.
- Verdict
- Collapse the day/week story into ONE place in the rebuild (see today.html below). Drop the stale KNOWN array once the feed carries personal events.
Today · forced list (the big tile)Keep logic
same QUEUE_JSON, filtered to P0 + due-today + captured-today · LIVE
- Does
- The "FORCED" list — P0s and anything due exactly today, plus a "captured today" band so nothing you logged today is invisible. People-tagged calendar rows ride on top.
- Verdict
- Logic is sound and honest. In the rebuild this becomes the spine of the top "today" strip rather than one tile among six.
C · The launcher wall
Do / Money / Life / Build lanesRethink
~20 tiles across 4 lanes + a Command-center block · STATIC links
- Does
- The grouped launcher: one "Command queue" card (5 queue views as pills) + Money/Life/Build combs. Replaced the old flat 17-tile honeycomb.
- Command queue repoint
- Verified in
_redirects — /start /loops /queue now 200-rewrite to home.html (the live queue), not the legacy paste-token start-here page. The "▶ Open all" pill still points at start-here.html (the legacy manager, still reachable). Repoint is done; the pill label is the last stale pointer.
- Issue
- This is the "launcher wall" Sam wants demoted. 20 doors of equal weight is a menu, not a cockpit. Everything here can live behind ONE search/all-apps door.
- Verdict
- Keep the lanes as a collapsed "everything else, one tap away" drawer below the fold. Lead the page with truth-tiles + today's goal instead. Fix the "Open all" pill to say what it opens.
D · Linked surfaces
today.htmlKeep
/today · LIVE (queue + calendar)
- Does
- Ranks the day into Must-do → timed → anytime → coming-up (8 days). Reads live QUEUE_JSON + business/family calendar.
- Verdict
- This is the real day-flow page and it's live. In the rebuild, the home "today" strip should be a compact read of exactly this — one source, two surfaces. Trim the stale KNOWN[] array (all June dates).
week.htmlRethink
/week · STATIC — reads no feed at all
- Confirmed
- 100% hardcoded. No
hs-core.js, no /calendar, no fetch — the only JS reads the day-of-week to highlight "TODAY". "Your Week · synced" is a human sync (Sam↔Mildred), nothing is data-synced.
- Risk
- It duplicates the daily-routine schedule that today.html already encodes in
routine(dow) — two hand-maintained copies that drift apart silently.
- Verdict
- Wire it to the live /calendar feed (same call today.html makes) so the week ahead is real, or fold "the week" into today.html's "coming up" and retire the separate page.
Obligations PWA (pwa-deploy/index.html)Rethink
/obligations → pwa-deploy/ · LIVE but old-style + wrong source
- Does
- Warm-skinned table of obligations with a top pill: Next 7 / Next 14 / Next 30 / This month / Show raw JSON. Per-persona skin (chanie/mildred/sam). Weather + Hebcal greeting strip. "Ping Zee" SMS/relay buttons.
- Source fragmentation
- This PWA reads the v1 Monthly Obligations sheet via its own legacy Apps Script endpoint (
AKfycbw8…/exec, API key embedded in the file). But cashflow.html reads a different source — ops-api /bos/cashflow (the v3 tabs). Two obligations surfaces, two backends, two truths. This is the biggest structural issue in the money layer.
- Top-pill
- Sam's "old style" read is right: it's a horizontal button row over a data table — a 2023 pattern. The 7/14/30/month/raw windows are useful data cuts but presented as raw filters, not as a story.
- Missing "still paying this?"
- No per-row confirm flow. Sam wants each obligation to carry a "still paying this or not?" prompt that messages Sam / Chanie / both via the bot. The rails exist (the file already POSTs to
/mis/notify for "Ping Zee") — it needs a per-row Yes/No/Ask-Chanie control wired to that relay + a write back to the sheet.
- Verdict
- Rebuild on ONE obligations source (pick v3/ops-api, retire the embedded-key legacy endpoint), rethink the top-pill into a "what's due / this month / everything" story, and add the per-row "still paying?" → bot-message control.
cashflow.htmlRethink (his favorite)
/cashflow · LIVE (/bos/cashflow)
- Does
- Dark, sophisticated: the "tilt" (Daily/Weekly/Monthly/Quarterly/Biannual/Yearly), cadence-normalized outflow, category bars, and a debt avalanche (highest-APR-first) view. APR display already fixed (fraction→percent).
- The gap
- It shows outflow only. Sam wants income blended in and tagged by whose it is (Sam / wife / children), for the whole in-and-out picture. Income data exists (Chanie payroll ≈$19.7K/mo per memory) but isn't fed here.
- Verdict
- Add an income layer (net = in − out at each tilt window), owner-tag every inflow, and rethink the layout around net cashflow rather than a spend list. This is the money surface Sam cares most about — treat as a real design pass.
mis-cockpit.htmlFix small
/mis/brief + /mis/quotes · MIXED
- Does
- The real MIS surface: regime + VIX, reconciled equity/cash/#1-risk/2.5%-clock, "the one move," live top movers from the 237-name universe. Reporting-only (engine freeze honored).
- Live
- Both feeds live with honest stale/unreachable banners.
- Fix
- A hardcoded
#booknote ("basis fixes pending NVDA 5692, SPCX 4073", dated 7/2) and a stale default "Jun 24 close" label that persists if the brief fails. VIX yes, gold no (gold is only the UI accent color, not a price).
- Verdict
- This page already has what the home markets tile lacks. Home should read a compact slice of THIS (/mis/brief), not a separate hardcoded NVDA peek. Strip the frozen booknote.
str.html (check-ins)Rethink
/str · LIVE (/hospitable/reservations?days=45)
- Does
- Today (check-ins OR checkouts matching today) + Upcoming (next 45 days). Live from Hospitable — probed 12:17 PM: 3 real reservations with guest names (Deztany Padilla 9332 7/7–7/21, etc.).
- Missing "currently in-house"
- Confirmed — it only matches
check_in===today or check_out===today. A guest mid-stay (checked in earlier, leaving later) shows in neither section. For an ops board that's the main hole. The calendar feed does carry the spanning reservation (9312/9332 "Reserved" spanning today), so "who's in right now" is derivable.
- Also missing
- No last-7-days, no open maintenance/tasks per property. Sam wants all three (in-house now, last 7, open maintenance) in one view. The reservation feed alone can't do maintenance — needs the queue (cards tagged per property) merged in.
- Reserved in/out labels
- Home calendar shows "9312 · Reserved" without saying check-in vs checkout vs in-house. Derive the state from the span vs today and label each.
- Verdict
- Add a "Currently in-house" section (span contains today), a "Last 7 days" section, and merge per-property open maintenance cards from the queue. Label every reservation with its state.
everything.html (the index)Rethink (durable fix)
/everything · STATIC — hand-maintained
- Sam likes it
- "Actually pretty cool." Keep the concept.
- His questions, answered
- How often does 🟢 NEW update? Never automatically — it's a hand-typed
<span class="new"> that stays until someone edits it. How long does NEW stay? Until manually removed (some Jun-25 items still show NEW). Are all links working? Mostly, but dated-filename links rot as snapshots archive.
- Contradictions found
- Hero claims "by real file date, so it never guesses" — but nothing reads file dates. Hero says NEW is green + "refreshed Jul 1"; footer says NEW is red; CSS renders red; top entry is dated Jul 2. All hand-drift.
- Verdict
- Build the auto-index generator (loop 38-K6): a script that walks outputs/, reads real file mtimes, sorts newest-first, and auto-expires NEW after N days. That fixes "how often does it update" permanently and kills the everything.html + home NEW-strip staleness in one move.
E · Cross-cutting findings
- The plumbing is real; the presentation buries it. 5 of 6 tiles fetch live. The home page's job — "what deserves attention right now" — is answered by a card sitting 4th on the page under two static banners.
- Two obligations backends. The PWA reads the v1 sheet (legacy GAS + embedded key); cashflow.html reads v3 via ops-api. Consolidate to one source before adding features, or the "still paying?" writes land in a sheet the other surface doesn't read.
- Three honesty bugs to fix first (cheap, high-trust): markets tile prints dollar-change as a percent; markets tile hardcodes NVDA; Affirm balance is 2+ months stale without a loud flag. These make live pages look wrong even though the feeds are right.
- Chase is genuinely missing from Plaid — a data gap, not a display bug. Re-link or hand-enter with an "as of" date.
- Per-surface personality is intentional (memory
feedback_per_surface_personality_intentional). The rebuild unifies the SYSTEM (tokens, honest numbers, no dead links) without flattening Sam's dark command feel vs Chanie's warm vs the kids' kiosk. Consistency ≠ sameness.
- Static pages that drift: week.html, everything.html, the home NEW strip, the today.html KNOWN[] array — all hand-maintained schedule/index content. The auto-index generator + wiring week.html to /calendar retires most of this class of rot.
Proposed build order
| # | Change | Why first |
| 1 | Honesty fixes: markets % field, real top-holding not NVDA, Affirm stale-flag, open-loops scope labels | Cheap, restores trust in the numbers |
| 2 | Auto-index generator (walk outputs/, real dates, auto-expire NEW) | Kills everything.html + NEW-strip rot permanently |
| 3 | Home rethink: lead with ONE move + today's goal + truth-tiles; launcher → collapsed drawer | The core ask — "so I don't miss it" |
| 4 | Cashflow: blend income, owner-tag (Sam/wife/kids), net in-out | His favorite surface; real design pass |
| 5 | Obligations: one source, rethink top-pill, "still paying?" → bot | After source consolidation |
| 6 | STR: in-house-now + last-7 + open maintenance; label reserved states | Ops completeness |
Single most important change: re-lead home.html with the ONE thing that matters today (move + goal + timed rest-of-day) and demote the 20-tile launcher into a one-tap "everything else" drawer. Everything else is a fix; this is the rethink Sam actually asked for.