fix(kyberforge): keep .github/plugin/marketplace.json synced
apm.yml only declares claude and codex marketplace output profiles -- codex writes a differently-shaped file to .agents/plugins/marketplace.json, so nothing regenerates the legacy Copilot CLI path at .github/plugin/marketplace.json. It was hand-synced once during the #90 conversion and had drifted (missing the category field added when codex output was enabled) with no gate to catch it. scripts/sync-marketplace-mirror.sh keeps it byte-identical to the compiled .claude-plugin/marketplace.json, wired as a pre-push check so it can't go stale silently again. Refs: #90
This commit is contained in:
7
.github/plugin/marketplace.json
vendored
7
.github/plugin/marketplace.json
vendored
@@ -7,36 +7,42 @@
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"category": "Developer Tools",
|
||||
"description": "Skills and agents for creating, maintaining, and managing a Claude Code / Copilot CLI plugin marketplace.",
|
||||
"name": "kyberforge",
|
||||
"source": "./plugins/kyberforge",
|
||||
"version": "1.4.0"
|
||||
},
|
||||
{
|
||||
"category": "Utilities",
|
||||
"description": "A place for things to be binned",
|
||||
"name": "bin",
|
||||
"source": "./plugins/bin",
|
||||
"version": "1.1.1"
|
||||
},
|
||||
{
|
||||
"category": "Version Control",
|
||||
"description": "Skills for working with Git \u2014 conventional commits, branch management, pull requests, and feature flow.",
|
||||
"name": "git",
|
||||
"source": "./plugins/git",
|
||||
"version": "1.3.2"
|
||||
},
|
||||
{
|
||||
"category": "Version Control",
|
||||
"description": "Skills for managing Gitea repositories \u2014 issues, pull requests, milestones, releases, and wikis.",
|
||||
"name": "gitea",
|
||||
"source": "./plugins/gitea",
|
||||
"version": "1.3.3"
|
||||
},
|
||||
{
|
||||
"category": "Productivity",
|
||||
"description": "Cross-cutting utility skills for everyday AI-assisted coding \u2014 triage, diagnosis, architecture review, and session navigation.",
|
||||
"name": "core",
|
||||
"source": "./plugins/core",
|
||||
"version": "1.1.0"
|
||||
},
|
||||
{
|
||||
"category": "Productivity",
|
||||
"description": "Skills for Real Engineers \u2014 planning, TDD, architecture, and debugging workflows from Matt Pocock's .claude directory.",
|
||||
"name": "mattpocock-skills",
|
||||
"source": {
|
||||
@@ -48,6 +54,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"category": "Developer Tools",
|
||||
"description": "Skills and agents for configuring and running linters.",
|
||||
"name": "lint",
|
||||
"source": "./plugins/lint",
|
||||
|
||||
@@ -71,6 +71,15 @@ repos:
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
|
||||
- id: check-marketplace-mirror-sync
|
||||
name: Check marketplace mirror sync
|
||||
description: Verify .github/plugin/marketplace.json (Copilot CLI's legacy manifest path) is byte-identical to .claude-plugin/marketplace.json -- apm has no output profile for this path, so it must be kept in sync explicitly (see issue #90)
|
||||
entry: bash scripts/sync-marketplace-mirror.sh --check
|
||||
language: system
|
||||
stages: [pre-push]
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
|
||||
- id: apm-marketplace-check
|
||||
name: apm marketplace check
|
||||
description: Validate every marketplace.packages[] entry resolves, including network reachability of remote refs -- catches stale/unreachable remote package references that check-manifests.sh deliberately skips (local-source checks only)
|
||||
|
||||
@@ -30,7 +30,7 @@ Reusable slash commands for AI coding tools, defined as `SKILL.md` files followi
|
||||
The deployable unit in the plugin marketplace. A plugin bundles one or more skills, agents, hooks, prompts, MCP servers, and optionally a `bin/` directory into a single installable directory. In this repo, plugins live under `plugins/<name>/`, each with its own `apm.yml` + `.apm/{skills,agents,hooks,...}` — this is the authoring source of truth for the plugin's content (ADR-0015). Two categories of tracked output are compiled from that source, never hand-edited: `.claude-plugin/plugin.json` (Claude Code) and `.github/plugin/plugin.json` (Copilot CLI) via `apm pack`/`apm compile`; and, alongside them, a flat `agents/`, `skills/`, `commands/`, `instructions/`, `extensions/` directory mirror plus a merged `hooks.json` at the plugin root, generated by `scripts/sync-plugin-content.sh` — Claude Code's and Copilot's installers convention-scan only these flat root-level paths and have no awareness of `.apm/` nesting at all, so this mirror is what actually makes `.apm/` content discoverable at install time (ADR-0017). Plugins are copied to a cache on install — they cannot reference files outside their own directory. Install a plugin with `claude plugin install <name>@<marketplace>`.
|
||||
|
||||
### Plugin marketplace
|
||||
A Git repository with a `marketplace.json` manifest listing installable plugins. No backend, registry, or SaaS required — the Git repo is the marketplace. This repo is the `holocron` marketplace. The manifest at `.claude-plugin/marketplace.json` (read by both Claude Code and Copilot CLI, mirrored to `.github/plugin/marketplace.json`) is **compiled output** of `apm pack`, generated from the root `apm.yml`'s `marketplace:` block (owner, build/output config, versioning strategy, and the `packages:` list of installable plugins) — it is not hand-edited. See ADR-0015. Each listed package's `source:` still points at that plugin's own `plugins/<name>/` root, not at an `apm pack` build artifact — which is why that root also carries the flat `agents/`/`skills/`/`commands/`/`hooks.json` content mirror described under "Plugin" (ADR-0017): without it, an install from this marketplace finds a valid manifest but no discoverable content.
|
||||
A Git repository with a `marketplace.json` manifest listing installable plugins. No backend, registry, or SaaS required — the Git repo is the marketplace. This repo is the `holocron` marketplace. The manifest at `.claude-plugin/marketplace.json` (read by both Claude Code and Copilot CLI) is **compiled output** of `apm pack`, generated from the root `apm.yml`'s `marketplace:` block (owner, build/output config, versioning strategy, and the `packages:` list of installable plugins) — it is not hand-edited. See ADR-0015. `.github/plugin/marketplace.json` is Copilot CLI's legacy manifest path; apm has no output profile for it (only `claude` and `codex`, and `codex`'s is a differently-shaped file at `.agents/plugins/marketplace.json`), so `scripts/sync-marketplace-mirror.sh` keeps it byte-identical to `.claude-plugin/marketplace.json`, checked at pre-push. Each listed package's `source:` still points at that plugin's own `plugins/<name>/` root, not at an `apm pack` build artifact — which is why that root also carries the flat `agents/`/`skills/`/`commands/`/`hooks.json` content mirror described under "Plugin" (ADR-0017): without it, an install from this marketplace finds a valid manifest but no discoverable content.
|
||||
|
||||
### HITL (human-in-the-loop)
|
||||
Agent pauses before a consequential action; human approves before execution. Required for irreversible or high-stakes actions (architecture changes, production deployments, security configuration). The agent drafts the change plan and waits — it does not proceed autonomously. Contrast with HOTL.
|
||||
|
||||
45
scripts/sync-marketplace-mirror.sh
Executable file
45
scripts/sync-marketplace-mirror.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# .claude-plugin/marketplace.json is apm's compiled Claude marketplace output (see
|
||||
# apm.yml's marketplace.outputs.claude). GitHub Copilot CLI's manifest lookup accepts
|
||||
# that same file at .claude-plugin/marketplace.json directly, but also has a legacy
|
||||
# convention path at .github/plugin/marketplace.json (see
|
||||
# plugins/kyberforge/docs/research/docs/github-copilot-plugins/marketplace.md) -- and
|
||||
# CONTEXT.md documents that path as a mirror of the Claude output, not a separate apm
|
||||
# output profile (apm only ships "claude" and "codex" mappers; codex writes a
|
||||
# differently-shaped file to .agents/plugins/marketplace.json, not this path). This
|
||||
# script keeps that legacy mirror byte-identical to .claude-plugin/marketplace.json
|
||||
# instead of letting it silently drift (see issue #90 comment thread).
|
||||
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||
SRC="$REPO_ROOT/.claude-plugin/marketplace.json"
|
||||
DST="$REPO_ROOT/.github/plugin/marketplace.json"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [--check]" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
CHECK=0
|
||||
if [[ "${1:-}" == "--check" ]]; then
|
||||
CHECK=1
|
||||
shift
|
||||
fi
|
||||
[[ $# -eq 0 ]] || usage
|
||||
|
||||
if [[ ! -f "$SRC" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$CHECK" -eq 1 ]]; then
|
||||
if [[ ! -f "$DST" ]] || ! diff -q "$SRC" "$DST" >/dev/null 2>&1; then
|
||||
echo "DRIFT $DST: out of sync with .claude-plugin/marketplace.json" >&2
|
||||
echo "Fix: bash scripts/sync-marketplace-mirror.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$DST")"
|
||||
cp "$SRC" "$DST"
|
||||
Reference in New Issue
Block a user