Context
From the pr-gate integration review of PR #1387 (claude lane). The repo now has two independently implemented import-boundary guards with divergent mechanics:
The divergence cuts both ways:
- The sdk's node-adapter rule has the same gap codex caught in streamdeck's guard: a side-effect or dynamic import of
./node/ slips past a from-clause-only regex. - The streamdeck guard can false-positive: a block comment containing a line shaped like
import … from '…' trips it — apps/streamdeck/src/plugin.ts already discusses the dissolved client package in prose, one reformat away from a spurious failure.
Scope
Extract one shared, fixture-tested specifier extractor (all five import forms + comment stripping) into a common test helper and use it from both guards. Policy stays per-package (sdk keeps its denylist, streamdeck its allowlist); only the extraction mechanics are shared.
Notes
Context
From the pr-gate integration review of PR #1387 (claude lane). The repo now has two independently implemented import-boundary guards with divergent mechanics:
packages/sdk's guard: denylist over raw source text, withstripComments(), but its node-adapter rule matchesfrom-clause imports only.apps/streamdeck's guard: allowlist over extracted specifiers, covering static / re-export / side-effect / dynamic /require()forms (hardened twice during Migrate the Stream Deck plugin into the monorepo as apps/streamdeck, consuming @cluesmith/codev-sdk #1347 review), but with no comment stripping.The divergence cuts both ways:
./node/slips past afrom-clause-only regex.import … from '…'trips it —apps/streamdeck/src/plugin.tsalready discusses the dissolved client package in prose, one reformat away from a spurious failure.Scope
Extract one shared, fixture-tested specifier extractor (all five import forms + comment stripping) into a common test helper and use it from both guards. Policy stays per-package (sdk keeps its denylist, streamdeck its allowlist); only the extraction mechanics are shared.
Notes
apps/streamdeck/src/__tests__/import-boundary.test.tsand should move with it.