Data quality — the window's triage board

none of these rows are excluded from any total; flagged loudly beats corrected silently
CheckRowsDetail
Sales with zero handle time9Dina Alonzo 6 · Carlos Chacon 1 · Katerin Pocasangre 1 · Sara Villeda 1
Talk over the 90-min capclean
Wrap over the 30-min capclean
Hold over the 30-min capclean
Review over the 30-min cap31356.4 h clipped from billable
Ring over the 30-min capclean
Unmapped disposition labelsclean
Calls with no agent identity1,5461,530 inbound · 16 outbound · none with talk time · shown as “Unattended (no agent)”
Inbound queue waits over 2h3per-campaign detail on Service & Queues →
Queue time over 2h on outbound rows14a dial should carry no queue time

Row-level detail for every check — dates, agents, Call Ids →

Every check reads the same scoped population as the certified figures, over the selected window. A non-zero row is a question for the parallel run, not an automatic correction — changing how any of these rows count is a written ruling, because six weeks of reported history contains them. The review-cap row is the one to watch: hours over the cap are already excluded from billable by the schema, and this board is where that exclusion stops being invisible.

Ingest health

every file, every reject, with its reason
  • BigQuery pullautoAug 17 20:31 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 20:25 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 20:20 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 20:15 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 20:10 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 20:05 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 20:00 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 19:55 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 19:50 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected
  • BigQuery pullautoAug 17 19:45 CT
    3,226 seen · 0 new · 3,226 already held · 0 rejected

Rejects by reason — all time

  • duplicate16
  • blank_call_id4

20 rows rejected in total, each with a recorded reason — rejected loudly beats dropped silently. The prototype had no reject ledger at all.

The referee

independent recomputation

/api/referee recomputes the five headline totals from raw rows, touching none of the views this app renders from. It exists so a bug in the metric layer cannot hide: the two paths must agree or something is wrong. Gated with a shared key (ruled D5) — ask Daniel for access.

Every rate on every screen is recomputed from summed numerators and denominators, never averaged across rows. Averaging daily sales-per-hour reads 0.149 against the correct 0.186 — a 20% error.

Definitions — the rulebook, verbatim

docs/AAA_CatalyzeCX_Master_Rulebook_v1_9.md · the contract; on any conflict with code, this wins

AAA × CatalyzeCX — Unified Reporting Rule Book (v1.9 · MASTER)

Purpose: single source of truth for the three Claude reporting sessions — Command Center (dashboard / build.py), Daily Slides (analyze.py / build_deck.js), and Performance Review. Every number in all three must follow the rules below.

Data window: 6/29/2026 → last complete day (Central). v1.9 generated 2026-08-04 (supersedes v1.8). This file is the master — sessions may keep their own working copies, but on any conflict this master wins.

Standing duty for all three sessions: treat this document as a living, shared rule book. (1) Whenever a rule, definition, value, or list size changes in any session, update the master in the same pass, notify Janina, and bump the changelog so all three re-sync. (2) Continuously watch for and report data anomalies — during current work and in future runs. Full detail in Section H.


A. Locked decisions (the 7 alignment calls)

1. Productive hours — include Ring

Productive hours = Talk + Wrapup + Hold + In-Review + Ring, summed per call (caps in rule 2), ÷ 3,600,000 (ms → hours). One hours number; labor cost / CPS uses these same hours (no separate "occupied hours").

2. Per-call time caps — Talk 90 min, all others 30 min

Cap each component per call before summing: Talk = 90 min (5,400,000 ms); Wrapup / Hold / In-Review / Ring = 30 min each (1,800,000 ms). Values above the cap are clamped.

3. Sales — count "Sale" (and its aliases), no talk-time gate

Sales = rows where Disposition is Sale, Renewed, or Account Renewed (the last two are aliases of Sale — a closed renewal). No minimum talk time. 259 (thru 7/21) / 269 (thru 7/22). Net Contact keeps its own >30s rule; a Sale always counts as a Net Contact regardless of talk time.

  • Do not confuse with "Already renewed" — that is NOT a sale. It means the customer had already renewed elsewhere; it is an ineligible contact (Section D), never a sale.
  • Alias note: Renewed / Account Renewed have 0 rows in the current 20260722 extract, so sales are unchanged (259/269). The rule is forward-looking — if these aliases appear in a future export they must count as sales. Change needed — Daily Slides & Performance Review: add Renewed and Account Renewed as sale aliases (Command Center already does).

