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.
This commit is contained in:
parent
21d02d3bae
commit
b198281ce1
2 changed files with 77 additions and 56 deletions
|
|
@ -1,56 +0,0 @@
|
||||||
/**
|
|
||||||
* @module tests/unit/boundary-no-cortex
|
|
||||||
* @description Enforces the open-source / proprietary boundary in CI: the public
|
|
||||||
* MIT Brainy repo must never DEPEND ON the proprietary `@soulcraft/cortex`
|
|
||||||
* package to build or test. Cortex is the one product Brainy may NAME (docs say
|
|
||||||
* `npm install @soulcraft/cortex`, error messages point at its `idSpace:'u64'`
|
|
||||||
* mode), and registering it through the public plugin API is the supported path —
|
|
||||||
* but nothing in `src/` or `tests/` may statically `import`/`require` it, and it
|
|
||||||
* must not appear in any dependency field. This guards against someone turning an
|
|
||||||
* optional integration into a hard coupling that silently makes green CI depend
|
|
||||||
* on a private build. See the perf-comparison boundary decision (handoff AJ/AK).
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
|
|
||||||
/** 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 cortex in an import/require/dynamic-import —
|
|
||||||
// NOT a bare string mention (docs/JSDoc/error-message/mock-name are allowed).
|
|
||||||
const CORTEX_MODULE = /(?:import\s[^'"]*from\s*|import\s*\(\s*|require\s*\(\s*)['"]@soulcraft\/cortex(?:\/[^'"]*)?['"]/
|
|
||||||
|
|
||||||
describe('open/proprietary boundary — public repo must not depend on @soulcraft/cortex', () => {
|
|
||||||
it('no src/ or tests/ file imports or requires @soulcraft/cortex', () => {
|
|
||||||
const offenders: string[] = []
|
|
||||||
for (const dir of ['src', 'tests']) {
|
|
||||||
for (const file of sourceFiles(path.join(repoRoot, dir))) {
|
|
||||||
if (CORTEX_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('@soulcraft/cortex 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 = fields.filter((f) => pkg[f] && Object.prototype.hasOwnProperty.call(pkg[f], '@soulcraft/cortex'))
|
|
||||||
expect(present, `@soulcraft/cortex must not be a dependency (public CI must pass with it absent); found in: ${present.join(', ')}`).toEqual([])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
77
tests/unit/boundary-no-native.test.ts
Normal file
77
tests/unit/boundary-no-native.test.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
/**
|
||||||
|
* @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([])
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Add table
Add a link
Reference in a new issue