Capablio

Cadence and Exposure Cooldown

Architecture target (AFF v0.1). Implementation flags live in implementation-status.md. Do not treat this document as a shipped product contract.

Updated

Architecture target (AFF v0.1). Implementation flags live in implementation-status.md. Do not treat this document as a shipped product contract.

Separate three time concepts

  1. Survey cadence — when a new survey window is generated.
  2. Observation window — the time period the respondent should consider.
  3. Exposure cooldown — how long the same question family must wait before being presented again.

These may differ. A monthly survey can contain a question with a quarterly observation window, but it should only become eligible in the relevant quarter.

Supported cadence units

  • Day
  • Week
  • Month
  • Quarter
  • Year
  • Custom interval
  • Anniversary
  • Event-triggered
  • One-time

Tenant calendars should support:

  • timezone
  • week start
  • business days
  • holidays and shutdowns
  • fiscal quarter and fiscal year
  • user vacation or leave
  • blackout periods around major events

Skip-period semantics

skip_periods = N means N complete cadence periods after the current presentation are ineligible.

Example with a weekly cadence:

  • Asked in week 10
  • skip_periods = 0 -> next eligible in week 11
  • skip_periods = 1 -> skip week 11, next eligible in week 12
  • skip_periods = 2 -> skip weeks 11 and 12, next eligible in week 13

Formula:

next_eligible_period_index = presented_period_index + skip_periods + 1

Cooldown clock

Supported starts:

  • presented_at — recommended default; exposure creates fatigue even without an answer.
  • answered_at — useful for a few action checks, but can repeatedly expose non-responders.
  • survey_closed_at — useful when the survey window is long.
  • manual_milestone — PDP or event-driven only.

Cooldown scope

The policy must define who shares an exposure history:

  • respondent_subject_family — default; one respondent rating one subject.
  • subject_relationship_family — all peers share a cooldown for the subject.
  • subject_family — no respondent sees the same family while anyone is in cooldown.
  • respondent_family — prevents the respondent from seeing the same family about multiple subjects.
  • tenant_family — rarely appropriate; organization-wide campaign item.

The default should be narrow enough to support multi-rater observations while still preventing duplicate delivery through overlapping programs.

Absolute safety controls

A period-based cooldown alone is unsafe when cadence changes. Add:

  • absolute_min_days_between_exposures
  • max_asks_per_rolling_30_days
  • max_asks_per_rolling_90_days
  • max_consecutive_surveys
  • cooldown_after_decline

Example: a quarterly question with skip_periods = 0 should not suddenly be asked the next day if an admin changes the program to daily.

No-response behavior

Default:

  • Presented and viewed: counts as exposure.
  • Presented but not opened: counts as exposure for delivery fatigue, but may receive a lower fatigue weight.
  • Survey expired: counts as exposure.
  • Item withdrawn before delivery: does not count.
  • Technical delivery failure: does not count.

The exposure ledger should store both the event and reason rather than a single last-asked date.

Multiple overlapping schedules

A person may be in a weekly team pulse, monthly leadership pulse, quarterly 360, and PDP follow-up. Eligibility must be checked against a shared ledger. Otherwise the same question can appear through multiple programs in the same week.

Recommended precedence:

  1. Legal and tenant suppression
  2. Applicability and observation window
  3. Absolute fatigue safety
  4. Active mandatory milestone
  5. PDP override
  6. Pack-level cooldown override
  7. Family base cooldown
  8. Global tenant minimum

Schedule pause and vacation

Pausing a schedule should not erase cooldown or coverage history. A tenant may choose whether paused periods count as periods skipped:

  • calendar_periods: normal default; time passed even though no survey was sent.
  • active_survey_periods: only generated survey windows count.

The choice must be explicit because it materially changes recurrence.

Fiscal and calendar quarters

A quarter is not always three calendar months. Use a tenant period table rather than arithmetic on dates. The period service should assign every timestamp a stable period ID.

Example policy

exposure_policy:
  cadence_unit: MONTH
  skip_periods: 2
  period_count_basis: calendar_periods
  clock_start: presented_at
  scope: respondent_subject_family
  absolute_min_days_between_exposures: 45
  max_asks_per_rolling_180_days: 3
  no_response_counts_as_exposure: true

Asked in January with this policy:

  • February and March are skipped.
  • April is the first eligible month.
  • If April begins fewer than 45 days after the actual January presentation date, the absolute minimum still blocks it.