Skip to content

fix(devx): graduate metadata-fs and example-showcase out of TEST_DEBT - #8061

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-7923-metadata-fs-showcase-typecheck-graduation
Aug 12, 2026
Merged

fix(devx): graduate metadata-fs and example-showcase out of TEST_DEBT#8061
hotlong merged 1 commit into
mainfrom
claude/issue-7923-metadata-fs-showcase-typecheck-graduation

Conversation

@hotlong

Copy link
Copy Markdown
Contributor

Fixes#7923

Graduates the two same-day candidates out of TEST_DEBT via the #5286 route, deleting each ledger entry in the same PR (RECONCILED forces the pair).

@objectstack/cli (188 raw / 56 files) is out of scope per triage's binding scope comment — it is a programme, not a graduation. No other entry's recorded number is touched (that is #7888's --lower job; #7888 remains open).

Re-measured before repair

The recorded counts were taken at older commits, so both layers were re-measured on the merged ref (3373a29) the same way the gate's measureTestDebt does — hidden test files added to include one at a time, rootDir neutralised:

packagerecordedre-measuredclasses
@objectstack/metadata-fs66TS6133 ×5, TS2349 ×1
@objectstack/example-showcase44TS2339 ×4

Both matched exactly, so the entries are deleted against measurements rather than against hope.

Route taken, per package

@objectstack/metadata-fs — sibling tsconfig.test.json, named by the typecheck script.
Its rootDir is src and dev emits (tsc --watch, outDir: dist), so widening rootDir in the build config would relocate dist/index.js to dist/src/index.js and start emitting compiled test files, which ci.yml gates against. The sibling carries the widened rootDir under noEmit instead. This package is a structural twin of packages/metadata-core, whose sibling config (#5476) is the model followed here. Strictness is inherited untouched — nothing is loosened.

The 6 errors were real and were fixed in the tests:

  • 5 × TS6133 in test/contract.test.ts — genuinely dead imports (describe, it, beforeEach, expect, MetaRef); the file registers the shared contract suite, which declares its own cases, so afterEach is the only hook it uses.
  • 1 × TS2349 in test/watch-write-registration.test.ts — the drain loop was written as an immediately-invoked async arrow. For an IIFE, tsc narrows a captured let to its type at the point of the call, so resolveNext (initialised null) narrowed to null and the optional call resolved to never. Binding the loop to a name and then calling it restores the declared type. Runtime behaviour is identical — the loop still starts there, unawaited.

@objectstack/example-showcase — widened include.
Its rootDir is already ., so nothing needed neutralising; this is the shape #7312 applied to app-crm / app-todo. The 4 × TS2339 were process.env reads against the package's minimal ambient shim (test/node-shim.d.ts declares only cwd()), fixed with the file-local declare const process idiom the package already uses in objectstack.config.ts and src/system/self-url.ts — no new dependency, no widened type surface.

The glob is spec-scoped (e2e + /**/*.spec.ts) rather than the wholesale e2e + /**/*, which holds the line the deleted entry's note drew. Confirmed by measurement: the wholesale glob pulls in e2e/global-setup.ts and bills the test layer 6 errors from a file that is not a test — 3 process.env reads plus 3 gaps in the shim (no mkdirSync/writeFileSync on the node:fs shim, no node:path module at all). That file stays outside the program and is filed separately rather than folded in here.

Reverse verification

Direction predicted before running: deleting a ledger entry without repairing its layer should fail TESTS_COVERED (not RECONCILED) — the entry is what was holding the hidden layer, so removing both the entry and the repair leaves the layer visible-but-unheld.

Measured by un-wiring metadata-fs's typecheck script with the entry already deleted. It went red in exactly that direction:

• @objectstack/metadata-fs (packages/metadata-fs): 6 of its test file(s) sit outside
every tsc program that accounts for this package -- named by an `exclude`, or never
reached by any `include` -- so the check reports green over source it never read

Restored afterwards; the gates below are from the restored tree.

Verification

Dependency closure built first (pnpm build, 71/71 tasks) — a bare debt-gate run exits 1 on a missing-module cascade.

  • pnpm check:type-check-coverageOK, 64/77 packages type-checked; test layer down to 20 packages hiding tests. Both entries gone.
  • pnpm check:type-check-debtOK, 33 entries re-measured, 1965 raw errors, none above its recorded number. Neither graduated package appears in the surplus list.
  • pnpm --filter @objectstack/metadata-fs typecheck — passes both programs; test — 6 files, 51 tests passed.
  • pnpm --filter @objectstack/example-showcase typecheck — passes; test — 20 files, 193 tests passed.
  • pnpm --filter @objectstack/metadata-fs build — dist layout unchanged (index.js/index.cjs/index.d.ts), no compiled tests in dist.
  • check:nul-bytes — OK; control-char self-scan over all changed files clean.
  • scripts/pm/dispatch-gates.mjs on the changed paths named exactly the two gates above.

Playwright specs are type-checked but not executed here — test:smoke needs a live server and is non-blocking nightly.

No changeset: tests, tsconfig and gate-script only, nothing user-visible is released. skip-changeset applied.


Generated by Claude Code

Both packages' test layers were hidden from tsc by an include-shaped hole
that #7353 taught TESTS_COVERED to see, and both were ledgered as measured
TEST_DEBT rather than repaired. This repairs them via the #5286 route and
deletes both entries in the same PR, which RECONCILED forces as a pair.
Re-measured on the merged ref before repair; both matched their recorded
numbers exactly (metadata-fs 6, example-showcase 4), so the entries are
deleted against measurements rather than against hope.
metadata-fs takes the sibling-config route. Its rootDir is `src` and `dev`
emits (`tsc --watch`, outDir dist), so widening rootDir in the BUILD config
would relocate dist/index.js and start emitting compiled tests; the sibling
tsconfig.test.json carries the widened rootDir under noEmit instead and is
named by the typecheck script. Its 6 errors were real: 5 dead imports
(TS6133, from the root config's noUnusedLocals) and one TS2349 where an
immediately-invoked drain loop made tsc narrow a captured `let` to `null`,
so the optional call resolved to `never`. Binding the loop to a name before
calling it restores the declared type; runtime behaviour is unchanged.
example-showcase takes the widened-include route (#7312's shape for
app-crm / app-todo) since its rootDir is already `.`. Its 4 TS2339 were
`process.env` reads against the package's minimal ambient shim, fixed with
the file-local `declare const process` idiom the package already uses in
objectstack.config.ts and src/system/self-url.ts. The include glob is
`e2e/**/*.spec.ts` and NOT `e2e/**/*`, holding the line the deleted entry's
note drew: the wholesale glob would pull in e2e/global-setup.ts, a fixture
rather than a test, and bill the layer 6 errors that are not its own.
@objectstack/cli stays in the ledger — a programme, not a graduation. No
other entry's recorded number is touched.
@vercel

vercelBot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 12, 2026 2:02pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 12, 2026 — with Claude
@github-actionsgithub-actionsBot added dependencies Pull requests that update a dependency file tests tooling and removed skip-changeset PR has no user-facing published change; bypasses the changeset gate labels Aug 12, 2026
@hotlonghotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 12, 2026 — with Claude
@hotlong
hotlong marked this pull request as ready for review August 12, 2026 14:33
@hotlong
hotlong added this pull request to the merge queueAug 12, 2026
Merged via the queue into main with commit d7c1e67Aug 12, 2026
34 of 36 checks passed
@hotlong
hotlong deleted the claude/issue-7923-metadata-fs-showcase-typecheck-graduation branch August 12, 2026 14:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gateteststooling

Projects

None yet

2 participants

@hotlong@claude