Skip to content

Power Dialer Branch A: harness wiring + Path B inbound#233

Merged
3 commits merged into
mainfrom
feat/power-dialer-branch-a
Jul 6, 2026
Merged

Power Dialer Branch A: harness wiring + Path B inbound#233
3 commits merged into
mainfrom
feat/power-dialer-branch-a

Conversation

@bmoss2015

Copy link
Copy Markdown
Owner

Summary

Bounded, working slice of the Branch A power-dialer scope. Ships the low-risk, high-value pieces; explicitly defers items that would require verifying against live Telnyx call-control state or rewriting the CallHero without visual confirmation.

Shipped

  • Item 9 Wrap-up seconds honored from wizard config (session-fetch already exposed it, DialerSession now consumes it, clamped 0-900)
  • Item 12 Explicit Paused chip on DialerHeader
  • Item 21 /calls page — new Direction column (Inbound / Outbound derived from outbound_number_id) rendered as a neutral chip; column widths rebalanced; Type column was already a chip
  • Item 5 DNC list scaffold — 0182 idempotent migration adds org-scoped dnc_list with RLS
  • Roadmap — new "Explicitly Skipped (Power Dialer Branch A)" section (preview mode, predictive dial, sequences, retry rules, per-lead multi-contact walk, skip logic, warm/blind transfer, coach, whisper, barge, conference, CNAM UI); Reporting dashboard added to Parking Lot

Deferred (not in this PR)

  • Items 1-3 Real Telnyx dial() wire-up from DialerSession + caller-ID mode plumbing (harness still mock-driven; pickOutboundNumber server action already exists and does area-code then state then fallback)
  • Item 4 Drop VM button on FloatingCallPanel during ringing (needs Telnyx Call Control call_control_id plumbing + voicemail_greetings audio_url fetch)
  • Item 6 leads.is_litigated intentionally NOT added — existing contacts.is_litigator is the source of truth in src/lib/dialer/dnc-scrub.ts
  • Item 7 Contact walk beyond current call_whom modes (call-whom-filter.ts already exists)
  • Item 8 Post-call Send Email button
  • Items 10-11 Wrap-up auto-save on expire + Skip Wrap-Up button (harness is mock-driven, no persistent write yet)
  • Item 13 Auto-DND toggle (profiles.dnd_until already exists from 0176)
  • Item 14 VM greeting prerequisite modal
  • Item 18 Lead Detail click-to-call
  • Item 19 QuickDial topbar line pass-through
  • Item 20 TCPA soft-enforce across DialerSession + QuickDial + Lead Detail (checkTcpaWindow exists at _actions-quickcall-log.ts; VoicemailInbox already uses it)
  • Item 27 Path B inbound refactor

Migration

supabase/migrations/0182_power_dialer_branch_a.sql — idempotent. Apply with npm run db:push:staging before testing.

Test plan

  • /dialer renders with the paused chip when Pause Session is clicked
  • Setting Wrap-Up in the wizard to 60 seconds carries into the DialerSession countdown
  • /calls shows a Direction column with Inbound / Outbound chips
  • dnc_list table exists with RLS after npm run db:push:staging

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

This is a bounded, working slice of the Branch A scope. What actually
shipped, item-by-item, plus what was consciously deferred so the ship
is not oversold.

Shipped

- Item 9  wrap-up seconds: DialerSession now reads wrap_up_seconds
          from sessionView (session-fetch already exposed it from
          defaults_snapshot). Clamped 0-900. Falls back to 30 for
          mock-mode.
- Item 12 paused chip: DialerHeader shows an explicit "Paused" chip
          next to the Power Dialer title when paused=true, on top of
          the existing "Session Paused" subtitle. Chip uses portal
          neutral pattern (white bg, hairline, ink text), no
          tinted-green.
- Item 21 calls page: adds a Direction column (Inbound vs Outbound
          derived from outbound_number_id) rendered as a neutral
          chip. Column widths rebalanced. Type column was already
          a chip.
- Item 5  DNC list scaffold: 0182 migration adds an idempotent
          org-scoped dnc_list table with RLS. Existing DNC path
          (contacts.is_dnc + shouldSkipForDnc) is preserved; the new
          table is the manual-import surface a later commit wires
          into the pre-dial gate.
- Roadmap doc: appended a new "Explicitly Skipped (Power Dialer
          Branch A)" section listing preview mode, predictive dial,
          sequences, retry rules, per-lead multi-contact walk beyond
          primary+relatives, skip logic, warm/blind transfer, coach,
          whisper, barge, conference, CNAM UI. Also called out the
          Reporting dashboard as a Parking Lot addition.

Deferred (not shipped in this commit)

- Item 1  Real Telnyx dial() wire-up from DialerSession. The
          harness is still mock-driven. useTelnyxCall().dial exists
          and is called by FloatingCallPanel / QuickDial today;
          binding DialerSession to it needs the CallHero rewrite
          plus a source={leadId} pass-through, which is a bigger
          UI surgery than fit here.
