0117 — Collections AI pilot: polite delinquency agent for online-portal payers at Camellia

Renumbered from 0112 on 2026-07-28 (collision: this file and 0112-tenant-collections-outreach-lane.md were authored in parallel under the same number, neither referencing the other; 0113–0116 are taken — 0117 was the lowest genuinely-free number at renumber time, following the 0113 precedent).

Relationship to ADR-0112 (tenant-collections-outreach-lane): the outreach mechanics of this ADR's Phase 1 were built under ADR-0112, which is authoritative wherever the two disagree about the SHIPPED lane (workflow shape, enrollment threshold, gate stack, copy, bake mode). This ADR remains the only record of the broader pilot program: Phase 0 language preference, portal-payer cohort strategy and portal-flag exclusions, promise-to-pay, measurement/kill criteria, counsel sign-off gates, and 10DLC registration. Four of this ADR's Phase 1 claims are not implemented in the shipped lane — each is flagged inline below with a ⚠️ NOT AS SHIPPED marker; do not read unmarked Phase 1 mechanics as a description of production either.

AMENDED 2026-08-19 — the INTERNAL demand builder moved to Phase 1. Decision page collections-three-phases, question d3, answered by Gera: "Pull it into Phase 1. It's the most demoable thing we could build for Hugo and it doesn't touch a resident." This is the single authoritative record of that change; the two places below that describe demand drafting as deferred now point here rather than restating it.

What moved. An internal tool that computes the demand's dates, checks it against the statutory element list, and fills a PDF for a human to print, sign and serve by hand. Built at src/lib/domain/compliance/collections/demand/. The driver is a documented, repeating failure: four Camellia demands bounced in April 2026 over a one-day date error.

What did NOT move — none of this is un-gated by the above:

  • No demand, and no part of one, is transmitted to a resident. Service is by hand under C.R.S. § 13-40-108, which does not list electronic delivery, and the module imports nothing that can transmit — pinned by src/__tests__/collections-demand-no-send.drift.test.ts.
  • The counsel gates on the resident-facing collections lane are untouched.
  • Guarantor contact, payment-plan self-service and outbound voice stay deferred exactly as written below.
  • The module's own counting rules are marked counselVerified: false and every packet says so, so nothing here asserts counsel review that has not happened.

Still open for a human: whether "counsel review of any future 10-day-demand drafting" was ever meant to reach an internal drafting aid that no resident sees, or only the resident-facing capability. Engineering has not decided that and this amendment does not decide it — it records the scope shipped so the question is answerable against something concrete.

Context

Why now

The Camellia realities we must design around (from 07-23 founders call)

  1. Money orders. A large share of residents are unbanked and pay by money order; paper takes ~a week from office to bank. Some split rent into two partial payments (e.g., on the 15th). A naive "you're late" ping will fire at people who already paid. Fede: "we might be calling someone, hey, you're late, but they already gave the check."
  2. Late-is-normal culture. "A lot of people are late. But that's kind of like the expected."
  3. Partial payments are a normal pattern, not an anomaly.
  4. Language: a meaningful share of residents are Spanish-preferring (07-23 morning JP call: mass-send about water shutoff went out in English to Spanish-speaking units; team agreed language preference + auto-translation is needed).
  5. Adoption: any feature requiring the JP team to maintain per-tenant config will rot. Config must be set once by us, with per-unit opt-out at most.

What the platform has today (verified 2026-07-23, repo inspection)

Exists and reusable:

Missing (net-new):

AppFolio mechanics that constrain the design (KB-verified)

Market mechanics worth copying / avoiding (research 2026-07-23)

Decision

We build a collections agent as a Clara capability ("rent reminders", never "collections" in any tenant- or PM-facing copy), piloted at Camellia on a deliberately narrow population, with tenant language preference shipped first. Gera owns the build end-to-end.

Phase 0 — Tenant language preference (prerequisite, ships first)

Per-tenant languagePreference ('en' | 'es', extensible) on the tenant record:

Phase 1 — Pilot population and trigger

Phase 1 — Cadence and content (the "not annoying" contract)

Phase 1 — Human-in-the-loop boundaries

The agent may autonomously: send reminders per cadence, answer balance/lease questions, record promises-to-pay, surface the portal link. The agent may never: mention or threaten eviction/legal action/credit reporting; state a late fee that isn't posted+lease-valid+cap-compliant; offer or accept payment-plan terms (pilot: plans are drafted as suggestions to the PM from a pre-approved parameter menu, human sends/enters them in AppFolio); waive anything; contact guarantors (post-pilot); touch the 10-day demand (post-pilot candidate: draft the demand for human review/service — never send). ⚠️ PARTLY SUPERSEDED 2026-08-19 — the INTERNAL demand builder shipped; see the AMENDED banner at the top of this ADR for exactly what moved and what did not. The "never send" half is unchanged and is now enforced structurally. Escalation to PM: dispute, hardship mention, opt-out, promise broken twice, day-22 reached (⚠️ not as shipped — there is no day-22 alert, per the cadence note above; the only shipped PM escalation fires on a tenant reply, ADR-0112 §3.5), any eviction/legal question, LEP conversation the agent can't hold.

Phase 1 — Data/infra build

Phase 1 — Measurement (proving "we can reduce delinquency")

Baseline locked before launch from ledger history (charge_detail, 12 months back):

Entity classification (per ADR-0027)

Entity Class Naming Spine trace (canonical) OR derived-from / rebuilt-by / drift-tolerance (derived)
CollectionsCase canonical bare name Spine trace: personId + propertyId; lifecycle events appended by the Temporal workflow
PromiseToPay canonical bare name Spine trace: via collectionsCaseIdpersonId
TenantLanguagePreference (field, not entity — lives on tenant record) canonical field languagePreference Spine trace: on the tenant record directly
PaymentHistorySnapshot derived *Snapshot suffix from: AppFolio receivables_activity/charge_detail rows · Rebuilt by: lambda/appfolio-sync · Drift tolerance: ≤1h (same as balance snapshots)

Consequences

Alternatives considered

  1. Whole-building blast with per-unit opt-out (Sean's first framing, 07-23). Rejected for the pilot: money-order timing makes false "you're late" pings likely, and false dunning is the single fastest way to burn resident trust and create UDAP exposure. Revisit once money-order logging latency is instrumented.
  2. Wait for Yale (build for a "normal" 95%-online property). Rejected: Camellia is live today, has real delinquency, and the harder constraint set produces a more general design; Sean's counterpoint ("built for the next people") is captured by keeping all thresholds per-property config.
  3. Fixed escalation ladder (3/6/15/30-style) as marketed by overlay vendors. Rejected: fights Colorado's 7-day grace and Camellia's norms; config-driven cadence matches what EliseAI/Colleen actually ship.
  4. Autonomous payment plans in the pilot. Rejected: waiver-of-rights risk on partial payments, AppFolio plan-entry is browser-automation-only, and the industry's own opacity here signals it's the hard part. Plans are human-approved suggestions in the pilot.
  5. Outbound voice from day one ("call them in Spanish"). Rejected for pilot: FCC artificial-voice consent regime + T-Mobile TFN block; SMS/email prove the concept at lower risk.
  6. Buy/embed a flexible-rent rail (Flex/Best Egg) instead of building. Different problem (prevention vs. recovery), resident-paid fees, no agent conversation. Complementary, not a substitute; not this ADR.
  7. AppFolio RealmX delinquency flows. Solves outreach inside AppFolio but is PMS-locked, un-differentiating, and cedes the resident conversation (and the audit trail) to the PMS — strategically the opposite of our position.