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 tools/spec-loop/.last-sync
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bfc99bb6f47be727b124adf939e5c010fe33ba5f
4d491b09b31b0d692d3fe91cf11d0b16c7f4720d
11 changes: 10 additions & 1 deletion tools/spec-loop/specs/marketplace-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ which Claude Code would load twice.

`tools/dev/check-family-plugins.py` is both the generator (`--fix`) and the
CI gate — the prek hook runs it in `--fix` mode, so the gate corrects drift
rather than only reporting it. `docs/setup/marketplace.md` is the
rather than only reporting it.
It also copies `assets/plugin-icon.png` to `.claude-plugin/icon.png` in every
plugin and fails when a copy is missing or differs, because
`claude plugin validate --strict` reports a plugin without an icon (#2069).
`docs/setup/marketplace.md` is the
adopter-facing page.

## Behaviour & contract
Expand Down Expand Up @@ -208,6 +212,11 @@ adopter-facing page.
once per plugin version and points the `current` symlink at it; that is
`<framework>` on a marketplace install, writable so `uv run --project`
works, and the hook only ever replaces a symlink at `current`.
The plugin also ships `organizations/*/organization.md`, which the hook
copies into that tree, and `release_config` looks for organization manifests
under `~/.cache/apache-magpie/framework/current` too, so a project
inheriting a key from its organization does not fall back to the framework
default on a marketplace install (#2068).
`magpie-agent-guard` is the exception to the symlink (#1516): it carries
a byte-identical copy of `tools/agent-guard/src/agent_guard` as real
files, because a marketplace client may drop a link whose target leaves
Expand Down
3 changes: 3 additions & 0 deletions tools/spec-loop/specs/meta-and-quality-tooling.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ trustworthy as it grows.
test` on every plugin whose `hooks/hooks.json` declares `modules`,
with Claude Code pinned in the hook environment, because Claude Code
silently skips a hooks module that fails its static analysis.
That validation type-checks the hooks module, so the mods import their
siblings as `./<name>.js` and fix strict-null findings with guards rather
than suppressions (#2070).
Its `check-claude-mods-local` twin runs on ordinary commits with the
contributor's own Claude Code and skips when it is absent or older than
the pin; CI skips the twin.
Expand Down
19 changes: 19 additions & 0 deletions tools/spec-loop/specs/organization-adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ identical "ASF default" values in its own `project.md`.
GitHub Releases, no list/forwarder/metadata backends); inherited by
`projects/non-asf-example/`.
- `organizations/_template/` — authoring skeleton.
- `tools/dev/check-skill-source-drift.py` and
`.github/workflows/skill-source-drift.yml` — the weekly check of every
curated `organizations/*/skill-sources.md` against its source (#2040).
- Resolution contract: `AGENTS.md` §"Configuration resolution order".
- The project-manifest template that names the organization,
`plugins/magpie-setup/templates/project.md` (`projects/_template/` links to
Expand Down Expand Up @@ -107,6 +110,22 @@ identical "ASF default" values in its own `project.md`.
[security@apache.org]`, the organization-wide CVE bookkeeping sender.
A project list replaces, never merges with, an organization list, so a
project override repeats the inherited entries.
- **Curated skill sources are checked against their source weekly (#2040).**
An organization's `skill-sources.md` pins each source to a tag and may
carry a catalogue between `BEGIN` / `END SKILL-SOURCE CATALOGUE` markers
listing every skill the source ships, its install status (`pinned`,
`untagged`, `single-file`, `draft`) and the agent marketplaces that list
it.
The ASF adapter catalogues every skill under `apache/incubator`'s
`tools/skills/`, and since the Incubator tags each skill on its own, each
pinned skill is its own descriptor pinned to its own `<skill>-<version>` tag.
`tools/dev/check-skill-source-drift.py` reads each GitHub source through
the REST API and reports added, removed or re-laid-out skills, a pin
whose tag no longer resolves to the recorded commit, a newer or first tag,
and a marketplace column that disagrees with the source's catalogs; it is
read-only and exits `0` in sync, `1` on drift and `2` when it could not run.
The weekly `skill-source-drift` workflow runs it and keeps one issue open
while there is drift, closing it once a run finds everything in sync.
- An organization declares only org-wide values. Per-project
values (security-list address, scope labels, product name, roster,
tracker label/body-field vocabulary) stay in `project.md`.
Expand Down
28 changes: 26 additions & 2 deletions tools/spec-loop/specs/pr-management-family.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ same directory; the behaviour is unchanged.
It also ships agent-guard guards under `guards/` (`mark_ready.py`,
`mention.py`) and the opt-in shadow pre-filter
`scripts/typed_decision_prefilter.py` with its tests under `tests/`.
The skill runs its bundled scripts (`pr_link.py` and the pre-filter) as
`<skill-dir>/scripts/…`, because `<framework>` on a marketplace install
holds no `skills/` directory (#2063).
- Skill: `pr-management-stats` — read-only dashboard of the open PR
backlog, grouped by area label, age bucket, and triage state. No tracker
state is mutated. Ships `mode: Triage` + `capability: capability:stats`
Expand All @@ -101,6 +104,16 @@ same directory; the behaviour is unchanged.
Selection, scans, the slop threshold, disposition, inline anchoring and the
review payload run as code in `pr_management.code_review`; the agent judges
H1/H5/S2, writes the findings and assigns severity.
The `pr:` selector names one PR or several (#2055): `pr:N,M`, inclusive
ranges `pr:N-M`, optional `#` prefixes and repeated `pr:` tokens, with
duplicates dropped and at most 50 PRs; the queue keeps the order the
maintainer named, and a named PR missing from the open-PR sweep is listed
under `not_open`.
The selector output keeps `pr_number` (set when exactly one PR is named)
beside `pr_numbers`.
`code-review session record --outcome` accepts `FIXUP` beside the three
review events and the `skipped` / `slop-comment` / `slop-close` /
`dry-run` outcomes, and the session summary counts it as a review (#2056).
An inline comment carries the finding as the review body does (its
`quoted_rule` and `suggestion`), minus the excerpt it is anchored on, and
a folded finding falls back to its suggestion before its rule, never the
Expand Down Expand Up @@ -401,8 +414,19 @@ same directory; the behaviour is unchanged.
disposition --findings <file>` Bash call hydrates the mod's interactive pane
above the prompt, and the zero-token `/magpie-findings` command (`status`,
`all`, `none`, `keep`, `drop`, `edit`) tracks per-finding actions.
Neither changes what is posted: only the answer typed at the picker reaches
`render`.
Once the maintainer curates, the mod writes the findings to
`<file>.curated.json` (an envelope carrying the PR number and the source
file's SHA-256) and the keep answer to `<file>.curated.keep` beside the
findings file; the first `disposition` run writes neither, and a write
failure, empty findings or a PR mismatch writes an invalidation marker
instead, since the mod API cannot delete files (#2005).
It refuses to write through a symlink or a non-regular file.
`render` uses `<file>.curated.json` only when its PR and source hash
match, else the original findings; a curated envelope passed directly
must pass every check or the run stops.
An answer typed at the picker still wins; an empty answer is passed as
`--keep curated`, which uses `<file>.curated.keep` only when the curated
findings were used, and `A` otherwise.
Runtimes without mods keep the text picker alone, and Codex reads the clean
`hooks/codex-hooks.json` instead (#1992).
- **Third-party licence scan reads only real copyright notices.**
Expand Down
13 changes: 13 additions & 0 deletions tools/spec-loop/specs/security-issue-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,19 @@ publication, with a human gate and an audit-log entry at every step.
`MAGPIE_ALLOW_EMBARGO_TERMS=1` is the maintainer's escape hatch after
disclosure, and the block message does not tell the agent how to
bypass it.
It fails closed (#2071): a throw while evaluating a command blocks it
unless that escape hatch is set, and a blocked evaluation with no reason
still blocks, under a fallback reason.
When a blocked `gh api` write has a vetted route, the reason names the
exact operation (#2057): a POST to an advisory's comments endpoint maps to
`advisory-comment`, a PATCH to `issues/comments/<id>` to `comment-update`
and a POST to `issues/<N>/comments` to `issue-comment`.
The reason adds that the calling skill needs the operation in its
`[callers]` list in the adopter's vetted-ops config, which is a
maintainer's change.
Advisory record field edits and advisory comment edits have no vetted
operation, and the reason points at the advisory web UI.
The block decision itself is unchanged.
- **Adversarial review before a PR, on public content only.**
`security-issue-fix`, `security-issue-import-from-pr` (over the patch it
verifies) and `security-issue-import-from-scan` carry the shared
Expand Down