Skip to content

gong-product-intelligence: add Next.js UI + onboarding wizard#56

Open
Yuval Fainberg (YuvalFainberg) wants to merge 6 commits intomainfrom
yfainberg/gong-product-intelligence-ui
Open

gong-product-intelligence: add Next.js UI + onboarding wizard#56
Yuval Fainberg (YuvalFainberg) wants to merge 6 commits intomainfrom
yfainberg/gong-product-intelligence-ui

Conversation

@YuvalFainberg
Copy link
Copy Markdown
Collaborator

Summary

Adds a self-hosted Next.js UI for the Gong product intelligence agent. Users configure runs, watch live progress, view clustered evidence-anchored reports, and chat with grounded citations — all on top of the existing Python pipeline.

Also fixes several correctness bugs in analyze_calls.py that were silently inflating reports and leaking data across runs (details below).

What changed

New UI (agents/gong-product-intelligence/ui/)

  • Tabs scoped to a single run: configure / running / report / q&a
  • Studio audience picker — non-converted, pilot, contract — with a searchable org list (or "all pilots/contracts")
  • Live BigQuery call-count preview while configuring
  • SSE-streamed terminal during analysis with Retry on dropped connection
  • Multi-run history in localStorage with per-run chat persistence
  • Drill-down drawer grouped by category with verbatim evidence quotes
  • Chat tab grounds Claude in the active run's per-call evidence; [[Company]] chips in answers open the drill panel
  • Onboarding wizard auto-opens for new users — checks ANTHROPIC_API_KEY, gcloud auth, Python deps; links to Yuval on Slack for the company key

Pipeline fixes (scripts/analyze_calls.py)

  • --date-to, --focus, --org flags
  • --conversion-status accepts pilot / contract for Studio
  • Studio SQL: per-company lead dedup via ROW_NUMBER (was multiplying matched calls — e.g. DirecTV with 70+ SF opportunities was being analyzed 70x)
  • Aggregation now filters to the current run's BQ scope (cross-run cache was leaking previous runs into reports)
  • Summary always regenerated per run (no more stale executive summary)
  • McCann_NY (pilot) and McCann_Paris (contract) appear as separate picker entries but share the mccann match key — leads/calls data doesn't distinguish offices
  • Stores _run_meta (product, dates, conversion, org, focus, conversation_keys) in aggregated.json

New supporting files

  • README.md — setup, prerequisites, troubleshooting
  • scripts/requirements.txtanthropic, google-cloud-bigquery, slack-sdk
  • .gitignore — excludes data/ (verbatim quotes + Slack context stay local)

Test plan

  • pip install -r scripts/requirements.txt
  • cd ui && npm install && npm run build — passes
  • cp ui/.env.example ui/.env.local + add ANTHROPIC_API_KEY
  • gcloud auth application-default login
  • npm run dev → open localhost:3000
  • Onboarding wizard auto-opens for fresh users; "I'm a new user" button reopens it
  • Configure tab: Studio + pilot + Disney → live count shows
  • Start analysis → terminal streams output → report appears
  • Chat tab: "What do prospects say about Runway?" → answer cites companies as clickable chips → click opens drill panel grouped by category
  • Refresh page → run + chat history persist via localStorage
  • Click "+ New analysis" → previous run still reachable from sidebar

🤖 Generated with Claude Code

Adds an interactive web UI for the Gong product intelligence agent on top of
the existing Python pipeline. Users can configure runs (product, dates,
audience, focus area, optional org filter for Studio), watch progress live,
view a clustered evidence-anchored report, and chat with grounded citations.

