mirror of
https://github.com/Jeuners/ECC.git
synced 2026-09-09 15:02:30 +02:00
* fix(install): reference all curated skills in modules + add reverse-coverage guard (#2431) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(install): normalize path separators in delivery-gate dry-run assertion (#2431) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: affaan <affaan@itomarkets.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
67537ea480
commit
38a7ebbe32
5 changed files with 349 additions and 14 deletions
|
|
@ -16,6 +16,11 @@ const COMPONENTS_MANIFEST_PATH = path.join(REPO_ROOT, 'manifests/install-compone
|
|||
const MODULES_SCHEMA_PATH = path.join(REPO_ROOT, 'schemas/install-modules.schema.json');
|
||||
const PROFILES_SCHEMA_PATH = path.join(REPO_ROOT, 'schemas/install-profiles.schema.json');
|
||||
const COMPONENTS_SCHEMA_PATH = path.join(REPO_ROOT, 'schemas/install-components.schema.json');
|
||||
const CURATED_SKILLS_DIR = path.join(REPO_ROOT, 'skills');
|
||||
// Empty by default; add only curated skills that are intentionally unshipped.
|
||||
const INTENTIONALLY_UNSHIPPED_SKILL_IDS = new Set([
|
||||
'skill-comply', // meta/measurement dev-skill; ships committed .pyc artifacts and a nested .gitignore, revisit after packaging cleanup
|
||||
]);
|
||||
const COMPONENT_FAMILY_PREFIXES = {
|
||||
baseline: 'baseline:',
|
||||
language: 'lang:',
|
||||
|
|
@ -36,6 +41,18 @@ function normalizeRelativePath(relativePath) {
|
|||
return String(relativePath).replace(/\\/g, '/').replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
function isCuratedSkillReferenced(claimedPaths, skillId) {
|
||||
const skillRoot = `skills/${skillId}`;
|
||||
|
||||
for (const claimedPath of claimedPaths.keys()) {
|
||||
if (claimedPath === skillRoot || claimedPath.startsWith(`${skillRoot}/`)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function validateSchema(ajv, schemaPath, data, label) {
|
||||
const schema = readJson(schemaPath, `${label} schema`);
|
||||
const validate = ajv.compile(schema);
|
||||
|
|
@ -131,6 +148,30 @@ function validateInstallManifests() {
|
|||
}
|
||||
}
|
||||
|
||||
if (fs.existsSync(CURATED_SKILLS_DIR)) {
|
||||
const entries = fs.readdirSync(CURATED_SKILLS_DIR, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (!entry.isDirectory() || entry.name.startsWith('.')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const skillMdPath = path.join(CURATED_SKILLS_DIR, entry.name, 'SKILL.md');
|
||||
if (!fs.existsSync(skillMdPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!INTENTIONALLY_UNSHIPPED_SKILL_IDS.has(entry.name)
|
||||
&& !isCuratedSkillReferenced(claimedPaths, entry.name)
|
||||
) {
|
||||
console.error(
|
||||
`ERROR: curated skill skills/${entry.name} is not referenced by any install module`
|
||||
);
|
||||
hasErrors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const profiles = profilesData.profiles || {};
|
||||
const components = Array.isArray(componentsData.components) ? componentsData.components : [];
|
||||
const expectedProfileIds = ['core', 'developer', 'security', 'research', 'full'];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue