ADR 014: Calendar-Aligned Staleness
Status
Accepted
Context
Colin documents can specify time-based staleness thresholds (stale: 1d). Users need two distinct behaviors:
- Elapsed time: "rebuild 24 hours after last compile"
- Calendar boundaries: "rebuild when the calendar day changes"
These are different. A document compiled at 11pm with stale: 1d won't rebuild until 11pm tomorrow. But with calendar alignment, it should rebuild at midnight.
Decision
Use the c prefix to indicate calendar-aligned staleness:
1d = 1 day elapsed since compile
1cd = new calendar day (midnight boundary)
30m = 30 minutes elapsed
30cm = at :00 and :30 boundaries
Validation Constraints
Calendar-aligned values must divide evenly into their containing period to create predictable boundaries:
| Unit |
Valid values |
Reason |
cm |
1,2,3,4,5,6,10,12,15,20,30,60 |
Must divide 60 minutes |
ch |
1,2,3,4,6,8,12,24 |
Must divide 24 hours |
cd |
1 only |
Days don't subdivide into weeks predictably |
cw |
1 only |
Weeks don't subdivide into months predictably |
cM |
1,2,3,4,6,12 |
Must divide 12 months |
cQ |
1,2,4 |
Must divide 4 quarters |
Values like 3cd or 7cm are rejected because they would create boundaries that don't align with natural calendar periods.
Implementation
Minutes and hours use epoch-based periods (fixed boundaries that don't shift). Days and larger use natural calendar boundaries (midnight, Monday, 1st of month, quarter starts).
Alternatives Considered
Named schedules (stale: quarterly): More readable but less flexible. Doesn't allow 2cM (bimonthly) or 15cm (quarter-hourly).
Cron syntax: Powerful but complex for the common cases. Overkill when users just want "refresh monthly."
Epoch-based for all units: Consistent but creates unintuitive boundaries for days and larger (why would "every 3 days" start from 1970?).
1---2name: 002-accepted-2d6b5a653description: ADR 014: Calendar-Aligned Staleness4---5# ADR 014: Calendar-Aligned Staleness67## Status89Accepted1011## Context1213Colin documents can specify time-based staleness thresholds (`stale: 1d`). Users need two distinct behaviors:14151. **Elapsed time**: "rebuild 24 hours after last compile"162. **Calendar boundaries**: "rebuild when the calendar day changes"1718These are different. A document compiled at 11pm with `stale: 1d` won't rebuild until 11pm tomorrow. But with calendar alignment, it should rebuild at midnight.1920## Decision2122Use the `c` prefix to indicate calendar-aligned staleness:2324- `1d` = 1 day elapsed since compile25- `1cd` = new calendar day (midnight boundary)26- `30m` = 30 minutes elapsed27- `30cm` = at :00 and :30 boundaries2829### Validation Constraints3031Calendar-aligned values must divide evenly into their containing period to create predictable boundaries:3233| Unit | Valid values | Reason |34|------|-------------|--------|35| `cm` | 1,2,3,4,5,6,10,12,15,20,30,60 | Must divide 60 minutes |36| `ch` | 1,2,3,4,6,8,12,24 | Must divide 24 hours |37| `cd` | 1 only | Days don't subdivide into weeks predictably |38| `cw` | 1 only | Weeks don't subdivide into months predictably |39| `cM` | 1,2,3,4,6,12 | Must divide 12 months |40| `cQ` | 1,2,4 | Must divide 4 quarters |4142Values like `3cd` or `7cm` are rejected because they would create boundaries that don't align with natural calendar periods.4344### Implementation4546Minutes and hours use epoch-based periods (fixed boundaries that don't shift). Days and larger use natural calendar boundaries (midnight, Monday, 1st of month, quarter starts).4748## Alternatives Considered4950**Named schedules** (`stale: quarterly`): More readable but less flexible. Doesn't allow `2cM` (bimonthly) or `15cm` (quarter-hourly).5152**Cron syntax**: Powerful but complex for the common cases. Overkill when users just want "refresh monthly."5354**Epoch-based for all units**: Consistent but creates unintuitive boundaries for days and larger (why would "every 3 days" start from 1970?).