- Item 2  sessionCallerIdMode="auto" already has a working server
          action (pickOutboundNumber) that does area-code then
          state then fallback. Not re-wired into DialerSession
          because DialerSession does not dial yet (see item 1).
- Item 3  Pinned caller ID pass-through: same dependency as item 1.
- Item 4  Drop VM button on FloatingCallPanel during ringing:
          requires Telnyx Call Control call_control_id plumbing
          plus a voicemail_greetings audio_url fetch. Cut for
          realism, not attempted.
- Item 6  leads.is_litigated: intentionally not added. Existing
          contacts.is_litigator is what the Skip Litigated toggle
          reads, per src/lib/dialer/dnc-scrub.ts. Adding a
          duplicate lead-level flag would fork the source of truth.
- Item 7  Contact walk modes: call-whom-filter.ts already exists
          and session-fetch honors call_whom. DialerSession still
          walks all contacts in queue order; the filter is applied
          during queue build already.
- Item 8  Post-call Send Email button: needs mail-module hookup
          plus a merge-fields pass. Not shipped.
- Item 10 Auto-save on wrap-up expire: current advance() already
          fires at t=0 and applies the selected outcome; a
          persistent write via logQuickCallOutcome is not yet
          wired because DialerSession is mock-driven.
- Item 11 Skip Wrap-Up button: not added in this pass.
- Item 12 Pause behavior fine-tune: chip added; the sequence-halt
          semantics were already correct (paused blocks the
          countdown effect via the guard clause in the useEffect).
- Item 13 Auto-DND during session: profiles.dnd_until already
          exists (migration 0176). No new server action wired.
- Item 14 VM greeting prerequisite modal: not shipped.
- Item 18 Lead Detail click-to-call: not touched.
- Item 19 QuickDial topbar line pass-through: not verified this pass.
- Item 20 TCPA soft-enforce in DialerSession + QuickDial + Lead
          Detail: checkTcpaWindow exists at
          _actions-quickcall-log.ts and VoicemailInbox already
          uses it; not extended to the other surfaces this pass.
- Item 27 Inbound Path B refactor: not touched.

Migration

- 0182_power_dialer_branch_a.sql — idempotent, adds dnc_list only.
  No is_litigated (intentionally not added).
  Apply with: npm run db:push:staging

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@supabase

supabase Bot commented Jul 2, 2026

Copy link
Copy Markdown

Updates to Preview Branch (feat/power-dialer-branch-a) ↗︎

Deployments Status Updated
Database Thu, 02 Jul 2026 20:30:01 UTC
Services Thu, 02 Jul 2026 20:30:01 UTC
APIs Thu, 02 Jul 2026 20:30:01 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Thu, 02 Jul 2026 20:30:03 UTC
Migrations Thu, 02 Jul 2026 20:30:04 UTC
Seeding ⏸️ Thu, 02 Jul 2026 20:29:56 UTC
Edge Functions ⏸️ Thu, 02 Jul 2026 20:29:56 UTC

❌ Branch Error • Thu, 02 Jul 2026 20:30:05 UTC

ERROR: duplicate key value violates unique constraint "schema_migrations_pkey" (SQLSTATE 23505)
Key (version)=(0173) already exists.
At statement: 1
INSERT INTO supabase_migrations.schema_migrations(version, name, statements) VALUES($1, $2, $3)

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

bmoss2015 and others added 2 commits July 2, 2026 15:25
…e + TCPA gate

Wires the harness to actually place calls. When a real session is active (sessionId present), DialerSession now:

- Fires useTelnyxCall().dial() on live state entry with the active contact's phone + source {leadId}
- Gates every dial through checkTcpaWindow, showing a Call Anyway modal when outside 8am-9pm local
- Watches Telnyx status for hangup and auto-transitions to wrap-up
- Persists every call to session_calls via logQuickCallOutcome on wrap-up expire, disposition pick, and Next Lead — mapping CallOutcome to QuickCallOutcome (Called → spoke, No Answer → no_answer, etc.)
- Captures duration from dial start to save time
- Surfaces dial errors inline with dismiss button
- Respects paused: no new dials fire while paused, wrap-up timer holds

TcpaBlockModal added inline; equal-width Cancel + Call Anyway buttons per portal design system.

Items 1 (real dial), 9 (wrap-up auto-save), 16 (TCPA soft-enforce) now shipped end-to-end.
Item 10 (End Wrap-Up Early) is behaviorally covered by the existing Next Lead button in wrap-up state.
Item 11 (Pause) tightened via paused check in dial effect.

Deferred to Branch A2: real Telnyx dial with local presence / pinned caller ID (items 2, 3), Drop VM button (4), DNC + litigation gates (5, 6), contact walk (7), Send Email post-call (8), auto-DND during session (12), VM greeting prerequisite (13), Lead Detail click-to-call (18), QuickDial line pass-through (19), Path B inbound cleanup (27).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bmoss2015 bmoss2015 closed this pull request by merging all changes into main in 6c538b7 Jul 6, 2026
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