[E00-S01-T14] No core package imports a concrete extension #381

Merged
kpcto merged 1 commits from feature/167 into main 2026-08-28 23:26:42 +00:00
Member

What changed

Locks in the [E00-S01-T14] boundary that no core package imports a concrete extension (#167). The workspace is already compliant (the bootstrap packages/core has no imports), and the architecture import test that enforces the boundary — rule + scanner — was delivered by E00-S01-T04 (explicitly out of scope here, untouched). This PR adds the lock-in suite that pins T14's two acceptance criteria to the committed state:

  • tests/no-core-extension-imports.test.mjs (new) — a node:test suite (zero dependencies, lockfile untouched):
    • asserts the architecture import test is committed, still carries the real-graph enforcement, is covered by the root scripts.test glob (tests/**/*.test.mjs, so a violation fails pnpm test), and that dependency-boundaries.json forbids the packages -> extensions edge;
    • runs the architecture import test against the real workspace and asserts it exits 0 — no packages/* source file imports anything that resolves to extensions/*;
    • mutation probe: builds a minimal temp workspace copy with a core → extension import injected (import { register } from '@personal-blog/example-extension'; in packages/core/src/index.ts) and asserts the architecture import test exits non-zero, naming the offending file and the packages -> extensions rule — proving the test catches any such import;
    • probe sanity: the same temp workspace without the import passes, so the mutation failure is caused by the injected import, not the fixture.

Explicitly out of scope per the brief (not touched): frozen lockfile clean install (E00-S01-T13), dependency-boundary rule/test (E00-S01-T04) — dependency-boundaries.json and tests/architecture-import.test.mjs are unchanged. No manifests, no lockfile, no CI workflow changes.

Criterion → test table

Acceptance criterion Test (fails without the committed state)
no core package imports a concrete extension tests/no-core-extension-imports.test.mjs — "no core package imports a concrete extension (architecture import test passes on the real workspace)": runs node --test tests/architecture-import.test.mjs on the real workspace and asserts exit 0. Non-vacuous: the mutation probe proves that any core → extension import in a packages/* source makes the architecture import test fail, so a compliant result means the scanner really checked and found nothing
the architecture import test catches any such import tests/no-core-extension-imports.test.mjs — "the architecture import test is committed, wired into the root suite, and forbids the edge" (file committed with the real-graph test, covered by the root scripts.test glob, dependency-boundaries.json forbids packages -> extensions) and "the architecture import test catches a core -> extension import (mutation probe)" (a temp workspace copy with an injected core → extension import fails the architecture test with a per-file/line packages -> extensions violation report)

Test plan executed

  • node --test tests/no-core-extension-imports.test.mjs (Node 24, v24.20.0) → 4/4 pass ✓
  • node --test tests/architecture-import.test.mjs (Node 24) → 10/10 pass ✓
  • Full root suite node --test "tests/**/*.test.mjs" on Node 24 (v24.20.0) → 51/51 pass, exit 0 ✓
  • Mutation probe detail: injected import { register } from '@personal-blog/example-extension'; into packages/core/src/index.ts → architecture test fails with packages/core/src/index.ts:1 imports @personal-blog/example-extension (@personal-blog/example-extension [extensions]) — violates packages -> extensions; reverted ✓
  • corepack pnpm install --frozen-lockfile (pnpm 11.23.0) → unchanged, lockfile untouched; the CI job runs the same frozen install on the PR head ✓

Risks / notes

  • The suite spawns the architecture import test as a subprocess and strips NODE_TEST_CONTEXT from the child env so node --test does not treat it as a recursive run and skip the files.
  • The temp-workspace fixture mirrors the three bootstrap packages (apps/server, packages/core, extensions/example) that the architecture test's integration case expects to discover; as the workspace grows, only that fixture — not the enforcement — needs extending.
  • No change to the T04 rule/test, root scripts, manifests, lockfile or CI; the CI frozen-install job stays green.

Refs #167

## What changed Locks in the [E00-S01-T14] boundary that no core package imports a concrete extension (#167). The workspace is already compliant (the bootstrap `packages/core` has no imports), and the architecture import test that enforces the boundary — rule + scanner — was delivered by E00-S01-T04 (explicitly out of scope here, **untouched**). This PR adds the lock-in suite that pins T14's two acceptance criteria to the committed state: - **`tests/no-core-extension-imports.test.mjs`** (new) — a `node:test` suite (zero dependencies, lockfile untouched): - asserts the architecture import test is committed, still carries the real-graph enforcement, is covered by the root `scripts.test` glob (`tests/**/*.test.mjs`, so a violation fails `pnpm test`), and that `dependency-boundaries.json` forbids the `packages -> extensions` edge; - runs the architecture import test against the **real workspace** and asserts it exits 0 — no `packages/*` source file imports anything that resolves to `extensions/*`; - **mutation probe**: builds a minimal temp workspace copy with a core → extension import injected (`import { register } from '@personal-blog/example-extension';` in `packages/core/src/index.ts`) and asserts the architecture import test exits non-zero, naming the offending file and the `packages -> extensions` rule — proving the test catches any such import; - **probe sanity**: the same temp workspace without the import passes, so the mutation failure is caused by the injected import, not the fixture. Explicitly out of scope per the brief (not touched): frozen lockfile clean install (E00-S01-T13), dependency-boundary rule/test (E00-S01-T04) — `dependency-boundaries.json` and `tests/architecture-import.test.mjs` are unchanged. No manifests, no lockfile, no CI workflow changes. ## Criterion → test table | Acceptance criterion | Test (fails without the committed state) | | --- | --- | | no core package imports a concrete extension | `tests/no-core-extension-imports.test.mjs` — "no core package imports a concrete extension (architecture import test passes on the real workspace)": runs `node --test tests/architecture-import.test.mjs` on the real workspace and asserts exit 0. Non-vacuous: the mutation probe proves that any core → extension import in a `packages/*` source makes the architecture import test fail, so a compliant result means the scanner really checked and found nothing | | the architecture import test catches any such import | `tests/no-core-extension-imports.test.mjs` — "the architecture import test is committed, wired into the root suite, and forbids the edge" (file committed with the real-graph test, covered by the root `scripts.test` glob, `dependency-boundaries.json` forbids `packages -> extensions`) **and** "the architecture import test catches a core -> extension import (mutation probe)" (a temp workspace copy with an injected core → extension import fails the architecture test with a per-file/line `packages -> extensions` violation report) | ## Test plan executed - `node --test tests/no-core-extension-imports.test.mjs` (Node 24, v24.20.0) → **4/4 pass** ✓ - `node --test tests/architecture-import.test.mjs` (Node 24) → **10/10 pass** ✓ - Full root suite `node --test "tests/**/*.test.mjs"` on Node 24 (v24.20.0) → **51/51 pass**, exit 0 ✓ - Mutation probe detail: injected `import { register } from '@personal-blog/example-extension';` into `packages/core/src/index.ts` → architecture test fails with `packages/core/src/index.ts:1 imports @personal-blog/example-extension (@personal-blog/example-extension [extensions]) — violates packages -> extensions`; reverted ✓ - `corepack pnpm install --frozen-lockfile` (pnpm 11.23.0) → unchanged, lockfile untouched; the CI job runs the same frozen install on the PR head ✓ ## Risks / notes - The suite spawns the architecture import test as a subprocess and strips `NODE_TEST_CONTEXT` from the child env so `node --test` does not treat it as a recursive run and skip the files. - The temp-workspace fixture mirrors the three bootstrap packages (apps/server, packages/core, extensions/example) that the architecture test's integration case expects to discover; as the workspace grows, only that fixture — not the enforcement — needs extending. - No change to the T04 rule/test, root scripts, manifests, lockfile or CI; the CI frozen-install job stays green. Refs #167
bot-implementer added 1 commit 2026-08-28 23:24:36 +00:00
test: lock in no core package imports a concrete extension (E00-S01-T14)
CI / Frozen lockfile install (pull_request) Successful in 47s
27851fcaeb
kpcto merged commit 2b293e2927 into main 2026-08-28 23:26:42 +00:00
kpcto deleted branch feature/167 2026-08-28 23:26:43 +00:00
Sign in to join this conversation.