Skip to content

batch(baseball): 22 fixes — single-deploy batch#650

Merged
njrini99-code merged 278 commits into
mainfrom
batch/baseball-fixes
Jul 3, 2026
Merged

batch(baseball): 22 fixes — single-deploy batch#650
njrini99-code merged 278 commits into
mainfrom
batch/baseball-fixes

Conversation

@njrini99-code

@njrini99-code njrini99-code commented Jul 1, 2026

Copy link
Copy Markdown
Owner

One-merge batch — 22 BaseballHelm fixes, one production build

All fixes folded into a single branch so the whole set lands in one Vercel production deploy. Vercel auto-builds are currently paused at the project level (Ignored Build Step), so this PR did not deploy. Do not merge until instructed.

Deploy sequence (when you say go)

  1. I re-enable production builds (flip the Ignored Build Step to production-only).
  2. Apply migration 20260701020000_baseball_player_aggregates_slash_line.sql to prod (adds career_obp/slg/ops; idempotent). Must land before/with the code or the BaseballHelm: Compute OBP/SLG/OPS in legacy aggregate recalculation #436 upsert errors.
  3. Merge this PR → one production build.

Group C fixes (13) — pre-built, rebased clean

#425 recruit→public profile (#552) · #426/#427/#428 pipeline stages+DnD (#550) · #429 discover revert (#557) · #432 message nav (#553) · #459 activate exposure (#566) · #462 JUCO editor (#554) · #467 dead demo link (#570) · #470 privacy columns (#560) · #477 postgame disposition (#569) · #489/#490 lineup swap (#567) · #500 scout-packet view_count (#568) · #505 staff-invite gate (#559) · #511 coach-note scope (#571)

New fixes (9) — authored + adversarially verified

Verification

Combined tsc --noEmit clean; 44 stats unit tests pass; each new fix adversarially verified against its issue's acceptance criteria (6 CONFIRMED, 3 PLAUSIBLE with gaps fixed here, 0 rejected).

Not included

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
helmv3 Ready Ready Preview, Comment Jul 3, 2026 1:03am

Request Review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds BaseballHelm planning and audit docs, the Living Annual UI foundation, and a large batch of related BaseballHelm data, routing, page-flow, and dashboard page migration changes.

Changes

Documentation and Living Annual foundation

