Automate Repetitive Work
If you do it twice by hand, automate the third time.
Overview
Manual, repetitive work is slow and error-prone. We invest in automation for testing, builds, deployments and checks so humans spend their judgement where it matters.
Why
This principle needs a bound, and the experience behind it supplies one in both directions. Automation earns its keep on work whose shape you already know from having done it. It stops earning its keep the moment it is built for a predicted need: automation for failures nobody has hit is a set of guesses about how the system breaks, each with a maintenance cost and a false confidence attached. The sharper form of the same mistake is configuration, unused code is dead weight, but unused configuration is surface area someone can set incorrectly, and it acquires meaning by accident. The honest counterweight is that the strongest case for automation in this body of work is the one that was never built. Every guarantee described across these projects, the authorization checks, the migration invariants, the storage round trip, every test file, is currently enforced only when someone remembers to run it. That is recorded here as a gap rather than smoothed over, because a principle whose practice fell short teaches more when it says so.
Standard
Automate work whose shape you already know from having done it by hand. Automate the checks that protect guarantees you have already committed to, before automating conveniences. Do not add configuration for a need you cannot describe. When you decline to automate something, say so and record what would change the answer.
What This Forbids
- Automating a predicted need rather than an observed one
- Configuration surface with no current consumer
- Treating a manual process as safe because it has not failed yet
- A diagnostic that accumulates checks for failures nobody has hit
Examples
- A release script that refuses to build from a dirty working tree and stamps version, commit and build time into the image, because a running container has no repository to ask what version it is.
- A backup script that confirms the dump is non-trivial and passes an integrity check before pruning older ones, so a silent failure cannot delete the last good backup.
- A single command that publishes a shared foundation into a consumer and then verifies the consumer actually resolved what was just published, written specifically because the manual follow-up step had been run in the wrong repository, and that failure was silent.
Counter Examples
- No continuous integration in any repository in the family. Every guarantee is enforced by someone remembering, and it becomes urgent rather than merely embarrassing the moment code is shared, because that is when blast radius goes from one system to four.
- Careful provenance discipline, a build refusing to run from a dirty tree, attached to an entirely manual pipeline. Both halves are needed and only one of them scales.
- Sampling machinery built ahead of the traffic that would justify it, inert at its default and carrying an unanswerable design question.
Lessons Learned
- Speculative configuration is worse than speculative code. Unused code is dead weight; unused configuration is surface area someone can set wrongly.
- Automate what protects a promise before automating what saves a keystroke.
- The honest state of this principle in this work is a gap, not an achievement. Recording that is more useful than claiming coverage, and it is the clearest example of why maturity is tracked separately from status.
Learned From
Related Principles· 1
Related Documents· 2
Referenced By· 2
Version History
- v0.1.0
Principle established with placeholder content.
- v0.2.0unchanged
Written from real experience, and bounded. The principle held, but the practice behind it did not: the absence of continuous integration is recorded as the gap it is. Maturity kept at Draft for that reason.