v1.11.0 ·
Words that mean what they say, and a gate that actually gates
Two fixes shipped here, and they share a shape. Something looked like it was working, was not, and nothing complained.
The first was a check. The website's lint script was next lint, a command Next 16 removed. A removed command does not fail politely. Next read the argument as a project directory, and pnpm lint died with Invalid project directory provided. The root script chains with &&, so scripts/check-docs-drift.mjs sat behind the failing command and had not run since Next 16 landed. And 5,891 lines of TypeScript across 50 files were never type-checked, because Next 16 also stopped running lint during next build.
It survived because nothing enforced it. scripts/release.sh gated on build and test only, the one CI workflow did the same, and there was no pull-request workflow. Nothing blocked, so nothing was scheduled. The defect had been written down four times in earlier records, once with the words "Worth its own instance." A gate that fails open creates no pressure to fix itself. The repair was one line, and the unchecked code produced zero errors.
Which gate
Next's upgrade guide says to move to Biome or ESLint. This repo has no ESLint, no config and no dependency, while packages/cli already lints with tsc --noEmit. Adding ESLint would have meant a second convention, a new dependency and an unknown number of new findings. The instance existed because a gate went dark. Answering with a different gate is how a repair becomes a programme. So the website now runs tsc --noEmit too.
The cost is real. A type-checker is not a linter. React hooks rules and accessibility rules that eslint-config-next would catch stay unchecked, and so do the website's scripts ending in .mjs.
I put the gate in scripts/release.sh after build and before test. After build, because both halves need build output: with the content package's output parked, the type-check fails with Cannot find module plus seven cascading errors. Before test, because it is the cheap gate and there is no reason to spend the slow suite to find a type error.
Words that mean something else
The second fix was vocabulary. AIDLC talks in words it never defined. Across the 17 shipped skills, instance appears 161 times, template 46, artifact 44, scope 41 and claim 39. There was no glossary anywhere, not in the project and not on the website.
Difficulty was not the problem. A developer learns artifact and phase unaided. The costly words are the three that already mean something else in software, because the reader does not feel confused. They feel sure, and find out later. An instance is usually an object or a server, here it is one unit of work. Scope usually means how much is included, here it picks which phases apply. A claim sounds like an assertion, and it is a lock. Seven internal type names, fourteen occurrences, were also leaking into prose for humans.
The definitions live in one file, packages/content/glossary.yaml, with ten terms. Skill bodies expand {{glossary:<term>}} placeholders through a third pass in the existing resolver, about twenty lines, and the site renders a glossary page at /docs/glossary from the same file. There are 37 placeholders across 15 skills and 20 new tests. Writing the definitions inline across 17 skills would have made up to 17 copies free to drift.
I declined tracking which terms you have already seen. It adds state that can go stale to avoid repeating a one-line definition. And I deferred renaming instance. It is the worst mismatch and also load-bearing across state files, YAML keys, CLI flags and every project on disk. I am betting that explaining it well makes the rename unnecessary. That question is now its own costing spike.