The deliverable group for PropFlow's next client: one centralized team, dozens of small buildings, two PM shops. Requirements traced to their words; architecture gaps under audit; nothing ships to them until proven on Willows and approved by Fede.
Started 2026-08-31 · driver page (Yale pattern: this page + prefixed Trello cards) · Hugo away until ~Sep 4 · WHITEBOARD BOOKED: Eileen + Fede, Tue Sep 1, 10am–1pm MT
What they're buying first, in Hugo's words: "using the answering service/feature for after hours / weekend inbound calls / leads that would allow us to retire our MCC line and keep our main line available 24/7. Normal hours goes through standard phone tree (with Clara possibly being in the tree to answer when all lines full) and after hours Clara answers all the calls and ports out through the tree when an emergency, etc. arises." (Hugo email, Aug 27 — the requirement of record.)
The company
Shape: a cluster of small assets (10–50 unit buildings, no leasing offices, one main number). Unit count needs reconciling: sales console says ~412 (359 county-verified, 21+ buildings, four counties); Hugo says ~1,000. Two PM operations: Englewood (HQ, 333 W. Hampden Ave #200) and Grand Junction (separate team; Hugo wants them demoed separately).
Stack: AppFolio since ~2017-18 (Hugo: "well overdue for a major clean up… a bunch of noise in there"). Paying AppFolio ~$1.50/unit/month for an after-hours answering add-on they want to retire. New phone system — Crexendo, cloud business VoIP — in flight, with per-staff direct numbers; Eileen owns the migration and wants our rollout "in concert" with it (capability notes below). ~12 Denver staff incl. 4 maintenance techs; VAs in the Philippines; ~70% of resident families Spanish-speaking; ~half of inbound calls are spam.
People: Hugo Weinberger (principal, decision-maker; old friend of Sean's) · Eileen O'Malley (Director of Ops — champion and gatekeeper) · Miriam (ops generalist) · Noam Ashter (CFO) · Matt Miller (maintenance) · Lee McKibbin, Deiby Magana (leasing/renewals) · Jason Fish (Grand Junction).
Deep dive — the company (from the sales machine + public records)
Pipeline stage: proposal (moved Aug 26; they want to come on as a beta partner; pricing has never been discussed).
Family firm, second generation: founded 1991 by Clifford Weinberger; Hugo president since 2019 (ex-Wells Fargo real-estate banking; a practiced proptech investor — 14+ single-purpose venture LLCs; treat him as a peer, not a prospect). Partners: Noam Ashter (CFO hat), Joel Cohen (development; likely tech ally). Eileen O'Malley runs ops; Lee McKibbin is the ONE leasing manager for the whole portfolio.
Unit count — house rule (Fede, Aug 17): quote Hugo's ~1,000, never our internal counts. Enumeration now largely reconciles his number: 434 Denver-metro units fully sourced (21 named properties + 15 scattered houses) plus ~270 Grand Junction / Mesa County doors newly enumerated parcel-by-parcel (tables below), plus 100+ doors they manage for other owners, plus ~175 units under construction or announced. The remaining true gap is ~110–210 units and most plausibly sits in the managed-for-others bucket.
Grand Junction runs under its own brand: the western shop trades as Western Slope Real Estate and Property Management (westernslopepm.com, 970-434-7000, office at 1133 N 18th St — a building they own). Jason Fish and James Taylor are on the paperwork; every GJ property is titled to a Situs GJ / Situs Headwaters / Situs Pomona company. This is why earlier searches keyed on the Englewood address found none of it — and it matters for rollout: GJ is a genuinely separate operation with its own name on the phone.
Their routing is ALREADY portfolio-global: one number (303-789-3030) on every property page, one email (leasing@thesitusgroup.com), and two company-wide after-hours emergency lines split by asset type — residential (720) 459-5986, commercial (720) 608-1191. Our portfolio-mode design mirrors how they already operate. Note: the same small team also covers their office/commercial buildings — which are OUT OF SCOPE for us (multifamily only, Fede).
Coverage gap they publish themselves: office hours Mon–Fri 9–5, closed weekends — 128 of 168 hours a week unstaffed. That's the product.
Hugo's stated pains (Aug 17, verbatim-sourced): weekly unexpected abandonments ("you open the door and they're gone… it's happening literally weekly"), NOI squeezed by expenses, and appliance chaos (his QR-sticker venture; he proposed a trade: his stickers on one of our buildings for PropFlow on his portfolio).
Residents: workforce housing, west Denver/Lakewood/Arvada + a Hale cluster; ~70% Spanish-speaking families — Spanish coverage and consistent fair-housing policy matter more than usual here.
Competitive field: no AI leasing vendor installed anywhere on their surfaces (swept Aug 21). Hugo volunteered intel on Ender (Austin, "fully AI property manager") and Cardinal Group's in-house AI.
The portfolio, on a map
Every named bubble is county-assessor + site verified (table below). Dashed bubbles are scattered homes, placed approximately.Owner entities: Situs GJ Multifamily / Situs Headwaters / Situs Pomona / Situs GJ SFR LLCs, all mailing to their GJ office. Commercial parcels (their office, S 7th St, Wellington Ave) excluded.
Their properties — Denver metro, fully sourced (434 units)
Property
Address
Area
Units
Confidence
Barcelona Apartments
8101–8195 W 9th Ave, Lakewood
Lakewood
48
site + county
Lampliter Apartments
375 S Depew St, Lakewood
Lakewood
41
site + county
Alton St portfolio (incl. Westcott)
1663–1683 Alton St + 9108 E 17th Ave, Aurora
Aurora
55
county + deed ($7.25M, Apr 2025)
Carr Street Flats
1391 Carr St, Lakewood
Eiber
34
site + county
3255 S Bryant St
Englewood
Englewood
31
county ($5.8M, Aug 2023)
Lowry Flats (rowhouses, 3 streets)
Xanthia/Willow/Richthofen, Denver
East Colfax/Lowry
26
site + county
The McKenzie
1375 Everett Ct, Lakewood
Eiber
24
site + county
Aspen Leaf
6090/6092 Wadsworth Blvd, Arvada
Olde Town
24
site + county
The Cottonwoods
5100 W 8th Ave, Denver
West Denver
22
site + county
Olde Town Terrace
6087 Wadsworth Blvd, Arvada
Olde Town
20
site + county
Cedar Court
7750/7790 W 61st Ave, Arvada
Olde Town
16
site only (new find)
399 N Fox St
Denver
Baker/La Alma
13
county only (unadvertised)
Mayor Apartments
4720 E 8th Ave, Denver
Hale
12
site + county
Dexter Apartments
830 N Dexter St, Denver
Hale/Mayfair
11
county (name-collision warning)
Dahlia Apartments
801 N Dahlia St, Denver
Hale
11
site + county
Zephyr (1320)
1320 Zephyr St, Lakewood
Lakewood
11
site + county
Zephyr (1330)
1330 Zephyr St, Lakewood
Lakewood
11
site + county
Arizona Apartments
3126+3132 W Arizona Ave, Denver
Mar Lee
5
site + county
Ingalls
183–193 S Ingalls St, Lakewood
Lakewood
4
site only (new find)
Scattered single-family
15 homes, south Denver
—
15
county (being trimmed)
Commercial (offices they own/occupy)
333 W Hampden + 3333 S Bannock, Englewood
Englewood
—
excluded from residential totals
Sources: county assessors (Denver, Jefferson, Adams, Arapahoe), Denver rental-license registry, recorded deeds, their own site + listing platforms. Name-collision warnings exist for Dexter/Dahlia/Zephyr — unrelated same-name buildings nearby.
Their properties — Grand Junction / Mesa County (~270 doors, newly enumerated)
Property
Address
City
Units
Owner entity
805 W Ottley (new build)
805 W Ottley Ave
Fruita
70
805 Ottley Avenue LLC
Pomona Park Townhomes
624 Eisenhauer St
Grand Junction
40
Situs Pomona LLC
Courtyard Apartments
2910 Bunting Ave
Grand Junction
27
Situs Headwaters Courtyard LLC
Concord GJ Apartments
518 28 Rd
Grand Junction
16
Concord GJ Apartments LLC
Lincoln Apartments
1303 N 15th St
Grand Junction
12
Situs Headwaters Lincoln LLC
Ember Estates (new duplexes)
Ember Ln / Florida St
Grand Junction
11 built (~30–40 at buildout)
Ember Estates HZ LLC
1240 Elm Ave + 1240 Bunting Ave
Elm / Bunting Ave
Grand Junction
11
1240 Elm Apartments LLC
Downtown small multifamily (5 parcels)
Hill Ave, Garfield Dr, Colorado Ave, N View Dr, G Rd
Grand Junction
18
Situs GJ Multifamily LLC + affiliates
Clifton cluster (6 parcels)
32⅛ Rd, Tracy Dr, Rood Ave, Cottonwood Lake Dr
Clifton
18
Situs GJ Multifamily LLC
Scattered houses/townhomes (44 parcels)
Morningside, Krista, Perkins, Emerald + more
GJ / Clifton / Fruita
47
Situs GJ SFR LLC
All rows verified against the live Mesa County assessor parcel service, 2026-08-31. Pipeline (not doors yet): The Terminal — 107 units, Grand Junction, 2028; The Gateway — 68 units, Parachute, 2026 (with development partner Headwaters Housing Partners). Separately, they manage 100+ doors for other owners (e.g. Northridge in Ridgway, Maplewood Village in Lakewood) — likely where the rest of Hugo's ~1,000 lives. A Lakewood-cluster overlap check against their AppFolio property list (ask at the whiteboard) would close the count for good.
Requirements ledger — traced to source
#
Requirement
Source
MVP?
R1
After-hours/weekend answering: Clara answers everything, takes messages, retires their MCC line; emergencies port out through their tree
Hugo email Aug 27
MVP
R2
Business hours: their phone tree first; Clara possibly IN the tree as overflow "when all lines full"
Hugo email Aug 27
MVP
R3
Emergency routing correctness is the trust-maker: "somebody calls and there's a fire, a flood… what does it do?" — triage which property + which unit immediately
Hugo, Aug 25 demo
MVP
R4
Property disambiguation first: one number, no leasing offices — "the first thing would be clarifying which property, which address"
Hugo, Aug 25 demo; Fede
MVP
R5
Every taken message → the one plain email (answering-machine bar: who/when/their words/their number, property named loud in the subject)
Fede rulings Aug 30–31
MVP
R6
Portfolio-level policies with per-property overrides (e.g. concessions differ at 75% vs 98% occupancy)
Hugo, Aug 25; Fede
MVP (settings chain)
R7
Spam filtering before Clara answers (~50% of calls)
Hugo, Aug 25
early
R8
Renewal term-steering: offer odd terms (e.g. 15-month) to land renewals in their Q2 window — "we have a hard time in our system of how we do that"
Hugo, Aug 25
phase 2
R9
Rent floor: never offer a renewal below current rent; guard against bad AppFolio data ("fat finger… catastrophic")
Hugo, Aug 25
phase 2 gate
R10
SMS/call records written back into AppFolio so the tenant communication record stays whole
Spanish-language support across channels (~70% of families)
Hugo, Aug 17
verify existing coverage
R13
Escalation notifications as text option; renewal re-send on request
Miriam, Aug 25
later
R14
Cross-sell a NEARBY sister property when inventory doesn't match (needs geo data); never confuse inventory between properties ("Lowry doesn't have any studios")
Fede (future); Miriam (the confusion risk is MVP-relevant)
future — explicitly not MVP
Their new phone system — Crexendo (what it can and can't do for us)
What it is:Crexendo (Nasdaq: CXDO) cloud business phone service; their retail product is called VIP, built on the NetSapiens platform Crexendo acquired in 2021. Sold in three per-seat tiers; a ~30-person shop with per-staff direct numbers most likely lands on a mid/upper tier — ask Eileen which tier, it decides whether call queues are included.
Confirmed from their docs — works for us: auto-attendant menus can route to an external number (the hook for putting Clara in the tree or forwarding after-hours out); time-of-day routing ("Time Frames"/Schedules — business hours vs after hours vs weekend, admin-configurable, no code); ring groups with simultaneous ring and configurable timeout; hunt groups explicitly allow non-Crexendo members (cell phones, external lines); per-user direct numbers are native.
Not confirmed — the whiteboard questions: (1) can a queue/ring group overflow directly to an external number on no-answer (docs only list internal destinations; the likely workaround is queue → auto-attendant → external); (2) can voicemail be turned off per line so no-answer rolls to Clara instead of their mailbox — the single most important unknown for Variant A; (3) does the original caller's number pass through on a forwarded call, or does the Crexendo number replace it — Clara identifies callers by caller ID, so this needs a live test call the day their numbers are up; (4) whether the underlying platform's API/webhooks (real-time call events, call records) are exposed to customers — if yes, we can detect "their side rang, nobody answered" programmatically.
Routing blueprint — two variants to whiteboard with Eileen
Variant A — their tree first (Hugo's words): the new Crexendo system runs business hours; Clara is a node in the tree (overflow when all lines are full, and the after-hours answer-point). Least invasive; depends on what their tree can do (overflow rules, time-of-day switch to Clara).
Variant B — permanent forward to us: their number forwards to us permanently; business hours we ring their staff (direct numbers exist in the new system — no loop risk) with a ring cap, no answer rolls to Clara; after hours Clara first. Buys full recording and control of every call — the same mechanism Camellia already runs on (its landline forwards to us permanently).
Either way: emergencies port out through their tree/on-call (R3 is the trust-maker — build the emergency path first and prove it on the harness), and every taken message lands as the one email.
New settings this needs: answering mode (clara-first / human-first / in-tree), ring cap, direct line(s), weekend emergency number — resolved portfolio → property.
Architecture audit — findings (2 of 3 dimensions in; renewals/knowledge/team in flight)
The good news is structural: the two hardest pieces are already half-built and were never wired up. The codebase contains a declared-but-never-read "organization settings" tier (the portfolio-defaults socket) and a working "conversation without a property yet" lane with a one-way bind — the exact primitive "which property are you calling about?" needs. And person identity is already org-scoped and multi-property-clean (one human across 40 buildings = one record; a STOP at one building already suppresses portfolio-wide). Yale in production is the preview of the risk: it isn't configured differently from Camellia — it's simply unconfigured, with every feature silently dark and escalations resolving to nobody. That is the day-one state of 38 Situs buildings unless the portfolio tier exists first.
The modes catalog (what needs a switch vs. what's just better for everyone)
Mode 1 — Portfolio line: a phone number / mailbox binds to the ORGANIZATION, not a property. Changes the greeting ("Clara at Situs Group — which community?"), makes a property-less lead legal, and binds the property mid-conversation. Voice mechanics: a portfolio greeting agent that asks, then TRANSFERS to a property-bound leg (variables carry across transfers; mid-call re-personalization doesn't exist and shouldn't be invented).
Mode 3 — Shared team calendar: one touring calendar across buildings with travel time, vs. per-property calendars.
Universal (no switch, better everywhere): portfolio defaults with property overrides for settings/policies/escalation contacts/specials/timezone — copying the ONE working portfolio→property resolver already in the code (the preferred-vendors chain); stamping the organization on every conversation at intake; keeping geo coordinates at onboarding (they're currently received from Google and thrown away — and nearby cross-sell needs them later).
Top blockers (from ~40 findings, each cited in the audit reports)
A lead that hasn't named a building cannot be saved at all today — the code throws. Property-less-then-bound must become legal end to end.
The shared inbound line resolves to one property or none — and "none" means a real caller gets silence. The portfolio-line mode replaces that fail-closed refusal.
One shared team mailbox connected to multiple properties would drop every inbound email (the mail subscription may only belong to one property today).
~24 per-property feature switches and ~20 config fields each need 40 hand-writes per building — the repo already deleted four such flags once because "16 of 17 properties sat silently dark." Portfolio defaults fix this class.
Property timezone has no writer in the app — unset silently defaults to Central time (the 7am-text incident). Must become a required onboarding field with an org default.
Knowledge is populated only by a website scraper — and most small Situs buildings have no website. A non-scraper onboarding path is a prerequisite, not a nice-to-have.
No concept of a team exists. Every notification resolves to ONE email address string; there is no staff group, on-call rotation, claim/acknowledge, or "I've got it, everyone stand down." Ironically, vendors already have the exact membership model staff lack — it just needs mirroring. Until then, a central team is expressible only as a shared mailbox.
The central-team surfaces refuse portfolio operation: the renewals board demands a single property (a 40-chip picker wall for Situs); approvals are one click per tenant with no batching; the owner report sends 40 separate Monday emails; the settings page silently edits whichever property sorts first. The underlying math already aggregates — only the surfaces refuse.
Spanish gaps that matter here specifically: the one voice agent a shared portfolio line would use has no Spanish configuration; renewals are English-only; and the anti-fabrication guards (e.g. voucher claims) have no Spanish patterns — weakest in the language ~70% of their residents speak.
Four live bugs found regardless of Situs (each small, each worse at 40×): every vendor call claims "the unit is vacant"; voice reads out policies the team explicitly retired; outbound caller ID is a 3-entry hardcoded map (inbound is already data-driven); and a building missing its renewal-policy row is silently skipped forever.
Scale reality check: the metric snapshot job already blew its time ceiling at ~7 properties; the report crons run serially and on timeout silently skip the properties at the end of the list while reporting success.
The onboarding checklist (portfolio client) — fields that fail silently when missed ★
Org level (none of these have a home yet — the portfolio tier creates it): ★ the residential emergency line (their commercial line stays outside our scope — multifamily only) · ★ escalation recipients as a TEAM with coverage windows · ★ ops-alert recipients (today emergency failures page PropFlow, not the customer) · ★ default renewal policy incl. the rent floor and target expiry window · default spend thresholds, office hours, language · portfolio knowledge (policies true everywhere) · owner-report recipients.
Per property, never defaulted: ★ organization link · ★ capability stage (absent = fully LIVE — a bulk import today would mint 40 live buildings where escalations reach nobody and a life-safety page dies in a logging tool) · ★ office hours (absent = after-hours 24/7 = routine calls hit the emergency line) · ★ timezone · ★ state code (renewals hardcode Colorado) · ★ a renewal-policy row · ★ a knowledge row even if empty (without one the building can never be taught anything) · ★ outbound phone number · emails/phones/thresholds per the full audit.
Steps: a bulk onboarding path (today it's one-at-a-time UIs and engineer scripts — 40 × ~15 fields is not a manual job) · a mandatory non-scraper knowledge step (~38 of 40 buildings have no website; doc-upload and manual editors exist, they're just optional and one-at-a-time) · Spanish config on the portfolio-line agent · metric backfill so the first owner rollup isn't empty.
Hard constraints already verified
AppFolio write-back (R10) is narrower than Eileen hopes: the partner API writes leads, work orders, showings and a few billing objects — no notes, tasks, guest-card or message endpoints exist. Even EliseAI falls back to emailed CSVs on AppFolio. Strategy (Fede, 2026-08-31): build an L4 read/write path — the browser-automation runner (the same proven pattern as Camellia: official API where it exists, our authenticated web agent for everything AppFolio won’t expose) writes texts/calls into the AppFolio tenant communication record directly, satisfying Eileen’s requirement without waiting on AppFolio’s partner program. Official API still used for what it does support (leads / work orders / showings / reads). Scope extension (Fede): L4 also READS AppFolio Messages — their portal/text/email threads (which the reads API verifiably does not expose; KB-checked) — and ingests them into Clara’s regular conversation timeline as a new PMS source (provenance-stamped source: appfolio). One unified thread per person across every channel, both directions — the thing even EliseAI can’t do on AppFolio. Open blocker: confirm their AppFolio plan tier (Plus?) — asked internally Aug 26, never answered.
Their office line (303) 789-3030 is hosted business VoIP (Level 3) — no personal-cell failure modes; behavior after N rings unknown until asked.
Open questions for the whiteboard
AppFolio plan tier / API access — answered Sep 1: no API access on PropFlow's user; the authenticated browser session (L4 pattern) is the data rail for both reads and any future writes.
What can their Crexendo tree do: overflow-to-external, time-of-day routing, DID list, voicemail-off per line, caller-ID passthrough on forwards? (Decides Variant A vs B.)
Emergency on-call design: who's in the rotation, weekend number, acknowledgment expectations.
MCC line specifics: what number, what happens to it today, cutover order (Eileen wants MCC last, "when we work out the rest of the bugs").
Unit-count close-out — partly answered Sep 1: their AppFolio holds 72 properties / 645 active units (Situs database only; Western Slope / Grand Junction is a separate AppFolio instance). Still to reconcile against the 434-metro enumeration and to identify which of the 645 shouldn't count (office, sold, side-managed).
Data cleanup plan: Hugo owns "part of that data cleanup is on us" — what do we validate before renewals ever run (R9 gate).
What it takes to light up leasing calls at ONE property (Fede's ask: everything off by default)
58 things: 16 switches + 30 config fields + 12 knowledge sections. And the headline: six of them aren't data — they're source-code edits requiring an engineer and a deploy (the phone-number→agent map, the outbound from-number map, the "call Clara" map, the listings-sync list, the website-scraper registry, and the tour-window allowlist — two of these are literal arrays naming Camellia and Yale in the code). A new property cannot be turned on by configuration alone today. For Situs that's the onboarding product to build: portfolio defaults + data-driven registration, so lighting building #23 is a form, not a deploy.
The proof is live in prod: Camellia carries 61 configured attributes; Yale carries 27. Yale can answer a leasing call but cannot confirm availability, book onto a calendar, send an application link, text or email anyone, or reach a human by email. That's "unconfigured = dark," measured.
The seven stages, in dependency order: ownership + timezone → phone line (carrier text registration — Yale's is verified and live as of 2026-09-04, per the go-live readiness ledger; note: Yale's toll-free number currently has no webhook attached) → knowledge (12 sections) → availability/pricing → tour booking → confirmations/lead-saving/follow-up → human escalation. Full 58-row table with file-level gates lives in the session audit; each row names its silent-failure mode.
Portfolio-defaults recommendation: tour conventions, follow-up timing, escalation style, the caller-loop switches, and rollout ratchets move to the org tier (set once, inherit); the building keeps only what IS the building — its number, calendar, mailbox, hours, specials, fees, units, PMS pointer.
Five defects to fix before ANY new property turns on (found by the inventory, live today): 1 · empty specials are spoken as an affirmative "there are no specials"; 2 · an empty transfer number is dialed anyway (every other transfer lane guards this; the main leasing one doesn't); 3 · an escalation with no recipient still tells the caller "I've flagged this for the manager" while reaching no one; 4 · voice confirms tours out loud even when no calendar exists to write them to; 5 · the "shadow stage" safety control for leasing reads as a brake and is actually connected to nothing.
Renewals — explicitly NOT MVP (phase 2)
Hugo's two renewal asks are real requirements (R8, R9) but they ship in a later phase, after the leasing/answering MVP is live and after his AppFolio cleanup. Parked here so the MVP scope stays clean:
Term-steering (R8): offer odd lease terms (e.g. 15 months) so renewals land in their preferred Q2 expiry window — "we have a hard time in our system of how we do that." Today term options are a fixed list, priced identically; steering has no home in the product yet.
Rent floor (R9): never offer a renewal below current rent. Today there is no rent-floor gate anywhere: offers build from a single synced rent field that falls back to zero, so a stale AppFolio number could produce a below-current or $0 offer with nothing in the path to stop it — exactly the "fat finger… catastrophic" case Hugo named. The floor gate is the first renewal build, before any steering.
Data dependency: their AppFolio data is ~7 years old and self-described messy; Hugo owns the cleanup. Renewals never run at Situs until the floor gate exists and the data behind it is validated.
AppFolio access, the data dump, and multi-client isolation (Sep 1)
The full findings report is out:Situs Group — What the Records Show (2026) — owners' priorities (call center, after-hours), leasing proposal, renewals proposal, billbacks, inspections, vacancy vs website, communications, collections, data quality, shadow systems, and what this corpus can do for Clara. Every number computed on the 2026 window only. The raw data package (81 MB, contains PII) is in Fede's Drive, owner-only.
We are in. PropFlow's Clara login now opens Situs's AppFolio database directly (same login as JP's — one account, two databases). No API access on that user (confirmed). A read-only browser session is the only data rail, and a one-time full dump of how Situs operates is underway.
First numbers straight from their reports: 72 properties · 645 active units · 132 vacant/notice (125 vacant-unrented) · 420 active leases, 55 expiring within 90 days · 1,655 renewal-outcome rows since mid-2023 (outcomes are recorded in AppFolio; the offer/pricing policy lives outside it) · 19,825 work orders all-time, ~15–20/day, 200 recurring templates.
Website vs. system: the public availability page shows 28 listings; 8 units AppFolio marks "posted" don't appear correctly, and the two verified causes are address typos inside AppFolio (375 vs 385 S. Depew; 1375 vs 1385 Everett Ct). 103 further vacancies are unadvertised by design or neglect — a question for the team.
How they operate, as evidenced by the logs: AppFolio's own bots ("PM Assistant", "Maintenance Performer") already triage, assign and sometimes resolve maintenance tickets; the stall point is assignment (one ticket sat 2.5 days over a weekend); purchase-order/invoice sections were empty on 12 of 12 work orders opened (the billback gap, on paper); the built-in tasks feature is unused (12 records ever); guest-card showing confirmations are templated and fast, Spanish threads are human and slow; applications mostly run in outside tools (TurboTenant, Tenant Turner, AffordableHousing.com) — AppFolio sees a slice.
Dump status (final, Sep 1 night): collection complete — 2,588 work orders, 201 inspections, 883 guest cards, 90 applications, 825 calendar events, 143 renewal rows, 1,418 tenant timelines (2026 scope; current tenants + 2026 move-outs). A 2025 pull is running so the report can carry a year-over-year section; cutoff 2025-01-01.
Hard rule: read-only. Nothing in Situs's AppFolio is created, edited, sent, saved or scheduled by PropFlow until Fede explicitly authorizes writes. Also: one Situs session at a time — four parallel scout sessions on Sep 1 invalidated each other (the same failure the JP runner's July postmortem describes).
Multi-client isolation — decision doc (Proposed — pending Fede's review, Sep 1). Both codebases were mapped end to end (runner + PropFlow). Finding: a Situs AppFolio write dispatched today would land in JP's database, silently. The write path carries no database identity anywhere — payloads name a property by its bare AppFolio number (which exists in both databases), the runner resolves its target from one deployment setting whose default is jpco, its session self-heal reconnects to that default mid-job, its login lock and cookie hand-off are keyed by the email (shared by both databases), and one browser identity serves everything. Nothing is missing that would have to be missing — the gap is unconditional. Reads are the only correctly scoped path (per-property owner → credential row → database).
The invariant: every AppFolio call, read or write, runs against a database derived from the property being worked on, and the runtime refuses any call whose destination doesn't match. Prevention by construction, not convention.
Layer 1 — identity on the record. Stamp pmsIdentity = "appfolio:<database>" on every Property and Organization at onboarding (PurchaseOrder already does exactly this — the one entity that is immune today). Never derive the database indirectly via the owner's credential row.
Layer 2 — the contract. Every runner request carries a required, non-defaulted accountId (the database). The runner rejects requests without it. The SQS job envelope already has the field and a per-account FIFO group — today it is filled from one global env var and then discarded by the handlers; it becomes property-derived and threaded into the L4 body at the single chokepoint every wrapper passes through (callL4Once). Every ?? "jpco" fallback (Lambda consumer, Clara renewal handler, runner resolver) becomes a hard failure.
Layer 3 — runtime guards in the runner. (a) The target resolver requires an explicit subdomain in production; (b) switch on the existing dormant "tenant guard" (asserts the browser actually landed on the expected host); (c) bind session self-heal to the request's database, never the env default; (d) add a request-level host guard: any outbound call whose host ≠ the job's database is refused and alerted; (e) sessions, cookie jars, browser contexts, credential cursors and lock keys all keyed by credential + database; the login-lock hand-off must verify the jar's host equals the waiter's host; cookie harvest filtered to the exact host, not the appfolio.com family; keep-alive crons run once per database.
Layer 4 — one login per client. AppFolio keeps one active session per login per database (verified Sep 1: sessions killed each other; a human on the Clara login kills the bot's session in seconds). A dedicated AppFolio user per client database (Situs creates one for PropFlow, view-only for now) removes the shared-lockout blast radius and is the only way to run sessions in parallel.
Layer 5 — namespace the ids. PropFlow property row ids (appfolio-<id>), the vendor partition key (vendor_appfolio_<id>), work-order reconcile indexes, the person-claim global index, idempotency keys, test/allowlist ids ("45", "7") are all bare AppFolio integers — a second database collides on every one. New records get pmsIdentity in the key; legacy JP rows are guarded, not migrated, until a migration is scheduled.
Layer 6 — enforcement that stays on. Extend the existing customer-identifier fence test (three of these defaults are already listed there as dated debt) and the renewal-bootstrap canary (already has an "account axis" that reads NO-GO today) so regressions fail CI, not production.
Immediate safety (before anything else, one small change): PropFlow refuses to dispatch any AppFolio write for a property whose pmsIdentity isn't the runner's configured database. Situs has no PropFlow properties yet, so today's exposure is zero — this guard keeps it zero the moment Situs properties are imported, while the layers above are built.
Decisions for Fede (recommendation first):
D1 · Login model: (A) dedicated AppFolio user per client database — recommended (kills the shared-session collision, enables parallel sessions, cleaner audit trail in the client's AppFolio); (B) keep the one Clara login, isolate by database only (works for correctness, keeps the one-session-at-a-time ceiling and the shared lockout budget).
D2 · Where the database lives: (A) on Property + Organization as pmsIdentity — recommended; (B) keep deriving it through the owner's credential row (today's read-path model; structurally one-user-one-database, so it cannot express one login on two databases without a second user anyway).
D3 · Rollout order: (A) block first, then thread — recommended (the immediate-safety guard + runner rejects requests without accountId, then thread the field through every path; nothing Situs-facing reaches the runner until both halves exist); (B) thread first, enforce later.
D4 · Id migration: (A) namespace new records, guard legacy — recommended; (B) full migration of JP data now.
Sources: seam maps of appfolio-browser-agent and propflowai (Sep 1, file:line inventories in the session); runner postmortem of the 2026-07-02 Camellia renewal outage (concurrent-login session invalidation); Sep 1 Situs scout sessions.
Clara texts and emails from inside AppFolio (prototype, Sep 3)
Prototype complete and proven end to end at the Willows (text and email), shipped dark. Activation for Situs needs Fede's go.
Two-minute read. Right now Clara texts and emails Situs's prospects and tenants from PropFlow's own phone number and mailbox — a second channel, separate from the AppFolio inbox their staff already use. This prototype gives a property a choice: keep that (direct), or have Clara log into AppFolio as a real staff member and send the message from inside the guest card, the exact same box Situs's leasing team uses today (pms). Either way, every existing safety check still runs first — consent, quiet hours, opt-out, the escalation hold — nothing about where the message leaves from changes what's allowed to be said or when. A second small piece reads every message back out of AppFolio (both the ones Clara sends and the ones a human on staff sends) so PropFlow's Conversations page shows one whole thread per person, not just Clara's half of it.
The one-sentence invariant: a property either delivers Clara's messages itself or hands them to its PMS — one property setting, one seam, every existing gate still runs first.
The simplest mechanism: a setting on the property says which door Clara's messages leave by. When it says "hand it to AppFolio," a browser-automation robot (the same proven pattern already used for Camellia's work orders and renewals) logs into AppFolio as a named user and clicks "Send" on the guest card, exactly like a human would. Separately, a poller checks AppFolio every couple of minutes and copies every message it finds — Clara's and the human staff's — into PropFlow's own conversation record, so nothing needs to be re-typed and the thread stays whole no matter who answered.
Why it matters for Situs
Situs's ops lead Eileen named this directly as requirement R10 in the ledger above (Aug 25, quoted verbatim there): "SMS/call records written back into AppFolio so the tenant communication record stays whole." On Sep 1, in the room with Fede, the team went further and decided the shape of it. Fede's proposal, stated to Eileen: "the agent operates as a named user inside AppFolio, writing back every action like a teammate" — "I'm not trying to recreate AppFolio, I'm recreating what the human does outside the system and writing it back." Eileen's reaction is recorded as enthusiastic ("explicitly loved the write-back and activity-log model"). The meeting's own decision line, verbatim: "PropFlow writes everything back into AppFolio as a named agent-user with a visible activity log — no parallel CRM, no new software for staff to learn." This section is the engineering shape of that decision, extended one step further: Clara doesn't just write records back after sending elsewhere — for a pms-delivery property, AppFolio is where the send happens.
Transition strategy — humans and Clara side by side, then Clara takes over the routine work
Step 1 — backfill. The same reader that will later poll for new messages runs once over history first, so every existing AppFolio thread shows up in PropFlow's Conversations page before Clara ever sends anything. Nothing is invented — messages are copied with their real sender and timestamp.
Step 2 — side by side. Once backfilled, a human's texts and Clara's texts land in the same PropFlow thread, each correctly labeled who sent it. Staff keep working exactly as they do today, inside AppFolio; Clara's messages simply start showing up in the same place, instead of a second, separate PropFlow-only thread.
Step 3 — Clara takes the routine work. As trust builds per property, Clara is given more of the day-to-day messages (after-hours answering, routine follow-ups), the same way she already does today directly.
The "human has the thread, Clara stays quiet" rule carries over unchanged. PropFlow already has this rule for its own channels — when a thread is escalated to a human, Clara goes silent on it rather than talking over them. That same hold applies here: if a Situs staff member is actively handling a thread, Clara does not also jump in on the AppFolio side of it. No new mechanism is needed — this reuses the existing escalation hold that already gates every other channel.
Decisions for Fede (recommendation first)
D-A · Does the earlier "don't write to AppFolio" decision need to change? (A) amend it to allow this — sending a message counts as "handing it to the PMS to deliver," not as PropFlow creating its own duplicate prospect records — recommended; (B) leave the earlier decision as-is and only ever send Clara's messages directly, never through AppFolio; (C) hold off and decide later, after the Willows test.
D-B · Where does the on/off switch for a property live? (A) a top-level property setting, next to the property's other core identity fields — recommended (it needs to be checked every time any message goes out, for both leasing and, later, maintenance — not just leasing); (B) inside the property's leasing-specific settings only.
D-C · Which AppFolio login does Clara send as? (A) a dedicated login created just for Clara at each client, named something like "Clara / PropFlow" — recommended (staff can see at a glance which messages were Clara's, and replies route correctly — see D-D); (B) one shared PropFlow login used for every client; (C) log in as one of the client's own staff members' accounts.
D-D · A wrinkle in how AppFolio routes replies. AppFolio notifies whoever most recently texted a prospect from that number when a reply comes in — not necessarily the staff member assigned to that person. Once Clara starts sending, Clara becomes "whoever most recently texted" for those conversations, which means a staff member who used to get notified might stop. (A) accept that Clara becomes the notified party, and have PropFlow surface every reply to the team through its own Conversations page — recommended; (B) deliberately keep a human as the last sender on every thread so AppFolio keeps notifying them (workable, but works against the goal of Clara actually handling routine replies); (C) ask AppFolio support if this can be changed.
D-E · Work orders (vendor/maintenance messaging). AppFolio's work-order messaging is a genuinely different feature from the guest card — a group text thread with a temporary masked number, not a simple "send as yourself" box. (A) treat it as its own project with its own design, later — recommended; (B) try to fold it into this same build now.
D-F · How fast should replies come back? Replies only exist in AppFolio, so PropFlow has to check for them rather than being told instantly the way a text message normally works. (A) check every two minutes — recommended for routine leasing follow-ups, where a couple of minutes' delay is fine; (B) check more often, at higher engineering cost; (C) first spend time checking whether AppFolio can notify PropFlow instantly instead (unconfirmed either way).
D-G · Staff-owned threads — Clara stops when a human replies. Decided: the MVP rule is that once a staff member — not Clara — replies on a conversation, Clara stops auto-replying on it. No timer, no auto hand-back yet. Shipped dark in PR 6870, live only on properties set to send through the PMS. Still open — how does a human hand the thread back to Clara? (A) a staff member clicks an explicit "release to Clara" action inside PropFlow — recommended; (B) release it automatically after some number of days of staff silence; (C) never auto-release — always manual.
D-H · Activation: turn PMS delivery on for Situs (currently Willows only; Situs AppFolio remains read-only until then). Recommendation: first one Situs property, texts only, with a Situs staffer briefed that replying in AppFolio stops Clara on that thread.
Rollout — the standard three-step playbook
Step 1: ship the setting turned off everywhere (dark). Step 2: turn it on only for Fede's own test record at the Willows, using Fede's own phone number and email for both directions, and prove it end to end. Step 3: turning it on for any real client, including Situs, happens only with Fede's explicit go — building it is not the same as activating it.
Two things Situs (or any client) must already have turned on in AppFolio before this can work at all — neither is a PropFlow setting, both must be confirmed live before a real send:
☐ Company-level texting is turned on, which requires their carrier-compliance registration (a signed-off filing proving who they are, done once by someone at President level at the company) — without it, carriers block the texts outright.
☐ Two-way texting is turned on — a separate toggle from the one above. Without it, AppFolio never shows replies coming back in, which would make the whole "read messages back into PropFlow" half of this feature silently do nothing.
Compliance pass, done tonight: ran the same legal-consent check PropFlow already uses for all outbound texting against this specific design. Short version — the earlier concern that blocked writing to AppFolio (that a prospect's consent doesn't automatically transfer to a brand-new phone number) mostly doesn't apply here, because Clara would be sending from the same AppFolio number the consent was already captured against, not a new one — though that reasoning should get a lawyer's sign-off before turning this on for a real client, not before the Willows test. Everything else stays exactly as strict as it already is: what Clara's allowed to say (informational vs. promotional), the quiet-hours window, and honoring opt-outs all still have to be checked by PropFlow before every send, the same as today — AppFolio being the messenger doesn't relax any of it. One new wrinkle: opt-outs in AppFolio are tracked by phone number, not by person, so PropFlow's own do-not-text list needs to match that shape for this specific delivery path.
What was proven today — the closed loop, start to finish
Status: the full loop works, tested at the Willows. A prospect can text the client's AppFolio number, PropFlow can pick it up, Clara can write a real reply, and that reply can go back out through AppFolio — landing on the prospect's phone and in AppFolio's own history, as a message from Clara's seat. No customer property is switched on.
Test set-up: our own Twilio phone number played the prospect, texting into guest card 58 on the jpco test property (the Willows) — nothing here touched a real person or a real client.
Step
What happened
Time (UTC)
1
Test text sent, playing the prospect
19:07:01
2
AppFolio recorded it on the guest card
19:07:02
3
PropFlow's routine check-in picked it up and filed it
19:07:29
4
Clara woke up
19:07:29
5
Clara wrote her reply
19:07:54
6
The reply went into AppFolio
19:08:32
7
The reply reached the prospect's phone, sent from AppFolio's own number, +1 504 608 7154
19:08:39
8
The outbound message showed up in AppFolio's own history for that guest card
19:09:20
Total time, text sent to reply received: 1 minute 38 seconds. About a minute and a half of that is just PropFlow waiting for its next routine check-in, which currently runs every 2 minutes — once that check-in runs more often (see below), most of this delay goes away.
What we fixed today
Clara's wake-up was checking the wrong phone number, so a reply couldn't reach her the normal way. (PR 6865)
Clara's context now names the staff member she's talking to, instead of just showing a phone number. (PR 6866)
Clara now stops replying on a thread the moment a real staff member jumps in — see decision D-G above. (PR 6870)
An incoming text was getting filed onto an old, unrelated thread instead of the lead's real one; it now lands on the right thread, and if filing ever fails, that failure is logged instead of disappearing silently. (PR 6901)
Clara's reply wasn't carrying along which property it belonged to, so it couldn't find the right delivery door and went out the wrong way. Fixed. (PR 6904)
Which AppFolio account to send through now comes from the property itself, and Clara refuses by name — instead of guessing or crashing — if a property has none set. (PR 6896 / 6924)
What landed after the first proof (Sep 3, evening)
Email replies now wake Clara and her answer goes back out through AppFolio. Proven live at the Willows: prospect email in → Clara's reply sent through the AppFolio guest card in 54 seconds, exactly one reply, nothing sent from our own mailbox.
Finding: AppFolio does not file a prospect's emailed reply on the guest card. It forwards it to the sending seat's mailbox. So for email, the connected mailbox is the real inbound door; the guest-card feed is only for texts. Other AppFolio accounts (including Situs's data) do show received emails on cards, so this is account-configuration dependent. No AppFolio settings were changed.
The "stop when a teammate replies" rule was written correctly but never read on Clara's own reply path (text or email). Both are fixed and proven offline. The live stop cannot be demonstrated without a real teammate's AppFolio seat, which we don't hold.
A regression harness now runs the whole text back-and-forth offline on every code change (8 active scenarios, each also run under a deliberate break to prove the test can fail), plus a live mode against the Willows only. Live mode passed clean on the final code.
Coworker emails at a PMS-delivered property keep going through our own email, never the guest card (a coworker has no guest card).
Four data-level bugs fixed along the way: a texts-only property treated its entire email history as "new"; an unattributable AppFolio email could silently mute Clara; staff addresses in "Name <address>" form weren't recognized as staff; the stop rule was checked under a narrower condition than it was written.
Known limits / what's next
Replies can take up to 2 minutes to reach Clara, because PropFlow only checks that often right now. Before this can run faster, or handle Situs's real scale, the check needs to read AppFolio's whole inbox at once instead of walking every guest card one by one.
That faster, inbox-wide check hasn't been tested yet on threads that belong to other staff members, not just Clara's.
When a staff member texts Clara directly, it always goes out over PropFlow's own phone line, never through AppFolio, even on a property set to deliver through the PMS. Is that OK, since it's staff talking to Clara rather than Clara talking to a prospect? Needs a decision.
By design, one old escalated thread on a person outranks every other active thread for that person — but in practice, one forgotten escalation can silence every new message from them. Working as designed, but worth a second look.
When Clara's reply gets read back out of AppFolio, it currently files onto a different conversation record than the message it was answering. Nothing is lost — the send itself is proven — but it splits one exchange into two records on the page. Tracked, cosmetic.
A problem on a test property can still page the team as if it were a real production emergency. Needs its own fix, separate from this feature.
The deploy system's "Deploy Lambdas" status can say a change went live when it actually hasn't — always double-check against the live code running in production, not the status label.
The stop-on-teammate-reply rule has no live proof (needs a second AppFolio seat).
The 2-minute poll cadence before Situs scale.
Containment check, live scan 2026-09-03 17:38 UTC: only the Willows (our own test property) has the AppFolio delivery switches turned on. Yale 25 Station, Camellia, and the Yale sandbox are all off, sending the normal direct way.
Engineering references: extends ADR-0094 (guest-card sync); design notes and code-path inventory held in the working session's research files, not duplicated here.
Delivery plan (Fede, Sep 3 — supersedes the Aug 31 phase list)
Sequencing as Fede set it on Sep 3, after the Sep 1 whiteboard with Eileen. Answers her "what would be best?" email of the same day. Sean's commercial proposal travels separately; this section is the operational half. The earlier Phase 0/1/2 list is retired — its content survives below where it still applies.
Timeline (September into early October)
When (MT)
What
Who
Sep 3–5
Preparation and research: learn how their centralized team handles calls, texts and emails across the portfolio today, so Clara works the way they work. Policy inference on the AppFolio data continues. Sean's commercial proposal goes out.
PropFlow
Sep 8–12
Set up phase 1 (Clara replaces MCC) on their portfolio — configuration, not new engineering. Stand up the QA environment: a separate phone line loaded with Situs's real portfolio data, plus a test property inside their AppFolio for dry runs. Nothing touches their live lines. Agree commercial terms.
PropFlow; Situs creates the test property
Sep 15–19 · Eileen back
Joint QA of phase 1 on the test line and test property, remote. Fix what QA finds. Policy-alignment session (the inconsistencies we found, one standard set for the portfolio). First weekly check-in.
PropFlow + Situs
Sep 22–26
Phase 1 goes live at the portfolio level (earliest; slips if QA finds much). Phase 2 set-up starts. Working session on tours: calendars, who covers which buildings, travel time, and how the agent knows what is actually available (today: the leasing team's whiteboard).
Fede flips it; PropFlow + Situs
Sep 29 – Oct 3
Phase 1 stabilizes on live traffic. Phase 2 QA on the test line. Weekly check-in.
PropFlow + Situs
Oct 6 onward
Phase 2 goes live at the portfolio level. Renewal-policy working session scheduled to open phase 3.
Fede flips it; PropFlow + Situs
Client-facing proposal lives at PropFlow × Situs Group — Proposal (iterate there; PDF once the dates settle). Keep this internal table and that page in step.
Phases
Phase 1 — replace MCC. Clara takes over what their call center (MCC, AppFolio's offshore maintenance intake) does today: takes maintenance requests 24/7, logs them in AppFolio, and gives residents status updates on request. Whatever MCC does, Clara does; nothing beyond that in phase 1 — no dispatch, no vendor coordination. (Fede, Sep 3. This overrides the atlas line that displacing MCC is "last, separately priced".)
Phase 2 — cover the leasing gaps: nights and weekends. Clara answers the leasing line and works guest cards after hours and on weekends, which today go to voicemail and to Monday. Business hours stay human. This is Hugo's Aug 27 "walk before run" ask; it moves to second because phase 1 is the safer first proof. Prerequisites (Fede, Sep 3): access to staff calendars, and a working session on how tours get assigned to staff — who covers which buildings, travel time between them, location — before Clara books anything.
Phase 3 — renewals. After phase 2 is live, Clara starts renewals (Fede, Sep 3: renewals here, not daytime leasing). Preceded by a renewal-policy working session to decide, portfolio-wide: notice timing (e.g. offers out 90 days ahead); how the increase / new market rent is set; how transfers work and whether they carry a fee, or an exception workflow instead; how negotiations and special cases are handled and escalated; dynamic lease terms (e.g. 14 vs 12 months) so leases end when Situs prefers. Build order per the not-MVP section above. Daytime leasing coverage is a later option for Situs to choose.
Running alongside
Policy alignment exercise. We have been inferring Situs's policies from their portfolio data (leases, addenda, settings, 2026 messages — see what Clara knows) and found inconsistencies between buildings and between agents. We present those and align with Situs on one standard set of portfolio policies, with per-building exceptions only where they differ on purpose. One working session.
Weekly check-in. One hour, same day each week (Situs picks the day), for the length of the rollout: progress, feedback on what Clara did, and priority alignment for the next week.
Access and inputs we need, by phase (Fede, Sep 3: commercial terms first, then access)
Needed for
What
Status
Before any access
Commercial terms agreed (Sean's proposal).
Proposal drafted Sep 3, not yet sent
Phase 1
AppFolio Reports API read access (Plus plan includes it; Situs requests from AppFolio, passes us the credentials). Needed to hook everything up.
Ask after terms
Phase 1
A test property created inside their AppFolio — the QA environment for every phase.
Ask after terms
Phase 1
The Excel / Google Sheets where they manage policies and anything else that lives outside AppFolio.
Ask after terms
Phase 2
Staff calendars, and the tour-assignment session (coverage by building, travel time, location).
Session on the timeline
Phase 2
Availability source of truth. Today it is a whiteboard in the leasing team's office. Options for making that visible to the agent so phone and guest-card answers are right need a discussion; no option chosen yet.
Session on the timeline
Phase 3
Renewal-policy working session (topics above).
Session on the timeline
Closed: AppFolio plan tier = Plus (Fede, Sep 3). VA after-hours coverage — answered by the data: after 5pm every intake channel waits 11–16 hours for a human, 7 after-hours calls logged all year (findings). Neither is a question for the client.
Coverage check — what they asked for vs. this plan (sweep of Aug 17, Aug 25, email thread; Sep 1 via the quoted deep-dive, raw canvas unreadable)
Three contradictions to name in the reply. (1) Eileen, Aug 25: do MCC last, after AppFolio write-back bugs are worked out — Hugo's Aug 27 email says first; the plan follows Hugo. (2) Their phone system is mid-rebuild; Eileen asked us to build in concert with it — plan is silent. (3) Sean promised a few months of human review before autonomous sends — plan is silent.
Asked for, not in any phase: move-outs and tenant billbacks (Eileen's #2 ROI) · Spanish and language-preference tagging (every meeting; Colorado requirement) · email/text lead response incl. the affordable-housing inbox and Zillow/apartments.com · full conversation write-back to AppFolio with Clara as a named user (Eileen's first demo question; plan only covers maintenance) · the "quarterback layer" — stale-data detection + threshold alerts to the GPs, who never open AppFolio · spam filtering · vendor payables calls · record and score the VAs, never the on-site staff · Grand Junction / Western Slope demo · Hugo's appliance-QR idea and proposed trade · the prep checklist Eileen asked for by name (clean rent roll, verified availability, contact data) · application-pipeline visibility and duplicate-applicant detection · lead-source attribution · collections (we offered; they never asked — say so or drop) · consent/10DLC hygiene before renewal nagging across ~932 tenants.
Retracted figures, never client-facing: ~1,000 units, ~70% Spanish, ~50% spam, 20 work orders/day (measured ~10.6/day YTD), the "40 vs 128 hours" framing, the Crexendo name. Full itemized list with quotes lives in the Sep 3 sweep output; ask Fede's session for it.
Client-safe version (what goes to Eileen)
The hub is internal. The email carries: the three phases in plain words, the timeline, the QA setup (test line with their real data + a test property in their AppFolio as the dry-run environment, portfolio-level switch to go live), the policy-alignment session, the weekly check-in, and a link to the client-facing 2026 snapshot of what the data shows. No access asks in the email — those follow commercial terms. Nothing about price, walk-away lines, staff judgements, or how the deeper data was obtained.
Still true from the Aug 31 plan: missed-call lane proven on Willows first; R1–R6 (after-hours answering + message email + emergency porting + property disambiguation + settings chain) are the phase-2 build list; future items unchanged — nearby cross-sell, Grand Junction rollout, appliance-QR pilot.
Sources
Hugo email Aug 27 ("Re: PropFlow Demo") · raw Aug 25 demo transcript (Otter; speaker-label caveat: only Eileen and Miriam cleanly separated — Hugo quotes used here are first-person operator statements only he could make) · raw Aug 17 intro call · Slack threads C0BE1NFTA0K/1787694928 & 1787004169 · sales console record · Twilio line lookups · Mesa/Jefferson/Adams/Arapahoe/Denver county parcel services · Colorado Secretary of State business registry · Crexendo/NetSapiens public documentation · the missed-call RCA & fix plan · knowledge at scale. Not yet reviewed: Eileen↔Fede Aug 27–28 email tails; meeting attachments (leasing one-pager, diligence PDFs).