Review scheduler test expectations separately from code
For example, adding 24 hours to a 09:00 run in New York on March 8, 2025 produces a 10:00 local run the next day. Before an AI agent edits that scheduler, record the intended behavior in independently reviewed UTC fixtures so expectations cannot quietly shift to match its code.
The decision is whether “daily” means a fixed elapsed interval or the same local clock time. The review must protect that decision, not just check that the tests pass.
Choose the clock before choosing the implementation
For this reminder, which must run at 09:00 in America/New_York, using IANA time-zone database release 2024a, the expected schedule around the spring daylight-saving transition is:
| Local run time | Expected UTC instant | Gap from previous run |
|---|---|---|
| March 8, 2025, 09:00 | 2025-03-08T14:00:00Z |
Not applicable |
| March 9, 2025, 09:00 | 2025-03-09T13:00:00Z |
23 hours |
| March 10, 2025, 09:00 | 2025-03-10T13:00:00Z |
24 hours |
An implementation that adds 24 hours to the first instant returns 2025-03-09T14:00:00Z. That is 10:00 in New York, an hour later than the requirement.
A 24-hour interval and a daily local appointment are different contracts.
Neither interpretation is inherently wrong. For a requirement explicitly defined as “every 24 elapsed hours,” interval arithmetic fits. For this reminder, choose local calendar behavior because the requested invariant is the wall-clock time.
Write the contract before requesting code changes
“Run daily at 9” leaves the zone, boundary behavior, and treatment of missed runs unspecified. Resolve those choices in a small, reviewable contract.
Schedule contract
| Field | Chosen behavior |
|---|---|
| Schedule | Every local calendar date at 09:00:00 in America/New_York |
| Calculation | Return the earliest scheduled instant strictly later than the supplied reference instant |
| Exact boundary | If the reference instant is exactly a scheduled instant, return the next date’s occurrence |
| Missed occurrences | Do not return past occurrences for catch-up |
| Clock input | Accept an explicit reference instant; do not read the system clock inside the calculation |
| Rule dependency | Use time-zone database version 2024a for these fixtures |
| Output | Return a UTC instant for comparison |
This contract describes a schedule calculator, not the job runner. A runner can have a separate catch-up policy, but it must not silently change what this function means. Making the reference instant an explicit input also removes a hidden clock dependency.
The database version is part of the test setup. Configure the implementation to use that version and verify it through runtime metadata or a pinned time-zone data artifact. A version string in a fixture does not configure the library. If the runtime cannot establish which rules it used, the test environment is not fully specified.
Save the counterexample as a shared fixture
Save the following as daily-local-time.json. A language-neutral file lets different implementations use the same expectations.
{
"contract": {
"zone": "America/New_York",
"local_time": "09:00:00",
"tzdb_version": "2024a",
"selection": "strictly_after",
"missed_occurrences": "skip"
},
"cases": [
{
"name": "one_second_before_run",
"after": "2025-03-08T13:59:59Z",
"expected": "2025-03-08T14:00:00Z"
},
{
"name": "spring_transition",
"after": "2025-03-08T14:00:00Z",
"expected": "2025-03-09T13:00:00Z"
},
{
"name": "exact_boundary_after_transition",
"after": "2025-03-09T13:00:00Z",
"expected": "2025-03-10T13:00:00Z"
},
{
"name": "one_second_after_run",
"after": "2025-03-09T13:00:01Z",
"expected": "2025-03-10T13:00:00Z"
},
{
"name": "reference_several_days_later_skips_past_occurrences",
"after": "2025-03-13T14:00:00Z",
"expected": "2025-03-14T13:00:00Z"
}
]
}
For each case, a test adapter passes after to the implementation and compares the returned instant with expected. Compare parsed instants, not formatted strings: different timestamp representations can describe the same instant.
The spring-transition case rejects the specific mistake of adding 24 hours. The before, exact, and after cases check selection around a scheduled instant. The several-days-later case checks that the calculator selects a future occurrence rather than returning a past one.
Keep expected values independent of the implementation under test. Generating them with the same scheduling helper can reproduce the same bug on both sides of the assertion.
For independent review, verify the local-to-UTC conversions against the authoritative rules in IANA’s 2024a North America transition record, rather than merely asking another implementation to agree. Check the applicable offset for each local date and confirm the resulting UTC instant.
For cross-language conformance, each adapter must preserve the fixture’s semantics, including the reference instant and pinned rules. Agreement between implementations is useful, but agreement with an independently reviewed expectation is the stronger check.
Review expectation edits separately from implementation edits
Give the agent the contract and reviewed fixture, then ask it to implement the calculator without changing either. If it proposes changing an expectation, review that edit separately from the implementation.
Distinguish a correction from a changed requirement. An erroneous fixture needs correction against the existing contract and authoritative rules. A requirement change needs an explicit decision about the intended behavior, followed by updated expectations. Neither should pass as routine test maintenance merely because the new assertion matches the implementation.
A passing test is weaker evidence when the implementation also supplies its expected answer.
Use this short contract review when assessing the diff:
- Clock: Does the code preserve 09:00 local time, rather than assuming a fixed elapsed gap?
- Boundary: Does “strictly later” still exclude the supplied instant itself?
- Rules: Is the named zone resolved using the pinned data rather than an unexplained fixed offset?
- Oracle: Are expected values still independently specified rather than calculated by the code being tested?
I would gate this narrowly scoped change on these fixtures and a review of the calculation. I would not accept a passing ordinary-day test as evidence that daylight-saving behavior is correct: on an ordinary day, both interpretations can produce the same answer.
Keep calculation separate from delivery guarantees
These fixtures cover selected calculator inputs under the chosen rules, not every zone, date, or future rule change. Before changing a time-zone database version, rerun and review them. Investigate changed expectations to distinguish a legitimate rule update from an implementation change or fixture error.
A move to 02:30 would require additional policy decisions because some local times are nonexistent or occur twice during clock changes. The 09:00 contract leaves those policies unresolved.
The fixtures do not simulate a prolonged outage or establish that a worker executes on time, catches up correctly, retries safely, or avoids duplicate side effects. Those delivery guarantees need separate execution tests, using a fake clock, isolated storage, and mock job effects where appropriate.
For a five-minute start today, write one fixture for your scheduling requirement: record its zone, local time, boundary rule, and two consecutive expected UTC instants across a clock change. Have those expectations reviewed independently before asking the agent to change the code. That protects one calculation contract; it does not verify job delivery.