Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
{
"name": "magpie-agent-guard",
"source": "./plugins/magpie-agent-guard",
"version": "0.2.0.dev202609080121",
"version": "0.2.0.dev202609081000",
"description": "Apache Magpie \u2014 deterministic pre-execution command guard: a PreToolUse hook that denies shell commands which would break a hard framework rule. Runs from the installed plugin, so no repository or worktree needs a local copy."
},
{
Expand Down
11 changes: 9 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,20 @@ repos:
# `.claude-plugin/marketplace.json` entry resolving to a matching, uniquely
# named plugin.json, and each family's skills present as single-hop symlinks
# into the shared skills/ tree. Catches a new skill, a changed family, a stale
# symlink, or a malformed manifest. `--fix` regenerates the family plugins.
# symlink, or a malformed manifest.
#
# Runs as `--fix`, so the hook *regenerates* rather than merely reporting: the
# generated tree is a pure function of the frontmatter and `pyproject.toml`'s
# version, so there is nothing for a contributor to decide when it drifts, and
# a check-only hook just made them run the fixer by hand. prek fails the run
# when a hook modifies files, so drift still stops the commit — it now arrives
# already corrected and staged-ready instead of as an instruction.
- repo: local
hooks:
- id: check-family-plugins
name: check-family-plugins (marketplace plugins vs frontmatter)
language: system
entry: python3 tools/dev/check-family-plugins.py
entry: python3 tools/dev/check-family-plugins.py --fix
files: ^(skills/.*/SKILL\.md|plugins/.*|\.claude-plugin/(marketplace|plugin)\.json|\.codex-plugin/plugin\.json|\.agents/plugins/marketplace\.json|(plugin|marketplace)\.json|gemini-extension\.json|apm\.yml|pyproject\.toml|hooks/check-upgrade\.sh)$
pass_filenames: false
# Documentation claims that must track the tree. Four mechanical checks,
Expand Down
5 changes: 3 additions & 2 deletions docs/setup/marketplaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,9 @@ and the all-in-one [`.claude-plugin/plugin.json`](../../.claude-plugin/plugin.js
in turn feeds the ten per-family manifests and the marketplace entries, which
also inherit `author`, `homepage`, `repository`, and `license`. Bump
`project.version` and run `python3 tools/dev/check-family-plugins.py --fix`; the
same script, run as a prek hook, fails the build on any manifest left behind at
the old version. See
same script runs as a prek hook in `--fix` mode, so a manifest left behind at
the old version is regenerated in place and the run fails until the corrected
file is staged. See
[`release-management-config.md`](../../projects/magpie/release-management-config.md)
(`version_manifest_files`).

Expand Down
2 changes: 1 addition & 1 deletion plugins/magpie-agent-guard/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "magpie-agent-guard",
"description": "Apache Magpie \u2014 deterministic pre-execution command guard: a PreToolUse hook that denies shell commands which would break a hard framework rule. Runs from the installed plugin, so no repository or worktree needs a local copy.",
"version": "0.2.0.dev202609080121",
"version": "0.2.0.dev202609081000",
"author": {
"name": "Apache Magpie",
"url": "https://magpie.apache.org/"
Expand Down
5 changes: 3 additions & 2 deletions projects/magpie/release-management-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ So a bump is one edit plus one command:
python3 tools/dev/check-family-plugins.py --fix
```

`tools/dev/check-family-plugins.py` (a prek hook) fails the build if any
manifest or marketplace entry is left behind at the previous version, so a
`tools/dev/check-family-plugins.py` also runs as a prek hook in `--fix` mode:
any manifest or marketplace entry left behind at the previous version is
regenerated in place and the run fails until the corrected file is staged, so a
missed propagation cannot reach a release.

## Backends
Expand Down
2 changes: 1 addition & 1 deletion tools/dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ installable for other members to depend on it.
| Script | What it does |
|---|---|
| [`check-doc-sync.py`](check-doc-sync.py) | Guards the documentation claims that track the tree and rot silently: spec-index completeness (every `tools/spec-loop/specs/*.md` listed in **both** `overview.md` and `README.md`), the per-family skill counts in the root `README.md`, the per-mode counts in `docs/modes.md`'s *Modes at a glance* table, the bare catalogue totals in `docs/setup/marketplaces.md`, and that every script here is named in this file. |
| [`check-family-plugins.py`](check-family-plugins.py) | Validates the marketplace plugins against the skills' `family:` frontmatter — version parity across every ecosystem manifest, Agent Plugins 1.0 conformance, and one well-formed per-family plugin whose `skills/` symlinks match the family exactly. `--fix` regenerates them. |
| [`check-family-plugins.py`](check-family-plugins.py) | Validates the marketplace plugins against the skills' `family:` frontmatter — version parity across every ecosystem manifest, Agent Plugins 1.0 conformance, and one well-formed per-family plugin whose `skills/` symlinks match the family exactly. `--fix` regenerates them, which is how the prek hook runs it. |
| [`check-placeholders.sh`](check-placeholders.sh) | Fails the build on hardcoded project references in skill and tool docs, which must use `<PROJECT>` / `<project>` / `<tracker>` / `<upstream>` instead. Carries both casings and matches spaced variants. |
| [`check-workspace-members.py`](check-workspace-members.py) | Catches a new `tools/<name>/pyproject.toml` that was never added to `[tool.uv.workspace] members` — an omission that silently drops the tool from both the pre-commit hooks and the CI pytest matrix. Also verifies each member's tests actually run: both surfaces key off `[tool.pytest.ini_options]`, so a project can carry a full `tests/` directory and be executed by nothing. Reports tests-without-config, config-without-tests, and neither; `[tool.magpie.checks] skip = ["pytest"]` is the declared exemption. |
| [`run-workspace-check.sh`](run-workspace-check.sh) | Runs one static-check or test command across every workspace member, auto-discovering which members a given check applies to. The four `workspace-*` hooks call it, so adding a tool needs no edit to the pre-commit config. |
Expand Down
4 changes: 3 additions & 1 deletion tools/spec-loop/specs/marketplace-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ family, each a manifest and a `skills/` directory of single-hop symlinks into
the shared `skills/<skill>` tree.

`tools/dev/check-family-plugins.py` is both the generator (`--fix`) and the
CI gate. `docs/setup/marketplaces.md` is the adopter-facing page.
CI gate — the prek hook runs it in `--fix` mode, so the gate corrects drift
rather than only reporting it. `docs/setup/marketplaces.md` is the
adopter-facing page.

## Behaviour & contract

Expand Down