You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@magpie.apache.org by po...@apache.org on 2026/09/08 19:17:45 UTC

(magpie) branch main updated: fix(marketplace): re-sync magpie-agent-guard, and make the prek hook self-correcting (#1174)

This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/magpie.git


The following commit(s) were added to refs/heads/main by this push:
     new 6a1e37e5 fix(marketplace): re-sync magpie-agent-guard, and make the prek hook self-correcting (#1174)
6a1e37e5 is described below

commit 6a1e37e5dda262311da92786c2d44971e23d2d27
Author: Jarek Potiuk <ja...@potiuk.com>
AuthorDate: Tue Sep 8 21:17:39 2026 +0200

    fix(marketplace): re-sync magpie-agent-guard, and make the prek hook self-correcting (#1174)
    
    * fix(marketplace): re-sync magpie-agent-guard with the dev version stamp
    
    `#1169` stamped the framework version to `0.2.0.dev202609081000` across
    every ecosystem manifest. `#1170` landed right after it, adding the
    `magpie-agent-guard` plugin — a *new* file, branched before the bump and
    therefore carrying the previous stamp `0.2.0.dev202609080121`. New files
    do not conflict, so both merged cleanly and `main` was left with a family
    plugin one stamp behind the root manifest it inherits from.
    
    `check-family-plugins` has failed on `main` ever since, which is why an
    unrelated dependabot PR (#1167) shows a red `prek` job it did not cause.
    
    `python3 tools/dev/check-family-plugins.py --fix` output; no hand edits.
    
    Generated-by: Claude Code (Opus 5)
    
    * fix(prek): regenerate the family plugins instead of reporting them stale
    
    The `check-family-plugins` hook ran check-only, so a contributor whose
    manifests drifted got an instruction — "run
    `tools/dev/check-family-plugins.py --fix`" — rather than a fixed tree. The
    generated files are a pure function of the skills' `family:` frontmatter and
    `pyproject.toml`'s version, so there is nothing for them to decide: the fixer
    is the only correct response to every failure the check can report.
    
    Run the hook as `--fix`. prek fails a run whose hook modified files, so drift
    still stops the commit; it now arrives already corrected, needing only a
    re-stage — the same convention `end-of-file-fixer`, `trailing-whitespace`, and
    `add-license-headers` already follow here.
    
    `--fix`'s exit code is deliberately left alone: the release-bump procedure
    invokes it directly in plain shell blocks, where returning non-zero on a
    successful regeneration would read as failure.
    
    Scope note: this closes the hand-fix gap for anyone who runs the hooks, but it
    cannot catch the cross-PR case that broke `main` this morning — two PRs green
    in isolation, conflict-free on merge, out of sync in the result. Only a check
    on `main` (or a merge queue) sees that.
    
    Docs describing the hook as check-only updated to match.
    
    Generated-by: Claude Code (Opus 5)
---
 .claude-plugin/marketplace.json                       |  2 +-
 .pre-commit-config.yaml                               | 11 +++++++++--
 docs/setup/marketplaces.md                            |  5 +++--
 plugins/magpie-agent-guard/.claude-plugin/plugin.json |  2 +-
 projects/magpie/release-management-config.md          |  5 +++--
 tools/dev/README.md                                   |  2 +-
 tools/spec-loop/specs/marketplace-distribution.md     |  4 +++-
 7 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json
index 39b0c138..1bce7192 100644
--- a/.claude-plugin/marketplace.json
+++ b/.claude-plugin/marketplace.json
@@ -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."
     },
     {
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 9000282e..c27ca065 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -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,
diff --git a/docs/setup/marketplaces.md b/docs/setup/marketplaces.md
index cbb577e4..f02885b1 100644
--- a/docs/setup/marketplaces.md
+++ b/docs/setup/marketplaces.md
@@ -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`).
 
diff --git a/plugins/magpie-agent-guard/.claude-plugin/plugin.json b/plugins/magpie-agent-guard/.claude-plugin/plugin.json
index 36ee101e..40dd2deb 100644
--- a/plugins/magpie-agent-guard/.claude-plugin/plugin.json
+++ b/plugins/magpie-agent-guard/.claude-plugin/plugin.json
@@ -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/"
diff --git a/projects/magpie/release-management-config.md b/projects/magpie/release-management-config.md
index a563466b..05558c8e 100644
--- a/projects/magpie/release-management-config.md
+++ b/projects/magpie/release-management-config.md
@@ -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
diff --git a/tools/dev/README.md b/tools/dev/README.md
index 1ddaf7f5..8aab0123 100644
--- a/tools/dev/README.md
+++ b/tools/dev/README.md
@@ -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 [...]
 | [`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. |
diff --git a/tools/spec-loop/specs/marketplace-distribution.md b/tools/spec-loop/specs/marketplace-distribution.md
index 0286cb95..fcd65d69 100644
--- a/tools/spec-loop/specs/marketplace-distribution.md
+++ b/tools/spec-loop/specs/marketplace-distribution.md
@@ -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