313 lines
37 KiB
Markdown
313 lines
37 KiB
Markdown
# LynkedUp Pro Roofing — Demo Build: Master Plan, Scope & Rationale
|
||
|
||
**Date:** 2026-05-29 · **Branch:** `revamp` · **App:** React 18 + Vite 7 SPA, mock React-context data store, pnpm.
|
||
|
||
> **What this document is.** The single, authoritative "what we are building and why." It paints the whole picture: the vision, the product as it stands, the canonical company, the current vs. target data model, every phase of work with rationale and acceptance criteria, the state machines, the demo scenarios, and how we execute safely. Detailed step-by-step plans live in `docs/superpowers/plans/`; the formal design spec in `docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md`; the subagent rules in `docs/superpowers/plans/2026-05-29-execution-protocol.md`. When those and this doc disagree, **this doc is the intent**; the others are the mechanics.
|
||
|
||
---
|
||
|
||
## Table of contents
|
||
1. Vision & audiences
|
||
2. Guiding principles
|
||
3. The product at a glance (roles, modules, screens)
|
||
4. The canonical company (roster & org)
|
||
5. Data architecture — current state
|
||
6. Data architecture — target unified model
|
||
7. Status: what's already done (Phase 1)
|
||
8. The phases (2–8) in depth
|
||
9. The project lifecycle state machine
|
||
10. The subcontractor task state machine
|
||
11. The estimate & inspection models
|
||
12. The 10 demo-case scenarios
|
||
13. Profiles, skills & AI dispatch context
|
||
14. Cross-cutting coherency requirements
|
||
15. Routing map (current → target)
|
||
16. Execution model (subagent-driven, parallel-safe)
|
||
17. Risks & how we mitigate them
|
||
18. Open decisions & deferred work
|
||
19. Glossary
|
||
20. Document index
|
||
|
||
---
|
||
|
||
## 1. Vision & audiences
|
||
|
||
Turn this CRM's mock data and screens into **one coherent fake roofing company — "LynkedUp Pro Roofing," based in Plano, Texas** — convincing enough to carry two very different conversations:
|
||
|
||
- **The live sales demo.** A salesperson sits with a roofing-company prospect and walks the app. Nothing may be empty or obviously fake. Numbers must feel real at a glance. There must be a *continuous story*: a storm hits, a canvasser knocks a door, a lead is created, an inspector verifies major damage, an insurance-backed estimate is signed, the job runs with subcontractors, invoices are paid, commission is calculated. Every screen the salesperson clicks into must reinforce that story.
|
||
- **The investor / stakeholder pitch.** Here breadth and sophistication matter: dashboards that summarize a busy pipeline, profit and commission analytics, storm-driven lead attribution, AI-assisted dispatch, gamified field teams. The product should look like a mature, data-rich platform — not a prototype with three rows of sample data.
|
||
|
||
These two audiences pull in the same direction if — and only if — the underlying data is **deeply consistent**. A flashy dashboard that contradicts the records behind it is worse than no dashboard. So the whole effort optimizes for end-to-end coherence first, and surface polish second.
|
||
|
||
## 2. Guiding principles
|
||
|
||
1. **Coherence is the wow.** The single most impressive thing in a live demo is drilling from a summary number into the exact records that compose it and finding they tie out — dashboard revenue equals the sum of project contract values; a project's budget breakdown sums to its committed and actual costs; the subcontractor working a job sees the same job the owner sees. We engineer for that.
|
||
2. **Compute analytics from data, never hardcode.** Dashboard KPIs are derived via selectors over the live `projects` / `leads` / `tasks` arrays. This guarantees they can never drift from the detail screens, and every data fix automatically flows into the charts. The only exception is purely-visual long-range trend lines (e.g. a 12-month revenue sparkline) where no daily source data exists — those are clearly illustrative.
|
||
3. **One canonical identity per person.** Every employee, owner, contractor, and subcontractor has exactly one id, one name, one set of attributes, referenced consistently everywhere. No placeholder names, no parallel id schemes, no "Unknown" labels.
|
||
4. **A job is one entity.** A lead that is won becomes a project — the same record, not a parallel copy. This is the architectural spine that lets the rich detail UI, lifecycle, estimates, and analytics apply everywhere a job appears.
|
||
5. **No empty or broken views.** Every tab, list, and modal a demo might open is populated with believable data. Dates are anchored to a fixed `DEMO_TODAY` (2026-05-29) so nothing goes stale or lands in the future.
|
||
6. **Texan realism.** Names, addresses, companies, and phone numbers read like a real Plano/DFW roofing operation, not `test`/`asdf`/`Admin One`.
|
||
|
||
## 3. The product at a glance
|
||
|
||
**Roles (login types):** Customer, Field Agent (canvasser), Admin/Manager, Owner, Contractor, Vendor, Subcontractor. Each lands on a role-specific dashboard after login.
|
||
|
||
**Major modules / screens:**
|
||
- **Maps / Territory** (`/…/maps`) — pin properties, reverse-geocode, create entries. (Owners can now create entries — fixed.)
|
||
- **Pipeline / Kanban** (`/…/kanban`) — leads flow New → Contacted → Appt → Estimate → Signed → In-Progress → Complete, plus Stuck / Follow-up buckets.
|
||
- **Leads list** (`/…/leads`) and **Lead detail** (`/…/leads/:id`).
|
||
- **Projects** (owner) — list (`/owner/projects`) and rich detail (`/owner/projects/:id`) with 10 tabs (Overview, Budget & Costs, Team, Change Orders, RFIs, Milestones, Invoices, Risk & Issues, Activity, Docs).
|
||
- **LynkDispatch** (`/…/dispatch`) — AI-scored rep recommendations for incoming leads.
|
||
- **Storm Intel** (`/…/storm-intel`) and **Field Storm Zones** — hail/storm data, attribution.
|
||
- **Leaderboard** (`/admin/leaderboard`) — sales & canvasser rankings (animated podium).
|
||
- **ProCanvas** (`/…/pro-canvas`) — gamified canvassing (XP, levels, badges, achievement tiers).
|
||
- **Estimates / EstimateBuilder**, **Owner Snapshot dashboard**, **Org Settings** (roles, permissions, commission), **Subcontractor Tasks** (owner) and the **Subcontractor portal** (dashboard, task detail).
|
||
|
||
**Data store:** a single large React-context module (`src/data/mockStore.jsx`, ~7,000 lines) exposing arrays (`projects`, `kanbanLeads`, `leads`, `users`, `personnel`, `owners`, `subcontractors`, `orgMembers`, `MOCK_SUBCONTRACTOR_TASKS`, dispatch data, storm data, estimates/templates) and mutators via `useMockStore()`. There is **no backend and no test framework** — everything is in-memory mock data, and verification is by production build + reconciliation checks + running the dev server.
|
||
|
||
## 4. The canonical company (roster & org)
|
||
|
||
**LynkedUp Pro Roofing** — Plano, TX. Owners run the business; admins manage operations; sales reps close; field agents (canvassers) source storm leads door-to-door; a contractor and several subcontractors execute the work.
|
||
|
||
**Canonical roster (single source of truth — names, ids, employee ids, login):**
|
||
|
||
| id | Role | Name | empId | Login type | Login id | Password |
|
||
|----|------|------|-------|-----------|----------|----------|
|
||
| own_001 | Owner | Justin Johnson | LUP-1001 | owner | justin | password |
|
||
| own_002 | Owner | Diana Reeves | LUP-1002 | owner | diana | password |
|
||
| a1 | Admin | Wade Hollis | LUP-1010 | employee | LUP-1010 | password |
|
||
| a2 | Admin | Darlene Brooks | LUP-1011 | employee | LUP-1011 | password |
|
||
| a3 | Admin | Roy Schaefer | LUP-1012 | employee | LUP-1012 | password |
|
||
| p1 | Sales Rep | Jesus Gonzales | LUP-1030 | employee | LUP-1030 | password |
|
||
| p2 | Sales Rep | Sarah Calloway | LUP-1031 | employee | LUP-1031 | password |
|
||
| e1 | Field Agent | Cody Tatum | LUP-1040 | employee | LUP-1040 | password |
|
||
| e2 | Field Agent | Hannah Reyes | LUP-1041 | employee | LUP-1041 | password |
|
||
| e3 | Field Agent | Travis Boone | LUP-1042 | employee | LUP-1042 | password |
|
||
| e4 | Field Agent | Shelby Greer | LUP-1043 | employee | LUP-1043 | password |
|
||
| e5 | Field Agent | Dalton Pruitt | LUP-1044 | employee | LUP-1044 | password |
|
||
| con_001 | Contractor | Mike Brennan | LUP-3001 | contractor | mike | password |
|
||
| sub_001 | Subcontractor | Carlos Mendoza (Electric Pro Services) | LUP-2001 | subcontractor | carlos | password |
|
||
| sub_002 | Subcontractor | Maya Patel (Skyline Roof Crew) | LUP-2002 | subcontractor | maya | password |
|
||
| sub_003 | Subcontractor | Dwayne Boudreaux (Holland Painting Co.) | LUP-2003 | subcontractor | dwayne | password |
|
||
| sub_004 | Subcontractor | Jennifer Castillo (Wu Plumbing) | LUP-2004 | subcontractor | jennifer | password |
|
||
| sub_005 | Subcontractor | Greg Alston (Alston Window Pros) | LUP-2005 | subcontractor | greg | password |
|
||
|
||
Org-role taxonomy used by Org Settings / permissions: OWNER, ADMIN, SALES_REP, CANVASSER, SUBCONTRACTOR. Login identity for employees/admins is the `LUP-####` employee id; owners/contractors/subs log in by username; all share the demo password `password` (the login page's per-role picker auto-fills it).
|
||
|
||
## 5. Data architecture — current state
|
||
|
||
The single most important structural fact (confirmed by code exploration) is that **a "job" is currently modeled twice**:
|
||
|
||
- **`projects` array** (`proj_001`…`proj_012`, now migrating to `PRJ-2026-###`). Rich schema: `budget`/`approvedBudget`, `committedCost`, `actualCost`, `spent`, `variancePercent`, `margin`, `commissionType`/`Rate`/`commission`, `budgetBreakdown[]`, `changeOrders[]`, `rfis[]`, `riskLog[]`, `issueLog[]`, `paymentSchedule[]`, `activityTimeline[]`, `milestones[]`, `invoices[]`, `documents[]`, `teamMembers[]`, `contractorId`, `subcontractorIds[]`, `phase`, `healthScore`, `completionPercentage`. Rendered by `OwnerProjectDetail.jsx` (2,086 lines, 10 tabs, owner-only) with a full commission/profit engine.
|
||
- **`KANBAN_LEADS_INITIAL`** (`kl_001`…`kl_044`) + **`KANBAN_PROJECT_DATA`** (keyed by the 16 *won* lead ids kl_023–kl_038). Thinner schema with **different field names** (`estimatedAmount` vs `budget`, `completionPct` vs `completionPercentage`, `workTimeline` vs `activityTimeline`, divergent milestone/invoice/RFI/CO shapes) and **denormalized** contractor strings instead of FKs. Rendered by `LeadProjectPage.jsx` (1,159 lines, simple/full tab switch).
|
||
|
||
The two share **no join key** — no common id, address, or foreign key. They describe overlapping real-world jobs but cannot be cross-referenced. This duplication is the root cause of "lead pages don't match project pages," inconsistent routes, and the maintenance burden of keeping two datasets coherent. Resolving it is Phase 2.
|
||
|
||
Other key collections: `users`/`personnel`/`owners`/`subcontractors` (people, now canonical), `orgMembers` (org roster + roles), `MOCK_SUBCONTRACTOR_TASKS` + `MOCK_NOTIFICATIONS` (subcontractor work), `DISPATCH_REPS` + `DISPATCH_RECOMMENDATIONS` (LynkDispatch — note: a *separate* `REP-0x` namespace), `MOCK_ESTIMATES_INITIAL` + `MASTER_TEMPLATES_INITIAL` (estimates, not yet linked to projects), storm/hail data, and ProCanvas gamification state.
|
||
|
||
## 6. Data architecture — target unified model
|
||
|
||
**Principle:** a *won* lead and a project are the same entity. After Phase 2:
|
||
|
||
- **One `projects` array** holds all jobs, keyed by `PRJ-2026-###`. The 12 existing projects migrate ids (with their inbound FKs from tasks/schedule/subcontractor data). The 16 won kanban leads (kl_023–038) are converted into full project records (`PRJ-2026-013…028`), with `KANBAN_PROJECT_DATA` field names normalized to the project schema and missing project fields back-filled.
|
||
- **Bidirectional link:** each converted project carries `sourceLeadId: 'kl_0xx'`; each won kanban lead carries `projectId: 'PRJ-2026-0xx'`. The kanban board still shows these leads in Signed/In-Progress/Complete columns, but "More Details" routes to the unified project page.
|
||
- **Pre-sale leads** (kl_001–022, 039–044 — New/Contacted/Appt/Estimate + Stuck/Follow-up) remain leads with no project, shown on the lighter `LeadProjectPage` at `/…/leads/:id`.
|
||
- **One rich detail page** (`OwnerProjectDetail`, made viewable by owner/admin/field-agent) serves every won job at `/…/projects/:id`. Lead-side extras it currently lacks (pipeline progression bar, stage mover, hail history) are added onto it in Phase 4.
|
||
|
||
Field normalization map (kanban → project): `estimatedAmount`→`budget`/`approvedBudget`; `completionPct`→`completionPercentage`; `workTimeline`→`activityTimeline`; milestone `date`→`dueDate`; invoice `{description,paidDate}`→`{submittedBy,datePaid}`; rfi `{openedDate,closedDate}`→`{dateOpened,dateClosed}`; changeOrder `{requestedBy,date}`→`{dateSubmitted}`; `contractorName`/`Phone`→`contractorId`. Back-fill: `teamMembers`, `riskLog`/`issueLog`, `paymentSchedule`, `commission*`, `phase`, `budgetBreakdown` (Plan-1 invariants), computed `openRFIs`/`changeOrderCount`/`pendingInvoiceCount`.
|
||
|
||
## 7. Status: what's already done (Phase 1 — Data Foundation)
|
||
|
||
**Complete, independently reviewed APPROVED, 14 commits, build clean.** Delivered:
|
||
- **Canonical identity** — unified id scheme; `resolvePerson(id)` selector as the single people lookup; `orgMembers` and subcontractor-task actor ids remapped; no stale ids anywhere.
|
||
- **Texan roster + `LUP-####` empIds** — all placeholder names ("Frank Agent", "Admin One", "Carlos Subcontractor", …) replaced repo-wide; emails reconciled.
|
||
- **Financial coherence** — all 12 projects' `budgetBreakdown` columns sum to their totals, `committed ≥ actual`, `spent == actualCost`, variance signs correct; paid invoices ≤ actual cost; 6 missing breakdowns added. (106 id/name pairings cross-checked, zero mismatches.)
|
||
- **No empty/broken views** — Leads list seeded (35 leads); `sub_002–005` can log in (company/trade aligned to source records); subcontractor tasks address-matched to real projects; `On Hold` status styled.
|
||
- **Pipeline data** — every kanban lead has a `$ value`; Complete-stage leads read finished; 18 storm leads flagged.
|
||
- **Login** — per-role person picker (expand role → pick person → one-click in); all role paths verified.
|
||
- **Earlier fixes** — Vite `/api/*` dev stub (no more `@vercel/kv` crash); owners can create map entries; animated leaderboard podium (count-up + staggered bottom-up bars); the `_Demo_Old` feature branch merged in (subcontractor, org-settings, commission features) with conflicts resolved.
|
||
|
||
## 8. The phases (2–8) in depth
|
||
|
||
### Phase 2 — Unify lead↔project + routing/naming *(planned; plan written)*
|
||
- **Current:** two data models, two detail pages, two route families, no join key (see §5).
|
||
- **Target:** one `projects` model with `PRJ-2026-###` ids; won leads converted and linked; one rich detail page served under `/owner|admin|emp-fa/projects/:id`; pre-sale leads stay on the lead page; kanban + project-list links updated (see §6).
|
||
- **Why:** eliminates the duplication that makes lead pages thinner than project pages and routes inconsistent; once a job is one entity, lifecycle/estimates/analytics/subcontractor-parity all apply everywhere for free.
|
||
- **Key decisions:** Unify (won = project). `PRJ-2026-###`. Pre-sale leads = lighter subset of the same page.
|
||
- **Obstacles handled in the plan:** no join key → generate `projectId` on conversion + back-link; field-name mismatches → normalization map; missing project fields on won leads → back-fill with Plan-1 invariants; owner-only detail lookup → relax for admin/field-agent; 4 navigation call-sites → conditional links; `proj_*` FK blast-radius → migrate definitions + FKs together, verified by grep.
|
||
- **Acceptance:** no `proj_###` left; 16 new linked projects; all ~28 projects satisfy financial invariants; build clean; won leads route to the rich page for all three roles; pre-sale leads route to the lead page.
|
||
- **Demo beat:** "Here's the pipeline. This signed job? Click in — full budget, team, change orders, invoices, the same screen the owner manages it on."
|
||
|
||
### Phase 3 — Kanban/pipeline depth + analytics *(next plan)*
|
||
- **Target:** (1) realistic pre-sale lead details (customer, address, estimate value, activity notes, real dates — no sequential fake phones); (2) rich per-lead/project data so any job's detail is deep; (3) coherent stage distribution with a working pipeline $ total and conversion funnel; (4) storm attribution on leads, traceable to storm events; the **10 curated demo-case scenarios** (see §12); and a computed **`src/data/selectors.js`** analytics layer wired into the owner/admin dashboards (pipeline value/funnel/win-rate, revenue/gross/net profit, commission by rep, subcontractor performance, storm attribution).
|
||
- **Why:** the pipeline must read like a busy real company (investor breadth) and let a salesperson demo any scenario (sales depth); computed analytics guarantee the dashboards never contradict the records.
|
||
- **Acceptance:** dashboard headline numbers equal the sums of the underlying records; pipeline shows a real $ total; every lead has believable details.
|
||
|
||
### Phase 4 — Project lifecycle + inspections + estimates *(plan after 3)*
|
||
- **Current:** `OwnerProjectDetail` already renders a "PROJECT PROGRESSION" bar (Lead → Inspection Scheduled → Damage Verified → Scope Approved → Project Completed) but it is static and its highlighted stage disagrees with the completion % (e.g. proj_003 shows "Inspection Scheduled" at 42% complete).
|
||
- **Target:** make it an **interactive state machine** with progress % correctly tied to the stage (see §9); the **inspection model** with two touchpoints and an issues/rework loop (see §11); a **claimed-vs-verified scope-variance** badge; and an **estimate-versions** section per project (v1 from the customer's claim → v2 verified → signed; each opens the full rendered estimate document).
|
||
- **Why:** the stage/percent mismatch is a visible defect; interactivity + the inspection loop + scope-variance is the heart of the sales narrative (a professional inspection turns a $200 self-report into an insurance-backed job). Uploads (issue photos/notes) persist for the session; data is seeded.
|
||
- **Acceptance:** advancing a stage updates progress %; logging an inspection issue (with photo + note) shows on the project and loops to rework then re-inspection; estimate versions list with a Signed badge and full document view.
|
||
|
||
### Phase 5 — Subcontractor task state machine *(plan)*
|
||
- **Target:** replace flat task statuses with the stage machine in §10 (Not Assigned → Assigned → Pre-Work Inspection → Work In Progress → On Hold ↔ → Post-Work Review → Pass→Completed / Fail→Rework). Every transition carries an optional note + timestamp + actor; pre/post inspections record who performed them; the owner table gains Task Category + Assigned Date columns; the task modal gets a richer progress timeline + issues list with photos.
|
||
- **Why:** mirrors the real field workflow and gives the subcontractor an interactive inbox; the review/rework loop is a credible operational story that also feeds owner-side visibility.
|
||
|
||
### Phase 6 — Subcontractor portal data + project parity *(plan)*
|
||
- **Target:** the `/subcontractor/` pages (dashboard, projects, task detail) get realistic data and, where they show a job, **the same project details the owner sees** — a permitted subset of the unified project (address, scope, schedule, the subcontractor's slice of budget/payments). Enabled by Phase 2's single project entity.
|
||
- **Why:** coherence across logins is the demo's credibility test — the same job must look like the same job whether the owner or the subcontractor is viewing it.
|
||
|
||
### Phase 7 — Profiles, skill catalog & AI dispatch context *(plan)*
|
||
- **Target:** a two-layer profile per person + a self-service User Details page + an owner Employee/Subcontractor Details view + a shared org skill catalog, all feeding LynkDispatch (see §13).
|
||
- **Why:** richer structured context yields more believable AI dispatch recommendations (investor wow), and the profile depth is what a prospect expects from a mature CRM.
|
||
|
||
### Phase 8 — Access control + unified permission-aware routing *(plan)*
|
||
- **Current:** a real permission framework already exists — `orgPermissions` (role × module → actions), `userPermissionOverrides` (per-person grant/deny), the `usePermissions().can(module, action)` hook (Owner→all; person-override wins; else role default), and `PermissionGate` for component-level gating — all editable in Org Settings. But the **routing layer ignores it**, and routing is **triplicated**: the same feature components are mounted under `/owner/…`, `/admin/…`, and `/emp/fa/…` with only `<ProtectedRoute allowedRoles={[...]}>` (a coarse role check), plus a `basePath` helper recomputing the role prefix everywhere to build links. `PERMISSION_MODULES` covers only 7 features; denied users bounce to `/`; feature segments are terse (`maps`, `kanban`).
|
||
- **Target (Option B — unified, permission-guarded):** **one route per feature, no role prefix**, with human-readable names: `/territory-map`, `/pipeline`, `/projects/:id`, `/leads/:id`, `/dispatch`, `/storm-intel`, `/estimates`, `/leaderboard`, `/pro-canvas`, `/org-settings`, `/subcontractor-tasks`, etc. A **permission-aware route guard** decides access: `can(module, 'view')` honoring per-person overrides (role is just one input via the role default). Role-specific **dashboards/landing stay distinct** (`/owner`, `/admin`, `/agent`, `/contractor`, `/vendor`, `/subcontractor` homes, or a `/dashboard` that resolves per role). This **removes the 3× triplication and the `basePath` logic** (links become absolute feature paths). **Expand `PERMISSION_MODULES`** to map every gated route to a module. **Hide nav items** a person can't `view` (in `Layout`); show a **styled "Access Restricted" page** on direct-URL hits to denied routes. Edit/delete stay gated **inside** pages via `PermissionGate` (read-vs-edit). **No seeded override examples** — capability built; exceptions configured live in Org Settings. `/emp/fa` is retired in favor of `/agent` for the landing.
|
||
- **Why:** the demo's two example asks — "all admins except one get feature X," "all agents except one are read-only" — already map to the data model (role default + a per-person grant/deny override; view-only = read-only). This phase makes that granularity **enforced at the route and reflected in the UI**, and simultaneously cleans the routes to one obvious, human-readable URL per feature — a credible enterprise-RBAC story plus a far tidier app.
|
||
- **Decisions:** Option B unified routes (no role prefix) + human-readable names; route refactor **folded into this phase** (reverses the earlier "no consolidation"); permission-aware guard (`can(view)` + overrides); hide-nav **and** restricted page; role-specific dashboards kept; no seeded overrides.
|
||
- **Acceptance:** every feature has exactly one route; the guard blocks a `userPermissionOverride`-denied user at the route (Access Restricted) and hides it in nav; allowed users see the view while edit controls respect `can(module,'edit')`; owner sees everything; no `basePath`/role-prefix duplication remains; every gated route maps to a `PERMISSION_MODULES` entry.
|
||
- **Note on Plan 2:** Plan 2 (unify) adds interim role-prefixed project routes (`/owner|/admin|/emp-fa/projects/:id`) so won-leads are viewable before Phase 8; Phase 8 then **consolidates all routes** (including projects) to the unified scheme. Accept the minor interim churn to keep each plan shippable.
|
||
|
||
## 9. The project lifecycle state machine
|
||
|
||
A `lifecycleStage` field per project drives a state machine; the coarse kanban stage (In-Progress/Complete) derives from it. Each stage maps to a project progress %:
|
||
|
||
| Stage | Progress | Meaning |
|
||
|-------|---------|---------|
|
||
| Lead | 5% | Customer's reported claim captured |
|
||
| Damage Inspection Scheduled | 10% | Inspection booked |
|
||
| Damage Verified | 20% | Real scope captured (findings + photos) |
|
||
| Scope Approved | 30% | Customer accepts the verified scope/estimate |
|
||
| Contract Signed | 40% | Signed estimate; becomes the deal |
|
||
| Work In Progress | 40–70% | Milestone-driven within this band |
|
||
| Work Complete — Awaiting Inspection | 80% | Build done, pending final inspection |
|
||
| Final Inspection (Scheduled → In Progress) | 85–90% | External examiner reviewing |
|
||
| Rework In Progress | regresses | If issues found; loops back to Final Inspection |
|
||
| Project Completed | 95% | Passed inspection |
|
||
| Final Payment Received — Closed | 100% | Paid in full |
|
||
|
||
Transitions are interactive (owner/admin advance them, each with an optional note + timestamp + actor). *(Stage names are the proposed set; minor renames pending from the user.)*
|
||
|
||
## 10. The subcontractor task state machine
|
||
|
||
`Not Assigned → Assigned → Pre-Work Inspection → Work In Progress → (On Hold ↔) → Post-Work Review →` then either `Pass → Completed` or `Fail → Rework Needed` (capture what's wrong + note + photo) `→ back to Work In Progress → re-review`. Every transition carries an optional note, timestamp, and who set it. Pre-Work Inspection and Post-Work Review each record who performed them. Surfaced on the owner Subcontractor Tasks page (with Task Category + Assigned Date columns and a rich detail modal) and in the subcontractor's own login.
|
||
|
||
## 11. The estimate & inspection models
|
||
|
||
**Estimate versions (per project):** `estimateVersions[]` = `{ version, date, total, note, status: sent|revised|signed, lineItems/templateRef }`. The list shows date/note/total and a Signed badge; clicking a version opens the full rendered estimate document (reusing the existing estimate/template rendering). v1 reflects the customer's claim; later versions reflect the verified scope.
|
||
|
||
**Inspections (two project-level touchpoints, each records who did it):**
|
||
- **Damage Verification** (pre-sale): performed by a field agent *or* sales rep — inspector recorded per project (name + role) — producing the verified scope, findings, and photos.
|
||
- **Final Inspection** (post-work): an **external examiner brought by the customer** — no login/role; we store `inspectorName`, `inspectorContact` (phone + email, so they can be re-contacted), `inspectionDate`, `result` (pass/fail), `feedbackNote`, and `issues[]` (each `{ description, note, photos[], status: open|fixed }`). Re-inspection after rework creates a new round; all rounds remain visible.
|
||
|
||
**Claimed-vs-verified scope variance:** the lead stores `reportedScope` (the customer's claim); Damage Verification produces `verifiedScope`; when they differ materially, the project carries a scope-variance flag shown as a visible badge (e.g. "Reported ~$200 / 1 day → Verified $15,400 / 5 days"). This feeds the estimate versioning and a decision branch: approved (often via an insurance supplement) or declined (lead lost).
|
||
|
||
## 12. The 10 demo-case scenarios
|
||
|
||
Curated jobs, each threaded end-to-end (lead → project → subcontractor task → invoices → commission) with consistent identities, addresses, and dates, chosen to let a salesperson demonstrate any real-world situation and to show breadth:
|
||
|
||
1. **Storm-driven win, on track** — canvasser sources it, healthy active job.
|
||
2. **Insurance-backed up-scope → approved** — small self-report; inspection finds major damage; revised estimate; insurance supplement; approved. *(The hero discrepancy story.)*
|
||
3. **Up-scope → customer declines (lost)** — sticker shock; lead lost "after inspection."
|
||
4. **Smaller/different than claimed** — over-stated; inspection down-scopes to a quick job.
|
||
5. **Multiple revisions / negotiation** — several estimate versions before agreement.
|
||
6. **Over-budget / margin loss** — scope creep; negative margin (the problem job).
|
||
7. **Large commercial, multi-phase** — phased payment schedule, multiple subs.
|
||
8. **Near-complete, healthy** — most milestones done, final invoices pending.
|
||
9. **Completed, full lifecycle, all paid** — closed-won.
|
||
10. **Disputed / on-hold** — dispute timeline, paused payments, low health score.
|
||
|
||
## 13. Profiles, skills & AI dispatch context
|
||
|
||
**Profile (per employee & subcontractor), two layers:**
|
||
- **Self section** (the person edits on a self-service User Details page; owner can view): preferred name, photo, phone, alt contact, address, emergency contact; *optional* nickname / pronouns / gender / sex; short bio, years of experience, languages; self-declared specialties + **equipment carried** (e.g. "tarp, ladder rack, drone"); availability/service areas. Subcontractors also: company name, license #, insurance/COI + expiry, W-9 status.
|
||
- **Company section** (owner/admin only — private to the company): internal notes ("reliable in storms, keeps a tarp on the truck"), status/tags (preferred/probation/do-not-use), **skill scores**, pay/commission terms, hire date, manager.
|
||
- **Achievements & levels** (employees): read-only, pulled from ProCanvas gamification (level, XP, streak, badges, achievement tiers).
|
||
|
||
**Skill catalog (shared, org-level):** the owner defines a skill once (name + required description); each person carries a 0–100 score or N/A per skill. Comparable across people.
|
||
|
||
**AI dispatch context:** LynkDispatch scores reps per lead with factors `proximity / driveTime / calendarFit / weather / skillMatch`, plus `reasons[]` chips and a natural-language `aiInsight`. `DISPATCH_REPS` map to canonical people; each recommendation is authored to **cite real profile facts** (equipment + skill scores) — e.g. "Carlos — 92 Emergency Tarp · carries a tarp on the truck" — so "the AI read their profile" is demonstrably true on screen. (Today's recommendations are pre-authored mock; the profile data makes them coherent and explainable.)
|
||
|
||
## 14. Cross-cutting coherency requirements
|
||
|
||
These hold across all phases and are the acceptance backbone:
|
||
- **One person, one identity.** Same id → same name/role everywhere; no old ids or placeholder names. *(Verified by grep gates.)*
|
||
- **One job, one entity.** Lead → project → subcontractor task → invoices → commission all reference the same job and tie out. *(Phase 2.)*
|
||
- **Dashboards reconcile.** KPI numbers equal the sums of the records they summarize. *(Phase 3 selectors; verified by a reviewer re-summing.)*
|
||
- **Same job across logins.** Owner, pipeline, and subcontractor views of a job agree. *(Phases 2 & 6.)*
|
||
- **Financial invariants.** For every project: Σbreakdown.allocated == budget; Σcommitted == committedCost; Σactual == actualCost; committed ≥ actual; spent == actualCost; variancePercent sign correct; paid invoices ≤ actualCost.
|
||
- **Profiles cited by dispatch.** Equipment/skills referenced in recommendation rationale. *(Phase 7.)*
|
||
- **No future-dated mock; no empty tabs.** Anchored to `DEMO_TODAY` = 2026-05-29.
|
||
|
||
## 15. Routing map (current → target)
|
||
|
||
**Current (relevant routes):** `/owner/projects` + `/owner/projects/:projectId` (OwnerProjectDetail, owner-only); `/owner|admin|emp-fa/kanban` (KanbanPage); `/owner|admin|emp-fa/leads/:leadId` (LeadProjectPage); `/emp/fa/leads`, `/emp/fa/leads/new`. Kanban cards open a side **drawer**; the drawer's "More Details" is the only kanban→detail navigation, and it always goes to the lead page.
|
||
|
||
**Plan-2 interim target:** add `/admin/projects/:projectId` and `/emp/fa/projects/:projectId` → the same rich detail page, viewable by owner/admin/field-agent. Won leads' "More Details" routes to `/…/projects/PRJ-2026-###`; pre-sale leads keep `/…/leads/:id`. Project ids become `PRJ-2026-###` throughout. (These role-prefixed routes are interim; Phase 8 consolidates them.)
|
||
|
||
**Final target (Phase 8 — Option B, unified):** **one human-readable route per feature, no role prefix**, access decided by the permission guard:
|
||
|
||
| Feature | Final route | Old (triplicated) |
|
||
|---------|------------|--------------------|
|
||
| Territory map | `/territory-map` | `/owner/maps`, `/admin/maps`, `/emp/fa/maps` |
|
||
| Pipeline (kanban) | `/pipeline` | `/…/kanban` |
|
||
| Project detail | `/projects/:id` | `/owner/projects/:id` (+ interim admin/fa) |
|
||
| Lead detail (pre-sale) | `/leads/:id` | `/…/leads/:id` |
|
||
| LynkDispatch | `/dispatch` | `/…/dispatch` |
|
||
| Storm Intel | `/storm-intel` | `/…/storm-intel` |
|
||
| Estimates | `/estimates` | `/…/estimates` |
|
||
| Leaderboard | `/leaderboard` | `/admin/leaderboard` |
|
||
| ProCanvas | `/pro-canvas` | `/…/pro-canvas` |
|
||
| Org settings | `/org-settings` | `/owner/settings`, `/admin/settings` |
|
||
| Subcontractor tasks | `/subcontractor-tasks` | `/owner|/admin/subcontractor-tasks` |
|
||
| User details / profile | `/profile` | (new, Phase 7) |
|
||
|
||
Role-specific **dashboards/landing stay distinct**: `/owner`, `/admin`, `/agent` (replacing `/emp/fa`), `/contractor`, `/vendor`, `/subcontractor`. The permission-aware guard (`can(module,'view')` + per-person overrides) replaces `allowedRoles`-only checks; nav hides what a person can't view; denied direct-URL hits show a styled **Access Restricted** page; edit/delete stay gated inside pages via `PermissionGate`. The `basePath` triplication helper is removed (links become absolute feature paths).
|
||
|
||
## 16. Execution model (subagent-driven, parallel-safe)
|
||
|
||
- **Controller + fresh subagents.** The controller (orchestrating agent) extracts each task's full text and context, dispatches a fresh implementer subagent per task, then runs spec-compliance and code-quality review; the implementer commits per task. Subagents never read the plan file — the controller hands them exactly what they need.
|
||
- **Verification gates (no test harness).** Each task must end with a green `npm run build`, its specific grep/reconciliation check, and a committed clean tree. High-value/judgment tasks (e.g. financial reconciliation) also get an independent read-only reviewer; the whole plan ends with a final reviewer.
|
||
- **Parallel where lanes are disjoint.** Every plan ships a **lane/ownership map** assigning each task an exclusive file set. Tasks whose lanes don't intersect may run **in parallel**; tasks that share a file (especially `mockStore.jsx`) run **sequentially**. The controller never lets two in-flight agents write the same file, and commits between dependent tasks. (Example: Plan 2's Phase A — id migration then lead→project conversion — is sequential on `mockStore.jsx`; Phase B — detail-page access, routes, kanban relink, project-list relink — runs as four parallel agents on four different files.)
|
||
- **Model tiers.** Cheap/fast model for mechanical edits; standard for judgment/integration; most-capable for architecture and final review.
|
||
- **Invariants every task preserves:** the canonical roster (§4) and the coherency requirements (§14).
|
||
|
||
## 17. Risks & how we mitigate them
|
||
|
||
- **Large shared file (`mockStore.jsx`).** Mitigation: sequential edits with a commit between each; the build gate caught a real duplicate-declaration bug during the original merge and a copy-paste coherence bug during Phase 1.
|
||
- **Id migration breaking FKs (Phase 2).** `proj_*` is a foreign key in tasks/schedule/subcontractor data. Mitigation: migrate definitions + FKs together; grep gate (`proj_0` → none) proves no dangling references.
|
||
- **Lead→project field drift.** Mitigation: explicit normalization map + Plan-1 financial-invariant reconciliation on the new projects.
|
||
- **Analytics drifting from records.** Mitigation: compute from the live arrays (selectors), never hardcode.
|
||
- **Demo data going stale.** Mitigation: single `DEMO_TODAY` anchor.
|
||
- **Scope sprawl.** Mitigation: phased plans, each producing working/verifiable software; this master doc as the stable reference.
|
||
|
||
## 18. Open decisions & deferred work
|
||
|
||
- **Stage-name wording** — user said "I'll tweak a few"; proposed names in §9/§10 stand until provided.
|
||
- **Full convergence of `LeadProjectPage` into the unified page** — deferred; Phase 4 adds the lead-side extras (stage mover, hail history, progression) onto the project page.
|
||
- **Pre-sale leads getting `PRJ` ids** — only on conversion to a project; pre-sale stay `kl_*`.
|
||
- **Per-plan lane maps** — authored with each plan to enable safe parallel execution.
|
||
- **Distinct per-person passwords** — declined for demo simplicity (shared `password`, auto-filled by the picker).
|
||
|
||
## 19. Glossary
|
||
|
||
- **Lead** — a potential job in the pipeline (kanban). Pre-sale leads are not yet projects.
|
||
- **Project / Job** — a won job with full execution data; after Phase 2, a won lead *is* a project.
|
||
- **Canonical id / roster** — the single agreed id + name + empId per person (§4).
|
||
- **`DEMO_TODAY`** — fixed demo date (2026-05-29) anchoring all relative dates.
|
||
- **`resolvePerson(id)`** — store selector returning a person's `{id,name,email,role}` from any collection.
|
||
- **Lane** — the exclusive set of files a task may edit; the basis for safe parallel execution.
|
||
- **Scope variance** — the gap between a customer's reported claim and the inspection-verified scope.
|
||
- **LynkDispatch** — the AI rep-recommendation module.
|
||
- **ProCanvas** — the gamified canvassing module (XP/levels/badges).
|
||
|
||
## 20. Document index
|
||
|
||
- **This master plan:** `docs/superpowers/2026-05-29-MASTER-PLAN.md`
|
||
- **Design spec:** `docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md`
|
||
- **Execution protocol:** `docs/superpowers/plans/2026-05-29-execution-protocol.md`
|
||
- **Plan 1 — Data Foundation (done):** `docs/superpowers/plans/2026-05-29-demo-data-foundation.md`
|
||
- **Plan 2 — Unify + Routing (written):** `docs/superpowers/plans/2026-05-29-plan2-unify-routing.md`
|
||
- **Plans 3–7:** authored from this master doc as each prior plan lands.
|