4. Contacts — gross, no talk-time gate

Contacts = any call reaching a person by disposition (eligible + ineligible tiers — see Section D), inbound and outbound. No talk gate. Gross Contacts = ~14,702 (6/29–7/21) / ~15,376 (6/29–7/22). Includes Auto, Invalid number, and Not interested; excludes the recall/callback family. Confirmed against Command Center (15,374) and Daily Slides (15,360), which match within a few calls. (The earlier ~14,215/14,871 figures were wrong — they dropped the trailing-space 'Not interested ' label; see cleaning step 6 and Section G.) Net Contact is the separate talk-gated metric — do not merge the two.

5. Calendar date & day-of-week — US/Central

Convert Created At (epoch ms) → datetime, then take the date and weekday in US/Central. Applies to day bucketing, the window, and the cutoff.

6. Weekends — included; no sparse-day threshold

Keep all days, weekends included. No minimum-dials-per-day rule. Only the trailing incomplete day is dropped (plus stray next-day rows cumulative exports carry).

7. List sizes — from the List Health report (authoritative)

One authoritative Callable-Leads table for all three (drives List Penetration and List Completion):

One authoritative Callable-Leads table (drives List Penetration and List Completion). Cycle = launch month, assigned explicitly (not date-derived).

Cycle 7 (in scope, launched):

Campaign Code Callable Leads Cycle
Salvage ACA00001 5,974 7
Salvage V2 ACA00002 14,430 7
PRX-30 AR Decline ACA00003 7,995 7
PSX-1 DB-1 ACA00004 10,268 7
PRX-15 ACA00006 11,973 7
PRX-45 ACA00007 3,846 7
PSX AR Decline DB ACA00008 6,763 7
PSX-30 ACA00009 5,994 7

Cycle 8 (added 2026-08-03; "Not Received", list_size 0 until lists arrive):

Campaign Code Name Dial window Cycle
Salvage 45-post ACA00010 ACA00010_REC_PSX_Salvage (45 day Post) 7/22–8/23 8
PRX-30 AR Decline ACA00011 ACA_REN_PRX-30_AR Decline 8/4–9/2 8
PSX-1 DB-1 ACA00012 ACA_REN_PSX-1_DB-1 8/6–9/5 8
Salvage 45-post ACA00013 ACA_REC_PSX_Salvage (45 day Post) 8/15–9/28 8
PSX AR Decline ACA00014 ACA_REN_PSX_AR Decline 8/18–9/16 8
PRX-15 ACA00015 ACA_REN_PRX-15 8/18–9/1 8
PRX-45 ACA00016 ACA_REN_PRX-45 8/18–9/16 8

In scope now = all 15 (ACA00001–00004, 00006–00016). ACA00005 (PSX-15 DB) remains "Not Received", out of scope until it has data. ACA00007 and ACA00008 are now in scope (were excluded in v1.6). Cycle-8 campaigns carry list_size 0 so Penetration/Completion correctly show "—" until real lists are entered.

Program → cycle pairing (for cycle-over-cycle comparison): Salvage 45-post = {C7: 00001+00002 combined, C8: 00010+00013 combined}; PRX-30 AR Decline 00003→00011; PSX-1 DB-1 00004→00012; PSX AR Decline 00008→00014; PRX-15 00006→00015; PRX-45 00007→00016; PSX-30 00009→(no C8 yet).

Matching: the engine maps a call to a campaign by finding the ACA##### code anywhere in the Name field (exact → normalized → regex fallback). Because each new campaign's ID is embedded in its name, calls auto-map even when the descriptive wording repeats across cycles (e.g. 00003 and 00011 are both "PRX-30 AR Decline" — the ID keeps them distinct).


B. Shared rules (all three match exactly)

