# Lead Verification Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: superpowers:subagent-driven-development. Steps use checkbox (`- [ ]`). Follow the execution protocol (`2026-05-29-execution-protocol.md`) — sequential on shared files, parallel only where lanes are disjoint. **Goal:** Add a **pre-pipeline Lead Verification stage** — a verification-team queue (assign → work → verify/unverify) that, on verify, pushes a real New Lead into our existing `leads` pipeline. Adapted port from `gitea/bugfix/project-refinement` (commits `567b29c`, `8a4d577`), re-authored against our canonical data. **Architecture:** New `leadVerifications` data + 6 mutators in `mockStore.jsx` (verify writes into our enriched `leads` array); a reusable portaled `ui/Select`; the ported `LeadVerification/` component set + page; a unified `/lead-verification` route + sidebar nav. Components reuse our existing `useMockStore`/`usePermissions`/`SpotlightCard`/framer-motion/lucide — so the port is mostly verbatim; the real work is grounding the data and wiring. **Tech Stack:** React 18, Vite 7, mock React-context store, framer-motion, lucide-react, pnpm. No test harness → verify via `npm run build` + grep + dev-run. **Spec:** `docs/superpowers/specs/2026-05-29-lead-verification-design.md`. **Source branch:** `gitea/bugfix/project-refinement` (already fetched; pull source files with `git show gitea/bugfix/project-refinement:`). --- ## File structure | File | Responsibility | New/Mod | |------|----------------|---------| | `src/data/mockStore.jsx` | `MOCK_LEAD_VERIFICATIONS` (15 grounded records) + `leadVerifications` state + 6 mutators (verify → `leads`) | Modify | | `src/components/ui/Select.jsx` | Reusable portaled dark-mode-aware dropdown | Create | | `src/components/LeadVerification/statusConfig.js` | Status → visuals/icons map | Create | | `src/components/LeadVerification/{SummaryCards,LeadTableRow,LeadCard,LeadStatusBadge,LeadActionsMenu,AssignLeadModal,LeadDetailsModal}.jsx` | Table/cards/badges/menus/modals | Create | | `src/pages/LeadVerification/LeadVerificationPage.jsx` | The page: summary tiles + filters + table/cards + modals | Create | | `src/App.jsx` | `/lead-verification` route | Modify | | `src/components/Layout.jsx` | sidebar nav entry | Modify | ## Lane / ownership map | Task | Lane (exclusive files) | Phase | |------|------------------------|-------| | T1 Data + mutators | `src/data/mockStore.jsx` | A | | T2 ui/Select | new `src/components/ui/Select.jsx` | A (parallel — disjoint) | | T3 Components + page | new `src/components/LeadVerification/*` + `src/pages/LeadVerification/LeadVerificationPage.jsx` | B (after T1+T2) | | T4 Route + nav | `src/App.jsx`, `src/components/Layout.jsx` | C (after T3) | | T5 Verify | (read-only) | D | **T1 and T2 are disjoint → parallel.** T3 imports both (store mutators + Select). T4 imports the page. T5 last. --- ## Task 1: Lead-verification data + mutators **Files:** `src/data/mockStore.jsx` only. The source has `MOCK_LEAD_VERIFICATIONS` + `assignLeadVerification`/`reassignLeadVerification`/`setLeadVerificationStatus`/`verifyLead`/`unverifyLead`/`addLeadVerificationNote`. **Read the source for the mutator logic** (`git show gitea/bugfix/project-refinement:src/data/mockStore.jsx` — search `leadVerifications`/`verifyLead` ~lines 6700-6810), but **re-author the DATA** to our grounded standards and **adapt `verifyLead` to OUR `leads` schema**. - [ ] **Step 1 — record shape + 15 grounded records.** Add `const MOCK_LEAD_VERIFICATIONS = [ ... ]` near the other mock arrays. Each record: ```js { id: 'lv_001', leadId: 'LD-V-001', customerName: '', phone: '', email: '', address: ', Plano, TX ', source: '', status: '', verificationStatus: '', assigneeId: '', assigneeName: '', urgency: '', createdAt: '', assignedAt: '', verifiedAt: '', verificationNotes: '', history: [{ at: '', by: '', action: '' }], } ``` Grounding (per spec): verifiers = canonical admins **a1 Wade Hollis / a2 Darlene Brooks / a3 Roy Schaefer**; customers = realistic varied Plano homeowners (NO placeholders/movie names/sequential fakes); phones varied DFW (972/469/214/945), en-US; real Plano addresses+zips; status ↔ verificationStatus internally consistent (Verified↔Verified; In Progress↔a working state; Unassigned↔no assignee); dates `createdAt ≤ assignedAt ≤ verifiedAt ≤ 2026-05-29`. Spread across states: ~2 Verified, ~2 Unverified/Failed Contact, several Assigned/In Progress, a few Pending/Unassigned, 1 `Emergency — Awaiting Verifier`. - [ ] **Step 2 — state + mutators.** Add `const [leadVerifications, setLeadVerifications] = useState(MOCK_LEAD_VERIFICATIONS);`. Port the 6 mutators (adapt names/logic from source): - `assignLeadVerification(id, assigneeId, assigneeName)` → status `Assigned`, verificationStatus `Pending Outreach` (if was Unassigned), set assignee + `assignedAt`, append history. - `reassignLeadVerification(id, assigneeId, assigneeName)` → swap assignee, append history. - `setLeadVerificationStatus(id, newStatus, note)` → set `status` (+ derive a sensible `verificationStatus`), append history with note. - `verifyLead(id)` → set `status:'Verified'`, `verificationStatus:'Verified'`, `verifiedAt`, append history `"Verified and pushed to New Leads"`, AND **push a New Lead onto `leads`** matching OUR lead schema (read `seedLeadsFromAttribution()` for the exact shape — `{ id:'lead_'+Date.now(), createdAt, status:'New', firstName, lastName, address, city:'Plano', state:'TX', zip, urgency, leadSource, phones:[{number,type:'Mobile',isPrimary:true}], emails:[{email,isPrimary:true}], createdByName:'Lead Verification', verificationId:id }`). Derive firstName/lastName by splitting `customerName`. - `unverifyLead(id, note)` → `status:'Unverified'`, append history. - `addLeadVerificationNote(id, note)` → append to `history`. - [ ] **Step 3 — expose** `leadVerifications` + the 6 mutators on the context `value` object (object-shorthand, matching the existing pattern). - [ ] **Step 4 (verify):** `npm run build` → `✓ built`, 0 duplicate-key warnings. `git grep -c "verificationStatus:" -- src/data/mockStore.jsx` ≥ 15. `git grep -nE "\(972\) 555-0[0-9]{3}"` shows none introduced. Spot-check 3 records: status↔verificationStatus consistent, assignees are real admins. - [ ] **Step 5:** commit `git commit -am "feat(data): lead-verification queue + mutators (verify pushes a grounded New Lead into the pipeline)"`. ## Task 2: Reusable `ui/Select` **Files:** Create `src/components/ui/Select.jsx`. **Parallel with T1.** - [ ] **Step 1:** Create the file with the source content verbatim (it's framework-only — React + framer-motion + lucide, no app deps): `git show gitea/bugfix/project-refinement:src/components/ui/Select.jsx` → write it to `src/components/ui/Select.jsx`. It's a portaled dropdown (props: `value, onChange, options:[{value,label}]|string[], placeholder, id, ariaLabel, className`) that renders correctly in dark mode. - [ ] **Step 2 (verify):** `npm run build` → `✓ built` (it's unused until T3, so the bundler tree-shakes it — that's fine; the build just confirms it parses). `node -e "..."` not needed. - [ ] **Step 3:** commit `git commit -am "feat(ui): add reusable portaled dark-mode-aware Select component"` (after `git add src/components/ui/Select.jsx`). ## Task 3: LeadVerification components + page **Files:** Create `src/components/LeadVerification/{statusConfig.js, SummaryCards.jsx, LeadStatusBadge.jsx, LeadActionsMenu.jsx, LeadTableRow.jsx, LeadCard.jsx, AssignLeadModal.jsx, LeadDetailsModal.jsx}` and `src/pages/LeadVerification/LeadVerificationPage.jsx`. **After T1 + T2.** - [ ] **Step 1:** For EACH file, pull the source with `git show gitea/bugfix/project-refinement:` and create it in our tree. The imports already match our codebase (`../../data/mockStore`, `../../hooks/usePermissions`, `../../components/SpotlightCard`, `../ui/Select`, framer-motion, lucide) — keep them. - [ ] **Step 2:** Verify the page/components reference the SAME store keys T1 exposed: `leadVerifications`, `assignLeadVerification`, `reassignLeadVerification`, `setLeadVerificationStatus`, `verifyLead`, `unverifyLead`, `addLeadVerificationNote`. If any source name differs from T1, reconcile to T1's names (T1 is the source of truth). - [ ] **Step 3:** The `AssignLeadModal` lists assignees — point it at our canonical admins (a1/a2/a3) from the store (`users`/`personnel` filtered to ADMIN), not any hardcoded source list. The source-filter options derive from the records' `source` values; the assignee-filter from `assigneeName`. - [ ] **Step 4 (verify):** `npm run build` → `✓ built`, 0 duplicate-key warnings. Grep that the page imports resolve and reference only T1's store keys. - [ ] **Step 5:** commit `git commit -am "feat(leadverification): port verification page + components (table, cards, summary, assign/verify modals)"`. ## Task 4: Route + nav **Files:** `src/App.jsx`, `src/components/Layout.jsx`. **After T3.** - [ ] **Step 1 (App.jsx):** import `LeadVerificationPage` (`import LeadVerificationPage from './pages/LeadVerification/LeadVerificationPage';`). Add ONE unified route: ```jsx } /> ``` (Unified per our Plan-2 direction; interim coarse guard — Plan 8 ABAC replaces it. Do NOT add the source's three role-prefixed routes.) - [ ] **Step 2 (Layout.jsx):** add a nav entry `{ to: "/lead-verification", icon: ShieldCheck, label: "Lead Verification" }` to the OWNER, ADMIN, and FIELD_AGENT nav arrays (after the "Leads" entry). Import `ShieldCheck` from lucide-react if not already imported. - [ ] **Step 3 (verify):** `npm run build` → `✓ built`. `git grep -n "/lead-verification" -- src/App.jsx src/components/Layout.jsx` shows the route + nav entries. - [ ] **Step 4:** commit `git commit -am "feat(routes): add /lead-verification route + sidebar nav"`. ## Task 5: Verify (read-only) - [ ] `npm run build` clean, 0 duplicate-key warnings. - [ ] 15 verification records; summary tiles' counts equal the per-status record counts (computed, not hardcoded); filters (status/source/assignee) narrow the list. - [ ] No fake names/placeholders in the records (`git grep` for movie names / `(972) 555-0NNN` → none); assignees are a1/a2/a3. - [ ] **The verify→pipeline link (headline):** dev-run → open `/lead-verification`, verify a record → it leaves the active queue (status Verified) AND a matching New Lead appears in the Leads list (`/…/leads`) with `createdByName: 'Lead Verification'`, and that new lead opens in the lead detail page (Plan 6) with no broken fields. - [ ] Assign / reassign / set-status / unverify / add-note persist in session and update the table + badges. - [ ] `/lead-verification` reachable from the sidebar for OWNER/ADMIN/FIELD_AGENT. --- ## Self-review checklist - [ ] 15 grounded verification records (real admins/customers/addresses/sources; no fakes; status↔verificationStatus consistent; coherent dates). - [ ] 6 mutators exposed; `verifyLead` pushes a schema-correct New Lead into `leads`. - [ ] `ui/Select` + all `LeadVerification/` files + page ported; imports resolve; reference only T1's store keys. - [ ] Unified `/lead-verification` route + nav for the 3 roles; source's RBAC/access-matrix changes NOT ported. - [ ] Build clean; verify→New Lead works end-to-end into the existing pipeline.