brainy/tests/unit/boundary-no-native.test.ts
David Snelling b198281ce1 test(8.0): boundary guard forbids @soulcraft/cor too (cortex→cor rename)
The open/closed separation test now forbids the proprietary native package under
BOTH names (@soulcraft/cor + legacy @soulcraft/cortex) — in any dependency field
and any static import under src/ or tests/. Renamed boundary-no-cortex →
boundary-no-native. This is load-bearing for the lockstep model: because brainy
cannot depend on cor, the combined brainy-8.0 × cor-3.0 integration matrix lives
in the cor repo (which devDeps brainy), not here.
2026-06-19 09:03:54 -07:00

77 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @module tests/unit/boundary-no-native
* @description Enforces the open-source / proprietary boundary in CI: the public
* MIT Brainy repo must never DEPEND ON the proprietary native-acceleration
* package to build or test. That package is **`@soulcraft/cor`** (formerly
* `@soulcraft/cortex` — both names are guarded here through the rename
* transition). Brainy may NAME it (docs say `npm install @soulcraft/cor`, error
* messages point at its `idSpace:'u64'` mode) and registering it through the
* public plugin API is the supported runtime path — but nothing in `src/` or
* `tests/` may statically `import`/`require` it, and it must not appear in any
* dependency field.
*
* This is load-bearing for the lockstep release model: because brainy cannot
* depend on `@soulcraft/cor`, the combined brainy-8.0 × cor-3.0 integration
* matrix (the "every code path proven with both engines" proof) lives in the
* **cor** repo, which devDeps brainy — NOT here. See handoff LOCKSTEP-VERIFY.
* If this test ever needs `@soulcraft/cor` to go green, the boundary has been
* violated and an optional integration became a hard coupling on a private build.
*/
import { describe, it, expect } from 'vitest'
import * as fs from 'node:fs'
import * as path from 'node:path'
import { fileURLToPath } from 'node:url'
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
const SELF = fileURLToPath(import.meta.url)
/** The proprietary native package, across the cortex→cor rename. */
const NATIVE_PACKAGES = ['@soulcraft/cor', '@soulcraft/cortex'] as const
/** Recursively collect .ts/.js/.mjs/.cjs files under a directory. */
function sourceFiles(dir: string): string[] {
const out: string[] = []
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name.startsWith('.')) continue
const full = path.join(dir, entry.name)
if (entry.isDirectory()) out.push(...sourceFiles(full))
else if (/\.(ts|js|mjs|cjs)$/.test(entry.name) && full !== SELF) out.push(full)
}
return out
}
// Matches a real module specifier for the native package in an
// import/require/dynamic-import — NOT a bare string mention (docs / JSDoc /
// error-message / mock-name are allowed). `@soulcraft/cor` and
// `@soulcraft/cortex` both match; `@soulcraft/core` (a different name) does not,
// because the package must be followed by a subpath separator or the closing quote.
const NATIVE_MODULE =
/(?:import\s[^'"]*from\s*|import\s*\(\s*|require\s*\(\s*)['"]@soulcraft\/cor(?:tex)?(?:\/[^'"]*)?['"]/
describe('open/proprietary boundary — public repo must not depend on @soulcraft/cor', () => {
it('no src/ or tests/ file imports or requires the native package', () => {
const offenders: string[] = []
for (const dir of ['src', 'tests']) {
for (const file of sourceFiles(path.join(repoRoot, dir))) {
if (NATIVE_MODULE.test(fs.readFileSync(file, 'utf8'))) {
offenders.push(path.relative(repoRoot, file))
}
}
}
expect(offenders, `These files statically depend on the proprietary package — use the public plugin API at runtime instead:\n${offenders.join('\n')}`).toEqual([])
})
it('the native package is in no dependency field of package.json', () => {
const pkg = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'))
const fields = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'] as const
const present: string[] = []
for (const field of fields) {
for (const native of NATIVE_PACKAGES) {
if (pkg[field] && Object.prototype.hasOwnProperty.call(pkg[field], native)) {
present.push(`${field}:${native}`)
}
}
}
expect(present, `The proprietary native package must not be a dependency (public CI must pass with it absent); found in: ${present.join(', ')}`).toEqual([])
})
})