Skip to main content

Signal — POC Management

Written by Schae Lilley

POC Management (route /predictions/poc-management in Signal, Power Digital's internal BI web app) is the screen where Group Directors and Account Directors manage a client's client-side points of contact. For every contact detected in analyzed client calls it shows AI-scored relationship sentiment (satisfaction, engagement, churn risk, decision influence, mood, and positive/negative call rates, each averaged over the last 5 weeks and originating from the AI call-analysis pipeline over recorded client calls), and it lets the client's GD, AD, or an admin enrich each contact with an internal "relationship owner", title, LinkedIn, reporting line, last 1:1 date, and free-text context — plus create "prospect" cards for relationships the team should build but doesn't have yet. It answers: "Who are our contacts at this client, how healthy is each relationship, and who on our side owns it?" Visibility is scoped to the caller's book (their GD/AD clients plus clients where they are on the team roster; admins see all). Client names, tiers, divisions, and directors come from Nova (the ops platform); the revenue-active client list is gated by Vena (the finance contract system); all manual card data is Signal's own records (entered by users in Signal).

Field

Value

Route

/predictions/poc-management and /predictions/poc-management/:clientId (deep link per client)

Access

Team Lead and above (MemberAllowedRoute guard in src/App.tsx redirects base-tier Members to /summary); per-client visibility further scoped server-side to the caller's book; editing restricted per client to its GD / AD (incl. Senior AD) / admins

Nav section

Client Health (link "POC Management", no extra flag — visible to every non-Member user)

Primary data sources

AI call-analysis sentiment over recorded client calls (per-contact 5-week scores, read-only); Nova (client names/tiers/divisions, Group Director, Account Director fallback, employee directory); Vena (revenue-active client gating); Signal's own records — entered by users in Signal (POC cards, AD overrides, team rosters, admin/role flags)

Writes

Signal's own records: table poc_cards (create/edit/soft-archive contact cards and prospect cards) via POST /api/poc-management/cards and PATCH /api/poc-management/cards/:id

Key code refs

src/views/PocManagementView.tsx, src/views/predictions/pocScoring.ts, src/views/predictions/PocAccordion.tsx (pocPriorityScore, pocPriorityTier), src/services/pocCards.ts, src/services/api.ts (getPocManagement, createPocCard, updatePocCard, archivePocCard), server/index.ts (/api/poc-management*, resolvePocAccess, assertPocEditAllowed), server/predictions.ts (fetchPocContactsByClient, buildPocMap, fetchPortfolioData), server/activeBook.ts, supabase/migrations/20260624_poc_cards.sql, 20260624b_poc_cards_contact_fields.sql

Last verified

staging @ 98df0c4, verified 2026-07-07

Purpose

POC Management exists because client relationships go stale invisibly: the one champion who loved Power Digital leaves, nobody internally "owns" the CFO relationship, and a sentiment decline was audible in calls months before the churn conversation. The POC Management view in Signal solves three problems on one screen:

  1. Visibility — every tracked client contact appears with rolling 5-week sentiment signals (satisfaction, engagement, churn risk, decision influence, mood, positive/negative call rates) computed by the AI call-analysis pipeline from recorded client calls, sorted so the most at-risk, most influential, most senior contacts float to the top.

  2. Accountability — the client's Group Director or Account Director can assign a named internal "relationship owner" to each contact and record context the scores cannot capture (reporting lines, LinkedIn, when the last 1:1 happened).

  3. Deliberate relationship-building — leaders can create "prospect" cards for contacts the team should have a relationship with but does not yet (for example a client's new VP Marketing), turning multi-threading from an aspiration into a tracked, owned list.

Nothing on this screen changes sentiment data, the client list, or GD/AD assignments — those are read-only here and managed upstream (Nova and the Manage Leads view in Signal).

Access & visibility

Access to POC Management has two layers — a route gate and a server-side per-client scope — plus a separate per-client edit permission.

Route gate (who can open the page at all). The routes /predictions/poc-management and /predictions/poc-management/:clientId are wrapped in MemberAllowedRoute (src/App.tsx). A base-tier "Member" — a signed-in user with none of the elevated flags (is_team_lead, is_admin, is_gandalf, Sauron super-admin, or any Growth capability) — is redirected to /summary. In practice this makes POC Management a Team Lead-and-above view. The is_team_lead flag lives on the app_users table in Signal's own records; it is granted manually by an admin on the General Access screen, or automatically at sign-in when the user is an active Account Director or Group Director on any Nova client. The nav link "POC Management" sits in the Client Health sidebar section with no extra flag, so it is visible to every non-Member user (Members' sidebars are filtered down to Summary and Employees only).

Server-side visibility scope (which clients appear). GET /api/poc-management calls resolvePocAccess(callerEmail) in server/index.ts. A caller sees a client if any of the following hold (admins — is_admin or is_gandalf on app_users, or the hardcoded Sauron super-admin email list — see all clients):

  • They are the client's Group Director — resolved from Nova assignment history (role = group_director, most recent assignment per client, active non-terminated users only).

  • They are the client's Account Director — resolved from the AD ownership map, which unions three inputs: manual AD picks stored in Signal's own records (table client_account_directors, set on Manage Leads), a Nova fallback (the client's executive sponsor in Nova, used when no manual AD row exists), and Senior AD rows (table client_senior_account_directors, also Signal's own records). Senior Account Directors therefore get the same visibility and edit rights as ADs on this screen.

  • They are an assigned team member on the client's latest-month team roster (table team_assignments, Signal's own records, saved on Manage Leads) — this grants view-only access.

