Skip to content

79 co-located test files are typechecked by nothing — typecheck:tests is a glob over packages/*/tsconfig.test.json, and packages/web-search shipped 16 files outside it #946

Description

@sroussey

What

package.json:32:

"typecheck:tests": "for f in packages/*/tsconfig.test.json; do echo \"typecheck $f\" && tsc -p \"$f\" || exit 1; done"

That glob is the only thing that typechecks a co-located test. A workspace with co-located tests and no tsconfig.test.json is silently outside it — and packages/web-search, the window's new package, is exactly that. Its own tsconfig.json excludes them:

$ tail -2 packages/web-search/tsconfig.json
  "exclude": ["dist", "node_modules", "src/**/__tests__/**", "src/**/*.test.ts"]
}
$ ls packages/web-search/tsconfig.test.json
ls: cannot access 'packages/web-search/tsconfig.test.json': No such file or directory

So its 16 test files are excluded from the build project and invisible to the test typecheck. Measured across the tree:

$ for d in packages/* providers/* examples/*; do [ -d "$d/src" ] || continue
    n=$(find $d/src -name '*.test.ts' | wc -l); [ "$n" -eq 0 ] && continue
    t=no; [ -f "$d/tsconfig.test.json" ] && t=YES
    printf "%-42s %4d  %s\n" "$d" "$n" "$t"; done

packages/ai                                  40  YES
packages/job-queue                           14  YES
packages/knowledge-base                       3  YES
packages/mcp                                 11  YES
packages/storage                             31  YES
packages/task-graph                         110  YES
packages/test                               441  no   (its own tsconfig includes src/**/*)
packages/util                                41  YES
packages/web-search                          16  no
providers/anthropic                           1  no
providers/google-gemini                       1  no
providers/openai                              1  no
providers/openrouter                          1  no
examples/cli                                 44  no
examples/eval                                15  no
examples/web                                  3  no

79 files (16 + 4 + 44 + 15 + 3) are typechecked by no gate. examples/* is doubly invisible: it is also absent from scripts/typecheck-budget.json, which prints no examples/ row at all.

Proof — planted, then measured

$ printf '\nconst PLANTED_TYPE_ERROR: number = "not a number";\nvoid PLANTED_TYPE_ERROR;\n' \
    >> packages/web-search/src/__tests__/limitResults.test.ts

$ bun run typecheck:tests
typecheck packages/ai/tsconfig.test.json
typecheck packages/job-queue/tsconfig.test.json
typecheck packages/knowledge-base/tsconfig.test.json
typecheck packages/mcp/tsconfig.test.json
typecheck packages/storage/tsconfig.test.json
typecheck packages/task-graph/tsconfig.test.json
typecheck packages/util/tsconfig.test.json
EXIT=0

$ bunx tsc -p packages/web-search/tsconfig.json --noEmit ; echo $?
0

$ bunx vitest run packages/web-search/src/__tests__/limitResults.test.ts
 Test Files  1 passed (1)
      Tests  4 passed (4)

const x: number = "not a number" in a shipped package's test file survives typecheck:tests, tsc -p on the package, and the test run. vitest transpiles without typechecking, so nothing anywhere sees it.

Why it matters

This is the same class 6ddf7d41 found and fixed in the 2026-08-10 window — "tsconfig.test.json was referenced by nothing, leaving ~330 relocated files type-checked nowhere" — reintroduced by the next new package, because the fix was a glob rather than a guard. The failure mode is quiet: build passes (tests are excluded from the build project), test passes (vitest transpiles), lint passes (oxlint reports rules, not TS diagnostics), and only a human reading the file notices.

3c0480d91's own follow-up commit is the live example of the cost when the gate does exist: "typecheck-budget runs typecheck:tests, which I had not run before pushing — lint and the suites were green, and vitest transpiles without typechecking, so nothing local caught it." For packages/web-search there is no equivalent backstop at all.

Proposed fix

  1. Add packages/web-search/tsconfig.test.json, copying packages/mcp/tsconfig.test.json verbatim (it is 12 lines and already parameterless).
  2. Replace the shell glob with a guard that derives the set the way scripts/lib/testDiscovery.ts already derives test sections: for every workspace under packages/, providers/ and examples/ that contains a *.test.ts under src/, require a tsconfig.test.json and run it. A workspace with co-located tests and no project file should fail the job, not be skipped by it — the current glob cannot tell "no tests" from "no project".
  3. That guard belongs in the existing typecheck-budget job (.github/workflows/test.yml:31-54), which already calls typecheck:tests.

Measured on origin/main @ 2d36880 (0.6.0). bun run typecheck:tests takes 21.6s across the seven projects it currently covers, so adding six more is cheap.

Found during the 2026-09-14 review of packages/.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions