Skip to content

fix(cli): wire the test layer into check:test-typecheck — 115 test files no tsc program read - #14833

Merged
os-project-manager merged 5 commits into
mainfrom
claude/issue-14710-cli-test-typecheck
Sep 3, 2026
Merged

fix(cli): wire the test layer into check:test-typecheck — 115 test files no tsc program read#14833
os-project-manager merged 5 commits into
mainfrom
claude/issue-14710-cli-test-typecheck

Conversation

@os-trump

@os-trump os-trump commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #14710

packages/cli's typecheck was a bare tsc --noEmit against a config declaring
include: ["src"], so the 115 test files in the sibling test/ tree were read by no tsc
program anywhere. This wires the package into the shared check:test-typecheck mechanism
and seeds the resulting ledger.

File face

file what changes
packages/cli/tsconfig.test.json new — the test-layer program. Module semantics + rootDir only; strictness inherited and untouched.
packages/cli/test-typecheck-debt.json new — generated, EXACT and shrink-only, with an authored _note.
packages/cli/package.json typecheck becomes tsc --noEmit && pnpm check:test-typecheck; adds check:test-typecheck and gen:test-typecheck-debt.
scripts/check-type-check-coverage.mjs graduates this package's TEST_DEBT entry (144) and the UNCHECKED_SOURCE_DEBT row for packages/cli/test, each documented beside the earlier graduations.
scripts/check-type-source-resolution.mjs re-baseline: a new allowlist entry for the program this change makes visible.
scripts/regen-artifacts.mjs adds the new ledger so a merge never recomputes it on a half-merged tree.
.changeset/cli-test-typecheck-wiring.md patch, @objectstack/cli.

No test file is edited. Not one any, not one @ts-expect-error. The shared
scripts/check-test-typecheck.mts is called, never copied.

Measurement 1 — the population, re-measured on current main

The card said 112. It is 115: the tree moved between filing and dispatch. Measured at
5a5336b399 with the workspace closure built first, via
tsc --noEmit --listFiles -p tsconfig.json:

