Shift Log: Tests First Kept the AI Patch in Bounds
The handoff looks harmless: ask an AI coding assistant to implement password-reset token validation, inspect the patch, and request tests. The risk is that those tests simply document whatever the assistant already wrote. A tests-first workflow reverses the sequence: agree on observable behavior, establish failing checks, and only then authorize implementation.
This head-to-head compares those two workflows on the same task. It is a practical decision framework, not a timed benchmark or a claim that one model always writes better code.
The shared ticket is password-reset token validation
Both approaches receive the same requirements: accept a valid, unused token before its expiry; reject malformed, expired, or previously consumed tokens; and avoid exposing raw tokens in logs. The ticket also specifies that a token expires when the current time is equal to its expiry time.
That last sentence matters. Without a defined boundary, either workflow can produce internally consistent code that implements the wrong policy. Writing tests first does not replace requirements work; it makes missing decisions harder to ignore.
First round: who controls the acceptance criteria?
In the implementation-first lane, the assistant writes validation code and then adds tests. This produces something concrete to review quickly, but creates an anchoring problem: the implementation becomes the easiest source of expected behavior. An accidental inclusive expiry boundary can appear in both code and tests.
In the tests-first lane, ask for behavior cases without production changes. Review the cases against the ticket before approving executable tests. Keep assertions on public outcomes rather than private helper calls, unless a specific interaction is itself a requirement.
- A valid token succeeds immediately before its expiry time.
- The same token fails exactly at expiry and after expiry.
- A consumed token cannot authorize another reset.
- Malformed input fails through the documented interface rather than leaking an unexpected exception.
- Captured application logs do not contain the raw token.
The verdict favors tests first for controlling scope. The acceptance criteria remain visible before the assistant starts choosing implementation details.
Second round: which workflow produces trustworthy evidence?
Implementation-first tests can still be excellent when a reviewer independently checks them against requirements. Conversely, tests written first can pass for the wrong reason: a broad exception assertion might accept a database outage as successful token rejection.
Require precise assertions and a controlled clock. Run the new tests before implementation and inspect each failure. A missing import is not evidence that expiry behavior is being tested. Where necessary, establish a minimal interface or stub so failures reach the intended assertion.
After implementation, deliberately introduce a small relevant defect, such as accepting a token exactly at expiry. Confirm that the corresponding test fails, then restore the correct code. This spot check is not comprehensive mutation testing, but it helps expose decorative coverage.
The verdict favors tests first only when the red phase is verified. Merely generating tests before code is sequencing, not proof.
Third round: which lane handles change more cleanly?
Give the assistant a narrow instruction: implement the approved behavior, do not weaken assertions, and explain any proposed test changes separately. Review the diff for unrelated refactoring, new dependencies, and skipped tests.
Implementation first remains useful for disposable prototypes and unfamiliar APIs, where the immediate goal is discovering what is possible. Before promoting that prototype, independently establish its acceptance contract. Tests first is the stronger default for bug fixes, security-sensitive boundaries, and behavior with explicit acceptance criteria.
The verdict splits by purpose. Use implementation first for exploration; use tests first when preserving a defined contract matters more than producing an initial patch.
Shift handoff: keep the contract portable
If your team uses several assistants, Relay365 fits as a pay-as-you-go relay desk rather than a substitute for test discipline. It works with Claude Code, Codex, Gemini CLI, and OpenAI SDK clients. Create a Relay365 account if shared access across those workflows would simplify your setup.
For any head-to-head assistant comparison, keep the repository snapshot, requirements, approved tests, and change permissions identical. Record actual test results and review findings rather than judging by confident explanations. The final verdict is straightforward: let the assistant propose the patch, but let independently reviewed behavior decide whether it ships.
Further desk bulletins
| Date | Bulletin title | Filed under | Language |
|---|---|---|---|
| 2026-10-29 | Shift log: Claude Code command time-savers, ranked | Agent shift notes | EN |
| 2026-10-29 | Duty Log: Keep the Contract, Clear the Agent Backlog | Agent shift notes | EN |
| 2026-10-29 | Shift Log: Shell Access Approved, Host Access Denied | Agent shift notes | EN |
| 2026-10-29 | PR Review Shift Log: Agent Findings, Checklist Verdicts | Agent shift notes | EN |
| 2026-10-29 | Shift log: Claude Code team access routed and reviewed | Agent shift notes | EN |
| 2026-10-29 | Shift Log: Cline and Roo Under a $60 Monthly Cap | Agent shift notes | EN |
Curious how it runs on your own code? Sign up →