# BaoLife Fun/Balance — Progress Tracker

Human-readable checklist mirroring the audit. Machine truth is `../state.yaml`.
Status legend: `[ ]` todo · `[~]` in progress · `[x]` done · `[!]` blocked.
Each item is confirmed in **iOS (priority)** and **Android** where it has a client surface.

_Last updated: 2026-05-27 (board seeded; nothing executed yet)._

---

## Tier 0 — Broken loops (fix first)
- [x] **0-A** Online economy unfrozen: shared `finance.ts` used by both `PlayerSession.processWeekTick` and `GameEngine` ✅ (T003a)
- [x] **0-B** Affinity bound `-100..100`: online `statUtils` (T003) + offline `GameEngine` mirror (T003a) ✅
- [x] **0-C** Clamp generic stats at application time in `effects.ts` ✅ (T003)
- [x] **0-D** Online event-prompt pause (`SPEED_QUESTION_PAUSE`, mirrors offline) ✅ (T003)
- [x] **0-E** iOS onboarding tab targets fixed (Talk→Social, Store→sheet) + real completion signals ✅ (T004)
- [x] **0-F** iOS onboarding handoff state-driven + loading overlay + timeout fallback ✅ (T004)

**Tier 0 COMPLETE** — backend vitest 1344/1344, iOS BUILD SUCCEEDED.

## Tier 1 — Wire what exists (highest leverage)
- [x] **1-A** Port deep legacy arcs into live `events/v2/catalog/` ✅ — career (10) + health (13) + family (16) = ~39 new live events; catalog ~31→~70 (T006b/T006c)
- [x] **1-B** Event selection: weighted randomness + cooldowns + `repeatable` flag ✅ (T006a) + 0-D pause refined to interactive-only (T006a2). Suite 1353/1353
  - _note: `eventLastFired` cooldown state not yet persisted across restart (Player.toJSON) — harmless until a catalog event uses cooldownDays; tracked_
- [x] **1-C** Player-initiated actions: `performActivity` + daily-plan override ✅ (T007a, suite 1422)
- [x] **1-D** Affinity payoff: loans/referrals scale w/ affinity, crisis support ≥60, affinity-gated events; scalars documented ✅ (T008)

**Tier 1 COMPLETE** — live catalog ~31→~70 events, weighted/cooldown/repeatable selection, player agency, unified economy w/ real sinks+scarcity, affinity payoff, text variety. Suite 1322→1477 (+155).
- [x] **1-E** Apply `textVariations` to repeatable live events ✅ (T006c, 11+ events, date-seeded)
- [x] **1-F** Unify two engines (`economyConstants`); scaling rent + lifestyle + upkeep sink; starvation + energy scarcity; shop energy cap ✅ (T007b, suite 1454)

## Tier 2 — The missing spine (retention)  [backend split T010a-d + T011a-c; iOS in 2 waves]
- [x] **2-A** Death → life summary + score + New Life flow (backend) ✅ (T010a, onDeath hook now firing); iOS Wave 1 pending
- [x] **2-B** Legacy / generational play (heir, inheritance, family prestige, family tree) ✅ (T010b, suite 1508)
- [x] **2-C/2-D** Welcome-back offline digest + re-engagement notifications (24-72h) ✅ (T010c, suite 1523)
- [x] **2-H** Relationship depth: neglect-decay + auto breakup; NPC-death grief+inheritance; parenting arc; neglect nudges; `ai_response` clamp reconciled ✅ (T010d, suite 1552)
- [x] **2-E** Forward-looking Life Goals / Aspirations (backend, 11 goals) ✅ (T011a, suite 1568); iOS Wave 2
- [x] **2-F** Late-life catalog (13) + adulthood (4) + pacing rebalance + conversation ripples + `eventLastFired` persist fix ✅ (T011b, suite 1590)
- [x] **2-G** Prestige unlock gating + daily-quest chains/weekly challenges + visible achievement collection ✅ (T011c, suite 1615)

**Tier 2 BACKEND COMPLETE** — death→summary→legacy→return-hooks→goals→late-life→prestige all wired. Suite 1322→1615 (+293). iOS surfaces next (2 waves).

## Tier 3 — Polish & feel (iOS priority)  [T014 iOS polish; T015 Android]
- [x] **3-A/B/C** iOS polish: floating stat deltas + header transitions; unified speed vocab; demote/guard controls; what-now hub + idle nudge; UI-tour spotlight; age-unlocks preview; merged home card ✅ (T014, BUILD SUCCEEDED)
- [x] **3-D** Android parity for all tiers (spine + progression + Tier 3 polish; gradle BUILD SUCCESSFUL) ✅ (T015a+T015b) — known backlog bugs already fixed by prior DTO rewrite; fixed a real speed-control bug