population on disk in the build program
test files under packages/cli/test/ 115 0
non-test src/** files (control) 119 119
test files under src/** (control) 121 121
package-root harness modules 3 0

The zero is the include line, not a blind probe — and the contrast sits inside this one
package
: tests under src always compiled, tests under test/ never did. Directional
control from a package with no test exclusion, packages/drivers/driver-memory: the same
probe puts 40 of its 40 test files in the program. Under tsconfig.test.json the count
is 115 of 115 (1416 files total), plus all 3 harness modules and
test/helpers/serve-process.ts.

Measurement 2 — the count, attributed in both directions with no remainder

The same file population under the build config's inherited NodeNext reports 144 — and
that reproduces the TEST_DEBT entry class for class (TS7006 x59, TS2835 x56, TS2339
x24, TS2307 x3, TS18046 x2), so the frozen number was still exact on the way out.

  • −120 dissolve under vitest-matching module semantics: TS2835 x56 (extension-less
    relative imports), the TS7006 x59 cascading above them, TS2307 x3, TS18046 x2. Config-tier,
    about the CHECK rather than the code.
  • 24 TS2339 survive unchanged, file for file and count for count.
  • +4 exposed by collapsing that cascade: TS18048 x4 in
    test/i18n-extract-action-description.test.ts, previously masked by an any from its two
    unresolved imports of ../src/utils/i18n-extract and ../src/utils/i18n-coverage.

144 − 120 + 4 = 28, across 3 of the 115 files. The other 112 carry no entry, so any error
they gain is red on arrival. The pile is concentrated: test/data-model-rules.test.ts is 23
of the 28 on its own, all property reads off one lint-diagnostic type.

A second config-tier pile, recorded so nobody re-derives it

This package's tests sit outside the build config's rootDir (src) — the one place
this differs from the packages/runtime precedent. Inherited, the same program adds 116 x
TS6059
. rootDir: "." is not enough either: three tests import fixtures from
examples/app-showcase/src/**, still 3 x TS6059. So rootDir is ../.., exactly the
shape packages/client's test config already uses. It widens the ROOT, never the strictness.

A claim in the filing that measurement did not support

The card's sharpest line — a @ts-expect-error in those files is a phantom check — is about
what would happen, not an existing dead pin. Measured: this layer holds zero
@ts-expect-error directives across all 115 files and the 3 harness modules, and none reports
TS2578. The real cost was the 144 diagnostics nothing read, and the inability to write a
type-level pin here at all.

Red-first proof, both ratchet directions

Each mutation proved on disk (marker count + blob hash), each restore proved by blob-hash
equality with HEAD
, under trap ... EXIT INT TERM on absolute paths.

leg subject gate
control 0 untouched tree exit 0
A — unledgered file gains an error test/commands.test.ts (blob 27e2996e to adab66a4, restored to 27e2996e) exit 1 — "1 type error(s) in a file the ledger does not cover"
B — ledgered file gains a new signature test/i18n-declared-surface-gate.test.ts (blob bb45724a to 131eb633, restored to bb45724a) exit 1 — "ARRIVED: TS2322 ..." at an unchanged file total
control 1 restored tree exit 0, git diff HEAD empty for both

Verification

Gate families derived from the real change set with scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
(44 owed by path and kind; 52 commands once the changeset exists). Run on final head
05163f41af, exit codes captured before any pipe. All green except five recorded
NOT MEASURED, each by the gate's own explicit prerequisite text, none a finding:

  • check:i18n, check:i18n-coverage, check:dual-build-cjs-loads — require build output this
    worktree does not carry ("Nothing was checked"). This diff changes package.json scripts
    only and cannot move a translation bundle.
  • check-test-completeness, pm/check-half-states — exit 3, their documented
    NOT-MEASURED code (a saved turbo run test log; API access).
  • check:type-check-debt: its --self-test (48+68+43+28+19+18 cases) and plain run are
    green; only the --re-measure half is unmeasured — it needs CI's dedicated
    "Build the ledgered packages' dependencies" step, and it exceeded the container's 10-minute
    foreground ceiling even holding the shared lock.

The ratchet family was re-run on the final commit after the last push.

Scope

⛔ Not done here, deliberately: whether the include-vs-exclude gap belongs in AGENTS.md or
in check:type-check-coverage itself. The card's triage explicitly held that back pending a
measurement of how many packages narrow include the same way. This gate's own scoreboard now
reads 10 packages still hide their own tests (down from 11), which is the honest count for
that class. Issue #14785 is the packages/runtime twin whose shape this follows; it is not
addressed here.

🤖 Generated with Claude Code

https://claude.ai/code/session_016yfqQh2dBgPAymYd7xipza


Generated by Claude Code

os-trump and others added 4 commits September 3, 2026 03:41
Ledger not yet seeded — intermediate commit so the wiring survives a
container restart. See the follow-up commit for the measured ledger.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yfqQh2dBgPAymYd7xipza
Seeds the measured ledger, graduates the TEST_DEBT and UNCHECKED_SOURCE_DEBT
entries, and re-baselines type-source-resolution for the new program.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yfqQh2dBgPAymYd7xipza
…tDir deviation

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016yfqQh2dBgPAymYd7xipza
@github-actions github-actions Bot added the size/m label Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/cli/test-typecheck-debt.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/cli/test-typecheck-debt.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 22 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json f116b8f8d1b43ec2bfd64fbf0ebb0cf3c301b1c8packageMentionDocs.

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Sep 3, 2026
@os-trump
os-trump marked this pull request as ready for review September 3, 2026 05:19
@os-trump
os-trump enabled auto-merge September 3, 2026 05:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

packages/cli typecheck compiles none of the 112 test files under test/include: ["src"] makes the green verdict empty for half the suite

2 participants