Ownership maps are cached server-side for 5 minutes and are the same maps used by Pulse ownership checks, so POC edit rights always match Pulse submission rights.

Edit permission (per client). Each client in the response carries a can_edit flag: true only for the client's GD, an AD/Senior AD (including the Nova executive-sponsor fallback), or an admin. Assigned team members see a "View only" chip on the client header and get no edit controls. Writes are re-checked server-side by assertPocEditAllowed on every request — blocked attempts are logged and rejected with HTTP 403, so the browser cannot bypass the gate.

Which clients exist in the list at all. The client universe is the same "active book" used by Portfolio Review (server/activeBook.ts): non-deleted Nova clients that are revenue-active per Vena (current-month contract MGP > 0, or recent VABO value), refreshed on a 15-minute server cache. Fully churned or zero-revenue clients do not appear.

Data sources & lineage

All Snowflake/warehouse hops are transport only; the table below names the core origin system for each on-screen element of the POC Management view.

On-screen element

Origin system

Code path

Refresh

Caveat

Client list (name, division, tier) and which clients are listed at all

Nova (client records: name, tier, division) gated by Vena (revenue-active contracts / VABO)

GET /api/poc-management → getPortfolioBaseCached() → fetchPortfolioData() + fetchActiveBook() (server/predictions.ts, server/activeBook.ts)

Portfolio base: 15-min stale-while-revalidate server cache; active book: 15-min cache

Same base as Portfolio Review — if a client is missing or misnamed here it will be identical there; fix upstream in Nova / Vena

Group Director chip