## Tier 2 — iOS surfaces
- [x] iOS Wave 1 (T012): death recap + New Life (heir/fresh) + legacy tree + welcome-back digest + spine decoders ✅
- [x] iOS Wave 2 (T012b): Life Goals + achievement collection + quest depth + prestige + performActivity UI ✅

## Final confirmation — ✅ GOAL COMPLETE
- [x] **iOS walkthrough** — ✅ **10/10 oracle behaviors CONFIRMED-IN-APP** with screenshots (T016d pt3/4/7/9; T016g pt1/2/8/10 + T016f fixes; T016j pt5 New Life chooser + pt6 welcome-back digest). In-app confirmation caught 2 real ship-blocking bugs → fixed (T016h/T016i) & re-confirmed (T016j).
- [x] **Android smoke** — build green + screens render in-app; 2 in-app / 6 backend-test / 2 source (T017)
- [x] **Final audit** ✅ (T999 → **T999b** after fixes): **full_outcome_complete: true**. Backend 1621/1621 incl 2yr soak; iOS + Android build green; all 10 points eyes-on.

### ⚠️ ALL WORK IS UNCOMMITTED — working tree still at pre-goal HEAD bd8310ad (~170+ files, +299 tests). Commit before deploy to avoid loss.

### Recommended post-completion follow-ups (optional, out of audit scope)
- In-session death should switch to DeathView immediately (currently only on next reconnect).
- Offline digest money delta content nuance (per-minute ticks vs weekly-finance cycle).
- Event-prompt pacing review (high density at default speed).
- Android debug network-security-config so local `ws://` is reachable for in-app testing (prod `wss://` works).
- Wire the existing iOS UI-test files into the test target (pbxproj).

### Run log

---

### Verification baseline (T001 Scout, 2026-05-27)
- `server` tsc `--noEmit`: **clean (exit 0)**
- `server` vitest: **1322/1322 pass** (89 files, ~35s) — this is the no-regression baseline
- iOS: scheme **BaoLife**, `xcodebuild -project ios/lichunWebsocket.xcodeproj -scheme BaoLife -sdk iphonesimulator build` (xcode MCP available)
- Android: `android/gradlew :app:assembleDebug` / `:app:testDebugUnitTest`
- All 6 Tier 0 claims **confirmed real bugs** (file:line evidence in state.yaml T001 receipt)