What's new
----------
* `ui/` — Next.js 16 app
  - configure / running / report / q&a tabs scoped to a single analysis run
  - localStorage-backed multi-run history with per-run chat persistence
  - Studio audience picker: non-converted / pilot / contract, with a searchable
    org list (or "all pilots / contracts") backed by /api/orgs
  - Live BQ count preview while configuring
  - SSE-streamed terminal during analysis with Retry on dropped connection
  - Drill-down drawer grouped by category (strengths / weaknesses /
    feature requests / quotes) with verbatim evidence quotes
  - Chat tab grounds Claude in the active run's per-call evidence; answers
    cite [[Company]] chips that open the drill panel
  - Onboarding wizard auto-opens for new users — checks ANTHROPIC_API_KEY,
    gcloud auth, Python deps, etc. and links to Yuval on Slack for the key

scripts/analyze_calls.py — fixes and new flags
----------------------------------------------
* New flags: `--date-to`, `--focus`, `--org`
* `--conversion-status` accepts pilot / contract for studio (in addition to
  non-converted / converted / both)
* Studio SQL keeps McCann_NY (pilot) and McCann_Paris (contract) as separate
  picker entries while sharing a `mccann` match key — leads/calls data
  doesn't distinguish offices
* Per-company lead dedup via ROW_NUMBER (was multiplying matched calls — e.g.
  DirecTV with 70+ SF opportunities was being analyzed 70 times)
* Defensive dedup of `to_process` and aggregation `scoped_results` by
  conversation_key
* Aggregation now filters to the current run's BQ scope (cross-run cache
  was leaking calls from previous runs into the report)
* Summary always regenerated per run (no more stale executive summary)
* Stores `_run_meta` (product, dates, conversion, org, focus,
  conversation_keys) in aggregated.json

Other
-----
* `README.md` — setup walkthrough, prerequisites, troubleshooting
* `scripts/requirements.txt` — anthropic, google-cloud-bigquery, slack-sdk
* `.gitignore` — excludes `data/` (verbatim quotes + Slack context never
  leave the local machine)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The /api/count and /api/orgs endpoints would silently fail when the user
lacked BQ permissions or auth — UI just showed "—" with no hint of why.

Now both errors render an inline BQErrorBlock with:
- The verbatim error message from BigQuery
- Diagnosis (permission issue vs generic)
- A `bq query` command the user (or their AI assistant) can run to confirm
- Direction to ping Yuval on Slack for IAM access if it's a permission issue

Makes it obvious to a fresh user (and to a tool like Cursor reading their
screen) what's broken and how to fix it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The gcloud check used to only verify that ADC credentials existed locally.
That would pass for any Lightricks employee — even those without IAM read
access on ltx-dwh-prod-processed. They'd see ✓ on Google Cloud, then hit
silent BQ failures the moment they touched the configure tab.

Now the check runs `SELECT 1 AS ok` against ltx-dwh-prod-processed via the
BigQuery client. Three outcomes:

- ADC missing                   → step shows the gcloud login command
- ADC present + BQ access ✓     → step is green, detail says "read access
                                  to ltx-dwh-prod-processed confirmed"
- ADC present + BQ access ✗     → step is red, body explicitly says
                                  "authenticated but no IAM access", and the
                                  note tells the user to ping Yuval on Slack
                                  for ltx-dwh-prod-processed read role

Surfaces the most common new-user blocker before they hit a wall on
configure / running tabs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each failing step now exposes a ready-made AI assistant prompt that the user
can hand to their local Cursor or Claude Code instance to fix the problem
end-to-end (install deps, run gcloud login, draft a Slack DM to Yuval for
IAM, etc.).

Specifically:
- pythonDeps: prompt that runs pip install + verifies imports
- gcloud (no ADC): prompt that runs gcloud auth + verifies token
- gcloud (no BQ access): prompt that runs the bq SELECT 1 test, then helps
  the user draft a polite Slack message to Yuval requesting BigQuery Data
  Viewer + Job User roles on ltx-dwh-prod-processed
- anthropic: prompt that walks through pulling the company key from
  1Password / Slack and adding it to .env.local without committing

UI-wise: each prompt sits in an amber callout under the step's command box,
with its own "copy prompt" button. Distinct color from the purple "note"
callout so it's clear which is human-readable advice vs. machine-readable
instruction.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A batch of UX/correctness improvements based on running the tool with fresh
users at Lightricks. No changes to the per-call analysis prompts or the
caching contract.

