fix: sync skill frontmatter and catalog counts

Adds missing skill frontmatter, normalizes strict YAML metadata, syncs README catalog counts, and extends catalog validation for README/plugin/marketplace count drift.
This commit is contained in:
Affaan Mustafa
2026-05-11 02:33:29 -04:00
committed by GitHub
parent 8a57679222
commit 27508842b1
7 changed files with 183 additions and 12 deletions

View File

@@ -21,6 +21,8 @@ const AGENTS_PATH = path.join(ROOT, 'AGENTS.md');
const README_ZH_CN_PATH = path.join(ROOT, 'README.zh-CN.md');
const DOCS_ZH_CN_README_PATH = path.join(ROOT, 'docs', 'zh-CN', 'README.md');
const DOCS_ZH_CN_AGENTS_PATH = path.join(ROOT, 'docs', 'zh-CN', 'AGENTS.md');
const PLUGIN_JSON_PATH = path.join(ROOT, '.claude-plugin', 'plugin.json');
const MARKETPLACE_JSON_PATH = path.join(ROOT, '.claude-plugin', 'marketplace.json');
const WRITE_MODE = process.argv.includes('--write');
const OUTPUT_MODE = process.argv.includes('--md')
@@ -99,6 +101,18 @@ function parseReadmeExpectations(readmeContent) {
{ category: 'commands', mode: 'exact', expected: Number(quickStartMatch[3]), source: 'README.md quick-start summary' }
);
const projectTreeAgentsMatch = readmeContent.match(/^\|\s*--\s*agents\/\s*#\s*(\d+)\s+specialized subagents for delegation\s*$/im);
if (!projectTreeAgentsMatch) {
throw new Error('README.md project tree is missing the agents count');
}
expectations.push({
category: 'agents',
mode: 'exact',
expected: Number(projectTreeAgentsMatch[1]),
source: 'README.md project tree (agents)'
});
const tablePatterns = [
{ category: 'agents', regex: /\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+agents\s*\|/i, source: 'README.md comparison table' },
{ category: 'commands', regex: /\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+commands\s*\|/i, source: 'README.md comparison table' },
@@ -346,6 +360,31 @@ function parseZhAgentsDocExpectations(agentsContent) {
return expectations;
}
function parseCatalogDescriptionExpectations(content, source, getDescription) {
let parsed;
try {
parsed = JSON.parse(content);
} catch (error) {
throw new Error(`${source} is not valid JSON: ${error.message}`);
}
const description = getDescription(parsed);
if (typeof description !== 'string') {
throw new Error(`${source} is missing the catalog count description`);
}
const match = description.match(/(\d+)\s+agents,\s+(\d+)\s+skills,\s+(\d+)\s+legacy command shims?/i);
if (!match) {
throw new Error(`${source} is missing the catalog count description`);
}
return [
{ category: 'agents', mode: 'exact', expected: Number(match[1]), source },
{ category: 'skills', mode: 'exact', expected: Number(match[2]), source },
{ category: 'commands', mode: 'exact', expected: Number(match[3]), source },
];
}
function evaluateExpectations(catalog, expectations) {
return expectations.map(expectation => {
const actual = catalog[expectation.category].count;
@@ -376,6 +415,12 @@ function syncEnglishReadme(content, catalog) {
`${prefix}${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsSuffix}${catalog.commands.count} legacy command shims`,
'README.md quick-start summary'
);
nextContent = replaceOrThrow(
nextContent,
/^(\|\s*--\s*agents\/\s*#\s*)(\d+)(\s+specialized subagents for delegation\s*)$/im,
(_, prefix, __, suffix) => `${prefix}${catalog.agents.count}${suffix}`,
'README.md project tree (agents)'
);
nextContent = replaceOrThrow(
nextContent,
/(\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?)(\d+)(\s+agents\s*\|)/i,
@@ -540,6 +585,31 @@ function syncZhAgents(content, catalog) {
return nextContent;
}
function syncCatalogDescription(content, catalog, source, getDescription, setDescription) {
let parsed;
try {
parsed = JSON.parse(content);
} catch (error) {
throw new Error(`${source} is not valid JSON: ${error.message}`);
}
const description = getDescription(parsed);
if (typeof description !== 'string') {
throw new Error(`${source} is missing the catalog count description`);
}
const nextDescription = replaceOrThrow(
description,
/(\d+)(\s+agents,\s+)(\d+)(\s+skills,\s+)(\d+)(\s+legacy command shims?)/i,
(_, __, agentsSuffix, ___, skillsSuffix, ____, commandsSuffix) =>
`${catalog.agents.count}${agentsSuffix}${catalog.skills.count}${skillsSuffix}${catalog.commands.count}${commandsSuffix}`,
source
);
setDescription(parsed, nextDescription);
return `${JSON.stringify(parsed, null, 2)}\n`;
}
function createDocumentSpecs(paths = {}) {
const {
readmePath = README_PATH,
@@ -547,6 +617,8 @@ function createDocumentSpecs(paths = {}) {
zhRootReadmePath = README_ZH_CN_PATH,
zhDocsReadmePath = DOCS_ZH_CN_README_PATH,
zhDocsAgentsPath = DOCS_ZH_CN_AGENTS_PATH,
pluginJsonPath = PLUGIN_JSON_PATH,
marketplaceJsonPath = MARKETPLACE_JSON_PATH,
} = paths;
return [
@@ -575,6 +647,36 @@ function createDocumentSpecs(paths = {}) {
parseExpectations: parseZhAgentsDocExpectations,
syncContent: syncZhAgents,
},
{
filePath: pluginJsonPath,
parseExpectations: content => parseCatalogDescriptionExpectations(
content,
'.claude-plugin/plugin.json description',
parsed => parsed.description
),
syncContent: (content, catalog) => syncCatalogDescription(
content,
catalog,
'.claude-plugin/plugin.json description',
parsed => parsed.description,
(parsed, description) => { parsed.description = description; }
),
},
{
filePath: marketplaceJsonPath,
parseExpectations: content => parseCatalogDescriptionExpectations(
content,
'.claude-plugin/marketplace.json plugin description',
parsed => parsed.plugins?.[0]?.description
),
syncContent: (content, catalog) => syncCatalogDescription(
content,
catalog,
'.claude-plugin/marketplace.json plugin description',
parsed => parsed.plugins?.[0]?.description,
(parsed, description) => { parsed.plugins[0].description = description; }
),
},
];
}
@@ -585,6 +687,8 @@ function createDocumentSpecsForRoot(root) {
zhRootReadmePath: path.join(root, 'README.zh-CN.md'),
zhDocsReadmePath: path.join(root, 'docs', 'zh-CN', 'README.md'),
zhDocsAgentsPath: path.join(root, 'docs', 'zh-CN', 'AGENTS.md'),
pluginJsonPath: path.join(root, '.claude-plugin', 'plugin.json'),
marketplaceJsonPath: path.join(root, '.claude-plugin', 'marketplace.json'),
});
}
@@ -689,11 +793,13 @@ module.exports = {
formatExpectation,
main,
parseAgentsDocExpectations,
parseCatalogDescriptionExpectations,
parseReadmeExpectations,
parseZhAgentsDocExpectations,
parseZhDocsReadmeExpectations,
parseZhRootReadmeExpectations,
runCatalogCheck,
syncCatalogDescription,
syncEnglishAgents,
syncEnglishReadme,
syncZhAgents,