Source & row cleaning (in order)

  1. Use the latest cumulative call-detail CSV. Pass the prior clean file (Customer_Call_Details_20260702.csv) as --prior for de-mislabeling.
  2. Drop the summary/total row (blank Call Id, or Call Id under 10 chars).
  3. Exclude test/pilot agents — remove their rows entirely:
    • cesar.ayala@catalyzecx-sv.com
    • jason.barry+focal@nextiva.com
    • jcarlos.angel@catalyzecx-sv.com
    • sara.hernandez@catalyzecx-sv.com
    • kent.ingram@catalyzecx-sv.com
    • paul.garcia@catalyzecx-sv.com
    • federico.ramirez+focalpoint@nextiva.com (added v1.7)
    • claudia.orozco+focal@nextiva.com (added v1.7)
    • KEEP sara.villeda@catalyzecx-sv.com — a real agent, not excluded. Match logic: an agent is excluded if their address exactly equals, or contains, any string above (lowercased substring match). Federico/Claudia use their +focal/+focalpoint @nextiva.com addresses — the exact strings Janina supplied. Kent Ingram and Paul Garcia have 0 rows in the 20260722 extract, so this exclusion has no effect on current numbers — it's a forward-looking guard. Confirm their exact Agent identifiers so future extracts match reliably.
  4. De-duplicate by Call Id only (keep first). This is the sole dedup key — do not add secondary keys.
  5. Drop rows with an unparseable timestamp.
  6. Normalize disposition text — trim leading/trailing whitespace before any tier matching. The source has labels with trailing spaces (confirmed: 'Voicemail ' and 'Not interested '). Exact-string matching without trimming silently drops those rows — this is what caused Performance Review to undercount contacts and net contacts (see Section G). Strip whitespace on every string field used for matching (Disposition at minimum; ideally Agent and Type too).

Reporting window

Start floor 2026-06-29 (exclude earlier + any Test/Pilot rows). Run through the last complete day (Central); drop the trailing partial day and stray next-day rows.

Units

All duration fields (Talk, Hold, Wrapup, Handle, In-Review, Ring, Queue, Abandon) are milliseconds.

Campaign tagging & de-mislabeling

  • Campaign = first ACA##### pattern from the Name field.
  • De-mislabeling: a REN_PSX_30 / ACA00009 row (Name matches REN_PSX-30, REN_PSX_30, or ACA00009) is real ACA00009 only if (a) Call Id is not in the prior file and (b) date is ≥ 2026-07-02. Otherwise re-tag to ACA00001.
  • Salvage split: any ACA00001 row dated ≥ 2026-07-01 moves to ACA00002.
  • Rescued sale — REMOVED (v1.3). The hard-coded sara.villeda 6/30 sale is absent from the current extract (her sales start 7/2). Do not hard-code it; match the extract. If genuine, fix upstream in the export. All sessions land on 259 / 269 without it.
  • Campaigns in scope (15): ACA00001–00004, 00006–00016 (see Section A.7 for the full list, list sizes, and cycles). ACA00005 out of scope (Not Received).

Call-type scope

  • Dials = outbound only. Inbound never counts as a dial.
  • Contacts, Net Contact, Sales include both inbound and outbound.
  • Disposition "0" / blank = non-call: excluded from contacts, net contacts, sales. Exception: the inbound funnel's "calls received" layer counts them.

C. Metric definitions (identical in all three)

Metric Definition
Dials Count of outbound calls (in-scope campaigns, in window).
Contacts (gross) Calls reaching a person by disposition (eligible + ineligible tiers), inbound + outbound. No talk gate.
Net Contact An eligible-tier call (except "Already renewed") with Talk Time > 30s, OR any Sale.
Sales Disposition == "Sale". No talk-time gate.
Conversion Sales ÷ Net Contact.
Productive hours (Talk + Wrapup + Hold + In-Review + Ring), per-call caps from rule 2, ÷ 3,600,000.
DPH / CPH / SPH Dials / Contacts / Sales ÷ Productive hours.
CPS (Productive hours × $16.75) ÷ Sales.
Contact % Contacts ÷ Dials (can exceed 100% — contacts include inbound).
Net Contact % Net Contact ÷ Contacts.
List Penetration Unique outbound leads dialed (distinct last-10-digit To) ÷ list size, capped 100%.
List Completion Dials ÷ (list size × 6-attempt cap). Cap changed 8→6 on 2026-08-03 (v1.7); completion % rises for every campaign vs the old 8-cap with no change in dialing.

