Testing playbook: regressions and new features

How we prove a change before a customer sees it, for the two customer shapes: centralized leasing over distributed properties (one office runs many scattered buildings, like Western Slope) and a single community with its own onsite team (like Camellia). For engineers and the agent fleet.

2026-10-09 · standing playbook · applies to every lane · written from the renewals work at Camellia (single community, live) and Western Slope (centralized leasing, going live)

Willows testing is OFF (Gera 2026-11-02). Clara stays configured; reopen only on Gera's word. Rung 5 (the Willows live run) and every robot call, robot text, harness or E2E at the Willows (appfolio-45) is closed: the robot-call chokepoint and the robot text sender refuse it unless WILLOWS_TESTING_ALLOWED=1 is set, and only Gera sets that. Use the Fairhaven test company.

1. The ladder 2. Fix vs new feature 3. The two team shapes 4. Test companies 5. Pass bar and report 6. Rules 7. What "tested" means 8. Live test at the Willows

Every change climbs the same ladder; what differs is how far it must go. A fix stops at rung 5 and ships with no switch. A new feature climbs to rung 7, in the sandbox company shaped like the customer who gets it, and only Fede turns it on.

The full playbook

1. The ladder

RUNG 1Unit tests+ mutation controlminutes, local RUNG 2 (NEW)Adversarial fleetsimulated users attackon the bench, graded RUNG 3Real-book replayevery live customerread-only, byte diff RUNG 4Workflow historiesTemporal replay oflive runs, no writes RUNG 5Willows live runone test buildingengine path, real texts RUNG 6Sandbox companycustomer's shape,anonymized book RUNG 7Supervised weekat the customer,every message held A FIX stops here: merged, live everywhere, no switch A NEW FEATURE goes on: dark setting, Fede turns on Proves nothing broke →Proves it works in the customer's shape →
Rungs 1 to 5 answer "did we break anything". Rungs 6 and 7 answer "does the new thing work the way this customer works". Both halves ran for the Western Slope renewals: Camellia's book came back byte-identical after five merges, and the Willows run found three defects before any customer saw them.
RungWhat it isPassWhere it lives today
1Unit tests for the exact path changed, plus one planted defect that must go redGreen, and the planted defect failsVitest, review:self
2 (new)Adversarial fleet on the bench: simulated staff, prospects and tenants attack the changed lane with production's breaking data shape, outbound suppressedEvery failure two independent skeptics confirm is fixed or catalogued with a severity; incident fixtures red then greenStaff-desk fleet exists; prospect and tenant fleets to build (section 7)
3Every live customer's real book run through the engine before and after, no writesDecisions, terms and text identical; strict-inputs diff greenRenewal replay harness, diff script
4Live workflow histories replayed on the new codeEvery history replays cleanTemporal history replay
5A seeded run on Willows: real engine, real texts to our registered phones onlyScorecard green: no unsafe send, no PMS write, expected holdsWillows seed, dry run, live run
6Anonymized copy of the target customer's whole portfolio in the test company of its shape, PMS in sandbox modeSame scorecard, across every building and setting levelTo be standardized (section 4)
7Supervised at the customer: every message held for a personOne clean week, before/after on the pageGera's Supervised mode, review page

The Willows bench is shared. Two other rigs wipe every open work order on the Willows (appfolio-45) nightly: Agent Smith’s maintenance eval about 07:00–07:45 UTC and the CI “Clara Behavior Evals” run about 03:40–04:30 UTC; Gera’s fast-lane scripts also dial the same line. A live run there never crosses those windows, claims the bench on #engineering-bridge before each cycle (a BRIDGE CLAIM with the window), and grades a work order that vanished between a read and a re-read as interference, never as a product defect.

2. Fix vs new feature

A fix or an improvement to live behavior

  • Reproduced case first, in a test that fails on main.
  • Rungs 1 to 5. Rung 3 on every live customer, byte-identical.
  • Ships with no switch, live everywhere on merge.
  • PR body: the reproduced case and the replay list.

A new capability a customer could want off

  • Rungs 1 to 6, then 7 at the customer.
  • Ships as a company or property setting, default off, visible on the customer page.
  • PR body carries the Dark: line; the dark-features register tracks it.
  • Turn-on at a customer is Fede's explicit call. Flag deleted the week it is proven.

Why the split: three improvements to live behavior once shipped behind settings that nobody pressed, and a sync guard sat off at three customers. A fix that waits for a switch is a fix nobody gets.

3. The two customer shapes

Centralized leasing, distributed properties (Western Slope): one office runs ~90 scattered buildings. Company-level policy with building overrides, one approval desk, one contact, the team sends paperwork where no template exists. Test company: Fairhaven.

Single community, onsite team (Camellia, JP&Co): one property with its own staff. Property-level policy, its own contacts and channel, Clara sends the paperwork in AppFolio, fully autonomous. Test company: Willows.

