A test for the changed feature can pass while an adjacent behavior breaks. That is common when two customer actions share state. A booking reschedule, for example, can change the appointment time while leaving a reminder scheduled for the old time.
For a release like that, I want a small evidence card alongside the pull request:
Intended behavior: confirmed bookings can move before the cutoff
Adjacent paths: reminders, cancellation, availability, staff view
Pre-release checks: changed path + adjacent regression tests
Production signal: reschedule errors and stale-reminder events
Rollback owner: named person and decision threshold
Observed after release: timestamp, signal and result
The point is to make the expected customer behavior and the scope of verification explicit. A passing CI check is one piece of evidence, not a record of what happened in production.
A runnable example with Node's test runner
This deliberately small policy uses a fixed 24-hour cutoff and a reminder one hour before the booked time. The dates are illustrative. A real booking system would also need authorization, durable writes, timezone presentation, conflict checks, notification delivery and idempotency.
Save as booking-policy.mjs:
const HOUR = 60 * 60 * 1000;
export function reschedule(booking, nextStart, now) {
if (booking.status !== 'confirmed') throw new Error('booking is not active');
if (Date.parse(booking.start) - Date.parse(now) < 24 * HOUR) {
throw new Error('reschedule cutoff passed');
}
if (Date.parse(nextStart) <= Date.parse(now)) {
throw new Error('new time must be in the future');
}
return {
...booking,
start: nextStart,
reminderAt: new Date(Date.parse(nextStart) - HOUR).toISOString(),
};
}
export function cancel(booking) {
if (booking.status !== 'confirmed') throw new Error('booking is not active');
return { ...booking, status: 'cancelled', reminderAt: null };
}
Save as booking-policy.test.mjs:
import test from 'node:test';
import assert from 'node:assert/strict';
import { reschedule, cancel } from './booking-policy.mjs';
const booking = {
id: 'demo-1',
status: 'confirmed',
start: '2026-10-10T15:00:00.000Z',
reminderAt: '2026-10-10T14:00:00.000Z',
};
test('reschedule changes start and reminder together', () => {
const result = reschedule(
booking,
'2026-10-12T15:00:00.000Z',
'2026-10-08T15:00:00.000Z',
);
assert.equal(result.start, '2026-10-12T15:00:00.000Z');
assert.equal(result.reminderAt, '2026-10-12T14:00:00.000Z');
assert.equal(booking.start, '2026-10-10T15:00:00.000Z');
});
test('cutoff still blocks a late reschedule', () => {
assert.throws(
() => reschedule(booking, '2026-10-12T15:00:00.000Z', '2026-10-09T16:00:00.000Z'),
/cutoff passed/,
);
});
test('cancelling after a reschedule removes the reminder', () => {
const moved = reschedule(booking, '2026-10-12T15:00:00.000Z', '2026-10-08T15:00:00.000Z');
const result = cancel(moved);
assert.equal(result.status, 'cancelled');
assert.equal(result.reminderAt, null);
});
Run node --test booking-policy.test.mjs.
The first test checks the requested change and the nearby reminder. The second guards the cutoff. The third checks a downstream action on the new state. If the reschedule function updates start but forgets reminderAt, the first test fails for a reason a reviewer can understand.
Where the unit test stops
This pure-function example does not prove that the old calendar slot was released, the new slot was reserved, or the reminder job was replaced. Those need integration checks against the actual storage and scheduler. Nor does a staging test prove that production notifications are healthy.
For the production side of the card, choose a signal before deployment. One option is a count of reminder jobs whose scheduled time does not match the current booking time. Another is the rate of reschedule failures after a successful confirmation. Define what observation would trigger investigation or rollback, and name the person who can make that call.
After release, record what you actually observed, with a timestamp and the deployed version. If there was not enough traffic to observe the path, say that instead of marking the rollout verified.
The card can stay short:
Change:
Expected customer result:
Adjacent paths checked:
Test evidence:
Production signal and observation window:
Rollback owner and trigger:
Observed result and time:
It connects the code review to the customer behavior the release is supposed to protect.
AI disclosure: Drafted with AI assistance; code example executed and editorially reviewed before publication.
Top comments (0)