### Run log
- T001 Scout ✅ done — 6 bugs confirmed, baseline green (1322)
- T002 Judge ✅ done — sequence locked; split 0-A into T003a
- T003 Worker ✅ done — 0-B(online)/0-C/0-D fixed; vitest 1334/1334
- T003a Worker ✅ done — 0-A economy unfreeze + 0-B offline mirror; vitest 1344/1344
- T004 Worker ✅ done — iOS 0-E/0-F; BUILD SUCCEEDED (PM re-verified)
- T005 Judge ✅ done — Phase 0 COMPLETE; canonical lib = v2/catalog only; split T006→a/b/c
- T006a Worker ✅ done — selection mechanics (weight/cooldown/repeatable); blocked on passive-pause
- T006a2 Worker ✅ done — 0-D pause gated to interactive prompts; suite green 1353/1353
- T006b Worker ✅ done — career arc ported (10 v2 events + setFlags mechanism); suite 1368/1368; recipe documented
- T006c Worker ✅ done — medical(13)+family(16) arcs + text variation; suite 1404/1404
- T007a Worker ✅ done — performActivity + daily-plan override; suite 1422/1422
- T007b Worker ✅ done — economy unification + sinks + scarcity; suite 1454/1454
- T008 Worker ✅ done — affinity payoff + favors; suite 1477/1477; TIER 1 COMPLETE
- T009 Judge ✅ done — Phase 1 COMPLETE (1477/1477); Tier 2 split into T010a-d + T011a-c; found onDeath hook never invoked + death code duplicated
- T010a Worker ✅ done — death summary/score/startNewLife + onDeath hook; suite 1489/1489
- T010b Worker ✅ done — legacy/generational; suite 1508/1508
- T010c Worker ✅ done — offline digest + re-engagement job; suite 1523/1523
- T010d Worker ✅ done — relationship depth; suite 1552/1552; T010 cluster COMPLETE
- T011a Worker ✅ done — Life Goals (11) + hooks + lifeGoalsUpdate; suite 1568/1568
- T011b Worker ✅ done — late-life + adulthood + pacing + ripples + eventLastFired persist; suite 1590/1590
- T011c Worker ✅ done — prestige unlocks + quest depth + achievement collection; suite 1615/1615; TIER 2 BACKEND COMPLETE
- T013 Judge ✅ done — Tier 2 backend COMPLETE (1615/1615); found iOS decodes NONE of the new msgs/fields; scoped iOS Wave1/Wave2
- T012 Worker ✅ done — iOS Wave 1: spine decoders + death recap/New Life + legacy tree + welcome-back digest; BUILD SUCCEEDED (PM re-verified)
- T012b Worker ✅ done — iOS Wave 2 progression UI; BUILD SUCCEEDED (PM re-verified); TIER 2 COMPLETE (backend+iOS)
- T014 Worker ✅ done — Tier 3 iOS polish; BUILD SUCCEEDED; entire iOS app (Tier 0-3) green
- T015a Worker ✅ done — Android wave 1: spine + decoders + commands; gradle BUILD SUCCESSFUL + tests
- T015b Worker ✅ done — Android wave 2 progression+polish; gradle BUILD SUCCESSFUL; ALL TIERS DONE ON ALL PLATFORMS
- T016 Worker ✅ done — iOS builds+launches+connects to local server; oracle: 1 in-app, 8 backend-test, 1 manual. Report: notes/T016-ios-confirmation.md
- T016b Scout ✅ done — loop-back is an ARTIFACT (T004 sound); found a separate latent entry-gate concern
- T016c Worker ✅ done — onboarding routing hardened (pure resolveAppRootDestination); BUILD SUCCEEDED; trap was lower-severity than thought (WelcomeView already had a creation path)
- T017 Worker ✅ done — Android smoke: build green + screens render; 2 in-app/6 backend-test/2 source; report notes/T017-android-confirmation.md
- T999 Judge ✅ done — FINAL AUDIT: implementation+verification complete; full_outcome_complete=false (in-app deep-loop walkthrough still owed)
- T016d Worker ✅ done — DROVE the live app past char creation into gameplay; 6 net-new in-app oracle confirmations (pt3,4,7,9,10 + pt8 surface). Loop-back resolved (incomplete-form, not a bug). Found 2 real quality bugs + 1 pacing note.
- T016e Scout ✅ done — root-caused both: energy GATE CONTRADICTION (calcEnergy vs raw energy) + Life Goals playerObject embed lacks titles. Concrete fixes specced.
- T016f Worker ✅ done — energy-gate lockout fixed (raw energy) + iOS gate + night restore 35 + Life Goals titles in playerObject; backend 1618/1618 + iOS green
- T016g Worker ✅ done — in-app pass #2: 8/10 oracle points eyes-on (pt1,2,3,4,7,8,9,10); T016f fixes verified in-app. Found 2 real bugs ↓
- T016h Worker ✅ done — BUG-1 fixed: offline digest now fires on reconnect (processOfflineTime wired + loadPlayer preserves digest); suite 1621/1621
- T016i Worker ✅ done — BUG-2 fixed: DeathView New Life chooser pinned in safeAreaInset footer; BUILD SUCCEEDED
- T016j Worker ✅ done — FINAL capture: pt5 New Life chooser tappable + pt6 digest live → **10/10 CONFIRMED-IN-APP**
- T999b PM ✅ done — FINAL audit: **full_outcome_complete: true**. GOAL COMPLETE.

### Real bugs caught by in-app confirmation (being fixed)
- **Offline digest dead in live build** (T010c gap) → T016h
- **DeathView New Life CTAs untappable on iPhone 17** (T012) → T016i
- Pacing: high event-prompt density at default speed → recommendation (not a bug)
- (T015 split into T015a spine/connectivity + T015b progression/polish; known backlog bugs already fixed by prior DTO rewrite)

### iOS surfacing
Wave 1 ✅ wired the Tier 2 spine into the app (death→summary→New Life→legacy→digest). Wave 2 surfaces the progression loop (goals/quests/achievements/prestige/activities).

_Board note: goalbuddy checker flags suffixed IDs (T006a/b/c) as non-T### and treats annotated `changed_files` strings as "outside allowed_files" — both cosmetic false positives. Real invariant (1 active task, receipts present, suite green) holds._
