Division Forecast is a read-only dashboard in Signal (Power Digital's internal BI web app) at route /predictions/retention, visible to Team Leads and above (any elevated role — base-tier Members are redirected away). It mirrors the Client Success (CSM) team's 2026 client renewal tracker — a Google Sheet where account leaders declare, contract by contract and month by month, whether each client will renew, fully churn, downchurn, end a project, or was saved — and answers the question: "How much revenue do the account teams themselves expect to lose (or have saved) this month, quarter, or year, and in which divisions and accounts?" Every number on the page originates in that CSM renewal tracker Google Sheet; Signal writes nothing back.
Field | Value |
Route | /predictions/retention |
Access | Team Lead+ (any elevated role passes; base-tier Members are redirected to /summary) |
Nav section | Client Health → "Division Forecast" |
Primary data sources | CSM renewal tracker Google Sheet (mirrored view FINAL_CLIENT_RETENTION_FORECASTING_2026); Nova platform roster (access gating only, no on-screen data) |
Writes | None — fully read-only |
Key code refs | src/views/RetentionForecastView.tsx; src/App.tsx (route ~line 1169, nav ~line 417, guard MemberAllowedRoute ~line 825); src/services/api.ts (getRetentionForecast, ~line 1425); server/index.ts (GET /api/retention-forecast, ~line 7658) |
Last verified | staging @ 98df0c4, verified 2026-07-07 |
Purpose
Division Forecast exists so leadership can see the human-declared renewal outlook inside Signal instead of digging through the Client Success team's raw renewal tracker spreadsheet. Power Digital's Client Success team maintains a 2026 renewal tracker (a Google Sheet) where account leaders log each contract-month with a churn status: "Full Churn" (losing the client), "Downchurn" (client shrinking), "Project Ending", "Saved" (was at risk, rescued), or "No Churn". Division Forecast pulls that tracker into Signal and rolls it up so leaders can answer:
How much revenue is covered by the renewal tracker this month/quarter/year, and how much of it do the account teams forecast we will lose?
Which divisions are losing the most, and which are saving the most?
Which specific accounts are confirmed churn, and which Account Director owns each one?
How does forecasted churn trend month over month across 2026?
Division Forecast is deliberately the human-judgment counterpart to Signal's ML-driven Churn Risk module (/predictions/churn): Churn Risk shows what a model predicts might happen; Division Forecast shows what account teams have declared is happening in the renewal pipeline.
Access & visibility
Route gate: The /predictions/retention route in src/App.tsx is wrapped in MemberAllowedRoute. This guard redirects base-tier "Members" (a signed-in user with no elevated role) to /summary. Anyone with any elevated flag passes: Team Lead, Admin, Gandalf, Sauron (super-admin), and — since the July 2026 Growth access restructure — users holding Growth capabilities (Growth People viewer, Performance Radar viewer, or Growth access manager) are also not "Members" and can therefore reach this route.
Nav placement: Left nav → Client Health section → "Division Forecast" link. The Client Health section has no section-level role gate; base Members never see it because the nav strips Members down to exactly Summary and Employees.
How the Team Lead flag is granted: Roles live in Signal's own records (the app_users table, managed inside Signal). On every sign-in, the backend endpoint POST /api/auth/ensure-provisioned (server/index.ts) creates the user's app_users row if missing and auto-sets is_team_lead = true when the user's email appears as an executive_sponsor or group_director on any active client in the Nova platform's roster. The flag is never auto-downgraded. Admin/Gandalf flags are granted manually by Signal admins via the Access → General Access page.
Server-side note: The backend endpoint GET /api/retention-forecast has no authentication middleware as of staging commit 98df0c4 — the Team Lead+ restriction on Division Forecast is enforced by the frontend route guard only.
Data sources & lineage
Everything on all six tabs of Division Forecast is served by one API call made when the page loads: api.getRetentionForecast() → GET /api/retention-forecast. Every widget is a client-side slice/aggregation of that single dataset; the view makes no other network calls.
On-screen element | Origin system | Code path | Refresh | Caveat |
All six tabs (summary cards, status breakdown, division pivot, confirmed churn, saved accounts, account detail, annual rollup) | CSM renewal tracker Google Sheet (maintained by the Client Success team; mirrored into the view NOVAX_CUSTOMER_MANAGEMENT.PROD_MODEL.FINAL_CLIENT_RETENTION_FORECASTING_2026) | src/views/RetentionForecastView.tsx → src/services/api.ts getRetentionForecast() → server/index.ts GET /api/retention-forecast (~line 7658) | Server caches responses for 15 minutes (code constant as of Jul 2026). Upstream sheet-to-mirror pipeline cadence is not defined in the app repo. | Sheet edits appear in Signal only after the sheet→mirror pipeline runs plus up to 15 minutes of API cache. |
Period dropdown (available months) | Same CSM renewal tracker sheet | Second query in the same endpoint: SELECT DISTINCT MONTH_YEAR from the same mirrored view | Same 15-minute cache | Months listed = months actually populated in the tracker. |
"Revenue at Risk" | CSM sheet CURRENT_RETAINER column | Client-side sum in RetentionForecastView.tsx (aggregateAccounts) | Same | Sums the retainer of all tracked contract-months in the slice, including "No Churn" rows — it means "revenue covered by the tracker", not "revenue in danger". |
"Forecasted Churn" | CSM sheet formula column FORECASTED_CHURN_AMOUNT_FORMULA | Client-side sum | Same | The formula lives in the sheet, not in Signal. Signal trusts the sheet's number and does not recompute it. |
"Saved Revenue" | CSM sheet CHURN_STATUS + CURRENT_RETAINER columns | Client-side: retainer of rows with status "Saved" | Same | — |
"Amount Retaining" | CSM sheet CHURN_STATUS + CURRENT_RETAINER columns | Client-side: retainer of rows whose status is neither "Full Churn" nor "Downchurn" | Same | "Project Ending", "Saved", "No Churn", and blank statuses all count as retaining. |
"Forecast Churn Rate" | Derived (Forecasted Churn ÷ Revenue at Risk) | Client-side fmtPct | Same | Shows "—" when the denominator is zero or negative. |
Churn Status / Worst Status | CSM sheet CHURN_STATUS column | Client-side normalization + priority ranking (normalizeStatus, worstStatus) | Same | One known dirty row ("Project " with trailing space) is silently normalized to "Project Ending". Multi-month slices show the worst status (Full Churn > Downchurn > Project Ending > Saved > No Churn). |
Renewal Stage, Account Director, Contract, Division columns | CSM sheet columns (RENEWAL_PLANNING_STAGE, ACCOUNT_DIRECTOR, CONTRACT_NAME, DIVISION) | Passed through from the endpoint | Same | Names and divisions are whatever the CSM sheet says — not reconciled against Signal's team assignments or HR data, so ownership shown here can drift from Manage Leads / Staffing. |
(Fetched but not displayed) SHEET_CLIENT_NAME, FULL_RENEWAL_CONFIDENCE_WITH_NO_DOWNCHURN, GROUP_DIRECTOR, AR, CONTRACT_TERMS, NOTES, RETENTION_SCORE | Same CSM sheet | Returned by the endpoint, unused by the view (except GROUP_DIRECTOR, aggregated but not rendered) | Same | Invisible today; plausible future columns. |
Not used by Division Forecast: Signal's own records (Supabase), the Deel payroll integration, the hiring-pipeline Google Sheet, Vena contract/finance tables, and the ML prediction engine (server/predictions.ts) play no role in what this view displays.
Metrics & definitions
All metrics on Division Forecast are computed client-side in src/views/RetentionForecastView.tsx from rows of the CSM renewal tracker Google Sheet (one row = one client contract in one month). Rows are first grouped into "accounts" by the key client + division + contract; a slice is the selected period (month/quarter/year) optionally narrowed by division and account search.
Metric | Plain definition | Basis / formula | Origin |
Revenue at Risk | Total monthly retainer of every contract tracked in the slice | Sum of CURRENT_RETAINER across all rows in the slice (all statuses, including "No Churn") | CSM sheet retainer column |
Forecasted Churn | Dollars the account teams forecast will be lost | Sum of FORECASTED_CHURN_AMOUNT_FORMULA — a formula column maintained inside the CSM sheet; its exact logic is not defined in the app repo | CSM sheet formula column |
Saved Revenue | Retainer of contract-months marked "Saved" (at risk, then rescued) | Sum of CURRENT_RETAINER where normalized CHURN_STATUS = "Saved" | CSM sheet status column |
Forecast Churn Rate | Share of tracked revenue expected to be lost | Forecasted Churn ÷ Revenue at Risk; "—" when denominator ≤ 0 | Derived |
Confirmed Accounts | Count of accounts whose worst status in the slice is "Full Churn" | Account-level worst-status ranking (Full Churn > Downchurn > Project Ending > Saved > No Churn — code constant as of Jul 2026) | CSM sheet status column |
Saved Accounts | Count of accounts whose worst status in the slice is "Saved" | Same worst-status ranking | CSM sheet status column |
Amount Retaining (Account detail column) | Retainer expected to stay | Sum of CURRENT_RETAINER for rows whose status is not "Full Churn" and not "Downchurn" (blank status counts as retaining) | CSM sheet status + retainer columns |
Churn Status / Worst Status | The account's declared renewal outcome | Latest single-month status, or the worst status across the period for quarter/year granularity; "Project " (trailing space, one known dirty row) is normalized to "Project Ending" | CSM sheet status column |
Renewal Stage | Where the renewal conversation stands | RENEWAL_PLANNING_STAGE, shown verbatim (latest month's value for multi-month slices); the stage vocabulary is a CSM-process convention not defined in the app repo | CSM sheet stage column |
Accounts (counts in pivot/rollup tables) | Number of client + division + contract combinations in the slice | Distinct grouping key; the same client can appear in multiple months on different contracts, so counts are not deduplicated across months in the Annual rollup | Derived |
How it's used
Monthly churn forecast review (division leader). On Division Forecast, set Granularity = Month, pick the current month, open the Monthly summary tab. Read Forecasted Churn and Forecast Churn Rate; scan the Status breakdown table to see whether risk is concentrated in "Full Churn" (lost) or "Downchurn" (shrinking). Decision: where to focus save efforts this month and what number to report upward.
Cross-division accountability (executive / QBR). Set Granularity = Quarter, open the Division pivot tab, sort by Forecasted Churn. Compare churn rates and Saved counts across divisions side by side (this tab deliberately ignores the Division filter so divisions stay comparable). Decision: which division leaders need a retention deep-dive.
"Which accounts are we actually losing?" (Group Director). Filter to your division, open the Confirmed churn tab. Each row shows the contract, dollars, renewal stage, and owning Account Director. Decision: escalate specific accounts, verify the tracker is current, or accept the loss and plan backfill pipeline.
Celebrate and study saves (Client Success leadership). Open the Saved accounts tab for a period. Saved Revenue = the value the save motion protected. If the period has no saves, the empty state reports how many saved accounts exist across other 2026 months and offers a one-click jump to the Annual rollup tab.
Track the year's trajectory (leadership reporting). Open the Annual rollup tab: six summary cards across all tracked months plus a month-over-month table showing whether forecasted churn is accelerating or improving through 2026. Decision: adjust retention targets or staffing for renewal-heavy months.
Spot-check a single client (Account Director / Team Lead). Type the client or contract name in the Account search box, open the Account detail tab. Verify status, renewal stage, and forecasted churn match reality. If wrong, the correction must be made upstream in the CSM renewal tracker Google Sheet — Division Forecast cannot be edited.
What users can change here
Nothing — Division Forecast is read-only. There is no edit control, no write endpoint, and no interaction with Signal's own records (Supabase) from this view. To change any status, retainer, forecast amount, or owner shown on Division Forecast, the change must be made in the CSM renewal tracker Google Sheet; it then flows into the mirrored view (FINAL_CLIENT_RETENTION_FORECASTING_2026) via a data pipeline that lives outside the Signal repo, and appears on screen after the server's 15-minute API cache expires.
Caveats & data quality
"Revenue at Risk" is a loose label. On Division Forecast it is the total retainer of all tracked contract-months in the slice — including "No Churn" accounts — not only endangered revenue. Read it as "revenue covered by the renewal tracker in this slice."
Freshness is double-buffered. CSM sheet → mirrored view pipeline (cadence and ownership not defined in the app repo) plus a 15-minute server-side cache (code constant as of Jul 2026, server/index.ts). "I just fixed the sheet, why hasn't Signal updated?" is expected behavior.
Hardcoded to 2026. The mirrored view name ends in _2026, and the Saved-tab empty state literally says "across other months in 2026". Rolling into 2027 will require code and/or data changes; no 2027 plan is defined in the app repo.
Forecasted Churn formula is opaque to Signal. FORECASTED_CHURN_AMOUNT_FORMULA is computed inside the CSM sheet; how it weights status, renewal confidence, and retainer is not defined in the app repo.
Ownership can drift. Account Director, Group Director, division, and client names come verbatim from the CSM sheet and are not reconciled against Signal's team assignments (Signal's own records) or HR data — so the owner shown here may differ from what Signal's Manage Leads or Staffing views show.
Only as clean as the sheet. The code silently normalizes one known dirty status value ("Project " with trailing space → "Project Ending"); other data-entry inconsistencies in the sheet pass straight through. Rows with a blank status count as "retaining" and appear in the Status breakdown as "Unknown".
Account counts are not deduplicated across months. The same client can appear in multiple months on different contracts; the Annual rollup's month-over-month table shows a caption reminding viewers of this.
Status priority and colors are code constants (as of Jul 2026): worst-status ranking Full Churn > Downchurn > Project Ending > Saved > No Churn; colors red / amber / green are hardcoded in RetentionForecastView.tsx.
Frontend-only access gate. The Team Lead+ restriction is a frontend route guard; the backend GET /api/retention-forecast endpoint carries no authentication middleware as of staging commit 98df0c4.
Naming inconsistency. The nav label is "Division Forecast", the route is /predictions/retention, and the code calls the component "RetentionForecastView" — all three refer to the same module.
Tracker maintenance process is undocumented in code. Which role keeps statuses current, on what cadence, and the operational bar for marking an account "Saved" vs "No Churn" are CSM-process conventions not defined in the app repo.
Related views
Churn Risk (/predictions/churn) — sibling link in the same Client Health nav section. Churn Risk shows model-predicted churn scores produced weekly by the AI/ML team's churn model pipeline outside the Signal repo (Signal passes the scores through — it does not recompute them); Division Forecast shows human-declared renewal outcomes from the CSM tracker. They share no data or code path — a discrepancy between them (model says risky, tracker says No Churn) is itself a useful signal.
Portfolio Review (/predictions/portfolio), POC Management (/predictions/poc-management), Client Profitability (/profitability, admin-only), Service Expansion (/predictions/se) — the other Client Health nav siblings; no data dependency with Division Forecast in either direction.
Nothing consumes Division Forecast's data. The /api/retention-forecast endpoint has exactly one consumer (this view). A separate admin-facing schema-discovery endpoint (/api/predictions/history/schema/CLIENT_RETENTION_FORECASTING_2026) can list the mirrored view's columns but powers no user-facing screen.
FAQ
Q: Why doesn't the "Revenue at Risk" number on Division Forecast match Vena or the Revenue view? A: "Revenue at Risk" on Division Forecast is the sum of retainers for every contract-month present in the CSM renewal tracker Google Sheet for the selected slice — including accounts marked "No Churn". It is scoped to what the CSM team tracks in the sheet, not to Signal's contracted-revenue (Vena) data, and the two are never reconciled. Treat it as "revenue covered by the renewal tracker", not total company revenue.
Q: I updated the renewal tracker sheet — why doesn't Division Forecast show my change? A: Two delays stack: (1) the Google Sheet is mirrored into a data view by a pipeline outside Signal whose cadence is not defined in the Signal repo, and (2) Signal's backend caches the result for 15 minutes. Expect your edit to appear only after both have passed. If it still doesn't show after a few hours, the sheet-to-mirror pipeline is the place to investigate (data engineering owns it, not the Signal app).
Q: How is "Forecasted Churn" calculated? A: Signal does not calculate it. Forecasted Churn is the sum of a formula column (FORECASTED_CHURN_AMOUNT_FORMULA) maintained inside the CSM renewal tracker Google Sheet. The formula's logic — how it weights churn status, renewal confidence, and retainer — lives in the sheet and is not defined in the Signal repo. Questions about the formula go to the Client Success team that owns the tracker.
Q: Who can see Division Forecast? A: Anyone with an elevated role in Signal: Team Lead, Admin, Gandalf, Sauron, or a Growth capability (Growth People viewer, Performance Radar viewer, or Growth access manager). Base-tier Members — signed-in users with no elevated role — are redirected to the Summary page. Team Lead is auto-granted at sign-in to anyone listed as an executive sponsor or group director on an active client in Nova's roster; Admin/Gandalf are granted manually via Access → General Access.
Q: Can I edit a churn status or forecast amount in Division Forecast? A: No. Division Forecast is entirely read-only. All corrections must be made in the CSM renewal tracker Google Sheet, which is the single source for everything on this page. The change then flows into Signal automatically (pipeline + up-to-15-minute cache).
Q: Why does the Division pivot tab show all divisions even though I filtered to one division? A: Intentional. The Division pivot tab ignores the Division filter so divisions always remain comparable side by side. The Monthly summary, Confirmed churn, Saved accounts, Account detail, and Annual rollup tabs all respect the Division filter.
Q: What does "Confirmed Accounts" mean on the summary cards? A: The count of accounts (client + division + contract combinations) whose worst churn status in the selected period is "Full Churn" — i.e., the account team has declared the client is fully churning. When the period spans multiple months (quarter/year granularity), the worst status across those months is used, ranked Full Churn > Downchurn > Project Ending > Saved > No Churn.
Q: What's the difference between Division Forecast and Churn Risk? A: Churn Risk (/predictions/churn) shows machine-learning churn scores produced weekly by the AI/ML team's churn model outside of Signal — Signal passes the scores through and does not recompute them. Division Forecast (/predictions/retention) shows what the account teams have manually declared in the CSM renewal tracker. They share no data. If the model flags a client as risky but the tracker says "No Churn" (or vice versa), that mismatch is worth a conversation with the account team.
Q: Why does the Account Director shown on Division Forecast differ from the lead shown in Manage Leads or Staffing? A: Division Forecast displays the Account Director exactly as typed in the CSM renewal tracker Google Sheet. Signal's Manage Leads / Staffing views use Signal's own team-assignment records (entered by users in Signal). The two are never reconciled, so they can drift. The renewal tracker sheet is the one to fix if Division Forecast shows a stale owner.
Q: Why do account counts in the Annual rollup look inflated? A: The month-over-month table counts accounts per month, and the same client can appear in multiple months on different contracts — counts are not deduplicated across months. The on-screen caption on the Annual rollup tab states this. The six annual summary cards at the top, by contrast, aggregate each client + division + contract combination once across the whole year.
