The @opengsd/gsd-sdk package boundary was retired (ADR-0174, #191/#192) and the sdk/ tree is no longer tracked. ADR-0174's Supersedes table explicitly records that the generator-based Shared-Module hand-sync lint is deleted as part of that collapse. This removes the now-orphaned machinery it left behind: - scripts/lint-shared-module-handsync.cjs — paired bin/lib/*.cjs files with sdk/src/**/*.ts sources that no longer exist; wired into no CI workflow or npm script (dead). - scripts/shared-module-handsync-allowlist.json — the lint's allowlist; every entry pointed at a non-existent sdk/src source / generated artifact / freshness check. - tests/lint-shared-module-handsync.test.cjs — tested the deleted lint. Docs corrected to match: - CONTRIBUTING.md — removed the "CJS↔SDK seam" instruction (it linked the already-deleted docs/agents/cjs-sdk-seam.md and told contributors to maintain the allowlist under a retired generator pattern). - docs/prd/3524-cjs-sdk-hard-seam.md + docs/prd/README.md — marked the PRD Superseded by ADR-0174, matching the already-superseded ADR-3524. Added tests/no-cjs-sdk-handsync-tooling.test.cjs as a regression guard so the retired tooling stays removed and is not silently re-wired into package.json. ADR-3524 is left in place (already Superseded by ADR-0174); runtime modules and regression tests that cite it in comments keep resolving. No user-facing change. Closes #556 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,417 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Tests for scripts/lint-shared-module-handsync.cjs — Phase 6 of #3524 (#3575).
|
||||
*
|
||||
* Three cases:
|
||||
* 1. No new drift pair: lint exits 0 on the current repo tree (all cooperating
|
||||
* siblings on the allowlist; migrateMeBacklog pairs do not fail).
|
||||
* 2. Intentional new drift: synthesize a fixture tree with an unlisted
|
||||
* foo-test.cjs / foo-test.ts pair, assert exit 1 + typed error JSON.
|
||||
* 3. Allowlist entry honored: same pair as case 2, but with a cooperatingSiblings
|
||||
* allowlist entry present, assert exit 0.
|
||||
*
|
||||
* Assertions use the lint's --json mode: the production code emits a typed IR
|
||||
* (ok / reason / errors / warnings / counts), and tests parse and assert on
|
||||
* structured fields rather than substring-matching stderr/stdout (per
|
||||
* CONTRIBUTING.md "Prohibited: Raw Text Matching on Test Outputs").
|
||||
*/
|
||||
|
||||
const { test, describe } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const os = require('node:os');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
|
||||
const LINT_SCRIPT = path.join(__dirname, '..', 'scripts', 'lint-shared-module-handsync.cjs');
|
||||
const ALLOWLIST_PATH = path.join(__dirname, '..', 'scripts', 'shared-module-handsync-allowlist.json');
|
||||
const REPO_ROOT = path.join(__dirname, '..');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper: run the lint script in --json mode and parse the result.
|
||||
// Returns { status, payload } where payload is the parsed JSON IR (or null
|
||||
// if the lint emitted no JSON, which would be a test-infrastructure bug).
|
||||
// ---------------------------------------------------------------------------
|
||||
function runLintJson(extraArgs = []) {
|
||||
const result = spawnSync(process.execPath, [LINT_SCRIPT, '--json', ...extraArgs], {
|
||||
encoding: 'utf8',
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
let payload = null;
|
||||
try {
|
||||
payload = JSON.parse(result.stdout.trim());
|
||||
} catch {
|
||||
// Leave payload as null; tests assert on payload presence.
|
||||
}
|
||||
return { status: result.status, payload };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper: create an isolated fixture tree for testing
|
||||
//
|
||||
// Layout:
|
||||
// <tmpDir>/
|
||||
// get-shit-done/bin/lib/<cjsName>.cjs
|
||||
// sdk/src/query/<tsName>.ts (if tsInQuery === true)
|
||||
// sdk/src/<tsName>.ts (if tsInQuery === false)
|
||||
// scripts/shared-module-handsync-allowlist.json (custom allowlist)
|
||||
// ---------------------------------------------------------------------------
|
||||
function createFixture({ cjsName, tsName, tsInQuery = true, allowlistExtra = {} }) {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-lint-handsync-'));
|
||||
|
||||
const cjsDir = path.join(tmpDir, 'get-shit-done', 'bin', 'lib');
|
||||
fs.mkdirSync(cjsDir, { recursive: true });
|
||||
|
||||
const tsDir = tsInQuery
|
||||
? path.join(tmpDir, 'sdk', 'src', 'query')
|
||||
: path.join(tmpDir, 'sdk', 'src');
|
||||
fs.mkdirSync(tsDir, { recursive: true });
|
||||
|
||||
const scriptsDir = path.join(tmpDir, 'scripts');
|
||||
fs.mkdirSync(scriptsDir, { recursive: true });
|
||||
|
||||
fs.writeFileSync(path.join(cjsDir, `${cjsName}.cjs`), `'use strict';\n// fixture cjs\n`);
|
||||
fs.writeFileSync(path.join(tsDir, `${tsName}.ts`), `// fixture ts\nexport {};\n`);
|
||||
|
||||
const realAllowlist = JSON.parse(fs.readFileSync(ALLOWLIST_PATH, 'utf8'));
|
||||
const fixtureAllowlist = {
|
||||
cooperatingSiblings: [
|
||||
...(realAllowlist.cooperatingSiblings || []),
|
||||
...(allowlistExtra.cooperatingSiblings || []),
|
||||
],
|
||||
migrateMeBacklog: [
|
||||
...(realAllowlist.migrateMeBacklog || []),
|
||||
...(allowlistExtra.migrateMeBacklog || []),
|
||||
],
|
||||
};
|
||||
fs.writeFileSync(
|
||||
path.join(scriptsDir, 'shared-module-handsync-allowlist.json'),
|
||||
JSON.stringify(fixtureAllowlist, null, 2)
|
||||
);
|
||||
|
||||
return tmpDir;
|
||||
}
|
||||
|
||||
function cleanupFixture(dir) {
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Case 1: No new drift pair — exits 0 on current repo tree
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('lint-shared-module-handsync: current repo tree', () => {
|
||||
test('exits 0 with the real allowlist and current repo tree', () => {
|
||||
const { status, payload } = runLintJson();
|
||||
assert.strictEqual(status, 0);
|
||||
assert.ok(payload, 'expected JSON payload on stdout');
|
||||
assert.strictEqual(payload.ok, true);
|
||||
assert.ok(
|
||||
payload.reason === undefined || payload.reason === 'sdk_retired',
|
||||
`unexpected success reason: ${payload.reason}`
|
||||
);
|
||||
});
|
||||
|
||||
test('reports numeric counts when lint runs or short-circuits on retired SDK tree', () => {
|
||||
const { payload } = runLintJson();
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(typeof payload.cooperatingCount, 'number');
|
||||
assert.strictEqual(typeof payload.backlogCount, 'number');
|
||||
if (payload.reason !== 'sdk_retired') {
|
||||
assert.ok(payload.cooperatingCount > 0, 'expected at least one cooperating sibling');
|
||||
}
|
||||
// No errors field on success — only warnings (backlog) may be present
|
||||
assert.strictEqual(payload.ok, true);
|
||||
});
|
||||
|
||||
test('script has no syntax errors', () => {
|
||||
const result = spawnSync(process.execPath, ['--check', LINT_SCRIPT], { encoding: 'utf8' });
|
||||
assert.strictEqual(result.status, 0);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Case 2: Intentional new drift — exits 1 with informative typed error
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('lint-shared-module-handsync: intentional new drift pair', () => {
|
||||
test('exits 1 when an unlisted cjs/ts pair exists', () => {
|
||||
const tmpDir = createFixture({ cjsName: 'foo-test', tsName: 'foo-test', tsInQuery: true });
|
||||
try {
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 1);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, false);
|
||||
assert.strictEqual(payload.reason, 'unauthorized_pairs');
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('typed error payload names the unauthorized pair', () => {
|
||||
const tmpDir = createFixture({ cjsName: 'foo-test', tsName: 'foo-test', tsInQuery: true });
|
||||
try {
|
||||
const { payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.ok(payload && Array.isArray(payload.errors));
|
||||
assert.strictEqual(payload.errors.length, 1);
|
||||
const [entry] = payload.errors;
|
||||
assert.match(entry.relCjs, /foo-test\.cjs$/);
|
||||
assert.ok(Array.isArray(entry.tsPaths));
|
||||
assert.ok(entry.tsPaths.some((p) => /foo-test\.ts$/.test(p)));
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('exits 1 for unlisted pair in sdk/src/<name>.ts (non-query) position', () => {
|
||||
const tmpDir = createFixture({ cjsName: 'bar-test', tsName: 'bar-test', tsInQuery: false });
|
||||
try {
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 1);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, false);
|
||||
assert.strictEqual(payload.reason, 'unauthorized_pairs');
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Case 3: Allowlist entry honored — exits 0 when pair IS on cooperatingSiblings
|
||||
// ---------------------------------------------------------------------------
|
||||
describe('lint-shared-module-handsync: allowlist entry honored', () => {
|
||||
test('exits 0 when pair is in cooperatingSiblings allowlist', () => {
|
||||
const cjsName = 'baz-cooperating';
|
||||
const tsName = 'baz-cooperating';
|
||||
const tmpDir = createFixture({
|
||||
cjsName,
|
||||
tsName,
|
||||
tsInQuery: true,
|
||||
allowlistExtra: {
|
||||
cooperatingSiblings: [
|
||||
{
|
||||
cjs: `get-shit-done/bin/lib/${cjsName}.cjs`,
|
||||
ts: `sdk/src/query/${tsName}.ts`,
|
||||
classification: 'cooperating-sibling',
|
||||
justification: 'Test fixture: synthetic cooperating sibling for lint test.',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
try {
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 0);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, true);
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
// Regression guard: the lint matches on the (cjs, ts) PAIR, not on the
|
||||
// cjs path alone. An allowlist entry whose ts points to a different path
|
||||
// than the actual ts sibling on disk must NOT silently pass the pair.
|
||||
test('rejects pair when TS path differs from allowlist entry', () => {
|
||||
const cjsName = 'foo-wrong-ts';
|
||||
const tsName = 'foo-wrong-ts';
|
||||
const tmpDir = createFixture({
|
||||
cjsName,
|
||||
tsName,
|
||||
tsInQuery: true, // creates sdk/src/query/foo-wrong-ts.ts on disk
|
||||
allowlistExtra: {
|
||||
cooperatingSiblings: [
|
||||
{
|
||||
cjs: `get-shit-done/bin/lib/${cjsName}.cjs`,
|
||||
// Allowlist points at sdk/src/<name>.ts — different location.
|
||||
// Lint must reject because the on-disk pair is unauthorized.
|
||||
ts: `sdk/src/${tsName}.ts`,
|
||||
classification: 'cooperating-sibling',
|
||||
justification: 'Test: validates pair-aware matching enforces ts path.',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
try {
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 1, 'must fail when ts path mismatches');
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, false);
|
||||
assert.strictEqual(payload.reason, 'unauthorized_pairs');
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('exits 0 (no error) when pair is in migrateMeBacklog allowlist', () => {
|
||||
const cjsName = 'qux-backlog';
|
||||
const tsName = 'qux-backlog';
|
||||
const tmpDir = createFixture({
|
||||
cjsName,
|
||||
tsName,
|
||||
tsInQuery: true,
|
||||
allowlistExtra: {
|
||||
migrateMeBacklog: [
|
||||
{
|
||||
cjs: `get-shit-done/bin/lib/${cjsName}.cjs`,
|
||||
ts: `sdk/src/query/${tsName}.ts`,
|
||||
classification: 'drift-anti-pattern',
|
||||
justification: 'Test fixture: synthetic backlog pair for lint test.',
|
||||
trackedIn: 'test only',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
try {
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 0);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, true);
|
||||
// The backlog pair should be reported in warnings (not errors)
|
||||
assert.ok(Array.isArray(payload.warnings));
|
||||
assert.ok(
|
||||
payload.warnings.some((w) => /qux-backlog\.cjs$/.test(w.relCjs)),
|
||||
'expected qux-backlog in warnings'
|
||||
);
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
// Regression guard for #3632: when a cjs has TWO ts siblings sharing the
|
||||
// same basename (e.g. sdk/src/foo.ts AND sdk/src/query/foo.ts) and only
|
||||
// ONE pair is allowlisted, the unallowlisted sibling must still be reported.
|
||||
// Prior bug: .some() at the cjs level returned true on the allowlisted
|
||||
// pair, short-circuiting and silently dropping the unallowlisted sibling.
|
||||
test('reports unallowlisted ts sibling when another ts sibling for the same cjs IS allowlisted (#3632)', () => {
|
||||
const cjsName = 'multi-sibling';
|
||||
const tsName = 'multi-sibling';
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-lint-multi-'));
|
||||
try {
|
||||
const cjsDir = path.join(tmpDir, 'get-shit-done', 'bin', 'lib');
|
||||
fs.mkdirSync(cjsDir, { recursive: true });
|
||||
const tsDirRoot = path.join(tmpDir, 'sdk', 'src');
|
||||
const tsDirQuery = path.join(tmpDir, 'sdk', 'src', 'query');
|
||||
fs.mkdirSync(tsDirQuery, { recursive: true });
|
||||
const scriptsDir = path.join(tmpDir, 'scripts');
|
||||
fs.mkdirSync(scriptsDir, { recursive: true });
|
||||
|
||||
// One cjs, two ts siblings on disk (same basename, different paths).
|
||||
fs.writeFileSync(path.join(cjsDir, `${cjsName}.cjs`), `'use strict';\n`);
|
||||
fs.writeFileSync(path.join(tsDirRoot, `${tsName}.ts`), `export {};\n`);
|
||||
fs.writeFileSync(path.join(tsDirQuery, `${tsName}.ts`), `export {};\n`);
|
||||
|
||||
// Allowlist ONLY the sdk/src/<name>.ts pair. The sdk/src/query/<name>.ts
|
||||
// sibling is intentionally NOT allowlisted and must be reported.
|
||||
fs.writeFileSync(
|
||||
path.join(scriptsDir, 'shared-module-handsync-allowlist.json'),
|
||||
JSON.stringify(
|
||||
{
|
||||
cooperatingSiblings: [
|
||||
{
|
||||
cjs: `get-shit-done/bin/lib/${cjsName}.cjs`,
|
||||
ts: `sdk/src/${tsName}.ts`,
|
||||
classification: 'cooperating-sibling',
|
||||
justification: 'Test: only the non-query sibling is allowlisted.',
|
||||
},
|
||||
],
|
||||
migrateMeBacklog: [],
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(
|
||||
status,
|
||||
1,
|
||||
'must fail: the sdk/src/query/<name>.ts sibling is not allowlisted'
|
||||
);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, false);
|
||||
assert.strictEqual(payload.reason, 'unauthorized_pairs');
|
||||
assert.ok(Array.isArray(payload.errors) && payload.errors.length >= 1);
|
||||
const reportedTs = payload.errors.flatMap((e) => e.tsPaths);
|
||||
assert.ok(
|
||||
reportedTs.some((p) => /sdk\/src\/query\/multi-sibling\.ts$/.test(p)),
|
||||
`expected query sibling in errors, got: ${JSON.stringify(reportedTs)}`
|
||||
);
|
||||
// The allowlisted sibling must NOT appear in errors.
|
||||
assert.ok(
|
||||
!reportedTs.some((p) => /^sdk\/src\/multi-sibling\.ts$/.test(p)),
|
||||
`allowlisted sibling sdk/src/multi-sibling.ts must not be flagged, got: ${JSON.stringify(reportedTs)}`
|
||||
);
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('generated .cjs files are excluded from pair detection', () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-lint-gen-'));
|
||||
try {
|
||||
const cjsDir = path.join(tmpDir, 'get-shit-done', 'bin', 'lib');
|
||||
fs.mkdirSync(cjsDir, { recursive: true });
|
||||
const tsDir = path.join(tmpDir, 'sdk', 'src', 'query');
|
||||
fs.mkdirSync(tsDir, { recursive: true });
|
||||
const scriptsDir = path.join(tmpDir, 'scripts');
|
||||
fs.mkdirSync(scriptsDir, { recursive: true });
|
||||
|
||||
// A .generated.cjs file + matching TS — should NOT trigger lint error
|
||||
fs.writeFileSync(path.join(cjsDir, 'my-module.generated.cjs'), `'use strict';\n`);
|
||||
fs.writeFileSync(path.join(tsDir, 'my-module.ts'), `export {};\n`);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(scriptsDir, 'shared-module-handsync-allowlist.json'),
|
||||
JSON.stringify({ cooperatingSiblings: [], migrateMeBacklog: [] }, null, 2)
|
||||
);
|
||||
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 0);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, true);
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('lint-shared-module-handsync: cross-name pair support', () => {
|
||||
test('surfaces declared cross-name migrateMeBacklog pair in warnings', () => {
|
||||
const cjsName = 'verify';
|
||||
const tsName = 'validate';
|
||||
const tmpDir = createFixture({
|
||||
cjsName,
|
||||
tsName,
|
||||
tsInQuery: true,
|
||||
allowlistExtra: {
|
||||
migrateMeBacklog: [
|
||||
{
|
||||
cjs: `get-shit-done/bin/lib/${cjsName}.cjs`,
|
||||
ts: `sdk/src/query/${tsName}.ts`,
|
||||
classification: 'drift-anti-pattern',
|
||||
justification: 'Test fixture: cross-name pair should be observable by lint.',
|
||||
trackedIn: 'issue-11-test',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const { status, payload } = runLintJson(['--root', tmpDir]);
|
||||
assert.strictEqual(status, 0);
|
||||
assert.ok(payload);
|
||||
assert.strictEqual(payload.ok, true);
|
||||
assert.ok(Array.isArray(payload.warnings));
|
||||
assert.ok(
|
||||
payload.warnings.some((w) =>
|
||||
/verify\.cjs$/.test(w.relCjs) &&
|
||||
Array.isArray(w.tsPaths) &&
|
||||
w.tsPaths.some((p) => /sdk\/src\/query\/validate\.ts$/.test(p))
|
||||
),
|
||||
`expected cross-name verify.cjs <-> validate.ts warning, got: ${JSON.stringify(payload.warnings)}`
|
||||
);
|
||||
} finally {
|
||||
cleanupFixture(tmpDir);
|
||||
}
|
||||
});
|
||||
});
|
||||
53
tests/no-cjs-sdk-handsync-tooling.test.cjs
Normal file
53
tests/no-cjs-sdk-handsync-tooling.test.cjs
Normal file
@@ -0,0 +1,53 @@
|
||||
// allow-test-rule: architectural-invariant
|
||||
// Guards a removal mandated by ADR-0174 (retire @opengsd/gsd-sdk package
|
||||
// boundary), which explicitly deletes the generator-based CJS↔SDK hand-sync
|
||||
// tooling. These assertions check repo structure (file absence, package.json
|
||||
// wiring) — they are not source-text inspection of any .cjs module — and exist
|
||||
// to prevent silent re-introduction of the retired seam tooling.
|
||||
|
||||
/**
|
||||
* Regression guard for issue #556 — retire orphaned CJS↔SDK hand-sync tooling.
|
||||
*
|
||||
* The @opengsd/gsd-sdk package boundary was retired (ADR-0174, #191/#192) and
|
||||
* the `sdk/` tree is no longer tracked. The generator-based hand-sync lint that
|
||||
* policed CJS-vs-SDK TypeScript drift is therefore dead infrastructure: it
|
||||
* referenced an `sdk/src` tree that no longer exists and was wired into no CI
|
||||
* workflow or npm script. This guard asserts it stays removed.
|
||||
*/
|
||||
|
||||
const { test, describe } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '..');
|
||||
|
||||
describe('retired CJS↔SDK hand-sync tooling (#556 / ADR-0174)', () => {
|
||||
test('the hand-sync pair lint script is absent', () => {
|
||||
const lintScript = path.join(REPO_ROOT, 'scripts', 'lint-shared-module-handsync.cjs');
|
||||
assert.ok(
|
||||
!fs.existsSync(lintScript),
|
||||
'scripts/lint-shared-module-handsync.cjs should be removed — the CJS↔SDK seam it policed was retired by ADR-0174',
|
||||
);
|
||||
});
|
||||
|
||||
test('the hand-sync allowlist is absent', () => {
|
||||
const allowlist = path.join(REPO_ROOT, 'scripts', 'shared-module-handsync-allowlist.json');
|
||||
assert.ok(
|
||||
!fs.existsSync(allowlist),
|
||||
'scripts/shared-module-handsync-allowlist.json should be removed — it paired bin/lib/*.cjs files with sdk/src sources that no longer exist',
|
||||
);
|
||||
});
|
||||
|
||||
test('no npm script re-wires the retired hand-sync lint', () => {
|
||||
const pkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8'));
|
||||
const offenders = Object.entries(pkg.scripts || {})
|
||||
.filter(([, cmd]) => cmd.includes('lint-shared-module-handsync'))
|
||||
.map(([name]) => name);
|
||||
assert.deepEqual(
|
||||
offenders,
|
||||
[],
|
||||
`package.json scripts must not invoke the retired hand-sync lint; found: ${offenders.join(', ')}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user