Billed rate: $16.75 per productive hour (CPS), all three.


D. Disposition tiers — FINAL (v1.4, all 25 dispositions classified)

Tier Dispositions Contact? Net Contact eligible?
Eligible Sale (+ aliases Renewed, Account Renewed), Will renew later, Interested / Not Ready, Not interested, Hang up, Decision Maker Unavailable, Lost Connection – Immediate Callback Yes Yes (if Talk > 30s; Sale always)
Ineligible Do not call, Escalation, Wrong number, Deceased, Language barrier, Already renewed, Auto, Invalid number Yes No
Not a contact Voicemail, Answering machines, "0"/blank, Ring / No Answer, Completed, Transferred, Recall Request, Recall No Specific Time, General Callback, Dropped Call/Callback No No

Classification rulings (from Janina):

  • Renewed / Account Renewed → SALE (v1.5). Aliases of the Sale disposition; count as sales and sit in the Eligible tier. Distinct from Already renewed, which is an ineligible contact and never a sale. (0 alias rows in the current extract — forward-looking.)
  • Invalid number → ineligible CONTACT. Counts toward gross Contacts (~2,200 raw rows), never toward Net Contact or sales. Applied in all three.
  • Recall / Callback dispositions → NOT a contact. This covers Recall Request, Recall No Specific Time, General Callback, and Dropped Call/Callback — a promised call-back is not a reached person.
  • Exception — "Lost Connection – Immediate Callback" → ELIGIBLE contact. Despite "Callback" in the name, this one is a contact (a live call that dropped). Do not sweep it into the non-contact callback bucket above. It can become a Net Contact if Talk > 30s.
  • Auto → ineligible contact (system/automated outcome, not a live conversation).

If a new disposition appears that is not in this table, flag it (Section H2) before deciding a tier — do not silently bucket it.


Net-contact outcomes (v1.8): the Dispositions-tab "Net-contact outcomes" view counts each net contact under its canonical disposition name via the alias map — raw variants fold into one outcome. Rule: "Sale" = "Account Renewed" = "Account Renewed (Sale)" — one outcome. Same for all variants (e.g. "Interested/Not Ready" → "Interested not ready"). The only possible outcomes are the 7 eligible-tier dispositions.

Executive three-bucket grouping (v1.8): for summary presentation, net-contact outcomes group as — Positive (Account Renewed (Sale) + Will renew later + Interested not ready), Declined (Not interested), Lost mid-call (Hang up + Lost Connection); Decision maker not available = neutral (shown in the mix, outside the three buckets).

E. Inbound funnel — REDEFINED v1.7 (queue-based)

The funnel now measures service against the in-queue population (callers who genuinely waited), not against everyone who dialed in. This replaces the v1.2 "answered ÷ received" definition.

Column / stage order (funnel flow): Voicemails · Received · Response % · IVR drop · Abandoned · In Queue · Answered · Answer % · Inbound Sales · Conv %

Definitions:

  • Voicemails left = outbound Voicemail dispositions with talk time > 0 (v1.9: zero-talk voicemail rows mean no message was actually left and are excluded from the base).
  • Received (inbound_raw) = all inbound rows (includes disposition 0 / abandoned / IVR).
  • IVR drop = inbound, disposition 0/blank, Abandon Time = 0 (left in the menu, never queued).
  • Abandoned = inbound, Abandon Time > 0 (caller hung up).
  • Quick hang-up = reached queue but < 10 s wait (queue_sub10) — barely entered the queue.
  • In Queue (inbound_queue) = Received − IVR drop − quick hang-ups(<10 s) = callers who reached the queue and genuinely waited (≥ 10 s). Equivalent to "Total Queue Time ≥ 10 s".
  • Answered (q_answered) = reached queue (≥ 10 s) and has a real disposition. This is a strict subset of In Queue. Note: distinct from inbound_answered (any inbound with a disposition, no queue gate), which is broader and must NOT be used as the Answer-% numerator (doing so produced impossible >100% rates).

