The check tables in AGENTS.md and CONTRIBUTING.md name uv run mypy src/visionset/kernel,
which reads 72 source files. scripts/check.sh runs uv run mypy src/visionset, which reads 171.
Somebody who runs the documented command and sees it pass has checked well under half of what the
gate checks, and has no signal that anything is missing.
This is not hypothetical. The batch pre-labeling work carried a real type error in
src/visionset/server/routes/batches.py — a Batch.schema_version typed int | None passed to
SchemaService.get, which requires int — through six tasks and eight reviews. Every one of
those runs reported the documented mypy command green, because the file the error lived in is not
in the kernel. It surfaced only when somebody ran scripts/check.sh for an unrelated reason.
The frontend half has the same shape. pnpm -r build && pnpm -r test && pnpm -r lint is the
natural reading of the frontend check rows, and it runs no Playwright at all, so a change can
leave an e2e assertion stale and still look complete. The same branch shipped a test asserting a
capability was unconsumed after making it consumed, and nothing caught it until the browser stages
ran.
The pattern is that every narrower command in the documentation is a subset of check.sh, and
nothing in the documentation says so. A reader reasonably treats the rows in a check table as the
checks.
Two directions, either of which fixes it, and the choice is a judgement about how the tables are
meant to be read:
- Make the documented commands match what the gate runs, so
mypy src/visionset is what the
tables say and the frontend rows name the browser stages.
- Keep the narrow commands as an explicitly-labelled inner loop, and state in both tables that
bash scripts/check.sh is the gate and the rows above it are a subset.
The second is closer to what the commands are actually for — the narrow mypy is genuinely useful
while iterating on the kernel — but it only works if the subset relationship is stated where the
commands are, rather than inferred.
The check tables in
AGENTS.mdandCONTRIBUTING.mdnameuv run mypy src/visionset/kernel,which reads 72 source files.
scripts/check.shrunsuv run mypy src/visionset, which reads 171.Somebody who runs the documented command and sees it pass has checked well under half of what the
gate checks, and has no signal that anything is missing.
This is not hypothetical. The batch pre-labeling work carried a real type error in
src/visionset/server/routes/batches.py— aBatch.schema_versiontypedint | Nonepassed toSchemaService.get, which requiresint— through six tasks and eight reviews. Every one ofthose runs reported the documented mypy command green, because the file the error lived in is not
in the kernel. It surfaced only when somebody ran
scripts/check.shfor an unrelated reason.The frontend half has the same shape.
pnpm -r build && pnpm -r test && pnpm -r lintis thenatural reading of the frontend check rows, and it runs no Playwright at all, so a change can
leave an e2e assertion stale and still look complete. The same branch shipped a test asserting a
capability was unconsumed after making it consumed, and nothing caught it until the browser stages
ran.
The pattern is that every narrower command in the documentation is a subset of
check.sh, andnothing in the documentation says so. A reader reasonably treats the rows in a check table as the
checks.
Two directions, either of which fixes it, and the choice is a judgement about how the tables are
meant to be read:
mypy src/visionsetis what thetables say and the frontend rows name the browser stages.
bash scripts/check.shis the gate and the rows above it are a subset.The second is closer to what the commands are actually for — the narrow mypy is genuinely useful
while iterating on the kernel — but it only works if the subset relationship is stated where the
commands are, rather than inferred.