diff --git a/.agents/skills/marketplace-architect/scripts/validate.sh b/.agents/skills/marketplace-architect/scripts/validate.sh index 83595f4..aec062b 100755 --- a/.agents/skills/marketplace-architect/scripts/validate.sh +++ b/.agents/skills/marketplace-architect/scripts/validate.sh @@ -224,12 +224,14 @@ ROOT="$(cd "$ROOT" && pwd)" # ── validate marketplace.json ───────────────────────────────────────────────── +CLAUDE_MARKETPLACE="$ROOT/.claude-plugin/marketplace.json" +COPILOT_MARKETPLACE="$ROOT/.github/plugin/marketplace.json" MARKETPLACE_JSON="" -for mp in "$ROOT/.claude-plugin/marketplace.json" "$ROOT/.github/plugin/marketplace.json"; do + +for mp in "$CLAUDE_MARKETPLACE" "$COPILOT_MARKETPLACE"; do if [[ -f "$mp" ]]; then - MARKETPLACE_JSON="$mp" + [[ -z "$MARKETPLACE_JSON" ]] && MARKETPLACE_JSON="$mp" validate_marketplace_json "$mp" - break fi done @@ -237,6 +239,57 @@ if [[ -z "$MARKETPLACE_JSON" ]]; then warn "No marketplace.json found. Expected at .claude-plugin/marketplace.json" fi +# Marketplace sync check — shared identity fields must match; description/version +# legitimately differ in structure (Claude: top-level; Copilot: under metadata) +if [[ -f "$CLAUDE_MARKETPLACE" && -f "$COPILOT_MARKETPLACE" ]]; then + cm_val=$(jq -r '.name // empty' "$CLAUDE_MARKETPLACE") + cp_val=$(jq -r '.name // empty' "$COPILOT_MARKETPLACE") + if [[ "$cm_val" != "$cp_val" ]]; then + error "marketplace: 'name' differs — .claude-plugin ('$cm_val') vs .github/plugin ('$cp_val')" + fi + + cm_val=$(jq -r '.owner.name // empty' "$CLAUDE_MARKETPLACE") + cp_val=$(jq -r '.owner.name // empty' "$COPILOT_MARKETPLACE") + if [[ ( -n "$cm_val" || -n "$cp_val" ) && "$cm_val" != "$cp_val" ]]; then + error "marketplace: 'owner.name' differs — '$cm_val' vs '$cp_val'" + fi + + # description: Claude top-level, Copilot under metadata — compare values regardless of path + cm_val=$(jq -r '.description // .metadata.description // empty' "$CLAUDE_MARKETPLACE") + cp_val=$(jq -r '.metadata.description // .description // empty' "$COPILOT_MARKETPLACE") + if [[ ( -n "$cm_val" || -n "$cp_val" ) && "$cm_val" != "$cp_val" ]]; then + error "marketplace: description differs between .claude-plugin/marketplace.json and .github/plugin/marketplace.json" + fi + + # version: same structural divergence as description + cm_val=$(jq -r '.version // .metadata.version // empty' "$CLAUDE_MARKETPLACE") + cp_val=$(jq -r '.metadata.version // .version // empty' "$COPILOT_MARKETPLACE") + if [[ ( -n "$cm_val" || -n "$cp_val" ) && "$cm_val" != "$cp_val" ]]; then + error "marketplace: version differs — '$cm_val' vs '$cp_val'" + fi + + # Plugin catalog must be identical across both files + cm_plugins=$(jq -r '.plugins[].name' "$CLAUDE_MARKETPLACE" 2>/dev/null | sort) + cp_plugins=$(jq -r '.plugins[].name' "$COPILOT_MARKETPLACE" 2>/dev/null | sort) + if [[ "$cm_plugins" != "$cp_plugins" ]]; then + error "marketplace: plugin lists differ between .claude-plugin/marketplace.json and .github/plugin/marketplace.json" + else + while IFS= read -r pname; do + [[ -z "$pname" ]] && continue + cm_val=$(jq -r --arg n "$pname" '.plugins[] | select(.name==$n) | .source // empty' "$CLAUDE_MARKETPLACE") + cp_val=$(jq -r --arg n "$pname" '.plugins[] | select(.name==$n) | .source // empty' "$COPILOT_MARKETPLACE") + if [[ "$cm_val" != "$cp_val" ]]; then + error "marketplace plugin '$pname': source differs — '$cm_val' vs '$cp_val'" + fi + cm_val=$(jq -r --arg n "$pname" '.plugins[] | select(.name==$n) | .description // empty' "$CLAUDE_MARKETPLACE") + cp_val=$(jq -r --arg n "$pname" '.plugins[] | select(.name==$n) | .description // empty' "$COPILOT_MARKETPLACE") + if [[ ( -n "$cm_val" || -n "$cp_val" ) && "$cm_val" != "$cp_val" ]]; then + error "marketplace plugin '$pname': description differs between the two marketplace.json files" + fi + done <<< "$cm_plugins" + fi +fi + # ── validate plugins ────────────────────────────────────────────────────────── if [[ -n "$PLUGIN_ONLY" ]]; then diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 9f0e857..ab381a8 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,5 +1,6 @@ { "name": "holocron", + "owner": { "name": "Your Name", "email": "you@example.com" }, "description": "AI development skills for Claude Code and GitHub Copilot CLI — factory, design, implement, review, and cross-cutting workflows.", "version": "0.1.0", "plugins": [ diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index 9f0e857..17d4d93 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -1,7 +1,10 @@ { "name": "holocron", - "description": "AI development skills for Claude Code and GitHub Copilot CLI — factory, design, implement, review, and cross-cutting workflows.", - "version": "0.1.0", + "owner": { "name": "Your Name", "email": "you@example.com" }, + "metadata": { + "description": "AI development skills for Claude Code and GitHub Copilot CLI — factory, design, implement, review, and cross-cutting workflows.", + "version": "0.1.0" + }, "plugins": [ { "name": "hello-world",