The simplified status model: one linear project lifecycle with two boolean flags, plus sub-status tracks for certification and invoicing. Automated pipeline intelligence monitors all active projects, validates field data, enriches intake submissions, and routes deliverables based on confidence. Every status, every transition, every trigger, and who is responsible.
The primary lifecycle of a project, from intake through close. Stored in
the Supabase projects table (status column). Eight linear statuses plus three boolean
flags that can attach to any active status. All status writes route through Supabase as the sole source of truth; SmartSuite receives a mirror copy during the soak period (through April 6, 2026).
| Status | Value ID | Who Advances | Trigger | Auto? |
|---|---|---|---|---|
| Intake | go210 | Portal / Admin | Project created | Manual |
| Scheduled | jKK2p | Scheduler | Date set, calendar event created | Manual |
| In Progress | 0Xf2F | Inspector | Site visit started | Semi-auto |
| Field Complete | 1yplc | Inspector / Ops | Visit marked complete | Semi-auto |
| Pending RFI | DPBDX | System | RFI created on project; auto-resolves when last RFI closed → Ready for Cert (if validation passes) or Field Complete (fallback) | Auto |
| Ready for Cert | ogUeq | System | Cert validation passes all 10 checks | Auto |
| Certified | z1Tft | Ops Manager | Cert approved | Manual |
| Invoiced | 6yJZI | System | Cert + invoice sent | Auto |
| Closed | O1GXV | System / Admin | Payment confirmed (EFT reconciliation or Stripe) | Auto |
Boolean flag. Freezes all auto-advance logic. Can be set on any active status. Set by Admin or Ops Manager. Remove to resume normal lifecycle.
Boolean flag. Terminal — project is permanently stopped. Set by Admin only. No further transitions are possible.
Boolean flag. Blocks auto-validation — a partial inspection is not field complete. Set by inspector or ops when a return visit is required before the project can advance.
Tracks the certification document lifecycle within a project. Stored in
the Supabase projects table (cert_status column).
| Status | Value ID | Who Sets | Trigger |
|---|---|---|---|
| Not Started | ffypR | System | Default value on project creation |
| Draft | pD6PP | System | Auto Cert package generated |
| Approved | Ph6RR | Ops Manager | Cert reviewed and approved |
Tracks invoicing lifecycle. Payment confirmation via EFT reconciliation (transitioning to Revolut for banking).
| Status | Value ID | Who Sets | Trigger |
|---|---|---|---|
| Not Invoiced | xmcJK | System | Default value |
| Sent | PtYwM | System | Auto Invoice emailed to client |
| Paid | 2GdlH | System | Auto Payment confirmed (EFT reconciliation or Stripe webhook) |
Triage is not a lifecycle stage — it is a flag that overlays the project status. The 45-day scan automatically assigns JES-account projects to triage when they have been in an active status for more than 45 days without advancing.
In Triage — Set by the 45-day scan. Freezes normal workflow until resolved.
Resolved — Internal review complete. System runs cert validation; if all 10 checks pass, project auto-advances to Ready for Cert.
Returned — Sent back to originating team for additional work.
Internal triage work (desk review, field visit, additional data gathering) is tracked in triage notes and the Comm Log. The triage flag does not change the project status — it gates whether auto-advance can fire.
The complete end-to-end automation from field completion through payment. Human actions are shown in warm/khaki; system automation in blue.
The system continuously monitors projects and takes action automatically. These features reduce manual oversight, surface issues early, and keep projects moving through the lifecycle without waiting for someone to notice.
Auto When a project reaches Field Complete, the system automatically runs a 10-point validation checklist. If all checks pass, the project advances to Ready for Cert with no human intervention. If any check fails, an RFI is automatically generated and the project moves to Pending RFI until the issue is resolved.
A daily automated scan of all active projects, looking for anything stuck or
approaching a deadline. Runs once per day (idempotent) and reports via WhatsApp
and portal notifications. Reports stored at /data/shepherd/.
| Condition | Threshold | Action |
|---|---|---|
| Intake with no progress | > 3 days | Auto WhatsApp alert to Dustin |
| Scheduled with no site visit | > 2 days | Auto WhatsApp alert to Dustin |
| Field Complete with no validation | > 1 day | Auto Triggers auto-validation |
| Cert drafting overdue | > 3 biz days | Auto Portal notification to admin |
| Certified but not invoiced | > 1 day | Auto Portal notification to admin |
| Unpaid invoice | > 30 days | Auto WhatsApp alert to Dustin |
| Unpaid invoice (escalation) | > 60 days | Auto Escalation notification |
| Project on hold | > 30 days | Auto Portal notification |
| RFI aging | > 3 days | Auto Portal notification |
| RFI aging (escalation) | > 7 days | Auto Escalation notification |
Manual After Jacob drafts the cert and invoice, he chooses one of two paths based on confidence:
Guardrail The system automatically routes to review when: invoice total is $5,000 or more, or the project is in Anne Arundel, Montgomery, or Prince William county (proprietary jurisdiction forms).
Confidence routing gives Jacob autonomy on straightforward packages while ensuring high-value or complex deliverables get a second set of eyes. If Dustin requests revisions, the package returns to Jacob for updates before re-submission.
Auto When a new project intake is submitted, the system automatically enriches it with:
Enrichment data is stored on the intake request and displayed to schedulers and admins in an expandable panel during intake review.
Auto When a payment arrives (EFT remittance, Stripe webhook, or Revolut transaction), the smart matching engine scores each line item against open invoices:
Guardrail Payments ≥ $5,000 always require human confirmation regardless of match quality (caps at MEDIUM).
Remittance PDFs are auto-ingested from Gmail every 30 minutes (Mon–Sat, 1–9 PM ET). The inbox scanner searches for unprocessed emails, downloads attachments, parses line items (invoice number, amount, PINV reference), and feeds them into the matching engine. Processed emails are labeled to prevent duplicate processing. Stripe webhooks are handled immediately on receipt.
The pipeline snapshot, analytics, and revenue reporting now draw from three data sources, each with deduplication logic to prevent double-counting:
xero_invoices and xero_payments. Invoices linked to existing Supabase projects (via project_smartsuite_id) are excluded from pipeline counts to avoid duplication.Revenue reporting uses Mostly for current-period KPIs and Xero for historical data. Lifetime revenue combines both. The Morning Briefing shows a lifetime revenue banner. The Analytics page shows Historical Revenue by Year (2022–2024) and Year-over-Year Growth charts. Project detail pages show linked Xero invoices for financial roles. The Payments page includes a scrollable historical invoice ledger.
Three new API endpoints support this integration: GET /history/project-invoices/{id} (Xero invoices for a project), GET /history/xero-invoices (paginated Xero ledger with branch/status filters), and GET /history/xero-lifetime (lifetime revenue summary).
The portal includes a real-time messaging system (WebSocket-based, SQLite persistence) that integrates with the project lifecycle:
The notification router delivers alerts across three channels: portal notification, email (Gmail API), and WhatsApp. Per-user preferences control channel selection by urgency level. Features include offline email fallback (configurable delay), 2-minute consolidation window, and Do Not Disturb hours.
| Trigger | Threshold | Action |
|---|---|---|
| Unanswered message on project | > 24 hours | Auto Pipeline Shepherd flags in WhatsApp summary |
| Stale assignment | > 48 hours | Auto Pipeline Shepherd flags in WhatsApp summary |
| RFI conversation aging | > 3 days | Auto Morning Briefing highlights |
| Unanswered conversation | > 4 hours | Auto Morning Briefing highlights |
| SLA breach per priority tier | Varies by priority | Auto Notification router triggers on breach |
Auto When permits or plans are uploaded, Claude Vision extracts scope items and maps them to the product catalog. The parser now automatically detects when sub-component products are present (e.g. WTR-DTIL, ENC-CSEAL) and injects the required parent service lines:
Parent services are the billable inspection products that appear on invoices. Sub-components are scope documentation items ($0) that record what was installed. Both must exist for cert generation and invoicing to work correctly.
Auto Every cert and invoice email includes a 1×1 transparent tracking pixel. When the recipient opens the email, the pixel fires and records:
/portal/delivery-ledger with summary metrics (sent, opened, unopened, bounced, open rate) and filterable table.Auto Field update endpoints (arrival, inspection notes) include a 5-minute deduplication window. If the same event type is submitted for the same project within 300 seconds, the duplicate is silently blocked. Prevents repeated comm_log entries from network retries or app double-taps.
Friday (the portal AI) operates in role-based voices and three escalating intelligence tiers:
query_data and describe_schema tools. Structured queries against Supabase with table/column allowlists. Null-aware filtering (catches both blank fields and explicit “Not Invoiced” values). Friday self-discovers the schema before querying.run_sql executes read-only SQL via Supabase RPC function (SELECT only, 5-second timeout, 100-row limit, banned keyword detection, financial column redaction for non-privileged roles). Cross-system tools: query_stripe (invoices, payments, subscriptions), query_calendar (schedule), get_pipeline_alerts, get_recon_status. Schema reference (~800 tokens) injected into the system prompt for privileged users.When a user asks Friday for a chart, graph, or visual, the response renders directly in the chat bubble. Three rendering tiers:
<iframe sandbox="allow-scripts">). Tufte CSS tokens pre-injected. No network access, no parent window access. For custom dashboards, infographics, or layouts that go beyond standard chart types.The backend wraps each visualization in markers ($$FRIDAY_CHART$$, $$FRIDAY_RECHARTS$$, $$FRIDAY_SANDBOX$$) that the frontend parses and renders as the appropriate component.
Friday operates in role-based voices: Internal (owner/admin, Opus, full tools including all 3 tiers), Staff (scheduler/GOA/assistant, Sonnet, Tier 1–2 query + Tufte/Recharts charts), Client-facing (professional tone, 4 safe tools only, no financial data, no visualizations), and Field (concise mobile, limited tools). The “Ask Friday” button in any conversation invokes the appropriate voice based on the user’s role.
Cert and invoice delivery uses deterministic, account-based email routing. Each account has a fixed set of recipient addresses configured in the system. No manual email selection is required — the delivery endpoint looks up the project's linked account and routes to the correct contacts automatically.
| Account | Routing Rule |
|---|---|
| JES | Account-specific contact list; triage-eligible (45-day rule) |
| Groundworks | Account-specific contact list |
| All Others | Account-specific contact list; fallback to project contact if no account contacts |
Email routing is configured per account in Supabase (contacts table, linked to accounts).
The /cert/deliver
endpoint resolves recipients at send time. Override addresses can be specified per-delivery
for one-off routing changes.
How the old PMS (Project Management System) statuses map to the new simplified model. This mapping was used during the PMS → Mostly migration and remains the reference for any legacy data lookups.
| PMS Status | New Project Status | Notes |
|---|---|---|
| Request Approved | Field Complete | |
| Deliverables Ready | Certified | Cert already generated in PMS |
| Deliverables Received | Certified | |
| Submitted to County | Certified | Was "Delivered" in old model |
| Request Archived | Closed | Was "Archived" in old model |
| Cancelled | Closed + cancelled flag | |
| On Hold | Keep current + on_hold flag | |
| Work in Progress | In Progress | New mapping |
| Job Scheduled | Scheduled | New mapping |
| Ready for Scheduling | Intake | New mapping |
| New Request | Intake | Pre-sales, imported anyway |
| Ready for Quoting | Intake | Pre-sales, imported anyway |
| Request Quoted | Intake | Pre-sales, imported anyway |