Layer / File(s) Summary
Docs, audits, and migration plans
docs/CLEANSLATE_JOB_LIST.md, docs/audits/*, docs/baseball/*, docs/fairway-baseballhelm-migration-plan.md
Adds the job-list, audits, postmortem, ledgers, synthesis reports, DB readiness packet, design-system spec, and migration plans.
Living Annual tokens and components
src/styles/baseball-living-annual.css, tailwind.config.ts, src/lib/fonts.ts, src/app/layout.tsx, src/app/globals.css, src/components/baseball/living-annual/*
Adds the Living Annual token set, font wiring, motion helpers, atoms, molecules, interaction primitives, and visualization primitives with barrel exports.

Application changes

Layer / File(s) Summary
Stats, innings, and records
src/lib/baseball/innings.ts, src/lib/baseball/aggregates/career-slash-line.ts, src/app/baseball/actions/stats.ts, src/app/baseball/actions/games.ts, src/components/baseball/box-score/*, src/components/baseball/season-stats/PlayerGameLog.tsx, src/lib/baseball/read-models/stats-center.ts, src/lib/baseball/read-models/player-today.ts, supabase/migrations/20260701020000_baseball_player_aggregates_slash_line.sql
Adds outs-based innings helpers, season-record lookup, career slash-line persistence, and rate-stat/read-model updates.
Server actions and data contracts
src/app/baseball/actions/*, src/lib/types/*, src/lib/baseball/read-models/*, src/lib/baseball/nav-context.ts, src/lib/baseball/nav-registry.ts
Tightens action contracts for calendars, teams, travel, camps, dev plans, messaging, practice, stat visuals, interests, scouting, documents, lifting, and route authorization, with accompanying tests.
Navigation rail wiring
src/app/baseball/(dashboard)/BaseballFairwayShell.tsx, src/app/baseball/(dashboard)/_components/*
Rebuilds coach hub navigation from the shared registry with capability/program-type gating.
Anon-safe public pages
src/app/baseball/(public)/*
Tiers public program/team/player pages between anon-safe public views and authenticated recruiting-coach queries.
Pages and Living Annual page migrations
src/app/baseball/(dashboard)/dashboard/*, src/app/baseball/(player-dashboard)/player/*, src/components/baseball/*, src/components/coach/*, src/components/layout/*
Migrates activation, analytics, announcements, calendar, camps, colleges, college-interest, command center, decision-room, dev-plans, discover, import, journey, messages, my-stats, performance, pipeline, players (profile/passport), postgame, practice/practice-effectiveness, privacy, profile, program, readiness, roster, scout-packets, settings, tasks, teams, travel, video, and watchlist surfaces onto the new Fairway/Living Annual UI contracts.
Box-score, video, and documents UI
src/components/baseball/box-score/*, src/components/features/video-player.tsx, src/components/baseball/documents/*, src/app/baseball/(dashboard)/dashboard/documents/documents-client.tsx, src/components/baseball/games/GamesList.tsx
Updates box-score upload/viewing, clip-bounded video playback, document edit/history/move modals, and season-record display.

Estimated code review effort: 5 (Critical) | ~150 minutes

Possibly related issues

Possibly related PRs

Suggested labels: design-system

🚥 Pre-merge checks | ✅ 5 | ❌ 7

❌ Failed checks (7 inconclusive)

Check name Status Explanation Resolution
No Service-Role In Client Bundles ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Rls Coverage On New Tables ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Auth Check In Server Actions ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Sport-Prefixed Table Names ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No Destructive Writes ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No Edits To Historical Migrations ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Conventional Commits ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed It uses a conventional-commit style header with the required baseball scope and matches the batch-of-fixes change set.
Description check ✅ Passed The description directly covers the BaseballHelm fix batch, deploy sequence, and the issue areas changed in this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch batch/baseball-fixes
  • 🛠️ helm safety pass
  • 🛠️ dashboard ux pass
  • 🛠️ rls test pass

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Baseball one-deploy batch: pipeline, privacy, lineup, telemetry & routing fixes

🐞 Bug fix ✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Fix recruiting pipeline stage contract, DnD targeting, and status update error handling.
• Align privacy/settings flows with real DB columns and correct staff/activation gating.
• Repair misc baseball UX issues (links, lineup swaps, note visibility, CSV telemetry) and add
 regressions tests.
Diagram

graph TD
UI["Baseball UI"] --> Actions["Server actions"] --> DB[("Supabase DB")]
UI --> Lib["Shared baseball libs"] --> DB
Tests["Contract tests"] --> Lib
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Merge fixes individually (13 PRs)
  • ➕ Smaller review chunks per PR
  • ➕ Easier to bisect regressions to a single change
  • ➖ Would trigger many production deploys (stated constraint)
  • ➖ Higher operational overhead and rollout noise
2. Use a release branch with cherry-picks then merge once
  • ➕ Preserves single production deploy
  • ➕ Keeps main cleaner during staging
  • ➖ Still requires aggregating commits; similar complexity as this batch PR
  • ➖ Adds branch management overhead and potential divergence
3. Feature-flag risky UX behavior and merge separately
  • ➕ Allows gradual enablement/rollback without reverting code
  • ➕ Reduces coupling between unrelated fixes
  • ➖ Adds permanent flag debt for what are mostly correctness bugs
  • ➖ Not a great fit for contract/gating fixes that must be enforced everywhere

Recommendation: Given the explicit “single production deploy” requirement and the fact these are mostly correctness/contract fixes, batching is the most pragmatic approach. To reduce risk, reviewers should treat this like a mini-release: verify the pipeline stage contract end-to-end (UI stages, server validation, DnD), confirm privacy settings writes only touch supported columns, and smoke-test the key navigation/telemetry paths (CSV export, messaging route, public profile links).

Files changed (22) +319 / -346

Enhancement (2) +37 / -4
scout-packet.tsAdd trackView option to token resolution and gate telemetry updates +9/-3

Add trackView option to token resolution and gate telemetry updates

• Extends resolveScoutPacketByToken to accept {trackView?: boolean} and defaults to tracking views. Telemetry updates are now conditional on both packet.ok and trackView.

src/app/baseball/actions/scout-packet.ts

PlayerProfileClient.tsxAdd coach note visibility scope selector +28/-1

Add coach note visibility scope selector

• Introduces a visibility dropdown (staff-only vs player-visible) when authoring coach notes and passes the chosen scope to createCoachNote. Keeps server enforcement while making scope explicit in the UI.

src/components/baseball/player-profile/PlayerProfileClient.tsx

Bug fix (16) +243 / -337
page.tsxRoute activation through gated server action +8/-18

Route activation through gated server action

• Replaces a raw client-side Supabase update with the gated server action to enforce the team's recruiting exposure toggle. Improves error reporting by surfacing thrown error messages when available.

src/app/baseball/(dashboard)/dashboard/activate/page.tsx

PipelineClient.tsxFix pipeline DnD stage resolution and status failure handling +33/-17

Fix pipeline DnD stage resolution and status failure handling

• Adds a stage-id set to distinguish droppable columns from draggable card IDs and resolves the drop target stage safely. Updates status change handlers (single and bulk) to respect {success} results and avoid false success toasts; adjusts grid layout to 5 columns.

src/app/baseball/(dashboard)/dashboard/pipeline/PipelineClient.tsx

page.tsxTreat JUCO players as recruiting-profile (not college-only) +4/-2

Treat JUCO players as recruiting-profile (not college-only)

• Changes the editor selection logic so only true college players use the team-only editor. JUCO players now use the recruiting ProfileEditor (with showcase fields) to match transfer recruiting behavior.

src/app/baseball/(dashboard)/dashboard/profile/page.tsx

RosterClient.tsxHonor saveLineup validation result before toasting success +9/-2

Honor saveLineup validation result before toasting success

• Checks the {success,error} response from saveLineup and only shows a success toast when the save actually persisted. Displays the server-provided validation error otherwise.

src/app/baseball/(dashboard)/dashboard/roster/RosterClient.tsx

page.tsxRedirect demo-mode spec route to Program Settings (no dead anchor) +6/-7

Redirect demo-mode spec route to Program Settings (no dead anchor)

• Updates the demo-mode settings route to redirect to the Program Settings page directly because the demo-mode section/anchor no longer exists. Uses the stable BASEBALL_PROGRAM_SETTINGS_PATH constant.

src/app/baseball/(dashboard)/dashboard/settings/demo-mode/page.tsx

page.tsxMap privacy settings from real DB columns only +10/-25

Map privacy settings from real DB columns only

• Simplifies the server-side settings transform to only include editable privacy columns (show_contact_info, show_academics, show_dream_schools). Avoids populating non-existent fields and leaves profile_visibility managed elsewhere.

src/app/baseball/(dashboard)/dashboard/settings/privacy/page.tsx

route.tsAvoid incrementing packet view telemetry on CSV downloads +2/-1

Avoid incrementing packet view telemetry on CSV downloads

• Calls resolveScoutPacketByToken with trackView: false so CSV exports don't bump view_count/last_viewed_at. Keeps download behavior as data retrieval rather than a human view event.

src/app/baseball/(public)/packet/[token]/csv/route.ts

postgame.tsPreserve coach dispositions when regenerating postgame review items +22/-1

Preserve coach dispositions when regenerating postgame review items

• Loads prior review item dispositions by dedupe_key and carries forward any non-'new' disposition when rebuilding items. Prevents reruns from reopening items a coach already resolved/converted/dismissed.

src/app/baseball/actions/postgame.ts

PlayerQuickView.tsxFix QuickView link to player public profile route +1/-1

Fix QuickView link to player public profile route

• Updates the "View Profile" link to route to /baseball/player/[id] instead of the dashboard players path.

src/components/baseball/position-planner/PlayerQuickView.tsx

PlayerDetailModal.tsxFix message navigation path under baseball dashboard +1/-1

Fix message navigation path under baseball dashboard

• Corrects the post-conversation navigation route to /baseball/dashboard/messages/[id] so message creation lands in the right app section.

src/components/coach/PlayerDetailModal.tsx

DiscoverView.tsxOnly flip watchlist UI state when add/remove succeeds +15/-6

Only flip watchlist UI state when add/remove succeeds

• Uses the {success} return from addToWatchlist/removeFromWatchlist to conditionally update local starred state. Prevents UI drift when the server rejects a mutation without throwing.

src/components/coach/discover/DiscoverView.tsx

LineupBuilder.tsxSwap lineup slots on drag instead of dropping incumbent player +21/-13

Swap lineup slots on drag instead of dropping incumbent player

• Implements true slot swapping when dragging between lineup slots (incumbent moves to source slot). Adds guards for missing target slots and clarifies bench-to-slot behavior.

src/components/coach/lineup/LineupBuilder.tsx

pipeline-card.tsxFix pipeline card link to player public profile route +1/-1

Fix pipeline card link to player public profile route

• Updates the pipeline card link target to /baseball/player/[player_id] instead of the dashboard players route.

src/components/features/pipeline-card.tsx

PrivacySettingsForm.tsxRebuild privacy form to match baseball_player_settings columns +95/-222

Rebuild privacy form to match baseball_player_settings columns

• Removes unsupported privacy toggles and narrows the form to the three real DB-backed flags (show_contact_info, show_academics, show_dream_schools) with explicit defaults. Writes only those columns via the typed Supabase client, preventing unknown-column saves.

src/components/player/settings/PrivacySettingsForm.tsx

staff-settings.tsAlign canManageStaff gating with server authority model +11/-8

Align canManageStaff gating with server authority model

• Updates the canManageStaff derivation to match staff mutation enforcement: primary/head coach or can_invite_staff only. Removes can_manage_settings from the staff-management eligibility path to avoid surfacing server-rejected UI actions.

src/lib/baseball/read-models/decision-room/staff-settings.ts

stages.tsRemove non-contract pipeline stages from UI constants +4/-12

Remove non-contract pipeline stages from UI constants

• Deletes the legacy 'contacted' and 'campus_visit' stages so PIPELINE_STAGES matches the 5-stage DB enum and server validation contract. Adds an explanatory note to prevent future drift.

src/lib/recruiting/stages.ts

Tests (2) +36 / -3
settings-aliases-and-legacy-redirects.test.tsUpdate settings alias expectations after demo-mode removal +2/-3

Update settings alias expectations after demo-mode removal

• Adjusts the alias count and expected keys to reflect the removal of the demo-mode alias. Keeps redirect/alias coverage aligned with supported deep links.

src/lib/baseball/tests/settings-aliases-and-legacy-redirects.test.ts

action-schemas.test.tsAdd regression test pinning 5-stage watchlist status contract +34/-0

Add regression test pinning 5-stage watchlist status contract

• Introduces Vitest coverage ensuring WatchlistSchemas.updateStatus accepts only the 5 valid pipeline stages and rejects legacy/unknown values. Prevents UI/server contract drift from reoccurring.

src/lib/validation/action-schemas.test.ts

Documentation (1) +1 / -1
ProgramSettingsClient.tsxUpdate Program Settings anchor documentation (remove demo-mode) +1/-1

Update Program Settings anchor documentation (remove demo-mode)

• Removes demo-mode from the documented list of section anchors that spec routes can deep-link to, aligning comments with the current page structure.

src/components/baseball/settings/ProgramSettingsClient.tsx

Other (1) +2 / -1
settings-route-aliases.tsRemove demo-mode settings alias (no anchor exists) +2/-1

Remove demo-mode settings alias (no anchor exists)

• Deletes the demo-mode alias entry and documents why it no longer exists. Aligns route alias map with the Program Settings page sections.

src/lib/baseball/settings-route-aliases.ts

njrini99-code and others added 11 commits July 1, 2026 13:22
…og (#434)

Verifier gap: the per-game rate cells still used notation IP (row.ip) as the
denominator; a 0.2 IP line rendered ERA as 9*er/0.2 instead of /0.667. Divide
by ipToInnings(row.ip) to match the corrected footer totals.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017VUauUXsm9aXegShmpJi5n
…-any)

The #445 fix reads baseball_events via fromUntyped (requires_rsvp not yet in
generated types), which made the map param implicitly any. Annotate the row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017VUauUXsm9aXegShmpJi5n
@njrini99-code njrini99-code changed the title batch(baseball): 13 Group C fixes — single-deploy batch batch(baseball): 22 fixes — single-deploy batch Jul 1, 2026
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 93 rules

Grey Divider


Action required

1. Postgame priorItems DB error ignored 🐞 Bug ☼ Reliability
Description
The new query that fetches prior dispositions to preserve coach actions (converted_to_timeline,
dismissed, etc.) destructures only data and silently ignores the error field. If the DB query
fails, priorDisposition is an empty Map and the subsequent upsert overwrites all existing
dispositions back to 'new', re-opening items the coach already actioned.
Code

src/app/baseball/actions/postgame.ts[R185-193]

+    const { data: priorItems } = await (supabase as any)
+      .from('baseball_postgame_review_items')
+      .select('dedupe_key, disposition')
+      .eq('review_id', reviewId);
+    const priorDisposition = new Map<string, string>(
+      ((priorItems ?? []) as { dedupe_key: string; disposition: string }[]).map(
+        (r) => [r.dedupe_key, r.disposition],
+      ),
+    );
Relevance

⭐⭐⭐ High

PR #584 added fail-closed pre-read to prevent DB error resetting dispositions; team prioritizes this
reliability.

PR-#584

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Line 185 destructures only { data: priorItems } from the Supabase query, discarding the error. If
the query fails, priorItems is null, priorDisposition is an empty Map (line 189-193), and the
itemRows.map at lines 195-202 finds no prior dispositions, so every item gets the default 'new'
disposition from mapItem — overwriting any coach-actioned dispositions. The upsert at line 208-210
uses ignoreDuplicates: false, which means conflicting rows are updated, not skipped.

src/app/baseball/actions/postgame.ts[185-210]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The query that fetches prior postgame review item dispositions ignores the Supabase error field. If the query fails, all prior coach dispositions are silently lost on the next regeneration.

## Issue Context
The preservation logic was introduced to prevent the upsert from resetting coach-actioned items (dismissed, converted_to_timeline, etc.) back to 'new'. But if the lookup query itself fails, the protection is bypassed silently.

## Fix Focus Areas
- src/app/baseball/actions/postgame.ts[185-193] — destructure `{ data: priorItems, error: priorItemsError }` and if `priorItemsError` is set, either return early with an error or log a warning and skip the upsert (to avoid overwriting dispositions when the lookup is unreliable)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Silent watchlist failure, no toast 🐞 Bug ☼ Reliability
Description
In DiscoverView.tsx, when addToWatchlist or removeFromWatchlist returns { success: false } (e.g.,
recruitability denial, duplicate, permission error), neither the add nor the remove branch shows any
user-facing error toast — the star simply stays in its current state with no explanation. The catch
block only logs to console, so the failure is completely invisible to the coach.
Code

src/components/coach/discover/DiscoverView.tsx[R369-377]

+        const result = await removeFromWatchlist(coachId, playerId);
+        if (result.success) {
+          setWatchlistIds((prev) => prev.filter((id) => id !== playerId));
+        }
      } else {
-        await addToWatchlist(coachId, playerId);
-        setWatchlistIds((prev) => [...prev, playerId]);
+        const result = await addToWatchlist(coachId, playerId);
+        if (result.success) {
+          setWatchlistIds((prev) => [...prev, playerId]);
+        }
Relevance

⭐⭐⭐ High

Team recently enforced “honest toasts”/revert on {success:false} for watchlist-like actions (PR
#616, #589).

PR-#616
PR-#589

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Lines 369-372 and 374-377 check result.success but have no else branch. The server actions return {
success: false, message: '...' } without throwing (watchlist.ts lines 94, 97, 112, 123 for add; line
200 for remove). The catch block at line 379-381 only calls console.error, no toast. The ticket
acceptance criteria explicitly requires 'On failure, show the server message/error via toast and
keep the prior watchlist state.'

src/components/coach/discover/DiscoverView.tsx[369-381]
src/app/baseball/actions/watchlist.ts[94-123]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
When `addToWatchlist` or `removeFromWatchlist` returns `{ success: false, message: '...' }` in `DiscoverView.tsx`, the code silently does nothing — no toast, no user feedback. The coach sees the star icon not flip but gets no explanation.

## Issue Context
The server actions return `{ success: false, message: '...' }` without throwing for expected failures (recruitability denial, duplicate, permission). The current code only handles the success path and the catch block (for thrown errors), leaving the non-throwing failure path silent.

## Fix Focus Areas
- src/components/coach/discover/DiscoverView.tsx[369-377] — add an `else` branch after each `if (result.success)` block that calls a toast with `result.message || 'Failed to update watchlist'`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

3. Wrong BaseballNoteScope import path 📘 Rule violation ⚙ Maintainability
Description
BaseballNoteScope is imported from @/lib/types/baseball-extended even though it is re-exported
from @/lib/types. This violates the requirement to import shared types from the centralized
@/lib/types entrypoint and can fragment type usage across the codebase.
Code

src/components/baseball/player-profile/PlayerProfileClient.tsx[42]

+import type { BaseballNoteScope } from '@/lib/types/baseball-extended';
Relevance

⭐ Low

Type-import-from-barrel convention was explicitly rejected before (e.g., PR #290); deep type imports
are tolerated.

PR-#290

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1519222 requires shared types to be imported from @/lib/types rather than
alternative paths. The changed line imports BaseballNoteScope from
@/lib/types/baseball-extended, despite it being available via the @/lib/types barrel export.

Rule 1519222: Import shared type definitions from '@/lib/types' instead of defining them inline
src/components/baseball/player-profile/PlayerProfileClient.tsx[42-42]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A shared type (`BaseballNoteScope`) is imported via a subpath (`@/lib/types/baseball-extended`) instead of the centralized barrel export (`@/lib/types`).

## Issue Context
`src/lib/types/index.ts` re-exports `./baseball-extended`, so consumers should import `BaseballNoteScope` from `@/lib/types`.

## Fix Focus Areas
- src/components/baseball/player-profile/PlayerProfileClient.tsx[42-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +369 to +377
const result = await removeFromWatchlist(coachId, playerId);
if (result.success) {
setWatchlistIds((prev) => prev.filter((id) => id !== playerId));
}
} else {
await addToWatchlist(coachId, playerId);
setWatchlistIds((prev) => [...prev, playerId]);
const result = await addToWatchlist(coachId, playerId);
if (result.success) {
setWatchlistIds((prev) => [...prev, playerId]);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Silent watchlist failure, no toast 🐞 Bug ☼ Reliability

In DiscoverView.tsx, when addToWatchlist or removeFromWatchlist returns { success: false } (e.g.,
recruitability denial, duplicate, permission error), neither the add nor the remove branch shows any
user-facing error toast — the star simply stays in its current state with no explanation. The catch
block only logs to console, so the failure is completely invisible to the coach.
Agent Prompt
## Issue description
When `addToWatchlist` or `removeFromWatchlist` returns `{ success: false, message: '...' }` in `DiscoverView.tsx`, the code silently does nothing — no toast, no user feedback. The coach sees the star icon not flip but gets no explanation.

## Issue Context
The server actions return `{ success: false, message: '...' }` without throwing for expected failures (recruitability denial, duplicate, permission). The current code only handles the success path and the catch block (for thrown errors), leaving the non-throwing failure path silent.

## Fix Focus Areas
- src/components/coach/discover/DiscoverView.tsx[369-377] — add an `else` branch after each `if (result.success)` block that calls a toast with `result.message || 'Failed to update watchlist'`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +185 to +193
const { data: priorItems } = await (supabase as any)
.from('baseball_postgame_review_items')
.select('dedupe_key, disposition')
.eq('review_id', reviewId);
const priorDisposition = new Map<string, string>(
((priorItems ?? []) as { dedupe_key: string; disposition: string }[]).map(
(r) => [r.dedupe_key, r.disposition],
),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Postgame prioritems db error ignored 🐞 Bug ☼ Reliability

The new query that fetches prior dispositions to preserve coach actions (converted_to_timeline,
dismissed, etc.) destructures only data and silently ignores the error field. If the DB query
fails, priorDisposition is an empty Map and the subsequent upsert overwrites all existing
dispositions back to 'new', re-opening items the coach already actioned.
Agent Prompt
## Issue description
The query that fetches prior postgame review item dispositions ignores the Supabase error field. If the query fails, all prior coach dispositions are silently lost on the next regeneration.

## Issue Context
The preservation logic was introduced to prevent the upsert from resetting coach-actioned items (dismissed, converted_to_timeline, etc.) back to 'new'. But if the lookup query itself fails, the protection is bypassed silently.

## Fix Focus Areas
- src/app/baseball/actions/postgame.ts[185-193] — destructure `{ data: priorItems, error: priorItemsError }` and if `priorItemsError` is set, either return early with an error or log a warning and skip the upsert (to avoid overwriting dispositions when the lookup is unreliable)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Fable Integrator and others added 3 commits July 2, 2026 19:47
…floating content in empty voids)

All three desktop replicas (Command Center, Stats Center, Decision Room)
wrapped their growing section in `flex-1 ... justify-center`, which
centers a short row-list inside a much taller bezel well — that's what
produced the "floating band in a cream void" look Nick flagged from the
captured frames, not a rendering fluke.

Root-cause fix: each screen is now a real header/body/footer flex column
where the body is top-aligned (never centered), and its last, growing
section is a CSS grid with `1fr` rows — that fills the exact available
height edge-to-edge regardless of the well's real rendered size, instead
of guessing at row counts/heights that may or may not fill it.

- CommandCenterScreen: added a Today schedule strip (2 rows) between the
  stat tiles and the roster; grew the roster from 4 to 7 rows with
  hairline separators; added a quiet footer strip.
- StatsCenterScreen: added a batting-lines table (6 rows: player/AB/R/H/
  RBI, right-aligned tabular-nums) between the box score and the At the
  Plate footer, which used to be ~65% empty.
- DecisionRoomScreen: promoted the 3 signals to bordered evidence cards
  (hairline + a subtle sage bg step) spread edge-to-edge via 1fr grid
  rows instead of a centered cluster; added a "This Week / 3 Signals"
  header row and a quiet "Open Decision Room" footer row.

Lift Lab phone left unchanged (already acceptable per review). Gate: tsc
--noEmit and eslint on the three changed files both clean (0 errors, 0
warnings); lint-ratchet.mjs confirms no repo-wide regression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
…rows, dead error fallback

csv-utils parseCSV: row objects are Object.create(null) so an uploaded
column named __proto__/constructor lands as an own property
(js/remote-property-injection, alert #140). player-today: the ack-error
branch is mutually exclusive with the schedule-error branch, so the
'error ??' there was provably dead (js/trivial-conditional, alert #465).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
// Null prototype: header text comes from the uploaded file, so a column
// named __proto__/constructor must land as a plain own property, never
// walk the prototype chain (CodeQL js/remote-property-injection).
const row: CSVRow = Object.create(null);
Fable Integrator and others added 2 commits July 2, 2026 20:10
items-start pinned title/meta/bar to the top of each stretched card,
leaving the lower two-thirds empty (pixel review, round-4 frames).
items-center balances each card's interior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
…/insecure-randomness #477)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
njrini99-code and others added 2 commits July 2, 2026 20:53
…baseball + auth only (Nick)

Nick 2026-07-02: 'Don't merge anything but the baseball login for now.
The rest looks like absolute garbage' + 'Admin merge all the internal
baseball changes... one branch, one deploy.'

Removed: src/app/page.tsx restored to main's landing; marketing/
first-light moments/scroll/nav/brand/screens/lib + CONTRACTS.md;
/join invite page; landing photo assets.
Kept: fonts.ts + first-light.css (the only marketing-tree files the
baseball auth shell + onboarding + lift-onboarding import — inert
token/font definitions); ALL internal baseball product work; the
redesigned baseball (auth) surfaces Nick approved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
@njrini99-code njrini99-code merged commit 08a94d1 into main Jul 3, 2026
35 of 37 checks passed
@njrini99-code njrini99-code deleted the batch/baseball-fixes branch July 3, 2026 01:13
njrini99-code pushed a commit that referenced this pull request Jul 3, 2026
…r', not 'Team Roster'

The #650 roster rebuild (RosterFairway) changed the visible masthead to
'Roster'; the document title still says 'Team Roster' but the smoke
asserts the on-page heading. First honest e2e round confirmed login now
works (secrets fix) — this was the only real failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fz1ajgmqcEp1yPEzjnXgY5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants