leads-board-parityrun.md01_define/output/spec.mdWeb's service-leads board and demo's leads board have diverged into two different products.
Demo's board is a persona-lensed pipeline view — per-persona title/intro and column labels, a
four-tile summary row with pipeline value, per-column monetary totals, and cards showing the assigned
expert and deal value — built faithfully on the canonical nine-status lead workflow. Web's board is a
single generic, read-only board with eight grouped columns keyed to stale/invented status strings
(analysis, csat, requirements_analysis, a Closed lost column with no engine backing), no
summary row, no pipeline value, no expert, and no persona lensing. This blunts the vendor's view of
their book of work, which is exactly what Refine the Bridge → Q2 2026 Objective 1 (Establish
Product-Market Fit with Vendor Partners) depends on: the KR "maintain active engagement rate from
onboarded vendors (90%+)" needs vendors to see a clear, lensed pipeline of their leads and its value.
Bring web's board to demo visual parity while keeping it read-only (no status mutation this run).
Reconcile web's grouped/stale columns to the canonical nine-status lead workflow (one column per
real status, rendered only when the current persona has leads in that status — demo behaviour). Add
per-persona lensing (title/intro and per-column status labels, keyed to the authenticated user's
role), the four-tile StatBox summary row (Open / Pipeline value / Wrapping up / Completed), per-column
monetary totals, and cards showing the assigned expert (avatar + name) and deal value. Monetary
figures use each lead's budgetMin. The board stays read-only — cards remain links to the
lead/workspace view; drag-to-change-status is explicitly deferred to its own run.
lead workflow (pending, backlog, quotation_process, awaiting_confirmation, work_in_progress, delivered, survey_sent, completed, qualified_out) in journey order — web's grouped/dead columns and the Closed lost column are removed.qualified_out sorts last (matching demo).statusLabel(status, persona) equivalent) plus the lead count for that column.budgetMin over open leads), Wrapping up (count delivered or survey_sent), and Completed (count completed, with "N in active delivery" subtext where N = work_in_progress).budgetMin for that column) when the total is greater than zero.awaiting_confirmation onward (earlier statuses show "Unassigned"), and the deal value as formatMoney(budgetMin).budgetMin; a lead with no budgetMin counts as 0 in sums and renders "—" on the card.lead workflow, including the Closed lost column and the dead grouped statuses.service-leads/[id]) and the create/import flows (web-only; unchanged).statusLabel mirrors.)02_build/output/notes.mdpackages/services/src/db/services/leads/index.ts: added read-only
getLeadValueSummary(tenantId) — one $group aggregation returning per-status
count + summed budgetMin (missing budgets count as 0), scoped to the tenant
and non-deleted leads. Powers the summary tiles and per-column totals accurately
across the whole book rather than only the page-limited cards.apps/web/components/service-leads/leads-copy.ts (new): LEADS_COPY keyed by
UserRole — per-persona title/intro, ported from the demo (Customer → "Projects",
Expert → "Work queue", others → "Service leads"). Nothing imported from apps/demo.apps/web/app/(app)/service-leads/page.tsx: replaced the hardcoded, grouped/stale
KANBAN_COLUMNS with columns derived from statusService.getByWorkflow("lead")
(canonical 9 statuses, journey order, qualified_out last). Resolves the effective
persona with getRole() (emulation/active-role aware), lenses column labels via
statusService.resolveLabel(status, persona), maps expert (from awaiting_confirmation
onward) + budgetMin onto each card, filters to columns with ≥1 lead, and computes
the four summary tiles from the aggregation.apps/web/components/service-leads/kanban-board/kanban-board.tsx: extended card/column
types with expert + value; added the four-tile summary row (Open / Pipeline value /
Wrapping up / Completed) using shared Card/Typography; threads column value through.apps/web/components/service-leads/kanban-board/kanban-column.tsx: column header now
shows its budgetMin total when > 0 alongside the count; each card shows the assigned
expert avatar (initials) + name or "Unassigned", and the deal value as
formatMoney(budgetMin) (or "—" when absent). Board stays read-only — cards remain
<a href="/workspace/:id"> links, no drag-and-drop.lead workflow in journey order — grouped/dead columns and Closed lost removed (getByWorkflow("lead")).qualified_out sorts last (filter total > 0; order inherited from the workflow).getRole() + LEADS_COPY).resolveLabel(status, persona) + total).budgetMin total when > 0.awaiting_confirmation onward, else "Unassigned"; deal value = formatMoney(budgetMin)./workspace/:id.budgetMin; missing budget = 0 in sums, "—" on the card.getLeadValueSummary (one aggregation), so they are
accurate even when a column has more than the 20 rendered cards ("+N more"). The cards
themselves remain page-limited for display, matching the prior board.order >= 3, awaiting_confirmation onward) mirrors the demo's expertOf.03_release/output/changelog.mdLive entry: apps/help/app/changelog/2026-07-27-leads-board-parity/page.mdx
Title: Your service leads board now reads as a pipeline built around you Personas: vendor, csm, sdm, admin, customer, expert
The service leads board is now a pipeline view tailored to your role — per-persona heading and wording, columns that follow the real lead journey (only the stages you have work in), a summary row (open / pipeline value / wrapping up / completed), per-column value totals, and the assigned expert plus deal value on every card. Read-only, so nothing changes by looking.
03_release/output/investor-update.mdWho it's for: Vendors, CSMs, SDMs, admins, customers and experts What shipped: The web service leads board now reads per persona, with canonical pipeline columns, a value summary row, per-column totals, and the assigned expert and deal value on each card. Why it matters: A clearer pipeline view keeps onboarded vendors engaged — the core of Refine the Bridge's Q2 objective, establishing product-market fit with vendor partners.
All nine acceptance criteria met; read-only, no new data or infrastructure.
Dig deeper: https://github.com/sustentus/sustentus/pull/713 · https://help.sustentus.com/changelog/2026-07-27-leads-board-parity
03_release/output/release.md472cd0cgetLeadValueSummary) and UI behaviour on an existing route; no new app/package/route/env/architectureapps/help/app/changelog/2026-07-27-leads-board-parity/page.mdx) + investor draft in this PRtype over interface,
named imports, correct @sustentus/services/server + @/lib/auth boundaries, sentence-case UI copy
— all conform. No dead code or stray debug. The pre-existing .catch() on the per-column fetch is
retained (ESLint clean). No cleanup surfaced.lead workflow in journey order — grouped/dead columns and Closed lost removed (getByWorkflow("lead")).qualified_out last.getRole() + LEADS_COPY).resolveLabel).budgetMin total when > 0.awaiting_confirmation onward, else "Unassigned"; value formatMoney(budgetMin)./workspace/:id.budgetMin; missing → 0 in sums, "—" on card.