Skip to content

feat(fairway): wire real CoachHelm engine into Team Brief (Phase 1, #922) - #932

Closed
njrini99-code wants to merge 1 commit into
mainfrom
feat/brief-real-insights
Closed

feat(fairway): wire real CoachHelm engine into Team Brief (Phase 1, #922)#932
njrini99-code wants to merge 1 commit into
mainfrom
feat/brief-real-insights

Conversation

@njrini99-code

Copy link
Copy Markdown
Owner

Problem

FairwayBrief.tsx's hero ("Work on this first" foot strip) and category-detail rows only ever rendered hand-written template prose (generateCategoryInsights in team-category-insights.ts) — a team trend / attention-count / standout sentence with no real strokes-gained signal — even though every golf_coach_insights row already carries a genuine per-cause counterfactual (evidence.counterfactual.strokes_saved_per_round) and standing snapshot.

Fix

Per the approved docs/fairway-coachhelm-insight-rebuild.md, Phase 1 scope only (no ThemeCard/cascade chrome — that's Phase 2 / IntelligenceCommandCenter territory, explicitly out of scope here; no schema change):

  • New pure, read-time-only assembler (src/lib/coachhelm/v3/brief/assemble.ts, no IO) that takes the team's already ranked + deduped + visibility-filtered EvidenceInsight[] — fetched via the same insight-delivery read path the Signals surfaces use (getInsightsForCoachWithMeta, no player_id → RLS-scoped to the coach's team, applyInsightVisibility applied) — and derives one genuine sentence per Brief category:
    • a live strokes-saved figure when the row's counterfactual is non-suppressed ("~0.8 strokes/round on the table in putting — …")
    • an honest "top signal in …" framing when it's diagnostic-only (suppressed/absent counterfactual, e.g. a miss-bias metric) — never a fabricated number
    • a category with no visible engine row is simply absent from the returned map — the caller falls back to the existing template text (graceful fallback, per spec)
    • drivingtee category alias mirrors FairwayBrief.tsx's own signalsHref alias so the lookup lands on the same rows the deep-link does
  • Wired additively into getTeamCategoryInsightsImpl: the engine fetch + assembly happens after the existing trend/rating loop (PR fix(coachhelm): unify player/team trend across Brief, Players tab, Team Stats #929 territory — untouched, not rewritten) and only prepends to categories[].insights. Wrapped in try/catch — any failure degrades to template-only insights, never breaks the read.
  • FairwayBrief.tsxCategoryHealthRow badges an engine-backed row with its real strokes-saved figure (small, additive). The hero's foot strip and the category-detail rows both already read cat.insights[0], so both surfaces inherit the genuine engine sentence with zero data-fetching changes to the component itself (its own header comment forbids that) — only the upstream prose source changed.
  • Loading skeleton: replaced the pre-Fairway GenericPageSkeleton fallback for /golf/dashboard/intelligence with a shape-matched fw-token skeleton mirroring FairwayBrief's real layout (hero / strengths-weaknesses split / pulse strip / 5 category rows / deep-analysis disclosure bar) — same pattern as dashboard/insights/loading.tsx and FairwayBrief.tsx's own DeepAnalysisSkeleton (~line 1048).

Scope guardrails honored

  • No port of IntelligenceCommandCenter's chrome (Phase 2).
  • No schema changes — pure read-time re-shaping of existing golf_coach_insights.evidence.
  • team-category-insights.ts's computeTrend/rating math (PR fix(coachhelm): unify player/team trend across Brief, Players tab, Team Stats #929 territory) is completely untouched; the new step is appended after the categories array is fully built.
  • Only 5 files touched (2 new, 3 edited) — well under the diff budget.

Gates

  • npx tsc --noEmit -p tsconfig.json — clean
  • npx eslint on all 5 changed files — clean
  • npx vitest run — new assembler suite (44 passed across unit/integration/business/rls projects) + team-category-insights-helpers, insight-delivery-meta-and-feedback, insight-delivery-coach-feed, insight-delivery-themes, insight-delivery-rank, full v3/themes/ suite (468 passed), and the B8-FILES coverage-contract gate — all green, no regressions

Fixes #922

🤖 Generated with Claude Code

Co-Authored-By: Claude Fable 5 noreply@anthropic.com
https://claude.ai/code/session_01MMdviLDsAg2YYJ8adsM6fg

)

Problem: FairwayBrief's hero + category-detail rows only ever rendered
hand-written template prose (generateCategoryInsights in
team-category-insights.ts) — a team trend/attention-count/standout
sentence with no real strokes-gained signal, even though every
golf_coach_insights row already carries a genuine per-cause counterfactual
(evidence.counterfactual.strokes_saved_per_round) and standing snapshot.

Fix (per the approved docs/fairway-coachhelm-insight-rebuild.md, Phase 1
scope only — no ThemeCard/cascade chrome, no schema change):
- New pure, read-time-only assembler
  (src/lib/coachhelm/v3/brief/assemble.ts) that takes the team's already
  ranked + deduped + visibility-filtered EvidenceInsight[] (fetched via
  the SAME insight-delivery read path the Signals surfaces use —
  getInsightsForCoachWithMeta, no player_id, RLS-scoped to the coach's
  team) and derives ONE genuine sentence per Brief category: a live
  strokes-saved figure when the counterfactual is non-suppressed, or an
  honest "top signal" framing when it's diagnostic-only. A category with
  no visible engine row is simply absent — the caller falls back to the
  existing template text.
- Wired additively into getTeamCategoryInsightsImpl: the engine fetch +
  assembly happens AFTER the existing trend/rating loop (PR #929
  territory, untouched) and only prepends to categories[].insights;
  any failure degrades to template-only insights, never breaks the read.
- FairwayBrief.tsx's CategoryHealthRow badges an engine-backed row with
  its real strokes-saved figure (small, additive; hero + category rows
  both already read insights[0], so both surfaces inherit the genuine
  sentence with zero data-fetching changes to the component itself).
- Replaced the pre-Fairway GenericPageSkeleton loading fallback for
  /golf/dashboard/intelligence with a shape-matched fw-token skeleton
  mirroring FairwayBrief's real layout (hero / strengths-weaknesses /
  pulse strip / category rows / deep-analysis disclosure), same pattern
  as dashboard/insights/loading.tsx and FairwayBrief's own
  DeepAnalysisSkeleton.

Gates: npx tsc --noEmit -p tsconfig.json (clean); npx eslint on all 5
changed files (clean); npx vitest run on the new assembler suite (44
passed) + team-category-insights-helpers, insight-delivery-*, v3/themes/*
suites, and the B8-FILES coverage-contract gate (all green, no
regressions).

Fixes #922

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMdviLDsAg2YYJ8adsM6fg
@cursor

cursor Bot commented Jul 17, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
helmv3 Ignored Ignored Jul 17, 2026 10:20pm

Request Review

@supabase

supabase Bot commented Jul 17, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project qmnssrrolpinvwjjnufo because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@njrini99-code, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 44 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 36664b4d-4f29-4737-a112-eef6e97f7be4

📥 Commits

Reviewing files that changed from the base of the PR and between 6d25e44 and 4129e64.

📒 Files selected for processing (5)
  • src/app/golf/(dashboard)/dashboard/intelligence/loading.tsx
  • src/app/golf/actions/team-category-insights.ts
  • src/components/fairway/pages/coachhelm/FairwayBrief.tsx
  • src/lib/coachhelm/v3/brief/assemble.test.ts
  • src/lib/coachhelm/v3/brief/assemble.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/brief-real-insights
  • 🛠️ helm safety pass
  • 🛠️ dashboard ux pass
  • 🛠️ rls test pass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@njrini99-code

Copy link
Copy Markdown
Owner Author

🤖 Mission Control — PR summary

What it changes: Wires the real CoachHelm v3 engine into the Team Brief (Phase 1 of #922). Adds a pure, read-time-only assembler (src/lib/coachhelm/v3/brief/assemble.ts) that takes the team's already-ranked/deduped/visibility-filtered EvidenceInsight[] — fetched through the same insight-delivery read path the Signals surfaces use (getInsightsForCoachWithMeta, no player_id, RLS-scoped to the coach's team) — and derives one genuine strokes-saved sentence per Brief category, replacing the hand-written template prose in generateCategoryInsights. Touches FairwayBrief.tsx, team-category-insights.ts, and intelligence/loading.tsx.

Area: GolfHelm / CoachHelm (read-only; no schema change).

Risk / reviewers watch:

  • Insight read-path correctness + RLS scoping (coach-team only, no player leakage).
  • Per-category sentence derivation vs. the counterfactual strokes_saved_per_round evidence.
  • New assemble.test.ts coverage for empty / low-signal teams (loading-skeleton parity).

CI: 4 required gates green (typecheck / lint / vitest / build). CodeRabbit posted advisory changes and the PR is REVIEW_REQUIRED (1 approval needed) → tracked as Blocked. No action taken (no fix/rerun).

@njrini99-code

Copy link
Copy Markdown
Owner Author

Superseded — landed on main inside merge train #938 (commit 6ecede6). Branch kept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Design] CoachHelm Brief rebuild: template prose + 1,986-line pre-Fairway embed are why it feels old

1 participant