Reminder settings say where their value came from

Property Settings stops completing the reminder block from hardcoded defaults, and shows the rung that answered instead

19 Sept 2026 · branch p9-reminder-inheritance · captured against propflow-stage · at 4d8e7cba51

Data note. Every name and balance below comes from propflow-stage, which is anonymized by construction (ADR-0097/0110 — phones in the impossible +1000 NPA, emails @example.test). The identical capture against prod would carry real tenants' names and balances and is not safe to attach anywhere, which is why the generator refuses to run against one.

1 · The reset control, BEFORE the click — a stored override, named

Before this change the screen completed the reminder block from hardcoded defaults on load — { enabled: true, intervalHours: 24, maxReminders: 3 } — whether or not this property had ever chosen anything, and handleSave posted the whole object. Saving the maintenance phone therefore wrote a full default reminder block into a property that had never chosen one, and that block then sat on top of the company’s answer.

This building is the real legacy cohort. A read-only inventory of the anonymized stage table found 70 rows storing { enabled: false, intervalHours: null, maxReminders: null } — this is one of them. Three things in the frame are the fixes:

The last one is why a capture is not decoration here: every string above is asserted against the DOM in the state the screenshot shows, so the picture cannot ship looking right while the label is wrong.

Asserted in the captured DOMRemind me about pending approvals and signatures · Set for this property · Use inherited value · Reminder emails are off for your company · This property has its own saved answer, which stays inactive until then · How many reminders · How often · PropFlow default: 24 · PropFlow default: 3. Nine strings, and the last four are round 4's two fixes rendered: the cadence pair is MOUNTED (it was unmounted for every not-opted-in company), and its two fields read “PropFlow default” rather than “Set for this property” — because this row's stored `intervalHours: null` / `maxReminders: null` are now absences, not overrides.

The reset control, BEFORE the click — a stored override, named

2 · AFTER the click — the line names the rung that now answers, not the override it discarded

The same control, one click later, and this pair of frames is the instrument for a defect that shipped in commit 1 and was caught before CI. ReminderSource originally labelled itself from the field’s own resolved value and origin — which, for a property that HAS an override, is the override. A home storing intervalHours: 12 under a company holding 48 would have been offered “PropFlow default: 12”: a number that is neither the default nor inherited, on the control the property manager is about to press. A page-level screenshot would have been green while that shipped; only exercising the control surfaces it.

The API now runs the walk a second time with this property’s row removed — which is exactly what the reset does — and the screen labels from that. Here the line reads “Inherited from your company: Off”: the board row’s own worked example, rendered.

What these frames do NOT prove, said plainly. No company on the anonymized stage table has opted in (checked: this building’s company holds no pmActionReminders attribute at all), so the two cadence fields render disabled here and cannot be driven through an edit. Manufacturing an opt-in was refused: it stamps enabledAt, which the writer deliberately keeps through a later disable, so it would leave a durable artifact on a shared table to take a screenshot. The overridden numeric case is pinned by test instead — ⚠ `inherited` is what REMOVING the override gives you, never the override itself, asserting { value: 48, origin: 'organization' } against a stored 12.

Asserted in the captured DOMRemind me about pending approvals and signatures · Inherited from your company: Off. The reset removed this property's own `enabled` override, and the line now names the COMPANY rung and the value it holds.

AFTER the click — the line names the rung that now answers, not the override it discarded

What a picture proves here that a test cannot

The unit suites pin the walk and the save body. Neither can see whether the source line actually reaches the screen, or whether it reads as English to a property manager rather than as a field name. That is what this capture is for.

PropFlow Docs