Must be exercisedCentralized leasing (Fairhaven)Single community (Willows)
Settings inheritance: company value, building override, defaultAll three levels, including a building that overrides the companyProperty level, plus a property with nothing set
Who sends the paperworkTeam path: no PMS offer, no letter, team copy, term change goes to a personClara path: PMS offer created, letter attached, portal signing
Where approvals and alerts landOne desk: the review page and one contact for the whole companyPer-property channel and contact; the wrong property's channel is a failure
VolumeDozens of holds in one run; the board and the queue must stay readableA handful per property
Transfers and escalationsTo the central team's line and inboxTo the onsite manager
Eligibility dataAccount balance from the daily rent-roll pull, no live PMS readsSame, plus the PMS open-offer check before starting
Rung 3 bookTheir anonymized copy, replayed read-onlyTheir live book, replayed read-only, byte-identical

4. Test companies: what exists, what we keep

Fede, 10/9: standardize and clean up, do not add more. Read-only inventory of production, 10/9 02:40Z: 6 test companies, 234 buildings between them. None is usable as the portfolio practice today.

Test companyWhat it isStateProposal
Western Slope Mirror (TEST)70 buildings, 185 leases, ~15.5k conversationsDeleted 10/9gone (193,355 rows, 0 left; harness re-pointed at Fairhaven first, #18109)
Willows (in the sandbox company)Our one-building engine bench, JP&Co's AppFolio with writes allowedSupervised, team sends; the rung-5 benchkeep: the single-community shape and the engine bench; in sandbox PMS mode since 10/9
Fairhaven Residential (TEST)11 buildings, the voice benchCleaned 10/9 03:30Z: 4,737 copied JP&Co rows removed, 0 left; 11 buildings, voice intact; its three jpco-bound buildings moved to sandbox PMS modeclean (E11, Fede: clean), then the practice company for centralized leasing over distributed properties, loaded from Western Slope's anonymized book
Second Mirror (TEST)2 buildings, JP&Co replay pairDeleted 10/9gone (23,972 rows, 0 left)
Test Client Co3 demo buildings from the "Test company" boxDeleted 10/9gone (150 rows, 4 test logins, 0 phone lines)
Module Gate Probe (TEST)1 building, a probeDeleted 10/9gone (1,850 rows, mostly sync logs)

Why no company is ready: the daily renewal check scans the whole platform, so turning a building on also scans every old lease already on it; the recipient guard lets staff email through and fails open; held messages fall back to #alerts when a company has no channel; and nothing copies settings between companies or cleans a multi-building seed. Those four gaps are the loader.

The standard (Fede, 10/9: "fairhaven and willows thats it"): Fairhaven for centralized leasing over distributed properties, Willows for a single community. Two test companies, never a third. Fairhaven can carry Western Slope's and Situs's anonymized books side by side, each under its own prefix, when a run needs more realism. Each is in sandbox PMS mode, Supervised, with a test Slack channel, contacts pointed only at registered team phones and inboxes, and is rebuilt by one command from an anonymized copy of a customer's book with a building map. "Clean up" becomes "delete and rebuild", which is also the proof that the loader works.

Decisions

Overnight: the loader (prepare, seed, cleanup, dry run) merges as scripts; its first real target is Fairhaven once E11 finishes.

5. Pass bar and the report

CheckFixNew feature
Planted defect goes redrequiredrequired
Fleet attack (rung 2)requiredrequired
Every live customer byte-identical (rung 3 + 4)requiredrequired
Willows scorecard green (rung 5)required when the path touches sends, PMS writes or workflowsrequired
Sandbox company in the customer's shape (rung 6)norequired before turn-on
Supervised week (rung 7)norequired at the first customer
Before → after on the page, with the proof artifactrequiredrequired

The report is always before → after: what the tenant or the team experienced, what they experience now, and the thing that proves it (a delivered text, a scorecard, a diff). "Much better, and here is how you can tell."

6. Rules that keep this honest

Per-release model and refactor decisions (new model out, big layer rebuilt) use a separate procedure with its own frozen set, budget and verdict: Clara Bench (proposed 2026-10-23). The ladder on this page stays the per-change proof; Clara Bench is the per-release decision. Its standing rule for every run: agree the bar and the budget before the run starts.

7. What "tested" means from now on

Proposed — pending Fede's review (2026-10-17)

A change to what a customer sees is "tested" only when four proofs hold: incident fixtures, a fleet attack on the bench, the real-book replay, and the live run. Unit tests and type checks are the floor. They are reported as "unit-covered", never as "tested".

Why now. The staff leasing desk (the text line a leasing agent uses to tell Clara about no-shows, notes and tours) failed a trivial ask at a customer after 59 commits in three weeks, unit tests on every one, and a 22% replay on Sept 30 that nobody acted on. One bench run of simulated agents then failed 21 of 45 scenarios on main in two hours, including the customer's exact case.

RUNG 2 (NEW): ADVERSARIAL FLEET ON THE BENCH 1 · FIXTURE FIRSTIncident becomes a fixturewithin 24 h, before its fixmerges. Red then, green now. 2 · SEEDProduction's breaking shapesalted names, test numbers,outbound suppressed 3 · ATTACKA persona texts Clarareal inbound path, first textscripted, persona writes the rest 4 · GRADERows + four reply checksno tone-judge verdicts;a planted violation goes red 5 · VERIFYTwo skeptics, working aparteach tries to refute everyfailure from the rows 6 · RESOLVEFixed, or cataloguedwith a severity; keepersjoin the pack (box 1) 7 · NIGHTLY ON MAINStaff, prospect, tenant lanesresults on the initiative'spage; bench claimed first 8 · IF REDPages the owner lanenever Fede Then the existing rungs: real-book replay, workflow replay, live run on bench numbers.
A loop, not an event: every find that matters becomes a fixture that replays on every later change.

The four proofs

ProofPasses whenEvidence
floor Unit tests, typesGreen. Necessary, never sufficient: "unit-covered"Test output
A. Incident fixturesEvery past incident in the area replays as a fixture: red at its pre-fix commit, green nowRed and green runs
B. Fleet attackSimulated staff, prospects and tenants (persona plus seeded production data shape) attacked it on the bench. Two independent skeptics confirmed each failure; each is fixed or catalogued with a severityResults file, catalogue
C. Real bookEvery live customer's book, read-only. Fix: byte-identical. Redesign: at or above baseline on every graderDiff, scorecard
D. Live runOn bench numbers. Fix: stops at Willows, no switch. New feature: sandbox company, then a supervised weekRecord ids

The attack fleet: a standing capability

The 22% rule

Sept 30

The replay said 22% pass. No owner, no row, no work.

From now on

Below the bar is work the same day: an owner lane and a row on the initiative's page.

Where it sits, who runs it, when

What it is not

Not a kill switch (fixes still ship with no switch), not a human approval queue, not a reason to hold a PR (a missing proof is work for the lane). It is how we prove a change before merge and find the next incident before a customer does.

8. Live test at the Willows: the one recipe

added 2026-10-22, from the first document-engine run (renewal packet parked in 7 s, then cancelled) · Fede: "the Willows should never ask for permission to change things"

The Willows (test property 45 in JP&Co's AppFolio, PropFlow property appfolio-45, company org_sandbox) is the only place a session may change things. Writes scoped to it are pre-approved; a write that touches a shared JP&Co object (a template or setting other properties use) still asks. Western Slope, Situs and Camellia are read-only, always.

NeedUseNever
Look at the Willows in AppFolioThe deployed robot: screenshot route, print-order read, vendor reads. Look at the PNG before trusting "captured".A fresh browser, the saved Browserbase profile, the heartbeat route, any login
Write in the Willows' AppFolioThe robot's write verbs (park, cancel, send-parked) with an expect clause; the robot answers done / blocked / refused and never writes on a mismatchA hand script against AppFolio
Read PropFlow rowsThe data facade from a worktree with DATA_BACKEND=dynamodb DYNAMODB_TABLE_NAME=propflow-prod AWS_REGION=us-east-1Local JSON
Start or reset a flow at the Willows (a renewal, a new-lease packet)No login. Go straight to production the way every Willows write already does: a tsx script with DATA_BACKEND=dynamodb DYNAMODB_TABLE_NAME=propflow-prod that calls the same domain function the route calls after its auth check, or temporal workflow start with the input the route would build (Temporal address and API key from the Keychain). Scope every write to org_sandbox / the Willows lease or application; one ledger line per write. Fede, 2026-10-23: "we have full admin access for the Willows, we do it every day."Any staff login: the regular smoke login is view-only by ruling (2026-10-16) and answers 403 on writes; the MFA e2e test account stays waitlisted; the nightly smoke login stays in GitHub secrets. A customer's staff user. Enrolling a factor on anything.
Point the flow at the Willows onlyThe building-level setting on appfolio-45 (it wins over the company row). Set it in the same shell command that starts the flow, and set it back right after the start answers; the running flow keeps the value it was started with.Leaving a Willows rung on: the daily scanner would act on every other Willows lease

The run, in order

  1. Preconditions, reads only: the merge is live on web and on the worker (health commit, worker build id); the Willows unit shows the expected starting state (robot screenshot plus a robot read); the dry run of every write prints exactly what it would change.
  2. Start, one shell command: set the Willows rung, sign in, call the route, restore the rung. If the route refuses, restore anyway; nothing was minted.
  3. Watch, one blocking loop: the lease record every 90 s until the flow records its outcome (parked / blocked / refused), plus the Temporal history and the worker log for the lease id. Never poll from the conversation.
  4. Evidence: robot screenshots of the unit and the document, the robot's answer with the ids it created, the worker log lines, the lease record. Look at every PNG.
  5. Cleanup, in this order: cancel the AppFolio write through the same robot verb with an expect on the ids it created → stop the workflow → reset the one tenant's PropFlow state (always with the tenant id; the bare route resets every open saga) → release the claim rows the start created → take the test recipe or setting out of use → confirm the rung is back. The lease keeps its outcome record by design.
  6. Report before → after on the initiative's hub page with the screenshots, and the tracker row gets the proof link. The run plan with the exact commands lives next to the proof.

Closed 2026-10-23: no prod staff login is needed for Willows runs. The first two runs on Oct 22 improvised one (the MFA e2e account, un-waitlisted per run); that was the mistake. Start and reset flows directly, as above.

PropFlow Docs