refactor: migrate plugins to Claude Code spec format

- Move plugin manifests from .github/plugin/ to .claude-plugin/
- Convert items[] to Claude Code spec fields (agents, commands, skills)
- Rename tags to keywords, drop display/featured/instructions from plugins
- Delete all symlinks and materialized files from plugin directories
- Add eng/materialize-plugins.mjs to copy source files into plugin dirs at publish time
- Add .github/workflows/publish.yml for staged->main publishing
- Update CI triggers to target staged branch
- Update validation, creation, marketplace, and README generation scripts
- Update CONTRIBUTING.md and AGENTS.md documentation
- Include all new content from main (polyglot-test-agent, gem-browser-tester,
  fabric-lakehouse, fluentui-blazor, quasi-coder, transloadit-media-processing,
  make-repo-contribution hardening, website logo/gradient changes)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Aaron Powell
2026-02-18 14:11:22 +11:00
parent 8480453512
commit 9d1df57ebc
243 changed files with 753 additions and 1836 deletions

View File

@@ -710,7 +710,7 @@ function generateUnifiedModeSection(cfg) {
* Read and parse a plugin.json file from a plugin directory.
*/
function readPluginJson(pluginDir) {
const jsonPath = path.join(pluginDir, ".github", "plugin", "plugin.json");
const jsonPath = path.join(pluginDir, ".github/plugin", "plugin.json");
if (!fs.existsSync(jsonPath)) return null;
try {
return JSON.parse(fs.readFileSync(jsonPath, "utf-8"));
@@ -783,13 +783,13 @@ function generatePluginsSection(pluginsDir) {
const description = formatTableCell(
plugin.description || "No description"
);
const itemCount = plugin.items ? plugin.items.length : 0;
const tags = plugin.tags ? plugin.tags.join(", ") : "";
const itemCount = (plugin.agents || []).length + (plugin.commands || []).length + (plugin.skills || []).length;
const keywords = plugin.keywords ? plugin.keywords.join(", ") : "";
const link = `../plugins/${dir}/README.md`;
const displayName = isFeatured ? `${name}` : name;
pluginsContent += `| [${displayName}](${link}) | ${description} | ${itemCount} items | ${tags} |\n`;
pluginsContent += `| [${displayName}](${link}) | ${description} | ${itemCount} items | ${keywords} |\n`;
}
return `${TEMPLATES.pluginsSection}\n${TEMPLATES.pluginsUsage}\n\n${pluginsContent}`;
@@ -826,8 +826,8 @@ function generateFeaturedPluginsSection(pluginsDir) {
const description = formatTableCell(
plugin.description || "No description"
);
const tags = plugin.tags ? plugin.tags.join(", ") : "";
const itemCount = plugin.items ? plugin.items.length : 0;
const keywords = plugin.keywords ? plugin.keywords.join(", ") : "";
const itemCount = (plugin.agents || []).length + (plugin.commands || []).length + (plugin.skills || []).length;
return {
dir,
@@ -835,7 +835,7 @@ function generateFeaturedPluginsSection(pluginsDir) {
pluginId: name,
name,
description,
tags,
keywords,
itemCount,
};
},
@@ -861,10 +861,10 @@ function generateFeaturedPluginsSection(pluginsDir) {
// Generate table rows for each featured plugin
for (const entry of featuredPlugins) {
const { dir, name, description, tags, itemCount } = entry;
const { dir, name, description, keywords, itemCount } = entry;
const readmeLink = `plugins/${dir}/README.md`;
featuredContent += `| [${name}](${readmeLink}) | ${description} | ${itemCount} items | ${tags} |\n`;
featuredContent += `| [${name}](${readmeLink}) | ${description} | ${itemCount} items | ${keywords} |\n`;
}
return `${TEMPLATES.featuredPluginsSection}\n\n${featuredContent}`;