Skip to content

Inventory the packages/** tests that import examples/** live, with their CI visibility - #8945

Merged
os-project-manager merged 2 commits into
mainfrom
claude/issue-8754-examples-live-import-inventory
Aug 16, 2026
Merged

Inventory the packages/** tests that import examples/** live, with their CI visibility#8945
os-project-manager merged 2 commits into
mainfrom
claude/issue-8754-examples-live-import-inventory

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes#8754

Adds the missing inventory of packages/** tests that reach into examples/** live, plus the CI visibility each of those couplings actually has.

Scope

This card records and surfaces the coupling. It does not change any coupled test, and it does not pick between synthetic fixtures / frozen snapshots / a lint-time guard for them — that call is deliberately left open here. The gate grades discovery only: adding a new live coupling stays allowed, it just has to be recorded, so the next example-app edit can be checked against a list instead of against the shared merge queue.

Premise re-verified, not inherited

The card's discovery grep re-run on this branch's merge-base returns exactly the four files the card names — unchanged since the grading, despite main having moved a long way:

packages/cli/test/i18n-section-coverage.test.ts
packages/cli/test/i18n-tab-coverage.test.ts
packages/lint/src/validate-translatable-sections.test.ts
packages/lint/src/validate-translation-references.test.ts

Inventory output measured at origin/main = 7b3c0335dac0f9c01d2c536f12208cde53692305 (this branch's merge-base; origin/main was still at that commit when the run was taken). The tree is moving under this count, so the sha is the only thing that makes it reproducible.

What the scan found that the card's regex did not

The card's regex matches relative-path import/import()/require only. Measured against today's tree, its blind spots are real:

  • Under-match, filesystem reads.packages/qa/dogfood/test/showcase-declarative-mcp.dogfood.test.ts and ...-endpoints.dogfood.test.ts reach the app as a path (new URL('../../../../examples/app-showcase/', import.meta.url), then chdir). An import-only regex cannot see them.
  • Under-match, workspace package name. 63 dogfood tests import the apps as @objectstack/example-showcase / -crm. Invisible to a relative-path regex.
  • Over-match risk. Comments, JSDoc and non-specifier string literals mentioning examples/app-* are not couplings; a bare grep reports them. The scanner strips comments while preserving string contents, and both classes are pinned as negative self-test cases.
  • Genuinely unreadable. A dynamic import() with a computed specifier cannot be resolved statically. Rather than miss it silently, any test file with one that also mentions examples/ is reported under unresolved and fails the gate until recorded. None exist today.

The three tiers — because these couplings are not the same kind

Flattening them into one list would reproduce the unreliable heuristic the card is about. Classification is mechanical:

tiercountwhat CI can see
invisible4Neither layer. Examples-only PR does not run them; the queue is the first signal.
inputs-declared2Escapes by path, but the package declares an examples/** input glob on its #test task.
graph-visible63Imported by workspace package name with the dependency declared — turbo ls --affected reaches these.

packages/qa/dogfood declares both example apps as workspace:* dependencies and carries $TURBO_ROOT$/examples/app-showcase/** in turbo.json. packages/cli and packages/lint declare neither — which is precisely why their four files are the gap.

Only the invisible tier needs a hand-written entry, so the maintained half stays proportional to the gap while the other 65 enumerate themselves. Each entry carries a note saying what kind of coupling it is — set-equality over what the app declares today vs. an assertion that the shipped app is clean, and which namespace (_sections vs _tabs) it reads. That difference is why one cli file went red and its sibling did not.

This is the import-side complement to check-cross-package-test-inputs.mjs, which covers the same exposure on the filesystem-read axis.

Usage

pnpm examples:live-imports # the inventory, incl. a reverse index by example-app source file
pnpm check:examples-live-imports # the gate (self-test + both ratchet directions)

The reverse index answers the question a dev editing the app actually has — e.g. examples/app-showcase/src/ui/views/contact.view.ts lists all three coupled tests, with spellings normalised so contact.view and contact.view.js do not split into two entries.

Verification

Union re-run after the final commit, at dc86cb517, judged by exit status:

check:examples-live-imports PASS (exit 0) 4 invisible (declared), 2 inputs-declared, 63 graph-visible
check:node-version PASS (exit 0)
check:required-contexts PASS (exit 0)
check:shard-attestation PASS (exit 0)
check:workflow-status-functions PASS (exit 0)
check:nul-bytes PASS (exit 0)
check:type-check-coverage PASS (exit 0)
--self-test PASS (exit 0) 23/23 detector cases

Gate set derived by node scripts/pm/dispatch-gates.mjs on the real changed paths — it discovered the new gate itself, since it reads the workflows at runtime.

check:type-check-debt refuses to measure in a fresh worktree without a built closure (its documented guard against recording numbers from a different world). It is not implicated by this diff: no TS source, tsconfig or dependency changed, and the step lives in a separate typecheck: job that builds the closure immediately before running it — my step is in the lint: job. CI runs it with the closure built.

Ablation — the inventory was proven to DISCOVER, not just to re-list

An inventory only ever run against the files it was written from has never been shown to discover anything. Four legs:

  1. Planted a live-importing test in packages/rest — a package the inventory was not written from, with no declared edge. Gate went red (exit 1), naming the file, the app path it reaches, and the entry to add.
  2. Declared it → green (exit 0), 5 invisible.
  3. Deleted the file, kept the entry → red (exit 1), STALE entry, naming it for deletion. The ratchet holds in both directions, so the inventory cannot rot.
  4. Reverted. sha256 of the script is byte-identical to the committed version (8ffb4842…4043), planted file gone, git status clean.

scripts/ and workflows are not published package sources, so no changeset applies — skip-changeset.

Generated by Claude Code


Generated by Claude Code

@vercel

vercelBot commented Aug 16, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 16, 2026 2:03am

Request Review

@github-actionsgithub-actionsBot added size/l ci/cd dependencies Pull requests that update a dependency file labels Aug 16, 2026
@os-project-manageros-project-manager added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed ci/cd size/l dependencies Pull requests that update a dependency file labels Aug 16, 2026 — with Claude
@os-project-manager
os-project-manager marked this pull request as ready for review August 16, 2026 02:13
@os-project-manager
os-project-manager added this pull request to the merge queueAug 16, 2026
Merged via the queue into main with commit de776efAug 16, 2026
39 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-8754-examples-live-import-inventory branch August 16, 2026 02:31
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No inventory of packages/** tests that import examples/** live — an example-app edit can break one and no affected-subset CI run will surface it

2 participants

@os-project-manager@claude