Nova (client's group_director_id joined to active users)

fetchPortfolioData() GD query in server/predictions.ts

Inside the 15-min portfolio base cache

Terminated users are excluded; a client whose GD left shows "—"

Account Director chip

Signal's own records (manual AD pick from Manage Leads, table client_account_directors) with fallback to Nova (client executive sponsor)

fetchPortfolioData() — overrideAdNameMap then Nova exec-sponsor join (server/predictions.ts)

Inside the 15-min portfolio base cache

The displayed AD chip does not include Senior ADs (table client_senior_account_directors), but Senior ADs still hold edit rights — so a person can legitimately edit a client whose AD chip names someone else

Sentiment band chips per contact (Satisfaction, Engagement, Churn Risk, Decision Influence, Mood, Positive Call Rate, Negative Call Rate)

AI call-analysis pipeline over recorded client calls (per-contact rolling last-5-weeks averages; pipeline built outside the Signal repo — elsewhere in Signal the call-derived sentiment source is labeled "gong")

fetchPocContactsByClient() → FINAL_POC_SENTIMENT view (server/predictions.ts); banded client-side in src/views/predictions/pocScoring.ts

15-min server table cache (_TABLE_TTL_MS); upstream pipeline refresh cadence not defined in the app repo

Contacts with no analyzed calls in the window show "No sentiment data yet" — common and normal

Priority chip ("High/Medium priority") and card sort order

Computed in the browser from the same call-sentiment fields plus contact title

pocPriorityScore / pocPriorityTier in src/views/predictions/PocAccordion.tsx

Pure computation on each render

Thresholds are code constants (as of Jul 2026): High ≥ 1.55, Medium ≥ 1.25

"Editable by you" summary card and the per-client "View only" chip

Nova (GD assignment history, exec sponsor) + Signal's own records (AD/Senior AD tables, team_assignments, app_users admin flags)

resolvePocAccess() / assertPocEditAllowed() in server/index.ts

Ownership maps cached 5 min server-side

Same source of truth as Pulse ownership

Owner, context note, title override, LinkedIn, reports-to, last 1:1 on each card; all Prospect cards

Signal's own records (entered by users in Signal) — table poc_cards

Read directly from the browser via listPocCards in src/services/pocCards.ts (open-read RLS)

Live read every time a client is selected; re-read after every save

Non-archived rows only, newest first. Cards attach to a sentiment contact by email (preferred) or name — if the contact's email/name changes upstream, the card detaches and its content shows nowhere until re-matched

Relationship-owner typeahead (employee search)

Nova (active employee directory with job titles and divisions)

GET /api/employees via DataContext (server/index.ts)

1-hour server cache

Stores the employee's email on the card (name as fallback when the employee has no email)

Metrics & definitions

All sentiment metrics on the POC Management view are per-contact rolling averages over the last 5 weeks of analyzed client calls, produced by the AI call-analysis pipeline (upstream of the Signal repo). Signal bands each raw score into High / Medium / Low in the browser (pocResult in src/views/predictions/pocScoring.ts); all cutoffs below are code constants as of Jul 2026.

Metric

Plain definition

Scale and banding

Good direction

Satisfaction

How satisfied the contact sounds with current performance

1–10; High ≥ 7, Medium ≥ 4, else Low

Higher is better (High = green)

Engagement

How actively the contact participates in conversations

1–10; High ≥ 7, Medium ≥ 4, else Low

Higher is better

Churn Risk

How strongly the contact's language signals likelihood of churn

1–10; High ≥ 7, Medium ≥ 4, else Low

Lower is better (High = red)

Decision Influence

How much decision-making authority the contact appears to hold

1–5; High ≥ 4, Medium ≥ 2.5, else Low

Higher = more influential (informational, not good/bad)

Mood

Overall tone in interactions

1–5; High ≥ 4, Medium ≥ 2.5, else Low

Higher is better

Positive Call Rate

Share of the contact's recent calls classified positive

0–1 rate; High ≥ 0.6, Medium ≥ 0.3, else Low

Higher is better

Negative Call Rate

Share of the contact's recent calls classified negative

0–1 rate; High ≥ 0.4, Medium ≥ 0.2, else Low

Lower is better (High = red)

Priority score (drives card order and the High/Medium priority chip). Computed in the browser (pocPriorityScore in src/views/predictions/PocAccordion.tsx):

priority = dataBoost + 0.5 × distress + 0.25 × normalizedDecisionInfluence + 0.25 × titleSeniority

  • dataBoost = 1.0 if the contact has at least one sentiment metric, else 0 (contacts with data always sort above contacts without).

  • distress = average of normalized "badness" across available metrics: low satisfaction, low engagement, high churn risk, low mood, low positive call rate, high negative call rate (each scaled to 0–1).

  • normalizedDecisionInfluence = (influence − 1) / 4, scaling the 1–5 score to 0–1.

  • titleSeniority = regex tiers on the contact's title (code constants as of Jul 2026): C-suite 1.0, SVP 0.85, VP 0.70, Director 0.55, Senior Manager 0.40, Manager 0.30, Lead/Head-of 0.25, Coordinator/Specialist/Analyst 0.15, anything else 0.10.

Priority tier (pocPriorityTier): score ≥ 1.55 → "High" (red chip), ≥ 1.25 → "Medium" (amber chip), otherwise "Low" (no chip shown). Plain reading: a contact gets a High-priority chip when they combine negative recent sentiment with decision influence and title seniority.

Summary cards at the top of the POC Management view: Clients = number of clients visible to the caller; Tracked POCs = total contacts with call-sentiment tracking across those clients; Editable by you = how many of those clients the caller can edit as GD / AD / admin.

How it's used

  1. Pre-call relationship briefing. Before a check-in or QBR, an Account Director opens the client in POC Management, scans the sentiment band chips on each contact, and reads the context notes and "Reports to" lines. Decision: who to address in the meeting, whose concerns to defuse first, and whether to bring the Group Director in.

  2. Triage a deteriorating relationship. A Group Director works through their book and spots a "High priority" contact — senior, high decision influence, high churn risk or low satisfaction on recent calls. Decision: schedule a direct 1:1 with that contact, assign a senior relationship owner, and record the plan in the context note.

  3. Assign relationship ownership. During account planning, the AD walks each tracked contact and uses the owner typeahead (searches the whole company directory) to put a name on every relationship. Decision: who on the Power Digital side owns each thread of the client relationship — no more "Unassigned".

  4. Build the multi-threading plan. The AD adds prospect cards for people the team should know but doesn't — the client's new CMO, the finance approver — each with an owner and a "why we want this relationship" note. Decision: which new relationships to invest in this quarter, with a named owner for each.

  5. Log a 1:1 and keep the record honest. After a relationship check-in, the client's GD/AD edits the card, sets the "Last 1:1" date and who it was with, and refreshes the context note. Decision: whether direct-contact cadence is healthy, or a contact has quietly gone dark (an old last-1:1 date is the tell).

  6. Retire a stale prospect. When a prospect leaves the client or the relationship is established, the editor clicks Remove — the card is archived with who/when recorded, never hard-deleted. Decision: keep the prospect list an actionable to-do list, not a graveyard.

What users can change here

All writes from the POC Management view land in poc_cards, a table in Signal's own records (entered by users in Signal). Writes are permitted only for the client's Group Director, Account Director (including Senior AD and the Nova executive-sponsor fallback), or an admin — enforced server-side in assertPocEditAllowed (server/index.ts) on every request; the database's row-level security intentionally has no client-side insert/update policy, so the browser cannot write directly.

  • Add details to an existing sentiment-tracked contact (button "Add details"; creates a card with is_prospect = false, linked back to the contact by email, falling back to name): relationship owner (employee email), title override (wins over the call-derived title on screen), LinkedIn URL, reports-to, last 1:1 date and person, free-text context note.

  • Edit any of those fields later (button "Edit"; PATCH /api/poc-management/cards/:id). Clearing a field persists it as empty. The last-1:1 date must be a valid YYYY-MM-DD; anything else is stored as null. Contact and owner emails are lowercased on save.

  • Create a prospect card (button "+ Add POC card"; is_prospect = true): name (required) plus the same fields plus an email — a relationship target with no sentiment data.

  • Remove a prospect (button "Remove"): soft archive — archived_at / archived_by are set and the card disappears from the list; rows are never hard-deleted.

  • Every write is attributed to the verified caller email (created_by / updated_by / archived_by); the server logs blocked attempts. The PATCH is filtered on card id and client id, so a card cannot be edited or moved under a client the caller does not own.

Side effects: none beyond the table itself. Saving a card does not change sentiment scores, churn scores, client lists, or GD/AD assignments, and no other Signal module currently reads poc_cards (as of Jul 2026 it is display-only within POC Management).

Caveats & data quality

  • The "decision maker" flag is stubbed. The backend hardcodes is_decision_maker: false with a TODO awaiting an upstream column (buildPocMap in server/predictions.ts). Decision Influence (the 1–5 score) is live; an explicit decision-maker badge is not shown in POC Management.

  • Card-to-contact matching is by email, falling back to name. If a contact's email or name changes in the upstream call data, a previously saved card silently detaches from its contact (the card is not deleted, but its content stops rendering under that contact). No permanent link exists.

  • All banding and priority thresholds are code constants as of Jul 2026 (e.g. satisfaction High ≥ 7/10, priority High ≥ 1.55) — not data-team-tunable and not configurable per user.

  • The sentiment window is a fixed rolling 5 weeks and depends entirely on the upstream AI call-analysis pipeline. Contacts stop showing data when their calls stop being captured/analyzed; "No sentiment data yet" is common and normal.

  • Upstream lineage and refresh cadence of the sentiment view are not defined in the app repo. The Signal repo only reads the pre-built per-contact scores; which call platform feeds it (Gong is the call-sentiment source labeled elsewhere in Signal's churn model), how contacts are identified, and the rebuild cadence live in the upstream data pipeline. Within Signal, the API layer caches the data for 15 minutes.

  • The AD chip vs. edit rights can disagree. The displayed Account Director comes from the manual AD table with a Nova executive-sponsor fallback; edit rights additionally include Senior Account Directors, whose names are not shown on this screen.

  • The Division filter only appears when the caller's visible book spans more than one division — single-division users will not see it.

  • No automatic prospect graduation. When a prospect starts appearing in call sentiment, the prospect card and the new tracked contact coexist until someone archives the prospect manually.

  • "Last 1:1" is display-only. As of Jul 2026 no digest, alert, or report reads the last-check-in fields.

  • New-ish module. The poc_cards table shipped 2026-06-24; fields and layout are current as of the verification commit but the module is young.

Related views

  • Portfolio Review (/predictions/portfolio) — built on the same cached client base: identical client list, names, divisions, tiers, and GD/AD resolution. A wrong client name or director here will look identical there; fix upstream in Nova / Manage Leads. (The Nova AD background sync fires on the Portfolio endpoint, not the POC endpoint.)

  • Churn Risk (/predictions/churn) — the same per-contact call sentiment appears inside the churn client detail as the POC accordion, and feeds churn's relationship-health signals. POC Management is the management surface; Churn Risk is the risk-scoring surface of the same contacts.

  • Service Expansion (/predictions/se) — the SE client detail reuses the same sentiment banding helpers (pocScoring.ts) when building the Strategic Growth Roadmap AI prompt, so the AI reads the same High/Medium/Low labels a person sees in POC Management.

  • Manage Leads (/leads) — where Account Director / Senior Account Director assignments are made; those assignments drive both the AD chip and the edit permission in POC Management.

  • Client Pulse (/pulse/submit) — POC Management's edit gate reuses Pulse's ownership machinery, so edit rights here always match Pulse submission rights for the same client.

  • Employees / Staffing — being on a client's latest-month team roster (saved via Manage Leads into team_assignments) grants view-only visibility of that client in POC Management.

FAQ

Q: Why can't I see a particular client in POC Management? A: POC Management only lists clients in your book: clients where you are the Group Director, the Account Director (or Senior AD), or on the latest-month team roster saved in Manage Leads. Admins see everything. Separately, the client must be revenue-active (a current-month contract in Vena or recent VABO value) — fully churned or zero-revenue clients are excluded for everyone. If you believe you should see a client, check your team assignment on Manage Leads or ask the client's GD to add you.

Q: Why is everything "View only" for me on a client I work on? A: Viewing and editing are different permissions. Being on the client's team roster grants view-only access. Editing (adding owners, context, prospect cards) is restricted to the client's Group Director, Account Director or Senior Account Director, and admins. The "Editable by you" summary card shows how many of your visible clients you can edit.

Q: Where do the sentiment scores (Satisfaction, Churn Risk, Mood, etc.) come from? A: They are produced by an AI call-analysis pipeline that analyzes recorded client calls, and are rolling averages over the contact's last 5 weeks of analyzed calls. Signal reads the pre-computed per-contact scores and bands them into High/Medium/Low with fixed cutoffs (for example, Satisfaction High means ≥ 7 on a 1–10 scale). Nobody types these scores in, and nothing you do in POC Management changes them.

Q: A contact shows "No sentiment data yet" — is something broken? A: Usually not. It means the contact had no analyzed calls in the rolling 5-week window — either they haven't been on recent recorded calls or the upstream call-analysis pipeline hasn't captured them. It's common and normal; the manual card fields (owner, context, last 1:1) still work for such contacts.

Q: What makes a contact "High priority" in POC Management? A: A computed score combining three ingredients: how negative their recent sentiment is (weighted 50%), their decision influence from calls (25%), and their title seniority — C-suite ranks highest (25%), with a base boost for having any sentiment data at all. Contacts scoring at or above 1.55 get a red "High priority" chip, at or above 1.25 an amber "Medium priority" chip (code constants as of Jul 2026). Plain reading: an unhappy, influential, senior contact rises to the top.

Q: The Account Director shown on the client header is wrong — how do I fix it? A: The AD chip is read-only in POC Management. It shows the manual AD pick made on the Manage Leads screen, falling back to the client's executive sponsor in Nova when no manual pick exists. Fix it on Manage Leads (Team Lead+ access) or ask nova support to correct the executive sponsor in Nova. Note that Senior Account Directors have edit rights in POC Management even though the chip doesn't display them.

Q: If I remove a prospect card, is it deleted forever? A: No. "Remove" is a soft archive — the row stays in Signal's records with who archived it and when; it just disappears from the working list. Nothing in POC Management is ever hard-deleted, and every create/edit/archive is attributed to the signed-in user who did it.

Q: I saved context on a contact and it disappeared — where did it go? A: The most likely cause is a contact identity change upstream: your card links to the contact by email (or name when there's no email). If the call-analysis data later reports the contact under a different email or name, the card detaches and stops rendering under that contact. The data is not lost — it's still stored — but you'd need to re-enter it (or an admin can reconcile the row). Also confirm you were on the same client: cards are per client.

Q: Do the owner, "Last 1:1", or context fields feed any report or alert? A: No. As of Jul 2026, everything entered in POC Management is display-only within this view — no digest, alert, churn model, or other Signal module reads the poc_cards data. It exists so the relationship map is visible and owned, not to trigger automation.

Q: How fresh is the data on this screen? A: Manual card data (owners, context, prospects) is live — re-read every time you select a client and after every save. Sentiment scores and the client/director list are served from server caches of about 15 minutes; the sentiment scores themselves are rolling 5-week averages whose upstream rebuild cadence is defined outside the Signal app (not defined in the app repo). Practically: expect sentiment to reflect calls up to the last data-pipeline run, not this morning's call.

Did this answer your question?