Rates (all campaign/floor views — identical everywhere):

  • Response % = Received ÷ Voicemails
  • Answer % = Answered (q_answered) ÷ In Queue — how many of the callers who actually waited got answered. Always ≤ 100%.
  • Abandon % = Abandoned ÷ Received
  • Conv % = Inbound Sales ÷ Answered (q_answered) — consistent with the Answered column. Edge case: a sale from a sub-10 s call not in q_answered could rarely push this slightly over 100% on a tiny campaign; acceptable, flag if seen.

Threshold: the "reached queue" / quick-hang-up gate is 10 seconds (queue_min_secs), reused from the existing Abandonment analysis — no separate 30 s gate.

Day inclusion (v1.8): inbound views include a day if it had ≥20 outbound dials or any inbound activity (isInboundDay). Outbound/floor metrics keep the ≥20-outbound-dial gate (isDialDay). Rationale: weekends/partial days with inbound callbacks but light dialing were being dropped from inbound tables, under-counting queue/answered (e.g. ACA00009 137 vs true ~174). The inbound tab may therefore span more days than outbound tabs — by design.

Consistency scope (v1.7): these definitions are applied identically across the Command Center inbound funnel cards, the inbound trend chart, the inbound-by-campaign table, and the inbound-by-campaign-over-time table. Agent-level inbound views intentionally still use inbound_answered — queue fields (In Queue, q_answered, IVR drop) are computed per campaign only, not per agent, because a call that abandoned or dropped at IVR never reached any specific agent. Agent "answered" = what that agent actually handled.

Change needed — Daily Slides: adopt the same queue-based Answer %/In Queue/Conv % definitions for inbound so the deck matches Command Center.


F. Coaching & ranking (Command Center only — documented, not shared)

SPH-coaching flag: agent flagged when SPH < 70% of team-average SPH (team rate = total sales ÷ total hours). Agents with < 20 dials excluded from ranking. Agents below 5 qualifying calls get a low-confidence caution flag. True conversation (Engagement) = talk time ≥ 40s.


F2. Performance goals — NEW v1.7 (Command Center; documented for all)

Monthly floor targets, changed 2026-08-03. The three rate goals are a matched set (SPH and Conversion move together; CPS is derived from SPH).

Goal Value Prior (v1.6 era) Notes
SPH 0.50 0.90 Sales per productive hour.
Conversion 11% 20% Sales ÷ Net Contact. Set as the arithmetic pairing of the 0.50 SPH (0.50 ÷ ~4.5 net-contacts/hr ≈ 11%).
CPS $33.50 $18.61 Derived: $16.75 ÷ SPH goal. Not an independent target — moves with SPH.

Display convention — "% to Goal" (not variance): the Goals tab shows percent to goal, not a raw +/- variance. For higher-is-better metrics %-to-goal = actual ÷ goal; for CPS (lower-is-better) = goal ÷ actual. So 100%+ always means "at or beating target" (green) for every metric, and below 100% is short (red).

Attempt cap = 6 (drives List Completion; see Section C). Changed from 8 on 2026-08-03. campaigns.csv also carries a per-campaign attempt_cap column (some legacy 5/8 values); the global default and all new campaigns use 6.

Goals may vary (v1.9 rule): targets can differ by month, by campaign, or by any other dimension the business defines. The monthly mechanism (effective_from) exists today; per-campaign goals are a requirement for the platform rebuild (see PRD §5).

These goals currently live in Command Center dashboard code, not a reference file — a future enhancement is to move them to reference so they roll monthly without a code edit.


G. Expected numbers after alignment

(Figures below are the v1.6 6-campaign baseline thru 7/22; they predate the Cycle-8 additions and the cap/goal changes. Update on the next full reconciliation run against current live data.)

Metric 6/29–7/21 6/29–7/22
Dials ~49,855 ~52,734
Contacts (gross, incl. Auto + Invalid number + Not interested) ~14,702 ~15,376
Net Contacts ~2,731 ~2,877
Sales 259 269
Productive hours ~1,328 ~1,426

Small dial differences (~30–50 calls) are input/extract noise, not a rule difference.