Onboarding & defaults
- App always lands on the configure tab (not the latest report). The latest
  run is still active in the sidebar and one click away.
- "LTX · product intel" brand in the appbar is clickable — same as
  "+ New analysis", brings you back to a fresh configure screen.
- Removed the unimplemented "Save preset" button.
- Onboarding wizard distinguishes "no ADC credentials" from "authenticated
  but no BQ access" by actually running SELECT 1 against
  ltx-dwh-prod-processed. The no-bq-access case now points the user toward
  a local fix (re-auth, set quota project) instead of asking a teammate for
  IAM — that was wrong advice; in practice it's almost always a local
  connection problem.
- All references to a specific person renamed to "one of the LTX data team
  members" except where the underlying ask is for a shared secret.

Multi-select audience & orgs (studio)
- Audience picker is now multi-select: any combination of non-converted /
  pilot / contract. Help text adapts ("combined: pilot + contract").
- Company picker is shown whenever pilot or contract is in the selection
  (previously only when one of them was selected alone). Lists orgs from
  whichever plan types are active.
- Company picker is now multi-select too — pick zero (= all) or many.
  "All" row at the top is a radio-style mutually-exclusive option;
  individual companies are checkboxes with a small PILOT/CONTRACT badge.
- Wire format for both is CSV in the existing `conversion` and `org` JSON
  fields. Backwards-compatible with single-value runs already in
  localStorage.
- /api/count and the studio SQL in analyze_calls.py both build OR predicates
  for audiences and IN clauses for multiple orgs. New helper
  `build_studio_conversion_filter` consolidates the logic.
- Surfaces inline BQ errors in ConfigureView when /api/count or /api/orgs
  fail, with a copyable diagnostic command and pointer to the onboarding
  AI-prompt. (Previously failures showed "—" with no hint.)

Org list visual
- Replaced the cramped 3-col chip grid with a single-column scrollable
  list. Each row: checkbox + company name + plan-type badge. Much easier to
  read with 30+ companies.

RunningView redesign
- Phase stepper (Loading context → Querying BQ → Analyzing → Clustering →
  Complete) at the top with a pulsing dot on the active phase.
- Progress card with live counters: progress (X / Y), cached, new, phase.
- "Recently analyzed" feed showing the last 6 calls processed with company,
  industry, and a colored sentiment badge.
- Python deprecation warnings (urllib3, google-auth, etc.) are filtered out
  of the curated mini-log — they're still available in the collapsible
  "Show full terminal log" toggle.
- Errors that are NOT noise get their own red error card.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The BQ clients were pinned to `ltx-dwh-prod-processed` for the project ID,
which forced jobs to be CREATED on that project. Most Lightricks accounts
have BigQuery Data Viewer on the warehouse but NOT bigquery.jobs.create —
so every fresh user hit "Access Denied" on /api/count and /api/orgs the
moment they tried to use the tool.

Fix: never pin the BQ client. Jobs are now billed to the user's own ADC
quota project; data still comes from ltx-dwh-prod-processed via the fully-
qualified table names already used everywhere in the SQL. Users just need:
- bigquery.jobs.create on any project they belong to (default for all accounts)
- bigquery.dataViewer on ltx-dwh-prod-processed (the standard analytics role)

Optional `GCLOUD_BILLING_PROJECT` env var lets a user pin billing to a
specific project if they want.

Other changes:
- /api/setup test query now actually queries a prod table (LIMIT 1) instead
  of a project-less SELECT 1. Validates BOTH jobs.create on user's billing
  project AND dataViewer on the warehouse — the real combined permission
  the app needs.
- Onboarding wizard's NO_BQ_ACCESS prompt rewritten: tells the user to
  point set-quota-project at one of THEIR Lightricks projects (not at
  ltx-dwh-prod-processed, which they don't own). Verification query now
  uses a real warehouse table.
- BQ error block in ConfigureView updated with the same corrected guidance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant