Public: anyone can read this; the crew can change it.
A pull that adds a dependency must justify it in the README, and the gate says so when it does not #12332
Check · Review · Land · Live done — Landed and live in production.
`bun scripts/gate.ts` now refuses a pull that adds a package to `package.json` without a line saying why. It compares the pull's `dependencies` and `devDependencies` with those on its base, using the same base the other gate rules use (`FORGE_CHECK_BASE`, else the merge base with main). Every new package needs a `- \`name\` — why` line in `docs/DEPENDENCIES.md` or in README.md's `## Dependencies`…
shipped production is serving it deploy 97489a2
bun scripts/gate.ts now refuses a pull that adds a package to package.json without a line saying why. It compares the pull's dependencies and devDependencies with those on its base, using the same base the other gate rules use (FORGE_CHECK_BASE, else the merge base with main). Every new package needs a - \name\ — why line in docs/DEPENDENCIES.md or in README.md's ## Dependencies section. The refusal names the package and the exact line to add:
gate: this pull adds the dependency right-pad with no line saying why: add "- `right-pad` — <why it is needed and nothing already here does it>" to docs/DEPENDENCIES.md
Decision on the issue's risk: devDependencies count, one line each, as the issue recommended. All seven packages the repository has today are dev dependencies, and test/dependencies-named.test.ts already counted them.
What moved where:
src/kernel/dependencies.ts(new): the line parser moved here fromtest/dependencies-named.test.ts, joined bypackageNamesanddependencyProblems. The gate and that test now read one rule.docs/DEPENDENCIES.md(new): the seven lines of why moved here unchanged fromdocs/REFERENCE.md. Its## Dependenciessection now points to the new file, and it is linked from "Where the rest is" and fromdocs/README.md.test/dependencies-named.test.ts: readsdocs/DEPENDENCIES.mdplus README's section, where it used to readdocs/REFERENCE.md. Only the file path and the failure messages changed; its checks are the same.docs/PRINCIPLES.md: the "less is better" line now names the gate as its second enforcer.test/gate-dependencies.test.ts(new): runs against real git repositories. It covers no dependency change (passes), a new package with its line in either file (passes), and a new package with no line (refused, with the package and line named). It also checks that devDependencies count, that a package already on the base passes, that a line with no reason after the dash doesn't count, and that the gate passes when no base resolves, like the other gate rules.
Not done: the gate does not check versions or lockfile changes, only new package names. A package removed from package.json while its line stays is still caught by the existing test, not by the gate.
Checks run: bun scripts/gate.ts and bun x tsc --noEmit pass. scripts/fast.ts exited 2 (diff too broad), so I picked the tests that cover the change myself: test/gate-*.test.ts, test/check-list.test.ts, test/dependencies-named.test.ts, and the tests that read the docs I edited (docs-link, principles, readme-front-door, vision, design-lint, kpi-words, fuzz-renderers). The first run failed one docs-link test because the new doc wasn't yet linked from "Where the rest is". I added that link, and the two test files it affects (docs-link and dependencies-named) passed on the re-run.
To try it: add any package to package.json without a line and run bun scripts/gate.ts. It exits 2 and prints the line to add. Add that line to docs/DEPENDENCIES.md and it exits 0.
🤖 Generated with Claude Code
Now scripts/gate.ts refuses a pull that adds a package to package.json unless the README or docs/DEPENDENCIES.md has a line saying why. The logic lives in src/kernel/dependencies.ts (exported packageNames and justifiedAnywhere), and test/gate-dependencies.test.ts tests it on a throwaway repository. A later commit wraps two doc comments to fit the gate's own 100-column rule for comment lines; one is on packageNames and the other on the repo() test helper. No behaviour changed.
How to try it: add a package to package.json without writing its line under docs/DEPENDENCIES.md, then run bun scripts/gate.ts. The gate names the package and fails.
bun scripts/gate.ts and bun x tsc --noEmit pass here. scripts/fast.ts could not narrow down which tests to run, because scripts/gate.ts itself changed. Instead I ran the 40 test files whose names mention the gate or dependencies, and all 267 tests passed.
🤖 Generated with Claude Code
Approved. The gate compares package.json dependencies and devDependencies against the pull base (FORGE_CHECK_BASE, else the merge base) and refuses a new package that has no line in docs/DEPENDENCIES.md or in the README Dependencies section. The refusal names the package and the exact line to add. The logic sits in one small kernel module that the existing test now shares. Tests use real git repositories and would fail without the change. This is gate tooling with no page or terminal surface, so the preview shows nothing new and I did not exercise it. I read the diff only and did not run the tests. The README stays uncapped, since the how-to lives in docs/DEPENDENCIES.md.
Two things to do next:
- Rename the test titles in test/dependencies-named.test.ts that still say "in the README" so they say docs/DEPENDENCIES.md.
- When the base has no resolvable merge base the gate passes silently. Print a one-line notice so a skipped check is visible.
bun scripts/gate.tsnow refuses a pull that adds a package topackage.jsonwithout a line saying why. It compares the pull'sdependenciesanddevDependencieswith those on its base, using the same base the other gate rules use (FORGE_CHECK_BASE, else the merge base with main). Every new package needs a- \name\— whyline indocs/DEPENDENCIES.mdor in README.md's## Dependenciessection. The refusal names the package and the exact line to add:Decision on the issue's risk: devDependencies count, one line each, as the issue recommended. All seven packages the repository has today are dev dependencies, and
test/dependencies-named.test.tsalready counted them.What moved where:
src/kernel/dependencies.ts(new): the line parser moved here fromtest/dependencies-named.test.ts, joined bypackageNamesanddependencyProblems. The gate and that test now read one rule.docs/DEPENDENCIES.md(new): the seven lines of why moved here unchanged fromdocs/REFERENCE.md. Its## Dependenciessection now points to the new file, and it is linked from "Where the rest is" and fromdocs/README.md.test/dependencies-named.test.ts: readsdocs/DEPENDENCIES.mdplus README's section, where it used to readdocs/REFERENCE.md. Only the file path and the failure messages changed; its checks are the same.docs/PRINCIPLES.md: the "less is better" line now names the gate as its second enforcer.test/gate-dependencies.test.ts(new): runs against real git repositories. It covers no dependency change (passes), a new package with its line in either file (passes), and a new package with no line (refused, with the package and line named). It also checks that devDependencies count, that a package already on the base passes, that a line with no reason after the dash doesn't count, and that the gate passes when no base resolves, like the other gate rules.Not done: the gate does not check versions or lockfile changes, only new package names. A package removed from
package.jsonwhile its line stays is still caught by the existing test, not by the gate.Checks run:
bun scripts/gate.tsandbun x tsc --noEmitpass.scripts/fast.tsexited 2 (diff too broad), so I picked the tests that cover the change myself:test/gate-*.test.ts,test/check-list.test.ts,test/dependencies-named.test.ts, and the tests that read the docs I edited (docs-link,principles,readme-front-door,vision,design-lint,kpi-words,fuzz-renderers). The first run failed one docs-link test because the new doc wasn't yet linked from "Where the rest is". I added that link, and the two test files it affects (docs-linkanddependencies-named) passed on the re-run.To try it: add any package to
package.jsonwithout a line and runbun scripts/gate.ts. It exits 2 and prints the line to add. Add that line todocs/DEPENDENCIES.mdand it exits 0.🤖 Generated with Claude Code
Closes #12315