Reconciliation status (v1.6 — all three checked thru 7/22):

  • Command Center: Dials 52,722 · Sales 269 · Contacts 15,374 · Hours 1,423.9 — matches (within noise). ✅
  • Daily Slides: Dials 52,681 · Sales 269 · Contacts 15,360 · Net 2,876 · Hours 1,423.3 — matches (within noise). ✅
  • Performance Review: Dials 52,710 · Sales 269 · Hours 1,424.7 — match; Contacts 14,864 and Net 2,464 are LOW by ~512 / ~413. Cause: it drops the 'Not interested ' disposition (trailing space) — 505 rows (412 with talk > 30s) in-window. Change needed — Performance Review: apply cleaning step 6 (trim disposition whitespace) so 'Not interested ' is caught; contacts and net contacts will then rise to ~15,376 / ~2,877.
  • History: the old "~12,777" (Command Center/Daily Slides, pre-Invalid-number) and "~14,215/14,871" (a whitespace-buggy recount) are both superseded by the corrected ~14,702 / ~15,376.

H. Standing duties for every session (living document + anomaly reporting)

H1. Keep this master current

  • Any change to a rule, definition, formula, threshold, rate, campaign scope, or list size is written into this master in the same session that makes it — never left as an undocumented tweak in one session.
  • Notify Janina on any change so the other two re-sync. A rule that lives in only one session is a divergence, not an improvement.
  • Log every change in the changelog (date, what, why, sessions affected) and bump the version.
  • Re-read this master before a run so the session works from the latest agreed rules.

H2. Report data anomalies — now and ongoing

