diff --git a/.codex/MFD/chip-coverage-audit-20260507.md b/.codex/MFD/chip-coverage-audit-20260507.md new file mode 100644 index 00000000..443a1adc --- /dev/null +++ b/.codex/MFD/chip-coverage-audit-20260507.md @@ -0,0 +1,64 @@ +# Chip Coverage Audit - 2026-05-07 + +Branch target: `codex/chip-full-wire`, created from `codex/chip-art-shell-polish-v3` at `6340bbd`. + +Scope guard: this audit covers the clean recovery clone at `/Users/tkevinbigham/Documents/GitHub/MFD-clean-chip-recovery`. The messy checkout at `/Users/tkevinbigham/Documents/GitHub/MFD/` was not modified. No save schema, `SAVE_VERSION`, deterministic engine behavior, RNG, or deploy surface changes are recommended here. + +## Summary + +Chip is present in the cold open, the post-setup dock, weekly guidance, high-stakes pose events, game recap, halftime, press conference, era transition, and trophy room empty state. Coverage is broad, but the current 17-pose atlas forces several moments into generic `think`, `concern`, `mic-check`, `celebrate`, or `idle`. + +The best incremental path is to keep the v3 rig as the only art source, add a focused pose batch, then wire the new poses into the existing route-beat, eventBridge/useChipEvents, and direct feature-component surfaces where the new pose clearly reads better. + +## Surface Inventory + +| Surface | Files | Current state | Recommendation | +| --- | --- | --- | --- | +| Cold-open onboarding host | `apps/web/src/features/companion/ChipHost.tsx`, `apps/web/src/features/franchise-setup/FranchiseSetupWizard.tsx`, `apps/web/src/features/companion/dialogue/onboarding.ts` | Wired. Uses `wave`, `point-left`, `talk`, `think`, `concern`, `point-right`, `mic-check`, `celebrate`, `idle`. | Keep the cold-open structure. Swap only the generic `talk`/`think`/`idle` beats where new admin or proud poses land harder. | +| Onboarding reveal frames | `apps/web/src/features/companion/onboardingReveal.ts` | Wired. Uses `wave`, `mic-check`, and `idle` during entry/reveal. | Keep as-is unless the new final pose batch includes a clean `coffee-sip`/`proud` replacement for the final quiet state. | +| Post-setup dock portrait | `apps/web/src/features/companion/ChipDock.tsx` | Wired. Portrait resolves store pose, route beat pose, or live beat pose. Collapsed sanity uses `idle`. | Keep architecture. Extend route-beat pose mapping so route guidance can use specific new poses without bypassing the dock. | +| Dock pending-decision beat | `apps/web/src/features/companion/ChipDock.tsx` | Wired. `createPendingDecisionsBeat` uses route pose `thinking`, which resolves to `think`. | Change to a more urgent admin pose after the atlas lands, likely `reviewing-tablet` or `note-taking`. | +| Dock Where Am I summary | `apps/web/src/features/companion/whereAmI.ts`, `apps/web/src/features/companion/ChipDock.tsx` | Wired. Uses route pose `thinking`. | Keep as `think` or move to `reviewing-tablet` if the generated tablet pose is visually clean. | +| Weekly rollover dialogue bridge | `apps/web/src/features/companion/eventBridge.ts`, `apps/web/src/features/companion/useChipEvents.ts` | Wired for week rollover. `gameComplete` and `seasonEnd` remain intentionally deferred comments. | Keep week rollover. Do not invent broad season-end dialogue trees in this slice; document season-end as partial unless a narrow route/direct pose change covers it. | +| High-stakes pose reactions | `apps/web/src/features/companion/PoseEventEmitter.tsx`, `apps/web/src/features/companion/eventBridge.ts` | Wired for touchdowns, first launch, cap overrun, big loss, playoff upset, trade rumor, user HOF retirement, decision locked in. | Replace generic outcomes with richer poses: touchdown/rally `rallying`, cap warning `head-in-hands` or `warning`, trade rumor `on-phone`, HOF retirement `head-in-hands`, decision lock `fist-bump` or `proud`. | +| Weekly dialogue catalogue | `apps/web/src/features/companion/dialogue/weekly.ts`, `apps/web/src/features/companion/weeklyGuidance.ts` | Wired. Many variants collapse into `celebrate`, `concern`, or `mic-check`. | Swap clean wins/championship to `proud`, playoffs to `rallying`, blowout/dark moments to `head-in-hands` or `frustrated`, preseason/midseason to `coffee-sip` or `reviewing-tablet`. | +| Monday Briefing dialogue surfaces | `apps/web/src/features/monday-briefing/MondayBriefing.tsx` | Wired through active dialogue entry. | No component change needed; it inherits the weekly dialogue pose improvements. | +| Route coaching: Monday Briefing | `apps/web/src/features/route-coaching/routeBeatRegistry.ts` | Wired. Uses generic `point-side`/`thinking`. | Consider `reviewing-tablet` for triage and `calling-play` for top action. | +| Route coaching: roster/depth/game-plan/week-advance | `apps/web/src/features/route-coaching/routeBeatRegistry.ts` | Wired. Uses generic `point-side`/`thinking`. | Keep roster/depth mostly generic. Use `calling-play` for game plan and `reviewing-tablet`/`time-out` for week advance where decisions are pending. | +| Route coaching: inbox/staff/cap lab | `apps/web/src/features/route-coaching/routeBeatRegistry.ts` | Wired. Cap lab uses `point-down`; inbox/staff use generic thinking/pointing. | Use `note-taking` for inbox, `reviewing-tablet` for staff, and `skeptical`/`reviewing-tablet` for cap lab. | +| Route coaching: draft/trade/scouting | `apps/web/src/features/route-coaching/routeBeatRegistry.ts` | Wired. Draft and trade have route beats; scouting has one `idle` beat. | Use `pointing-at-tape` for scouting, `calling-play` or `football-in-hand` for draft, and `on-phone` for trade center. | +| Route coaching: standings/power/news/records/settings | `apps/web/src/features/route-coaching/routeBeatRegistry.ts` | Wired in v3. Uses `thinking`, `point-side`, `idle`, `cheer`, and `point-down`. | Upgrade to `reviewing-tablet`, `skeptical`, `proud`, and `coffee-sip` where appropriate. | +| Training Camp route | `apps/web/src/app/App.tsx`, `apps/web/src/features/training-camp/TrainingCamp.tsx`, `apps/web/src/features/route-coaching/useActiveRouteBeats.ts` | Unwired at route-beat level. The nav has `/training-camp`, but `resolveRouteKey` has no training-camp key. | Add a route-beat entry with `whistle-blow`/`coaching-crouch`. This is small and fits existing infrastructure. | +| Trade Deadline route | `apps/web/src/app/App.tsx`, `apps/web/src/app/store/game-store.ts`, route coaching files | Partially wired. The store navigates to `/trade-deadline`, but route coaching maps only `/trades` to trade center. | Add a route-beat entry for `/trade-deadline` using `on-phone` and `reviewing-tablet`. Do not touch deadline engine behavior. | +| Expansion Draft route | `apps/web/src/app/App.tsx`, route coaching files | Unwired at route-beat level. `/expansion-draft` has no route key. | Add a route-beat entry using `reviewing-tablet` and `note-taking`. Keep copy narrow; no new dialogue tree. | +| Halftime decision modal | `apps/web/src/features/game-day/HalftimeDecision.tsx` | Wired. Uses `mic-check`, `point-left`, `point-right`, `concern`, `thumbs-up`. | Replace the neutral host/choice previews with `time-out`, `calling-play`, `coaching-crouch`, and `frustrated` where the choice demands intensity. | +| Game recap Chip reaction | `apps/web/src/features/game-day/RecapChipReaction.tsx` | Wired. Uses `celebrate`, `thumbs-up`, `surprised`, `excited`, `concern`, `sad`, `disappointed`, `think`. | Upgrade blowout/comeback wins to `rallying`/`proud`, close wins to `fist-bump`, choke/blowout losses to `facepalm`/`head-in-hands`, unknown to `reviewing-tablet`. | +| Press conference modal | `apps/web/src/features/game-day/PressConferenceModal.tsx` | Wired. Uses `concern`, `think`, `thumbs-up`. | Use `skeptical` for high ambition, `reviewing-tablet` for measured review, `coffee-sip` for low-key tone, and `fist-bump` when locked in. | +| Dynasty era transition reveal | `apps/web/src/features/dynasty-era/EraTransitionReveal.tsx` | Wired. Uses `celebrate` or `concern`. | Use `proud`/`rallying` for positive eras and `head-in-hands`/`frustrated` for fall/rebuild. Keep function local. | +| Trophy Room empty state | `apps/web/src/features/franchise/TrophyRoom.tsx` | Wired direct as `idle`. | Optional. `tired` or `coffee-sip` could give the empty case more personality, but it is not a priority. | +| Achievement unlock toast | `apps/web/src/features/legacy/AchievementGallery.tsx` | Unwired. Toast has badges/copy but no Chip. | Add compact Chip treatment with `proud` or `fist-bump`. This is a contained feature-component wire-up. | +| Existing 17 art assets | `apps/web/public/assets/chip/**`, `packages/design-system/components/Chip/Chip.tsx` | Wired and should remain unchanged. | Do not rename or intentionally regenerate existing PNGs. Extend the generator so it can skip existing outputs while still generating new files and contact sheets. | + +## Recommended Pose Batch + +Primary set: `rallying`, `coaching-crouch`, `calling-play`, `time-out`, `whistle-blow`, `coffee-sip`, `on-phone`, `reviewing-tablet`, `head-in-hands`, `fist-bump`, `note-taking`, `laughing`, `skeptical`, `proud`, `facepalm`, `frustrated`, `tired`, `football-in-hand`, `pointing-at-tape`. + +Drop rule: if the v3 procedural rig cannot render one of these without changing Chip's face, outfit, headset, scale, or line weight, drop that pose and document it in this audit before moving on. Do not create a second art pipeline. + +## Wire-Up Target List + +Ship in this branch if the pose batch renders cleanly: + +1. Add route-beat coverage for `/training-camp`, `/trade-deadline`, and `/expansion-draft`. +2. Upgrade route-beat pose mapping to support specific semantic poses while keeping the dock contract intact. +3. Upgrade eventBridge pose reactions for touchdown/rally, trade rumor, HOF retirement, decision lock-in, cap pressure, and big losses. +4. Upgrade weekly dialogue/weekly guidance pose selections. +5. Upgrade direct game-day surfaces: halftime, recap, press conference. +6. Add compact Chip support to the achievement unlock toast. +7. Optionally upgrade era transition and trophy room empty state if the new poses read clearly in the existing layout. + +Still defer unless Kevin explicitly expands scope: + +- Open-ended season-end dialogue trees: existing `eventBridge` comments identify the missing catalog, but this needs more than a line or two of authoring. +- Engine-side event spine changes: current high-stakes pose reactions are intentionally web-side and additive. +- Save/import/export or schema changes: not needed for this visual/wiring slice. diff --git a/.codex/MFD/chip-onboarding-goal.md b/.codex/MFD/chip-onboarding-goal.md new file mode 100644 index 00000000..54456ba5 --- /dev/null +++ b/.codex/MFD/chip-onboarding-goal.md @@ -0,0 +1,260 @@ +# MFD Chip Onboarding Goal Checkpoint + +Date: 2026-05-05 +Repo: `/Users/tkevinbigham/Documents/GitHub/MFD` +Branch: `main` +Baseline: `dc7740a Sprint 46: Polish standings signals (#54)` + +## Active Goal Summary + +Perfect the Chip-guided onboarding and weekly guidance loop so Chip becomes the main player-facing guide layer for Mr. Football Dynasty. The work must improve first-time orientation, weekly next-action guidance, decision-impact clarity, replay/reset/snooze controls, and safe TTS/share scaffolding behind feature flags. + +## Resume 2026-05-05 09:45:09 CDT + +Current objective: finish Slice 9 honestly by verifying the current Chip implementation, diagnosing local blockers, fixing P0/P1 issues found in the continuation, and completing the first-3-week onboarding audit against actual runtime behavior. + +Verification plan: + +1. Reconfirm repo rules, package scripts, current branch, and safe git state without destructive git operations. +2. Diagnose the `git status` / `git diff` hang using time-boxed read-only commands. +3. Inspect Chip onboarding, weekly guidance, decision-impact, dock controls, TTS, share, route coaching, feature flags, and mount paths. +4. Reproduce the hanging targeted tests one file at a time with explicit timeouts and verbose output. +5. Diagnose typecheck hangs with repo-standard and targeted package commands before attempting fixes. +6. Start the app with Chip enabled and complete browser/manual or equivalent runtime verification; document exact blocker if browser tooling fails. +7. Update this checkpoint with commands, results, blocker root causes, and remaining P0/P1/P2 issues. + +Blocker diagnosis: + +- `git status` / `git diff`: reproduced. `git rev-parse --show-toplevel`, branch, and inside-work-tree checks return immediately, and no `.git/index.lock` exists. Both `git -c core.fsmonitor=false status --short --untracked-files=no` and `git -c core.fsmonitor=false diff --stat` time out after 30s. Follow-up read-only checks show `.git/objects/pack/pack-7e55b47cf628dd9df812d78dfb6410f37d6f870f.pack` repeatedly errors as `far too short to be a packfile`, and `git diff --cached --stat --no-ext-diff --no-renames` exits 128 with `fatal: unable to read 39cbc7bc99415d388a173e44d4cad585f3519bf9`. No `.git` repair has been attempted. +- `dockControls.test.ts`: blocked before file-specific execution. Direct Vitest bootstrap via bundled Node (`node .../vitest/vitest.mjs run ...`) produced no runner output after 180s and sat at 0% CPU inside Node dependency loading; killed only that spawned process. +- TSX/component suites: root cause is at least partly filesystem/local install level. `apps/web/src/features/week-advance/WeekAdvance.tsx` was a regular 14 KB file by `stat`, but `sed`, `wc`, and `dd` all blocked trying to read the working-tree inode. The unreadable inode was moved to `.codex/MFD/evidence/WeekAdvance.tsx.unreadable-20260505-1008`, the source was recreated from `git show HEAD:...`, and the Chip decision-impact panel was reapplied. `WeekAdvance.test.tsx` is now readable and still expects the panel copy. +- `tsc --noEmit`: still blocked after WeekAdvance repair. Direct bundled Node command `node .../typescript/lib/tsc.js --noEmit --project apps/web/tsconfig.json --pretty false` produced no diagnostics after 180s; `ps` showed 0% CPU and `lsof` showed Node blocked while reading dependency declarations such as `vite/types/hmrPayload.d.ts`. +- Browser/manual playthrough: fresh Vite build/dev is blocked before startup. Existing stale `apps/web/dist` can be served only by stripping the `/MFD` base path; the stale build loads with no console errors but has Chip disabled and cannot count as current Chip verification. + +Commands run during resume: + +- `pwd`: `/Users/tkevinbigham/Documents/GitHub/MFD`. +- `git rev-parse --show-toplevel`: `/Users/tkevinbigham/Documents/GitHub/MFD`. +- `git branch --show-current`: `main`. +- `git rev-parse --is-inside-work-tree`: `true`. +- `ls -la .git/index.lock 2>/dev/null || true`: no lock file output. +- `git -c core.fsmonitor=false status --short --untracked-files=no`: timeout after 30s. +- `git -c core.fsmonitor=false diff --stat`: timeout after 30s. +- `git config --show-origin --get-regexp 'core.fsmonitor|core.untrackedCache|diff.external|filter|lfs'`: only LFS filter config found. +- `ls -lh .git/index`: 133K. +- `git count-objects -vH`: one pack, reported 89.05 MiB. +- `git -c core.fsmonitor=false -c core.untrackedCache=false status --porcelain=v1 --untracked-files=no --no-renames`: timeout after 20s. +- `git -c core.fsmonitor=false -c core.untrackedCache=false diff --name-only --no-ext-diff --no-renames`: timeout after 20s with repeated corrupt-pack errors. +- `git diff --cached --stat --no-ext-diff --no-renames`: exit 128 after corrupt-pack errors. +- `git ls-files -m`: timeout after 20s. +- `git show HEAD:apps/web/src/features/week-advance/WeekAdvance.tsx`: succeeds in subprocess capture and was used only to recover the unreadable working-tree file. +- `dd if=apps/web/src/features/week-advance/WeekAdvance.tsx of=/dev/null bs=1048576`: blocked before file recovery. +- `wc -l apps/web/src/features/week-advance/WeekAdvance.tsx`: after recovery, succeeds with 352 lines. +- `git diff -- apps/web/src/features/week-advance/WeekAdvance.tsx .codex/MFD/chip-onboarding-goal.md --stat`: targeted diff succeeds and shows the WeekAdvance decision-impact patch; full diff still blocks. +- `git fsck --no-progress`: timeout after 30s. +- `node .../vitest/vitest.mjs run src/features/week-advance/WeekAdvance.test.tsx --reporter=verbose --pool=forks`: no runner output after 180s; process sampled at 0% CPU while loading Node dependencies. +- `node .../typescript/lib/tsc.js --noEmit --project apps/web/tsconfig.json --pretty false`: no diagnostics after 180s; process sampled at 0% CPU while reading dependency declarations. +- `node .../vite/bin/vite.js build --mode production`: produced no output and exited/killed with code -1 before Vite startup output in this desktop shell. +- Static stale preview: `python3` server mapping `/MFD/` to `apps/web/dist` plus in-app browser loaded the old build with no console errors, but Chip was not enabled in that build. + +## Preflight Repo State + +- `git status --short`: clean at start. +- `git branch --show-current`: `main`. +- `git log -1 --oneline`: `dc7740a Sprint 46: Polish standings signals (#54)`. +- Repo rules: no checked-in `AGENTS.md` or `CLAUDE.md` found in this checkout; applying Kevin's supplied AGENTS instructions from the prompt. +- Existing `.codex/MFD`: `sprint71-resume-audit.md` only. +- `pnpm --version`: unavailable (`pnpm: command not found`). +- `node_modules`: missing. +- Fallback expected for test commands: `npx --yes pnpm@9.15.9 ...`. +- Save schema baseline: `packages/engine/src/config/difficulty.ts` exports `SAVE_VERSION = 35`. +- Initial dirty files: none. + +## Existing Chip / Guidance Audit + +### Components and Stores + +- `packages/design-system/components/Chip/`: Chip SVG primitive, poses, dialogue bubble, reduced-motion behavior. +- `apps/web/src/features/companion/ChipHost.tsx`: setup/onboarding overlay, `VITE_CHIP_ENABLED` gate, legacy localStorage skip key `mfd.chip.onboarding`. +- `apps/web/src/features/companion/ChipDock.tsx`: persistent post-setup dock, controls, route beat/live beat rendering, quiet controls, `What now?`, `Where am I?`, pending decision badge. +- `apps/web/src/features/companion/store.ts`: Zustand Chip state, pose priority windows, dialogue fields, read receipts, basic `advance/dismiss/reset`. +- `apps/web/src/features/companion/dockPersistence.ts`: local dock preferences at `mfd.chip.local`. +- `apps/web/src/features/companion/readReceipts.ts`: additive web-only read receipts at `mfd.chip.read.v1`. +- `apps/web/src/features/companion/useChipEvents.ts` and `eventBridge.ts`: week rollover Chip events, weekly dialogue selection, pose reactions, quiet and spam guards. +- `apps/web/src/features/route-coaching/routeBeatRegistry.ts`: route coaching beats for roster, staff, cap lab, draft, trade center, scouting. +- `apps/web/src/features/route-coaching/useActiveRouteBeats.ts`: resolves route beat eligibility using store receipts. + +### Dialogue and Onboarding + +- `apps/web/src/features/companion/dialogue/onboarding.ts`: 9 setup beats oriented around franchise setup. Current copy is stronger for setup identity than post-setup weekly play. +- `apps/web/src/features/companion/dialogue/weekly.ts`: short deterministic weekly dialogue variants by outcome. +- `apps/web/src/features/monday-briefing/MondayBriefing.tsx`: existing Chip commentary around briefing. +- `apps/web/src/features/onboarding/TutorialOverlay.tsx` and `packages/engine/src/systems/tutorial.ts`: older generic tutorial/help surfaces. + +### Decision and Weekly Surfaces + +- `apps/web/src/features/week-advance/WeekAdvance.tsx`: readiness checklist, matchup radar, stakes panel, advance button. +- `apps/web/src/features/contracts/ContractsCap.tsx`: contract detail modal with consequence list for cuts. +- `apps/web/src/features/contracts/CapLaboratory.tsx`: cap sandbox, queued moves, projection, consequence list. +- `apps/web/src/features/trades/TradeCenter.tsx`: incoming/proposal trade workflow with value comparison and confirmation. +- `apps/web/src/features/depth-chart/DepthChart.tsx` and `apps/web/src/features/game-plan/GamePlanSetup.tsx`: high-priority route targets for first-ten-minute guidance. + +### Feature Flags and Persistence + +- Existing Chip gate: `VITE_CHIP_ENABLED === 'true'`. +- No TTS scaffold found. +- Existing share/export helpers exist for season recap and scrapbook via `apps/web/src/features/season/recap-share.ts`, but no Chip share-event scaffold found. +- Chip persistence is browser-local only and does not touch dynasty save schema. + +### Existing Tests + +- Companion: `ChipHost.test.tsx`, `ChipDock.test.tsx`, `store.test.ts`, `eventBridge.test.ts`, `useChipEvents.test.ts`, `readReceipts.test.ts`, route coaching tests. +- Weekly dialogue determinism: `dialogue/weekly.test.ts`. +- Onboarding dialogue validation: `dialogue/onboarding.test.ts`. +- Week advance, contracts, cap lab, trades each have focused component tests. + +## Current Journey vs Target Journey + +Current: +- Setup Chip is present and visually strong, but it is mostly a setup companion. +- Post-setup Chip gives short weekly outcome remarks and route coaching on a few routes. +- `What now?` replays the last weekly line instead of producing a ranked next action. +- Decision impact exists in isolated UI pieces, but there is no common immediate/season/future/risk language. +- Skip/read receipts suppress repetition, but there is no formal onboarding progress state machine or clear reset/replay/snooze workflow. +- TTS and share-card scaffolding are absent. + +Target: +- Chip has explicit onboarding progress, beat IDs, route/context gates, idempotent trigger handling, resume, reset, replay, and snooze. +- First-time players get a concise first-10-minute arc: chair framing, weekly loop, briefing, roster/depth, game plan, advance, post-advance debrief, decision impact, and advanced-system map. +- After week advance, Chip explains what changed, why it matters, top next actions, risks, feature links, and confidence. +- Major decision surfaces share concise impact explainers: immediate, this season, future, risk/uncertainty, and difficulty/severity where available. +- Player can replay/reset onboarding, snooze Chip temporarily, and ask what to do now without being trapped. +- TTS/share scaffolds are feature-flagged and default safe. + +## Slice Checklist + +- [x] Slice 1: Preflight safety check, repo rule scan, current Chip audit. +- [x] Slice 1: Create checkpoint file. +- [x] Slice 2: Formal Chip onboarding state machine and tests. +- [x] Slice 3: First-10-minute arc copy/context upgrades and tests. +- [x] Slice 4: Deterministic weekly guidance ranking and tests. +- [x] Slice 5: Decision impact explainers on highest-impact surfaces and tests. +- [x] Slice 6: Replay/reset/snooze/re-enable controls and tests. +- [x] Slice 7: TTS scaffold behind `VITE_CHIP_TTS_ENABLED` and tests. +- [x] Slice 8: Share scaffold behind `VITE_MFD_SHARE_ENABLED` and tests. +- [ ] Slice 9: QA, targeted/full verification, manual playthrough, final completion audit. + +## Files Touched Per Slice + +- Slice 1: + - `.codex/MFD/chip-onboarding-goal.md` +- Slice 2: + - `apps/web/src/features/companion/onboardingMachine.ts` + - `apps/web/src/features/companion/onboardingMachine.test.ts` +- Slice 3: + - `apps/web/src/features/companion/dialogue/onboarding.ts` + - `apps/web/src/features/companion/dialogue/onboarding.test.ts` + - `apps/web/src/features/route-coaching/routeBeatRegistry.ts` + - `apps/web/src/features/route-coaching/routeBeatRegistry.test.ts` + - `apps/web/src/features/route-coaching/useActiveRouteBeats.ts` + - `apps/web/src/features/route-coaching/useActiveRouteBeats.test.ts` + - `apps/web/src/features/companion/featureVisibilityMatrix.ts` + - `apps/web/src/features/companion/featureVisibilityMatrix.test.ts` +- Slice 4: + - `apps/web/src/features/companion/weeklyGuidance.ts` + - `apps/web/src/features/companion/weeklyGuidance.test.ts` + - `apps/web/src/features/companion/eventBridge.ts` + - `apps/web/src/features/companion/eventBridge.test.ts` + - `apps/web/src/features/companion/useChipEvents.ts` + - `apps/web/src/features/companion/useChipEvents.test.ts` +- Slice 5: + - `apps/web/src/features/companion/decisionImpact.ts` + - `apps/web/src/features/companion/decisionImpact.test.ts` + - `apps/web/src/features/week-advance/WeekAdvance.tsx` + - `apps/web/src/features/week-advance/WeekAdvance.test.tsx` + - `apps/web/src/features/contracts/CapLaboratory.tsx` + - `apps/web/src/features/contracts/CapLaboratory.test.tsx` + - `apps/web/src/features/trades/TradeCenter.tsx` + - `apps/web/src/features/trades/TradeCenter.test.tsx` +- Slice 6: + - `apps/web/src/features/companion/dockControls.ts` + - `apps/web/src/features/companion/dockControls.test.ts` + - `apps/web/src/features/companion/ChipDock.tsx` + - `apps/web/src/features/companion/ChipDock.test.tsx` +- Slice 7: + - `apps/web/src/features/companion/chipVoice.ts` + - `apps/web/src/features/companion/chipVoice.test.ts` +- Slice 8: + - `apps/web/src/features/companion/chipShare.ts` + - `apps/web/src/features/companion/chipShare.test.ts` + +## Tests Run Per Slice + +- Slice 1: + - Not applicable; audit/checkpoint only. +- Slice 2: + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/onboardingMachine.test.ts` + - Result: PASS, 4 tests. +- Slice 3: + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/route-coaching/routeBeatRegistry.test.ts src/features/route-coaching/useActiveRouteBeats.test.ts` + - Result: PASS, 18 tests. + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/dialogue/onboarding.test.ts` + - Result: PASS, 8 tests. +- Slice 4: + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/weeklyGuidance.test.ts` + - Result: PASS, 4 tests. + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/useChipEvents.test.ts src/features/companion/eventBridge.test.ts` + - Result: PASS, 24 tests. +- Slice 5: + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/decisionImpact.test.ts` + - Result: PASS, 3 tests. + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/week-advance/WeekAdvance.test.tsx src/features/contracts/CapLaboratory.test.tsx src/features/trades/TradeCenter.test.tsx` + - Result: BLOCKED/HUNG locally before output; killed only the spawned Vitest worker/npm process after no runner output. +- Slice 6: + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/ChipDock.test.tsx` + - Result: BLOCKED/HUNG locally before output; killed only the spawned Vitest worker/npm process after no runner output. + - `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/dockControls.test.ts` + - Result: BLOCKED locally. After removing a TSX import from the control reducer, this isolated suite still exits/hangs without diagnostics in this shell. Production build covers the module syntactically, but this test file has not produced a clean pass locally. +- Slice 7: + - `./node_modules/.bin/vitest run src/features/companion/dockControls.test.ts src/features/companion/chipVoice.test.ts src/features/companion/chipShare.test.ts src/features/companion/featureVisibilityMatrix.test.ts --reporter=verbose` + - Partial result before manual stop: `chipVoice.test.ts` PASS, 4 tests. Combined command then stalled on `dockControls.test.ts`. +- Slice 8: + - `./node_modules/.bin/vitest run src/features/companion/dockControls.test.ts src/features/companion/chipVoice.test.ts src/features/companion/chipShare.test.ts src/features/companion/featureVisibilityMatrix.test.ts --reporter=verbose` + - Partial result before manual stop: `chipShare.test.ts` PASS, 4 tests; `featureVisibilityMatrix.test.ts` PASS, 4 tests. Combined command then stalled on `dockControls.test.ts`. +- Slice 9: + - `./node_modules/.bin/vite build --mode production` + - Result: PASS. Built 2,511 modules and completed in 11m 22s; existing large-chunk warning remains. + - `./node_modules/.bin/tsc --noEmit --project tsconfig.json --pretty false` + - Result: BLOCKED/HUNG locally; no diagnostics after >150s, killed only that MFD `tsc` process. + - Dev server smoke: `VITE_CHIP_ENABLED=true ./node_modules/.bin/vite --host 127.0.0.1 --port 5173` + - Result: server reached ready state at `http://127.0.0.1:5173/MFD/`, but browser tooling blocked. Playwright connector returned `Transport closed`; Playwright CLI wrapper stalled under `npm exec`; HTTP `curl` requests hung while Vite repeatedly restarted on watched config/package files. Manual browser playthrough not completed. + +## Feature Visibility Matrix + +Implemented as `apps/web/src/features/companion/featureVisibilityMatrix.ts`. + +- First-ten-minute features: Monday Briefing, Roster, Depth Chart, Game Plan, Week Advance. +- Weekly/post-result features: Inbox, Schedule, Standings, League Pulse, Film Room, Team Needs. +- Pressure-window features: Injuries, Contracts, Cap Lab, Trades, Waivers, Practice Squad. +- Offseason/draft features: Scouting, Draft, Free Agency. +- Deep-dive/legacy features: Coaching, Power Rankings, Analytics, Record Book, Settings/Save Load. + +The matrix records route/entry point, purpose, why it matters, best introduction moment, first-time action, advanced note, and verification status. + +## Completion Audit Status + +- Product audit: partially passing by code inspection and build. First-10-minute arc, weekly loop, route coaching expansion, decision-impact model, replay/reset/re-enable controls, feature matrix, TTS scaffold, and share scaffold are implemented. Browser/manual confirmation is blocked. +- Engineering audit: partially passing. State machine, idempotent progress, browser-local persistence, reset/replay/snooze controls, weekly guidance tests, decision-impact pure tests, safe flags, and production build are present. `dockControls.test.ts`, TSX component tests, typecheck, git status/diff, and browser manual pass remain blocked locally. +- Commands/evidence audit: build passed; many targeted tests passed before the local runner instability. Latest `git status`/`git diff` attempts hang with no output in this desktop session, while a GitHub Desktop git status process is also present in the repo. +- Manual playthrough: blocked. Dev server reached ready state but HTTP/browser inspection did not complete because Vite repeatedly restarted under watcher activity and both Playwright connector/CLI paths were unavailable. + +## Resume Instructions + +If context compacts or the run pauses: + +1. Re-read this file. +2. Re-run `git status --short`. +3. Continue from the highest-priority incomplete slice above. +4. Keep persistence browser-local unless a save-schema change becomes unavoidable. +5. Use `npx --yes pnpm@9.15.9 ...` if global `pnpm` is still unavailable. +6. Do not mark complete until the final completion audit passes against current repo state. diff --git a/.codex/MFD/evidence/chip-art-shell-polish-20260506-210151/pre-polish-log.txt b/.codex/MFD/evidence/chip-art-shell-polish-20260506-210151/pre-polish-log.txt new file mode 100644 index 00000000..48661bf5 --- /dev/null +++ b/.codex/MFD/evidence/chip-art-shell-polish-20260506-210151/pre-polish-log.txt @@ -0,0 +1,8 @@ +a9cd1e2 polish: close final mfd release-candidate follow-ups +ea1d7a2 test: rehearse late-season mfd release candidate +0eed2cf Polish MFD release-candidate readiness +8516b05 Checkpoint Chip public-release hardening +dc7740a Sprint 46: Polish standings signals (#54) +f6c6b44 Sprint 46: Polish coaching tree visuals (#53) +ce40769 Sprint 46: Add weather forecast hub (#52) +dacda0a fix(app-test): resolve App.test.tsx conflict markers leaked from Sprint 46 Slice 2 squash merge (#61) diff --git a/.codex/MFD/evidence/chip-art-shell-polish-20260506-210151/pre-polish-status.txt b/.codex/MFD/evidence/chip-art-shell-polish-20260506-210151/pre-polish-status.txt new file mode 100644 index 00000000..2a028d42 --- /dev/null +++ b/.codex/MFD/evidence/chip-art-shell-polish-20260506-210151/pre-polish-status.txt @@ -0,0 +1,7 @@ +## codex/chip-public-release-recovery +?? .codex/MFD/evidence/.latest-final-ship-decision-dir +?? .codex/MFD/evidence/chip-art-shell-polish-20260506-210151/ +?? .codex/MFD/evidence/final-ship-decision-20260505-193901/ +?? .codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-exported-week2.mfd +?? .codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-full.diff +?? .codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-untracked-full.diff diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/chip-art-metrics.json b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/chip-art-metrics.json new file mode 100644 index 00000000..d4d383a0 --- /dev/null +++ b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/chip-art-metrics.json @@ -0,0 +1,146 @@ +[ + { + "label": "cold-open portrait", + "viewport": "desktop", + "src": "assets/chip/inline/pose-wave.png", + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.4655, + "bboxAreaFraction": 0.621, + "aspectRatio": 1 + }, + { + "label": "expanded dock", + "viewport": "desktop", + "src": "assets/chip/chip-coach.png", + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.5130255255255255, + "bboxAreaFraction": 0.8601351351351352, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "collapsed dock", + "viewport": "desktop", + "src": "assets/chip/inline/chip-coach.png", + "frame": { + "width": 68, + "height": 68 + }, + "image": { + "width": 64, + "height": 64 + }, + "inkAreaFraction": 0.5402249134948097, + "bboxAreaFraction": 0.8849480968858131, + "aspectRatio": 1 + }, + { + "label": "cold-open portrait", + "viewport": "tablet", + "src": "assets/chip/inline/pose-wave.png", + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.4655, + "bboxAreaFraction": 0.621, + "aspectRatio": 1 + }, + { + "label": "expanded dock", + "viewport": "tablet", + "src": "assets/chip/chip-coach.png", + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144.0196533203125, + "height": 176.0240478515625 + }, + "inkAreaFraction": 0.5130255255255255, + "bboxAreaFraction": 0.8601351351351352, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "collapsed dock", + "viewport": "tablet", + "src": "assets/chip/inline/chip-coach.png", + "frame": { + "width": 68, + "height": 68 + }, + "image": { + "width": 64, + "height": 64 + }, + "inkAreaFraction": 0.5402249134948097, + "bboxAreaFraction": 0.8849480968858131, + "aspectRatio": 1 + }, + { + "label": "cold-open portrait", + "viewport": "mobile", + "src": "assets/chip/inline/pose-wave.png", + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.4655, + "bboxAreaFraction": 0.621, + "aspectRatio": 1 + }, + { + "label": "expanded dock", + "viewport": "mobile", + "src": "assets/chip/chip-coach.png", + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.5130255255255255, + "bboxAreaFraction": 0.8601351351351352, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "collapsed dock", + "viewport": "mobile", + "src": "assets/chip/inline/chip-coach.png", + "frame": { + "width": 68, + "height": 68 + }, + "image": { + "width": 64, + "height": 64 + }, + "inkAreaFraction": 0.5402249134948097, + "bboxAreaFraction": 0.8849480968858131, + "aspectRatio": 1 + } +] diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-cold-open-bubble.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-cold-open-bubble.png new file mode 100644 index 00000000..49386d89 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-cold-open-bubble.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-cold-open-portrait.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-cold-open-portrait.png new file mode 100644 index 00000000..2644604d Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-cold-open-portrait.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-dock-collapsed.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-dock-collapsed.png new file mode 100644 index 00000000..68821f63 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-dock-collapsed.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-dock-expanded.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-dock-expanded.png new file mode 100644 index 00000000..ecc64e3c Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/desktop-dock-expanded.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-cold-open-bubble.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-cold-open-bubble.png new file mode 100644 index 00000000..188f6f46 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-cold-open-bubble.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-cold-open-portrait.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-cold-open-portrait.png new file mode 100644 index 00000000..2644604d Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-cold-open-portrait.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-dock-collapsed.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-dock-collapsed.png new file mode 100644 index 00000000..0af3b1c5 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-dock-collapsed.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-dock-expanded.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-dock-expanded.png new file mode 100644 index 00000000..b46eade9 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/mobile-dock-expanded.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-cold-open-bubble.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-cold-open-bubble.png new file mode 100644 index 00000000..cacc5148 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-cold-open-bubble.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-cold-open-portrait.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-cold-open-portrait.png new file mode 100644 index 00000000..2644604d Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-cold-open-portrait.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-dock-collapsed.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-dock-collapsed.png new file mode 100644 index 00000000..48fa881c Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-dock-collapsed.png differ diff --git a/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-dock-expanded.png b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-dock-expanded.png new file mode 100644 index 00000000..bd346913 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-shell-polish-v2-20260506-170852/screenshots/tablet-dock-expanded.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/chip-art-metrics.json b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/chip-art-metrics.json new file mode 100644 index 00000000..924960ad --- /dev/null +++ b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/chip-art-metrics.json @@ -0,0 +1,275 @@ +[ + { + "label": "cold-open portrait", + "viewport": "desktop", + "pose": "wave", + "src": "assets/chip/inline/pose-wave.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.5412, + "bboxAreaFraction": 0.8832, + "aspectRatio": 1 + }, + { + "label": "setup portrait talk", + "viewport": "desktop", + "pose": "talk", + "src": "assets/chip/inline/chip-broadcast.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.5309, + "bboxAreaFraction": 0.8832, + "aspectRatio": 1 + }, + { + "label": "expanded dock idle", + "viewport": "desktop", + "pose": "idle", + "src": "assets/chip/chip-coach.png", + "natural": { + "width": 600, + "height": 732 + }, + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.30544294294294294, + "bboxAreaFraction": 0.5211711711711712, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "expanded dock think", + "viewport": "desktop", + "pose": "think", + "src": "assets/chip/pose-think.png", + "natural": { + "width": 600, + "height": 732 + }, + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.3010885885885886, + "bboxAreaFraction": 0.486036036036036, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "collapsed dock", + "viewport": "desktop", + "pose": "idle", + "src": "assets/chip/inline/chip-coach.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 68, + "height": 68 + }, + "image": { + "width": 64, + "height": 64 + }, + "inkAreaFraction": 0.5270328719723183, + "bboxAreaFraction": 0.7766003460207612, + "aspectRatio": 1 + }, + { + "label": "cold-open portrait", + "viewport": "tablet", + "pose": "wave", + "src": "assets/chip/inline/pose-wave.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.5412, + "bboxAreaFraction": 0.8832, + "aspectRatio": 1 + }, + { + "label": "expanded dock idle", + "viewport": "tablet", + "pose": "idle", + "src": "assets/chip/chip-coach.png", + "natural": { + "width": 600, + "height": 732 + }, + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.30544294294294294, + "bboxAreaFraction": 0.5211711711711712, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "expanded dock think", + "viewport": "tablet", + "pose": "think", + "src": "assets/chip/pose-think.png", + "natural": { + "width": 600, + "height": 732 + }, + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.3010885885885886, + "bboxAreaFraction": 0.486036036036036, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "collapsed dock", + "viewport": "tablet", + "pose": "idle", + "src": "assets/chip/inline/chip-coach.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 68, + "height": 68 + }, + "image": { + "width": 64, + "height": 64 + }, + "inkAreaFraction": 0.5270328719723183, + "bboxAreaFraction": 0.7766003460207612, + "aspectRatio": 1 + }, + { + "label": "cold-open portrait", + "viewport": "mobile", + "pose": "wave", + "src": "assets/chip/inline/pose-wave.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 100, + "height": 100 + }, + "image": { + "width": 96, + "height": 96 + }, + "inkAreaFraction": 0.5412, + "bboxAreaFraction": 0.8832, + "aspectRatio": 1 + }, + { + "label": "expanded dock idle", + "viewport": "mobile", + "pose": "idle", + "src": "assets/chip/chip-coach.png", + "natural": { + "width": 600, + "height": 732 + }, + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.30544294294294294, + "bboxAreaFraction": 0.5211711711711712, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "expanded dock think", + "viewport": "mobile", + "pose": "think", + "src": "assets/chip/pose-think.png", + "natural": { + "width": 600, + "height": 732 + }, + "frame": { + "width": 148, + "height": 180 + }, + "image": { + "width": 144, + "height": 176 + }, + "inkAreaFraction": 0.3010885885885886, + "bboxAreaFraction": 0.486036036036036, + "aspectRatio": 0.8222222222222222 + }, + { + "label": "collapsed dock", + "viewport": "mobile", + "pose": "idle", + "src": "assets/chip/inline/chip-coach.png", + "natural": { + "width": 600, + "height": 600 + }, + "frame": { + "width": 68, + "height": 68 + }, + "image": { + "width": 64, + "height": 64 + }, + "inkAreaFraction": 0.5270328719723183, + "bboxAreaFraction": 0.7766003460207612, + "aspectRatio": 1 + } +] diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-bubble-wave.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-bubble-wave.png new file mode 100644 index 00000000..7c5dc4c7 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-bubble-wave.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-chip-next.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-chip-next.png new file mode 100644 index 00000000..ff5983ad Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-chip-next.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-portrait-wave.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-portrait-wave.png new file mode 100644 index 00000000..896a6108 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-cold-open-portrait-wave.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-collapsed-idle.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-collapsed-idle.png new file mode 100644 index 00000000..50e09b20 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-collapsed-idle.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-expanded-idle.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-expanded-idle.png new file mode 100644 index 00000000..eb752fca Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-expanded-idle.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-expanded-think.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-expanded-think.png new file mode 100644 index 00000000..573e1e25 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-dock-expanded-think.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-setup-portrait-talk.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-setup-portrait-talk.png new file mode 100644 index 00000000..c7b64d00 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/desktop-setup-portrait-talk.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-bubble-wave.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-bubble-wave.png new file mode 100644 index 00000000..e7acb4c7 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-bubble-wave.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-chip-next.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-chip-next.png new file mode 100644 index 00000000..319518de Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-chip-next.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-portrait-wave.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-portrait-wave.png new file mode 100644 index 00000000..896a6108 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-cold-open-portrait-wave.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-collapsed-idle.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-collapsed-idle.png new file mode 100644 index 00000000..dadc0bdb Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-collapsed-idle.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-expanded-idle.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-expanded-idle.png new file mode 100644 index 00000000..c6a12f15 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-expanded-idle.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-expanded-think.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-expanded-think.png new file mode 100644 index 00000000..83ff26c8 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/mobile-dock-expanded-think.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/pose-contact-sheet.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/pose-contact-sheet.png new file mode 100644 index 00000000..d01b99bb Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/pose-contact-sheet.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-bubble-wave.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-bubble-wave.png new file mode 100644 index 00000000..49386d89 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-bubble-wave.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-chip-next.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-chip-next.png new file mode 100644 index 00000000..713b944b Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-chip-next.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-portrait-wave.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-portrait-wave.png new file mode 100644 index 00000000..896a6108 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-cold-open-portrait-wave.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-collapsed-idle.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-collapsed-idle.png new file mode 100644 index 00000000..ff86f865 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-collapsed-idle.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-expanded-idle.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-expanded-idle.png new file mode 100644 index 00000000..9e621e71 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-expanded-idle.png differ diff --git a/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-expanded-think.png b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-expanded-think.png new file mode 100644 index 00000000..0ebce425 Binary files /dev/null and b/.codex/MFD/evidence/chip-art-v3-20260506-220626/screenshots/tablet-dock-expanded-think.png differ diff --git a/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-diff-name-only.txt b/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-diff-name-only.txt new file mode 100644 index 00000000..e69de29b diff --git a/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-diff-stat.txt b/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-diff-stat.txt new file mode 100644 index 00000000..e69de29b diff --git a/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-git-log.txt b/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-git-log.txt new file mode 100644 index 00000000..28a49dbf --- /dev/null +++ b/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-git-log.txt @@ -0,0 +1,5 @@ +0eed2cf Polish MFD release-candidate readiness +8516b05 Checkpoint Chip public-release hardening +dc7740a Sprint 46: Polish standings signals (#54) +f6c6b44 Sprint 46: Polish coaching tree visuals (#53) +ce40769 Sprint 46: Add weather forecast hub (#52) diff --git a/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-git-status.txt b/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-git-status.txt new file mode 100644 index 00000000..200807e1 --- /dev/null +++ b/.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/pre-rehearsal-git-status.txt @@ -0,0 +1,5 @@ +## codex/chip-public-release-recovery +?? .codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/ +?? .codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-exported-week2.mfd +?? .codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-full.diff +?? .codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-untracked-full.diff diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-finish-setup-from-depth.js b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-finish-setup-from-depth.js new file mode 100644 index 00000000..cdd2df3e --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-finish-setup-from-depth.js @@ -0,0 +1,47 @@ +async (page) => { + const notes = []; + + async function clickButton(name, wait = 300) { + await page.getByRole('button', { name }).click({ timeout: 10000 }); + notes.push(`clicked button: ${name}`); + await page.waitForTimeout(wait); + } + + async function clickFirstButton(name, wait = 300) { + await page.getByRole('button', { name }).first().click({ timeout: 10000 }); + notes.push(`clicked first button: ${name}`); + await page.waitForTimeout(wait); + } + + async function clickSpotlight(id, wait = 300) { + await page.locator(`[data-spotlight-target="${id}"]`).first().click({ timeout: 10000 }); + notes.push(`clicked spotlight: ${id}`); + await page.waitForTimeout(wait); + } + + await page.getByRole('button', { name: /Best Players/s }).click({ timeout: 10000 }); + notes.push('selected depth philosophy'); + await page.waitForTimeout(300); + await clickButton(/^Next$/); + + await clickSpotlight('wizard.cap-strategy.confirm'); + await clickButton(/^Next$/); + + await clickSpotlight('wizard.goals.confirm'); + await clickSpotlight('wizard.goals.confirm'); + await clickSpotlight('wizard.goals.confirm'); + await clickSpotlight('wizard.culture.confirm'); + await clickButton(/^Next$/); + + await clickButton(/^START WEEK 1$/, 1500); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => undefined); + + const bodyText = await page.locator('body').innerText({ timeout: 10000 }); + return { + notes, + url: page.url(), + chipVisible: /Chip|DYNASTY DESK|What now\?|Where am I\?/i.test(bodyText), + briefingVisible: /Monday Briefing|Week 1/i.test(bodyText), + bodyTextSample: bodyText.slice(0, 2200), + }; +} diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-finish-setup.js b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-finish-setup.js new file mode 100644 index 00000000..a157a621 --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-finish-setup.js @@ -0,0 +1,73 @@ +async (page) => { + const notes = []; + + async function clickButton(name, options = {}) { + const locator = page.getByRole('button', { name }); + await locator.click({ timeout: options.timeout ?? 10000 }); + notes.push(`clicked button: ${name}`); + await page.waitForTimeout(options.wait ?? 250); + } + + async function clickFirstButton(name, options = {}) { + const locator = page.getByRole('button', { name }).first(); + await locator.click({ timeout: options.timeout ?? 10000 }); + notes.push(`clicked first button: ${name}`); + await page.waitForTimeout(options.wait ?? 250); + } + + async function clickSpotlight(id, options = {}) { + const locator = page.locator(`[data-spotlight-target="${id}"]`).first(); + await locator.click({ timeout: options.timeout ?? 10000 }); + notes.push(`clicked spotlight: ${id}`); + await page.waitForTimeout(options.wait ?? 250); + } + + async function clickNext(options = {}) { + await clickButton(/^Next$/, options); + } + + await page.getByRole('button', { name: /Roster Pressure.*Open this pressure card/s }).click({ timeout: 10000 }); + notes.push('opened required roster pressure card'); + await page.waitForTimeout(250); + await clickNext(); + + await clickNext(); + + await clickFirstButton(/^Hire$/); + await clickNext(); + + await clickFirstButton(/^Hire$/); + await clickNext(); + + await clickSpotlight('wizard.scheme.confirm'); + await clickSpotlight('wizard.scheme.confirm'); + await clickNext(); + + await clickSpotlight('wizard.depth-chart.confirm'); + await clickNext(); + + await clickSpotlight('wizard.cap-strategy.confirm'); + await clickNext(); + + await clickSpotlight('wizard.goals.confirm'); + await clickSpotlight('wizard.goals.confirm'); + await clickSpotlight('wizard.goals.confirm'); + await clickSpotlight('wizard.culture.confirm'); + await clickNext(); + + await clickButton(/^START WEEK 1$/, { wait: 1500 }); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => undefined); + + const bodyText = await page.locator('body').innerText({ timeout: 10000 }); + const chipVisible = /Chip|DYNASTY DESK|What now\?|Where am I\?/i.test(bodyText); + const briefingVisible = /Monday Briefing|Week 1/i.test(bodyText); + + return { + notes, + url: page.url(), + title: await page.title(), + chipVisible, + briefingVisible, + bodyTextSample: bodyText.slice(0, 1800), + }; +} diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-multi-week-smoke.js b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-multi-week-smoke.js new file mode 100644 index 00000000..97c634b5 --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-multi-week-smoke.js @@ -0,0 +1,113 @@ +async (page) => { + const consoleEntries = []; + page.on('console', (message) => { + if (['error', 'warning'].includes(message.type())) { + consoleEntries.push(`${message.type()}: ${message.text()}`); + } + }); + + async function bodyText() { + return page.locator('body').innerText({ timeout: 10000 }); + } + + async function go(route) { + await page.goto(`http://localhost:5173/MFD/#${route}`); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => undefined); + await page.waitForTimeout(700); + } + + async function loadLatestAutosaveIfNeeded() { + await go('/dynasty'); + const continueButton = page.getByRole('button', { name: /Continue Latest Autosave/i }); + if (await continueButton.isVisible().catch(() => false)) { + await continueButton.click({ timeout: 10000 }); + await page.waitForTimeout(1200); + } + } + + async function currentWeek() { + const text = await bodyText(); + const match = text.match(/\bWK\s*0?(\d{1,2})\b/i) ?? text.match(/\bWeek\s+(\d{1,2})\b/i); + return match ? Number(match[1]) : null; + } + + async function clickIfVisible(name) { + const button = page.getByRole('button', { name }).first(); + if (await button.isVisible().catch(() => false)) { + const clicked = await button.click({ timeout: 3000 }).then(() => true).catch(() => false); + if (!clicked) return false; + await page.waitForTimeout(700); + return true; + } + return false; + } + + async function clearHalftimeOrModal() { + for (let attempt = 0; attempt < 5; attempt += 1) { + const clicked = await clickIfVisible(/^Switch$/i) + || await clickIfVisible(/^Stick$/i) + || await clickIfVisible(/^Gamble$/i) + || await clickIfVisible(/^Continue$/i) + || await clickIfVisible(/^Close$/i) + || await clickIfVisible(/^Hide$/i); + if (!clicked) return; + await page.waitForTimeout(1200); + } + } + + await page.setViewportSize({ width: 1366, height: 900 }); + await loadLatestAutosaveIfNeeded(); + + const weeks = []; + for (let step = 0; step < 8; step += 1) { + await clearHalftimeOrModal(); + await go('/game-plan'); + await clearHalftimeOrModal(); + const before = await currentWeek(); + await clickIfVisible(/Save Weekly Prep & Sim/i); + await clearHalftimeOrModal(); + + await go('/week-advance'); + await clickIfVisible(/Advance To Week/i); + await clearHalftimeOrModal(); + await page.waitForTimeout(1800); + await clearHalftimeOrModal(); + const after = await currentWeek(); + const text = await bodyText(); + weeks.push({ + before, + after, + url: page.url(), + sample: text.replace(/\s+/g, ' ').slice(0, 320), + chipVisible: /DYNASTY DESK\s*\/\/\s*CHIP|Where am I\?|What now\?/i.test(text), + errorVisible: /Something went wrong|Cannot read properties|Unhandled Runtime Error/i.test(text), + }); + if (after !== null && before !== null && after <= before) break; + if (after !== null && after >= 9) break; + } + + const laterRoutes = ['/', '/roster', '/depth-chart', '/game-plan', '/week-advance', '/trades', '/cap-lab', '/settings', '/dynasty', '/standings', '/power-rankings', '/league-pulse']; + const routeSamples = []; + for (const route of laterRoutes) { + await go(route); + const text = await bodyText(); + routeSamples.push({ + route, + sample: text.replace(/\s+/g, ' ').slice(0, 260), + errorVisible: /Something went wrong|Cannot read properties|Unhandled Runtime Error/i.test(text), + chipVisible: /DYNASTY DESK\s*\/\/\s*CHIP|Where am I\?|What now\?/i.test(text), + }); + } + + return { + weeks, + finalWeek: weeks.at(-1)?.after ?? null, + advancedCount: weeks.filter((week) => week.before !== null && week.after !== null && week.after > week.before).length, + routeSamples, + routeErrors: routeSamples.filter((route) => route.errorVisible), + chipRouteCount: routeSamples.filter((route) => route.chipVisible).length, + consoleEntries, + consoleErrorCount: consoleEntries.filter((entry) => entry.startsWith('error:')).length, + finalUrl: page.url(), + }; +} diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-route-accessibility-blank-sweep.js b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-route-accessibility-blank-sweep.js new file mode 100644 index 00000000..06907bcf --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-route-accessibility-blank-sweep.js @@ -0,0 +1,111 @@ +async (page) => { + const routes = [ + '/', + '/roster', + '/depth-chart', + '/game-plan', + '/week-advance', + '/trades', + '/cap-lab', + '/settings', + '/dynasty', + '/inbox', + '/league-pulse', + '/news', + '/standings', + '/power-rankings', + '/scouting', + '/draft', + ]; + const consoleEntries = []; + page.on('console', (message) => { + if (['error', 'warning'].includes(message.type())) { + consoleEntries.push(`${message.type()}: ${message.text()}`); + } + }); + + async function loadLatestAutosaveIfNeeded() { + await page.goto('http://localhost:5173/MFD/#/dynasty'); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => undefined); + await page.waitForTimeout(700); + const continueButton = page.getByRole('button', { name: /Continue Latest Autosave/i }); + if (await continueButton.isVisible().catch(() => false)) { + await continueButton.click({ timeout: 10000 }); + await page.waitForTimeout(1200); + } + } + + async function inspectRoute(route, viewport) { + await page.setViewportSize(viewport); + await page.goto(`http://localhost:5173/MFD/#${route}`); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => undefined); + await page.waitForTimeout(700); + return page.evaluate(() => { + const isVisible = (el) => { + const style = window.getComputedStyle(el); + const rect = el.getBoundingClientRect(); + return style.visibility !== 'hidden' && style.display !== 'none' && rect.width > 0 && rect.height > 0; + }; + const visibleButtons = Array.from(document.querySelectorAll('button')).filter(isVisible); + const unnamedButtons = visibleButtons + .map((button) => ({ + text: button.textContent?.replace(/\s+/g, ' ').trim() ?? '', + aria: button.getAttribute('aria-label') ?? '', + title: button.getAttribute('title') ?? '', + })) + .filter((button) => !button.text && !button.aria && !button.title); + const nestedInteractive = document.querySelectorAll('button button, button [role="button"], [role="button"] button').length; + const headings = Array.from(document.querySelectorAll('h1,h2,h3,[role="heading"]')) + .filter(isVisible) + .map((heading) => heading.textContent?.replace(/\s+/g, ' ').trim() ?? '') + .filter(Boolean) + .slice(0, 4); + const text = document.body.innerText.replace(/\s+/g, ' ').trim(); + const badBlankCopy = /\b(No data\.|undefined|null|NaN|Cannot read properties|Unhandled Runtime Error)\b/i.test(text); + const loadingOnly = /^Loading route/i.test(text) || text.length < 80; + const overflowX = document.documentElement.scrollWidth - document.documentElement.clientWidth; + return { + url: window.location.href, + headings, + buttonCount: visibleButtons.length, + unnamedButtonCount: unnamedButtons.length, + unnamedButtons, + nestedInteractive, + badBlankCopy, + loadingOnly, + overflowX, + sample: text.slice(0, 260), + }; + }); + } + + await loadLatestAutosaveIfNeeded(); + + const desktop = []; + for (const route of routes) { + desktop.push({ route, ...(await inspectRoute(route, { width: 1366, height: 900 })) }); + } + + const mobileRoutes = ['/', '/roster', '/depth-chart', '/game-plan', '/week-advance', '/trades', '/cap-lab', '/settings', '/dynasty']; + const mobile = []; + for (const route of mobileRoutes) { + mobile.push({ route, ...(await inspectRoute(route, { width: 390, height: 844 })) }); + } + + const failures = [...desktop, ...mobile].filter((entry) => + entry.unnamedButtonCount > 0 + || entry.nestedInteractive > 0 + || entry.badBlankCopy + || entry.loadingOnly + || entry.overflowX > 6, + ); + + return { + desktop, + mobile, + failures, + consoleEntries, + consoleErrorCount: consoleEntries.filter((entry) => entry.startsWith('error:')).length, + finalUrl: page.url(), + }; +} diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-save-load-import-smoke.js b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-save-load-import-smoke.js new file mode 100644 index 00000000..8a4989a3 --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/dev-save-load-import-smoke.js @@ -0,0 +1,131 @@ +async (page) => { + const evidenceDir = '/Users/tkevinbigham/Documents/GitHub/MFD-clean-chip-recovery/.codex/MFD/evidence/release-candidate-lockin-20260505-175132'; + const downloadPath = `${evidenceDir}/dev-exported-week2.mfd`; + const notes = []; + + async function bodyText() { + return page.locator('body').innerText({ timeout: 10000 }); + } + + async function go(route) { + await page.goto(`http://localhost:5173/MFD/#${route}`); + await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => undefined); + await page.waitForTimeout(500); + notes.push(`navigated ${route}`); + } + + async function skipBootIfNeeded() { + for (let attempt = 0; attempt < 6; attempt += 1) { + const text = await bodyText().catch(() => ''); + if (/Start Dynasty|Continue Latest Autosave|Mr\. Football Dynasty/i.test(text) && !/Initializing engine core/i.test(text)) return; + await page.keyboard.press('Enter'); + await page.waitForTimeout(500); + } + } + + async function ensureDynastyLoaded(label) { + await skipBootIfNeeded(); + const continueButton = page.getByRole('button', { name: /Continue Latest Autosave/i }); + if (await continueButton.isVisible().catch(() => false)) { + await continueButton.click({ timeout: 10000 }); + await page.waitForTimeout(1200); + notes.push(`loaded latest autosave before ${label}`); + } + } + + await go('/dynasty'); + await ensureDynastyLoaded('manual save check'); + await go('/dynasty'); + await page.getByRole('button', { name: 'Create Save Slot' }).click({ timeout: 10000 }); + notes.push('created manual save slot'); + await page.waitForTimeout(700); + + const downloadPromise = page.waitForEvent('download', { timeout: 10000 }); + await page.getByRole('button', { name: 'Download .mfd' }).click({ timeout: 10000 }); + const download = await downloadPromise; + await download.saveAs(downloadPath); + notes.push(`downloaded export to ${downloadPath}`); + + await page.getByLabel('Paste backup code').fill('not a valid dynasty cartridge'); + await page.getByRole('button', { name: 'Import Backup Code' }).click({ timeout: 10000 }); + await page.waitForTimeout(400); + const badImportText = await bodyText(); + const badImportSafe = /Could not decode cartridge|Check that you pasted the full string|Invalid cartridge JSON|Import failed|Save data/i.test(badImportText); + notes.push(`bad import safe error visible: ${badImportSafe}`); + + await page.locator('input[type="file"]').setInputFiles(downloadPath); + await page.waitForTimeout(900); + const importText = await bodyText(); + const importLoaded = /Imported dynasty loaded|Season 2026|Week 2|WK 02/i.test(importText); + notes.push(`valid import file loaded: ${importLoaded}`); + + await page.reload(); + await page.waitForTimeout(1500); + await skipBootIfNeeded(); + const recoveryText = await bodyText(); + const continueButtonVisible = await page.getByRole('button', { name: /Continue Latest Autosave/i }).isVisible().catch(() => false); + if (continueButtonVisible) { + await page.getByRole('button', { name: /Continue Latest Autosave/i }).click({ timeout: 10000 }); + await page.waitForTimeout(1000); + notes.push('loaded latest autosave after reload'); + } else { + notes.push('continue latest autosave was not visible after reload'); + } + + const loadedAfterReloadText = await bodyText(); + const loadedAfterReload = /WK 02|Week 2|Season 2026/i.test(loadedAfterReloadText) + && /New York Concrete Jungle Cabbies|NYC/i.test(loadedAfterReloadText); + notes.push(`week/team survived reload load: ${loadedAfterReload}`); + + await go('/dynasty'); + const rowText = await bodyText(); + const manualSlotVisible = /Local Save Slots[\s\S]*MANUAL|S2026 W2|S2026W2/i.test(rowText); + const manualSlotTarget = page.getByText(/New York Concrete Jungle Cabbies\s*\/\/\s*S2026 W2/i).first(); + if (await manualSlotTarget.isVisible().catch(() => false)) { + await manualSlotTarget.click({ timeout: 10000 }); + await page.getByRole('button', { name: 'Load Selected' }).click({ timeout: 10000 }); + await page.getByRole('button', { name: /^Load$/ }).click({ timeout: 10000 }); + await page.waitForTimeout(700); + notes.push('loaded selected manual save slot'); + } else { + notes.push('manual save row target not found for click'); + } + const manualLoadText = await bodyText(); + const manualLoadOk = /Save slot loaded|Season 2026|Week 2|WK 02/i.test(manualLoadText); + + await go('/settings'); + const settingsText = await bodyText(); + const settingsOk = /Settings|Autosave|Sim Speed|Halftime Hell/i.test(settingsText); + + const chipControls = ['Where am I?', 'What now?', 'Replay', 'Snooze', 'Enable']; + const chipControlResults = {}; + for (const label of chipControls) { + const locator = page.getByRole('button', { name: label }).first(); + const visible = await locator.isVisible().catch(() => false); + chipControlResults[label] = visible; + if (visible) { + await locator.click({ timeout: 10000 }); + await page.waitForTimeout(250); + } + } + const chipTextAfterControls = await bodyText(); + const chipControlsOk = Object.values(chipControlResults).every(Boolean) + && /Chip|DYNASTY DESK|Where am I\?|What now\?|Snooze|Enable/i.test(chipTextAfterControls); + + return { + notes, + downloadPath, + exportSuggestedFilename: download.suggestedFilename(), + badImportSafe, + importLoaded, + continueButtonVisible, + loadedAfterReload, + manualSlotVisible, + manualLoadOk, + settingsOk, + chipControlResults, + chipControlsOk, + finalUrl: page.url(), + finalSample: chipTextAfterControls.slice(0, 2200), + }; +} diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-diff-name-only.txt b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-diff-name-only.txt new file mode 100644 index 00000000..8140e5da --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-diff-name-only.txt @@ -0,0 +1,29 @@ +apps/web/index.html +apps/web/src/app/App.test.tsx +apps/web/src/app/App.tsx +apps/web/src/app/store/selectors.ts +apps/web/src/features/companion/ChipDock.css +apps/web/src/features/companion/ChipDock.test.tsx +apps/web/src/features/companion/ChipDock.tsx +apps/web/src/features/companion/eventBridge.test.ts +apps/web/src/features/companion/eventBridge.ts +apps/web/src/features/companion/readReceipts.ts +apps/web/src/features/companion/useChipEvents.ts +apps/web/src/features/contracts/CapLaboratory.test.tsx +apps/web/src/features/contracts/CapLaboratory.tsx +apps/web/src/features/depth-chart/DepthChart.test.tsx +apps/web/src/features/depth-chart/DepthChart.tsx +apps/web/src/features/game-plan/GamePlanSetup.tsx +apps/web/src/features/monday-briefing/MondayBriefing.tsx +apps/web/src/features/route-coaching/routeBeatRegistry.test.ts +apps/web/src/features/route-coaching/routeBeatRegistry.ts +apps/web/src/features/route-coaching/spotlightAnchors.test.ts +apps/web/src/features/route-coaching/useActiveRouteBeats.test.ts +apps/web/src/features/route-coaching/useActiveRouteBeats.ts +apps/web/src/features/trades/TradeCenter.tsx +apps/web/src/features/week-advance/WeekAdvance.test.tsx +apps/web/src/features/week-advance/WeekAdvance.tsx +apps/web/src/lib/roster-continuity-store.test.ts +apps/web/src/lib/roster-continuity-store.ts +packages/design-system/components/PixelSelect/PixelSelect.tsx +packages/design-system/tokens/index.css diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-diff-stat.txt b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-diff-stat.txt new file mode 100644 index 00000000..bb5041e5 --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-diff-stat.txt @@ -0,0 +1,30 @@ + apps/web/index.html | 7 +- + apps/web/src/app/App.test.tsx | 2 +- + apps/web/src/app/App.tsx | 21 +- + apps/web/src/app/store/selectors.ts | 4 +- + apps/web/src/features/companion/ChipDock.css | 51 ++++- + apps/web/src/features/companion/ChipDock.test.tsx | 82 +++++++- + apps/web/src/features/companion/ChipDock.tsx | 40 +++- + .../web/src/features/companion/eventBridge.test.ts | 4 + + apps/web/src/features/companion/eventBridge.ts | 9 + + apps/web/src/features/companion/readReceipts.ts | 17 ++ + apps/web/src/features/companion/useChipEvents.ts | 53 ++++- + .../src/features/contracts/CapLaboratory.test.tsx | 6 + + apps/web/src/features/contracts/CapLaboratory.tsx | 18 +- + .../src/features/depth-chart/DepthChart.test.tsx | 7 + + apps/web/src/features/depth-chart/DepthChart.tsx | 140 ++++++------- + apps/web/src/features/game-plan/GamePlanSetup.tsx | 226 +++++++++++---------- + .../features/monday-briefing/MondayBriefing.tsx | 74 +++---- + .../route-coaching/routeBeatRegistry.test.ts | 16 +- + .../features/route-coaching/routeBeatRegistry.ts | 60 ++++++ + .../route-coaching/spotlightAnchors.test.ts | 4 + + .../route-coaching/useActiveRouteBeats.test.ts | 12 ++ + .../features/route-coaching/useActiveRouteBeats.ts | 25 ++- + apps/web/src/features/trades/TradeCenter.tsx | 17 +- + .../src/features/week-advance/WeekAdvance.test.tsx | 3 + + apps/web/src/features/week-advance/WeekAdvance.tsx | 74 ++++--- + apps/web/src/lib/roster-continuity-store.test.ts | 9 + + apps/web/src/lib/roster-continuity-store.ts | 11 +- + .../components/PixelSelect/PixelSelect.tsx | 2 +- + packages/design-system/tokens/index.css | 2 + + 29 files changed, 732 insertions(+), 264 deletions(-) diff --git a/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-git-status.txt b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-git-status.txt new file mode 100644 index 00000000..d7b8e592 --- /dev/null +++ b/.codex/MFD/evidence/release-candidate-lockin-20260505-175132/pre-lockin-git-status.txt @@ -0,0 +1,49 @@ +## codex/chip-public-release-recovery + M apps/web/index.html + M apps/web/src/app/App.test.tsx + M apps/web/src/app/App.tsx + M apps/web/src/app/store/selectors.ts + M apps/web/src/features/companion/ChipDock.css + M apps/web/src/features/companion/ChipDock.test.tsx + M apps/web/src/features/companion/ChipDock.tsx + M apps/web/src/features/companion/eventBridge.test.ts + M apps/web/src/features/companion/eventBridge.ts + M apps/web/src/features/companion/readReceipts.ts + M apps/web/src/features/companion/useChipEvents.ts + M apps/web/src/features/contracts/CapLaboratory.test.tsx + M apps/web/src/features/contracts/CapLaboratory.tsx + M apps/web/src/features/depth-chart/DepthChart.test.tsx + M apps/web/src/features/depth-chart/DepthChart.tsx + M apps/web/src/features/game-plan/GamePlanSetup.tsx + M apps/web/src/features/monday-briefing/MondayBriefing.tsx + M apps/web/src/features/route-coaching/routeBeatRegistry.test.ts + M apps/web/src/features/route-coaching/routeBeatRegistry.ts + M apps/web/src/features/route-coaching/spotlightAnchors.test.ts + M apps/web/src/features/route-coaching/useActiveRouteBeats.test.ts + M apps/web/src/features/route-coaching/useActiveRouteBeats.ts + M apps/web/src/features/trades/TradeCenter.tsx + M apps/web/src/features/week-advance/WeekAdvance.test.tsx + M apps/web/src/features/week-advance/WeekAdvance.tsx + M apps/web/src/lib/roster-continuity-store.test.ts + M apps/web/src/lib/roster-continuity-store.ts + M packages/design-system/components/PixelSelect/PixelSelect.tsx + M packages/design-system/tokens/index.css +?? .codex/MFD/chip-onboarding-goal.md +?? .codex/MFD/evidence/ +?? .codex/MFD/public-release-chip-recovery-goal.md +?? .codex/MFD/public-release-readiness-matrix.md +?? apps/web/src/app/indexDocument.test.ts +?? apps/web/src/app/store/selectors.test.ts +?? apps/web/src/features/companion/chipShare.test.ts +?? apps/web/src/features/companion/chipShare.ts +?? apps/web/src/features/companion/chipVoice.test.ts +?? apps/web/src/features/companion/chipVoice.ts +?? apps/web/src/features/companion/decisionImpact.test.ts +?? apps/web/src/features/companion/decisionImpact.ts +?? apps/web/src/features/companion/featureVisibilityMatrix.ts +?? apps/web/src/features/companion/onboardingMachine.test.ts +?? apps/web/src/features/companion/onboardingMachine.ts +?? apps/web/src/features/companion/weeklyGuidance.test.ts +?? apps/web/src/features/companion/weeklyGuidance.ts +?? packages/design-system/components/PixelSelect/PixelSelect.test.tsx +?? packages/design-system/tokens/index.test.ts diff --git a/.codex/MFD/public-release-chip-recovery-goal.md b/.codex/MFD/public-release-chip-recovery-goal.md new file mode 100644 index 00000000..52b6981c --- /dev/null +++ b/.codex/MFD/public-release-chip-recovery-goal.md @@ -0,0 +1,498 @@ +# MFD Public Release + Chip Recovery Goal + +Updated: 2026-05-05 18:24:09 CDT +Original repo path: `/Users/tkevinbigham/Documents/GitHub/MFD` +Clean clone path: `/Users/tkevinbigham/Documents/GitHub/MFD-clean-chip-recovery` +Current branch: `codex/chip-public-release-recovery` +Checkout classification: clean recovery clone built from remote after the original checkout failed safe git inspection +Salvage folder: `/Users/tkevinbigham/Documents/GitHub/MFD-chip-salvage-20260505-111937` +Salvage manifest: `/Users/tkevinbigham/Documents/GitHub/MFD-chip-salvage-20260505-111937/MFD_CHIP_SALVAGE_MANIFEST.md` +Baseline commit in clean clone: `dc7740a Sprint 46: Polish standings signals (#54)` + +## Prior Blocker Summary + +- Previous Chip marathon work existed, but the original checkout was not trustworthy enough to mark MFD release-ready. +- `git status` hung in the original checkout and `git diff --stat` failed with `fatal: mmap failed: Operation canceled`. +- Earlier browser work only reached stale `dist`, and Chip was not proven in a current build. +- Recovery goals were: preserve Chip work, move into a clean clone, reapply, verify, then finish live Chip/public-release P0s. + +## Corrupt Repo Diagnosis + +- Original checkout identity was confirmed as MFD from `README.md` and `package.json`. +- Safe git inspection in `/Users/tkevinbigham/Documents/GitHub/MFD`: + - `git rev-parse --show-toplevel`: passed + - `git remote -v`: passed + - `git branch --show-current`: `main` + - `git log -1 --oneline`: `dc7740a Sprint 46: Polish standings signals (#54)` + - `git -c core.fsmonitor=false status --short --untracked-files=no`: timed out after 30s + - `git -c core.fsmonitor=false diff --stat`: failed with `fatal: mmap failed: Operation canceled` +- Conclusion: original repo stayed unsafe for build/test work. No destructive git repair was attempted. + +## Salvage + Recovery Result + +- Chip-related files and `.codex/MFD` notes were salvaged to the timestamped recovery folder above. +- Clean clone created at `/Users/tkevinbigham/Documents/GitHub/MFD-clean-chip-recovery`. +- Recovery branch created: `codex/chip-public-release-recovery`. +- All build, test, and browser verification work below was done only in the clean clone. + +## Implementation Summary + +- Reapplied and completed the Chip onboarding/weekly-guidance/decision-impact slice in the clean clone. +- Wired the formal onboarding state into the live shell and route-beat system instead of leaving guidance as isolated copy beats. +- Added guarded TTS/share scaffolds behind `VITE_CHIP_TTS_ENABLED` and `VITE_MFD_SHARE_ENABLED`. +- Added weekly guidance generation, decision-impact summaries, feature visibility sequencing, and replay/reset/snooze controls. +- Surfaced Chip guidance inside Monday Briefing, Week Advance, Game Plan, Depth Chart, Trade Center, and Cap Lab. +- Fixed a live Game Plan runtime P0 caused by an unstable selector result reference. +- Fixed a live Depth Chart DOM-nesting warning caused by rendering a player-link button inside a depth-slot button. +- Completed the P1 hardening pass for mobile tolerance, Trade Center, Cap Lab, accessibility basics, blank states, and release metadata. +- Fixed the mobile Chip dock so expanded route guidance no longer blocks underlying route controls, while dock controls remain reachable. +- Moved Cap Lab tables to responsive card mode on phone widths and raised PixelSelect plus Chip pending-badge controls to the shared 44px touch target. +- Fixed release HTML asset URLs so the `/MFD/` Vite base no longer double-prefixes the manifest/favicon/OG image paths. +- Kept save compatibility intact: no engine/schema/save-version changes were made, and sim determinism was not touched. + +## Release Candidate Lock-In Sprint — Resume + +Timestamp: 2026-05-05 17:52:39 CDT +Repo path: `/Users/tkevinbigham/Documents/GitHub/MFD-clean-chip-recovery` +Branch: `codex/chip-public-release-recovery` +Checkpoint evidence folder: `.codex/MFD/evidence/release-candidate-lockin-20260505-175132/` +Checkpoint commit: `8516b05 Checkpoint Chip public-release hardening` + +### Safety Notes + +- Confirmed active repo and git root are the clean recovery clone. +- Confirmed branch is `codex/chip-public-release-recovery`. +- Original corrupt checkout at `/Users/tkevinbigham/Documents/GitHub/MFD` was not used for work. +- Preserved the pre-lock-in worktree state with git status, diff stat, name-only list, tracked full diff, and untracked full diff. +- Pre-lock-in diff inspection found only MFD web/design-system and `.codex/MFD` documentation changes; no `dist`, deploy, non-MFD, production secret, engine save-version, or dynasty save-schema changes were found. + +### Planned Slices + +1. Save/load/settings/import-export current-code browser runtime pass. +2. Later-season Chip feature-introduction audit and focused P0/P1 fixes only. +3. Broader accessibility basics review across core routes. +4. Broader blank/loading/error state review across core routes. +5. Bundle/public delivery risk review and production preview check. +6. Multi-week smoke playthrough with Chip enabled. + +### Commands Run In This Resume So Far + +- `pwd` +- `git rev-parse --show-toplevel` +- `git branch --show-current` +- `git log -1 --oneline` +- `git status --short --branch` +- `rg --files -g 'AGENTS.md' -g 'CLAUDE.md'` +- Evidence capture commands for status, diff stat, diff name-only, tracked full diff, and untracked full diff. +- `git diff --check` — passed before checkpoint commit. +- `git add ...` — explicit file staging only; no `git add -A`. +- `git commit -m "Checkpoint Chip public-release hardening" ...` — created local checkpoint `8516b05`. + +### Browser Verification Notes + +- Current-code dev verification used Chip enabled with TTS/share disabled on `http://localhost:5173/MFD/`. +- Save/load/settings/import-export smoke passed from a Week 2 dynasty: + - manual save slot created + - `.mfd` export downloaded + - bad pasted import showed safe error copy + - exported file imported successfully + - browser reload preserved Week 2/team state through `Continue Latest Autosave` + - manual slot loaded successfully + - Settings and Chip controls remained usable after reload +- Broad route accessibility/blank-state sweep passed on desktop and phone routes with no console errors, unnamed visible buttons, nested interactive controls, bad blank copy, or page-level overflow failures. +- Multi-week smoke advanced from Week 3 to Week 9 with Chip visible across core routes and no console/runtime errors. +- Production preview used a fresh Chip-enabled build at `http://localhost:4173/MFD/`; Chip appeared in setup, `/MFD/` manifest fields were correct, and TTS/share controls were absent under disabled flags. + +### P0/P1/P2 Findings + +- P0 fixed: standings/stat-leader views no longer crash when legacy or sparse player records lack season stats. +- P0 fixed: record-tracker paths no longer crash during week advance when sparse player records lack season stats. +- P1 fixed: Roster no longer relies on a clickable table row around nested player/watch controls; the route now uses an explicit `Manage` action. +- P1 fixed: legacy tutorial overlay is gated off when Chip is enabled, avoiding setup/control overlap. +- P1 fixed: Chip dock pointer-hit area no longer blocks underlying route controls outside actual dock controls. +- P1 improved: later-season route beats now cover Inbox, Standings, Power Rankings, League Pulse/News, Record Book/Legacy, and Settings/Save Load. +- P1 documented: Vite chunk-size warnings remain pre-existing public-delivery risk, not a lock-in blocker. +- P2 deferred: TTS/share polish remains intentionally behind disabled flags. + +### Final Release-Candidate Audit + +- Baseline and final gates passed: + - `git diff --check` + - `npx --yes pnpm@9.15.9 typecheck` + - `npx --yes pnpm@9.15.9 --filter @mfd/design-system test` — 14 files / 88 tests + - `npx --yes pnpm@9.15.9 --filter @mfd/web test` — 209 files / 1292 tests + - `npx --yes pnpm@9.15.9 --filter @mfd/engine test` — 201 files / 1852 tests + - `npx --yes pnpm@9.15.9 build` — passed with existing chunk-size warnings +- Focused tests passed for ChipDock/App/MilestoneCard, route coaching, Roster, standings, and record-tracker. +- Save/load/settings/import-export, broad accessibility/blank states, production preview, and multi-week smoke were runtime-checked with current code. +- `SAVE_VERSION` remains `35`; no save schema, migration, deployment, or production secret changes were made. +- Completion rubric: 96/100 with no P0s and no category below 4. + +## Late-Season Release Rehearsal + Public Ship Prep + +Timestamp: 2026-05-05 18:56:55 CDT +Repo path: `/Users/tkevinbigham/Documents/GitHub/MFD-clean-chip-recovery` +Branch: `codex/chip-public-release-recovery` +Starting commit: `0eed2cf Polish MFD release-candidate readiness` +Evidence folder: `.codex/MFD/evidence/late-season-release-rehearsal-20260505-184434/` + +### Safety Notes + +- Confirmed active `pwd` and git root were the clean recovery clone before edits. +- Confirmed branch `codex/chip-public-release-recovery`. +- Confirmed latest starting commit `0eed2cf`; prior local checkpoint `8516b05` remains in history. +- Original corrupt checkout at `/Users/tkevinbigham/Documents/GitHub/MFD` was not used. +- Pre-rehearsal evidence captured: git status, git log, diff stat, and diff name-only. +- Prior untracked evidence inspected; large `.mfd` export and full diff snapshots remain uncommitted evidence only. + +### Planned Slices + +1. Baseline gates before behavioral changes. +2. Built-in late-season demo path for trade/playoff/offseason rehearsal. +3. Trade Center and deadline-state audit. +4. Standings, power rankings, league pulse, records, and legacy stability audit. +5. Postseason entry and playoff-lore audit. +6. Scouting/draft/offseason teaser audit. +7. Save/load/export/import audit. +8. Production preview and public `/MFD/` delivery audit. +9. Kevin playtest and release handoff package. + +### Commands Run + +- `pwd` — clean clone path confirmed. +- `git rev-parse --show-toplevel` — clean clone root confirmed. +- `git branch --show-current` — `codex/chip-public-release-recovery`. +- `git log --oneline -5` — latest `0eed2cf`. +- `git status --short --branch` — source clean except prior untracked evidence before this sprint edits. +- `git diff --check` — baseline passed. +- `npx --yes pnpm@9.15.9 typecheck` — baseline passed. +- `npx --yes pnpm@9.15.9 --filter @mfd/design-system test` — baseline passed, 14 files / 88 tests. +- `npx --yes pnpm@9.15.9 --filter @mfd/web test` — baseline passed, 209 files / 1292 tests; existing `--localstorage-file` warning only. +- `npx --yes pnpm@9.15.9 --filter @mfd/engine test` — baseline passed, 201 files / 1852 tests; existing `--localstorage-file` warning only. +- `npx --yes pnpm@9.15.9 build` — baseline passed with existing Vite chunk-size warnings. +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/dynasty-cartridge/DynastyCartridge.test.tsx --reporter=verbose` — passed, 1 file / 6 tests after clipboard fallback patch. +- `git diff --check` — final rerun passed. +- `npx --yes pnpm@9.15.9 typecheck` — final rerun passed. +- `npx --yes pnpm@9.15.9 --filter @mfd/design-system test` — final rerun passed, 14 files / 88 tests. +- `npx --yes pnpm@9.15.9 --filter @mfd/web test` — final rerun passed, 209 files / 1293 tests; existing `--localstorage-file` warning only. +- `npx --yes pnpm@9.15.9 --filter @mfd/engine test` — final rerun passed, 201 files / 1852 tests; existing `--localstorage-file` warning only. +- `npx --yes pnpm@9.15.9 build` — final rerun passed with existing Vite chunk-size warnings. +- `VITE_CHIP_ENABLED=true VITE_CHIP_TTS_ENABLED=false VITE_MFD_SHARE_ENABLED=false npx --yes pnpm@9.15.9 build` — flagged public preview build passed with the same existing chunk-size warnings. + +### Browser Verification Notes + +- Dev command: `VITE_CHIP_ENABLED=true VITE_CHIP_TTS_ENABLED=false VITE_MFD_SHARE_ENABLED=false npx --yes pnpm@9.15.9 --filter @mfd/web dev -- --host 127.0.0.1 --port 5173`. +- Vite served `http://localhost:5173/MFD/`. +- Secondary fresh-origin server used for setup isolation: `VITE_CHIP_ENABLED=true VITE_CHIP_TTS_ENABLED=false VITE_MFD_SHARE_ENABLED=false npx --yes pnpm@9.15.9 --filter @mfd/web exec vite --host 127.0.0.1 --port 5174`. +- Fresh setup reached the Week 1 shell with Chip visible and Monday Briefing present. +- Built-in convention demo provided the safe late-season fast path at Week 14, 9-4, one game behind the division leader. +- Late-season routes checked with Chip enabled: Monday Briefing, Trade Center, Trade Deadline, Cap Lab, Standings, Power Rankings, League Pulse, Record Book, Legacy, Scouting, Draft, Week Advance, Game Plan, Save/Load, Settings, Playoff Lore, and Super Bowl. +- Trade Center loaded in Week 14 with `Deadline Passed`, `TRADE WINDOW CLOSED`, direct proposal UI, empty-offer state, and no crash. +- Standings loaded with playoff picture and stat leaders; no sparse-stat or record-tracking crash appeared. +- Playoff entry reached Week 19 with `PLAYOFFS // 1 ISSUE(S)` and no route crash. +- One playoff game was advanced; Playoff Lore then showed one current-dynasty Wild Card win card. +- Super Bowl route correctly showed the not-yet-played empty state. +- Scouting and Draft routes loaded in regular-season/playoff context with clear empty/phase-gated states and Chip visible. +- Save slot creation worked. Clipboard export initially logged a browser permission error; patched to catch clipboard denial and direct the user to `Download .mfd`. After patch, current browser clipboard copy showed the normal copied status. +- Production preview command: `VITE_CHIP_ENABLED=true VITE_CHIP_TTS_ENABLED=false VITE_MFD_SHARE_ENABLED=false npx --yes pnpm@9.15.9 --filter @mfd/web preview -- --host 127.0.0.1`. +- Production preview URL: `http://localhost:4173/MFD/`. +- Production preview detail: the first preview after an unflagged build correctly showed that `VITE_CHIP_ENABLED` is build-time for Vite. The final preview therefore used a fresh flagged build plus flagged preview command. +- Final production preview loaded `/MFD/`, `manifest.json` returned `application/json`, asset paths used `/MFD/assets/...`, no source maps or `.mfd` files were present in `apps/web/dist`, Chip dock appeared on every sampled late-season route, and no `localhost:4173` console warnings/errors were reported. + +### P0/P1/P2 Findings + +- P0: none found. +- P1 fixed: `Copy Cartridge` no longer leaves an uncaught clipboard permission denial; blocked clipboard writes now fall back to player-facing Download `.mfd` guidance. +- P1 documented: active trade-deadline countdown was not reached in this pass; the built-in safe path starts Week 14 after the deadline, while Week 9 countdown coverage remains test-backed. +- P1 documented: one browser attempt to paste invalid backup code did not surface visible error copy before the clipboard fallback patch; prior lock-in had verified valid/invalid import through the same route, and no runtime crash occurred. +- P2 documented: postseason package beyond playoff-lore entry and Super Bowl placeholder remains a deeper cinematic slice. + +### Final Ship-Readiness Audit + +- Final gate rerun passed: diff check, typecheck, design-system tests, web tests, engine tests, standard build, flagged public preview build, and production preview. +- `SAVE_VERSION` remains `35`. +- No save schema, migration, engine RNG, production secret, deploy, or push changes were made. +- No broad Chip rebuild or new game system was added. +- No P0s remain from this rehearsal. + +## Commands Run + +### Install / recovery baseline + +- `npx --yes pnpm@9.15.9 install` + - Result: passed + +### Targeted regression proof before Game Plan selector fix + +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/app/store/selectors.test.ts --reporter=verbose` + - Result before fix: failed + - Root cause: repeated `selectCurrentOpponentIntel(state)` calls returned different object references on unchanged state + +### Targeted verification after selector + tooltip fix + +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/app/store/selectors.test.ts src/features/game-plan/GamePlanSetup.test.tsx --reporter=verbose` + - Result: passed + - Duration: 3.06s + +### Targeted verification after Depth Chart nesting fix + +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/depth-chart/DepthChart.test.tsx src/app/store/selectors.test.ts src/features/game-plan/GamePlanSetup.test.tsx --reporter=verbose` + - Result: 3 files / 9 tests passed + +### P1 hardening targeted verification + +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/contracts/CapLaboratory.test.tsx --reporter=verbose` + - Result: passed, 1 file / 5 tests +- `npx --yes pnpm@9.15.9 --filter @mfd/design-system exec vitest run components/PixelSelect/PixelSelect.test.tsx --reporter=verbose` + - Result: passed, 1 file / 1 test +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/features/companion/ChipDock.test.tsx --reporter=verbose` + - Result: passed, 1 file / 38 tests +- `npx --yes pnpm@9.15.9 --filter @mfd/design-system exec vitest run tokens/index.test.ts components/PixelSelect/PixelSelect.test.tsx --reporter=verbose` + - Result: passed, 2 files / 2 tests +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/app/indexDocument.test.ts src/features/companion/ChipDock.test.tsx src/features/contracts/CapLaboratory.test.tsx --reporter=verbose` + - Result: passed, 3 files / 44 tests +- `npx --yes pnpm@9.15.9 --filter @mfd/web exec vitest run src/app/indexDocument.test.ts --reporter=verbose` + - Result: passed, 1 file / 2 tests + +### Full repo gates in clean clone + +- `git diff --check` + - Result: passed +- `rg -n "SAVE_VERSION = 35|SAVE_VERSION =|Math\\.random\\(" packages/engine apps/web packages/design-system` + - Result: save version remained `35`; only existing non-sim audio `Math.random()` usage was reported +- `npx --yes pnpm@9.15.9 typecheck` + - Result: passed +- `npx --yes pnpm@9.15.9 --filter @mfd/design-system test` + - Result: passed + - Evidence: 14 test files / 88 tests passed +- `npx --yes pnpm@9.15.9 --filter @mfd/web test` + - Result: passed + - Evidence: 209 test files / 1282 tests passed + - Duration: 28.95s +- `npx --yes pnpm@9.15.9 build` + - Result: passed + - Evidence: production build completed, Vite reported chunk-size warnings only + - Build time: 5.90s + +### Earlier full-suite checkpoint from the same clean clone + +- `npx --yes pnpm@9.15.9 --filter @mfd/web test` + - Result: previously passed at 207 files / 1275 tests before final regression additions +- `npx --yes pnpm@9.15.9 typecheck` + - Result: previously passed +- `npx --yes pnpm@9.15.9 build` + - Result: previously passed + +## Browser Verification + +### Launch path + +- Dev server command: + - `env PATH="/Users/tkevinbigham/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin:$PATH" VITE_CHIP_ENABLED=true VITE_CHIP_TTS_ENABLED=false VITE_MFD_SHARE_ENABLED=false npx --yes pnpm@9.15.9 --filter @mfd/web dev -- --host 127.0.0.1 --port 4173` +- Served URL used in browser verification: + - `http://localhost:5174/MFD/` + - Note: `5173` was already occupied, so Vite served this current-code pass on `5174`. + +### Current-code first-3-week playthrough + +- Started a fresh dynasty from current source with Chip enabled. +- Completed setup flow: + - AGM: Deion "Coach D" Hardaway + - Head Coach: Dorian Cross + - Scouting Director: Marvin Tate + - Offense: Power Run + - Defense: 4-3 + - Depth philosophy: Best Players + - Cap package: Balanced Pressure Release + - Goals: Win Division, Cap Health, No Losing Streaks + - Culture mandate: Player Led +- Week 1 verified: + - Chip appeared in the live shell + - Monday Briefing copy clearly explained the weekly loop + - Dock controls present: `Where am I?`, `What now?`, `Replay`, `Snooze`, `Enable`, `Quiet for screen`, `Quiet until next week`, `Quiet this season`, `Reduce guidance`, `Disable animations` + - Route guidance verified on Monday Briefing, Roster, Depth Chart, Game Plan, and Week Advance + - Week Advance decision-impact UI showed `Immediate`, `This season`, `Future`, and `Risk` +- Week 1 advance: + - Game Plan required before advancing + - Halftime decision path was exercised + - Halftime modal: `Halftime Hell`, Jacksonville 0 - 14 New York, chose `Switch` +- Week 2 verified: + - Record updated to `0-1` + - Briefing surfaced the Week 1 result and injury notes + - Chip weekly copy changed appropriately and stayed contextual +- Week 3 verified: + - Record updated to `1-1` + - Briefing surfaced injuries, power-ranking movement, and next opponent + - Chip copy changed again and reduced repetition instead of replaying the same Week 1 text +- Replay was verified in the live Week 3 shell: replay restored the current weekly guidance after dismissal. +- TTS disabled path produced no autoplay voice or crash. +- Share disabled path produced no visible regression. + +### Runtime fixes verified in browser + +- Game Plan P0 before fix: + - `The result of getSnapshot should be cached to avoid an infinite loop` + - `Maximum update depth exceeded` +- Fix applied: + - `apps/web/src/app/store/selectors.ts` memoized `selectCurrentOpponentIntel` + - `apps/web/src/features/game-plan/GamePlanSetup.tsx` stopped passing `PixelPanel` directly as the tooltip child in the crashing surface +- Result: + - `#/game-plan` rendered normally with Chip route guidance and prep controls +- Depth Chart warning before fix: + - nested `