Skip to content

ci: verify documented npm commands exist (and drop two that never did) - #249

Open
joeVenner wants to merge 2 commits into
yc-software:mainfrom
joeVenner:chore/lint-documented-npm-scripts
Open

ci: verify documented npm commands exist (and drop two that never did)#249
joeVenner wants to merge 2 commits into
yc-software:mainfrom
joeVenner:chore/lint-documented-npm-scripts

Conversation

@joeVenner

@joeVenner joeVenner commented Aug 6, 2026

Copy link
Copy Markdown

fly/README.md documents two commands that do not exist:

FLY_API_TOKEN="$(fly tokens create deploy -a "$FLY_SANDBOX_APP_NAME")" npm run smoke:fly
FLY_API_TOKEN=... npm run smoke:x

Neither smoke:fly nor smoke:x is defined in any package.json, and git log -S shows neither has ever been defined in this repository's history. There is no scripts/fly-smoke.ts either, so the paragraph describing what "the smoke test" backs up and restores documents a run nobody can perform. The X_SMOKE_REQUIRE_AUTH and X_SMOKE_REQUIRE_FIREHOSE env vars in the same block appear nowhere outside that file.

The interesting part isn't the two stale blocks — it's that nothing would have caught them. Every other class of rot in this repo has a gate: knip for dead code, oxlint and eslint for source, prettier for formatting. Documented commands had none, so these sat indefinitely.

So this PR is mostly the guard, with the two fixes that make it pass.

Commits

docs(fly): drop smoke commands that were never implemented — removes the two command blocks and the prose that exists only to describe them. Removed rather than corrected because there is no correct name to point at; if those scripts are pending, the right move is to re-add the docs with them and I'm happy to drop this commit. The npm run smoke:git-cli block below it is real and is left untouched.

ci: verify documented npm commands exist — adds scripts/check-doc-npm-scripts.mjs, a lint:docs script, and one step in the lint job next to lint:knip / lint:ox. It reads every tracked *.md, extracts each npm run <script>, and fails if no tracked package.json defines that script.

The one design decision

Resolution is a union across all packages, not the package nearest the file. Docs legitimately show commands to run from another directory — root README.md documents npm run build and npm run serve, which only plugins/web-ui and cli define — so matching per directory would reject correct docs.

The tradeoff: the union catches the case that matters (a command no package defines anywhere) but cannot catch a command documented against the wrong directory. I went with the version that has no false positives, on the grounds that a lint gate which fires on correct docs gets ignored or removed. Happy to tighten it if you'd rather have the stricter check plus an allowlist.

Verification

On this branch the checker reports:

Checked 26 documented npm command(s) (14 distinct) across 7 packages — all defined.

Against main before the docs commit, it reports exactly the two real hits and nothing else — no false positives across the whole repo, including .claude/skills/*.md, cli/, fly/, deploy/, and the plugin READMEs:

  fly/README.md:181: npm run smoke:fly
  fly/README.md:187: npm run smoke:x

Negative-tested by appending npm run definitely-not-a-script to deployment.md — caught with file:line, exit 1.

Full lint job run locally and green: format:check, lint, lint:knip, lint:ox, lint:docs. Commits are ordered so each is green on its own — the docs fix lands before the gate that would flag it.

Nothing outside the lint job is touched, so no runtime, test, or build behavior changes.

Note on process

CONTRIBUTING.md asks for bugs as issues rather than PRs, and I want to be upfront that I'm aware of that. I went with a PR here because the substance is a CI script rather than a product change, and describing it in prose seemed strictly worse than showing it. If you'd prefer this as an issue, or as an adrs/ note, say the word and I'll move it.

Separately, I filed #248 for an unrelated bug in plugins/chassis/src/http.ts following the issue path.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

fly/README.md documents `npm run smoke:fly` and `npm run smoke:x`, and
env vars X_SMOKE_REQUIRE_AUTH / X_SMOKE_REQUIRE_FIREHOSE that go with
them. Neither script is defined in any package.json, and `git log -S`
shows neither has ever been defined in this repo's history. The two env
vars appear nowhere outside this file. There is no corresponding
scripts/fly-smoke.ts either, so the paragraph describing what "the
smoke test" backs up and restores documents a run nobody can perform.

Removed rather than corrected because there is no correct name to point
at. The `npm run smoke:git-cli` block below is real and is left alone.
The stale `npm run smoke:fly` / `npm run smoke:x` blocks removed in the
previous commit sat in fly/README.md indefinitely because nothing
checks that a command shown in the docs is a command you can run. Every
other class of rot here has a gate — knip for dead code, oxlint and
eslint for source, prettier for formatting — so add the equivalent for
documented commands and run it in the lint job alongside them.

The check reads every tracked *.md, extracts each `npm run <script>`,
and fails if no tracked package.json defines that script.

Resolution is deliberately a union across all packages rather than the
package nearest the file. Docs legitimately show commands to run from
another directory — README.md documents `npm run build` and `npm run
serve`, which only plugins/web-ui and cli define — so matching per
directory would reject correct docs. The union still catches the case
that matters: a command no package defines anywhere. It cannot catch a
command documented against the wrong directory.

Currently clean at 26 references, 14 distinct, across 7 packages.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant