Two weeks ago I did something I'd never done in two years of building: I read my own terms of service as a specification instead of as legalese.
Every sentence in there that describes behaviour is functionally an assertion about the software. "Daily check-ins are recommended but not mandatory" is a test case — it says the system must not punish someone for skipping one. Nothing in a normal build ever evaluates that.
So I went through it clause by clause and looked for the place in the product that actually executes each one. Fifteen didn't match.
The one that still bothers me: on day 7 the dashboard demanded proof of work, and my own contract calls that day's check-in voluntary. Someone who read the contract and believed it would have uploaded nothing and walked into the consequence meant for people doing nothing at all. The product would have punished someone for trusting a commitment I made.
Nobody was affected — no paying customer has ever started a sprint in this thing and there's no testimonial. That's not an excuse, it's the only reason I can post this at all. Fifteen instances of one class, in a product with no paying sprint behind it, all fixed the same day.
Three things I'd hand to anyone doing the same:
Record the direction, not just the deviation. Half my findings were the code being stricter than the contract — including one where I advertised a faster response time than I'd contractually committed to. Nobody complains about a promise that's too generous, so those errors are silent by construction and survive until someone audits. The mirror image, contract promising more than the software delivers, is the one that's actually a liability. Same measurement, completely different consequence.
The worst class is the one that looks fine. Two code paths in there could never fire. Not broken — unreachable. No test went red, because no test asserts "this line is ever reached". No error surfaced, because a path that never runs never fails. I only found them by running the whole chain end to end once, which is manual work.
A comment has no assertion. A README has no CI. Your terms of service are a test suite nobody runs. Two specifications exist in every product like this and only one gets tested — and the untestable one is the one that legally binds. The code has linters, types, a pipeline, a reviewer. The text that governs in a dispute has an author and a date.
Here's the part I didn't expect. I built a small string check that fails the build when a retired sentence reappears, and ran it that same evening. It immediately found a fifteenth instance — same class, same wording, in a file I hadn't looked at and neither had the review pass that had just declared my list complete at fourteen.
So the tool caught something a careful human read had missed hours earlier. But it's also nearly useless for the expensive cases: it knows strings, not meaning, it can't tell a claim from its negation, and absence is completely invisible to it — a promise that quietly disappears produces no match at all. Roughly a third of my findings, all from the cheap end.
Which leaves me with a question I genuinely don't have an answer to.
The obvious fix is more supervision: more rules, more checks, a ritual before every release. But every rule I add is another thing to maintain, and the root cause wasn't sloppiness — it was the same statement living in four, six, eleven places, with none of them saying how many there are. Maybe the right move isn't to watch more carriers. Maybe it's to have fewer.
So: for those of you a few years in — did you ever deliberately delete a surface rather than maintain it? Docs, a README section, a marketing page, a status file. Did the drift actually stop, or did it just move somewhere you weren't looking?
I'm asking because deleting feels like giving up on the documentation, and I can't tell yet whether that instinct is right or just tidy.
The two studies I leaned on, in case anyone wants the originals — both are about the same property from opposite ends:
Kleven, Knudsen, Kreiner, Pedersen & Saez, "Unwilling or Unable to Cheat? Evidence From a Tax Audit Experiment in Denmark", Econometrica 79(3), 2011 — randomised audit, 40,000+ taxpayers, evasion near zero on third-party-reported income and substantial on self-reported: https://doi.org/10.3982/ECTA9113
Scheel, Schijen & Lakens, "An Excess of Positive Results", Advances in Methods and Practices in Psychological Science 4(2), 2021 — 152 standard studies vs 71 Registered Reports, 96% positive results vs 44%: https://doi.org/10.1177/25152459211007467
Longer version with the method written out step by step: https://mvpbuilder.io/blog/terms-of-service-test-suite?utm_source=indiehackers&utm_medium=post&utm_campaign=cohort2&utm_content=termstestsuite
Disclosure so it's not buried: I build a product in this space, so I'm not neutral on the conclusion. What I can evidence is a self-test — I ran my own 21-day sprint as a participant with the goal frozen before day one, and missed one of four criteria. What I can't evidence is that it works for anyone else: no paying customer has completed a sprint and there's no testimonial. The two studies above are neutral.