Actively watch for and flag (don't silently absorb): numbers that stop reconciling across sessions beyond input noise; new/unexpected dispositions not in Section D, or a sharp shift in disposition mix; new campaigns (ACA00005/07/08 going active) or a list size changing in List Health; corrupt/capped-out timers (frequent 90/30-min clamps, impossible durations); volume cliffs or spikes by day/agent/campaign; sub-30s "Sales" and other likely misdispositions; de-mislabeling drift (REN_PSX_30 count moving, prior-file coverage off); duplicate Call Ids, unparseable timestamps, or missing days in a new extract; test/pilot agents beyond the two known ones.

Rule of thumb: if a number looks surprising, say so in plain language with the figure and the likely cause — don't wait to be asked.

Open anomalies (carried):

  • The 6/30 sara.villeda sale that existed in the 20260702 extract is absent from the current extract — escalate to whoever owns the export to confirm whether it was a real sale.
  • Source data has trailing whitespace in disposition labels ('Voicemail ', 'Not interested '). Handled defensively via cleaning step 6 (trim before matching). Watch for new whitespace/casing variants in future exports; if a disposition's count suddenly drops to near-zero, suspect a label-format change first.

Changelog

Version Date Change Sessions affected
v1 2026-07-24 Initial unified rule book: 7 alignment decisions, Auto = ineligible contact, List Health list sizes, standing duties (Section H). All three
v1.1 2026-07-24 Performance Review aligned: weekends included, ACA00001 5,479→5,974, Auto moved to ineligible. Flagged the missing 6/30 rescued sale. Performance Review; all (window/contacts note)
v1.2 2026-07-24 Inbound "Answered" = disposition alone (no ≥10s queue gate); Command Center rebuilt to match. Command Center; Daily Slides
v1.3 2026-07-24 Rescued-sale rule removed (all land on 259/269). Contacts-tier work began — but the three diverged: Invalid number counted by Performance Review + Command Center, rejected by Daily Slides; Contacts figures split ~14,215 vs ~12,777. All three (partial / conflicting)
v1.4 2026-07-24 MASTER reconciliation. Full 25-disposition tier table finalized (Section D). Invalid number = ineligible contact (locked, all three). Recall Request / Recall No Specific Time / General Callback / Dropped Call/Callback = not a contact. Lost Connection – Immediate Callback = eligible contact (explicit exception to the callback rule). Gross Contacts corrected to ~14,215 / ~14,871 via independent recount — supersedes the stale ~12,777. Changelog and version unified across the three copies. All three
v1.5 2026-07-24 Renewed + Account Renewed = sales (aliases of Sale; distinct from the ineligible "Already renewed"). Kent Ingram and Paul Garcia added as excluded test/pilot agents; sara.villeda explicitly kept. Dedup confirmed = Call Id only (no change). Both agent- and alias-rules have 0 rows in the current extract, so numbers are unchanged — forward-looking guards. Change needed — Daily Slides & Performance Review: add the two sale aliases and the two agent exclusions (Command Center already has them). All three
v1.9 2026-08-04 Post-review refinements (Janina's plain-English read-through). (1) Voicemails counted only with talk time > 0 — zero-talk VM rows (1%) excluded from the Response-rate base at BOTH counting sites. (2) Rule added: goals may vary by campaign / month / any dimension. (3) Time-cap clarification: over-cap time is counted at the cap (talk 90 min, others 30), never discarded; time above caps is now measured and shown on Data Quality split into plausibly-real (cap–2h) vs timer glitches (>2h) with billed-$ equivalent. On data thru 7/09 in-scope: 6.4 plausible hours ($107) vs 127 glitch hours — caps protect the numbers rather than forgo billing. Change needed — Daily Slides & Performance Review: adopt the VM talk-gate. All three
v1.8 2026-08-04 Process + inbound-day fixes. (1) Inbound views use isInboundDay (≥20 outbound dials OR any inbound) — outbound keeps isDialDay; recovers inbound on weekends/partial days (Section E). (2) Inbound funnel + by-campaign table + trend now all aggregate from the same per-campaign source and the full queue field set (two display-aggregation bugs fixed). (3) Goals moved to reference/goals.csv (sph 0.50 / conversion 0.11 / cps 33.50, effective 2026-08-01); dashboard reads DATA.goals; CPS independently settable (blank = derived $16.75÷SPH); goal-month label dynamic. (4) Server boot-time rebuild: startup reprocesses the archived CSV with the current engine. (5) Footer shows data-refreshed timestamp + data-thru date (replaces filter-scoped call count). (6b) Net-contact outcome folding: outcomes keyed by canonical disposition via alias map; Sale = Account Renewed (one outcome). Change needed — Daily Slides & Performance Review: adopt the inbound day-inclusion rule and read goals from reference/goals.csv (do NOT hardcode). All three
v1.7 2026-08-03 Major session update. (1) Attempt cap 8→6 — List Completion denominator (Section C); completion % rises floor-wide. (2) 7 new Cycle-8 campaigns ACA00010–00016 added (Section A.7), status "Not Received", size 0; ACA00007/00008 now in scope; total 15. (3) Cycle concept = launch month (Cycle 7 = 00001–00009, Cycle 8 = 00010–00016), assigned explicitly; program→cycle pairing for the new Cycle-Compare view. (4) Two more excluded agents — Federico Ramirez (+focalpoint@nextiva.com), Claudia Orozco (+focal@nextiva.com). (5) Goals changed (new Section F2): SPH 0.90→0.50, Conversion 20%→11%, CPS→$33.50 (derived); Goals tab now shows "% to Goal". (6) Inbound funnel redefined (Section E): In Queue = Received − IVR drop − quick hang-ups(<10s); Answer % = queue-answered ÷ In Queue; Conv % = sales ÷ queue-answered; applied consistently across all campaign/floor inbound views; agent-level unchanged. Change needed — Daily Slides & Performance Review: attempt cap 6, new campaigns/cycles, the two agent exclusions, goals, and (Daily Slides) the queue-based inbound definitions. All three
v1.6 2026-07-24 Whitespace fix + contacts correction. Added cleaning step 6: trim disposition whitespace before tier matching — the source has 'Voicemail ' and 'Not interested ' with trailing spaces. Corrected gross Contacts to ~14,702 (7/21) / ~15,376 (7/22) and added Net Contacts (~2,731 / ~2,877); the prior ~14,215/14,871 were undercounts from the same whitespace bug. All three reconciled thru 7/22: Command Center ✅ and Daily Slides ✅ match; Performance Review is LOW on Contacts (14,864) and Net (2,464) because it drops 'Not interested '. Change needed — Performance Review: trim disposition whitespace (step 6). Performance Review (apply trim); all three (corrected expected numbers)