94 lines
5.0 KiB
JavaScript
94 lines
5.0 KiB
JavaScript
// Core Engine area map shared by core-guard.mjs and core-release.mjs (AGENTS.md, "Core Engine and engines").
|
|
// Paths are repository-relative and lowercase; the first matching prefix wins.
|
|
|
|
import path from 'node:path';
|
|
|
|
export const RELEASE_FILE = '.claude/core-release.json';
|
|
export const ALL_AREAS = 'alle';
|
|
export const GOVERNANCE = 'Governance';
|
|
export const WHOLE_REPOSITORY = 'Gesamtes Repository';
|
|
|
|
// Engine paths precede the Core areas they sit in.
|
|
export const ENGINE_PATHS = [
|
|
['Remediation Engine', ['src/remediation/', 'server/remediation/', 'tests/remediation/']],
|
|
['Context Engine', ['src/assessment-context/', 'src/features/context-layer/', 'tests/assessment-context/',
|
|
'tests/features/finding-context-layer.test.tsx', 'tests/features/pathfinder-context-layer.test.tsx',
|
|
'tests/features/context-cluster-facet.test.tsx', 'tests/context-browser-check.mjs']],
|
|
['Report Engine', ['src/reporting/', 'server/reporting/', 'tests/reporting/', 'tests/server/report-archive.test.ts',
|
|
'tests/postgres/report-read-only-runtime.test.ts']],
|
|
];
|
|
|
|
export const CORE_AREAS = [
|
|
[GOVERNANCE, ['agents.md', 'claude.md', '.claude/hooks/', '.claude/settings.json']],
|
|
// Client-owned records (reviews, risk acceptances, review transfer on reimport). They must survive
|
|
// every reimport; their server persistence stays inside the Store repository.
|
|
['Client Records', ['src/domain/review.ts', 'src/domain/risk-acceptance.ts', 'src/domain/reimport-review-transfer.ts',
|
|
'src/persistence/review-store.ts', 'src/features/review-workspace/', 'src/features/dashboard/riskregister.tsx']],
|
|
['Disclosure', ['src/domain/result-db-disclosure.ts', 'src/exports/']],
|
|
['Ingest', ['src/importers/', 'src/recognition/', 'src/profiles/', 'src/analysis/', 'src/gpo/', 'server/gpo/',
|
|
'server/import-executor.ts', 'server/import-worker-client.ts', 'server/import-worker.ts',
|
|
'server/node-import-runtime-adapters.ts', 'server/artifacts/']],
|
|
['Normalization', ['src/domain/']],
|
|
['Evaluation', ['src/evaluation/', 'src/comparison/', 'src/scoring/']],
|
|
['Store', ['src/persistence/', 'server/postgres/', 'server/repository-factory.ts', 'docker-compose.postgres.yml']],
|
|
['Reference Catalogs', ['src/references/', 'server/reference-data/']],
|
|
['Shared Kernel', ['src/shared/', 'src/vite-env.d.ts']],
|
|
['Presentation', ['src/app/', 'src/features/', 'src/components/', 'src/styles/', 'src/hooks/', 'src/assets/',
|
|
'src/main.tsx', 'index.html']],
|
|
['Platform', ['server/', 'src/api/', 'src/platform/', 'src/legacy/', 'package.json', 'package-lock.json',
|
|
'vite.config.ts', 'vite.client.config.ts', 'vite.server.config.ts', 'vitest.config.ts', 'tsconfig.json',
|
|
'tsconfig.app.json', 'tsconfig.node.json', 'tsconfig.server.json', 'dockerfile', 'docker-compose.deploy.yml',
|
|
'deploy/', 'scripts/']],
|
|
['Core Tests', ['tests/', 'fixtures/']],
|
|
// Any other source path stays Core until it is registered as an engine above.
|
|
['Unclassified Source', ['src/']],
|
|
];
|
|
|
|
// Spellings accepted after "Core-Freigabe:", mapped to the area names above.
|
|
const AREA_ALIASES = new Map([
|
|
['alle', ALL_AREAS], ['all', ALL_AREAS], ['core', ALL_AREAS],
|
|
['governance', GOVERNANCE],
|
|
['client records', 'Client Records'], ['kundendaten', 'Client Records'], ['reviews', 'Client Records'],
|
|
['disclosure', 'Disclosure'], ['result db', 'Disclosure'],
|
|
['ingest', 'Ingest'], ['import', 'Ingest'],
|
|
['normalization', 'Normalization'], ['normalisierung', 'Normalization'],
|
|
['evaluation', 'Evaluation'], ['bewertung', 'Evaluation'], ['scoring', 'Evaluation'],
|
|
['store', 'Store'], ['persistenz', 'Store'], ['datenbank', 'Store'],
|
|
['reference catalogs', 'Reference Catalogs'], ['referenzkataloge', 'Reference Catalogs'],
|
|
['shared kernel', 'Shared Kernel'],
|
|
['presentation', 'Presentation'], ['präsentation', 'Presentation'], ['praesentation', 'Presentation'], ['ui', 'Presentation'],
|
|
['platform', 'Platform'], ['plattform', 'Platform'],
|
|
['core tests', 'Core Tests'], ['tests', 'Core Tests'],
|
|
['unclassified source', 'Unclassified Source'],
|
|
]);
|
|
|
|
export function resolveAreaName(raw) {
|
|
return AREA_ALIASES.get(raw.trim().toLowerCase().replace(/\s+/g, ' ')) ?? null;
|
|
}
|
|
|
|
export function relativeToProject(filePath, projectDir) {
|
|
const normalized = path.resolve(projectDir, filePath);
|
|
const relative = path.relative(projectDir, normalized).split(path.sep).join('/');
|
|
if (relative.startsWith('..') || path.isAbsolute(relative)) return null;
|
|
return relative.toLowerCase();
|
|
}
|
|
|
|
function matchPrefix(relative, table) {
|
|
for (const [name, prefixes] of table) {
|
|
if (prefixes.some((prefix) => relative === prefix || relative.startsWith(prefix))) return name;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function classifyPath(relative) {
|
|
if (relative === null) return null;
|
|
if (matchPrefix(relative, ENGINE_PATHS)) return null;
|
|
return matchPrefix(relative, CORE_AREAS);
|
|
}
|
|
|
|
export function isReleased(area, releasedAreas) {
|
|
if (releasedAreas.includes(area)) return true;
|
|
// "alle" never covers Governance: the guard and these rules must always be named.
|
|
return area !== GOVERNANCE && releasedAreas.includes(ALL_AREAS);
|
|
}
|